From b07233263ed3eba29151971a7eeec8aaa573ae7d Mon Sep 17 00:00:00 2001 From: Andrew McElroy Date: Wed, 29 Dec 2010 14:04:37 -0600 Subject: [PATCH 01/16] Revert "destroyed legacy try ruby" This reverts commit b64abd74aed283a086bb1a8d85410fc76082fcb6. --- public/.gitignore | 2 + public/blank.html | 4 + public/comics.txt | 4 + public/es_index.html | 96 +++ public/images/background.png | Bin 0 -> 35315 bytes public/images/footer.png | Bin 0 -> 6840 bytes public/images/header.png | Bin 0 -> 46523 bytes public/images/index.html | 8 + public/images/tile.png | Bin 0 -> 305 bytes public/index.html | 96 +++ public/irb.cgi | 37 ++ public/js/index.html | 8 + public/js/irb.js | 110 ++++ public/js/jquery-1.3.2.min.js | 19 + public/js/jquery.js | 32 + public/js/mouseapp_2.js | 913 ++++++++++++++++++++++++++ public/js/mouseirb_2.js | 179 +++++ public/keypress_test.html | 37 ++ public/moods/index.html | 8 + public/moods/sick.gif | Bin 0 -> 94 bytes public/popup.rb | 114 ++++ public/setup.rb | 66 ++ public/site.css | 211 ++++++ public/submodules/fakefs | 1 + public/test.rb | 633 ++++++++++++++++++ public/tmp/index.html | 8 + public/tryruby.rb | 174 +++++ public/tutorials/es_intro.html | 666 +++++++++++++++++++ public/tutorials/intro.html | 680 +++++++++++++++++++ public/tutorials/intro.html.broken | 638 ++++++++++++++++++ public/tutorials/intro_files/sick.gif | Bin 0 -> 94 bytes 31 files changed, 4744 insertions(+) create mode 100644 public/.gitignore create mode 100755 public/blank.html create mode 100755 public/comics.txt create mode 100644 public/es_index.html create mode 100755 public/images/background.png create mode 100755 public/images/footer.png create mode 100644 public/images/header.png create mode 100755 public/images/index.html create mode 100755 public/images/tile.png create mode 100644 public/index.html create mode 100755 public/irb.cgi create mode 100755 public/js/index.html create mode 100755 public/js/irb.js create mode 100644 public/js/jquery-1.3.2.min.js create mode 100755 public/js/jquery.js create mode 100755 public/js/mouseapp_2.js create mode 100755 public/js/mouseirb_2.js create mode 100644 public/keypress_test.html create mode 100755 public/moods/index.html create mode 100755 public/moods/sick.gif create mode 100755 public/popup.rb create mode 100644 public/setup.rb create mode 100755 public/site.css create mode 160000 public/submodules/fakefs create mode 100755 public/test.rb create mode 100755 public/tmp/index.html create mode 100644 public/tryruby.rb create mode 100644 public/tutorials/es_intro.html create mode 100644 public/tutorials/intro.html create mode 100755 public/tutorials/intro.html.broken create mode 100755 public/tutorials/intro_files/sick.gif diff --git a/public/.gitignore b/public/.gitignore new file mode 100644 index 0000000..a1632ab --- /dev/null +++ b/public/.gitignore @@ -0,0 +1,2 @@ +tmp/ + diff --git a/public/blank.html b/public/blank.html new file mode 100755 index 0000000..7879e1c --- /dev/null +++ b/public/blank.html @@ -0,0 +1,4 @@ + + + + diff --git a/public/comics.txt b/public/comics.txt new file mode 100755 index 0000000..7dfc8e6 --- /dev/null +++ b/public/comics.txt @@ -0,0 +1,4 @@ +Achewood: http://achewood.com/ +Dinosaur Comics: http://qwantz.com/ +Perry Bible Fellowship: http://cheston.com/pbf/archive.html +Get Your War On: http://mnftiu.cc/ diff --git a/public/es_index.html b/public/es_index.html new file mode 100644 index 0000000..7519e36 --- /dev/null +++ b/public/es_index.html @@ -0,0 +1,96 @@ + + + + + try ruby! (en tu navegador) + + + + + + + + + +
+ +
+
+
+ +

A Popup Browser

+

[x]

+
+ +
+
+ +
+
+
+
+
+
+

¿Tienes 15 minutos? ¡Prueba Ruby ahora mismo!

+

Ruby es un lenguaje de programación de Japón + (disponible en ruby-lang.org) + que está revolucionando la web. + La belleza de Ruby se encuentra en su balance entre la simplicidad y el poder.

+ +

Prueba código Ruby en el prompt de arriba. Además de los métodos + originales de Ruby, los siguientes comandos están disponibles:

+
    +
  • help + Empieza el tutorial interactivo de 15 minutos. ¡Creeme, es muy básico!
  • +
  • help 2 + Salta al capítulo 2.
  • + +
  • clear + Limpia la pantalla. Útil si tu navegador empieza a alerdarce. + Tu historial de comandos será recordado. +
  • back + Retrocede una pantalla en el tutorial.
  • +
  • reset + Resetea el interprete. (o Ctrl-D!)
  • +
  • next + Te permite saltear la siguiente lección
  • + +
  • time + Detiene el reloj. Imprime cuanto tiempo tu sesión estuvo abierta.
  • +
+

Si te pasa de dejar o refrescar la página, tu sesión seguirá aquí a menos que + se deje inactiva por diez minutos.

+
+
+
+ +
+
¿Atrapado en los dos puntos? Unas comillas o algo fue dejado abierto. Escribe: reset o aprieta Ctrl-D.
+
+ +

This place was sired by why the lucky stiff. + Please contact me using the email address at that link.is maintained by Andrew McElroy and David Miani. For support issues, please post a ticket or contact Sophrinix on github.
Por asuntos de traducción, mandar un ticket o contactarse con Cristian Re (leizzer) en Github.
+

+ +
+ + + + + + + + + + diff --git a/public/images/background.png b/public/images/background.png new file mode 100755 index 0000000000000000000000000000000000000000..3a2dee031614731e46c00b5f8416d471908af982 GIT binary patch literal 35315 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 b}X6WEoFQ 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 literal 0 HcmV?d00001 diff --git a/public/images/index.html b/public/images/index.html new file mode 100755 index 0000000..e933af9 --- /dev/null +++ b/public/images/index.html @@ -0,0 +1,8 @@ + + + + + +

you shouldn't be here.. kicking you out!

+ + diff --git a/public/images/tile.png b/public/images/tile.png new file mode 100755 index 0000000000000000000000000000000000000000..399139f26d14e29a407d8b4bb8473ad2279edc41 GIT binary patch literal 305 zcmV-10nYx3P)e#ZdVeV@YYlo&$tx`(sO@ILaF1IwM9!1&Y00000NkvXXu0mjf DW=Vhn literal 0 HcmV?d00001 diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..01289b0 --- /dev/null +++ b/public/index.html @@ -0,0 +1,96 @@ + + + + + try ruby! (in your browser) + + + + + + + + + +
+ +
+ +
+ +
+
+
+
+
+
+

Got 15 minutes? Give Ruby a shot right now!

+

Ruby is a programming language from Japan + (available at ruby-lang.org) + which is revolutionizing the web. + The beauty of Ruby is found in its balance between simplicity and power.

+ +

Try out Ruby code in the prompt above. In addition + to Ruby's builtin methods, the following commands are available:

+
    +
  • help + Start the 15 minute interactive tutorial. Trust me, it's very basic!
  • +
  • help 2 + Hop to chapter two.
  • + +
  • clear + Clear screen. Useful if your browser starts slowing down. + Your command history will be remembered. +
  • back + Go back one screen in the tutorial.
  • +
  • reset + Reset the interpreter if you get too deep. (or Ctrl-D!)
  • +
  • next +Allows you to skip to the next section of a lesson.
  • + +
  • time + A stopwatch. Prints the time your session has been open.
  • +
+

If you happen to leave or refresh the page, your session will still be here for + unless it is left inactive for ten minutes.

+
+
+
+ +
+
Trapped in double dots? A quote or something was left open. Type: reset or hit Ctrl-D.
+
+ +

This place was sired by why the lucky stiff. + Please contact me using the email address at that link.is maintained by Andrew McElroy and David Miani. For support issues, please post a ticket or contact Sophrinix on github. +

+ +
+ + + + + + + + + + diff --git a/public/irb.cgi b/public/irb.cgi new file mode 100755 index 0000000..6c1c2de --- /dev/null +++ b/public/irb.cgi @@ -0,0 +1,37 @@ +#!/usr/bin/env ruby + +require 'tryruby.rb' +require 'cgi' +require 'cgi/session' +require 'cgi/session/pstore' + +class TryRubyCGISession# < TryRuby::Session + attr_accessor :cgi, :session + + def initialize + @session = CGI::Session.new @cgi = CGI.new, + 'database_manager' => CGI::Session::PStore, # use PStore + 'session_key' => 'trb_sess_id', # custom $session key + 'session_expires' => Time.now + 60 * 60, # 60 minute timeout + 'prefix' => 'pstore_sid_', #Pstore option + 'tmpdir' => 'tmp' # Temp Directory for sessions + + + @session['start_time'] ||= Time.now + @session['current_statement'] ||= '' + @session['past_commands'] ||= '' + end + + def header + @cgi.header 'text/plain' + end + + [:current_statement, :past_commands, :start_time].each do |accessor| + define_method(accessor) { @session[accessor.to_s] } + define_method(:"#{accessor.to_s}=") { |new_val| @session[accessor.to_s] = new_val } + end +end + +TryRuby.session = TryRubyCGISession.new + +print TryRuby.session.header + TryRuby.run_line(TryRuby.session.cgi['cmd']).format \ No newline at end of file diff --git a/public/js/index.html b/public/js/index.html new file mode 100755 index 0000000..e933af9 --- /dev/null +++ b/public/js/index.html @@ -0,0 +1,8 @@ + + + + + +

you shouldn't be here.. kicking you out!

+ + diff --git a/public/js/irb.js b/public/js/irb.js new file mode 100755 index 0000000..23d83df --- /dev/null +++ b/public/js/irb.js @@ -0,0 +1,110 @@ +// +// Copyright (c) 2008 why the lucky stiff +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +var allStretch; +var helpPages; +var chapPages; +var defaultPage; +var toot = window.location.search.substr(1) + +//the main function, call to the effect object +function dumpAlert(obj) { + props = []; + for ( var i in obj ) { + props.push( "" + i + ": " + obj[i] ); + } + alert( props ); +} +window.onload = function() { + defaultPage = $('#helpstone .stretcher').html(); + + window.irb = new MouseApp.Irb('#irb', { + rows: 13, + name: 'IRB', + greeting: "%+r Interactive ruby ready. %-r", + ps: '\033[1;31m>>\033[m', + user: 'guest', + host: 'tryruby', + // original: irbUrl: '/irb', + irbUrl: '/irb.cgi', + init: function () { + helpPages = $(".stretcher"); + chapPages = new Array(); + for (var i = 0; i < helpPages.length; i++ ) { + var cls = helpPages[i].className.split(' '); + for (var j = 0; j < cls.length; j++) { + if (cls[j] == 'chapmark') { + chapPages.push([i, helpPages[i]]); + break; + } + } + } + }, + loadTutorial: function (id, instruct) { + $.ajax({ + url: '/tutorials/' + id + '.html', + type: 'GET', + complete: function (r) { + $('#helpstone').html("
" + defaultPage + "
" + r.responseText); + window.irb.init(); + window.irb.showHelp(0); + } + }); + }, + showChapter: function (n) { + if (n >= chapPages.length) return; + this.setHelpPage(chapPages[n][0], chapPages[n][1]); + }, + showHelp: function (n) { + if (n >= helpPages.length) return; + this.setHelpPage(n, helpPages[n]); + }, + popup_goto: function (u) { + $('#lilBrowser').show().css({left: '40px', top: '40px'}); + $('#lbIframe').attr('src', u); + }, + popup_make: function (s) { + $('#lilBrowser').show().css({left: '40px', top: '40px'}); + $('#lbIframe').get(0).onIframeLoad = function () { + alert($(this).html()); + alert("$(this).html()"); + return s; + }; + //$('#lbIframe').attr({src: '/blank.html'}); + src = s.replace(/\\/g, "\\\\").replace(/\"/g, "\\\""); + $('#lbIframe').attr({src: "javascript:\"" + src + "\""}); + // $('# + }, + popup_close: function () { + $('#lilBrowser').hide(); + } + }); + + if ( !toot ) { + toot = 'intro'; + } + try { + window.irb.options.loadTutorial( toot, true ); + } catch (e) {} +} diff --git a/public/js/jquery-1.3.2.min.js b/public/js/jquery-1.3.2.min.js new file mode 100644 index 0000000..b1ae21d --- /dev/null +++ b/public/js/jquery-1.3.2.min.js @@ -0,0 +1,19 @@ +/* + * jQuery JavaScript Library v1.3.2 + * http://jquery.com/ + * + * Copyright (c) 2009 John Resig + * Dual licensed under the MIT and GPL licenses. + * http://docs.jquery.com/License + * + * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) + * Revision: 6246 + */ +(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("",""]||!O.indexOf("",""]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
"]||!O.indexOf("",""]||(!O.indexOf("",""]||!O.indexOf("",""]||!o.support.htmlSerialize&&[1,"div
","
"]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}}); +/* + * Sizzle CSS Selector Engine - v0.9.3 + * Copyright 2009, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return UT[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="

";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="
";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("
").append(M.responseText.replace(//g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='
';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})(); \ No newline at end of file diff --git a/public/js/jquery.js b/public/js/jquery.js new file mode 100755 index 0000000..3747929 --- /dev/null +++ b/public/js/jquery.js @@ -0,0 +1,32 @@ +/* + * jQuery 1.2.3 - New Wave Javascript + * + * Copyright (c) 2008 John Resig (jquery.com) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * $Date: 2008-02-06 00:21:25 -0500 (Wed, 06 Feb 2008) $ + * $Rev: 4663 $ + */ +(function(){if(window.jQuery)var _jQuery=window.jQuery;var jQuery=window.jQuery=function(selector,context){return new jQuery.prototype.init(selector,context);};if(window.$)var _$=window.$;window.$=jQuery;var quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;var isSimple=/^.[^:#\[\.]*$/;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;return this;}else if(typeof selector=="string"){var match=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1])selector=jQuery.clean([match[1]],context);else{var elem=document.getElementById(match[3]);if(elem)if(elem.id!=match[3])return jQuery().find(selector);else{this[0]=elem;this.length=1;return this;}else +selector=[];}}else +return new jQuery(context).find(selector);}else if(jQuery.isFunction(selector))return new jQuery(document)[jQuery.fn.ready?"ready":"load"](selector);return this.setArray(selector.constructor==Array&&selector||(selector.jquery||selector.length&&selector!=window&&!selector.nodeType&&selector[0]!=undefined&&selector[0].nodeType)&&jQuery.makeArray(selector)||[selector]);},jquery:"1.2.3",size:function(){return this.length;},length:0,get:function(num){return num==undefined?jQuery.makeArray(this):this[num];},pushStack:function(elems){var ret=jQuery(elems);ret.prevObject=this;return ret;},setArray:function(elems){this.length=0;Array.prototype.push.apply(this,elems);return this;},each:function(callback,args){return jQuery.each(this,callback,args);},index:function(elem){var ret=-1;this.each(function(i){if(this==elem)ret=i;});return ret;},attr:function(name,value,type){var options=name;if(name.constructor==String)if(value==undefined)return this.length&&jQuery[type||"attr"](this[0],name)||undefined;else{options={};options[name]=value;}return this.each(function(i){for(name in options)jQuery.attr(type?this.style:this,name,jQuery.prop(this,options[name],type,i,name));});},css:function(key,value){if((key=='width'||key=='height')&&parseFloat(value)<0)value=undefined;return this.attr(key,value,"curCSS");},text:function(text){if(typeof text!="object"&&text!=null)return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(text));var ret="";jQuery.each(text||this,function(){jQuery.each(this.childNodes,function(){if(this.nodeType!=8)ret+=this.nodeType!=1?this.nodeValue:jQuery.fn.text([this]);});});return ret;},wrapAll:function(html){if(this[0])jQuery(html,this[0].ownerDocument).clone().insertBefore(this[0]).map(function(){var elem=this;while(elem.firstChild)elem=elem.firstChild;return elem;}).append(this);return this;},wrapInner:function(html){return this.each(function(){jQuery(this).contents().wrapAll(html);});},wrap:function(html){return this.each(function(){jQuery(this).wrapAll(html);});},append:function(){return this.domManip(arguments,true,false,function(elem){if(this.nodeType==1)this.appendChild(elem);});},prepend:function(){return this.domManip(arguments,true,true,function(elem){if(this.nodeType==1)this.insertBefore(elem,this.firstChild);});},before:function(){return this.domManip(arguments,false,false,function(elem){this.parentNode.insertBefore(elem,this);});},after:function(){return this.domManip(arguments,false,true,function(elem){this.parentNode.insertBefore(elem,this.nextSibling);});},end:function(){return this.prevObject||jQuery([]);},find:function(selector){var elems=jQuery.map(this,function(elem){return jQuery.find(selector,elem);});return this.pushStack(/[^+>] [^+>]/.test(selector)||selector.indexOf("..")>-1?jQuery.unique(elems):elems);},clone:function(events){var ret=this.map(function(){if(jQuery.browser.msie&&!jQuery.isXMLDoc(this)){var clone=this.cloneNode(true),container=document.createElement("div");container.appendChild(clone);return jQuery.clean([container.innerHTML])[0];}else +return this.cloneNode(true);});var clone=ret.find("*").andSelf().each(function(){if(this[expando]!=undefined)this[expando]=null;});if(events===true)this.find("*").andSelf().each(function(i){if(this.nodeType==3)return;var events=jQuery.data(this,"events");for(var type in events)for(var handler in events[type])jQuery.event.add(clone[i],type,events[type][handler],events[type][handler].data);});return ret;},filter:function(selector){return this.pushStack(jQuery.isFunction(selector)&&jQuery.grep(this,function(elem,i){return selector.call(elem,i);})||jQuery.multiFilter(selector,this));},not:function(selector){if(selector.constructor==String)if(isSimple.test(selector))return this.pushStack(jQuery.multiFilter(selector,this,true));else +selector=jQuery.multiFilter(selector,this);var isArrayLike=selector.length&&selector[selector.length-1]!==undefined&&!selector.nodeType;return this.filter(function(){return isArrayLike?jQuery.inArray(this,selector)<0:this!=selector;});},add:function(selector){return!selector?this:this.pushStack(jQuery.merge(this.get(),selector.constructor==String?jQuery(selector).get():selector.length!=undefined&&(!selector.nodeName||jQuery.nodeName(selector,"form"))?selector:[selector]));},is:function(selector){return selector?jQuery.multiFilter(selector,this).length>0:false;},hasClass:function(selector){return this.is("."+selector);},val:function(value){if(value==undefined){if(this.length){var elem=this[0];if(jQuery.nodeName(elem,"select")){var index=elem.selectedIndex,values=[],options=elem.options,one=elem.type=="select-one";if(index<0)return null;for(var i=one?index:0,max=one?index+1:options.length;i=0||jQuery.inArray(this.name,value)>=0);else if(jQuery.nodeName(this,"select")){var values=value.constructor==Array?value:[value];jQuery("option",this).each(function(){this.selected=(jQuery.inArray(this.value,values)>=0||jQuery.inArray(this.text,values)>=0);});if(!values.length)this.selectedIndex=-1;}else +this.value=value;});},html:function(value){return value==undefined?(this.length?this[0].innerHTML:null):this.empty().append(value);},replaceWith:function(value){return this.after(value).remove();},eq:function(i){return this.slice(i,i+1);},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments));},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem);}));},andSelf:function(){return this.add(this.prevObject);},data:function(key,value){var parts=key.split(".");parts[1]=parts[1]?"."+parts[1]:"";if(value==null){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data==undefined&&this.length)data=jQuery.data(this[0],key);return data==null&&parts[1]?this.data(parts[0]):data;}else +return this.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){jQuery.data(this,key,value);});},removeData:function(key){return this.each(function(){jQuery.removeData(this,key);});},domManip:function(args,table,reverse,callback){var clone=this.length>1,elems;return this.each(function(){if(!elems){elems=jQuery.clean(args,this.ownerDocument);if(reverse)elems.reverse();}var obj=this;if(table&&jQuery.nodeName(this,"table")&&jQuery.nodeName(elems[0],"tr"))obj=this.getElementsByTagName("tbody")[0]||this.appendChild(this.ownerDocument.createElement("tbody"));var scripts=jQuery([]);jQuery.each(elems,function(){var elem=clone?jQuery(this).clone(true)[0]:this;if(jQuery.nodeName(elem,"script")){scripts=scripts.add(elem);}else{if(elem.nodeType==1)scripts=scripts.add(jQuery("script",elem).remove());callback.call(obj,elem);}});scripts.each(evalScript);});}};jQuery.prototype.init.prototype=jQuery.prototype;function evalScript(i,elem){if(elem.src)jQuery.ajax({url:elem.src,async:false,dataType:"script"});else +jQuery.globalEval(elem.text||elem.textContent||elem.innerHTML||"");if(elem.parentNode)elem.parentNode.removeChild(elem);}jQuery.extend=jQuery.fn.extend=function(){var target=arguments[0]||{},i=1,length=arguments.length,deep=false,options;if(target.constructor==Boolean){deep=target;target=arguments[1]||{};i=2;}if(typeof target!="object"&&typeof target!="function")target={};if(length==1){target=this;i=0;}for(;i-1;}},swap:function(elem,options,callback){var old={};for(var name in options){old[name]=elem.style[name];elem.style[name]=options[name];}callback.call(elem);for(var name in options)elem.style[name]=old[name];},css:function(elem,name,force){if(name=="width"||name=="height"){var val,props={position:"absolute",visibility:"hidden",display:"block"},which=name=="width"?["Left","Right"]:["Top","Bottom"];function getWH(){val=name=="width"?elem.offsetWidth:elem.offsetHeight;var padding=0,border=0;jQuery.each(which,function(){padding+=parseFloat(jQuery.curCSS(elem,"padding"+this,true))||0;border+=parseFloat(jQuery.curCSS(elem,"border"+this+"Width",true))||0;});val-=Math.round(padding+border);}if(jQuery(elem).is(":visible"))getWH();else +jQuery.swap(elem,props,getWH);return Math.max(0,val);}return jQuery.curCSS(elem,name,force);},curCSS:function(elem,name,force){var ret;function color(elem){if(!jQuery.browser.safari)return false;var ret=document.defaultView.getComputedStyle(elem,null);return!ret||ret.getPropertyValue("color")=="";}if(name=="opacity"&&jQuery.browser.msie){ret=jQuery.attr(elem.style,"opacity");return ret==""?"1":ret;}if(jQuery.browser.opera&&name=="display"){var save=elem.style.outline;elem.style.outline="0 solid black";elem.style.outline=save;}if(name.match(/float/i))name=styleFloat;if(!force&&elem.style&&elem.style[name])ret=elem.style[name];else if(document.defaultView&&document.defaultView.getComputedStyle){if(name.match(/float/i))name="float";name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var getComputedStyle=document.defaultView.getComputedStyle(elem,null);if(getComputedStyle&&!color(elem))ret=getComputedStyle.getPropertyValue(name);else{var swap=[],stack=[];for(var a=elem;a&&color(a);a=a.parentNode)stack.unshift(a);for(var i=0;i]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+">";});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("",""]||!tags.indexOf("",""]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
"]||!tags.indexOf("",""]||(!tags.indexOf("",""]||!tags.indexOf("",""]||jQuery.browser.msie&&[1,"div
","
"]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--)div=div.lastChild;if(jQuery.browser.msie){var tbody=!tags.indexOf(""&&tags.indexOf("=0;--j)if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length)tbody[j].parentNode.removeChild(tbody[j]);if(/^\s/.test(elem))div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]),div.firstChild);}elem=jQuery.makeArray(div.childNodes);}if(elem.length===0&&(!jQuery.nodeName(elem,"form")&&!jQuery.nodeName(elem,"select")))return;if(elem[0]==undefined||jQuery.nodeName(elem,"form")||elem.options)ret.push(elem);else +ret=jQuery.merge(ret,elem);});return ret;},attr:function(elem,name,value){if(!elem||elem.nodeType==3||elem.nodeType==8)return undefined;var fix=jQuery.isXMLDoc(elem)?{}:jQuery.props;if(name=="selected"&&jQuery.browser.safari)elem.parentNode.selectedIndex;if(fix[name]){if(value!=undefined)elem[fix[name]]=value;return elem[fix[name]];}else if(jQuery.browser.msie&&name=="style")return jQuery.attr(elem.style,"cssText",value);else if(value==undefined&&jQuery.browser.msie&&jQuery.nodeName(elem,"form")&&(name=="action"||name=="method"))return elem.getAttributeNode(name).nodeValue;else if(elem.tagName){if(value!=undefined){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode)throw"type property can't be changed";elem.setAttribute(name,""+value);}if(jQuery.browser.msie&&/href|src/.test(name)&&!jQuery.isXMLDoc(elem))return elem.getAttribute(name,2);return elem.getAttribute(name);}else{if(name=="opacity"&&jQuery.browser.msie){if(value!=undefined){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+(parseFloat(value).toString()=="NaN"?"":"alpha(opacity="+value*100+")");}return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100).toString():"";}name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase();});if(value!=undefined)elem[name]=value;return elem[name];}},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"");},makeArray:function(array){var ret=[];if(typeof array!="array")for(var i=0,length=array.length;i*",this).remove();while(this.firstChild)this.removeChild(this.firstChild);}},function(name,fn){jQuery.fn[name]=function(){return this.each(fn,arguments);};});jQuery.each(["Height","Width"],function(i,name){var type=name.toLowerCase();jQuery.fn[type]=function(size){return this[0]==window?jQuery.browser.opera&&document.body["client"+name]||jQuery.browser.safari&&window["inner"+name]||document.compatMode=="CSS1Compat"&&document.documentElement["client"+name]||document.body["client"+name]:this[0]==document?Math.max(Math.max(document.body["scroll"+name],document.documentElement["scroll"+name]),Math.max(document.body["offset"+name],document.documentElement["offset"+name])):size==undefined?(this.length?jQuery.css(this[0],type):null):this.css(type,size.constructor==String?size:size+"px");};});var chars=jQuery.browser.safari&&parseInt(jQuery.browser.version)<417?"(?:[\\w*_-]|\\\\.)":"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",quickChild=new RegExp("^>\\s*("+chars+"+)"),quickID=new RegExp("^("+chars+"+)(#)("+chars+"+)"),quickClass=new RegExp("^([#.]?)("+chars+"*)");jQuery.extend({expr:{"":function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},"#":function(a,i,m){return a.getAttribute("id")==m[2];},":":{lt:function(a,i,m){return im[3]-0;},nth:function(a,i,m){return m[3]-0==i;},eq:function(a,i,m){return m[3]-0==i;},first:function(a,i){return i==0;},last:function(a,i,m,r){return i==r.length-1;},even:function(a,i){return i%2==0;},odd:function(a,i){return i%2;},"first-child":function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},"last-child":function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},"only-child":function(a){return!jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},parent:function(a){return a.firstChild;},empty:function(a){return!a.firstChild;},contains:function(a,i,m){return(a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},visible:function(a){return"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},hidden:function(a){return"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},enabled:function(a){return!a.disabled;},disabled:function(a){return a.disabled;},checked:function(a){return a.checked;},selected:function(a){return a.selected||jQuery.attr(a,"selected");},text:function(a){return"text"==a.type;},radio:function(a){return"radio"==a.type;},checkbox:function(a){return"checkbox"==a.type;},file:function(a){return"file"==a.type;},password:function(a){return"password"==a.type;},submit:function(a){return"submit"==a.type;},image:function(a){return"image"==a.type;},reset:function(a){return"reset"==a.type;},button:function(a){return"button"==a.type||jQuery.nodeName(a,"button");},input:function(a){return/input|select|textarea|button/i.test(a.nodeName);},has:function(a,i,m){return jQuery.find(m[3],a).length;},header:function(a){return/h\d/i.test(a.nodeName);},animated:function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}}},parse:[/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,new RegExp("^([:.#]*)("+chars+"+)")],multiFilter:function(expr,elems,not){var old,cur=[];while(expr&&expr!=old){old=expr;var f=jQuery.filter(expr,elems,not);expr=f.t.replace(/^\s*,\s*/,"");cur=not?elems=f.r:jQuery.merge(cur,f.r);}return cur;},find:function(t,context){if(typeof t!="string")return[t];if(context&&context.nodeType!=1&&context.nodeType!=9)return[];context=context||document;var ret=[context],done=[],last,nodeName;while(t&&last!=t){var r=[];last=t;t=jQuery.trim(t);var foundToken=false;var re=quickChild;var m=re.exec(t);if(m){nodeName=m[1].toUpperCase();for(var i=0;ret[i];i++)for(var c=ret[i].firstChild;c;c=c.nextSibling)if(c.nodeType==1&&(nodeName=="*"||c.nodeName.toUpperCase()==nodeName))r.push(c);ret=r;t=t.replace(re,"");if(t.indexOf(" ")==0)continue;foundToken=true;}else{re=/^([>+~])\s*(\w*)/i;if((m=re.exec(t))!=null){r=[];var merge={};nodeName=m[2].toUpperCase();m=m[1];for(var j=0,rl=ret.length;j=0;if(!not&&pass||not&&!pass)tmp.push(r[i]);}return tmp;},filter:function(t,r,not){var last;while(t&&t!=last){last=t;var p=jQuery.parse,m;for(var i=0;p[i];i++){m=p[i].exec(t);if(m){t=t.substring(m[0].length);m[2]=m[2].replace(/\\/g,"");break;}}if(!m)break;if(m[1]==":"&&m[2]=="not")r=isSimple.test(m[3])?jQuery.filter(m[3],r,true).r:jQuery(r).not(m[3]);else if(m[1]==".")r=jQuery.classFilter(r,m[2],not);else if(m[1]=="["){var tmp=[],type=m[3];for(var i=0,rl=r.length;i=0)^not)tmp.push(a);}r=tmp;}else if(m[1]==":"&&m[2]=="nth-child"){var merge={},tmp=[],test=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3]=="even"&&"2n"||m[3]=="odd"&&"2n+1"||!/\D/.test(m[3])&&"0n+"+m[3]||m[3]),first=(test[1]+(test[2]||1))-0,last=test[3]-0;for(var i=0,rl=r.length;i=0)add=true;if(add^not)tmp.push(node);}r=tmp;}else{var fn=jQuery.expr[m[1]];if(typeof fn=="object")fn=fn[m[2]];if(typeof fn=="string")fn=eval("false||function(a,i){return "+fn+";}");r=jQuery.grep(r,function(elem,i){return fn(elem,i,m,r);},not);}}return{r:r,t:t};},dir:function(elem,dir){var matched=[];var cur=elem[dir];while(cur&&cur!=document){if(cur.nodeType==1)matched.push(cur);cur=cur[dir];}return matched;},nth:function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir])if(cur.nodeType==1&&++num==result)break;return cur;},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType==1&&(!elem||n!=elem))r.push(n);}return r;}});jQuery.event={add:function(elem,types,handler,data){if(elem.nodeType==3||elem.nodeType==8)return;if(jQuery.browser.msie&&elem.setInterval!=undefined)elem=window;if(!handler.guid)handler.guid=this.guid++;if(data!=undefined){var fn=handler;handler=function(){return fn.apply(this,arguments);};handler.data=data;handler.guid=fn.guid;}var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){var val;if(typeof jQuery=="undefined"||jQuery.event.triggered)return val;val=jQuery.event.handle.apply(arguments.callee.elem,arguments);return val;});handle.elem=elem;jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];handler.type=parts[1];var handlers=events[type];if(!handlers){handlers=events[type]={};if(!jQuery.event.special[type]||jQuery.event.special[type].setup.call(elem)===false){if(elem.addEventListener)elem.addEventListener(type,handle,false);else if(elem.attachEvent)elem.attachEvent("on"+type,handle);}}handlers[handler.guid]=handler;jQuery.event.global[type]=true;});elem=null;},guid:1,global:{},remove:function(elem,types,handler){if(elem.nodeType==3||elem.nodeType==8)return;var events=jQuery.data(elem,"events"),ret,index;if(events){if(types==undefined||(typeof types=="string"&&types.charAt(0)=="."))for(var type in events)this.remove(elem,type+(types||""));else{if(types.type){handler=types.handler;types=types.type;}jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];if(events[type]){if(handler)delete events[type][handler.guid];else +for(handler in events[type])if(!parts[1]||events[type][handler].type==parts[1])delete events[type][handler];for(ret in events[type])break;if(!ret){if(!jQuery.event.special[type]||jQuery.event.special[type].teardown.call(elem)===false){if(elem.removeEventListener)elem.removeEventListener(type,jQuery.data(elem,"handle"),false);else if(elem.detachEvent)elem.detachEvent("on"+type,jQuery.data(elem,"handle"));}ret=null;delete events[type];}}});}for(ret in events)break;if(!ret){var handle=jQuery.data(elem,"handle");if(handle)handle.elem=null;jQuery.removeData(elem,"events");jQuery.removeData(elem,"handle");}}},trigger:function(type,data,elem,donative,extra){data=jQuery.makeArray(data||[]);if(type.indexOf("!")>=0){type=type.slice(0,-1);var exclusive=true;}if(!elem){if(this.global[type])jQuery("*").add([window,document]).trigger(type,data);}else{if(elem.nodeType==3||elem.nodeType==8)return undefined;var val,ret,fn=jQuery.isFunction(elem[type]||null),event=!data[0]||!data[0].preventDefault;if(event)data.unshift(this.fix({type:type,target:elem}));data[0].type=type;if(exclusive)data[0].exclusive=true;if(jQuery.isFunction(jQuery.data(elem,"handle")))val=jQuery.data(elem,"handle").apply(elem,data);if(!fn&&elem["on"+type]&&elem["on"+type].apply(elem,data)===false)val=false;if(event)data.shift();if(extra&&jQuery.isFunction(extra)){ret=extra.apply(elem,val==null?data:data.concat(val));if(ret!==undefined)val=ret;}if(fn&&donative!==false&&val!==false&&!(jQuery.nodeName(elem,'a')&&type=="click")){this.triggered=true;try{elem[type]();}catch(e){}}this.triggered=false;}return val;},handle:function(event){var val;event=jQuery.event.fix(event||window.event||{});var parts=event.type.split(".");event.type=parts[0];var handlers=jQuery.data(this,"events")&&jQuery.data(this,"events")[event.type],args=Array.prototype.slice.call(arguments,1);args.unshift(event);for(var j in handlers){var handler=handlers[j];args[0].handler=handler;args[0].data=handler.data;if(!parts[1]&&!event.exclusive||handler.type==parts[1]){var ret=handler.apply(this,args);if(val!==false)val=ret;if(ret===false){event.preventDefault();event.stopPropagation();}}}if(jQuery.browser.msie)event.target=event.preventDefault=event.stopPropagation=event.handler=event.data=null;return val;},fix:function(event){var originalEvent=event;event=jQuery.extend({},originalEvent);event.preventDefault=function(){if(originalEvent.preventDefault)originalEvent.preventDefault();originalEvent.returnValue=false;};event.stopPropagation=function(){if(originalEvent.stopPropagation)originalEvent.stopPropagation();originalEvent.cancelBubble=true;};if(!event.target)event.target=event.srcElement||document;if(event.target.nodeType==3)event.target=originalEvent.target.parentNode;if(!event.relatedTarget&&event.fromElement)event.relatedTarget=event.fromElement==event.target?event.toElement:event.fromElement;if(event.pageX==null&&event.clientX!=null){var doc=document.documentElement,body=document.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc.clientTop||0);}if(!event.which&&((event.charCode||event.charCode===0)?event.charCode:event.keyCode))event.which=event.charCode||event.keyCode;if(!event.metaKey&&event.ctrlKey)event.metaKey=event.ctrlKey;if(!event.which&&event.button)event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)));return event;},special:{ready:{setup:function(){bindReady();return;},teardown:function(){return;}},mouseenter:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseover",jQuery.event.special.mouseenter.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseover",jQuery.event.special.mouseenter.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseenter";return jQuery.event.handle.apply(this,arguments);}},mouseleave:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseout",jQuery.event.special.mouseleave.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseout",jQuery.event.special.mouseleave.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseleave";return jQuery.event.handle.apply(this,arguments);}}}};jQuery.fn.extend({bind:function(type,data,fn){return type=="unload"?this.one(type,data,fn):this.each(function(){jQuery.event.add(this,type,fn||data,fn&&data);});},one:function(type,data,fn){return this.each(function(){jQuery.event.add(this,type,function(event){jQuery(this).unbind(event);return(fn||data).apply(this,arguments);},fn&&data);});},unbind:function(type,fn){return this.each(function(){jQuery.event.remove(this,type,fn);});},trigger:function(type,data,fn){return this.each(function(){jQuery.event.trigger(type,data,this,true,fn);});},triggerHandler:function(type,data,fn){if(this[0])return jQuery.event.trigger(type,data,this[0],false,fn);return undefined;},toggle:function(){var args=arguments;return this.click(function(event){this.lastToggle=0==this.lastToggle?1:0;event.preventDefault();return args[this.lastToggle].apply(this,arguments)||false;});},hover:function(fnOver,fnOut){return this.bind('mouseenter',fnOver).bind('mouseleave',fnOut);},ready:function(fn){bindReady();if(jQuery.isReady)fn.call(document,jQuery);else +jQuery.readyList.push(function(){return fn.call(this,jQuery);});return this;}});jQuery.extend({isReady:false,readyList:[],ready:function(){if(!jQuery.isReady){jQuery.isReady=true;if(jQuery.readyList){jQuery.each(jQuery.readyList,function(){this.apply(document);});jQuery.readyList=null;}jQuery(document).triggerHandler("ready");}}});var readyBound=false;function bindReady(){if(readyBound)return;readyBound=true;if(document.addEventListener&&!jQuery.browser.opera)document.addEventListener("DOMContentLoaded",jQuery.ready,false);if(jQuery.browser.msie&&window==top)(function(){if(jQuery.isReady)return;try{document.documentElement.doScroll("left");}catch(error){setTimeout(arguments.callee,0);return;}jQuery.ready();})();if(jQuery.browser.opera)document.addEventListener("DOMContentLoaded",function(){if(jQuery.isReady)return;for(var i=0;i=0){var selector=url.slice(off,url.length);url=url.slice(0,off);}callback=callback||function(){};var type="GET";if(params)if(jQuery.isFunction(params)){callback=params;params=null;}else{params=jQuery.param(params);type="POST";}var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(res,status){if(status=="success"||status=="notmodified")self.html(selector?jQuery("
").append(res.responseText.replace(//g,"")).find(selector):res.responseText);self.each(callback,[res.responseText,status,res]);}});return this;},serialize:function(){return jQuery.param(this.serializeArray());},serializeArray:function(){return this.map(function(){return jQuery.nodeName(this,"form")?jQuery.makeArray(this.elements):this;}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type));}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:val.constructor==Array?jQuery.map(val,function(val,i){return{name:elem.name,value:val};}):{name:elem.name,value:val};}).get();}});jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(i,o){jQuery.fn[o]=function(f){return this.bind(o,f);};});var jsc=(new Date).getTime();jQuery.extend({get:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data=null;}return jQuery.ajax({type:"GET",url:url,data:data,success:callback,dataType:type});},getScript:function(url,callback){return jQuery.get(url,null,callback,"script");},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},post:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data={};}return jQuery.ajax({type:"POST",url:url,data:data,success:callback,dataType:type});},ajaxSetup:function(settings){jQuery.extend(jQuery.ajaxSettings,settings);},ajaxSettings:{global:true,type:"GET",timeout:0,contentType:"application/x-www-form-urlencoded",processData:true,async:true,data:null,username:null,password:null,accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(s){var jsonp,jsre=/=\?(&|$)/g,status,data;s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));if(s.data&&s.processData&&typeof s.data!="string")s.data=jQuery.param(s.data);if(s.dataType=="jsonp"){if(s.type.toLowerCase()=="get"){if(!s.url.match(jsre))s.url+=(s.url.match(/\?/)?"&":"?")+(s.jsonp||"callback")+"=?";}else if(!s.data||!s.data.match(jsre))s.data=(s.data?s.data+"&":"")+(s.jsonp||"callback")+"=?";s.dataType="json";}if(s.dataType=="json"&&(s.data&&s.data.match(jsre)||s.url.match(jsre))){jsonp="jsonp"+jsc++;if(s.data)s.data=(s.data+"").replace(jsre,"="+jsonp+"$1");s.url=s.url.replace(jsre,"="+jsonp+"$1");s.dataType="script";window[jsonp]=function(tmp){data=tmp;success();complete();window[jsonp]=undefined;try{delete window[jsonp];}catch(e){}if(head)head.removeChild(script);};}if(s.dataType=="script"&&s.cache==null)s.cache=false;if(s.cache===false&&s.type.toLowerCase()=="get"){var ts=(new Date()).getTime();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"");}if(s.data&&s.type.toLowerCase()=="get"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null;}if(s.global&&!jQuery.active++)jQuery.event.trigger("ajaxStart");if((!s.url.indexOf("http")||!s.url.indexOf("//"))&&s.dataType=="script"&&s.type.toLowerCase()=="get"){var head=document.getElementsByTagName("head")[0];var script=document.createElement("script");script.src=s.url;if(s.scriptCharset)script.charset=s.scriptCharset;if(!jsonp){var done=false;script.onload=script.onreadystatechange=function(){if(!done&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){done=true;success();complete();head.removeChild(script);}};}head.appendChild(script);return undefined;}var requestDone=false;var xml=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();xml.open(s.type,s.url,s.async,s.username,s.password);try{if(s.data)xml.setRequestHeader("Content-Type",s.contentType);if(s.ifModified)xml.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT");xml.setRequestHeader("X-Requested-With","XMLHttpRequest");xml.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default);}catch(e){}if(s.beforeSend)s.beforeSend(xml);if(s.global)jQuery.event.trigger("ajaxSend",[xml,s]);var onreadystatechange=function(isTimeout){if(!requestDone&&xml&&(xml.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null;}status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xml)&&"error"||s.ifModified&&jQuery.httpNotModified(xml,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xml,s.dataType);}catch(e){status="parsererror";}}if(status=="success"){var modRes;try{modRes=xml.getResponseHeader("Last-Modified");}catch(e){}if(s.ifModified&&modRes)jQuery.lastModified[s.url]=modRes;if(!jsonp)success();}else +jQuery.handleError(s,xml,status);complete();if(s.async)xml=null;}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0)setTimeout(function(){if(xml){xml.abort();if(!requestDone)onreadystatechange("timeout");}},s.timeout);}try{xml.send(s.data);}catch(e){jQuery.handleError(s,xml,null,e);}if(!s.async)onreadystatechange();function success(){if(s.success)s.success(data,status);if(s.global)jQuery.event.trigger("ajaxSuccess",[xml,s]);}function complete(){if(s.complete)s.complete(xml,status);if(s.global)jQuery.event.trigger("ajaxComplete",[xml,s]);if(s.global&&!--jQuery.active)jQuery.event.trigger("ajaxStop");}return xml;},handleError:function(s,xml,status,e){if(s.error)s.error(xml,status,e);if(s.global)jQuery.event.trigger("ajaxError",[xml,s,e]);},active:0,httpSuccess:function(r){try{return!r.status&&location.protocol=="file:"||(r.status>=200&&r.status<300)||r.status==304||r.status==1223||jQuery.browser.safari&&r.status==undefined;}catch(e){}return false;},httpNotModified:function(xml,url){try{var xmlRes=xml.getResponseHeader("Last-Modified");return xml.status==304||xmlRes==jQuery.lastModified[url]||jQuery.browser.safari&&xml.status==undefined;}catch(e){}return false;},httpData:function(r,type){var ct=r.getResponseHeader("content-type");var xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0;var data=xml?r.responseXML:r.responseText;if(xml&&data.documentElement.tagName=="parsererror")throw"parsererror";if(type=="script")jQuery.globalEval(data);if(type=="json")data=eval("("+data+")");return data;},param:function(a){var s=[];if(a.constructor==Array||a.jquery)jQuery.each(a,function(){s.push(encodeURIComponent(this.name)+"="+encodeURIComponent(this.value));});else +for(var j in a)if(a[j]&&a[j].constructor==Array)jQuery.each(a[j],function(){s.push(encodeURIComponent(j)+"="+encodeURIComponent(this));});else +s.push(encodeURIComponent(j)+"="+encodeURIComponent(a[j]));return s.join("&").replace(/%20/g,"+");}});jQuery.fn.extend({show:function(speed,callback){return speed?this.animate({height:"show",width:"show",opacity:"show"},speed,callback):this.filter(":hidden").each(function(){this.style.display=this.oldblock||"";if(jQuery.css(this,"display")=="none"){var elem=jQuery("<"+this.tagName+" />").appendTo("body");this.style.display=elem.css("display");if(this.style.display=="none")this.style.display="block";elem.remove();}}).end();},hide:function(speed,callback){return speed?this.animate({height:"hide",width:"hide",opacity:"hide"},speed,callback):this.filter(":visible").each(function(){this.oldblock=this.oldblock||jQuery.css(this,"display");this.style.display="none";}).end();},_toggle:jQuery.fn.toggle,toggle:function(fn,fn2){return jQuery.isFunction(fn)&&jQuery.isFunction(fn2)?this._toggle(fn,fn2):fn?this.animate({height:"toggle",width:"toggle",opacity:"toggle"},fn,fn2):this.each(function(){jQuery(this)[jQuery(this).is(":hidden")?"show":"hide"]();});},slideDown:function(speed,callback){return this.animate({height:"show"},speed,callback);},slideUp:function(speed,callback){return this.animate({height:"hide"},speed,callback);},slideToggle:function(speed,callback){return this.animate({height:"toggle"},speed,callback);},fadeIn:function(speed,callback){return this.animate({opacity:"show"},speed,callback);},fadeOut:function(speed,callback){return this.animate({opacity:"hide"},speed,callback);},fadeTo:function(speed,to,callback){return this.animate({opacity:to},speed,callback);},animate:function(prop,speed,easing,callback){var optall=jQuery.speed(speed,easing,callback);return this[optall.queue===false?"each":"queue"](function(){if(this.nodeType!=1)return false;var opt=jQuery.extend({},optall);var hidden=jQuery(this).is(":hidden"),self=this;for(var p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden)return jQuery.isFunction(opt.complete)&&opt.complete.apply(this);if(p=="height"||p=="width"){opt.display=jQuery.css(this,"display");opt.overflow=this.style.overflow;}}if(opt.overflow!=null)this.style.overflow="hidden";opt.curAnim=jQuery.extend({},prop);jQuery.each(prop,function(name,val){var e=new jQuery.fx(self,opt,name);if(/toggle|show|hide/.test(val))e[val=="toggle"?hidden?"show":"hide":val](prop);else{var parts=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),start=e.cur(true)||0;if(parts){var end=parseFloat(parts[2]),unit=parts[3]||"px";if(unit!="px"){self.style[name]=(end||1)+unit;start=((end||1)/e.cur(true))*start;self.style[name]=start+unit;}if(parts[1])end=((parts[1]=="-="?-1:1)*end)+start;e.custom(start,end,unit);}else +e.custom(start,val,"");}});return true;});},queue:function(type,fn){if(jQuery.isFunction(type)||(type&&type.constructor==Array)){fn=type;type="fx";}if(!type||(typeof type=="string"&&!fn))return queue(this[0],type);return this.each(function(){if(fn.constructor==Array)queue(this,type,fn);else{queue(this,type).push(fn);if(queue(this,type).length==1)fn.apply(this);}});},stop:function(clearQueue,gotoEnd){var timers=jQuery.timers;if(clearQueue)this.queue([]);this.each(function(){for(var i=timers.length-1;i>=0;i--)if(timers[i].elem==this){if(gotoEnd)timers[i](true);timers.splice(i,1);}});if(!gotoEnd)this.dequeue();return this;}});var queue=function(elem,type,array){if(!elem)return undefined;type=type||"fx";var q=jQuery.data(elem,type+"queue");if(!q||array)q=jQuery.data(elem,type+"queue",array?jQuery.makeArray(array):[]);return q;};jQuery.fn.dequeue=function(type){type=type||"fx";return this.each(function(){var q=queue(this,type);q.shift();if(q.length)q[0].apply(this);});};jQuery.extend({speed:function(speed,easing,fn){var opt=speed&&speed.constructor==Object?speed:{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&easing.constructor!=Function&&easing};opt.duration=(opt.duration&&opt.duration.constructor==Number?opt.duration:{slow:600,fast:200}[opt.duration])||400;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false)jQuery(this).dequeue();if(jQuery.isFunction(opt.old))opt.old.apply(this);};return opt;},easing:{linear:function(p,n,firstNum,diff){return firstNum+diff*p;},swing:function(p,n,firstNum,diff){return((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum;}},timers:[],timerId:null,fx:function(elem,options,prop){this.options=options;this.elem=elem;this.prop=prop;if(!options.orig)options.orig={};}});jQuery.fx.prototype={update:function(){if(this.options.step)this.options.step.apply(this.elem,[this.now,this]);(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);if(this.prop=="height"||this.prop=="width")this.elem.style.display="block";},cur:function(force){if(this.elem[this.prop]!=null&&this.elem.style[this.prop]==null)return this.elem[this.prop];var r=parseFloat(jQuery.css(this.elem,this.prop,force));return r&&r>-10000?r:parseFloat(jQuery.curCSS(this.elem,this.prop))||0;},custom:function(from,to,unit){this.startTime=(new Date()).getTime();this.start=from;this.end=to;this.unit=unit||this.unit||"px";this.now=this.start;this.pos=this.state=0;this.update();var self=this;function t(gotoEnd){return self.step(gotoEnd);}t.elem=this.elem;jQuery.timers.push(t);if(jQuery.timerId==null){jQuery.timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;ithis.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var done=true;for(var i in this.options.curAnim)if(this.options.curAnim[i]!==true)done=false;if(done){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(jQuery.css(this.elem,"display")=="none")this.elem.style.display="block";}if(this.options.hide)this.elem.style.display="none";if(this.options.hide||this.options.show)for(var p in this.options.curAnim)jQuery.attr(this.elem.style,p,this.options.orig[p]);}if(done&&jQuery.isFunction(this.options.complete))this.options.complete.apply(this.elem);return false;}else{var n=t-this.startTime;this.state=n/this.options.duration;this.pos=jQuery.easing[this.options.easing||(jQuery.easing.swing?"swing":"linear")](this.state,n,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update();}return true;}};jQuery.fx.step={scrollLeft:function(fx){fx.elem.scrollLeft=fx.now;},scrollTop:function(fx){fx.elem.scrollTop=fx.now;},opacity:function(fx){jQuery.attr(fx.elem.style,"opacity",fx.now);},_default:function(fx){fx.elem.style[fx.prop]=fx.now+fx.unit;}};jQuery.fn.offset=function(){var left=0,top=0,elem=this[0],results;if(elem)with(jQuery.browser){var parent=elem.parentNode,offsetChild=elem,offsetParent=elem.offsetParent,doc=elem.ownerDocument,safari2=safari&&parseInt(version)<522&&!/adobeair/i.test(userAgent),fixed=jQuery.css(elem,"position")=="fixed";if(elem.getBoundingClientRect){var box=elem.getBoundingClientRect();add(box.left+Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),box.top+Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));add(-doc.documentElement.clientLeft,-doc.documentElement.clientTop);}else{add(elem.offsetLeft,elem.offsetTop);while(offsetParent){add(offsetParent.offsetLeft,offsetParent.offsetTop);if(mozilla&&!/^t(able|d|h)$/i.test(offsetParent.tagName)||safari&&!safari2)border(offsetParent);if(!fixed&&jQuery.css(offsetParent,"position")=="fixed")fixed=true;offsetChild=/^body$/i.test(offsetParent.tagName)?offsetChild:offsetParent;offsetParent=offsetParent.offsetParent;}while(parent&&parent.tagName&&!/^body|html$/i.test(parent.tagName)){if(!/^inline|table.*$/i.test(jQuery.css(parent,"display")))add(-parent.scrollLeft,-parent.scrollTop);if(mozilla&&jQuery.css(parent,"overflow")!="visible")border(parent);parent=parent.parentNode;}if((safari2&&(fixed||jQuery.css(offsetChild,"position")=="absolute"))||(mozilla&&jQuery.css(offsetChild,"position")!="absolute"))add(-doc.body.offsetLeft,-doc.body.offsetTop);if(fixed)add(Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));}results={top:top,left:left};}function border(elem){add(jQuery.curCSS(elem,"borderLeftWidth",true),jQuery.curCSS(elem,"borderTopWidth",true));}function add(l,t){left+=parseInt(l)||0;top+=parseInt(t)||0;}return results;};})(); \ No newline at end of file diff --git a/public/js/mouseapp_2.js b/public/js/mouseapp_2.js new file mode 100755 index 0000000..6ea09a4 --- /dev/null +++ b/public/js/mouseapp_2.js @@ -0,0 +1,913 @@ +// +// Copyright (c) 2008 why the lucky stiff +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +var MouseApp = { + Version: '0.12', + CharCodes: { + 0: ' ', 1: ' ', 9: ' ', + 32: ' ', 34: '"', 38: '&', + 60: '<', 62: '>', 127: '◊', + 0x20AC: '€' + }, + KeyCodes: { + Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 33, PageDown: 34, + End: 35, Home: 36, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 45, + Delete: 46, F1: 112, F2: 113, F3: 114, F4: 115, F5: 116, F6: 117, + F7: 118, F8: 119, F10: 121 + }, + CodeKeys: {}, + Modes: { 1: 'b', 2: 'u', 4: 'i', 8: 'strike' }, + ModeIds: { r: 1, u: 2, i: 4, s: 8 }, + Colors: ['black', 'blue', 'green', + 'cyan', 'red', 'purple', 'brown', + 'gray', 'dark_gray', 'lt_blue', + 'lt_green', 'lt_cyan', 'lt_red', + 'lt_purple', 'yellow', 'white'] +} +//some of these are patently false, because I need to get on a real keyboard-- not a macbook. +if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1){ + MouseApp.KeyCodes = { + Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, + End: 63275, Home: 63273, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 632325, + Delete: 8, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, + F7: 63242, F8: 63243, F10: 63244 + } + +} + +//even though I am tempted to combine chrome and opera into the same if statment, I will refrain for now +// i dont have proper access to a proper keyboard and there might be a single difference between the two +if (navigator.userAgent.indexOf("Opera") > -1){ + MouseApp.KeyCodes = { + Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, + End: 63275, Home: 63273, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 632325, + Delete: 8, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, + F7: 63242, F8: 63243, F10: 63244 + } + +} + +// i am going to comment this out, since this seems un needed. if it past december 15 2009 and this +// is still commented it, please del me +//if ( navigator.appVersion.indexOf('AppleWebKit') > 0 ) { +// MouseApp.KeyCodes = { +// Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, +// End: 63275, Home: 63273, Left: 63234, Up: 63232, Right: 63235, Down: 63233, Insert: 632325, +// Delete: 63272, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, +// F7: 63242, F8: 63243, F10: 63244 +// };// +//} +for ( var k in MouseApp.KeyCodes ) { + MouseApp.CodeKeys[MouseApp.KeyCodes[k]] = k; +} + +MouseApp.isPrintable = function(ch) { + return (ch >= 32); +}; + +MouseApp.Base = function(){}; +MouseApp.Base.prototype = { + setOptions: function(options) { + this.options = { + columns: 72, rows: 24, indent: 2, + title: 'MouseApp', + blinkRate: 500, + ps: '>', + greeting:'%+r Terminal ready. %-r' + } + $.extend(this.options, options || {}); + } +} + +MouseApp.Manager = new Object(); +$.extend(MouseApp.Manager, { + observeTerm: function(term) { + this.activeTerm = term; + if ( this.observingKeyboard ) return; + var mgr = this; + if ( term.input ) { + term.input.keypress(function(e) { mgr.onKeyPress(e) }); + if (!window.opera) term.input.keydown(function(e) { mgr.onKeyDown(e) }); + else window.setInterval(function(){term.input.focus()},1); + } else { + if (!window.opera) $(document).keydown(function(e) { mgr.onKeyDown(e) }); + $(document).keypress(function(e) { mgr.onKeyPress(e) }); + } + this.observingKeyboard = true; + }, + + onKeyDown: function(e) { + e = (e) ? e : ((event) ? event : null); + if ( e && MouseApp.CodeKeys[e.keyCode] ) { + if ( window.event ) { + this.sendKeyPress(e); + } + this.blockEvent(e); + return false; + } + return true; + }, + + onKeyPress: function(e) { + if ( !window.opera && window.event && e.keyCode != 13 && e.keyCode != 8 ) { + e.charCode = e.keyCode; e.keyCode = null; + } + if ( e.keyCode == 191 ) { /* FF 1.0.x sends this upsy quizy -- ignore */ + return; + } + return this.sendKeyPress(e); + }, + + sendKeyPress: function(e) { + var term = MouseApp.Manager.activeTerm; + term.cursorOff(); + b = term.onKeyPress(e); + term.cursorOn(); + return b; + }, + + blockEvent: function (e) { + e.cancelBubble=true; + if (window.event && !window.opera) e.keyCode=0; + if (e.stopPropagation) e.stopPropagation(); + if (e.preventDefault) e.preventDefault(); + } +}); + +/* Basic text window functionality */ +MouseApp.Window = function(element, options) { + this.element = $(element); + this.setOptions(options); + this.initWindow(); +}; + +$.extend(MouseApp.Window.prototype, (new MouseApp.Base()), { + initWindow: function() { + var html = ''; + for ( var i = 0; i < this.options.rows; i++ ) { + html += "
 
\n"; + } + this.element.html(html); + this.typingOn(); + if (this.options.input) { + this.input = $(this.options.input); + this.input.focus(); + } + MouseApp.Manager.observeTerm(this); + this.clear(); + this.cursorOn(); + this.painting = true; + this.element.css({visibility: 'visible'}); + }, + + text: function() { + var str = ""; + for (var i = 0; i < this.screen.length; i++ ) { + for (var j = 0; j < this.options.columns; j++ ) { + var ch = this.screen[i][j]; + if ( ch[0] != 0 ) { + str += String.fromCharCode(ch[0]); + } + } + } + return str; + }, + + clear: function() { + this.rpos = 0; + this.cpos = 0; + this.screen = []; + this.element.html(''); + this.screen[0] = this.fillRow(this.options.columns, 0); + this.paint(0); + }, + + typingOn: function() { this.typing = true; }, + typingOff: function() { this.typing = false; }, + + cursorOn: function() { + if ( this.blinker ) { + clearInterval( this.blinker ); + } + this.underblink = this.screen[this.rpos][this.cpos][1]; + MouseApp.Manager.activeTerm.blink(); + this.blinker = setInterval(function(){MouseApp.Manager.activeTerm.blink();}, this.options.blinkRate); + this.cursor = true; + }, + + cursorOff: function() { + if ( this.blinker ) { + clearInterval( this.blinker ); + } + if ( this.cursor ) { + this.screen[this.rpos][this.cpos][1] = this.underblink; + this.paint(this.rpos); + this.cursor = false; + } + }, + + blink: function() { + if ( this == MouseApp.Manager.activeTerm ) { + var mode = this.screen[this.rpos][this.cpos][1]; + this.screen[this.rpos][this.cpos][1] = ( mode & 1 ) ? mode & 4094 : mode | 1; + this.paint(this.rpos); + } + }, + + fillRow: function(len, ch, mode) { + ary = [] + for (var i = 0; i < len; i++) { + ary[i] = [ch, mode]; + } + return ary; + }, + + paint: function(start, end) { + if (!this.painting) return; + + if (!end) end = start; + for (var row = start; row <= end && row < this.screen.length; row++) { + var html = ''; + var mode = 0; + var fcolor = 0; + var bcolor = 0; + var spans = 0; + for (var i = 0; i < this.options.columns; i++ ) { + var c = this.screen[row][i][0]; + var m = this.screen[row][i][1] & 15; // 4 mode bits + var f = (this.screen[row][i][1] & (15 << 4)) >> 4; // 4 foreground bits + var b = (this.screen[row][i][1] & (15 << 8)) >> 8; // 4 background bits + if ( m != mode ) { + if ( MouseApp.Modes[mode] ) html += ""; + if ( MouseApp.Modes[m] ) html += "<" + MouseApp.Modes[m] + ">"; + mode = m; + } + if ( ( f != fcolor && f == 0 ) || ( b != bcolor && b == 0 ) ) { + for ( var s = 0; s < spans; s++ ) html += ""; + fcolor = 0; bcolor = 0; + } + if ( f != fcolor ) { + if ( MouseApp.Colors[f] ) { + html += ""; + spans++; + } + fcolor = f; + } + if ( b != bcolor ) { + if ( MouseApp.Colors[b] ) html += ""; + spans++; bcolor = b; + } + html += MouseApp.CharCodes[c] ? MouseApp.CharCodes[c] : String.fromCharCode(c); + } + if ( MouseApp.Modes[mode] ) html += ""; + for ( var s = 0; s < spans; s++ ) html += ""; + var new_id = this.element.attr('id') + '_' + row; + if (!$('#' + new_id).get(0)) { + this.element.append("
 
"); + this.scrollAllTheWayDown(); + } + $('#' + new_id).html(html); + } + }, + + onAfterKey: function() { + this.scrollAllTheWayDown(); + }, + + highlightLine: function(i) { + if (i >= 0 && i < this.screen.length) + { + $("#" + this.element.attr('id') + "_" + i); + } + }, + + scrollToLine: function(i) { + var p = this.element[0].parentNode; + if ( p.scrollHeight > p.clientHeight ) { + p.scrollTop = (p.scrollHeight - p.clientHeight); + } + }, + + scrollAllTheWayDown: function() { + var p = this.element[0].parentNode; + if ( p.scrollHeight > p.clientHeight ) { + p.scrollTop = (p.scrollHeight - p.clientHeight); + } + }, + + putc: function(ch, mode) { + if ( ch == 13 ) { + return; + } else if ( ch == 10 ) { + this.screen[this.rpos][this.cpos] = [ch, mode]; + this.advanceLine(); + } else { + this.screen[this.rpos][this.cpos] = [ch, mode]; + this.paint(this.rpos); + this.advance(); + } + }, + + zpad: function(n) { + if (n < 10) n = "0" + n; + return n; + }, + + puts: function(str, mode) { + if ( !str ) return; + var p = this.painting; + var r = this.rpos; + this.painting = false; + for ( var i = 0; i < str.length; i++ ) { + this.insertc(str.charCodeAt(i), mode); + } + this.painting = p; + this.paint(r, this.rpos); + }, + + advance: function() { + this.cpos++; + if ( this.cpos >= this.options.columns ) { + this.advanceLine(); + } + }, + + advanceLine: function() { + this.cpos = 0; + this.rpos++; + this.ensureRow(this.rpos); + this.paint(this.rpos, this.screen.length - 1); + }, + + fwdc: function() { + var r = this.rpos; + var c = this.cpos; + if ( c < this.options.columns - 1 ) { + c++; + } else if ( r < this.screen.length - 1 ) { + r++; + c = 0; + } + var ch = (c == 0 ? this.screen[r-1][this.options.columns-1] : this.screen[r][c-1]); + if ( MouseApp.isPrintable(ch[0]) ) { + this.rpos = r; + this.cpos = c; + } + }, + + fwdLine: function() { + if ( this.rpos >= this.screen.length - 1 ) return; + this.rpos++; + while ( this.cpos > 0 && !MouseApp.isPrintable(this.screen[this.rpos][this.cpos - 1][0]) ) { + this.cpos--; + } + }, + + backc: function() { + var r = this.rpos; + var c = this.cpos; + if ( c > 0 ) { + c--; + } else if ( r > 0 ) { + c = this.options.columns - 1; + r--; + } + if ( MouseApp.isPrintable(this.screen[r][c][0]) ) { + this.rpos = r; + this.cpos = c; + return true; + } + return false; + }, + + getTypingStart: function() { + var c = this.cpos; + if ( !MouseApp.isPrintable(this.screen[this.rpos][c][0]) ) { + c--; + } + var pos = null; + for ( var r = this.rpos; r >= 0; r-- ) { + while ( c >= 0 ) { + if ( !MouseApp.isPrintable(this.screen[r][c][0]) ) { + return pos; + } + pos = [r, c]; + c--; + } + c = this.options.columns - 1; + } + }, + + getTypingEnd: function(mod) { + var c = this.cpos; + if ( !MouseApp.isPrintable(this.screen[this.rpos][c][0]) ) { + c--; + } + var pos = null; + for ( var r = this.rpos; r < this.screen.length; r++ ) { + while ( c < this.options.columns ) { + if ( !this.screen[r] || !this.screen[r][c] || !MouseApp.isPrintable(this.screen[r][c][0]) ) { + if (!mod) return pos; + mod--; + } + pos = [r, c]; + c++; + } + c = 0; + } + }, + + getTypingAt: function(start, end) { + var r = start[0]; + var c = start[1]; + var str = ''; + while ( r < end[0] || c <= end[1] ) { + if ( c < this.options.columns ) { + str += String.fromCharCode(this.screen[r][c][0]); + c++; + } else { + c = 0; + r++; + } + } + return str; + }, + + ensureRow: function(r) { + if (!this.screen[r]) { + this.screen[r] = this.fillRow(this.options.columns, 0); + } + }, + + insertc: function(ch, mode) { + var r = this.rpos; var c = this.cpos; + var end = this.getTypingEnd(+1); + if (end) { + var thisc = null; + var lastc = this.screen[this.rpos][this.cpos]; + while ( r < end[0] || c <= end[1] ) { + if ( c < this.options.columns ) { + thisc = this.screen[r][c]; + this.screen[r][c] = lastc; + lastc = thisc; + c++; + } else { + c = 0; + r++; + this.ensureRow(r); + } + } + this.paint(this.rpos, end[0]); + } + this.putc(ch, mode); + }, + + delc: function() { + /* end of line */ + if ( MouseApp.isPrintable(this.screen[this.rpos][this.cpos][0]) ) { + var end = this.getTypingEnd(); + var thisc = null; + var lastc = [0, 0]; + while ( this.rpos < end[0] || this.cpos <= end[1] ) { + if ( end[1] >= 0 ) { + thisc = this.screen[end[0]][end[1]]; + this.screen[end[0]][end[1]] = lastc; + lastc = thisc; + end[1]--; + } else { + end[1] = this.options.columns - 1; + this.paint(end[0]); + end[0]--; + } + } + } + }, + + backspace: function() { + /* end of line */ + if ( !MouseApp.isPrintable(this.screen[this.rpos][this.cpos][0]) ) { + this.backc(); + this.screen[this.rpos][this.cpos] = [0, 0]; + } else { + if ( this.backc() ) this.delc(); + } + }, + + backLine: function() { + if ( this.rpos < 1 ) return; + this.rpos--; + while ( this.cpos > 0 && !MouseApp.isPrintable(this.screen[this.rpos][this.cpos - 1][0]) ) { + this.cpos--; + } + }, + + onKeyPress: function(e) { + var ch = e.keyCode; + var key_name = MouseApp.CodeKeys[ch]; + if (window.opera && !e.altKey && e.keyCode != 13 && e.keyCode != 8) key_name = null; + ch = (e.which || e.charCode || e.keyCode); + if (e.which) ch = e.which; + if (!key_name) { key_name = String.fromCharCode(ch); } + if (e.ctrlKey) { key_name = 'Ctrl' + key_name; } + + // alert([e.keyCode, e.which, key_name, this['onKey' + key_name]]); + if (this.typing && this.onAnyKey) this.onAnyKey(key_name); + if (key_name && this['onKey' + key_name]) { + if (this.typing) this['onKey' + key_name](); + MouseApp.Manager.blockEvent(e); + if (this.typing && this.onAfterKey) this.onAfterKey(key_name, true); + return false; + } + if (!e.ctrlKey) { + if (MouseApp.isPrintable(ch)) { + if (this.typing) this.insertc(ch, 0); + MouseApp.Manager.blockEvent(e); + if (this.typing && this.onAfterKey) this.onAfterKey(key_name, true); + return false; + } + } + if (this.typing && this.onAfterKey) this.onAfterKey(key_name, false); + return true; + }, + onKeyHome: function() { + var s = this.getTypingStart(); + this.rpos = s[0]; this.cpos = s[1]; + }, + onKeyEnd: function() { + var e = this.getTypingEnd(+1); + this.rpos = e[0]; this.cpos = e[1]; + }, + onKeyInsert: function() { }, + onKeyDelete: function() { this.delc(); }, + onKeyUp: function() { this.backLine(); }, + onKeyLeft: function() { this.backc(); }, + onKeyRight: function() { this.fwdc(); }, + onKeyDown: function() { this.fwdLine(); }, + onKeyBackspace: function() { this.backspace(); }, + onKeyEnter: function() { this.insertc(10, 0); }, + onKeyTab: function() { + this.insertc(32, 0); + while (this.cpos % this.options.indent != 0) this.insertc(32, 0); + } +}); + +/* Terminal running moush */ +MouseApp.Terminal = function(element, options) { + this.element = $(element); + this.setOptions(options); + this.initWindow(); + this.setup(); +}; + +$.extend(MouseApp.Terminal.prototype, MouseApp.Window.prototype, { + setup: function() { + this.history = []; + this.backupNum = this.historyNum = this.commandNum = 0; + if (this.onStart) { + this.onStart(); + } else { + this.write(this.options.greeting + "\n", true); + this.prompt(); + } + }, + + prompt: function(ps, pt) { + if (!ps) { + ps = this.options.ps; pt = true; + } + this.write(ps, pt); + this.putc(1, 0); + this.typingOn(); + }, + + getCommand: function() { + var s = this.getTypingStart(); + var e = this.getTypingEnd(); + if (!s || !e) return; + return this.getTypingAt(s, e); + }, + + clearCommand: function() { + var s = this.getTypingStart(); + var e = this.getTypingEnd(); + if (!s || !e) return; + var r = s[0]; + var c = s[1]; + this.rpos = r; this.cpos = c; + while ( r < e[0] || c <= e[1] ) { + if ( c < this.options.columns ) { + this.screen[r][c] = [0, 0]; + c++; + } else { + c = 0; + this.paint(r); + r++; + } + } + this.paint(r); + }, + + write: function(str, pcodes) { + var p = this.painting; + var r = this.rpos; + this.painting = false; + var mode = 0; + var today = new Date(); + for ( var i = 0; i < str.length; i++ ) { + if ( str.substr(i,1) == "\n" ) { + this.advanceLine(); + continue; + } else if ( str.substr(i,1) == "\033" ) { + if ( str.substr(i+1,2) == "[m" ) { + mode = 0; + i += 2; + continue; + } + if ( str.substr(i+1,5) == "[0;0m" ) { + mode = 0; + i += 5; + continue; + } + var colors = str.substr(i+1,7).match(/^\[(\d);(\d+)m/); + if ( colors ) { + var colCode = parseInt( colors[2] ); + var color = colCode % 10; + if ( colors[1] == '1' ) { + color += 8; + } + if ( colCode / 10 == 4 ) { + color = color << 4; + } + mode = (mode & 15) + color << 4; + i += colors[0].length; + continue; + } + } else if ( str.substr(i,1) == '%' && pcodes ) { + var s2 = str.substr(i,2); + switch ( s2 ) { + case '%h': + this.puts(this.options.host, mode); + i++; + continue; + case '%l': + this.puts(this.options.name, mode); + i++; + continue; + case '%n': + this.advanceLine(); + i++; + continue; + case '%s': + this.puts("moush", mode); + i++; + continue; + case '%t': + this.puts(this.zpad(today.getHours()) + ":" + this.zpad(today.getMinutes()) + ":" + + this.zpad(today.getSeconds()), mode); + i++; + continue; + case '%u': + this.puts(this.options.user, mode); + i++; + continue; + case '%v': + this.puts(MouseApp.Version, mode); + i++; + continue; + case '%!': + this.puts(this.historyNum.toString(), mode); + i++; + continue; + case '%#': + this.puts(this.commandNum.toString(), mode); + i++; + continue; + case '%+': + var kind = str.substr(i+2, 1); + if ( MouseApp.ModeIds[kind] ) { + mode = mode | MouseApp.ModeIds[kind]; + i += 2; + continue; + } + break; + case '%-': + var kind = str.substr(i+2, 1); + if ( MouseApp.ModeIds[kind] ) { + mode = mode & ( 4095 - MouseApp.ModeIds[kind] ); + i += 2; + continue; + } + break; + } + } + this.putc(str.charCodeAt(i), mode); + } + this.painting = p; + this.paint(r, this.rpos); + }, + + onKeyUp: function() { + if ( this.backupNum == 0 ) return; + if ( this.backupNum == this.historyNum ) { + this.history[this.historyNum] = this.getCommand(); + } + this.clearCommand(); + this.backupNum--; + this.puts(this.history[this.backupNum]); + }, + onKeyDown: function() { + if ( this.backupNum >= this.historyNum ) return; + this.clearCommand(); + this.backupNum++; + this.puts(this.history[this.backupNum]); + }, + onKeyEnter: function() { + var cmd = this.getCommand(); + if (cmd) { + this.history[this.historyNum] = cmd; + this.backupNum = ++this.historyNum; + } + this.commandNum++; + this.advanceLine(); + if (cmd) { + var str = this.onCommand(cmd); + if (str) { + if ( str.substr(str.length - 1, 1) != "\n" ) { + str += "\n"; + } + this.write(str); + } + } + this.prompt(); + }, + onCommand: function(line) { + // this.puts("Echoing: " + line + "\n"); + if ( line == "clear" ) { + this.clear(); + } else { + return "\033[1;37m\033[0;44mYou typed:\033[m " + line; + } + } +}); + +/* Notepad sort of editor */ +MouseApp.Notepad = function(element, options) { + this.element = $(element); + this.setOptions(options); + this.initWindow(); + this.history = []; + this.lineno = 0; +}; + +$.extend(MouseApp.Notepad.prototype, MouseApp.Window.prototype, { + csave: function() { + if ( this.cpos_save ) { + this.cpos = this.cpos_save; + } else { + this.cpos_save = this.cpos; + } + }, + onKeyUp: function() { if ( this.rpos < 1 ) { return; } this.csave(); this.backLine(); }, + onKeyDown: function() { if ( this.rpos < this.screen.length - 1 ) { this.csave(); this.fwdLine(); } }, + onAfterKey: function(key, st) { + if ( st && !(key == 'Up' || key == 'Down') ) { + this.cpos_save = null; + } + }, + insertc: function(ch, mode) { + if (ch == 10) { + this.element.append("
 
"); + this.screen.splice(this.rpos + 1, 0, this.fillRow(this.options.columns, 0)); + var c = this.cpos; var c2 = 0; + while (c < this.options.columns) + { + if (this.screen[this.rpos][c] == 0) break; + this.screen[this.rpos + 1][c2] = this.screen[this.rpos][c]; + this.screen[this.rpos][c] = [0, 0]; + c++; c2++; + } + this.paint(this.rpos); + if (MouseApp.isPrintable(this.screen[this.rpos][c])) + { + var r = this.rpos; var c = this.cpos; + this.rpos += 1; this.cpos = c2; + this.delc(); + this.rpos = r; this.cpos = c; + } + this.putc(ch, mode); + if (this.rpos == this.screen.length - 1) + this.scrollAllTheWayDown(); + } else { + var c = this.cpos + 1; + var lastc = this.screen[this.rpos][this.cpos]; + this.putc(ch, mode); + for ( var r = this.rpos; r < this.screen.length; r++ ) { + while (c < this.options.columns) + { + var tmpc = this.screen[r][c]; + if (lastc[0] == 0) + break; + this.screen[r][c] = lastc; + lastc = tmpc; + c++; + } + if (c < this.options.columns) { + break; + } + c = 0; + } + } + }, + + backc: function() { + var r = this.rpos; + var c = this.cpos - 1; + for ( var r = this.rpos; r >= 0; r-- ) { + while ( c >= 0 ) { + this.rpos = r; + this.cpos = c; + if ( this.screen[r][c][0] != 0 ) { + this.paint(r); + return true; + } + this.screen[r][c] = [0, 0]; + c--; + } + c = this.options.columns - 1; + } + return false; + }, + delc: function() { + var c = this.cpos + 1; + for ( var r = this.rpos; r < this.screen.length; r++ ) { + while ( c < this.options.columns ) { + if ( this.screen[r][c][0] != 0 ) { + break; + } + c++; + } + if ( c < this.options.columns ) break; + c = 0; + } + + if (r >= this.screen.length) return; + + var r2 = this.rpos; + var c2 = this.cpos; + for ( var r2 = this.rpos; r2 < this.screen.length; r2++ ) { + while (c2 < this.options.columns) + { + if (this.screen[r][c][0] == 0) + break; + this.screen[r2][c2] = this.screen[r][c]; + c2++; + c++; + if (c >= this.options.columns) { + r++; + if (r >= this.options.rows) break; + c = 0; + } + } + if (c2 < this.options.columns) { + while (c2 < this.options.columns) { + this.screen[r2][c2] = [0, 0]; + c2++; + } + break; + } + c2 = 0; + } + + if (r != r2 && r < this.screen.length) + { + this.screen.splice(r, 1); + $("#" + this.element.attr('id') + "_" + this.screen.length).remove(); + } + this.paint(this.rpos, this.screen.length); + }, + onKeyBackspace: function() { + if (this.backc()) this.delc(); + } + +}); diff --git a/public/js/mouseirb_2.js b/public/js/mouseirb_2.js new file mode 100755 index 0000000..0fa5f12 --- /dev/null +++ b/public/js/mouseirb_2.js @@ -0,0 +1,179 @@ +// +// Copyright (c) 2008 why the lucky stiff +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// + +/* Irb running moush */ +MouseApp.Irb = function(element, options) { + this.element = $(element); + this.setOptions(options); + this.showHelp = this.options.showHelp; + if ( this.options.showChapter ) { + this.showChapter = this.options.showChapter; + } + if ( this.options.init ) { + this.init = this.options.init; + } + this.initWindow(); + this.setup(); + this.helpPage = null; + this.irbInit = false; +}; + +$.extend(MouseApp.Irb.prototype, MouseApp.Terminal.prototype, { + cmdToQuery: function(cmd) { + return "cmd=" + escape(cmd.replace(/</g, '<').replace(/>/g, '>'). + replace(/&/g, '&').replace(/\r?\n/g, "\n")).replace(/\+/g, "%2B"); + }, + + fireOffCmd: function(cmd, func) { + var irb = this; + if (!this.irbInit) + { + $.ajax({url: this.options.irbUrl + "?" + this.cmdToQuery("!INIT!IRB!"), type: "GET", + complete: (function(r) { irb.irbInit = true; irb.fireOffCmd(cmd, func); })}); + } + else + { + $.ajax({url: this.options.irbUrl + "?" + this.cmdToQuery(cmd), type: "GET", + complete: func}); + } + }, + + reply: function(str) { + var raw = str.replace(/\033\[(\d);(\d+)m/g, ''); + this.checkAnswer(raw); + if (!str.match(/^(\.\.)+$/)) { + if ( str[str.length - 1] != "\n" ) { + str += "\n"; + } + js_payload = /\033\[1;JSm(.*)\033\[m/; + js_in = str.match(js_payload); + if (js_in) { + try { + js_in = eval(js_in[1]); + } catch (e) {} + str = str.replace(js_payload, ''); + } + var pr_re = new RegExp("(^|\\n)=>"); + if ( str.match( pr_re ) ) { + str = str.replace(new RegExp("(^|\\n)=>"), "$1\033[1;34m=>\033[m"); + } else { + str = str.replace(new RegExp("(^|\\n)= (.+?) ="), "$1\033[1;33m$2\033[m"); + } + this.write(str); + this.prompt(); + } else { + this.prompt("\033[1;32m" + ".." + "\033[m", true); + this.puts(str.replace(/\./g, ' '), 0); + } + }, + + setHelpPage: function(n, page) { + if (this.helpPage) + $(this.helpPage.ele).hide('fast'); + this.helpPage = {index: n, ele: page}; + match = this.scanHelpPageFor('load'); + if (match != -1) + { + this.fireOffCmd(match, (function(r) { + $(page).show('fast'); + })); + } + else + { + $(page).show('fast'); + } + }, + + scanHelpPageFor: function(eleClass) { + match = $("div." + eleClass, this.helpPage.ele); + if ( match[0] ) return match[0].innerHTML; + else return -1; + }, + + checkAnswer: function(str) { + if ( this.helpPage ) { + match = this.scanHelpPageFor('answer'); + if ( match != -1 ) { + if ( str.match( new RegExp('^\s*=> ' + match + '\s*$', 'm') ) ) { + this.showHelp(this.helpPage.index + 1); + } + } else { + match = this.scanHelpPageFor('stdout'); + if ( match != -1 ) { + if ( match == '' ) { + if ( str == '' || str == null ) this.showHelp(this.helpPage.index + 1); + } else if ( str.match( new RegExp('^\s*' + match + '$', 'm') ) ) { + this.showHelp(this.helpPage.index + 1); + } + } + } + } + }, + + onKeyCtrld: function() { + this.clearCommand(); + this.puts("reset"); + this.onKeyEnter(); + }, + + onKeyEnter: function() { + this.typingOff(); + var cmd = this.getCommand(); + if (cmd) { + this.history[this.historyNum] = cmd; + this.backupNum = ++this.historyNum; + } + this.commandNum++; + this.advanceLine(); + if (cmd) { + if ( cmd == "clear" ) { + this.clear(); + this.prompt(); + } else if ( cmd.match(/^(back)$/) ) { + if (this.helpPage && this.helpPage.index >= 1) { + this.showHelp(this.helpPage.index - 1); + } + this.prompt(); + } else if ( cmd.match(/^(next)$/) ) { + if (this.helpPage) { + this.showHelp(this.helpPage.index + 1); + } + this.prompt(); + } else if ( cmd.match(/^(help|wtf\?*)$/) ) { + this.showHelp(1); + this.prompt(); + } else if ( regs = cmd.match(/^(help|wtf\?*)\s+#?(\d+)\s*$/) ) { + this.showChapter(parseInt(regs[2])); + this.prompt(); + } else { + var term = this; + this.fireOffCmd(cmd, (function(r) { term.reply(r.responseText ? r.responseText : ''); })); + } + } else { + this.prompt(); + } + } +}); + diff --git a/public/keypress_test.html b/public/keypress_test.html new file mode 100644 index 0000000..7297c4d --- /dev/null +++ b/public/keypress_test.html @@ -0,0 +1,37 @@ + + + + + + + + + +

Press a key, the details will be displayed below

+
+ + + diff --git a/public/moods/index.html b/public/moods/index.html new file mode 100755 index 0000000..e933af9 --- /dev/null +++ b/public/moods/index.html @@ -0,0 +1,8 @@ + + + + + +

you shouldn't be here.. kicking you out!

+ + diff --git a/public/moods/sick.gif b/public/moods/sick.gif new file mode 100755 index 0000000000000000000000000000000000000000..217a67cbae60740fdc90b92e06b977cf7fc56699 GIT binary patch literal 94 zcmZ?wbhEHb|6B#{self.text}" + end + + end + + class Link + attr_accessor :text, :target + def initialize(text, target) + self.text, self.target = text, target + end + def generate_html + "#{text}" + end + + + end + + class List + attr_accessor :elements + def initialize(elements) + self.elements = elements + end + + def generate_html + items = elements.map do |elem| + text = elem.instance_of?(Paragraph) ? elem.text : elem.generate_html + "
  • #{text}
  • " + end.join(" ") + + "
      #{items}
    " + end + end + + + class Paragraph + attr_accessor :text + def initialize(text) + self.text = text + end + + def generate_html + "

    #{self.text}

    " + end + end + + + class ComplexPopup + attr_reader :elements + def initialize + @elements = [] + end + + (1..6).each do |n| + define_method "h#{n}".to_sym do |text| + @elements << Header.new(n, text) + end + end + + + # def h1 text + # @elements << Header.new(1, text) + # end + + def link(text, target) + @elements << Link.new(text, target) + end + + def p(text) + @elements << Paragraph.new(text) + end + + def list(&block) + lst = ComplexPopup.new + lst.instance_eval(&block) + @elements << List.new(lst.elements) + end + + def generate_html() + @elements.map(&:generate_html).join(" ") + end + + + + end + + + def self.make(&block) + result = ComplexPopup.new + result.instance_eval(&block) + + html = result.generate_html.gsub('\\', '\\\\').gsub('"', '\"') + command = "window.irb.options.popup_make(\"#{html}\")" + TryRuby::Output.javascript command + end + +end diff --git a/public/setup.rb b/public/setup.rb new file mode 100644 index 0000000..ab97a9e --- /dev/null +++ b/public/setup.rb @@ -0,0 +1,66 @@ +module TryRuby +SetupCode = < is the given type + # - Proc: Proc should take one param (the ) and run assertions with that value + # - Regexp: Tests (a string) against the regexp + # - : should equal + def tryruby_session(session = TryRubyTestSession.new, &block) + input_o = TryRubySession_Input.new + input_o.session = session + input_o.test = self + input_o.instance_eval(&block) + + end + + + def test_lesson1 + tryruby_session do + input '2 + 6' , result: 8 + input '"Jimmy"' , result: "Jimmy" + input '"Jimmy".reverse' , result: "ymmiJ" + input '"Jimmy".length' , result: 5 + input '"Jimmy" * 5' , result: "JimmyJimmyJimmyJimmyJimmy" + end + end + + # tests statements that should end with a line continuation + def test_line_continuations + tryruby_session do + input '3.times do |v|' , line_continuation: 1 + input '3.times { |v|', line_continuation: 2 + input '}; end', result: Proc.new {true} + input 'class MyClass', line_continuation: 1 + input "def mymethod", line_continuation: 2 + input "end; end", result: Proc.new{true} + end + end + + def test_lines_with_semicolons + tryruby_session do + input '3; 4', result: 4 + input 'puts "hello"; a = 4; 5', output: "hello\n", result: 5 + input 'a', result: 4 + input '; 42', result: 42 + end + end + + + def test_errors + tryruby_session do + input 'asdf', error: NameError, output: "" + input 'print "hello"; asdf', error: NameError, output: "hello" + end + end + + # tests statements that shouldn't end with a line continuation + def test_shouldnt_have_line_continuation + tryruby_session do + input "'helloclassend'", result: "helloclassend" + input "3.class", result: Class + end + end + + def test_illegal_ops + $session = TryRubyTestSession.new + tryruby_session $session do + input '`cat /etc/passwd`', illegal: true + input 'require "popup"', result: Proc.new{} + input '%x(cat /etc/passwd)', illegal: true + end + end + + + def test_lesson2 + tryruby_session do + input '40.reverse', error: NoMethodError + input '40.to_s.reverse', result: "04" + input '[]', result: [] + input '[12,47,35]', result: [12,47,35] + input '[12,47,35].max', result: 47 + input 'ticket = [12,47,35]', result: [12,47,35] + input 'ticket', result: [12,47,35] + input 'ticket.sort!', result: [12,35,47] + end + end + + def test_lesson3 + poem = <<-EOF +My toast has flown from my hand +And my toast has gone to the +moon. +But when I saw it on television, +Planting our flag on Halley's +comet, +More still did I want to eat it. +EOF + + tryruby_session do + # the below line should be done automatically by the interpretor + # when help 3 is loaded + # input "poem = #{poem.inspect}", result: Proc.new{} + + input 'print poem', output: poem + input "poem['toast'] = 'honeydew'", result: "honeydew" + input 'print poem', output: (poem['toast'] = 'honeydew'; poem) + input 'poem.reverse', result: poem.reverse + input 'poem.lines.to_a.reverse', result: poem.lines.to_a.reverse + input 'print poem.lines.to_a.reverse.join', output: poem.lines.to_a.reverse.join + end + end + + def test_lesson4 + tryruby_session do + input 'books = {}', result: {} + + input 'books["Gravity\'s Rainbow"] = :splendid', + result: :splendid + + input 'books["a"] = :mediocre', result: :mediocre + input 'books["b"] = :mediocre', result: :mediocre + input 'books["c"] = :mediocre', result: :mediocre + input 'books.length', result: 4 + input 'books["Gravity\'s Rainbow"]', result: :splendid + input 'books.keys', result: ["Gravity's Rainbow", "a", "b", "c"] + input 'ratings = Hash.new {0}', result: {} + + input 'books.values.each { |rate| ratings[rate] += 1 }', + result: [:splendid, :mediocre, :mediocre, :mediocre] + + input '5.times {print "Odelay!" }', + result: 5, + output: 'Odelay!Odelay!Odelay!Odelay!Odelay!' + + end + end + + def test_lesson5 + tryruby_session do + input 'Dir.entries "/"', + result: [".", "..", "Home", "Libraries", "MouseHole", "Programs", "Tutorials", + "comics.txt"] + input 'Dir["/*.txt"]', result: ["/comics.txt"] + comics_txt_text = <", value.inspect + } + input 'File.mtime("/Home/comics.txt")', result: Time + input 'File.mtime("/Home/comics.txt").hour', result: Fixnum + end + + end + + def test_lesson6 + $session = TryRubyTestSession.new + tryruby_session $session do + input 'def load_comics( path )', line_continuation: 1 + input 'comics = {}', line_continuation: 1 + input 'File.foreach(path) do |line|', line_continuation: 2 + input "name, url = line.split(': ')", line_continuation: 2 + input 'comics[name] = url.strip', line_continuation: 2 + input 'end', line_continuation: 1 + input 'comics', line_continuation: 1 + input 'end', result: nil + + input "comics = load_comics('/comics.txt')", result: + {"Achewood"=>"http://achewood.com/", + "Dinosaur Comics"=>"http://qwantz.com/", + "Perry Bible Fellowship"=>"http://cheston.com/pbf/archive.html" , + "Get Your War On"=>"http://mnftiu.cc/"} + + input "require 'popup'", result: Proc.new {} + input 'Popup.goto "http://google.com/"', + javascript: "window.irb.options.popup_goto(\"http://google.com/\")" + + input 'Popup.make {', line_continuation: 1 + input 'h1 "My Links"', line_continuation: 1 + input 'link "Go to Google", "http://google.com/"', line_continuation: 1 + input '}', javascript: + "window.irb.options.popup_make" + + "(\"

    My Links

    " + + "Go to Google\")" + + input 'Popup.make do', line_continuation: 1 + input 'h1 "Things To Do"', line_continuation: 1 + input 'list do', line_continuation: 2 + input 'p "Try out Ruby"', line_continuation: 2 + input 'p "Ride a tiger"', line_continuation: 2 + input 'p "(down River Euphrates)"', line_continuation: 2 + input 'end', line_continuation: 1 + expected = <Things To Do +
    • Try out Ruby
    • +
    • Ride a tiger
    • +
    • (down River Euphrates) +
    ") +EOF + input 'end', javascript: expected.gsub("\n", "") + +input 'Popup.make do', line_continuation: 1 +input 'h1 "Comics on the Web"', line_continuation: 1 +input 'list do', line_continuation: 2 +input 'comics.each do |name, url|', line_continuation: 3 +input 'link name, url', line_continuation: 3 +input 'end', line_continuation: 2 +input 'end', line_continuation: 1 +input 'end', javascript: Proc.new { |v| + matches = v.match(/^window.irb.options.popup_make\("(.*)"\)/) + assert_not_nil(matches) + html = matches[1].gsub(/\\(.)/, '\1') + doc = Hpricot(html) + assert_equal("Comics on the Web", (doc/:h1).inner_html) + list_items = (doc/:li/:a).map do |elem| + {href: elem.attributes['href'], title: elem.inner_html} + end + assert_equal({href: "http://achewood.com/", title: "Achewood"}, + list_items[0]) + assert_equal({href: "http://qwantz.com/", title: "Dinosaur Comics"}, + list_items[1]) + assert_equal({href: "http://cheston.com/pbf/archive.html", + title: "Perry Bible Fellowship"}, + list_items[2]) + assert_equal({href: "http://mnftiu.cc/", title: "Get Your War On"}, + list_items[3]) + + #assert_equal("", html) + } + + + + + end + + end + + + + + def test_lesson7_and_8 + $session = TryRubyTestSession.new + tryruby_session $session do + input 'Hash.new', result: {} + input 'class BlogEntry', line_continuation: 1 + input 'attr_accessor :title, :time, :fulltext, :mood', line_continuation: 1 + input 'end', result: nil + + # can't test for BlogEntry directly, as it isn't defined in this scope + input 'entry = BlogEntry.new', result: Proc.new {|v| + assert_equal("BlogEntry", v.class.name, + "line should result in a BlogEntry") + } + + input 'entry.title = "Today Mt. Hood Was Stolen!"', result: "Today Mt. Hood Was Stolen!" + + input 'entry.time = Time.now', result: Time + + input 'entry.mood = :sick', result: :sick + + str = <

    My Blog

    +
      +
    • Today Mt. Hood Was Stolen!

    • +
    • I can't believe Mt. Hood was stolen! I am speechless! + It was stolen by a giraffe who drove away in his + Cadillac Seville very nonchalant!!
    • +
    • I Left my Hoodie on the Mountain!

    • +
    • I am never going back to that mountain and + I hope a giraffe steals it.
    • +
    + EOF + + expected_xml = REXML::Document.new(expected_str.strip) + assert_match(/^window.irb.options.popup_make\(".*"\)?/m, + v, + "testing that Popup calls the correct javascript function") + actual_str = v.match(/^window.irb.options.popup_make\("(.*)"\);?/m)[1] + actual_str = "#{actual_str}" + actual_xml = REXML::Document.new(actual_str.strip) + assert_equal(expected_xml.write(StringIO.new).to_s, + actual_xml.write(StringIO.new).to_s, + "testing that html used with the javascript popup " + + "function is correct") + } + + input 'Time.now - 2.weeks', result: Time + + input 'File.read("/MouseHole/flickrpedia.user.rb")', result: String + + end # tryruby_session + + end # lesson6_and_7 + + + + + # class that performs the tests with the input sections of the + # tryrubysession test helper + class TryRubySession_Input + attr_accessor :session, :test + + # performs an assertion + # actual is the value being tested + # expected should either be a + # - Class: the class of actual should be expected + # - Regexp: actual (a string) should match the expected Regexp + # - Proc: A proc that takes one argument, actual. Assertions can + # be used inside that proc, eg assert_equal, assert. + # - : actual should equal expected + # name is the name of the input (result, output, javascript, error), + # used in messages + # line is the line being tested + def do_assert(actual, expected, name, line) + case expected + when Class + @test.assert_kind_of(expected, actual, + "Testing line `#{line}': #{name} should be a #{expected}") + when Regexp + @test.assert_match(expected, actual, + "Testing line `#{line}': #{name} should match #{expected}") + when Proc + @backtrace_pos = 0 + @test.instance_exec(actual, &expected) + + # @test.assert(expected.call(actual), + # "Testing line `#{line}': #{message} \n[#{actual}]") + else + @test.assert_equal(expected,actual, + "Testing line `#{line}' for correct #{name}") + end + end + + # runs the line using this objects session. + def do_test(line) + o = Object.new + # store the initial constants of Object + initial_constants = Object.constants + session = @session + + thread = Thread.new do + o.instance_eval do + run_script(session, line) + end + end + + result = thread.value + # restores require to its old functionality + #def Object.require(str) + # old_require(str) + #end + + # next 4 lines will revert Object to the way it was before + # run_script + diff_constants = Object.constants - initial_constants + diff_constants.each do |constant| + Object.send(:remove_const, constant) + end + result + end + + + # The input function, used with the tryruby_session test helper + # see tryruby_session for more details + def input(line, params = {}) + @backtrace_pos = 2 + params[:output] ||= "" + params[:result] ||= nil + params[:error] ||= nil + + result = do_test(line) + begin + if params[:illegal] then + @test.assert_equal(:illegal, result.type, + "Testing if line `#{line}' resulted in an illegal operation") + elsif params[:error] then + @test.assert_equal(:error, result.type, + "Testing if line `#{line}` resulted in an error") + do_assert(result.error, params[:error], "error", line) + do_assert(result.output, params[:output], "output", line) + elsif params[:javascript] then + @test.assert_nil(result.error, + "Testing line `#{line}' to ensure there was no error") + do_assert(result.javascript, params[:javascript], "javascript", line) + do_assert(result.output, params[:output], "output", line) + elsif params[:line_continuation] + @test.assert_equal(:line_continuation, result.type, + "Testing if line `#{line}' resulted in a line continuation") + if params[:line_continuation] != true then + @test.assert_equal(result.indent_level, params[:line_continuation], + "Testing if line `#{line}' triggered enough autoindent") + end + else + @test.assert_nil(result.error, + "Testing line `#{line}' to ensure there was no error") + do_assert(result.result, params[:result], "result" , line) + do_assert(result.output, params[:output], "output", line) + end + + rescue Test::Unit::AssertionFailedError => e + p e + + new_bt = Test::Unit::Util::BacktraceFilter.filter_backtrace(e.backtrace) + new_bt = new_bt[@backtrace_pos..@backtrace_pos] + e.set_backtrace(new_bt) + raise e + + end + end + end +end + +# tests if the TryRubyOutput translation, for use with mouseapp_2.js and similar +# is working correctly +class TryRubyOutputTest < Test::Unit::TestCase + def test_simple_result + t = TryRubyOutput.standard(result: [12,24]) + assert_equal("=> \033[1;20m[12, 24]", t.format_output) + end + + def test_result_and_output + t = TryRubyOutput.standard(result: 333, output: "hello") + assert_equal("hello=> \033[1;20m333", t.format_output) + end + + def test_error + begin + 40.reverse + rescue Exception => e + t = TryRubyOutput.error(error: e) + end + assert_equal("\033[1;33mNoMethodError: undefined method `reverse' for 40:Fixnum", + t.format_output) + end + + def test_error_with_output + begin + 40.reverse + rescue Exception => e + t = TryRubyOutput.error(error: e, output: "hello\nworld") + end + assert_equal("hello\nworld\033[1;33mNoMethodError: undefined method `reverse' for 40:Fixnum", + t.format_output) + end + + def test_illegal + t = TryRubyOutput.illegal + assert_equal("\033[1;33mYou aren't allowed to run that command!", + t.format_output) + end + + + + def test_line_continuation + t = TryRubyOutput.line_continuation(3) + assert_equal(".." * 3, t.format_output) + end + + def test_javascript + t = TryRubyOutput.javascript(javascript: 'alert("hello")') + # expected ends in a space to stop a visual problem in mouseapp + assert_equal("\033[1;JSmalert(\"hello\")\033[m ", t.format_output) + end + +end diff --git a/public/tmp/index.html b/public/tmp/index.html new file mode 100755 index 0000000..e933af9 --- /dev/null +++ b/public/tmp/index.html @@ -0,0 +1,8 @@ + + + + + +

    you shouldn't be here.. kicking you out!

    + + diff --git a/public/tryruby.rb b/public/tryruby.rb new file mode 100644 index 0000000..bcdc183 --- /dev/null +++ b/public/tryruby.rb @@ -0,0 +1,174 @@ +#$LOAD_PATH.unshift File.join(File.dirname(__FILE__), 'submodules', 'fakefs', 'lib') +require 'setup.rb' +require 'ruby_parser' +require 'fakefs/safe' +require 'stringio' + +module TryRuby + extend self + + class Session + attr_accessor :past_commands, :current_statement, :start_time + def initialize + @past_commands = '' + @current_statement = '' + @start_time = Time.now + end + end + + class Output + attr_reader :type, :result, :output, :error, :indent_level, :javascript + + def self.standard(params = {}) + Output.new type: :standard, result: params[:result], + output: params[:output] || '' + end + + def self.illegal + Output.new type: :illegal + end + + def self.javascript(js) + Output.new type: :javascript, javascript: js + end + + def self.no_output + Output.standard result: nil + end + + def self.line_continuation(level) + Output.new type: :line_continuation, indent_level: level + end + + def self.error(params = {}) + params[:error] ||= StandardError.new('TryRuby Error') + params[:error].message.gsub! /\(eval\):\d*/, '(TryRuby):1' + Output.new type: :error, error: params[:error], + output: params[:output] || '' + end + + def format + case @type + when :line_continuation + ".." * @indent_level + when :error + @output + "\033[1;33m#{@error.class}: #{@error.message}" + when :illegal + "\033[1;33mYou aren't allowed to run that command!" + when :javascript + "\033[1;JSm#{@javascript}\033[m " + else + @output + "=> \033[1;20m#{@result.inspect}" + end + end + + protected + def initialize(values = {}) + values.each do |variable, value| + instance_variable_set("@#{variable}", value) + end + end + end + + + class << self + attr_accessor :session + TryRuby.session = TryRuby::Session.new + end + + def calculate_nesting_level(statement) + begin + RubyParser.new.parse(statement) + 0 + rescue Racc::ParseError => e + case e.message + when /parse error on value \"\$end\" \(\$end\)/ then + new_statement = statement + "\n end" + begin + RubyParser.new.parse(new_statement) + return 1 + rescue Racc::ParseError => e + if e.message =~ /parse error on value \"end\" \(kEND\)/ then + new_statement = statement + "\n }" + end + end + begin + 1 + calculate_nesting_level(new_statement) + rescue Racc::ParseError => e + return 1 + end + else + raise e + end + end + end + + def run_line(code) + case code.strip + when '!INIT!IRB!' + return Output.no_output + when 'reset' + TryRuby.session.current_statement = '' + return Output.no_output + when 'time' + seconds = (Time.now - session.start_time).ceil + return Output.standard result: + if seconds < 60; "#{seconds} seconds" + elsif seconds < 120; "1 minute" + else; "#{seconds / 60} minutes" + end + end + + # nesting level + level = begin + calculate_nesting_level(session.current_statement + "\n" + code) + rescue Racc::ParseError, SyntaxError + 0 + end + if level > 0 + session.current_statement += "\n" + code + return Output.line_continuation(level) + end + + # run something + FakeFS.activate! + stdout_id = $stdout.to_i + $stdout = StringIO.new + cmd = <<-EOF + #{SetupCode} + $SAFE = 3 + #{session.past_commands} + $stdout = StringIO.new + begin + #{session.current_statement} + #{code} + end + EOF + begin + result = Thread.new { eval cmd, TOPLEVEL_BINDING }.value + rescue SecurityError + return Output.illegal + rescue Exception => e + return Output.error :error => e, :output => get_stdout + ensure + output = get_stdout + $stdout = IO.new(stdout_id) + FakeFS.deactivate! + end + + session.current_statement += "\n" + code + session.past_commands += "\n" + session.current_statement.strip + session.current_statement = '' + + return result if result.is_a? Output and result.type == :javascript + Output.standard result: result, output: output + end + + private + def get_stdout + raise TypeError, "$stdout is a #{$stdout.class}" unless $stdout.is_a? StringIO + $stdout.rewind + $stdout.read + end + +end \ No newline at end of file diff --git a/public/tutorials/es_intro.html b/public/tutorials/es_intro.html new file mode 100644 index 0000000..256de2f --- /dev/null +++ b/public/tutorials/es_intro.html @@ -0,0 +1,666 @@ + +
    +

    Usando El Prompt

    +

    La ventana azul de arriba es el prompt de Ruby. ¡Escribe una línea de código Ruby, aprieta Enter + y velo correr!

    +

    Por ejemplo, trata de escribir algo matemático. Como: 2 + 6

    +
    \d+
    +
    +
    +

    Números & Matemática

    +

    ¡Bien! Hiciste algo de matemática. ¿Ves como la respuesta salta a la vista?

    +

    Ruby reconoce números y símbolos matemáticos. Puedes probar otras cosas como:

    +
    • 4 * 10
    • +
    • 5 - 12
    • +
    • 40 / 4
    +

    Seguro, las computadoras son habilidosas y rápidas con las matemáticas. Sigamos... ¿Quieres ver tu nombre al revés? + Escribe tu primer nombre entre comillas así: "Jimmy"

    +
    "(\w+)"
    +
    +
    +

    Decir Tu Nombre Al Revés

    +

    Perfecto, has formado un string de las letras de tu nombre. Un string + es un juego de caracteres que la computadora puede procesar.

    +

    Imagina que las letras están en una cuerda donde + se cuelga la ropa y las comillas son los broches que sostienen los bordes. Las comillas marcan el comienzo y el final.

    +

    Para invertir tu nombre, escribe: "Jimmy".reverse (¡No olvides el punto!)

    +
    "(\w+)"
    +
    +
    +

    Contando Las Letras

    +

    ¡Has usado el método reverse sobre tu nombre! Poniendo tu nombre entre comillas, + hiciste un string. Luego llamaste al método reverse, que funciona sobre un string cambiando + todas las letras de atrás para adelante.

    +

    Ahora, vamos a ver cuantas letras tiene tu nombre: "Jimmy".length

    +
    \d+
    +
    +
    +

    Repitiendo

    +

    Ahora, estoy seguro que te estarás preguntando para que sirve todo esto. Bueno, estoy seguro que habrás estado en alguna + pagina web donde te gritaron, ¡Hey, tu password es muy corto! Ves, algunos programas + usan este código tan simple.

    +

    Mira esto. Vamos a multiplicar tu nombre por 5. "Jimmy" * 5

    +
    "(\w+)"
    +
    +
    +

    Hey, Sumario #1 Listo

    +

    Vamos a ver que es lo que has aprendido en el primer minuto.

    +
      +
    • El prompt. Escribiendo código en el prompt verde obtienes + una respuesta del prompt rojo. Todo código te da una respuesta.
    • +
    • Números y strings son objetos matemáticos y de texto de Ruby.
    • +
    • Métodos Has usado métodos en Ingles como reverse + y métodos simbólicos como * (el método de multiplicación.) ¡Los métodos son acciones!
    • +
    +

    Esta es la esencia del aprendizaje. Tomar cosas simples, jugar con ellas + y trasformarlas en cosas nuevas. ¿Te sientes cómodo con todo? Te aseguro que lo estas.

    +

    Bien, vamos a hacer algo incomodo. Trata de invertir un número: 40.reverse

    +
    NoMethodError: undefined method `reverse' for (\d+):Fixnum
    +
    +
    +

    ¡Basta, Te Volviste Loco!

    +

    No puedes invertir el numero cuarenta. Supongo que puedes poner tu monitor en + frente de un espejo, pero invertir un numero no tiene sentido. Ruby lanza un + mensaje de error. Ruby te dice que no hay un método reverse para los números.

    +

    Tal vez si lo conviertes en un string: 40.to_s.reverse.

    +
    \"(\d+)\"
    +
    +
    +

    Los Chicos Son Diferentes De Las Chicas

    +

    Y los números son diferentes de los strings. Aunque puedes usar métodos en cualquier objeto + en Ruby, algunos métodos solo funcionan en cierto tipo de cosas. Pero siempre puedes + convertir entre diferentes tipos usando el método "to" de Ruby.

    +
    • to_s convierte cosas a strings.
    • +
    • to_i convierte cosas a integers (números.)
    • +
    • to_a convierte cosas a arrays.
    • +
    +

    ¿Que son los arrays?! Son listas. Escribe entre un par de corchetes: [].

    +
    \[\]
    +
    +
    +

    Mantenerse en Cola

    +

    Genial, eso es una lista vacía. Las listas guardan cosas en orden. + Como esperando en la cola para palomitas de maíz. Estas atrás de alguien y jamás + pensarías en empujarlo a un costado, ¿no es así? Y con respecto al tipo detrás de ti, + mantienes un ojo sobre el, ¿correcto?

    +

    Acá hay una lista para ti. Números de la lotería: [12, 47, 35].

    +
    \[(\d+(, )?){2,}\]
    +
    +
    +

    Uno Levanta La Mano

    +

    Una lista de números de la lotería. ¿Cual es el mayor?

    +

    Prueba: [12, 47, 35].max.

    +
    (\d+)
    +
    +
    +

    Manteniendo la Lista

    +

    Bien, bien. Pero es un fastidio el tener que reescribir esa lista, ¿no es así?

    +

    Guardemos nuestros números en un ticket de esta manera: ticket = [12, 47, 35]

    +
    \[(\d+(, )?){2,}\]
    +
    +
    +

    Ahora Escribe Ticket

    +

    Ahora, escribe: ticket

    +
    \[(\d+(, )?){2,}\]
    +
    +
    +

    Guardado, Escondido

    +

    ¡Fantástico! Te has aferrado a tus números de la lotería, escondiéndolos dentro de una + variable llamada ticket.

    +

    Vamos a poner tus números en orden, que te parece? Usa: ticket.sort!

    +
    \[(\d+(, )?){2,}\]
    +
    +
    +

    Sumario #2 Está Sobre Nosotros

    +

    Tenías una lista. Ordenaste la lista. La variable ticket ahora esta cambiada.

    +

    ¿Te diste cuenta que el método sort! tiene un claro y llamativo signo de exclamación al final? + Muchas veces los métodos de Ruby gritan así si es que alteran la variable para bien. No es nada + especial, solo una marca.

    +

    Ahora, mira como te fue en tu segundo minuto:

    +
      +
    • Errors. Si tratas de invertir un número o hacer algo sospechoso, + Ruby salteara el prompt para avisarte.
    • +
    • Arrays son listas para ordenar cosas en orden.
    • +
    • Variables guardan cosas y le dan un nombre. Usaste el + signo igual para hacerlo.
      Like: ticket = [14, 37, 18].
    • +
    +

    En total hay ocho lecciones. Estás a dos octavos de camino! + Esto es cosa simple, no te parece? Las cosas buenas están mas adelante.

    +

    Cambiemos de dirección por un momento. Rellené con un poco de poesía cierta + variable para ti. Hecha un vistazo. Escribe print poem

    +
    poem = "My toast has flown from my hand\nAnd my toast has gone to the +moon.\nBut when I saw it on television,\nPlanting our flag on Halley's +comet,\nMore still did I want to eat it.\n"
    +
    My toast (.+)
    +
    +
    +

    Desgraciadamente, Tú Odias la poesía de Tostadas

    +

    Mira, esta bien. No tiene que gustarte. Hackéalo, yo invito.

    +

    En vez de tostada, ve por un melón o algo. Prueba esto: poem['toast'] = 'honeydew'

    +

    Y luego escribe print poem para ver el nuevo poema.

    +
    My honey(.+)
    +
    +
    +

    Listo, Apuntado

    +

    Los corchetes que acabas de usar son muy comunes en Ruby. Recuerda, escribiste: poem['toast'] = 'honeydew'. Esa casilla con la palabra toast tiene corchetes a ambos lados, ¿ves?

    +

    Los +corchetes son como una mira para alinear un objetivo. Exacto. Estos +corchetes significan, "Estoy buscando ____." Listo, apuntado. Aquí estas buscando +una costada e intercambiándola por una fruta.

    +

    Aquí hay una pregunta: ¿Que pasa si volteamos el poema entero? poem.reverse +

    "\\n.ti tae ot (.+)"
    +
    +
    +

    Demasiado Invertido

    +

    Está bien, seguro. Entonces todo el poema fue puesto al revés. Letra por letra. Sin embargo, yo realmente solo quería + invertir las líneas. Mover la última línea a la primera y la primera hacia abajo a la ultima. Al revés, pero no + ése revés.

    +

    Aquí esta como lograrlo: poem.lines.to_a.reverse

    +
    \["More still did I(.+)"\]
    +
    +
    +

    Rizos de Metodos Concatenados

    +

    Dime, que es lo que ves? Que paso acá? Escribiste poem.lines.to_a.reverse y ¿que pasó?

    +

    Dos cosas pasaron. Convertiste poem en una lista usando +lines.to_a. lines decide la forma en que +el string se divide, luego to_a lo +convierte en un Array. (To array.) Diferentes métodos, como +bytes y chars pueden ser usadas en lugar de +lines. Usando lines, Ruby retornará cada línea de poem.

    +

    Luego, tu revertiste, reversed, esa lista. Tenías cada línea. Las revertiste. Eso es todo.

    +

    Vamos a hilar un método más al final de todo esto: print poem.lines.to_a.reverse.join +

    More still did I(.+)
    +
    +
    +

    De Todos los Sumarios, el #3 esta aquí

    +

    Buen espectáculo, mi amigo! El método join toma la lista de líneas revertidas y las pone juntas en un string. + (Seguro, también podrías haber usado to_s.)

    +

    Tiempo de Revisión.

    +
      +
    • Exclamaciones. Métodos pueden tener signos de exclamación (y también de interrogación) en + sus nombres. No es la gran cosa. Prueba: poem.include? "my hand"
    • +
    • Corchetes. Establece objetivos y busca cosas. Busca y reemplaza.
    • +
    • Concatenar métodos te permite hacer mas cosas juntas. Partir poem, revertirlo, + reensamblarlo: poem.lines.to_a.reverse.join
    • +
    +

    En este punto, querras manosear un poco más el poema. Una lista completa de métodos + String estan + + acá. + No temas y prueba algunos (como poem.downcase o poem.delete.)

    +

    Cuando estés listo para seguir adelante, escribe: books = {}

    +
    \{\}
    +
    +
    +

    Un Pequeñín Libro en Blanco

    +

    Has hecho un hash vacío. (también conocido como: un diccionario vacío.)

    +

    Vamos a rellenar con un libro de críticas en miniatura. Acá esta nuestro sistema de calificación:

    +
      +
    • :splendid → una obra maestra.
    • +
    • :quite_good → disfrutable, por supuesto que sí.
    • +
    • :mediocre → partes iguales de bueno y malo.
    • +
    • :quite_not_good → notablemente malo.
    • +
    • :abyssmal → una perdida de tiempo.
    • +
    +

    Para calificar un libro, pon el título entre corchetes y la calificación luego del signo igual.

    +

    Por ejemplo: books["Gravity's Rainbow"] = :splendid

    +
    :\w+
    +
    +
    +

    Mas Críticas Tamaño Bocadillo

    +

    Tú sigue, agrega mas críticas. Y, si quieres ver toda la lista, + implemente escribe: books

    +

    De nuevo, las calificaciones son: :splendid, :quite_good, :mediocre, + :quite_not_good, and :abyssmal.

    +

    Estas calificaciones no son strings. Cuando colocas dos puntos frente a una palabra simple, obtienes un + symbol. Los símbolos son más baratos que los strings (en términos de memoria de la computadora.) Si usas + una palabra una y otra vez en un programa, usa un símbolo. En vez de tener miles de + copias de una palabra en memoria, la computadora guardara el símbolo solamente una vez.

    +

    Una vez que tengas tres o cuatro libros allí + dentro, escribe: books.length.

    +
    [3-9]
    +
    +
    +

    Espera, ¿Me gustó Gravity's Rainbow?

    +

    Ves, el método length funciona sobre strings, list y hashes. Una gran cosa acerca de + Ruby es que los nombres usualmente se reutilizan, lo que significa menos nombres para recordar.

    +

    Si quisieras ver una de tus críticas hechas, vuelve a poner el título entre corchetes. Pero deja de lado el + signo igual.

    +

    Al igual que aquí: books["Gravity's Rainbow"]

    +
    :\w+
    +
    +
    +

    Hashes como Pares

    +

    Ten en mente que los hashes no mantienen las cosas en orden. Ese no es su trabajo. Solo emparejará dos + cosas: una key (llave) y un valor. En tus críticas, la key es el + titulo del libro y el valor es la calificación.

    +

    Si simplemente quieres ver los títulos de los libros que calificaste: books.keys

    +
    \[".*"\]
    +
    +
    +

    ¿Eres Duro?

    +

    ¿Estás dando duras injustas críticas? Sigamos puntuando con rigurosidad:
    ratings = Hash.new {0}

    +

    Entonces, bien, ahora vamos a contar tus críticas. Trata de seguirme. Escribe:
    + books.values.each { |rate| ratings[rate] += 1 }

    +

    (La línea vertical es el signo de tubería, probablemente lo logres con AltGr+1 con tu teclado.)

    +
    \[:.+\]
    +
    +
    +

    Un Recuento

    +

    Genial, wow! Has hecho un recuento de tus calificaciones. Escribe ratings para ver las cuenta. Este nuevo + hash muestra las calificaciones y luego el numero de veces que has dado esa calificación.

    +

    Una de las asombrosas cosas nuevas que acabamos de usar es un bloque, block. Vamos a explorar + explore these more in the next summary. más esto en el próximo sumario. Pero, básicamente, un bloque es un pedazo de código Ruby + rodeado por llaves.

    +

    Probemos otro bloque: 5.times { print "Odelay!" }

    +
    Odelay!Od.*
    +
    +
    +

    Ahora Arribamos al Sumario #4

    +

    Los bloques están siempre apegados a métodos. Como el método times, que toma el bloque y lo corre + repetidas veces. (En este caso: cinco veces.)

    +

    Esta última lección fue algo mas larga. Probablemente usaste unos tres minutos aprendiendo sobre:

    +
      +
    • Hashes. El pequeño diccionario con páginas arrugadas: {}.
    • +
    • Symbols. Pequeñas, eficientes palabras con dos puntos: :splendid.
    • +
    • Blocks. Pedazos de código que pueden ser clavados a muchos métodos de Ruby. Aquí + esta el código que usaste para crear el recuento:
      books.values.each { |rate| ratings[rate] += 1 }.
    • +
    +

    En tu computadora, probablemente tienes muchos archivos diferentes. Archivos con fotos en ellos, + archivos con programas dentro. Y los archivos usualmente se organizan en carpetas, también llamadas: + directorios.

    +

    He preparado algunos directorios para ti. Echa un vistazo: + Dir.entries "/"

    +
    \["\.", .+\]
    +
    +
    +

    La Privada Colección de Dr. Dir

    +

    Acabas de listar todo lo existente en el directorio superior. El directorio raíz, indicado + por la barra en diagonal. Conteniendo algunos programas y otros tutoriales y semejantes.

    +

    Entonces, ¿que es el método Dir.entries? Bueno, es solo un método ¿si?, + entries es el método llamado sobre la variable Dir. + Y Dir tiene una colección de métodos para chequear los archivos de los directorios.

    +

    Otra pequeña cosa de la que no hemos hablado abiertamente. Argumentos de los métodos, resaltados en verde.

    +
      +
    • Dir.entries "/": Cualquier cosa listada luego de un método + es considerado acoplamiento.
    • +
    • print poem: Ves, print es un método ordinario. + Y el poema esta acoplado. Para ser impreso.
    • +
    • print "pre", "event", "ual", "ism" posee varios argumentos, + con comas entre ellos.
    • +
    +

    Para listar solamente archivos de texto en el directorio: Dir["/*.txt"]

    +
    \["\/comics\.txt"\]
    +
    +
    +

    Ven, Lee Historietas Conmigo

    +

    El método Dir[] hace como entries pero tu buscas por archivos + archivos con carácteres de comodín. ¡Aquí, vemos esos corchetes otra vez! Te das + cuenta como todavía significan, "Estoy buscando _____.".

    +

    Mas específicamente: "Estoy buscando archivos que terminen con .txt."

    +

    Abramos este archivo con historietas de una vez. Aquí esta la manera:
    + print File.read("/comics.txt")

    +
    Achewood.+
    +
    +
    +

    Mi Comicas, Tu Comicas

    +

    ¡De acuerdo! Podemos comenzar a usar archivos para guardar cosas. Esto es excelente + porque normalmente cuando salimos de Ruby, todas nuestras variables desaparecerán. + Ruby, por si mismo, olvida estas cosas. Pero si salvamos cosas en archivos, + podemos leer esos archivos en futuras escapadas a Ruby.

    +

    Hey, y ¿adivina que? ¡El directorio /Home es tuyo! ¡Te lo entrego a ti! ¡Soy generoso! Hagamos una copia del archivo de la historieta.

    +

    Querrás hacer lo siguiente: FileUtils.copy('/comics.txt', '/Home/comics.txt') +

    Si ya has creado el archivo, usa File.delete('/Home/comics.txt') para arrojarlo a la basura.

    +
    nil
    +
    +
    +

    Tu Propio Territorio

    +

    Ok, tienes una copia. Chequéala: Dir["/Home/*.txt"]

    +

    Para agregar tu propia historieta a la lista, abramos el archivo en modo append.

    +

    Empieza asi: File.open("/Home/comics.txt", "a") do |f|.

    +
    ..
    +
    +
    +

    Y Ahora, para la Sorprendente Conclusión

    +

    Asi que tu prompt ha cambiado. ¿Lo notas? Tu prompt es doble punto ahora.

    +

    En este tutorial, este prompt significa que Ruby espera que escribas más. A + medida que vayas completando con líneas de código, los doble puntos se mantendrán + hasta que hallas finalizado.

    +

    Hot tip: si quieres parar de trabajar en el código y salirte de los doble puntos, usa el comando reset. + Si quieres volver a la pagina previa del tutorial, usa el comando back.

    +

    Aquí esta tu código. Ya has escrito la primera línea, asi que simplemente ingresa la segunda. (El \n + es el carácter de Enter.

    +
    • File.open("/Home/comics.txt", "a") do |f|
    • +
    •   f << "Cat and Girl: http://catandgirl.com/\n"
    • +
    • end
    • +
    +

    Y, como te has vuelto avanzado y capaz aquí, otro tip: puedes usar las flechas hacia + arriba y hacia abajo para editar tus viejos comandos o correrlos otra vez.

    +
    ..
    +
    +
    +

    Ruby se Sienta y Espera

    +

    Esa ultima línea agrega la historieta Cat and Girl a la lista, pero Ruby seguirá esperando + hasta que hallas terminado por completo para tomar acción.

    +

    Ahora, para finalizar el código que has empezado. Empezaste un nuevo bloque cuando escribiste do. + Hasta ahora los bloques que hemos visto usaban llaves. Esta vez usaremos do y end en lugar + de las llaves. Muchos Rubyistas usan do...end cuando el bloque ocupa varias líneas.

    +

    Terminemos ese bloque ahora mismo, con: end

    +
    • File.open("/Home/comics.txt", "a") do |f|
    • +
    •   f << "Cat and Girl: http://catandgirl.com/\n"
    • +
    • end
    • +
    +
    #.File:/Home/comics\.txt \(closed\).
    +
    +
    +

    El Reloj Clavado en el Archivo

    +

    ¡Bien, bien! Has añadido esa historieta al archivo. Puedes verlo por ti mismo: print File.read("/Home/comics.txt")

    +

    ¿Qué hora era cuando cambiaste el archivo? Veamos. Escribe: File.mtime("/Home/comics.txt")

    +
    \w+ \w+ \d+ \d{2}:\d{2}:\d{2} [+-]\d{4} \d{4}
    +
    +
    +

    Sólo la Manecilla de la Hora

    +

    Estupendo, allí esta la hora. La hora exacta en la que agregaste la historieta al archivo. El mtime te devuelve un objeto Time de Ruby.

    +

    Si sólo quieres ver la hora que era, aprieta la flecha para arriba y cambia la línea a: File.mtime("/Home/comics.txt").hour

    +
    \d+
    +
    +
    +

    Hola, ¿Quién Anda Ahí? Y el Sumario #5 Agita su Sombrero!

    +

    Bien hecho, bien hecho, bien hecho, ¡bien hecho! Realmente, realmente, realmente, realmente, ¡reaaaaaaaaalllmente!

    +

    Aquí esta tu último minuto de tu vida en retrospectiva:

    +
      +
    • Archivos. ¿Que más se puede decir? Muchos métodos para editar archivos y revisar directorios.
    • +
    • Argumentos. Los argumentos son listas de cosas mandadas en un método. Separadas con comas.
    • +
    • También hablamos sobre do y end que es otra manera de hacer un bloque.
    • +
    +

    Ahora ya sabes como usar Ruby por completo. Me refiero a que tienes lo esencial. Solo necesitas seguir + aprendiendo métodos y probar bloques más complejos.

    +

    Pero existe un lado de Ruby que no hemos hablado. Hacer tus propios métodos y clases.

    +

    Ahem! Acabemos con ello de una vez.

    +

    Empieza con: def load_comics( path )

    +
    ..
    +
    +
    +

    En Ruby, Def Leppard Significa ¡Define Leppard (un Método)!

    +

    Hey, bueno, lo hiciste. Estas haciendo tu propio método. Comenzaste con def, seguido por el nombre del método. + Y una lista de argumentos que va a necesitar el método. ¡Esto no da tanto miedo ni es peligroso!

    +

    Todo lo que debemos hacer es rellenar con Ruby y terminarlo con end.

    +

    Aquí esta el código:

    +
    • def load_comics( path )
    • +
    •   comics = {}
    • +
    •   File.foreach(path) do |line|
    • +
    •     url, name = line.split(': ')
    • +
    •     comics[url] = name.strip
    • +
    •   end
    • +
    •   comics
    • +
    • end
    • +
    +

    No necesitas indentar, si no quieres. Lo hice solo para que sea más legible.

    +
    nil
    +
    +
    +

    La Madura Fruta de tu Propia Creación

    +

    Un nuevo método ha nacido. Vamos a usarlo: comics = load_comics('/comics.txt')

    +

    Si tienes un problema, puedes haberlo escrito mal. Usa el comando back y prueba otra vez.

    +
    \{.*"Achewood"=."http://achewood.com/".*\}
    +
    +
    +

    Hey, Cool, Una Cosa de Historietas

    +

    En tu ventana de Ruby arriba, mira el código que has escrito para el método load_comics. ¿Qué esta pasando? Tu estas + pasando en la variable path y estas recibiendo la variable comics. Ruby permite filtrar el hash comics + que es devuelto al final del método.

    +

    Una cantidad de métodos se usaron para realizar el trabajo. Fíjate si puedes hallarlos.

    +
    • File.foreach es el método que abre un archivo y manda cada línea al bloque. La variable line + dentro del bloque do...end va turnando con cada línea del archivo.
    • +
    • split es un método para strings, que rompe los string en colocándolo en un array. Un hacha es arrojada sobre las comas + y las líneas se cortan en dos, dándonos la url y el nombre, name, de las historietas.
    • +
    • strip remueve los espacios extra alrededor de name. Por si acaso.
    • +
    +

    Justo allí. Bravo. Tienes las historietas en un hash de Ruby. ¿Pero ahora qué? ¿Qué tan bueno es en verdad?

    +

    Hagamos una página de links. ¿Qué te parece? Vamos a necesitar una pequeña librería que hice para ti.

    +

    Escribe: require 'popup'

    +
    true
    +
    +
    +

    El Navegador de Títere

    +

    Excelente, has cargado la librería popup. Está guardada en un archivo en el directorio Libraries. Mira: Dir["/Libraries/*"]

    +

    La librería popup contiene un puñado de métodos que he escrito y te dejaran controlar ventanas emergentes aquí en Try Ruby.

    +

    Mira, prueba esto: Popup.goto "http://google.com/"

    +
    \033\[1;JSm.*popup_goto\(.*\)\033\[m.*
    +
    +
    +

    Haciendo Links e Hilando Redes

    +

    Nuestro propio adorable, pequeño popup para manipular. también puedes rellenarlo con tus cositas. Empecemos por algo pequeño:

    +
    • Popup.make {
    • +
    •   h1 "My Links"
    • +
    •   link "Go to Google", "http://google.com/"
    • +
    • }
    • +
    +

    El termino h1 (h-uno) significa encabezado de nivel uno. En HTML, es el encabezado más grande.

    +
    \033\[1;JSm.*popup_make\(.*h1.*a href.*\)\033\[m.*
    +
    +
    +

    Los Popups son tan fáciles, es una Locura

    +

    Se ve bien, lo hiciste perfecto, tal como se te pidió. Hagamos una lista entonces.

    +

    Aquí esta como haces una lista con la librería de popup:

    +
    • Popup.make do
    • +
    •   h1 "Things To Do"
    • +
    •   list do
    • +
    •     p "Try out Ruby"
    • +
    •     p "Ride a tiger"
    • +
    •     p "(down River Euphrates)"
    • +
    •   end
    • +
    • end
    • +
    +

    El método p es la manera corta para "párrafo".

    +
    \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*li.*\)\033\[m.*
    +
    +
    +

    Expandiendo las Historietas en la Tabla

    +

    Bien, esto esta yendo maravilloso. Esto es algo simple, pero mantén en mente que no sabias nada sobre Ruby hace quince minutos atrás!<

    +

    Ultimo paso. Vamos a juntar todo, ¿sabes? ¡Juntémoslo como esos juegos de + campanillas hermosas que tintinean en los pórticos bajo la hermosa luz del sol + en la playa!

    +

    Asegúrate de que las historietas están cargadas: comics = load_comics( '/comics.txt' )

    +

    Ahora, hagamos una lista de links para cada historieta:

    +
    • Popup.make do
    • +
    •   h1 "Comics on the Web"
    • +
    •   list do
    • +
    •     comics.each do |name, url|
    • +
    •       link name, url
    • +
    •     end
    • +
    •   end
    • +
    • end
    • +
    +

    Puedes clickear en los links y leer las historietas ¡inclusive en la ventana principal! ¡Bárbaro!

    +
    \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*a href.*li.*a href.*\)\033\[m.*
    +
    +
    +

    Sumario #6 lo que Significa que has Llegado Muy Lejos

    +

    Eres un clérigo nivel 6 de Ruby. Quiero decir que buen trabajo has hecho. Vamos a revisar:

    +
      +
    • Agregaste tu propio método con def y usaste ese método load_comics varias veces.
    • +
    • Librerias. Tú usaste el método require para cargar la librería popup.
      Escribiendo: require 'popup'
    • +
    • Y como si no fuera suficiente, hiciste tu propia página web para listar los archivos de historietas. ¡Hiciste un programa real!
    • +
    +

    Entonces ¿Qué podrá venir luego? ¿Qué deberías aprender posiblemente ahora? + Ja, esta es la mejor parte. Has recorrido un largo camino y ahora descubrirás + las clases. En dos lecciones mas y ya estarás hecho.

    +

    Tempranamente, creamos un hash como este: Hash.new pruébalo.

    +
    \{\}
    +
    +
    +

    No una Clase de Escuela, Una Clase Trabajadora

    +

    Ves, las llaves vacías {} son abreviaciones para Hash.new. El método new + es usado para hacer objetos de cierta clase. (Piensa "clase" como en "clase + trabajadora" — un grupo especifico de objetos similares, tienen el + mismo trabajo, la misma camisa.)

    +

    Pregúntate esto: ¿Cómo haría mi blog en Ruby? ¿Dónde deberías + comenzar? Bien, deberías guardar tus entradas del blog en un archivo, ¿cierto? + Pero ¿cómo seguirías los títulos de las entradas y el momento en que fue creado? + Y cuando cargas el archivo, ¿cómo se vería en Ruby? ¿Sería un Hash? ¿O un Array? ¿O + un Array de Arrys? ¿O alguna otra cosa?

    Yo realmente creo que querrás usar una clase. Ya estas familiarizado con varias clases: Hash, Array, String.

    +

    Hagamos una clase nueva: class BlogEntry.

    +
    ..
    +
    +
    +

    El Relleno del Blog esta Hecho de

    +

    Has abierto una nueva clase BlogEntry. ¿De que están hechas las entradas de tu blog? Un titulo, seguro. también, + la fecha en la que fue creada. El texto entero de la entrada.

    +

    Vamos a poner el estado de ánimo, también, tal como LiveJournal. La internet ha traído de vuelta las personas de palitos y emoticones + fuera de la bancarrota.¡Que emoción!

    +

    Bueno, ya tienes la primera línea de la clase, aquí esta el resto:/p> +

    • class BlogEntry
    • +
    •   attr_accessor :title, :time, :fulltext, :mood
    • +
    • end
    • +
    +
    nil
    +
    +
    +

    Accessors Son las Extremidades Colgantes

    +

    Hey, buena clase, colega. Tienes una nueva clase BlogEntry. Para comenzar una entrada:
    entry = BlogEntry.new.

    +

    En la definición de la clase, usaste un método llamado attr_accessor. Existen varios métodos attribute + atributo, como este que agregan pequeñas configuraciones a la clase. Estos atributos son simplemente variables adosadas a la clase.

    +

    Piénsalo de este modo. Una clase es como una persona. Esa forma de estrella + del humano. Y los atributos son las extremidades, las diferentes partes que + hacen un cuerpo.

    +

    Para crear el titulo de tu entrada: entry.title = "Today Mt. Hood Was Stolen!"

    +
    ".+"
    +
    +
    +

    Un Objeto, Ese Estupendo Paquete Pequeño

    +

    Sigue adelante y pon la hora: entry.time = Time.now

    +

    Y el estado de animo: entry.mood = :sick

    +

    Y el anuncio en si: entry.fulltext = "I can't believe Mt. Hood was stolen! I am speechless! It was stolen by a giraffe who drove away + in his Cadillac Seville very nonchalant!!"

    +

    Para ver toda la configuración, simplemente escribe en el prompt: entry.

    +
    #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
    +
    +
    +

    Agilizando

    +

    Genial, tu blog es impresionante. Hey, hagamos las cosas algo mas fácil. No querrás + poner la hora asi todas las veces que postees. Solo quieres escribir el titulo, + el contenido y el emoticon rápido, ¿verdad?

    +

    Vamos a agregar un método initialize.

    +
    • class BlogEntry
    • +
    •   def initialize( title, mood, fulltext )
    • +
    •     @time = Time.now
    • +
    •     @title, @mood, @fulltext = title, mood, fulltext
    • +
    •   end
    • +
    • end
    • +
    +

    Una vez que lo hallas escrito, prueba hacer una nueva entrada: BlogEntry.new

    +
    ArgumentError: wrong number of arguments \(0 for 3\).*
    +
    +
    +

    Tu le Has Enseñado al Blog a Rechazar lo Malo

    +

    ¿Viste como usamos dentro de la clase el símbolo arroba? De este modo: @time = Time.now

    +

    Fuera de la clase, usamos accesos (accessors): entry.time = Time.now Pero dentro variables de instancia: @time = Time.now + Son exactamente lo mismo, pero expresado en dos partes diferentes de tu programa.

    +

    tu blog ahora necesita un titulo, estado de ánimo y el post para funcionar. Cuando un nuevo BlogEntry es creado, el método initialize + es usado para chequear cualquier argumento para new. ¡Uh, necesitamos tres argumentos!

    +

    Prueba de nuevo con los tres.

    +

    entry2 += BlogEntry.new( "I Left my Hoodie on the Mountain!", :confused, "I am +never going back to that mountain and I hope a giraffe steals it." )

    +
    #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
    +
    +
    +

    Una Jirafa No Ha Robado el Sumario #7

    +

    Aha, estas aquí. Y todo en una pieza. Todavía vamos a hacer tu blog realidad, pero hasta entonces, vamos a revisar, ¿bien?

    +
      +
    • Clases. Todo en Ruby es algún tipo de objeto. Las clases explican los objetos. Como ciertos objetos + trabajan. Por ejemplo, haces algunas entradas de blog y estos objetos están explicados en la clase BlogEntry. + En otras palabras: los llamas objetos del tipo BlogEntry.
    • +
    • Accessors son variables adosadas a un objeto que pueden ser usadas fuera del objeto. (entry.time = Time.now)
    • +
    • Variables de instancia son las mismas variables para accesos dentro del objeto. + Como en la definición de un método. (@time = Time.now)
    • +
    +

    Bueno, vamos a envolver las cosas, niño. Aquí esta el ultimo capitulo de la FASCINANTE épica + historia de Try Ruby! Ahora que ya has probado como todo funciona, ¿cómo vas a + usar eso alrededor de la casa y en tu tienda de comestibles? Eres una + gran persona (una de mis favoritas), pero necesitas dirección.

    +

    Vamos a terminar tu blog. Tienes entradas de blog, pero no un blog.

    +

    Pon las entradas en un array: blog = [entry, entry2]

    +
    \[#.BlogEntry:0x[0-9a-f]+.*, #.BlogEntry:0x[0-9a-f]+.*\]
    +
    +
    +

    Todo Se Trata de Combinar Cosas

    +

    Cosas hermosas pueden hacerse de partes simples de Ruby, especialmente + cuando las combinas entre ellas para formar algo nuevo. Aquí tenemos un blog + hecho de un array de clases. Y, en realidad, Ruby realmente hace buenas cosas + con este tipo de criaturas.

    +

    Aquí hay un puñado de cosas que puedes hacer con tu blog array:

    +
    • Querrás ordenar tus entradas de mas reciente a viejas. Puedes hacerlo con:
      + blog.sort_by { |entry| entry.time }.reverse
      Ve sort_by para más explicación.
    • +
    • Si quieres buscar en el blog por cualquier cosa relacionada con "cadillac":
      + blog.find_all { |entry| entry.fulltext.match(/cadillac/i) }
      + Lee mas en find_all + y match + para descubrir como funciona. También: /giraffe/i es un objeto Regexp, usado para concordar palabras.
    • +
    • Y agregar nuevas entradas con blog << new_entry
      + Y aquí la documentación del método <<.
    • +
    +

    Puedes buscar entre la lista de los métodos con los que viene Ruby en ruby-doc.org's core. + Otra buena lista hay en online pickaxe.

    +

    Un método realmente útil (probablemente yo uso esto mas que otra cosa) es map. Escribe: blog.map { |entry| entry.mood }

    +
    \[(:\w+, )+:\w+\]
    +
    +
    +

    Mira Su Cara — La Transformación Ha Comenzado

    +

    El método map recorre un array y reemplaza cada ítem con algo nuevo. ¿Dices que quieres reemplazar cada entrada de tu blog + con el nombre de Bruce Willis?. Hazlo entonces: blog.map { "Bruce Willis" }

    +

    Como el bloque siempre devuelve el string "Bruce Willis", eso es lo que obtienes. En el código que acabas de usar, la entrada entry wfue reemplazada + por solo el entry.mood.

    +

    Ahora, quiero que hagas un popup con las entradas de tu blog. Yo no te voy a + dar todo el código. Solo te voy a dar una parte.

    +
    • blog.each do |entry|
    • +
    •   h2 entry.title
    • +
    •   p entry.fulltext
    • +
    • end
    • +
    +

    Ahora, yo espero que pongas el código del popup alrededor y agregues un titulo con el nombre de tu blog usando h1. Como extra, tienes la hora de cada entrada para mostrar.

    +
    \033\[1;JSm.*popup_make\(.*h1.*h2.*li.*h2.*li.*\)\033\[m.*
    +
    +
    +

    Eres Una Especie de Gurú Web, Tengo Estrellas en Mis Ojos

    +

    Bien, ¡eso es! Este es exactamente el código que puedes usar para escribir tu + propio blog real en Ruby. Si te sientes aventurero, yo chequearía el video de + Rails videos donde muestran a un joven compañero creando un blog en 15 minutos. Solo sientete cómodo y mira.

    +

    Debo mencionar a Rails. Tú has estado aprendiendo el lenguaje Ruby, como + hablarlo. Pero Rails es grupo de librerías (algo asi como la librería de popup + que hemos estado usando.) Es un poderoso conjunto de herramientas para crear + sitios web. Si estas interesado en aprender sobre Rails, yo miraría head + por aquí directamente. ¡Empieza a usar tus habilidades en Ruby apropiadamente!

    +

    Algo que tiene Rails son métodos para manejar fechas fácilmente. Como, prueba: Time.now - 2.weeks

    +
    class Integer; def weeks; self * 7*24*60*60; end; end
    +
    \w+ \w+ \d+ \d{2}:\d{2}:\d{2} .*
    +
    +
    +

    Si Quieres Empezar Poco a Poco

    +

    Si quieres comenzar escribiendo pequeños programas en Ruby para practicar, tengo un proyecto llamado MouseHole + que es una pequeña caja de herramientas en la web para escribir programas cortos en Ruby. Puedes ver aquí algunos + scripts para ver que quiero decir.

    +

    MouseHole no es para escribir sitios web en realidad. Es para escribir + pequeños programas y correrlos dentro del navegador. Como hay un programa block + de notas para MouseHole y un programa que agrega una imagen de un ratón a los + links de la web que linkean a programas de MouseHole.

    +

    Tengo un script de MouseHole dentro de un archivo aquí mismo:
    + print File.read("/MouseHole/flickrpedia.user.rb")

    +
    .*Inserts Wikipedia links for Flickr tags.*
    +
    +
    +

    Sumario #8, El Sumario Hey-Relájate-Lo-Hiciste-Bien

    +

    Esta ultima sección se tomó un momento para relajarse, para darte algunos consejos de como + puedes usar Ruby. Si lo has disfrutado, descarga Ruby e instálalo.

    + +

    Una vez que tengas Ruby instalado, puedes usar Ruby Interactivo ejecutando el comando irb en el prompt de tu sistema. Para mas sobre Irb, esta + The Tiger's Vest para ayudarte.

    +

    Tú realmente mereces una torta doble-capa con doble-doble azúcar glaseado y + un tipo tocando una de esas guitarras que son doble-guitarra. Quiero decir + terminaste, ¡lo hiciste! No hay dudas de eso, ¡eres un gran ser certificado!

    +
    +
    + \ No newline at end of file diff --git a/public/tutorials/intro.html b/public/tutorials/intro.html new file mode 100644 index 0000000..20e6ae5 --- /dev/null +++ b/public/tutorials/intro.html @@ -0,0 +1,680 @@ + +
    +

    Using the Prompt

    +

    The blue window above is a Ruby prompt. Type a line of Ruby code, hit Enter + and watch it run!

    +

    For example, try typing some math. Like: 2 + 6

    +
    \d+
    +
    +
    +

    Numbers & Math

    +

    Good! You did a bit of math. See how the answer popped out?

    +

    Ruby recognizes numbers and mathematic symbols. You could try some other math like:

    +
    • 4 * 10
    • +
    • 5 - 12
    • +
    • 40 / 4
    +

    Sure, computers are handy and fast for math. Let's move on. Want to see your name reversed? + Type your first name in quotes like this: "Jimmy"

    +
    "(\w+)"
    +
    +
    +

    Say Your Name Backwards

    +

    Perfect, you've formed a string from the letters of your name. A string + is a set of characters the computer can process.

    +

    Imagine the letters are on a string of + laundry line and the quotes are clothespins holding the ends. The quotes mark the beginning and end.

    +

    To reverse your name, type: "Jimmy".reverse (Don't forget the dot!)

    +
    "(\w+)"
    +
    +
    +

    Counting the Letters

    +

    You have used the reverse method on your name! By enclosing your name in + quotes, you made a string. Then you called the reverse method, which works on strings to flip + all the letters backwards.

    +

    Now, let's see how many letters are in your name: "Jimmy".length

    +
    \d+
    +
    +
    +

    On Repeat

    +

    Now, I'm sure by now you're wondering what any of this is good for. Well, I'm sure you've been to + a website that screamed, Hey, your password is too short! See, some programs + use this simple code.

    +

    Watch this. Let's multiply your name by 5. "Jimmy" * 5

    +
    "(\w+)"
    +
    +
    +

    Hey, Summary #1 Already

    +

    Let's look at what you've learned in the first minute.

    +
      +
    • The prompt. Typing code into the green prompt gives you + an answer from a red prompt. All code gives an answer.
    • +
    • Numbers and strings are Ruby's math and text objects.
    • +
    • Methods. You've used English-language methods like reverse + and symbolic methods like * (the multiplication method.) Methods are action!
    • +
    +

    This is the essence of your learning. Taking simple things, toying with + them and turning them into new things. Feeling comfortable yet? I promise you are.

    +

    Okay, let's do something uncomfortable. Try reversing a number: 40.reverse

    +
    NoMethodError: undefined method `reverse' for (\d+):Fixnum
    +
    +
    +

    Stop, You're Barking Mad!

    +

    You can't reverse the number forty. I guess you can hold your monitor up to the + mirror, but reversing a number just doesn't make sense. Ruby has tossed an error + message. Ruby is telling you there is no method reverse for numbers.

    +

    Maybe if you turn it into a string: 40.to_s.reverse.

    +
    \"(\d+)\"
    +
    +
    +

    Boys are Different From Girls

    +

    And numbers are different from strings. While you can use methods on any object + in Ruby, some methods only work on certain types of things. But you can always + convert between different types using Ruby's "to" methods.

    +
    • to_s converts things to strings.
    • +
    • to_i converts things to integers (numbers.)
    • +
    • to_a converts things to arrays.
    • +
    +

    What are arrays?! They are lists. Type in a pair of brackets: [].

    +
    \[\]
    +
    +
    +

    Standing in Line

    +

    Great, that's an empty list. Lists store things in order. + Like standing in line for popcorn. You are behind someone and you wouldn't + dream of pushing them aside, right? And the guy behind you, you've got a + close eye on him, right?

    +

    Here's a list for you. Lottery numbers: [12, 47, 35].

    +
    \[(\d+(, )?){2,}\]
    +
    +
    +

    One Raises Its Hand

    +

    A list of lottery numbers. Which one is the highest?

    +

    Try: [12, 47, 35].max.

    +
    (\d+)
    +
    +
    +

    Tucking a List Away

    +

    Good, good. But it's annoying to have to retype that list, isn't it?

    +

    Let's save our numbers inside a ticket like so: ticket = [12, 47, 35]

    +
    \[(\d+(, )?){2,}\]
    +
    +
    +

    Now Type Ticket

    +

    Now, type: ticket

    +
    \[(\d+(, )?){2,}\]
    +
    +
    +

    Saved, Tucked Away

    +

    Fantastic! You've hung on to your lotto numbers, tucking them away inside a + variable called ticket.

    +

    Let's put your lotto numbers in order, how about? Use: ticket.sort!

    +
    \[(\d+(, )?){2,}\]
    +
    +
    +

    Summary #2 is Upon Us

    +

    You had a list. You sorted the list. The ticket variable is now changed.

    +

    Did you notice that the sort! method has a big, bright exclamation at the end? + A lot of times Ruby methods shout like that if they alter the variable for good. It's nothin + special, just a mark.

    +

    Now, look how your second minute went:

    +
      +
    • Errors. If you try to reverse a number or do anything fishy, + Ruby will skip the prompt and tell you so.
    • +
    • Arrays are lists for storing things in order.
    • +
    • Variables save a thing and give it a name. You used the + equals sign to do this.
      Like: ticket = [14, 37, 18].
    • +
    +

    In all there are eight lessons. You are two-eighths of the way there! + This is simple stuff, don't you think? Good stuff up ahead.

    +

    Let's change directions for a moment. I've stuffed a bit of poetry for you in + a certain variable. Take a look. Type print poem

    +
    poem = "My toast has flown from my hand\nAnd my toast has gone to the +moon.\nBut when I saw it on television,\nPlanting our flag on Halley's +comet,\nMore still did I want to eat it.\n"
    +
    My toast (.+)
    +
    +
    +

    Sadly, You Hate Toast Poetry

    +

    Look, it's okay. You don't have to like it. Hack it up, be my guest.

    +

    Instead of toast, go for a melon or something. Try this: poem['toast'] = 'honeydew'

    +

    And then type print poem by itself to see the new poem.

    +
    My honey(.+)
    +
    +
    +

    Ready, Aim

    +

    The square brackets you just used are very common in Ruby. Remember, you typed: poem['toast'] = 'honeydew'. That box with the word toast has a square bracket on each side, see?

    +

    The +two brackets are like sights used to line up a target. Exactly. These +brackets mean, "I am looking for ____." Ready, aim. Here you're looking +for toast and swapping it out with fruit.

    +

    Here's a question: what happens when we reverse this whole poem? poem.reverse +

    "\\n.ti tae ot (.+)"
    +
    +
    +

    Too Much Reversal

    +

    Okay, sure. So the whole poem's been turned backwards, letter-by-letter. I really want to just + reverse the lines, though. Move the last line up to first and the first line down to last. Backwards, but not + that backwards.

    +

    Here's how: poem.lines.to_a.reverse

    +
    \["More still did I(.+)"\]
    +
    +
    +

    Ringlets of Chained Methods

    +

    So what do you see? What happened there? You typed poem.lines.to_a.reverse and what happened?

    +

    Two things happened. You turned the poem into a +list using lines.to_a. lines decides the way +the string is split up, then to_a converted it into an +Array. (To array.) Different methods, such +as bytes and chars can be used in place +of lines. By using lines, ruby will return each line of the poem.

    +

    Then, you reversed that list. You had each line. You reversed them. That's it.

    +

    Let's tack one more method on the end there: print poem.lines.to_a.reverse.join +

    More still did I(.+)
    +
    +
    +

    Of All the Summaries, #3 is Here Now

    +

    Good show, my friend! The join method took that list of reversed lines and put them + together into a string. (Sure, you could have also just used to_s.)

    +

    Review time.

    +
      +
    • Exclamations. Methods may have exclamations (and also question marks) + in their name. No big deal. Try: poem.include? "my hand"
    • +
    • Square brackets. Target and find things. Search and replace.
    • +
    • Chaining methods lets you get a lot more done. Break up a poem, + reverse it, reassemble it: poem.lines.to_a.reverse.join
    • +
    +

    At this point, you may want to tinker with the poem a bit more. A complete list of all + the String methods is + + here. + Go ahead and try a few (such as poem.downcase or poem.delete.)

    +

    When you're ready to move on, type: books = {}

    +
    \{\}
    +
    +
    +

    A Wee Blank Book

    +

    You've made an empty hash. (Also known as: an empty dictionary.)

    +

    We're going to stuff some miniature book reviews in this hash. Here's our rating system:

    +
      +
    • :splendid → a masterpiece.
    • +
    • :quite_good → enjoyed, sure, yes.
    • +
    • :mediocre → equal parts great and terrible.
    • +
    • :quite_not_good → notably bad.
    • +
    • :abyssmal → steaming wreck.
    • +
    +

    To rate a book, put the title in square brackets and put the rating after the equals.

    +

    For example: books["Gravity's Rainbow"] = :splendid

    +
    :\w+
    +
    +
    +

    More Bite-Size Reviews

    +

    Keep going, fill it up with reviews. And, if you want to see the whole list, + just type: books

    +

    Again, the ratings are: :splendid, :quite_good, :mediocre, + :quite_not_good, and :abyssmal.

    +

    These ratings are not strings. When you place a colon in front of a simple word, you get a + symbol. Symbols are cheaper than strings (in terms of computer memory.) If + you use a word over and over in your program, use a symbol. Rather than having thousands of + copies of that word in memory, the computer will store the symbol only once.

    +

    Once you've got three or four books in + there, type: books.length.

    +
    [3-9]
    +
    +
    +

    Wait, Did I Like Gravity's Rainbow?

    +

    See, the length method works on strings, list and hashes. One great thing about + Ruby is that names are often reused, which means fewer names you need to remember.

    +

    If you'd like to look up one of your old reviews, again put the title in the square. But leave off + the equals.

    +

    Just like this: books["Gravity's Rainbow"]

    +
    :\w+
    +
    +
    +

    Hashes as Pairs

    +

    Keep in mind that hashes won't keep things in order. That's not their job. It'll just pair up two + things: a key and a value. In your reviews, the key is the book's + title and the value is the rating.

    +

    If you want to just see the titles of the books you've reviewed: books.keys

    +
    \[".*"\]
    +
    +
    +

    Are You Harsh?

    +

    So are you giving out harsh, unfair reviews? Let's keep score with this hash:
    ratings = Hash.new {0}

    +

    Then, okay, now let's count up your reviews. Just stay with me. Type:
    + books.values.each { |rate| ratings[rate] += 1 }

    +

    (The straight line in the code is the pipe character, probably located right above the + Enter key on your keyboard.)

    +
    \[:.+\]
    +
    +
    +

    A Tally

    +

    Great, wow! You've made a scorecard of your ratings. Type ratings to see the count. + This new hash shows a rating and then the number of times you've given that rating.

    +

    One of the amazing new things we've just used is a block. We're going to + explore these more in the next summary. But, basically, a block is a bit of Ruby code surrounded + by curly braces.

    +

    Let's try another block: 5.times { print "Odelay!" }

    +
    Odelay!Od.*
    +
    +
    +

    Now Arriving at Summary #4

    +

    Blocks are always attached to methods. Like the times method, which takes the + block and runs the code over and over. (In this case: five times.)

    +

    This last lesson was a bit longer. You've probably used up three minutes learning about:

    +
      +
    • Hashes. The little dictionary with the curly pages: {}.
    • +
    • Symbols. Tiny, efficient code words with a colon: :splendid.
    • +
    • Blocks. Chunks of code which can be tacked on to many of Ruby's methods. Here's the + code you used to build a scorecard:
      books.values.each { |rate| ratings[rate] += 1 }.
    • +
    +

    On your computer, you probably have a lot of different files. Files with pictures in them, + files with programs in them. And files are often organized into folders, also called: + directories.

    +

    I've prepared a few directories for you. Take a look: + Dir.entries "/"

    +
    \["\.", .+\]
    +
    +
    +

    The Private Collection of Dr. Dir

    +

    You've just listed out everything in the top directory. The root directory, indicated + by a single slash. Containing some programs and other tutorials and such.

    +

    So, what is the Dir.entries method? Well, it's just a method, right? + entries is a method called on the Dir variable. + And Dir has a collection of methods for checking out file directories.

    +

    One other little thing we haven't really talked about openly. Method arguments, highlighted in green.

    +
      +
    • Dir.entries "/": Anything listed after a method + is considered an attachment.
    • +
    • print poem: See, print is an ordinary method. And the + poem is attached. To be printed.
    • +
    • print "pre", "event", "ual", "ism" has several arguments, with commas + between them.
    • +
    +

    To list just the text files in that directory: Dir["/*.txt"]

    +
    \["\/comics\.txt"\]
    +
    +
    +

    Come, Read Comics With Me

    +

    The Dir[] method is like entries but you search for files + with wildcard characters. Here, we see those square brackets again! Notice how + they still mean, "I am looking for _____?"

    +

    More specifically: "I am looking for files which end with .txt."

    +

    Let's crack open this comics file, then. Here's the way:
    + print File.read("/comics.txt")

    +
    Achewood.+
    +
    +
    +

    Mi Comicas, Tu Comicas

    +

    All right! We can start to use files to store things. This is great because normally when + we exit Ruby, all our variables will be gone. Ruby, by itself, forgets these things. + But if we save things in files, we can read those files in future Ruby escapades.

    +

    Hey, and guess what? The /Home directory is yours! I gave it to you! I am generous! Let's make a copy of the comics file.

    +

    You'll want to: FileUtils.copy('/comics.txt', '/Home/comics.txt') +

    If you've already created the file, use File.delete('/Home/comics.txt') to trash it.

    +
    nil
    +
    +
    +

    Your Own Turf

    +

    Okay, you've got a copy. Check it: Dir["/Home/*.txt"]

    +

    To add your own comic to the list, let's open the file in append mode.

    +

    Start like this: File.open("/Home/comics.txt", "a") do |f|.

    +
    ..
    +
    +
    +

    And Now For the Startling Conclusion

    +

    So your prompt has changed. See that? Your prompt is a double dot now.

    +

    In this tutorial, this prompt means that Ruby is expecting you to type more. + As you type in the lines of Ruby code, the double dots will continue until you + are completely finished.

    +

    Hot tip: If you want to stop working on the code and break out of the double dots, use the reset + command. If you want to go the previous page of the tutorial, use the back command.

    +

    Here's your code. You've already typed the first line, so just enter the second line. (The \n + is an Enter character.

    +
    • File.open("/Home/comics.txt", "a") do |f|
    • +
    •   f << "Cat and Girl: http://catandgirl.com/\n"
    • +
    • end
    • +
    +

    And, since you're getting so advanced and capable here, one other tip: you can use the up and down arrow keys to + edit your old commands or run them again.

    +
    ..
    +
    +
    +

    Ruby Sits Still

    +

    That last line adds the Cat and Girl comic to the list, but Ruby's going to wait until you're totally finished to + take action.

    +

    Now, to finish the code you've started. You opened a new block when you typed do. + So far the blocks we've seen have used curly braces. This time we'll be using do and end instead + of curly braces. A lot of Rubyists will use do...end when the block goes on for many lines.

    +

    Let's get that block finished now, with: end

    +
    • File.open("/Home/comics.txt", "a") do |f|
    • +
    •   f << "Cat and Girl: http://catandgirl.com/\n"
    • +
    • end
    • +
    +
    #.File:/Home/comics\.txt \(closed\).
    +
    +
    +

    The Clock Nailed To the File

    +

    Good, good! You've added that new comic to the file. You can see for yourself: print File.read("/Home/comics.txt")

    +

    What time was it when you changed the file? Let's check. Type: File.mtime("/Home/comics.txt")

    +
    \d{4}-\d+-\d+ \d{2}:\d{2}:\d{2} [+-]\d{4}
    +
    +
    +

    Just the Hour Hand

    +

    Great, there's the time. The precise time exactly when you added to the file. The mtime gives you a Ruby Time object.

    +

    If you want to check just what hour it was, hit the up arrow key and change the line to: File.mtime("/Home/comics.txt").hour

    +
    \d+
    +
    +
    +

    Hallo, Who's There? And Summary #5 Waves Its Hat!

    +

    Well done, well done, well done, well done! Truly, truly, truly, truly, truuuuuuuuly!

    +

    Here's the last few minutes of your life in review:

    +
      +
    • Files. What more can be said? Lots of methods for editing files and lookin around in directories.
    • +
    • Arguments. Arguments are a list of things sent into a method. With commas between.
    • +
    • We also spoke about do and end which are another way to make a block.
    • +
    +

    You totally know how to use Ruby now. I mean you've got down the essentials. You just need to keep learning more methods and + try out more complex blocks.

    +

    But there's one side of Ruby we haven't settled. Making your own methods and classes.

    +

    Ahem! Let's get it over with then.

    +

    Start with: def load_comics( path )

    +
    ..
    +
    +
    +

    In Ruby, Def Leppard Means Define Leppard (a Method)!

    +

    Hey, okay, you done it. You're making your own method. You started with def, followed by the name of the method. + And a list of arguments which the method will need. This isn't too scary and dangerous!

    +

    All we have to do is fill it up with Ruby and finish it up with end.

    +

    Here's the code:

    +
    • def load_comics( path )
    • +
    •   comics = {}
    • +
    •   File.foreach(path) do |line|
    • +
    •     name, url = line.split(': ')
    • +
    •     comics[name] = url.strip
    • +
    •   end
    • +
    •   comics
    • +
    • end
    • +
    +

    No need to indent, if you don't want. I just do that to make it read easier.

    +
    nil
    +
    +
    +

    The Ripened Fruit of Your Own Creation

    +

    A new method is born. Let us use it: comics = load_comics('/comics.txt')

    +

    If you have a problem, you might have mistyped. Use the back command and try again.

    +
    \{.*"Achewood"=."http://achewood.com/".*\}
    +
    +
    +

    Hey, Cool, a Comics Thing

    +

    In your Ruby window above, look at the code you've typed for the load_comics method. What is happening? You're + passing in the path variable and you're getting back the comics variable. Ruby lets the comics + hash trickle out the end of the method.

    +

    A number of methods were used to get the job done. See if you can spot them.

    +
    • File.foreach is a method which opens a file and hands each line to the block. The line + variable inside the do...end block took turns with each line in the file.
    • +
    • split is a method for strings, which breaks the string up into an array. An axe is laid on the colon + and the line is chopped in half, giving us the url and name for each comic.
    • +
    • strip removes extra spaces around the name. Just in case.
    • +
    +

    Right on. Bravo. You've got the comics in a Ruby hash. But what now? What good is this really?

    +

    Let's make a page of links. How about that? We'll need to load a little library I've made for you.

    +

    Type: require 'popup'

    +
    true
    +
    +
    +

    Browser Puppetry

    +

    Excellent, you've loaded the popup library. It's saved in a file in the Libraries folder. See: Dir["/Libraries/*"]

    +

    The popup library contains a bunch of methods I've written which let you control a popup here on the Try Ruby site.

    +

    Here, try this: Popup.goto "http://google.com/"

    +
    \033\[1;JSm.*popup_goto\(.*\)\033\[m.*
    +
    +
    +

    Making Links and Spinning Webs

    +

    Our own lovely, little popup to manipulate. You can also fill it with your own goodies. We'll start small:

    +
    • Popup.make {
    • +
    •   h1 "My Links"
    • +
    •   link "Go to Google", "http://google.com/"
    • +
    • }
    • +
    +

    The term h1 (h-one) means a level-one header. In HTML, this is the largest size of header.

    +
    \033\[1;JSm.*popup_make\(.*h1.*a href.*\)\033\[m.*
    +
    +
    +

    Popups Are So Easy, It's Crazy

    +

    Looks good, you did it perfectly, just as you were asked. Let's make a list then.

    +

    Here's how you make a list with the popup library:

    +
    • Popup.make do
    • +
    •   h1 "Things To Do"
    • +
    •   list do
    • +
    •     p "Try out Ruby"
    • +
    •     p "Ride a tiger"
    • +
    •     p "(down River Euphrates)"
    • +
    •   end
    • +
    • end
    • +
    +

    The p method is short for "paragraph".

    +
    \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*li.*\)\033\[m.*
    +
    +
    +

    Spread the Comics on the Table

    +

    Okay, this is coming along wonderfully. This is simple stuff, but keep in mind that you didn't know any Ruby whatsoever just fifteen minutes ago!

    +

    Last +step. Let's tie it all together, you know? Let's make it chime together +like a very nice set of glistening chimes on the beach in the +maginificent sunlight!

    +

    Make sure the comics are loaded: comics = load_comics( '/comics.txt' )

    +

    Now, let's make a list of the links to each comic:

    +
    • Popup.make do
    • +
    •   h1 "Comics on the Web"
    • +
    •   list do
    • +
    •     comics.each do |name, url|
    • +
    •       link name, url
    • +
    •     end
    • +
    •   end
    • +
    • end
    • +
    +

    You can click on the links and read the comics in the little window even! Smashing!

    +
    \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*a href.*li.*a href.*\)\033\[m.*
    +
    +
    +

    Summary #6 Which Means You've Come So Far

    +

    You're a level six Ruby cleric. I mean what a great job you've done. Let's review:

    +
      +
    • You added your own method with def and you used that load_comics method several times.
    • +
    • Libraries. You used the require method to load the popup library.
      By typing: require 'popup'
    • +
    • And if that wasn't enough, you made your own web page from a list of comics in a file. You made a real program!
    • +
    +

    So +what could possibly be next? What could you possibly have to learn now? +Ha, this is the best part. You've come such a long way that we're going +to uncover classes. For two more short lessons and you're done.

    +

    Earlier, we created a hash like this: Hash.new Try it.

    +
    \{\}
    +
    +
    +

    Not a School Class, a Working Class

    +

    You see, the empty curly braces {} is a shortcut for Hash.new. The new +method is used to make objects of a certain class. (Think "class" as in +"working class" — a specific group of objects which are similar, have +the same jobs, the same shirts.)

    +

    Ask yourself this: How would I make a blog in Ruby? +Where would you start? Well, you might store your blog entries in a +file, right? But how would you keep track of the title of the entry and +the time it was posted? And when you loaded the file, how would it look +in Ruby? Would it be a Hash? Or an Array? Or an Array of Arrays? Or +something else?

    I really think you'll want to use a class. You are already familiar with many classes: Hash, Array, String.

    +

    Let's make a new class: class BlogEntry.

    +
    ..
    +
    +
    +

    The Stuff Blogs are Made of

    +

    You've opened up a new BlogEntry class. What is your blog entry made of? A title, sure. Also, a time when the entry was posted. The + full text of the entry.

    +

    We'll do a mood setting, too, just like LiveJournal. The Internet has really brought back stick people and smileys + out of bankruptcy. Emote!

    +

    Okay, so you've got the first line of the class, here's the rest:

    +
    • class BlogEntry
    • +
    •   attr_accessor :title, :time, :fulltext, :mood
    • +
    • end
    • +
    +
    nil
    +
    +
    +

    Accessors Are the Dangling Limbs

    +

    Hey, good class, man. You've got a new BlogEntry class. To start an entry:
    entry = BlogEntry.new.

    +

    In the class definition, you used a method called attr_accessor. There are many attribute methods like + this which add little settings to classes. These attributes are just variables attached to a class.

    +

    Think +of it this way. A class is like a person. That star-shaped human thing +out there. And the attributes are the dangling limbs, the different +parts that make up a body.

    +

    To set the title of your entry: entry.title = "Today Mt. Hood Was Stolen!"

    +
    ".+"
    +
    +
    +

    An Object, That Neat Little Package

    +

    Go ahead and set the post time: entry.time = Time.now

    +

    And the mood: entry.mood = :sick

    +

    And the post itself: entry.fulltext = "I can't believe Mt. Hood was stolen! I am speechless! It was stolen by a giraffe who drove away + in his Cadillac Seville very nonchalant!!"

    +

    To see all your settings, just type at the prompt: entry.

    +
    #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
    +
    +
    +

    Quickening it Up

    +

    Cool, +you're blog is awesome. Hey, let's make things a bit easier on you. +You're not going to want to set the time like that every time you post. +You just want to type in the title and the entry and the mood quickly, +right?

    +

    Let's add an initialize method.

    +
    • class BlogEntry
    • +
    •   def initialize( title, mood, fulltext )
    • +
    •     @time = Time.now
    • +
    •     @title, @mood, @fulltext = title, mood, fulltext
    • +
    •   end
    • +
    • end
    • +
    +

    Once you've got that typed in, try making a new entry: BlogEntry.new

    +
    ArgumentError: wrong number of arguments \(0 for 3\).*
    +
    +
    +

    You've Taught Your Blog to Reject Worthless Things

    +

    Did you see how inside the class we used the at-symbols? Like this: @time = Time.now

    +

    Outside the class, we use accessors: entry.time = Time.now But inside we use instance variables: @time = Time.now + They're the exact same thing, but expressed in two different places of your program.

    +

    Your blog now needs a title, a mood and a post in order to work. When a new BlogEntry is created, the initialize method + is used to check for any arguments to new. Uh, we need three arguments!

    +

    Try it again with all three.

    +

    entry2 += BlogEntry.new( "I Left my Hoodie on the Mountain!", :confused, "I am +never going back to that mountain and I hope a giraffe steals it." )

    +
    #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
    +
    +
    +

    A Giraffe Has Not Stolen Summary #7

    +

    Aha, you're here. And all in one piece. We're still going to make your blog real, but until then, let's review, okay?

    +
      +
    • Classes. Everything in Ruby is some kind of object. Classes explain objects. How a certain object works. + For example, you made a few blog entry objects and these objects are explained in the BlogEntry class. + In other words: you call them BlogEntry objects.
    • +
    • Accessors are variables attached to an object which can be used outside the object. (entry.time = Time.now)
    • +
    • Instance variables are the same variables you're using for accessors when inside the object. + Like in a method definition. (@time = Time.now)
    • +
    +

    Okay, +let's wrap things up, kid. Here's the last chapter of the GRIPPING epic +story of Try Ruby! Now that you've got a taste of how it all works, how +are you going to use it around the house and in your grocer's freezer? +You're a great person (one of my favorites), but you need guidance.

    +

    Let's finish your blog. You have blog entries, but no actual blog.

    +

    Put the entries into an array: blog = [entry, entry2]

    +
    \[#.BlogEntry:0x[0-9a-f]+.*, #.BlogEntry:0x[0-9a-f]+.*\]
    +
    +
    +

    It's All About Combining Things

    +

    Some +beautiful things can be done with the simple parts of Ruby, especially +when you combine them together into new things. Here we've got a blog +made of an array of classes. And, actually, Ruby really does good with +this kind of creature.

    +

    Here's a few things you can do with your array blog:

    +
    • You'll want to sort your entries from newest to oldest. You can do this with:
      + blog.sort_by { |entry| entry.time }.reverse
      See the sort_by explanation for more.
    • +
    • If you want to search your blog for anything related to "cadillac":
      + blog.find_all { |entry| entry.fulltext.match(/cadillac/i) }
      + Read all about find_all + and match + to figure out how that works. Also: the slashy /giraffe/i is a Regexp object, used for matching words.
    • +
    • Add new entries with blog << new_entry
      + And check out the << method documentation.
    • +
    +

    You can browse a list of all Ruby's built-in methods at ruby-doc.org's core list. + Another good list is at the online pickaxe.

    +

    One really useful method (I probably use this more than anything else) is map. Type: blog.map { |entry| entry.mood }

    +
    \[(:\w+, )+:\w+\]
    +
    +
    +

    Look at His Face — The Transformation Has Begun

    +

    The map method cycles through an array and replaces each item with something new. Say you wanted to replace each of your blog entries + with the name Bruce Willis. Do it so: blog.map { "Bruce Willis" }

    +

    Since the block always returns the string "Bruce Willis", that's what you get. In the code you just used, the entry was swapped out + for only the entry.mood.

    +

    Now, +I want you to make a popup with your blog entries. I'm not going to +give you all of the code. I'm just going to give you part of it.

    +
    • blog.each do |entry|
    • +
    •   h2 entry.title
    • +
    •   p entry.fulltext
    • +
    • end
    • +
    +

    Now, I expect you to put the popup code around it and add an h1 title with the name of your blog. For extra haroompf, have the time of each entry display.

    +
    \033\[1;JSm.*popup_make\(.*h1.*h2.*li.*h2.*li.*\)\033\[m.*
    +
    +
    +

    You are Some Kind of Web Guru, I Have Stars in My Eyes

    +

    Good, +that's it! This is exactly the code you can use to write your own real +Ruby blog. If you're feeling adventurous, I'd check out the Rails videos which show a swift young fellow creating a blog in 15 minutes. You just sit back and watch.

    +

    I +should mention Rails. You have been learning the Ruby language, how to +speak it. But Rails is a bunch of libraries (sort of like the popup +library we've been using.) It's a very powerful toolkit for building +websites. If you're interested in learning about Rails, I would head + over there right away. Start using your Ruby skills proper!

    +

    One thing Rails has is easy methods for dates. Like, try: Time.now - 2.weeks

    +
    class Integer; def weeks; self * 7*24*60*60; end; end
    +
    \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-+]\d{4}
    +
    +
    +

    If You Want to Start Small

    +

    If you'd like to start writing little Ruby programs just to practice, I have a project called MouseHole + which is a little web toolkit for writing short Ruby programs. You can look over a few + scripts to see what I mean.

    +

    MouseHole +isn't for writing web sites really. It's just for writing little +programs you run inside your browser. Like there's a notepad program +for MouseHole and a program which adds a mouse picture next to links on +the web which link to MouseHole programs.

    +

    I've got a MouseHole script inside a file here:
    + print File.read("/MouseHole/flickrpedia.user.rb")

    +
    .*Inserts Wikipedia links for Flickr tags.*
    +
    +
    +

    Summary #8, The Hey-Relax-You-Did-Good Summary

    +

    This last section took a moment to wind down, to give you some pointers as to how you can use Ruby. If you enjoyed yourself, + download Ruby and install it.

    + +

    Once you have Ruby installed, you can use Interactive Ruby by running irb on your system's prompt. For more on Irb, + there's The Tiger's Vest to help you.

    +

    You +really deserve a double-layer cake with double-double frosting and a +guy playing one of those guitars that's a double guitar. I mean you +finished, you really did! No doubt about it, you're a certified +red-blooded smartiac!

    +
    +
    + + diff --git a/public/tutorials/intro.html.broken b/public/tutorials/intro.html.broken new file mode 100755 index 0000000..5a6c27c --- /dev/null +++ b/public/tutorials/intro.html.broken @@ -0,0 +1,638 @@ + +
    +

    Using the Prompt

    +

    The blue window above is a Ruby prompt. Type a line of Ruby code, hit Enter + and watch it run!

    +

    For example, try typing some math. Like: 2 + 6

    +
    \d+
    +
    +
    +

    Numbers & Math

    +

    Good! You did a bit of math. See how the answer popped out?

    +

    Ruby recognizes numbers and mathematic symbols. You could try some other math like:

    +
    • 4 * 10
    • +
    • 5 - 12
    • +
    • 40 / 4
    +

    Sure, computers are handy and fast for math. Let's move on. Want to see your name reversed? + Type your first name in quotes like this: "Jimmy"

    +
    "(\w+)"
    +
    +
    +

    Say Your Name Backwards

    +

    Perfect, you've formed a string from the letters of your name. A string + is a set of characters the computer can process.

    +

    Imagine the letters are on a string of + laundry line and the quotes are clothespins holding the ends. The quotes mark the beginning and end.

    +

    To reverse your name, type: "Jimmy".reverse (Don't forget the dot!)

    +
    "(\w+)"
    +
    +
    +

    Counting the Letters

    +

    You have used the reverse method on your name! By enclosing your name in + quotes, you made a string. Then you called the reverse method, which works on strings to flip + all the letters backwards.

    +

    Now, let's see how many letters are in your name: "Jimmy".length

    +
    \d+
    +
    +
    +

    On Repeat

    +

    Now, I'm sure by now you're wondering what any of this is good for. Well, I'm sure you've been to + a website that screamed, Hey, your password is too short! See, some programs + use this simple code.

    +

    Watch this. Let's multiply your name by 5. "Jimmy" * 5

    +
    "(\w+)"
    +
    +
    +

    Hey, Summary #1 Already

    +

    Let's look at what you've learned in the first minute.

    +
      +
    • The prompt. Typing code into the green prompt gives you + an answer from a red prompt. All code gives an answer.
    • +
    • Numbers and strings are Ruby's math and text objects.
    • +
    • Methods. You've used English-language methods like reverse + and symbolic methods like * (the multiplication method.) Methods are action!
    • +
    +

    This is the essence of your learning. Taking simple things, toying with + them and turning them into new things. Feeling comfortable yet? I promise you are.

    +

    Okay, let's do something uncomfortable. Try reversing a number: 40.reverse

    +
    NoMethodError: undefined method `reverse' for (\d+):Fixnum
    +
    +
    +

    Stop, You're Barking Mad!

    +

    You can't reverse the number forty. I guess you can hold your monitor up to the + mirror, but reversing a number just doesn't make sense. Ruby has tossed an error + message. Ruby is telling you there is no method reverse for numbers.

    +

    Maybe if you turn it into a string: 40.to_s.reverse.

    +
    \"(\d+)\"
    +
    +
    +

    Boys are Different From Girls

    +

    And numbers are different from strings. While you can use methods on any object + in Ruby, some methods only work on certain types of things. But you can always + convert between different types using Ruby's "to" methods.

    +
    • to_s converts things to strings.
    • +
    • to_i converts things to integers (numbers.)
    • +
    • to_a converts things to arrays.
    • +
    +

    What are arrays?! They are lists. Type in a pair of brackets: [].

    +
    \[\]
    +
    +
    +

    Standing in Line

    +

    Great, that's an empty list. Lists store things in order. + Like standing in line for popcorn. You are behind someone and you wouldn't + dream of pushing them aside, right? And the guy behind you, you've got a + close eye on him, right?

    +

    Here's a list for you. Lottery numbers: [12, 47, 35].

    +
    \[(\d+(, )?){2,}\]
    +
    +
    +

    One Raises Its Hand

    +

    A list of lottery numbers. Which one is the highest?

    +

    Try: [12, 47, 35].max.

    +
    (\d+)
    +
    +
    +

    Tucking a List Away

    +

    Good, good. But it's annoying to have to retype that list, isn't it?

    +

    Let's save our numbers inside a ticket like so: ticket = [12, 47, 35]

    +
    \[(\d+(, )?){2,}\]
    +
    +
    +

    Now Type Ticket

    +

    Now, type: ticket

    +
    \[(\d+(, )?){2,}\]
    +
    +
    +

    Saved, Tucked Away

    +

    Fantastic! You've hung on to your lotto numbers, tucking them away inside a + variable called ticket.

    +

    Let's put your lotto numbers in order, how about? Use: ticket.sort!

    +
    \[(\d+(, )?){2,}\]
    +
    +
    +

    Summary #2 is Upon Us

    +

    You had a list. You sorted the list. The ticket variable is now changed.

    +

    Did you notice that the sort! method has a big, bright exclamation at the end? + A lot of times Ruby methods shout like that if they alter the variable for good. It's nothin + special, just a mark.

    +

    Now, look how your second minute went:

    +
      +
    • Errors. If you try to reverse a number or do anything fishy, + Ruby will skip the prompt and tell you so.
    • +
    • Arrays are lists for storing things in order.
    • +
    • Variables save a thing and give it a name. You used the + equals sign to do this.
      Like: ticket = [14, 37, 18].
    • +
    +

    In all there are eight lessons. You are two-eighths of the way there! + This is simple stuff, don't you think? Good stuff up ahead.

    +

    Let's change directions for a moment. I've stuffed a bit of poetry for you in + a certain variable. Take a look. Type print poem

    +
    poem = "My toast has flown from my hand\nAnd my toast has gone to the +moon.\nBut when I saw it on television,\nPlanting our flag on Halley's +comet,\nMore still did I want to eat it.\n"
    +
    My toast (.+)
    +
    +
    +

    Sadly, You Hate Toast Poetry

    +

    Look, it's okay. You don't have to like it. Hack it up, be my guest.

    +

    Instead of toast, go for a melon or something. Try this: poem['toast'] = 'honeydew'

    +

    And then type print poem by itself to see the new poem.

    +
    My honey(.+)
    +
    +
    +

    Ready, Aim

    +

    The square brackets you just used are very common in Ruby. Remember, you typed: poem['toast'] = 'honeydew'. That box with the word toast has a square bracket on each side, see?

    +

    The +two brackets are like sights used to line up a target. Exactly. These +brackets mean, "I am looking for ____." Ready, aim. Here you're looking +for toast and swapping it out with fruit.

    +

    Here's a question: what happens when we reverse this whole poem? poem.reverse +

    "\\n.ti tae ot (.+)"
    +
    +
    +

    Too Much Reversal

    +

    Okay, sure. So the whole poem's been turned backwards, letter-by-letter. I really want to just + reverse the lines, though. Move the last line up to first and the first line down to last. Backwards, but not + that backwards.

    +

    Here's how: poem.lines.to_a.reverse

    +
    \["More still did I(.+)"\]
    +
    +
    +

    Ringlets of Chained Methods

    +

    So what do you see? What happened there? You typed poem.lines.to_a.reverse and what happened?

    +

    Two things happened. You turned the poem into a +list using lines.to_a. lines decides the way +the string is split up, then to_a converted it into an +Array. (To array.) Different methods, such +as bytes and chars can be used in place +of lines. By using lines, ruby will return each line of the poem.

    +

    Then, you reversed that list. You had each line. You reversed them. That's it.

    +

    Let's tack one more method on the end there: print poem.lines.to_a.reverse.join +

    More still did I(.+)
    +
    +
    +

    Of All the Summaries, #3 is Here Now

    +

    Good show, my friend! The join method took that list of reversed lines and put them + together into a string. (Sure, you could have also just used to_s.)

    +

    Review time.

    +
      +
    • Exclamations. Methods may have exclamations (and also question marks) + in their name. No big deal. Try: poem.include? "my hand"
    • +
    • Square brackets. Target and find things. Search and replace.
    • +
    • Chaining methods lets you get a lot more done. Break up a poem, + reverse it, reassemble it: poem.lines.to_a.reverse.join
    • +
    +

    At this point, you may want to tinker with the poem a bit more. A complete list of all + the String methods is + + here. + Go ahead and try a few (such as poem.downcase or poem.delete.)

    +

    When you're ready to move on, type: books = {}

    +
    \{\}
    +
    +
    +

    A Wee Blank Book

    +

    You've made an empty hash. (Also known as: an empty dictionary.)

    +

    We're going to stuff some miniature book reviews in this hash. Here's our rating system:

    +
      +
    • :splendid → a masterpiece.
    • +
    • :quite_good → enjoyed, sure, yes.
    • +
    • :mediocre → equal parts great and terrible.
    • +
    • :quite_not_good → notably bad.
    • +
    • :abyssmal → steaming wreck.
    • +
    +

    To rate a book, put the title in square brackets and put the rating after the equals.

    +

    For example: books["Gravity's Rainbow"] = :splendid

    +
    :\w+
    +
    +
    +

    More Bite-Size Reviews

    +

    Keep going, fill it up with reviews. And, if you want to see the whole list, + just type: books

    +

    Again, the ratings are: :splendid, :quite_good, :mediocre, + :quite_not_good, and :abyssmal.

    +

    These ratings are not strings. When you place a colon in front of a simple word, you get a + symbol. Symbols are cheaper than strings (in terms of computer memory.) If + you use a word over and over in your program, use a symbol. Rather than having thousands of + copies of that word in memory, the computer will store the symbol only once.

    +

    Once you've got three or four books in + there, type: books.length.

    +
    [3-9]
    +
    +
    +

    Wait, Did I Like Gravity's Rainbow?

    +

    See, the length method works on strings, list and hashes. One great thing about + Ruby is that names are often reused, which means fewer names you need to remember.

    +

    If you'd like to look up one of your old reviews, again put the title in the square. But leave off + the equals.

    +

    Just like this: books["Gravity's Rainbow"]

    +
    :\w+
    +
    +
    +

    Hashes as Pairs

    +

    Keep in mind that hashes won't keep things in order. That's not their job. It'll just pair up two + things: a key and a value. In your reviews, the key is the book's + title and the value is the rating.

    +

    If you want to just see the titles of the books you've reviewed: books.keys

    +
    \[".*"\]
    +
    +
    +

    Are You Harsh?

    +

    So are you giving out harsh, unfair reviews? Let's keep score with this hash:
    ratings = Hash.new {0}

    +

    Then, okay, now let's count up your reviews. Just stay with me. Type:
    + books.values.each { |rate| ratings[rate] += 1 }

    +

    (The straight line in the code is the pipe character, probably located right above the + Enter key on your keyboard.)

    +
    \[:.+\]
    +
    +
    +

    A Tally

    +

    Great, wow! You've made a scorecard of your ratings. Type ratings to see the count. + This new hash shows a rating and then the number of times you've given that rating.

    +

    One of the amazing new things we've just used is a block. We're going to + explore these more in the next summary. But, basically, a block is a bit of Ruby code surrounded + by curly braces.

    +

    Let's try another block: 5.times { print "Odelay!" }

    +
    Odelay!Od.*
    +
    +
    +

    Now Arriving at Summary #4

    +

    Blocks are always attached to methods. Like the times method, which takes the + block and runs the code over and over. (In this case: five times.)

    +

    This last lesson was a bit longer. You've probably used up three minutes learning about:

    +
      +
    • Hashes. The little dictionary with the curly pages: {}.
    • +
    • Symbols. Tiny, efficient code words with a colon: :splendid.
    • +
    • Blocks. Chunks of code which can be tacked on to many of Ruby's methods. Here's the + code you used to build a scorecard:
      books.values.each { |rate| ratings[rate] += 1 }.
    • +
    +<<<<<<< HEAD + + +======= +

    On your computer, you probably have a lot of different files. Files with pictures in them, + files with programs in them. And files are often organized into folders, also called: + directories.

    +

    I've prepared a few directories for you. Take a look: + Dir.entries "/"

    +
    \["\.", .+\]
    +
    +
    +

    The Private Collection of Dr. Dir

    +

    You've just listed out everything in the top directory. The root directory, indicated + by a single slash. Containing some programs and other tutorials and such.

    +

    So, what is the Dir.entries method? Well, it's just a method, right? + entries is a method called on the Dir variable. + And Dir has a collection of methods for checking out file directories.

    +

    One other little thing we haven't really talked about openly. Method arguments, highlighted in green.

    +
      +
    • Dir.entries "/": Anything listed after a method + is considered an attachment.
    • +
    • print poem: See, print is an ordinary method. And the + poem is attached. To be printed.
    • +
    • print "pre", "event", "ual", "ism" has several arguments, with commas + between them.
    • +
    +

    To list just the text files in that directory: Dir["/*.txt"]

    +
    \["\/comics\.txt"\]
    +
    +
    +

    Come, Read Comics With Me

    +

    The Dir[] method is like entries but you search for files + with wildcard characters. Here, we see those square brackets again! Notice how + they still mean, "I am looking for _____?"

    +

    More specifically: "I am looking for files which end with .txt."

    +

    Let's crack open this comics file, then. Here's the way:
    + print File.read("/comics.txt")

    +
    Achewood.+
    +
    +
    +

    Mi Comicas, Tu Comicas

    +

    All right! We can start to use files to store things. This is great because normally when + we exit Ruby, all our variables will be gone. Ruby, by itself, forgets these things. + But if we save things in files, we can read those files in future Ruby escapades.

    +

    Hey, and guess what? The /Home directory is yours! I gave it to you! I am generous! Let's make a copy of the comics file.

    +

    You'll want to: FileUtils.copy('/comics.txt', '/Home/comics.txt') +

    If you've already created the file, use File.delete('/Home/comics.txt') to trash it.

    +
    nil
    +
    +
    +

    Your Own Turf

    +

    Okay, you've got a copy. Check it: Dir["/Home/*.txt"]

    +

    To add your own comic to the list, let's open the file in append mode.

    +

    Start like this: File.open("/Home/comics.txt", "a") do |f|.

    +
    ..
    +
    +
    +

    And Now For the Startling Conclusion

    +

    So your prompt has changed. See that? Your prompt is a double dot now.

    +

    In this tutorial, this prompt means that Ruby is expecting you to type more. + As you type in the lines of Ruby code, the double dots will continue until you + are completely finished.

    +

    Hot tip: If you want to stop working on the code and break out of the double dots, use the reset + command. If you want to go the previous page of the tutorial, use the back command.

    +

    Here's your code. You've already typed the first line, so just enter the second line. (The \n + is an Enter character.

    +
    • File.open("/Home/comics.txt", "a") do |f|
    • +
    •   f << "Cat and Girl: http://catandgirl.com/\n"
    • +
    • end
    • +
    +

    And, since you're getting so advanced and capable here, one other tip: you can use the up and down arrow keys to + edit your old commands or run them again.

    +
    ..
    +
    +
    +

    Ruby Sits Still

    +

    That last line adds the Cat and Girl comic to the list, but Ruby's going to wait until you're totally finished to + take action.

    +

    Now, to finish the code you've started. You opened a new block when you typed do. + So far the blocks we've seen have used curly braces. This time we'll be using do and end instead + of curly braces. A lot of Rubyists will use do...end when the block goes on for many lines.

    +

    Let's get that block finished now, with: end

    +
    • File.open("/Home/comics.txt", "a") do |f|
    • +
    •   f << "Cat and Girl: http://catandgirl.com/\n"
    • +
    • end
    • +
    +
    #.File:/Home/comics\.txt \(closed\).
    +
    +
    +

    The Clock Nailed To the File

    +

    Good, good! You've added that new comic to the file. You can see for yourself: print File.read("/Home/comics.txt")

    +

    What time was it when you changed the file? Let's check. Type: File.mtime("/Home/comics.txt")

    +
    \d{4}-\d+-\d+ \d{2}:\d{2}:\d{2} [+-]\d{4}
    +
    +
    +

    Just the Hour Hand

    +

    Great, there's the time. The precise time exactly when you added to the file. The mtime gives you a Ruby Time object.

    +

    If you want to check just what hour it was, hit the up arrow key and change the line to: File.mtime("/Home/comics.txt").hour

    +
    \d+
    +>>>>>>> nanothief/master +
    + +
    +

    Hallo, Who's There? And Summary #5 Waves Its Hat!

    +

    Well done, well done, well done, well done! Truly, truly, truly, truly, truuuuuuuuly!

    +

    Here's the last few minutes of your life in review:

    +
      +
    • Arguments. Arguments are a list of things sent into a method. With commas between.
    • +
    • We also spoke about do and end which are another way to make a block.
    • +
    +

    You totally know how to use Ruby now. I mean you've got down the essentials. You just need to keep learning more methods and + try out more complex blocks.

    +

    But there's one side of Ruby we haven't settled. Making your own methods and classes.

    +

    Ahem! Let's get it over with then.

    +
    +
    +

    In Ruby, Def Leppard Means Define Leppard (a Method)!

    +

    Hey, okay, you done it. You're making your own method. You started with def, followed by the name of the method. + And a list of arguments which the method will need. This isn't too scary and dangerous!

    +

    All we have to do is fill it up with Ruby and finish it up with end.

    +
    +
    +

    Hey, Cool, a Popup

    +

    Let's make a page of links. How about that? We'll need to load a little library I've made for you.

    +

    Type: require 'popup'

    +
    true
    +
    +
    +

    Browser Puppetry

    +

    Excellent, you've loaded the popup library.

    +

    The popup library contains a bunch of methods I've written which let you control a popup here on the Try Ruby site.

    +

    Here, try this: Popup.goto "http://google.com/"

    +
    \033\[1;JSm.*popup_goto\(.*\)\033\[m.*
    +
    +
    +

    Making Links and Spinning Webs

    +

    Our own lovely, little popup to manipulate. You can also fill it with your own goodies. We'll start small:

    +
    • Popup.make {
    • +
    •   h1 "My Links"
    • +
    •   link "Go to Google", "http://google.com/"
    • +
    • }
    • +
    +

    The term h1 (h-one) means a level-one header. In HTML, this is the largest size of header.

    +
    \033\[1;JSm.*popup_make\(.*h1.*a href.*\)\033\[m.*
    +
    +
    +

    Popups Are So Easy, It's Crazy

    +

    Looks good, you did it perfectly, just as you were asked. Let's make a list then.

    +

    Here's how you make a list with the popup library:

    +
    • Popup.make do
    • +
    •   h1 "Things To Do"
    • +
    •   list do
    • +
    •     p "Try out Ruby"
    • +
    •     p "Ride a tiger"
    • +
    •     p "(down River Euphrates)"
    • +
    •   end
    • +
    • end
    • +
    +

    The p method is short for "paragraph".

    +
    \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*li.*\)\033\[m.*
    +
    +
    +

    Spread the Comics on the Table

    +

    Okay, this is coming along wonderfully. This is simple stuff, but keep in mind that you didn't know any Ruby whatsoever just fifteen minutes ago!

    +

    Last +step. Let's tie it all together, you know? Let's make it chime together +like a very nice set of glistening chimes on the beach in the +maginificent sunlight!

    +

    Now, let's make a list of the links to each comic:

    +
    • Popup.make do
    • +
    •   h1 "Comics on the Web"
    • +
    •   list do
    • +
    •     comics.each do |name, url|
    • +
    •       link name, url
    • +
    •     end
    • +
    •   end
    • +
    • end
    • +
    +

    You can click on the links and read the comics in the little window even! Smashing!

    +
    \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*a href.*li.*a href.*\)\033\[m.*
    +
    +
    +

    Summary #6 Which Means You've Come So Far

    +

    You're a level six Ruby cleric. I mean what a great job you've done. Let's review:

    +
      +
    • You added your own method with def and you used that [coming soon]
    • +
    • You used the require method to load the popup library.
      By typing: require 'popup'
    • +
    • And if that wasn't enough, you made your own web page from a list of comics in a file no you havent. You made a real program!
    • +
    +

    So +what could possibly be next? What could you possibly have to learn now? +Ha, this is the best part. You've come such a long way that we're going +to uncover classes. For two more short lessons and you're done.

    +

    Earlier, we created a hash like this: Hash.new Try it.

    +
    \{\}
    +
    +
    +

    Not a School Class, a Working Class

    +

    You see, the empty curly braces {} is a shortcut for Hash.new. The new +method is used to make objects of a certain class. (Think "class" as in +"working class" — a specific group of objects which are similar, have +the same jobs, the same shirts.)

    +

    Ask yourself this: How would I make a blog in Ruby? +Where would you start? Well, you might store your blog entries in a +file, right? But how would you keep track of the title of the entry and +the time it was posted? And when you loaded the file, how would it look +in Ruby? Would it be a Hash? Or an Array? Or an Array of Arrays? Or +something else?

    I really think you'll want to use a class. You are already familiar with many classes: Hash, Array, String.

    +

    Let's make a new class: class BlogEntry.

    +
    ..
    +
    +
    +

    The Stuff Blogs are Made of

    +

    You've opened up a new BlogEntry class. What is your blog entry made of? A title, sure. Also, a time when the entry was posted. The + full text of the entry.

    +

    We'll do a mood setting, too, just like LiveJournal. The Internet has really brought back stick people and smileys + out of bankruptcy. Emote!

    +

    Okay, so you've got the first line of the class, here's the rest:

    +
    • class BlogEntry
    • +
    •   attr_accessor :title, :time, :fulltext, :mood
    • +
    • end
    • +
    +
    nil
    +
    +
    +

    Accessors Are the Dangling Limbs

    +

    Hey, good class, man. You've got a new BlogEntry class. To start an entry:
    entry = BlogEntry.new.

    +

    In the class definition, you used a method called attr_accessor. There are many attribute methods like + this which add little settings to classes. These attributes are just variables attached to a class.

    +

    Think +of it this way. A class is like a person. That star-shaped human thing +out there. And the attributes are the dangling limbs, the different +parts that make up a body.

    +

    To set the title of your entry: entry.title = "Today Mt. Hood Was Stolen!"

    +
    ".+"
    +
    +
    +

    An Object, That Neat Little Package

    +

    Go ahead and set the post time: entry.time = Time.now

    +

    And the mood: entry.mood = :sick

    +

    And the post itself: entry.fulltext = "I can't believe Mt. Hood was stolen! I am speechless! It was stolen by a giraffe who drove away + in his Cadillac Seville very nonchalant!!"

    +

    To see all your settings, just type at the prompt: entry.

    +
    #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
    +
    +
    +

    Quickening it Up

    +

    Cool, +you're blog is awesome. Hey, let's make things a bit easier on you. +You're not going to want to set the time like that every time you post. +You just want to type in the title and the entry and the mood quickly, +right?

    +

    Let's add an initialize method.

    +
    • class BlogEntry
    • +
    •   def initialize( title, mood, fulltext )
    • +
    •     @time = Time.now
    • +
    •     @title, @mood, @fulltext = title, mood, fulltext
    • +
    •   end
    • +
    • end
    • +
    +

    Once you've got that typed in, try making a new entry: BlogEntry.new

    +
    ArgumentError: wrong number of arguments \(0 for 3\).*
    +
    +
    +

    You've Taught Your Blog to Reject Worthless Things

    +

    Did you see how inside the class we used the at-symbols? Like this: @time = Time.now

    +

    Outside the class, we use accessors: entry.time = Time.now But inside we use instance variables: @time = Time.now + They're the exact same thing, but expressed in two different places of your program.

    +

    Your blog now needs a title, a mood and a post in order to work. When a new BlogEntry is created, the initialize method + is used to check for any arguments to new. Uh, we need three arguments!

    +

    Try it again with all three.

    +

    entry2 += BlogEntry.new( "I Left my Hoodie on the Mountain!", :confused, "I am +never going back to that mountain and I hope a giraffe steals it." )

    +
    #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
    +
    +
    +

    A Giraffe Has Not Stolen Summary #7

    +

    Aha, you're here. And all in one piece. We're still going to make your blog real, but until then, let's review, okay?

    +
      +
    • Classes. Everything in Ruby is some kind of object. Classes explain objects. How a certain object works. + For example, you made a few blog entry objects and these objects are explained in the BlogEntry class. + In other words: you call them BlogEntry objects.
    • +
    • Accessors are variables attached to an object which can be used outside the object. (entry.time = Time.now)
    • +
    • Instance variables are the same variables you're using for accessors when inside the object. + Like in a method definition. (@time = Time.now)
    • +
    +

    Okay, +let's wrap things up, kid. Here's the last chapter of the GRIPPING epic +story of Try Ruby! Now that you've got a taste of how it all works, how +are you going to use it around the house and in your grocer's freezer? +You're a great person (one of my favorites), but you need guidance.

    +

    Let's finish your blog. You have blog entries, but no actual blog.

    +

    Put the entries into an array: blog = [entry, entry2]

    +
    \[#.BlogEntry:0x[0-9a-f]+.*, #.BlogEntry:0x[0-9a-f]+.*\]
    +
    +
    +

    It's All About Combining Things

    +

    Some +beautiful things can be done with the simple parts of Ruby, especially +when you combine them together into new things. Here we've got a blog +made of an array of classes. And, actually, Ruby really does good with +this kind of creature.

    +

    Here's a few things you can do with your array blog:

    +
    • You'll want to sort your entries from newest to oldest. You can do this with:
      + blog.sort_by { |entry| entry.time }.reverse
      See the sort_by explanation for more.
    • +
    • If you want to search your blog for anything related to "cadillac":
      + blog.find_all { |entry| entry.fulltext.match(/cadillac/i) }
      + Read all about find_all + and match + to figure out how that works. Also: the slashy /giraffe/i is a Regexp object, used for matching words.
    • +
    • Add new entries with blog << new_entry
      + And check out the << method documentation.
    • +
    +

    You can browse a list of all Ruby's built-in methods at ruby-doc.org's core list. + Another good list is at the online pickaxe.

    +

    One really useful method (I probably use this more than anything else) is map. Type: blog.map { |entry| entry.mood }

    +
    \[(:\w+, )+:\w+\]
    +
    +
    +

    Look at His Face — The Transformation Has Begun

    +

    The map method cycles through an array and replaces each item with something new. Say you wanted to replace each of your blog entries + with the name Bruce Willis. Do it so: blog.map { "Bruce Willis" }

    +

    Since the block always returns the string "Bruce Willis", that's what you get. In the code you just used, the entry was swapped out + for only the entry.mood.

    +

    Now, +I want you to make a popup with your blog entries. I'm not going to +give you all of the code. I'm just going to give you part of it.

    +
    • blog.each do |entry|
    • +
    •   h2 entry.title
    • +
    •   p entry.fulltext
    • +
    • end
    • +
    +

    Now, I expect you to put the popup code around it and add an h1 title with the name of your blog. For extra haroompf, have the time of each entry display.

    +
    \033\[1;JSm.*popup_make\(.*h1.*h2.*li.*h2.*li.*\)\033\[m.*
    +
    +
    +

    You are Some Kind of Web Guru, I Have Stars in My Eyes

    +

    Good, +that's it! This is exactly the code you can use to write your own real +Ruby blog. If you're feeling adventurous, I'd check out the Rails videos which show a swift young fellow creating a blog in 15 minutes. You just sit back and watch.

    +

    I +should mention Rails. You have been learning the Ruby language, how to +speak it. But Rails is a bunch of libraries (sort of like the popup +library we've been using.) It's a very powerful toolkit for building +websites. If you're interested in learning about Rails, I would head + over there right away. Start using your Ruby skills proper!

    +

    One thing Rails has is easy methods for dates. Like, try: Time.now - 2.weeks

    +
    class Integer; def weeks; self * 7*24*60*60; end; end
    +
    \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-+]\d{4}
    +
    +
    +

    Summary #8, The Hey-Relax-You-Did-Good Summary

    +

    This last section took a moment to wind down, to give you some pointers as to how you can use Ruby. If you enjoyed yourself, + download Ruby and install it.

    + +

    Once you have Ruby installed, you can use Interactive Ruby by running irb on your system's prompt. For more on Irb, + there's The Tiger's Vest to help you.

    +

    You +really deserve a double-layer cake with double-double frosting and a +guy playing one of those guitars that's a double guitar. I mean you +finished, you really did! No doubt about it, you're a certified +red-blooded smartiac!

    +
    +
    + diff --git a/public/tutorials/intro_files/sick.gif b/public/tutorials/intro_files/sick.gif new file mode 100755 index 0000000000000000000000000000000000000000..217a67cbae60740fdc90b92e06b977cf7fc56699 GIT binary patch literal 94 zcmZ?wbhEHb|6B Date: Tue, 11 Jan 2011 09:48:14 -0600 Subject: [PATCH 02/16] code dump.. this version works --- public/fakefs | 1 + public/index.html | 1 - public/irb.cgi | 7 ++++--- public/setup.rb | 9 +++++---- public/tryruby.rb | 6 +++--- public/tutorials/intro.html | 4 ++-- 6 files changed, 15 insertions(+), 13 deletions(-) create mode 160000 public/fakefs diff --git a/public/fakefs b/public/fakefs new file mode 160000 index 0000000..c6168d4 --- /dev/null +++ b/public/fakefs @@ -0,0 +1 @@ +Subproject commit c6168d41363e4c60ddf9d4cb784e6acf79ea581d diff --git a/public/index.html b/public/index.html index 01289b0..333c950 100644 --- a/public/index.html +++ b/public/index.html @@ -13,7 +13,6 @@ -
    diff --git a/public/irb.cgi b/public/irb.cgi index 6c1c2de..9bf2d06 100755 --- a/public/irb.cgi +++ b/public/irb.cgi @@ -1,9 +1,10 @@ -#!/usr/bin/env ruby +#!/usr/local/bin/ruby -require 'tryruby.rb' +require './tryruby.rb' require 'cgi' require 'cgi/session' require 'cgi/session/pstore' +require './popup.rb' class TryRubyCGISession# < TryRuby::Session attr_accessor :cgi, :session @@ -34,4 +35,4 @@ end TryRuby.session = TryRubyCGISession.new -print TryRuby.session.header + TryRuby.run_line(TryRuby.session.cgi['cmd']).format \ No newline at end of file +print TryRuby.session.header + TryRuby.run_line(TryRuby.session.cgi['cmd']).format diff --git a/public/setup.rb b/public/setup.rb index ab97a9e..10c1a39 100644 --- a/public/setup.rb +++ b/public/setup.rb @@ -38,9 +38,10 @@ module TryRuby FLICK_EOF popup_rb_text = <<-POPUP_EOF -module Popup - # ... -end + + + + POPUP_EOF File.open('/comics.txt', "w") {|f| f.write(comic_txt_text) } @@ -63,4 +64,4 @@ def require(path) end SETUP_EOF -end \ No newline at end of file +end diff --git a/public/tryruby.rb b/public/tryruby.rb index bcdc183..4b9bbcb 100644 --- a/public/tryruby.rb +++ b/public/tryruby.rb @@ -1,7 +1,7 @@ #$LOAD_PATH.unshift File.join(File.dirname(__FILE__), 'submodules', 'fakefs', 'lib') -require 'setup.rb' +require './setup.rb' require 'ruby_parser' -require 'fakefs/safe' +require './fakefs/safe' require 'stringio' module TryRuby @@ -171,4 +171,4 @@ def get_stdout $stdout.read end -end \ No newline at end of file +end diff --git a/public/tutorials/intro.html b/public/tutorials/intro.html index 20e6ae5..56c1d1c 100644 --- a/public/tutorials/intro.html +++ b/public/tutorials/intro.html @@ -417,8 +417,8 @@

    Hey, Cool, a Comics Thing

  • strip removes extra spaces around the name. Just in case.
  • Right on. Bravo. You've got the comics in a Ruby hash. But what now? What good is this really?

    -

    Let's make a page of links. How about that? We'll need to load a little library I've made for you.

    -

    Type: require 'popup'

    +

    Let's make a page of links. How about that? I went ahead and loaded a little library I've made for you.

    +

    Type: next. This is temporary as I updates new lessons.

    true
    From b930b7f5938ea1fa526b80b6bfbc735bbb4c4cf4 Mon Sep 17 00:00:00 2001 From: David Prince Date: Tue, 18 Jan 2011 09:45:35 +0800 Subject: [PATCH 03/16] Fixed grammatical error: Replaced 'you're blog is awesome' with 'your blog is awesome'. --- tryruby/app/views/tutorials/intro.rhtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryruby/app/views/tutorials/intro.rhtml b/tryruby/app/views/tutorials/intro.rhtml index 4b43137..7443c46 100644 --- a/tryruby/app/views/tutorials/intro.rhtml +++ b/tryruby/app/views/tutorials/intro.rhtml @@ -543,7 +543,7 @@ parts that make up a body.

    Quickening it Up

    Cool, -you're blog is awesome. Hey, let's make things a bit easier on you. +your blog is awesome. Hey, let's make things a bit easier on you. You're not going to want to set the time like that every time you post. You just want to type in the title and the entry and the mood quickly, right?

    From 0fcd9f19c4385c6eed94df5e32ebe831e8a1b9b1 Mon Sep 17 00:00:00 2001 From: Andrew McElroy Date: Mon, 21 Mar 2011 12:25:35 -0500 Subject: [PATCH 04/16] one of a lot of updates --- TryRuby/.gitignore | 4 + TryRuby/.rspec | 1 + TryRuby/.rvmrc | 1 + TryRuby/app/controllers/classic_controller.rb | 2 + TryRuby/app/controllers/irb_controller.rb | 85 + TryRuby/app/controllers/public_controller.rb | 2 + TryRuby/app/helpers/classic_helper.rb | 2 + TryRuby/app/helpers/irb_helper.rb | 2 + TryRuby/app/helpers/public_helper.rb | 2 + TryRuby/app/views/irb/_form.html.erb | 17 + TryRuby/app/views/irb/edit.html.erb | 6 + TryRuby/app/views/irb/index.html.erb | 21 + TryRuby/app/views/irb/new.html.erb | 5 + TryRuby/app/views/irb/show.html.erb | 5 + TryRuby/app/views/layouts/tryruby_es.rhtml | 96 + TryRuby/app/views/tryruby/_donate.html.erb | 41 + TryRuby/config.ru | 4 + TryRuby/config/application.rb | 42 + TryRuby/config/cucumber.yml | 8 + TryRuby/config/initializers/secret_token.rb | 7 + .../db/migrate/20110314191710_create_irb.rb | 12 + TryRuby/db/schema.rb | 15 + TryRuby/features/lesson1.feature | 7 + TryRuby/features/lesson2.feature | 0 .../features/step_definitions/web_steps.rb | 219 +++ TryRuby/features/support/env.rb | 57 + TryRuby/features/support/paths.rb | 33 + TryRuby/lib/tasks/.gitkeep | 0 TryRuby/lib/tasks/cucumber.rake | 53 + TryRuby/public/images/ajax-loader.gif | Bin 0 -> 673 bytes TryRuby/public/images/closelabel.png | Bin 0 -> 168 bytes TryRuby/public/javascripts/facebox.js | 309 ++++ TryRuby/public/javascripts/jQuery.irb.js | 1641 +++++++++++++++++ TryRuby/public/javascripts/raphael-min.js | 113 ++ TryRuby/public/stylesheets/facebox.css | 83 + TryRuby/public/stylesheets/reset.css | 46 + TryRuby/public/stylesheets/scaffold.css | 56 + TryRuby/public/tutorials/es_intro.html | 666 +++++++ TryRuby/public/tutorials/intro.html | 680 +++++++ TryRuby/public/tutorials/intro.html.broken | 638 +++++++ TryRuby/public/tutorials/intro_files/sick.gif | Bin 0 -> 94 bytes TryRuby/script/cucumber | 10 + TryRuby/script/rails | 6 + .../controllers/classic_controller_spec.rb | 5 + .../spec/controllers/irb_controller_spec.rb | 125 ++ .../controllers/public_controller_spec.rb | 5 + TryRuby/spec/helpers/classic_helper_spec.rb | 15 + TryRuby/spec/helpers/irb_helper_spec.rb | 15 + TryRuby/spec/helpers/public_helper_spec.rb | 15 + TryRuby/spec/models/irb_spec.rb | 5 + TryRuby/spec/requests/irb_spec.rb | 11 + TryRuby/spec/routing/irb_routing_spec.rb | 35 + TryRuby/spec/spec_helper.rb | 27 + TryRuby/spec/views/irb/edit.html.erb_spec.rb | 15 + TryRuby/spec/views/irb/index.html.erb_spec.rb | 14 + TryRuby/spec/views/irb/new.html.erb_spec.rb | 15 + TryRuby/spec/views/irb/show.html.erb_spec.rb | 11 + TryRuby/vendor/plugins/.gitkeep | 0 public/images/header.png | Bin 46523 -> 51873 bytes public/index.html | 46 +- public/javascripts/application.js | 2 + public/javascripts/console.js | 288 +++ public/javascripts/controls.js | 963 ++++++++++ public/javascripts/dragdrop.js | 973 ++++++++++ public/javascripts/effects.js | 1128 +++++++++++ public/javascripts/facebox.js | 309 ++++ public/javascripts/index.html | 8 + public/javascripts/irb.js | 110 ++ public/javascripts/jQuery.irb.js | 1641 +++++++++++++++++ public/javascripts/jquery-1.3.2.min.js | 19 + public/javascripts/jquery-1.4.2.min.js | 154 ++ public/javascripts/jquery.console.js | 609 ++++++ public/javascripts/jquery.console.min.js | 1 + public/javascripts/jquery.js | 32 + public/javascripts/json2.js | 1 + public/javascripts/lib.min.js | 159 ++ public/javascripts/mouseapp_2.js | 913 +++++++++ public/javascripts/mouseirb_2.js | 179 ++ public/javascripts/raphael-min.js | 113 ++ public/stylesheets/facebox.css | 83 + public/stylesheets/reset.css | 46 + public/stylesheets/scaffold.css | 56 + public/stylesheets/site.css | 378 ++++ tryruby/Gemfile | 52 +- tryruby/README | 265 ++- tryruby/Rakefile | 7 +- .../app/controllers/application_controller.rb | 13 +- tryruby/app/controllers/tryruby_controller.rb | 13 +- tryruby/app/helpers/application_helper.rb | 17 +- tryruby/app/views/layouts/tryruby.rhtml | 82 +- tryruby/app/views/tryruby/index.rhtml | 12 +- tryruby/config/boot.rb | 126 +- tryruby/config/database.yml | 36 +- tryruby/config/environment.rb | 48 +- tryruby/config/environments/development.rb | 35 +- tryruby/config/environments/production.rb | 61 +- tryruby/config/environments/test.rb | 63 +- .../initializers/backtrace_silencers.rb | 4 +- tryruby/config/initializers/inflections.rb | 8 +- tryruby/config/initializers/session_store.rb | 13 +- tryruby/config/locales/en.yml | 2 +- tryruby/config/routes.rb | 69 +- tryruby/db/seeds.rb | 4 +- tryruby/lib/tryruby.rb | 4 +- tryruby/public/images/header.png | Bin 46523 -> 51873 bytes tryruby/public/javascripts/jquery.console.js | 347 ++-- tryruby/public/stylesheets/site.css | 193 +- tryruby/test/performance/browsing_test.rb | 4 +- tryruby/test/test_helper.rb | 53 +- tryruby/tmp/pids/server.pid | 2 +- 110 files changed, 14549 insertions(+), 505 deletions(-) create mode 100644 TryRuby/.gitignore create mode 100644 TryRuby/.rspec create mode 100644 TryRuby/.rvmrc create mode 100644 TryRuby/app/controllers/classic_controller.rb create mode 100644 TryRuby/app/controllers/irb_controller.rb create mode 100644 TryRuby/app/controllers/public_controller.rb create mode 100644 TryRuby/app/helpers/classic_helper.rb create mode 100644 TryRuby/app/helpers/irb_helper.rb create mode 100644 TryRuby/app/helpers/public_helper.rb create mode 100644 TryRuby/app/views/irb/_form.html.erb create mode 100644 TryRuby/app/views/irb/edit.html.erb create mode 100644 TryRuby/app/views/irb/index.html.erb create mode 100644 TryRuby/app/views/irb/new.html.erb create mode 100644 TryRuby/app/views/irb/show.html.erb create mode 100644 TryRuby/app/views/layouts/tryruby_es.rhtml create mode 100644 TryRuby/app/views/tryruby/_donate.html.erb create mode 100644 TryRuby/config.ru create mode 100644 TryRuby/config/application.rb create mode 100644 TryRuby/config/cucumber.yml create mode 100644 TryRuby/config/initializers/secret_token.rb create mode 100644 TryRuby/db/migrate/20110314191710_create_irb.rb create mode 100644 TryRuby/db/schema.rb create mode 100644 TryRuby/features/lesson1.feature create mode 100644 TryRuby/features/lesson2.feature create mode 100644 TryRuby/features/step_definitions/web_steps.rb create mode 100644 TryRuby/features/support/env.rb create mode 100644 TryRuby/features/support/paths.rb create mode 100644 TryRuby/lib/tasks/.gitkeep create mode 100644 TryRuby/lib/tasks/cucumber.rake create mode 100644 TryRuby/public/images/ajax-loader.gif create mode 100755 TryRuby/public/images/closelabel.png create mode 100755 TryRuby/public/javascripts/facebox.js create mode 100644 TryRuby/public/javascripts/jQuery.irb.js create mode 100644 TryRuby/public/javascripts/raphael-min.js create mode 100755 TryRuby/public/stylesheets/facebox.css create mode 100644 TryRuby/public/stylesheets/reset.css create mode 100644 TryRuby/public/stylesheets/scaffold.css create mode 100644 TryRuby/public/tutorials/es_intro.html create mode 100644 TryRuby/public/tutorials/intro.html create mode 100755 TryRuby/public/tutorials/intro.html.broken create mode 100755 TryRuby/public/tutorials/intro_files/sick.gif create mode 100755 TryRuby/script/cucumber create mode 100755 TryRuby/script/rails create mode 100644 TryRuby/spec/controllers/classic_controller_spec.rb create mode 100644 TryRuby/spec/controllers/irb_controller_spec.rb create mode 100644 TryRuby/spec/controllers/public_controller_spec.rb create mode 100644 TryRuby/spec/helpers/classic_helper_spec.rb create mode 100644 TryRuby/spec/helpers/irb_helper_spec.rb create mode 100644 TryRuby/spec/helpers/public_helper_spec.rb create mode 100644 TryRuby/spec/models/irb_spec.rb create mode 100644 TryRuby/spec/requests/irb_spec.rb create mode 100644 TryRuby/spec/routing/irb_routing_spec.rb create mode 100644 TryRuby/spec/spec_helper.rb create mode 100644 TryRuby/spec/views/irb/edit.html.erb_spec.rb create mode 100644 TryRuby/spec/views/irb/index.html.erb_spec.rb create mode 100644 TryRuby/spec/views/irb/new.html.erb_spec.rb create mode 100644 TryRuby/spec/views/irb/show.html.erb_spec.rb create mode 100644 TryRuby/vendor/plugins/.gitkeep create mode 100644 public/javascripts/application.js create mode 100644 public/javascripts/console.js create mode 100644 public/javascripts/controls.js create mode 100644 public/javascripts/dragdrop.js create mode 100644 public/javascripts/effects.js create mode 100755 public/javascripts/facebox.js create mode 100755 public/javascripts/index.html create mode 100755 public/javascripts/irb.js create mode 100644 public/javascripts/jQuery.irb.js create mode 100644 public/javascripts/jquery-1.3.2.min.js create mode 100644 public/javascripts/jquery-1.4.2.min.js create mode 100644 public/javascripts/jquery.console.js create mode 100644 public/javascripts/jquery.console.min.js create mode 100755 public/javascripts/jquery.js create mode 100644 public/javascripts/json2.js create mode 100644 public/javascripts/lib.min.js create mode 100755 public/javascripts/mouseapp_2.js create mode 100755 public/javascripts/mouseirb_2.js create mode 100644 public/javascripts/raphael-min.js create mode 100755 public/stylesheets/facebox.css create mode 100644 public/stylesheets/reset.css create mode 100644 public/stylesheets/scaffold.css create mode 100755 public/stylesheets/site.css diff --git a/TryRuby/.gitignore b/TryRuby/.gitignore new file mode 100644 index 0000000..f0fa30c --- /dev/null +++ b/TryRuby/.gitignore @@ -0,0 +1,4 @@ +.bundle +db/*.sqlite3 +log/*.log +tmp/ diff --git a/TryRuby/.rspec b/TryRuby/.rspec new file mode 100644 index 0000000..53607ea --- /dev/null +++ b/TryRuby/.rspec @@ -0,0 +1 @@ +--colour diff --git a/TryRuby/.rvmrc b/TryRuby/.rvmrc new file mode 100644 index 0000000..39b50dd --- /dev/null +++ b/TryRuby/.rvmrc @@ -0,0 +1 @@ +rvm use 1.9.2@tryruby diff --git a/TryRuby/app/controllers/classic_controller.rb b/TryRuby/app/controllers/classic_controller.rb new file mode 100644 index 0000000..019e234 --- /dev/null +++ b/TryRuby/app/controllers/classic_controller.rb @@ -0,0 +1,2 @@ +class ClassicController < ApplicationController +end diff --git a/TryRuby/app/controllers/irb_controller.rb b/TryRuby/app/controllers/irb_controller.rb new file mode 100644 index 0000000..f296b07 --- /dev/null +++ b/TryRuby/app/controllers/irb_controller.rb @@ -0,0 +1,85 @@ +class IrbController < ApplicationController + # GET /irb + # GET /irb.xml + def index + + @irb = [] + + respond_to do |format| + format.html # index.html.erb + format.to_json + format.xml { render :xml => @irb } + end + end + + # GET /irb/1 + # GET /irb/1.xml + def show + @irb = Irb.find(params[:id]) + + respond_to do |format| + format.html # show.html.erb + format.xml { render :xml => @irb } + end + end + + # GET /irb/new + # GET /irb/new.xml + def new + @irb = Irb.new + + respond_to do |format| + format.html # new.html.erb + format.xml { render :xml => @irb } + end + end + + # GET /irb/1/edit + def edit + @irb = Irb.find(params[:id]) + end + + # POST /irb + # POST /irb.xml + def create + @irb = Irb.new(params[:irb]) + + respond_to do |format| + if @irb.save + format.html { redirect_to(@irb, :notice => 'Irb was successfully created.') } + format.xml { render :xml => @irb, :status => :created, :location => @irb } + else + format.html { render :action => "new" } + format.xml { render :xml => @irb.errors, :status => :unprocessable_entity } + end + end + end + + # PUT /irb/1 + # PUT /irb/1.xml + def update + @irb = Irb.find(params[:id]) + + respond_to do |format| + if @irb.update_attributes(params[:irb]) + format.html { redirect_to(@irb, :notice => 'Irb was successfully updated.') } + format.xml { head :ok } + else + format.html { render :action => "edit" } + format.xml { render :xml => @irb.errors, :status => :unprocessable_entity } + end + end + end + + # DELETE /irb/1 + # DELETE /irb/1.xml + def destroy + @irb = Irb.find(params[:id]) + @irb.destroy + + respond_to do |format| + format.html { redirect_to(irb_url) } + format.xml { head :ok } + end + end +end diff --git a/TryRuby/app/controllers/public_controller.rb b/TryRuby/app/controllers/public_controller.rb new file mode 100644 index 0000000..2857026 --- /dev/null +++ b/TryRuby/app/controllers/public_controller.rb @@ -0,0 +1,2 @@ +class PublicController < ApplicationController +end diff --git a/TryRuby/app/helpers/classic_helper.rb b/TryRuby/app/helpers/classic_helper.rb new file mode 100644 index 0000000..e85110a --- /dev/null +++ b/TryRuby/app/helpers/classic_helper.rb @@ -0,0 +1,2 @@ +module ClassicHelper +end diff --git a/TryRuby/app/helpers/irb_helper.rb b/TryRuby/app/helpers/irb_helper.rb new file mode 100644 index 0000000..6c9f3c9 --- /dev/null +++ b/TryRuby/app/helpers/irb_helper.rb @@ -0,0 +1,2 @@ +module IrbHelper +end diff --git a/TryRuby/app/helpers/public_helper.rb b/TryRuby/app/helpers/public_helper.rb new file mode 100644 index 0000000..0d8e188 --- /dev/null +++ b/TryRuby/app/helpers/public_helper.rb @@ -0,0 +1,2 @@ +module PublicHelper +end diff --git a/TryRuby/app/views/irb/_form.html.erb b/TryRuby/app/views/irb/_form.html.erb new file mode 100644 index 0000000..4e3cdae --- /dev/null +++ b/TryRuby/app/views/irb/_form.html.erb @@ -0,0 +1,17 @@ +<%= form_for(@irb) do |f| %> + <% if @irb.errors.any? %> +
    +

    <%= pluralize(@irb.errors.count, "error") %> prohibited this irb from being saved:

    + +
      + <% @irb.errors.full_messages.each do |msg| %> +
    • <%= msg %>
    • + <% end %> +
    +
    + <% end %> + +
    + <%= f.submit %> +
    +<% end %> diff --git a/TryRuby/app/views/irb/edit.html.erb b/TryRuby/app/views/irb/edit.html.erb new file mode 100644 index 0000000..9e50dc3 --- /dev/null +++ b/TryRuby/app/views/irb/edit.html.erb @@ -0,0 +1,6 @@ +

    Editing irb

    + +<%= render 'form' %> + +<%= link_to 'Show', @irb %> | +<%= link_to 'Back', irb_path %> diff --git a/TryRuby/app/views/irb/index.html.erb b/TryRuby/app/views/irb/index.html.erb new file mode 100644 index 0000000..90b773b --- /dev/null +++ b/TryRuby/app/views/irb/index.html.erb @@ -0,0 +1,21 @@ +

    Listing irb

    + + + + + + + + +<% @irb.each do |irb| %> + + + + + +<% end %> +
    <%= link_to 'Show', irb %><%= link_to 'Edit', edit_irb_path(irb) %><%= link_to 'Destroy', irb, :confirm => 'Are you sure?', :method => :delete %>
    + +
    + +<%= link_to 'New Irb', new_irb_path %> diff --git a/TryRuby/app/views/irb/new.html.erb b/TryRuby/app/views/irb/new.html.erb new file mode 100644 index 0000000..9a7b635 --- /dev/null +++ b/TryRuby/app/views/irb/new.html.erb @@ -0,0 +1,5 @@ +

    New irb

    + +<%= render 'form' %> + +<%= link_to 'Back', irb_path %> diff --git a/TryRuby/app/views/irb/show.html.erb b/TryRuby/app/views/irb/show.html.erb new file mode 100644 index 0000000..c271c01 --- /dev/null +++ b/TryRuby/app/views/irb/show.html.erb @@ -0,0 +1,5 @@ +

    <%= notice %>

    + + +<%= link_to 'Edit', edit_irb_path(@irb) %> | +<%= link_to 'Back', irb_path %> diff --git a/TryRuby/app/views/layouts/tryruby_es.rhtml b/TryRuby/app/views/layouts/tryruby_es.rhtml new file mode 100644 index 0000000..9ab71c1 --- /dev/null +++ b/TryRuby/app/views/layouts/tryruby_es.rhtml @@ -0,0 +1,96 @@ + + + + + try ruby! (en tu navegador) + + + + + + + + + +
    + +
    +
    +
    + +

    A Popup Browser

    +

    [x]

    +
    + +
    +
    + +
    +
    +
    +
    +
    +
    +

    ¿Tienes 15 minutos? ¡Prueba Ruby ahora mismo!

    +

    Ruby es un lenguaje de programación de Japón + (disponible en ruby-lang.org) + que está revolucionando la web. + La belleza de Ruby se encuentra en su balance entre la simplicidad y el poder.

    + +

    Prueba código Ruby en el prompt de arriba. Además de los métodos + originales de Ruby, los siguientes comandos están disponibles:

    +
      +
    • help + Empieza el tutorial interactivo de 15 minutos. ¡Creeme, es muy básico!
    • +
    • help 2 + Salta al capítulo 2.
    • + +
    • clear + Limpia la pantalla. Útil si tu navegador empieza a alerdarce. + Tu historial de comandos será recordado. +
    • back + Retrocede una pantalla en el tutorial.
    • +
    • reset + Resetea el interprete. (o Ctrl-D!)
    • +
    • next + Te permite saltear la siguiente lección
    • + +
    • time + Detiene el reloj. Imprime cuanto tiempo tu sesión estuvo abierta.
    • +
    +

    Si te pasa de dejar o refrescar la página, tu sesión seguirá aquí a menos que + se deje inactiva por diez minutos.

    +
    +
    +
    + +
    +
    ¿Atrapado en los dos puntos? Unas comillas o algo fue dejado abierto. Escribe: reset o aprieta Ctrl-D.
    +
    + +

    This place was sired by why the lucky stiff. + Please contact me using the email address at that link.is maintained by Andrew McElroy and David Miani. For support issues, please post a ticket or contact Sophrinix on github.
    Por asuntos de traducción, mandar un ticket o contactarse con Cristian Re (leizzer) en Github.
    +

    + +
    + + + + + + + + + + diff --git a/TryRuby/app/views/tryruby/_donate.html.erb b/TryRuby/app/views/tryruby/_donate.html.erb new file mode 100644 index 0000000..f7095b1 --- /dev/null +++ b/TryRuby/app/views/tryruby/_donate.html.erb @@ -0,0 +1,41 @@ + \ No newline at end of file diff --git a/TryRuby/config.ru b/TryRuby/config.ru new file mode 100644 index 0000000..df742d3 --- /dev/null +++ b/TryRuby/config.ru @@ -0,0 +1,4 @@ +# This file is used by Rack-based servers to start the application. + +require ::File.expand_path('../config/environment', __FILE__) +run TryRuby::Application diff --git a/TryRuby/config/application.rb b/TryRuby/config/application.rb new file mode 100644 index 0000000..a8f1bd9 --- /dev/null +++ b/TryRuby/config/application.rb @@ -0,0 +1,42 @@ +require File.expand_path('../boot', __FILE__) + +require 'rails/all' + +# If you have a Gemfile, require the gems listed there, including any gems +# you've limited to :test, :development, or :production. +Bundler.require(:default, Rails.env) if defined?(Bundler) + +module TryRuby + class Application < Rails::Application + # Settings in config/environments/* take precedence over those specified here. + # Application configuration should go into files in config/initializers + # -- all .rb files in that directory are automatically loaded. + + # Custom directories with classes and modules you want to be autoloadable. + # config.autoload_paths += %W(#{config.root}/extras) + + # Only load the plugins named here, in the order given (default is alphabetical). + # :all can be used as a placeholder for all plugins not explicitly named. + # config.plugins = [ :exception_notification, :ssl_requirement, :all ] + + # Activate observers that should always be running. + # config.active_record.observers = :cacher, :garbage_collector, :forum_observer + + # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. + # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. + # config.time_zone = 'Central Time (US & Canada)' + + # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. + # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] + # config.i18n.default_locale = :de + + # JavaScript files you want as :defaults (application.js is always included). + # config.action_view.javascript_expansions[:defaults] = %w(jquery rails) + + # Configure the default encoding used in templates for Ruby 1.9. + config.encoding = "utf-8" + + # Configure sensitive parameters which will be filtered from the log file. + config.filter_parameters += [:password] + end +end diff --git a/TryRuby/config/cucumber.yml b/TryRuby/config/cucumber.yml new file mode 100644 index 0000000..621a14c --- /dev/null +++ b/TryRuby/config/cucumber.yml @@ -0,0 +1,8 @@ +<% +rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : "" +rerun_opts = rerun.to_s.strip.empty? ? "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}" +std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} --strict --tags ~@wip" +%> +default: <%= std_opts %> features +wip: --tags @wip:3 --wip features +rerun: <%= rerun_opts %> --format rerun --out rerun.txt --strict --tags ~@wip diff --git a/TryRuby/config/initializers/secret_token.rb b/TryRuby/config/initializers/secret_token.rb new file mode 100644 index 0000000..5e9b98f --- /dev/null +++ b/TryRuby/config/initializers/secret_token.rb @@ -0,0 +1,7 @@ +# Be sure to restart your server when you modify this file. + +# Your secret key for verifying the integrity of signed cookies. +# If you change this key, all old signed cookies will become invalid! +# Make sure the secret is at least 30 characters and all random, +# no regular words or you'll be exposed to dictionary attacks. +TryRuby::Application.config.secret_token = 'f256893c2715b8fab149294c7f3b79fbc7a725534be51332c220c2e19965e631cc72c360acfec77dcc0469f58b81b5023e7c93a800626520f9420816639948d5' diff --git a/TryRuby/db/migrate/20110314191710_create_irb.rb b/TryRuby/db/migrate/20110314191710_create_irb.rb new file mode 100644 index 0000000..b628478 --- /dev/null +++ b/TryRuby/db/migrate/20110314191710_create_irb.rb @@ -0,0 +1,12 @@ +class CreateIrb < ActiveRecord::Migration + def self.up + create_table :irb do |t| + + t.timestamps + end + end + + def self.down + drop_table :irb + end +end diff --git a/TryRuby/db/schema.rb b/TryRuby/db/schema.rb new file mode 100644 index 0000000..671c0da --- /dev/null +++ b/TryRuby/db/schema.rb @@ -0,0 +1,15 @@ +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# Note that this schema.rb definition is the authoritative source for your +# database schema. If you need to create the application database on another +# system, you should be using db:schema:load, not running all the migrations +# from scratch. The latter is a flawed and unsustainable approach (the more migrations +# you'll amass, the slower it'll run and the greater likelihood for issues). +# +# It's strongly recommended to check this file into your version control system. + +ActiveRecord::Schema.define(:version => 0) do + +end diff --git a/TryRuby/features/lesson1.feature b/TryRuby/features/lesson1.feature new file mode 100644 index 0000000..409a21f --- /dev/null +++ b/TryRuby/features/lesson1.feature @@ -0,0 +1,7 @@ +Feature: Successfully execute lesson 1 + Scenario: starting into try ruby + Given I am on index + When I type help + Then I should see Using The Prompt + + diff --git a/TryRuby/features/lesson2.feature b/TryRuby/features/lesson2.feature new file mode 100644 index 0000000..e69de29 diff --git a/TryRuby/features/step_definitions/web_steps.rb b/TryRuby/features/step_definitions/web_steps.rb new file mode 100644 index 0000000..0f0af8a --- /dev/null +++ b/TryRuby/features/step_definitions/web_steps.rb @@ -0,0 +1,219 @@ +# IMPORTANT: This file is generated by cucumber-rails - edit at your own peril. +# It is recommended to regenerate this file in the future when you upgrade to a +# newer version of cucumber-rails. Consider adding your own code to a new file +# instead of editing this one. Cucumber will automatically load all features/**/*.rb +# files. + + +require 'uri' +require 'cgi' +require File.expand_path(File.join(File.dirname(__FILE__), "..", "support", "paths")) + +module WithinHelpers + def with_scope(locator) + locator ? within(locator) { yield } : yield + end +end +World(WithinHelpers) + +Given /^(?:|I )am on (.+)$/ do |page_name| + visit path_to(page_name) +end + +When /^(?:|I )go to (.+)$/ do |page_name| + visit path_to(page_name) +end + +When /^(?:|I )press "([^"]*)"(?: within "([^"]*)")?$/ do |button, selector| + with_scope(selector) do + click_button(button) + end +end + +When /^(?:|I )follow "([^"]*)"(?: within "([^"]*)")?$/ do |link, selector| + with_scope(selector) do + click_link(link) + end +end + +When /^(?:|I )fill in "([^"]*)" with "([^"]*)"(?: within "([^"]*)")?$/ do |field, value, selector| + with_scope(selector) do + fill_in(field, :with => value) + end +end + +When /^(?:|I )fill in "([^"]*)" for "([^"]*)"(?: within "([^"]*)")?$/ do |value, field, selector| + with_scope(selector) do + fill_in(field, :with => value) + end +end + +# Use this to fill in an entire form with data from a table. Example: +# +# When I fill in the following: +# | Account Number | 5002 | +# | Expiry date | 2009-11-01 | +# | Note | Nice guy | +# | Wants Email? | | +# +# TODO: Add support for checkbox, select og option +# based on naming conventions. +# +When /^(?:|I )fill in the following(?: within "([^"]*)")?:$/ do |selector, fields| + with_scope(selector) do + fields.rows_hash.each do |name, value| + When %{I fill in "#{name}" with "#{value}"} + end + end +end + +When /^(?:|I )select "([^"]*)" from "([^"]*)"(?: within "([^"]*)")?$/ do |value, field, selector| + with_scope(selector) do + select(value, :from => field) + end +end + +When /^(?:|I )check "([^"]*)"(?: within "([^"]*)")?$/ do |field, selector| + with_scope(selector) do + check(field) + end +end + +When /^(?:|I )uncheck "([^"]*)"(?: within "([^"]*)")?$/ do |field, selector| + with_scope(selector) do + uncheck(field) + end +end + +When /^(?:|I )choose "([^"]*)"(?: within "([^"]*)")?$/ do |field, selector| + with_scope(selector) do + choose(field) + end +end + +When /^(?:|I )attach the file "([^"]*)" to "([^"]*)"(?: within "([^"]*)")?$/ do |path, field, selector| + with_scope(selector) do + attach_file(field, path) + end +end + +Then /^(?:|I )should see JSON:$/ do |expected_json| + require 'json' + expected = JSON.pretty_generate(JSON.parse(expected_json)) + actual = JSON.pretty_generate(JSON.parse(response.body)) + expected.should == actual +end + +Then /^(?:|I )should see "([^"]*)"(?: within "([^"]*)")?$/ do |text, selector| + with_scope(selector) do + if page.respond_to? :should + page.should have_content(text) + else + assert page.has_content?(text) + end + end +end + +Then /^(?:|I )should see \/([^\/]*)\/(?: within "([^"]*)")?$/ do |regexp, selector| + regexp = Regexp.new(regexp) + with_scope(selector) do + if page.respond_to? :should + page.should have_xpath('//*', :text => regexp) + else + assert page.has_xpath?('//*', :text => regexp) + end + end +end + +Then /^(?:|I )should not see "([^"]*)"(?: within "([^"]*)")?$/ do |text, selector| + with_scope(selector) do + if page.respond_to? :should + page.should have_no_content(text) + else + assert page.has_no_content?(text) + end + end +end + +Then /^(?:|I )should not see \/([^\/]*)\/(?: within "([^"]*)")?$/ do |regexp, selector| + regexp = Regexp.new(regexp) + with_scope(selector) do + if page.respond_to? :should + page.should have_no_xpath('//*', :text => regexp) + else + assert page.has_no_xpath?('//*', :text => regexp) + end + end +end + +Then /^the "([^"]*)" field(?: within "([^"]*)")? should contain "([^"]*)"$/ do |field, selector, value| + with_scope(selector) do + field = find_field(field) + field_value = (field.tag_name == 'textarea') ? field.text : field.value + if field_value.respond_to? :should + field_value.should =~ /#{value}/ + else + assert_match(/#{value}/, field_value) + end + end +end + +Then /^the "([^"]*)" field(?: within "([^"]*)")? should not contain "([^"]*)"$/ do |field, selector, value| + with_scope(selector) do + field = find_field(field) + field_value = (field.tag_name == 'textarea') ? field.text : field.value + if field_value.respond_to? :should_not + field_value.should_not =~ /#{value}/ + else + assert_no_match(/#{value}/, field_value) + end + end +end + +Then /^the "([^"]*)" checkbox(?: within "([^"]*)")? should be checked$/ do |label, selector| + with_scope(selector) do + field_checked = find_field(label)['checked'] + if field_checked.respond_to? :should + field_checked.should be_true + else + assert field_checked + end + end +end + +Then /^the "([^"]*)" checkbox(?: within "([^"]*)")? should not be checked$/ do |label, selector| + with_scope(selector) do + field_checked = find_field(label)['checked'] + if field_checked.respond_to? :should + field_checked.should be_false + else + assert !field_checked + end + end +end + +Then /^(?:|I )should be on (.+)$/ do |page_name| + current_path = URI.parse(current_url).path + if current_path.respond_to? :should + current_path.should == path_to(page_name) + else + assert_equal path_to(page_name), current_path + end +end + +Then /^(?:|I )should have the following query string:$/ do |expected_pairs| + query = URI.parse(current_url).query + actual_params = query ? CGI.parse(query) : {} + expected_params = {} + expected_pairs.rows_hash.each_pair{|k,v| expected_params[k] = v.split(',')} + + if actual_params.respond_to? :should + actual_params.should == expected_params + else + assert_equal expected_params, actual_params + end +end + +Then /^show me the page$/ do + save_and_open_page +end diff --git a/TryRuby/features/support/env.rb b/TryRuby/features/support/env.rb new file mode 100644 index 0000000..3333139 --- /dev/null +++ b/TryRuby/features/support/env.rb @@ -0,0 +1,57 @@ +# IMPORTANT: This file is generated by cucumber-rails - edit at your own peril. +# It is recommended to regenerate this file in the future when you upgrade to a +# newer version of cucumber-rails. Consider adding your own code to a new file +# instead of editing this one. Cucumber will automatically load all features/**/*.rb +# files. + +ENV["RAILS_ENV"] ||= "test" +require File.expand_path(File.dirname(__FILE__) + '/../../config/environment') + +require 'cucumber/formatter/unicode' # Remove this line if you don't want Cucumber Unicode support +require 'cucumber/rails/world' +require 'cucumber/rails/active_record' +require 'cucumber/web/tableish' + +require 'capybara/rails' +require 'capybara/cucumber' +require 'capybara/session' +require 'cucumber/rails/capybara_javascript_emulation' # Lets you click links with onclick javascript handlers without using @culerity or @javascript +# Capybara defaults to XPath selectors rather than Webrat's default of CSS3. In +# order to ease the transition to Capybara we set the default here. If you'd +# prefer to use XPath just remove this line and adjust any selectors in your +# steps to use the XPath syntax. +Capybara.default_selector = :css + +# If you set this to false, any error raised from within your app will bubble +# up to your step definition and out to cucumber unless you catch it somewhere +# on the way. You can make Rails rescue errors and render error pages on a +# per-scenario basis by tagging a scenario or feature with the @allow-rescue tag. +# +# If you set this to true, Rails will rescue all errors and render error +# pages, more or less in the same way your application would behave in the +# default production environment. It's not recommended to do this for all +# of your scenarios, as this makes it hard to discover errors in your application. +ActionController::Base.allow_rescue = false + +# If you set this to true, each scenario will run in a database transaction. +# You can still turn off transactions on a per-scenario basis, simply tagging +# a feature or scenario with the @no-txn tag. If you are using Capybara, +# tagging with @culerity or @javascript will also turn transactions off. +# +# If you set this to false, transactions will be off for all scenarios, +# regardless of whether you use @no-txn or not. +# +# Beware that turning transactions off will leave data in your database +# after each scenario, which can lead to hard-to-debug failures in +# subsequent scenarios. If you do this, we recommend you create a Before +# block that will explicitly put your database in a known state. +Cucumber::Rails::World.use_transactional_fixtures = true +# How to clean your database when transactions are turned off. See +# http://github.com/bmabey/database_cleaner for more info. +if defined?(ActiveRecord::Base) + begin + require 'database_cleaner' + DatabaseCleaner.strategy = :truncation + rescue LoadError => ignore_if_database_cleaner_not_present + end +end diff --git a/TryRuby/features/support/paths.rb b/TryRuby/features/support/paths.rb new file mode 100644 index 0000000..06b3efb --- /dev/null +++ b/TryRuby/features/support/paths.rb @@ -0,0 +1,33 @@ +module NavigationHelpers + # Maps a name to a path. Used by the + # + # When /^I go to (.+)$/ do |page_name| + # + # step definition in web_steps.rb + # + def path_to(page_name) + case page_name + + when /the home\s?page/ + '/' + + # Add more mappings here. + # Here is an example that pulls values out of the Regexp: + # + # when /^(.*)'s profile page$/i + # user_profile_path(User.find_by_login($1)) + + else + begin + page_name =~ /the (.*) page/ + path_components = $1.split(/\s+/) + self.send(path_components.push('path').join('_').to_sym) + rescue Object => e + raise "Can't find mapping from \"#{page_name}\" to a path.\n" + + "Now, go and add a mapping in #{__FILE__}" + end + end + end +end + +World(NavigationHelpers) diff --git a/TryRuby/lib/tasks/.gitkeep b/TryRuby/lib/tasks/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/TryRuby/lib/tasks/cucumber.rake b/TryRuby/lib/tasks/cucumber.rake new file mode 100644 index 0000000..7db1a55 --- /dev/null +++ b/TryRuby/lib/tasks/cucumber.rake @@ -0,0 +1,53 @@ +# IMPORTANT: This file is generated by cucumber-rails - edit at your own peril. +# It is recommended to regenerate this file in the future when you upgrade to a +# newer version of cucumber-rails. Consider adding your own code to a new file +# instead of editing this one. Cucumber will automatically load all features/**/*.rb +# files. + + +unless ARGV.any? {|a| a =~ /^gems/} # Don't load anything when running the gems:* tasks + +vendored_cucumber_bin = Dir["#{Rails.root}/vendor/{gems,plugins}/cucumber*/bin/cucumber"].first +$LOAD_PATH.unshift(File.dirname(vendored_cucumber_bin) + '/../lib') unless vendored_cucumber_bin.nil? + +begin + require 'cucumber/rake/task' + + namespace :cucumber do + Cucumber::Rake::Task.new({:ok => 'db:test:prepare'}, 'Run features that should pass') do |t| + t.binary = vendored_cucumber_bin # If nil, the gem's binary is used. + t.fork = true # You may get faster startup if you set this to false + t.profile = 'default' + end + + Cucumber::Rake::Task.new({:wip => 'db:test:prepare'}, 'Run features that are being worked on') do |t| + t.binary = vendored_cucumber_bin + t.fork = true # You may get faster startup if you set this to false + t.profile = 'wip' + end + + Cucumber::Rake::Task.new({:rerun => 'db:test:prepare'}, 'Record failing features and run only them if any exist') do |t| + t.binary = vendored_cucumber_bin + t.fork = true # You may get faster startup if you set this to false + t.profile = 'rerun' + end + + desc 'Run all features' + task :all => [:ok, :wip] + end + desc 'Alias for cucumber:ok' + task :cucumber => 'cucumber:ok' + + task :default => :cucumber + + task :features => :cucumber do + STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***" + end +rescue LoadError + desc 'cucumber rake task not available (cucumber not installed)' + task :cucumber do + abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin' + end +end + +end diff --git a/TryRuby/public/images/ajax-loader.gif b/TryRuby/public/images/ajax-loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..f2a1bc0c6f545e20e631a96e8e92f9822e75d046 GIT binary patch literal 673 zcmZ?wbhEHb6krfw_{6~Q|Nnmm28Kh24mmkF0U1e2Nli^nlO|14{3qpHl$uzQnxasi zS(2fUn3Y(Olb@KPmzkHA&!G5|g@FsGT=74*pKD04vtxj(k)8oFBTz^Oh=E26FfcG1 zbL_hF&)}42ws10s6^G;;cE1^EoUR)U5A70}d2pLv!jVIT7j&Z~EblI3x0K*v_sV|m z0W=b9G$XP(CLnYCdK49;TX=SFc-G}o=oA=|U?{1O;Nu!CwW3C5Yw7*Bi4yD$3fCnb zwK+>}QdQ9sf*QnxY>*kpE+b{_Q;sJloS71)&(@kO!}mqf@1v(v;*8Y=G9S3kY~Cw# zY=t&c z;3~JK4HxB^lY(MD+sYeQ=t%XSSW;x^1M?dTvN=W^yNcAcy`HCte31C;)5xP%b~qs> zDP&4(%TBqBNGHwnryK;BdMI$fEg xd0mc!C@j^ZpLxYv4HmnPfI0THYuv<%+6iSmMn&w3dPGDfL1|=LY008wP(boU~ literal 0 HcmV?d00001 diff --git a/TryRuby/public/images/closelabel.png b/TryRuby/public/images/closelabel.png new file mode 100755 index 0000000000000000000000000000000000000000..c339e59333e4c3b5bc5fd910796fda5469a2515f GIT binary patch literal 168 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5XygXeTLn>}1B_t#Wus+)Bu;yq3!!CzC+*<6@{_r1Jzd&eL zz_O}6Q6nrOf&;;F`V=YhW2-H5dcFFaTerms + * Loads the #terms div in the box + * + * Terms + * Loads the terms.html page in the box + * + * Terms + * Loads the terms.png image in the box + * + * + * You can also use it programmatically: + * + * jQuery.facebox('some html') + * jQuery.facebox('some html', 'my-groovy-style') + * + * The above will open a facebox with "some html" as the content. + * + * jQuery.facebox(function($) { + * $.get('blah.html', function(data) { $.facebox(data) }) + * }) + * + * The above will show a loading screen before the passed function is called, + * allowing for a better ajaxy experience. + * + * The facebox function can also display an ajax page, an image, or the contents of a div: + * + * jQuery.facebox({ ajax: 'remote.html' }) + * jQuery.facebox({ ajax: 'remote.html' }, 'my-groovy-style') + * jQuery.facebox({ image: 'stairs.jpg' }) + * jQuery.facebox({ image: 'stairs.jpg' }, 'my-groovy-style') + * jQuery.facebox({ div: '#box' }) + * jQuery.facebox({ div: '#box' }, 'my-groovy-style') + * + * Want to close the facebox? Trigger the 'close.facebox' document event: + * + * jQuery(document).trigger('close.facebox') + * + * Facebox also has a bunch of other hooks: + * + * loading.facebox + * beforeReveal.facebox + * reveal.facebox (aliased as 'afterReveal.facebox') + * init.facebox + * afterClose.facebox + * + * Simply bind a function to any of these hooks: + * + * $(document).bind('reveal.facebox', function() { ...stuff to do after the facebox and contents are revealed... }) + * + */ +(function($) { + $.facebox = function(data, klass) { + $.facebox.loading() + + if (data.ajax) fillFaceboxFromAjax(data.ajax, klass) + else if (data.image) fillFaceboxFromImage(data.image, klass) + else if (data.div) fillFaceboxFromHref(data.div, klass) + else if ($.isFunction(data)) data.call($) + else $.facebox.reveal(data, klass) + } + + /* + * Public, $.facebox methods + */ + + $.extend($.facebox, { + settings: { + opacity : 0.2, + overlay : true, + loadingImage : '/facebox/loading.gif', + closeImage : '/facebox/closelabel.png', + imageTypes : [ 'png', 'jpg', 'jpeg', 'gif' ], + faceboxHtml : '\ + ' + }, + + loading: function() { + init() + if ($('#facebox .loading').length == 1) return true + showOverlay() + + $('#facebox .content').empty() + $('#facebox .body').children().hide().end(). + append('
    ') + + $('#facebox').css({ + top: getPageScroll()[1] + (getPageHeight() / 10), + left: $(window).width() / 2 - 205 + }).show() + + $(document).bind('keydown.facebox', function(e) { + if (e.keyCode == 27) $.facebox.close() + return true + }) + $(document).trigger('loading.facebox') + }, + + reveal: function(data, klass) { + $(document).trigger('beforeReveal.facebox') + if (klass) $('#facebox .content').addClass(klass) + $('#facebox .content').append(data) + $('#facebox .loading').remove() + $('#facebox .body').children().fadeIn('normal') + $('#facebox').css('left', $(window).width() / 2 - ($('#facebox .popup').width() / 2)) + $(document).trigger('reveal.facebox').trigger('afterReveal.facebox') + }, + + close: function() { + $(document).trigger('close.facebox') + return false + } + }) + + /* + * Public, $.fn methods + */ + + $.fn.facebox = function(settings) { + if ($(this).length == 0) return + + init(settings) + + function clickHandler() { + $.facebox.loading(true) + + // support for rel="facebox.inline_popup" syntax, to add a class + // also supports deprecated "facebox[.inline_popup]" syntax + var klass = this.rel.match(/facebox\[?\.(\w+)\]?/) + if (klass) klass = klass[1] + + fillFaceboxFromHref(this.href, klass) + return false + } + + return this.bind('click.facebox', clickHandler) + } + + /* + * Private methods + */ + + // called one time to setup facebox on this page + function init(settings) { + if ($.facebox.settings.inited) return true + else $.facebox.settings.inited = true + + $(document).trigger('init.facebox') + makeCompatible() + + var imageTypes = $.facebox.settings.imageTypes.join('|') + $.facebox.settings.imageTypesRegexp = new RegExp('\.(' + imageTypes + ')$', 'i') + + if (settings) $.extend($.facebox.settings, settings) + $('body').append($.facebox.settings.faceboxHtml) + + var preload = [ new Image(), new Image() ] + preload[0].src = $.facebox.settings.closeImage + preload[1].src = $.facebox.settings.loadingImage + + $('#facebox').find('.b:first, .bl').each(function() { + preload.push(new Image()) + preload.slice(-1).src = $(this).css('background-image').replace(/url\((.+)\)/, '$1') + }) + + $('#facebox .close').click($.facebox.close) + $('#facebox .close_image').attr('src', $.facebox.settings.closeImage) + } + + // getPageScroll() by quirksmode.com + function getPageScroll() { + var xScroll, yScroll; + if (self.pageYOffset) { + yScroll = self.pageYOffset; + xScroll = self.pageXOffset; + } else if (document.documentElement && document.documentElement.scrollTop) { // Explorer 6 Strict + yScroll = document.documentElement.scrollTop; + xScroll = document.documentElement.scrollLeft; + } else if (document.body) {// all other Explorers + yScroll = document.body.scrollTop; + xScroll = document.body.scrollLeft; + } + return new Array(xScroll,yScroll) + } + + // Adapted from getPageSize() by quirksmode.com + function getPageHeight() { + var windowHeight + if (self.innerHeight) { // all except Explorer + windowHeight = self.innerHeight; + } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode + windowHeight = document.documentElement.clientHeight; + } else if (document.body) { // other Explorers + windowHeight = document.body.clientHeight; + } + return windowHeight + } + + // Backwards compatibility + function makeCompatible() { + var $s = $.facebox.settings + + $s.loadingImage = $s.loading_image || $s.loadingImage + $s.closeImage = $s.close_image || $s.closeImage + $s.imageTypes = $s.image_types || $s.imageTypes + $s.faceboxHtml = $s.facebox_html || $s.faceboxHtml + } + + // Figures out what you want to display and displays it + // formats are: + // div: #id + // image: blah.extension + // ajax: anything else + function fillFaceboxFromHref(href, klass) { + // div + if (href.match(/#/)) { + var url = window.location.href.split('#')[0] + var target = href.replace(url,'') + if (target == '#') return + $.facebox.reveal($(target).html(), klass) + + // image + } else if (href.match($.facebox.settings.imageTypesRegexp)) { + fillFaceboxFromImage(href, klass) + // ajax + } else { + fillFaceboxFromAjax(href, klass) + } + } + + function fillFaceboxFromImage(href, klass) { + var image = new Image() + image.onload = function() { + $.facebox.reveal('
    ', klass) + } + image.src = href + } + + function fillFaceboxFromAjax(href, klass) { + $.get(href, function(data) { $.facebox.reveal(data, klass) }) + } + + function skipOverlay() { + return $.facebox.settings.overlay == false || $.facebox.settings.opacity === null + } + + function showOverlay() { + if (skipOverlay()) return + + if ($('#facebox_overlay').length == 0) + $("body").append('
    ') + + $('#facebox_overlay').hide().addClass("facebox_overlayBG") + .css('opacity', $.facebox.settings.opacity) + .click(function() { $(document).trigger('close.facebox') }) + .fadeIn(200) + return false + } + + function hideOverlay() { + if (skipOverlay()) return + + $('#facebox_overlay').fadeOut(200, function(){ + $("#facebox_overlay").removeClass("facebox_overlayBG") + $("#facebox_overlay").addClass("facebox_hide") + $("#facebox_overlay").remove() + }) + + return false + } + + /* + * Bindings + */ + + $(document).bind('close.facebox', function() { + $(document).unbind('keydown.facebox') + $('#facebox').fadeOut(function() { + $('#facebox .content').removeClass().addClass('content') + $('#facebox .loading').remove() + $(document).trigger('afterClose.facebox') + }) + hideOverlay() + }) + +})(jQuery); diff --git a/TryRuby/public/javascripts/jQuery.irb.js b/TryRuby/public/javascripts/jQuery.irb.js new file mode 100644 index 0000000..765858d --- /dev/null +++ b/TryRuby/public/javascripts/jQuery.irb.js @@ -0,0 +1,1641 @@ +//Try Ruby 1.5 (defacto version Number) +// March 14 2011 + +// large parts of this file are lifted from Try Haskell ( which lifted parts from try ruby without copyright notice >:-/ ) + +// Thus it is fair to include the following banner if/until there is no try haskell code left/ only code that originally existed in try ruby in the +//first place. + + // Try Haskell 1.0.1 + // Tue Feb 23 18:34:48 GMT 2010 + // + // Copyright 2010 Chris Done. All rights reserved. + // + // Redistribution and use in source and binary forms, with or without + // modification, are permitted provided that the following conditions + // are met: + // + // 1. Redistributions of source code must retain the above + // copyright notice, this list of conditions and the following + // disclaimer. + // 2. Redistributions in binary form must reproduce the above + // copyright notice, this list of conditions and the following + // disclaimer in the documentation and/or other materials + // provided with the distribution. + // + // THIS SOFTWARE IS PROVIDED BY CHRIS DONE ``AS IS'' AND ANY EXPRESS + // OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + // ARE DISCLAIMED. IN NO EVENT SHALL CHRIS DONE OR CONTRIBUTORS BE + // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + // OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + // DAMAGE. + // The views and conclusions contained in the software and + // documentation are those of the authors and should not be + // interpreted as representing official policies, either expressed or + // implied, of Chris Done. + // + // TESTED ON + // Internet Explorer 6 + // Opera 10.01 + // Chromium 4.0.237.0 (Ubuntu build 31094) + // Firefox 3.5.8 + + //IOS 4.3 (all devices) + +// Temporary fix +function opera() { + return navigator.userAgent.indexOf("Opera") == 0; +} + +function encodeHex(str) { + var result = ""; + for (var i = 0; i < str.length; i++) { + result += "%" + pad(toHex(str.charCodeAt(i) & 0xff), 2, '0'); + } + return result; +} + +//var handleJSON = function(a){ alert('Unassigned JSONP: ' + a); } +var hexv = { + "00": 0, + "01": 1, + "02": 2, + "03": 3, + "04": 4, + "05": 5, + "06": 6, + "07": 7, + "08": 8, + "09": 9, + "0A": 10, + "0B": 11, + "0C": 12, + "0D": 13, + "0E": 14, + "0F": 15, + "10": 16, + "11": 17, + "12": 18, + "13": 19, + "14": 20, + "15": 21, + "16": 22, + "17": 23, + "18": 24, + "19": 25, + "1A": 26, + "1B": 27, + "1C": 28, + "1D": 29, + "1E": 30, + "1F": 31, + "20": 32, + "21": 33, + "22": 34, + "23": 35, + "24": 36, + "25": 37, + "26": 38, + "27": 39, + "28": 40, + "29": 41, + "2A": 42, + "2B": 43, + "2C": 44, + "2D": 45, + "2E": 46, + "2F": 47, + "30": 48, + "31": 49, + "32": 50, + "33": 51, + "34": 52, + "35": 53, + "36": 54, + "37": 55, + "38": 56, + "39": 57, + "3A": 58, + "3B": 59, + "3C": 60, + "3D": 61, + "3E": 62, + "3F": 63, + "40": 64, + "41": 65, + "42": 66, + "43": 67, + "44": 68, + "45": 69, + "46": 70, + "47": 71, + "48": 72, + "49": 73, + "4A": 74, + "4B": 75, + "4C": 76, + "4D": 77, + "4E": 78, + "4F": 79, + "50": 80, + "51": 81, + "52": 82, + "53": 83, + "54": 84, + "55": 85, + "56": 86, + "57": 87, + "58": 88, + "59": 89, + "5A": 90, + "5B": 91, + "5C": 92, + "5D": 93, + "5E": 94, + "5F": 95, + "60": 96, + "61": 97, + "62": 98, + "63": 99, + "64": 100, + "65": 101, + "66": 102, + "67": 103, + "68": 104, + "69": 105, + "6A": 106, + "6B": 107, + "6C": 108, + "6D": 109, + "6E": 110, + "6F": 111, + "70": 112, + "71": 113, + "72": 114, + "73": 115, + "74": 116, + "75": 117, + "76": 118, + "77": 119, + "78": 120, + "79": 121, + "7A": 122, + "7B": 123, + "7C": 124, + "7D": 125, + "7E": 126, + "7F": 127, + "80": 128, + "81": 129, + "82": 130, + "83": 131, + "84": 132, + "85": 133, + "86": 134, + "87": 135, + "88": 136, + "89": 137, + "8A": 138, + "8B": 139, + "8C": 140, + "8D": 141, + "8E": 142, + "8F": 143, + "90": 144, + "91": 145, + "92": 146, + "93": 147, + "94": 148, + "95": 149, + "96": 150, + "97": 151, + "98": 152, + "99": 153, + "9A": 154, + "9B": 155, + "9C": 156, + "9D": 157, + "9E": 158, + "9F": 159, + "A0": 160, + "A1": 161, + "A2": 162, + "A3": 163, + "A4": 164, + "A5": 165, + "A6": 166, + "A7": 167, + "A8": 168, + "A9": 169, + "AA": 170, + "AB": 171, + "AC": 172, + "AD": 173, + "AE": 174, + "AF": 175, + "B0": 176, + "B1": 177, + "B2": 178, + "B3": 179, + "B4": 180, + "B5": 181, + "B6": 182, + "B7": 183, + "B8": 184, + "B9": 185, + "BA": 186, + "BB": 187, + "BC": 188, + "BD": 189, + "BE": 190, + "BF": 191, + "C0": 192, + "C1": 193, + "C2": 194, + "C3": 195, + "C4": 196, + "C5": 197, + "C6": 198, + "C7": 199, + "C8": 200, + "C9": 201, + "CA": 202, + "CB": 203, + "CC": 204, + "CD": 205, + "CE": 206, + "CF": 207, + "D0": 208, + "D1": 209, + "D2": 210, + "D3": 211, + "D4": 212, + "D5": 213, + "D6": 214, + "D7": 215, + "D8": 216, + "D9": 217, + "DA": 218, + "DB": 219, + "DC": 220, + "DD": 221, + "DE": 222, + "DF": 223, + "E0": 224, + "E1": 225, + "E2": 226, + "E3": 227, + "E4": 228, + "E5": 229, + "E6": 230, + "E7": 231, + "E8": 232, + "E9": 233, + "EA": 234, + "EB": 235, + "EC": 236, + "ED": 237, + "EE": 238, + "EF": 239, + "F0": 240, + "F1": 241, + "F2": 242, + "F3": 243, + "F4": 244, + "F5": 245, + "F6": 246, + "F7": 247, + "F8": 248, + "F9": 249, + "FA": 250, + "FB": 251, + "FC": 252, + "FD": 253, + "FE": 254, + "FF": 255 +}; + +function pad(str, len, pad) { + var result = str; + for (var i = str.length; i < len; i++) { + result = pad + result; + } + return result; +} + +var digitArray = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'); + +function toHex(n) { + var result = '' + var start = true; + for (var i = 32; i > 0;) { + i -= 4; + var digit = (n >> i) & 0xf; + if (!start || digit != 0) { + start = false; + result += digitArray[digit]; + } + } + return (result == '' ? '0': result); +} + + (function($) { + var raphaelPaper; + var raphaelObjs; + var tutorialGuide; + + // I don't like this at all... I intend to make this pull via ajax from a key value data store. + var pages = + [ + //////////////////////////////////////////////////////////////////////// + // Lesson 1 + // Simple addition + { + lesson: 1, + title: 'Basics; numbers, strings, etc.', + guide: + '

    ' + rmsg(['Learning By Numbers', 'Music is Math', 'Back to Basics']) + + '

    ' + + "

    To kick off let's try some maths out. Up there you can" + + " type in Haskell expressions. Try this out: 5 + 7

    " + }, + { + guide: function(result) { + if (!result) result = { + expr: '5+7', + result: 12 + }; + var complied = result.expr.replace(/ /g, '') == "5+7"; + var who = complied ? 'we': 'you'; + return '

    ' + rmsg(['Your first Haskell expression', + "First Time's a Charm"]) + '

    ' + + '

    Well done, you typed it perfect! You got back the number' + + ' ' + result.result + '. Just what ' + who + ' wanted. ' + + "

    Let's try something completely different." + + " Type in your name like this:" + + ' "chris"

    ' + }, + trigger: function(result) { + return result.type == "(Num t) => t" || + result.type == "Integer" || + result.type == "Int"; + } + }, + // Strings & types + { + guide: function(result) { + if (!result) result = { + expr: '"chris"', + result: "\"chris\"" + }; + var n = unString(result.result); + if (n) n = ", " + n; + n += "!"; + return '

    ' + rmsg(['Types of values', "What's in a name?"]) + + '

    ' + + '

    Hi there' + htmlEncode(n) + + (n != "!" ? " That's a pretty name. Honest.": "") + + " You're getting the hang of this!

    " + + "

    Note: You can chat to Haskell programmers while learning here, enter chat to start it." + + " You will join the official IRC channel of the Haskell community!

    " + + "

    Each time, you're getting back the value of the expression. So " + + "far, just a number and a list of characters.

    " + + "

    You can have lists of other stuff, too. Let's see your " + + " lottery numbers: [42,13,22]

    " + }, + trigger: function(result) { + return result.type == "[Char]" + || result.type == "String"; + } + }, + // Overview of lesson 1 + { + guide: function(result) { + if (!result) result = { + result: "[42,13,22]" + }; + return '

    ' + rmsg(["Lesson 1 done already!"]) + + '

    ' + + "

    Great, you made a list of numbers! If you win we'll split" + + " the winnings, right?

    " + + "

    Let's see what you've learned so far:

    " + + "
      " + + "
    1. How to write maths and lists of things.
    2. " + + "
    " + + "

    You can do stuff with lists. Maybe you want the lottery " + + "numbers sorted in the right order, try this: " + + "sort " + result.result + "

    " + }, + trigger: function(result) { + return result.expr.match(/^[ ]*\[[0-9, ]+\][ ]*$/) && + result.type == "(Num t) => [t]"; + } + }, + /////////////////////////////////////////////////////////////////////// + // Lesson 2 - Functions + // Functions on lists + { + lesson: 2, + title: 'Simple Functions', + guide: function(result) { + if (!result) result = { + result: "[13,23,30]" + }; + return '

    ' + rmsg(["We put the funk in function"]) + + '

    ' + + "

    Congratulations, you just used a function." + + " They're how you get things done in Haskell." + + "

    As you might've guessed, we got back " + + htmlEncode(result.result) + + ".

    Ever wanted an evil twin nemesis? Me too. " + + "Luckily, you can sort lists of characters, or " + + "strings" + + ", in the same way as numbers! sort \"chris\"

    " + }, + trigger: function(result) { + return result.expr.match(/sort/) && + result.type == "(Num t, Ord t) => [t]"; + } + }, + // Tuples + { + guide: function(result) { + if (!result) result = { + result: "\"chirs\"" + }; + nemesis = htmlEncode(unString(result.result)); + return '

    ' + + rmsg(["Tuples, because sometimes one value ain't enough!"]) + + '

    ' + + "

    Watch out for " + nemesis + "! You should keep their credentials for the police.

    " + + "

    My nemesis is 28 years of age: " + + "(28,\"chirs\")

    " + }, + trigger: function(result) { + return result.expr.match(/sort/) && + result.type == "[Char]"; + } + }, + // Functions on tuples + { + guide: function(result) { + if (!result) result = { + result: "(28,\"chirs\")" + }; + var age = result.result.match(/^\(([0-9]+)+/); + var villain = htmlEncode(result.result.replace(/\\"/g, '"')); + return '

    ' + + rmsg(["We'll keep them safe, don't worry about it."]) + + '

    ' + + "

    Is " + (age ? age[1] : "that") + " a normal age for a " + + "super-villain?

    " + + "

    You just wrote a tuple. It's a way to keep a bunch of values together in Haskell. " + + "You can put as many as you like in there:

    " + + "
    • (1,\"hats\",23/35)
    • (\"Shaggy\",\"Daphnie\",\"Velma\")
    " + + "

    Actually, let's say our villain is " + + "" + villain + "" + + ", how do you get their age?

    " + + "fst " + villain + "" + }, + trigger: function(result) { + return result.expr.match(/\([0-9]+,[ ]*"[^"]+"\)/) && + result.type == "(Num t) => (t, [Char])"; + } + }, + // Summary of lesson 2 + { + guide: function(result) { + return '

    ' + + rmsg(["Lesson 2 done! Wow, great job!", + "Lesson 2 completo!"]) + + '

    ' + + + "

    Good job! You got the age back from the tuple! Didn't " + + " even break a sweat, did you? The fst function " + + "just gets the first value. It's called \"fst\" because " + + "it's used a lot in Haskell so it really needs to be short!

    " + + + "

    Time to take a rest and see what you learned:

    " + + "
      " + + "
    1. Functions can be used on lists of any type.
    2. " + + "
    3. We can stuff values into tuples.
    4. " + + "
    5. Getting the values back from tuples is easy.
    6. " + + "
    " + + + "

    Now let's say you want " + + " to use a value more than once, how would you do it? " + + "To make our lives easier, we can say:

    " + + + "let x = 4 in x * x" + }, + trigger: function(result) { + return result.expr.match(/fst/) && + result.type == "(Num t) => t"; + } + }, + { + guide: function(result) { + return "

    Let them eat cake

    " + + + "

    You just bound a variable. " + + "That is, you bound x to the expression 4, " + + " and then you can write x in some code (the body) and " + + " it will mean the same as if you'd written 4.

    " + + + "

    It's like this: let var = expression in body

    " + + + "The in part just separates the expression from the body.

    " + + + "

    For example try: " + + "let x = 8 * 10 in x + x

    " + + + "

    So if we wanted to get the age of our villain, we could do:

    " + + + "let villain = (28,\"chirs\") in fst villain" + + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]+x[ ]*=[ ]*[0-9]+[ ]*in[ ]*x[ ]*\*[ ]*x/) && + result.type == "(Num t) => t"; + } + }, + { + guide: function(result) { + return "

    Basics over, let's go!

    " + + "

    Next, let's take a short detour to learn about " + + "syntactic sugar. " + + "Try typing this out:

    " + + "

    'a' : []

    " + + "

    Or skip to lesson4 to learn about functions," + + " the meat of Haskell!"; + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]+villain[ ]*=[ ]*\([0-9]+,[ ]*"[^"]+"\)[ ]*in[ ]+fst[ ]+villain[ ]*/) && + result.type == "(Num t) => t"; + } + }, + // Lesson 3: Syntactic sugar + { + lesson: 3, + title: 'Syntactic Sugar', + guide: function(result) { + return '

    ' + + rmsg(["You constructed a list!"]) + + '

    ' + + "

    Well done, that was tricky syntax. You used the (:) " + + "function. It takes two values, some value and a list, and " + + " constructs a new list" + + " out of them. We call it 'cons' for short.

    " + + "

    'a' is " + + "the character 'a', [] is an empty list. So " + + "tacking 'a' at the start of an empty list just " + + "makes a list ['a']!

    " + + "

    But thankfully we don't have to type out " + + "'a' : 'b' : [] every time to we want to make a " + + "list of characters; we can use " + + "syntactic sugar and just write" + + " ['a','b']. Don't believe me, check this!

    " + + "'a' : 'b' : [] == ['a','b']" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*'a'[ ]*:[ ]*\[\][ ]*/) && + result.type == "[Char]"; + } + }, + // Booleans and string syntactic sugar + { + guide: function(result) { + return '

    ' + + rmsg(["You're on fire!"]) + + '

    ' + + "

    You're handling this syntax really well, nice!

    " + + "

    You just got a boolean value back, and it said " + + "True. That means they're equal!

    " + + "

    One final demonstration on syntactic sugar for now:

    " + + "['a','b','c'] == \"abc\"" + }, + trigger: function(result) { + return result.type == "Bool" && + result.expr.replace(/[^':\[\]\=,]/g, '') == "'':'':[]==['','']"; + } + }, + // Summary of syntactic sugar section + { + guide: function(result) { + return '

    ' + + rmsg(["Lesson 3 over! Syntactic sugar is sweet"]) + + '

    ' + + "

    Let's have a gander at what you learned:

    " + + "
      " + + "
    1. In 'a' : [], : is really just " + + " another function, just clever looking.
    2. " + + "
    3. Pretty functions like this are written like (:) when " + + " you talk about them.
    4. " + + "
    5. A list of characters ['a','b'] can just be written " + + "\"ab\". Much easier!
    6. " + + "
    " + + "

    Phew! You're getting pretty deep! Your arch nemesis, " + + nemesis + ", is gonna try to steal your " + rmsg(['mojo', + 'pizza']) + + "! Let's learn a bit more about functions and passing " + + "them around. Try this:

    map (+1) [1..5]

    "; + }, + trigger: function(result) { + return result.expr.replace(/[^\]\[',=\"]?/g, '') == "['','','']==\"\"" && + result.type == "Bool"; + } + }, + { + lesson: 4, + title: 'Functions, reloaded; passing, defining, etc.', + guide: function() { + var title = + rmsg(["Functions [of a Geisha]", + "Functions, functors, functoids, funky", + "Functions: Expanded fo' real"]); + return "

    " + title + "

    " + + + "

    Here's where the magic begins!

    " + + + "

    You just passed the (+1) " + + "function to the map function.

    " + + + "

    You can try other things like (remember: click to insert them):

    " + + + "
      " + + "
    • map (*99) [1..10]
    • " + + "
    • map (/5) [13,24,52,42]
    • " + + "
    • filter (>5) [62,3,25,7,1,9]
    • " + + "
    " + + + "

    Note that a tuple is different to a list because you can do this:

    " + + "(1,\"George\")" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*map[ ]+\(\+1\)[ ]*\[1..5\][ ]*$/) && + result.type == "(Num a, Enum a) => [a]"; + } + }, + { + guide: function(result) { + return "

    Lists and Tuples

    " + + + "

    You can only " + + " have a list of numbers or a list of characters, whereas in a tuple you can throw anything in!

    " + + + "

    We've also seen that you can make a new list with (:) that joins two values together, like:

    " + + "

    1 : [2,3]

    " + + + "

    But we can't do this with tuples! You can only write a tuple and then look at what's inside. You can't make new ones on the fly like a list." + + + "

    Let's write our own functions! It's really easy. How about something simple:

    " + + "let square x = x * x in square " + rmsg([52, 10, 3]) + "" + + }, + trigger: function(result) { + return result.expr.match(/^[ ]*\(1,"[^"]+"\)[ ]*$/) && + result.type == "(Num t) => (t, [Char])"; + } + }, + { + guide: function(result) { + return "

    Let there be functions

    " + + "

    Nice one! I think you're getting used to the let syntax.

    " + + "

    You defined a function. You can read it as, as for a given " + + "parameter called x, square of " + + "x is x * x." + + "

    Some others you can try are:

    " + + "
    • let add1 x = x + 1 in add1 5
    • " + + "
    • let second x = snd x in second (3,4)
    • " + + "
    " + + "

    Let's go crazy and use our square function with map:

    " + + "let square x = x * x in map square [1..10]" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]*square[ ]+x[ ]*=[ ]*x[ ]*\*[ ]*x[ ]*in[ ]*square[ ]+[0-9]+/) && + result.type == "(Num t) => t"; + } + }, + { + guide: function(result) { + if (!result || !result.value) result = { + value: "[1,4,9,16,25,36,49,64,81,100]" + }; + return "

    Let there be functions

    " + + + "

    That's so cool! You described a simple function square and then " + + "you just passed it to another function (map) and got back " + + htmlEncode(result.value) + ", exactly what you expected!

    " + + + "

    Haskell is pretty good at composing things together like this. " + + "Some other things you can try are:

    " + + + "
      " + + "
    • let add1 x = x + 1 in map add1 [1,5,7]
    • " + + "
    • let take5s = filter (==5) in take5s [1,5,2,5,3,5]
    • " + + "
    • let take5s = filter (==5) in map take5s [[1,5],[5],[1,1]]
    • " + + "
    " + + + "

    Did you get back what you expected?

    " + + + "

    One more example for text; how do you upcase a letter?

    " + + + "

    toUpper 'a'

    " + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]+square[ ]+x[ ]*=[ ]*x[ ]*\*[ ]*x[ ]*in[ ]+map[ ]+square[ ]*\[1..10\][ ]*$/) && + result.type == "(Num a, Enum a) => [a]"; + } + }, + { + guide: function(result) { + return "

    Exercise time!

    " + + + "

    Easy! Remember: characters are written like 'a' and " + + "strings (lists of characters) are written like \"a\"." + + + "

    I need you to use toUpper capitalise my whole name, " + + "\"Chris\". Give it a try." + + " You can do it, I believe in you!

    " + + + '

    Spoiler: map toUpper "Chris"

    ' + }, + trigger: function(result) { + return result.expr.match(/^toUpper 'a'$/) && + result.type == "Char"; + } + }, + { + guide: function(result) { + return "

    Lesson 4 complete!

    " + + + "

    Brilliant! You're making excellent progress! " + + "You just passed toUpper to map. No problem.

    " + + + "

    Let's go over what you've learned in this lesson:

    " + + + "
      " + + "
    1. Functions like map take other functions as parameters.
    2. " + + "
    3. Functions like (+1), (>5) and " + + "square can be passed to other functions.
    4. " + + "
    5. Defining functions is just a case of writing what " + + "to do with the parameters.
    6. " + "
    " + + + "

    Let's check out pattern matching; a way to " + + "get values from other values using patterns. Try this:

    " + + "

    let (a,b) = (10,12) in a * 2

    " + + + "

    Or you can skip this section and go to straight to lesson6; types!

    " + }, + trigger: function(result) { + return result.type == "[Char]" && + result.expr.match(/^map[ ]+toUpper/); + } + }, + { + lesson: 5, + title: 'Pattern Matching', + guide: function(result) { + var title = + rmsg(["And therefore, patterns emerge in nature.", + "And Then Patterns", + "Pattern matching!"]) + return "

    " + title + "

    " + + + "

    Jolly good show!

    " + + "

    So you had a value (10,12) and matched " + + "it against a pattern (a,b), then you were able" + + " to do stuff with the a and b!" + + + "

    Note: Pattern matching (a,b) against " + + "(1,2) to get the a is the same as" + + " doing fst (1,2), like you did in step7!

    " + + + "

    A pattern always matches the way the " + + "value was originally constructed. Remember that \"abc\" is " + + "syntactic sugar for 'a' : 'b' : 'c' : [].

    " + + + "

    So you can get the characters from a string with patterns:

    " + + + "let (a:b:c:[]) = \"xyz\" in a" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]+\(a,b\)[ ]+=[ ]+\(10,12\)[ ]+in[ ]+a[ ]*\*[ ]*2[ ]*$/) && + result.type == "(Num t) => t"; + } + }, + { + guide: function(result) { + return "

    " + rmsg(["Ignorance is bliss", "Ignoring values"]) + "

    " + + + "

    You're getting into tricky syntax, huh? I know you can handle it!

    " + + + "

    If you just want some of the values, you can ignore the others with _ (underscore) like this:

    " + + + "

    let (a:_:_:_) = \"xyz\" in a

    " + + + "

    In fact, (a:b:c:d) is short-hand for " + + "(a:(b:(c:d))), so you can just ignore the rest in one go:

    " + + + "let (a:_) = \"xyz\" in a" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]+\(a:b:c:\[\]\)[ ]*=[ ]*\"xyz\"[ ]*in[ ]+a[ ]*$/) && + result.type == "Char"; + } + }, + { + guide: function(result) { + return "

    " + rmsg(["Exercise!", "Show me the money!"]) + "

    " + + + "

    Try to get the 'a' value from this value using pattern matching:

    " + + "

    (10,\"abc\")

    " + + + "

    Spoiler: let (_,(a:_)) = (10,\"abc\") in a

    " + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]*\(a:_\)[ ]*=[ ]*"xyz"[ ]*in[ ]*a[ ]*$/) && + result.type == "Char"; + } + }, + { + guide: function(result) { + return "

    " + rmsg(["Well done!", "Brilliant!", "Perfetto!"]) + "

    " + + + "

    Wizard! I think you've got pattern-matching down.

    " + + + "

    If you're still a bit unsure, here are some other things you can try:

    " + + + "
      " + + "
    • let _:_:c:_ = \"abcd\" in c
    • " + + "
    • let [a,b,c] = \"cat\" in (a,b,c)
    • " + + "
    " + + + "

    You can also grab a whole value and pattern match on it (have your cake and eat it too):

    " + + + "let abc@(a,b,c) = (10,20,30) in (abc,a,b,c)" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]*\(_,\(?a:_\)?\)[ ]*=[ ]*\(10,\"abc\"\)[ ]*in[ ]*a[ ]*$/) && + result.type == "Char"; + } + }, + { + guide: function(result) { + return "

    " + rmsg(["And that's the end of that chapter"]) + "

    " + + + "

    That was easy, right?

    " + + + "

    Let's go over what you've learned in this lesson:

    " + + + "
      " + + "
    1. Values are pattern matched, or deconstructed, by writing however they were constructed.
    2. " + + "
    3. Patterns let you use the values that you match.
    4. " + + "
    5. You can ignore whichever values you want.
    6. " + + "
    7. You can pattern match and keep hold of the original value too.
    8. " + + "
    " + + + "

    Now we get to the Deep Ones. Types!

    " + + + "

    Consider the following value: 'a'

    " + + }, + trigger: function(result) { + return result.type == "(Num t, Num t1, Num t2) => ((t, t1, t2), t, t1, t2)"; + } + }, + { + lesson: 6, + title: 'Types', + guide: function(result) { + showTypes = true; + return "

    " + rmsg(["Types", "What's in a Type?", "Types & Values"]) + "

    " + + "

    What's this? Something new!

    " + + + "

    In Haskell there are types of values. Every value belongs to a type. To demonstrate this fact, I've sneakily enabled types to be " + + "shown of every value in the console from now on.

    " + + + "

    The type of the value 'a' is Char (short for 'character', but you guessed that, right?).

    " + + + "

    You've seen the type of a character, now what about" + + " a list of characters?

    " + + "\"Spartacus\"" + }, + trigger: function(result) { + return result.type == 'Char'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

    " + rmsg(["Lists of stuff, types"]) + "

    " + + + "

    I'm Spartacus!

    " + + + "

    Okay, so a list of characters has type [Char].

    " + + + "

    Notice that when we write a :: X it means the value a has type X. It's just a short-hand called a signature.

    " + + + "

    If you just want the type of a value, without actually evaluating it, you can just type:

    " + + ":t toUpper" + }, + trigger: function(result) { + return result.expr.match(/"[^"]+"/) && + result.type == '[Char]'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

    " + rmsg(["Function types"]) + "

    " + + + "

    Woah! Hold your blinkin' 'orses! The type of toUpper reads: Char -> Char

    " + + + "

    It's pretty easy; a -> b means function from a to b. " + + "So

    toUpper :: Char -> Char means: for a" + + " given character (Char value) a, toUpper a has type Char.

    " + + + "

    Some other things you can try are:

    " + + + "
    • :t words
    • " + + "
    • :t unwords
    • " + + "
    • :t True
    • " + + "
    • :t not
    • " + + "
    " + + + "

    The words function is pretty handy. Want to get a list of words from a sentence?

    " + + "words \"There's jam in my pants.\"" + }, + trigger: function(result) { + return result.type == 'Char -> Char'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

    " + rmsg(["Mid-way review"]) + "

    " + + + "

    The type of words was String -> [String]. You got a list of strings back! Just what you expected, right?

    " + + + "

    Let's take a rest in the middle of this lesson and go over what we've learned:

    " + + + "
      " + + "
    1. All values in Haskell have a type. We describe the types of values with signatures, like True :: Bool.
    2. " + + "
    3. Functions are values too, and they have types, notated a -> b.
    4. " + + "
    5. Functions can be defined for any type to any other type.
    6. " + + "
    7. Humble reader has a thing for jammy pants.
    8. " + + "
    " + + + "

    But what if you have a type that can contain values of any type, like a tuple?

    " + + ":t fst" + + }, + trigger: function(result) { + return result.expr.match(/^[ ]*words[ ]*\"[^"]+\"[ ]*$/) && + result.type == '[String]'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

    " + rmsg(["Polymorphic functions"]) + "

    " + + + "

    Remember this one? I know you do! fst (1,2) is 1, right?

    " + + "

    We read its type

    " + + "

    fst :: (a, b) -> a

    " + + "

    as: for all types a and b, the fst has type (a,b) to a. So the fst " + + "function works on a pair of values of any types! We call such a function polymorphic." + + "

    " + + "

    Remember the drop function? Maybe you don't. I don't! Let's check out its type:

    " + + "

    :t drop

    " + }, + trigger: function(result) { + return result.type == '(a, b) -> a'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

    " + rmsg(["Multi parameter functions"]) + "

    " + + + "

    So the drop function has type

    Int -> [a] -> [a].

    " + + + "

    This is something new. You've got two arrows! Relax. You can read

    " + + "

    a -> b -> c as a -> (b -> c)

    " + + + "

    In other words, drop is a function from integers (Int values) to functions of lists to lists ([a] -> [a] values). Drop is a function to another function.

    " + + + "

    Check for yourself! :t drop 3

    " + }, + trigger: function(result) { + return result.type == 'Int -> [a] -> [a]'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

    " + rmsg(["Partial application"]) + "

    " + + + "

    You've got a function of type [a] -> [a]! The drop function is considered a multi-parameter function. Remember the map function? Its parameters were a function and a list. Just another multi-parameter function.

    " + + + "

    You can add another parameter and, hey presto, you get a list!

    " + + + "drop 3 \"hello!\"" + + }, + trigger: function(result) { + return result.type == '[a] -> [a]'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

    " + rmsg(["Higher order functions"]) + "

    " + + + "

    'Lo bob! You've already used the map function loads. I wonder if you can guess its type?

    " + + + "

    map :: (a -> b) -> [a] -> [b] (spoiler)

    " + + + "

    It's okay to peek! Have a go at guessing these: filter, take

    " + + + "

    Tip: You can use parantheses to use more than one function. You want to double all the numbers over five? Psch!

    " + + "map (*2) (filter (>5) [10,2,16,9,4])" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*drop[ ]*[0-9]+[ ]*"[^"]+"[ ]*$/) && + result.type == '[Char]'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

    " + rmsg(["Phew! Rest time!"]) + "

    " + + + "

    Wow! You're doing so great! Have a look at what you know now!

    " + + + "
      " + + "
    1. Function parameters can be polymorphic; any type!
    2. " + + "
    3. Functions can have multiple parameters by returning more functions.
    4. " + + "
    5. You can wrap expressions in parentheses and apply functions to them as a whole value.
    6. " + + "
    " + + + "

    You're really making great progress. Don't hesitate to sit and play in the console between chapters to get a good feel of it!

    " + + + "

    Stay tuned for more chapters on type classes and the meaning of :t 1, :t (*), etc.

    " + + learnMore + }, + trigger: function(result) { + return result.type == '(Num a, Ord a) => [a]'; + } + } + ]; + // + // var webchat; + // + // function runWebchat() { + // if (!webchat) { + // // Create webchat frame + // var webchat = + // $(''); + // webchat.attr('width', 635); + // webchat.attr('height', 500); + // webchat.css('float', 'left'); + // webchat.css('webkit-border-radius', '3px'); + // webchat.css('moz-border-radius', '3px'); + // webchat.css('border-radius', '3px'); + // webchat.css('border', '5px solid #eeeeee'); + // + // // Extend page wrap to fit console and chat + // $('.page-wrap').css({ + // width: '1250px' + // }); + // $('.primary-content').css('margin-left', 0); + // $('.page-wrap').append(webchat.css('margin-left', '5px')); + // } + // } + + var pageTrigger = -1; + var notices = []; + var controller; + // Console controller + var learnMore; + + //////////////////////////////////////////////////////////////////////// + // Unshow a string + function unString(str) { + return str.replace(/^"(.*)"$/, "$1").replace(/\\"/, '"'); + } + + //////////////////////////////////////////////////////////////////////// + // Random message from a list of messages + function rmsg(choices) { + return choices[Math.floor((Math.random() * 100) % choices.length)]; + } + + // Simple HTML encoding + // Simply replace '<', '>' and '&' + // TODO: Use jQuery's .html() trick, or grab a proper, fast + // HTML encoder. + function htmlEncode(text, shy) { + return ( + ('' + text).replace(/&/g, '&') + .replace(/'); + handleJSON = function(r) { + script.remove(); + func(r); + }; + script.attr('src', url); + $('body').append(script); + } + + + var console = $('.console'); + controller = console.console({ + promptLabel: '> ', + continuedPromptLabel: ' .. ', /*not quiet right but good enough*/ + cancelHandle: function() { + controller.commandRef.ignore = true; + controller.finishCommand(); + controller.report(); + }, + + commandHandle: function(line, report) { + + controller.ajaxloader = $('

    Loading...

    '); + var commandRef = {}; + controller.currentLine = line; + controller.commandRef = commandRef; + controller.report = report; + if (tellAboutRet) tellAboutRet.fadeOut(function() { + $(this).remove(); + }); + + if (libTrigger(line, report)) return; + controller.inner.append(controller.ajaxloader); + controller.scrollToBottom(); + + jsonp("http://localhost:3030/tryruby/run/?cmd=" + encodeHex(line), + function(resp) { + if (commandRef.ignore) { + return; + } + controller.finishCommand(); + var result = resp; + if (pageTrigger > -1 && result.expr) { + triggerTutorialPage(pageTrigger, result); + } + if (result.type) { + if (pageTrigger == 24) showTypes = false; + handleSuccess(report, result); + } else if (result.error) { + report( + [{ + msg: result.error, + className: "jquery-console-message-error jquery-console-message-compile-error" + }] + ); + notice('compile-error', + "A compile-time error! " + + "It just means the expression wasn't quite right. " + + "Try again.", + 'prompt'); + } else if (result.exception) { + var err = limitsError(result.exception); + report( + [{ + msg: err, + className: "jquery-console-message-error jquery-console-message-exception" + }] + ); + if (err == result.exception) { + notice('compile-error', + "A run-time error! The expression was right but the" + + " result didn't make sense. Check your expression and try again.", + 'prompt'); + } + } else if (result.internal) { + report( + [{ + msg: limitsError(result.internal), + className: "jquery-console-message-error jquery-console-message-internal" + }] + ); + } else if (result.bind) { + report(); + } else if (result.result) { + if (result.expr.match(/^:modules/)) { + report( + [{ + msg: result.result.replace(/[\["\]]/g, '') + .replace(/,/g, ', '), + className: "jquery-console-message-type" + }]); + } + } + }); + + }, + + charInsertTrigger: function() { + var t = notice('tellaboutreturn', + "Hit Return when you're " + + "finished typing your expression."); + if (t) tellAboutRet = t; + return true; + }, + autofocus: true, + promptHistory: true, + historyPreserveColumn: true, + welcomeMessage: 'Interactive ruby ready' + }); + + controller.finishCommand = function() { + controller.ajaxloader.remove(); + $('.jquery-console-prompt :last').each(function() { + lastLine = controller.currentLine; + if (!$(this).hasClass('prompt-done')) { + $(this).addClass('prompt-done'); + $(this).click(function() { + controller.promptText(controller.currentLine); + }); + } + }); + } + + makeGuidSamplesClickable(); + + var match = window.location.href.match(/#([0-9]+)$/); + if (match) { + pageTrigger = match[1] - 1; + setTutorialPage(undefined, match[1] - 1); + } + + var match = window.location.href.match(/\?input=([^&]+)/); + if (match) { + controller.promptText(urlDecode(match[1])); + controller.inner.click(); + controller.typer.consoleControl(13); + } + }); + + function urlDecode(encodedString) { + var output = encodedString; + var binVal, + thisString; + var myregexp = /(%[^%]{2})/; + while ((match = myregexp.exec(output)) != null + && match.length > 1 + && match[1] != '') { + binVal = parseInt(match[1].substr(1), 16); + thisString = String.fromCharCode(binVal); + output = output.replace(match[1], thisString); + } + return output; + } + + function makeGuidSamplesClickable() { + $('.chapmark code').each(function() { + $(this).css('cursor', 'pointer'); + $(this).attr('title', 'Click me to insert "' + + $(this).text() + '" into the console.'); + $(this).click(function() { + controller.promptText($(this).text()); + controller.inner.click(); + }); + }); + } + + String.prototype.trim = function() { + return this.replace(/^[\t ]*(.*)[\t ]*$/, '$1'); + }; + + //////////////////////////////////////////////////////////////////////// + // Trigger console commands + function libTrigger(line, report) { + switch (line.trim()) { + case 'help': + { + setTutorialPage(undefined, 0); + report(); + pageTrigger = 0; + return true; + } + case 'back': + { + if (pageTrigger > 0) { + setTutorialPage(undefined, pageTrigger - 1); + pageTrigger--; + report(); + return true; + } + break; + } + case 'lessons': + { + var lessons = $('
      '); + for (var i = 0; i < pages.length; i++) { + if (pages[i].lesson) { + lessons.append($('
    1. '). + html('lesson' + pages[i].lesson + ' - ' + + pages[i].title)); + } + } + var lessonsList = '

      Lessons

      ' + lessons.html(); + tutorialGuide.animate({ + opacity: 0, + height: 0 + }, + 'fast', + function() { + tutorialGuide.html(lessonsList); + tutorialGuide.css({ + height: 'auto' + }); + tutorialGuide.animate({ + opacity: 1 + }, + 'fast'); + makeGuidSamplesClickable(); + }); + report(); + return true; + } + default: + { + if (line.trim() == 'chat') { + notice('irc', + 'Enter your nick on the right hand side and hit Connect!', + 'prompt'); + report(); + runWebchat(); + return true; + } + + var m = line.trim().match(/^link(.*)/); + if (m) { + var data; + if (m[1]) data = m[1].trim(); + else if (lastLine) data = lastLine; + if (data) { + var addr = '?input=' + encodeHex(data); + report([{ + msg: '', + className: 'latest-link' + }]); + var link = $(''). + text('link for ' + data).click(function() { + window.location.href = $(this).attr('href'); + return false; + }); + $('.latest-link').html(link).removeClass('latest-link'); + return true; + } + } + + var m = line.trim().match(/^step([0-9]+)/); + if (m) { + if ((m[1] * 1) <= pages.length) { + setTutorialPage(undefined, m[1] - 1); + report(); + pageTrigger = m[1] - 1; + return true; + } + } + var m = line.trim().match(/^help ([0-9]+)/); + if (m) { + for (var i = 0; i < pages.length; i++) { + if (pages[i].lesson == m[1] * 1) { + setTutorialPage(undefined, i); + report(); + pageTrigger = i; + return true; + } + } + } + } + }; + }; + + //////////////////////////////////////////////////////////////////////// + // Change the tutorial page + function setTutorialPage(result, n) { + if (pages[n]) { + window.location.href = '#' + (1 * n + 1); + tutorialGuide.find('#helpstone').remove(); + tutorialGuide.animate({ + opacity: 0, + height: 0 + }, + 'fast', + function() { + if (typeof(pages[n].guide) == 'function') + tutorialGuide.html(pages[n].guide(result)); + else + tutorialGuide.html(pages[n].guide); + var back = ''; + if (pageTrigger > 0) + back = 'You\'re at step' + (n + 1) + + '. Type back to go back.'; + else + back = 'You\'re at step' + (n + 1) + '. Type step' + (n + 1) + + ' to return here.'; + if (true) tutorialGuide + .append('
      ' + back + '
      ') + .append('
      Lesson: ' + + searchLessonBack(n) + + '
      '); + tutorialGuide.css({ + height: 'auto' + }); + tutorialGuide.animate({ + opacity: 1 + }, + 'fast'); + makeGuidSamplesClickable(); + }); + } + }; + + function searchLessonBack(page) { + for (var i = page; i >= 0; i--) { + if (pages[i].lesson) return pages[i].lesson; + } + return "1"; + } + + //////////////////////////////////////////////////////////////////////// + // Trigger a page according to a result + function triggerTutorialPage(n, result) { + n++; + if (pages[n] && (typeof(pages[n].trigger) == 'function') + && pages[n].trigger(result)) { + pageTrigger++; + setTutorialPage(result, n); + } + }; + + //////////////////////////////////////////////////////////////////////// + // Trigger various libraries after JSONRPC returned + function handleSuccess(report, result) { + if (result.type.match(/^Graphics\.Raphael\.Raphael[\r\n ]/)) { + runRaphael(result.result); + report(); + } + if (result.type.match(/standard/)) { + var hashrocket = ''; + var msg_value = ' => '; + if (result.result == null) { + hashrocket = ' => ' + msg_value = ''; + } + report( + [{ + msg: msg_value + result.output + hashrocket + result.result, + className: "jquery-console-message-value" + }]); + } + + if (result.type.match(/error/)) { + + report( + [{ + msg: result.error, + className: "jquery-console-message-value" + }]); + } + + if (result.type.match(/illegal/)) { + + report( + [{ + msg: 'You are not allowed to run that command!', + className: "jquery-console-message-value" + }]); + } + + + if (result.type.match(/line_continuation/)) { + report( + [{ + msg: '..', + className: "jquery-console-prompt-label" + }]); + } + + }; + + //////////////////////////////////////////////////////////////////////// + // Raphael support + function runRaphael(expr) { + raphaelPaper.clear(); + $('#raphael').parent().parent().slideDown(function() { + var exprs = expr.split(/\n/g); + for (var i = 0; i < exprs.length; i++) + raphaelRunExpr(exprs[i]); + }); + } + function raphaelRunExpr(expr) { + var expr = expr.split(/ /g); + switch (expr[0]) { + case 'new': + { + switch (expr[2]) { + case 'circle': + { + var x = expr[3], + y = expr[4], + radius = expr[5]; + var circle = raphaelPaper.circle(x * 1, y * 1, radius * 1); + circle.attr("fill", "#7360a4"); + break; + } + } + } + } + } + + function notice(name, msg, style) { + if (opera()) return; + if (!notices[name]) { + notices[name] = name; + return controller.notice(msg, style); + } + } + + function limitsError(str) { + if (str == "Terminated!") { + notice('terminated', + "This error means it took to long to work" + + " out on the server.", + 'fadeout'); + return "Terminated!"; + } else if (str == "Time limit exceeded.") { + notice('exceeded', + "This error means it took to long to work out on the server. " + + "Try again.", + 'fadeout'); + return "Terminated! Try again."; + } + return str; + } + +})(jQuery); diff --git a/TryRuby/public/javascripts/raphael-min.js b/TryRuby/public/javascripts/raphael-min.js new file mode 100644 index 0000000..4a99e3e --- /dev/null +++ b/TryRuby/public/javascripts/raphael-min.js @@ -0,0 +1,113 @@ +/* + * Raphael 1.4.3 - JavaScript Vector Library + * + * Copyright (c) 2010 Dmitry Baranovskiy (http://raphaeljs.com) + * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. + */ +Raphael=function(){function m(){if(m.is(arguments[0],U)){for(var a=arguments[0],b=Aa[K](m,a.splice(0,3+m.is(a[0],O))),c=b.set(),d=0,f=a[o];d

      ";if(ha.childNodes[o]!=2)return m.type=null;ha=null}m.svg=!(m.vml=m.type=="VML");G[p]=m[p];m._id=0;m._oid=0;m.fn={};m.is=function(a,b){b=ca.call(b);return b=="object"&&a===Object(a)||b=="undefined"&&typeof a==b||b=="null"&&a==null||ca.call(ob.call(a).slice(8,-1))==b};m.setWindow=function(a){X=a;C=X.document};function ra(a){if(m.vml){var b=/^\s+|\s+$/g;ra=T(function(d){var f;d=(d+s)[I](b, +s);try{var e=new X.ActiveXObject("htmlfile");e.write("");e.close();f=e.body}catch(g){f=X.createPopup().document.body}e=f.createTextRange();try{f.style.color=d;var h=e.queryCommandValue("ForeColor");h=(h&255)<<16|h&65280|(h&16711680)>>>16;return"#"+("000000"+h[N](16)).slice(-6)}catch(i){return"none"}})}else{var c=C.createElement("i");c.title="Rapha\u00ebl Colour Picker";c.style.display="none";C.body[y](c);ra=T(function(d){c.style.color=d;return C.defaultView.getComputedStyle(c,s).getPropertyValue("color")})}return ra(a)} +function qb(){return"hsb("+[this.h,this.s,this.b]+")"}function rb(){return this.hex}m.hsb2rgb=T(function(a,b,c){if(m.is(a,"object")&&"h"in a&&"s"in a&&"b"in a){c=a.b;b=a.s;a=a.h}var d;if(c==0)return{r:0,g:0,b:0,hex:"#000"};if(a>1||b>1||c>1){a/=255;b/=255;c/=255}d=~~(a*6);a=a*6-d;var f=c*(1-b),e=c*(1-b*a),g=c*(1-b*(1-a));a=[c,e,f,f,g,c,c][d];b=[g,c,c,e,f,f,g][d];d=[f,f,g,c,c,e,f][d];a*=255;b*=255;d*=255;c={r:a,g:b,b:d,toString:rb};a=(~~a)[N](16);b=(~~b)[N](16);d=(~~d)[N](16);a=a[I](ga,"0");b=b[I](ga, +"0");d=d[I](ga,"0");c.hex="#"+a+b+d;return c},m);m.rgb2hsb=T(function(a,b,c){if(m.is(a,"object")&&"r"in a&&"g"in a&&"b"in a){c=a.b;b=a.g;a=a.r}if(m.is(a,ea)){var d=m.getRGB(a);a=d.r;b=d.g;c=d.b}if(a>1||b>1||c>1){a/=255;b/=255;c/=255}var f=Y(a,b,c),e=$(a,b,c);d=f;if(e==f)return{h:0,s:0,b:f};else{var g=f-e;e=g/f;a=a==f?(b-c)/g:b==f?2+(c-a)/g:4+(a-b)/g;a/=6;a<0&&a++;a>1&&a--}return{h:a,s:e,b:d,toString:qb}},m);var sb=/,?([achlmqrstvxz]),?/gi,sa=/\s*,\s*/,tb={hs:1,rg:1};m._path2string=function(){return this.join(",")[I](sb, +"$1")};function T(a,b,c){function d(){var f=Array[p].slice.call(arguments,0),e=f[Q]("\u25ba"),g=d.cache=d.cache||{},h=d.count=d.count||[];if(g[z](e))return c?c(g[e]):g[e];h[o]>=1000&&delete g[h.shift()];h[E](e);g[e]=a[K](b,f);return c?c(g[e]):g[e]}return d}m.getRGB=T(function(a){if(!a||(a+=s).indexOf("-")+1)return{r:-1,g:-1,b:-1,hex:"none",error:1};if(a=="none")return{r:-1,g:-1,b:-1,hex:"none"};!(tb[z](a.substring(0,2))||a.charAt()=="#")&&(a=ra(a));var b,c,d,f,e;if(a=a.match(pb)){if(a[2]){d=da(a[2].substring(5), +16);c=da(a[2].substring(3,5),16);b=da(a[2].substring(1,3),16)}if(a[3]){d=da((e=a[3].charAt(3))+e,16);c=da((e=a[3].charAt(2))+e,16);b=da((e=a[3].charAt(1))+e,16)}if(a[4]){a=a[4][H](sa);b=A(a[0]);c=A(a[1]);d=A(a[2]);f=A(a[3])}if(a[5]){a=a[5][H](sa);b=A(a[0])*2.55;c=A(a[1])*2.55;d=A(a[2])*2.55;f=A(a[3])}if(a[6]){a=a[6][H](sa);b=A(a[0]);c=A(a[1]);d=A(a[2]);return m.hsb2rgb(b,c,d)}if(a[7]){a=a[7][H](sa);b=A(a[0])*2.55;c=A(a[1])*2.55;d=A(a[2])*2.55;return m.hsb2rgb(b,c,d)}a={r:b,g:c,b:d};b=(~~b)[N](16); +c=(~~c)[N](16);d=(~~d)[N](16);b=b[I](ga,"0");c=c[I](ga,"0");d=d[I](ga,"0");a.hex="#"+b+c+d;isFinite(A(f))&&(a.o=f);return a}return{r:-1,g:-1,b:-1,hex:"none",error:1}},m);m.getColor=function(a){a=this.getColor.start=this.getColor.start||{h:0,s:1,b:a||0.75};var b=this.hsb2rgb(a.h,a.s,a.b);a.h+=0.075;if(a.h>1){a.h=0;a.s-=0.2;a.s<=0&&(this.getColor.start={h:0,s:1,b:a.b})}return b.hex};m.getColor.reset=function(){delete this.start};var ub=/([achlmqstvz])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig, +vb=/(-?\d*\.?\d*(?:e[-+]?\d+)?)\s*,?\s*/ig;m.parsePathString=T(function(a){if(!a)return null;var b={a:7,c:6,h:1,l:2,m:2,q:4,s:4,t:2,v:1,z:0},c=[];if(m.is(a,U)&&m.is(a[0],U))c=ta(a);c[o]||(a+s)[I](ub,function(d,f,e){var g=[];d=ca.call(f);e[I](vb,function(h,i){i&&g[E](+i)});if(d=="m"&&g[o]>2){c[E]([f][M](g.splice(0,2)));d="l";f=f=="m"?"l":"L"}for(;g[o]>=b[d];){c[E]([f][M](g.splice(0,b[d])));if(!b[d])break}});c[N]=m._path2string;return c});m.findDotsAtSegment=function(a,b,c,d,f,e,g,h,i){var j=1-i,l= +D(j,3)*a+D(j,2)*3*i*c+j*3*i*i*f+D(i,3)*g;j=D(j,3)*b+D(j,2)*3*i*d+j*3*i*i*e+D(i,3)*h;var n=a+2*i*(c-a)+i*i*(f-2*c+a),r=b+2*i*(d-b)+i*i*(e-2*d+b),q=c+2*i*(f-c)+i*i*(g-2*f+c),k=d+2*i*(e-d)+i*i*(h-2*e+d);a=(1-i)*a+i*c;b=(1-i)*b+i*d;f=(1-i)*f+i*g;e=(1-i)*e+i*h;h=90-w.atan((n-q)/(r-k))*180/w.PI;(n>q||r1){B=w.sqrt(B);c=B*c;d=B*d}B=c*c;var L=d*d;B=(e==g?-1:1)*w.sqrt(w.abs((B*L-B*x*x-L*k*k)/(B*x*x+L*k*k)));e=B*c*x/d+(a+h)/2;var B= +B*-d*k/c+(b+i)/2,x=w.asin(((b-B)/d).toFixed(7));k=w.asin(((i-B)/d).toFixed(7));x=ak)x-=l*2;if(!g&&k>x)k-=l*2}l=k-x;if(w.abs(l)>n){q=k;l=h;L=i;k=x+n*(g&&k>x?1:-1);h=e+c*w.cos(k);i=B+d*w.sin(k);q=Qa(h,i,c,d,f,0,g,l,L,[k,q,e,B])}l=k-x;f=w.cos(x);e=w.sin(x);g=w.cos(k);k=w.sin(k);l=w.tan(l/4);c=4/3*c*l;l=4/3*d*l;d=[a,b];a=[a+c*e,b-l*f];b=[h+c*k,i-l*g];h=[h,i];a[0]=2*d[0]-a[0];a[1]=2*d[1]-a[1];if(j)return[a,b,h][M](q);else{q=[a,b,h][M](q)[Q]()[H](","); +j=[];h=0;for(i=q[o];h1000000000000&&(n=0.5);w.abs(i)>1000000000000&&(i=0.5);if(n>0&&n<1){n=la(a,b,c,d,f,e,g,h,n);q[E](n.x);r[E](n.y)}if(i> +0&&i<1){n=la(a,b,c,d,f,e,g,h,i);q[E](n.x);r[E](n.y)}i=e-2*d+b-(h-2*e+d);j=2*(d-b)-2*(e-d);l=b-d;n=(-j+w.sqrt(j*j-4*i*l))/2/i;i=(-j-w.sqrt(j*j-4*i*l))/2/i;w.abs(n)>1000000000000&&(n=0.5);w.abs(i)>1000000000000&&(i=0.5);if(n>0&&n<1){n=la(a,b,c,d,f,e,g,h,n);q[E](n.x);r[E](n.y)}if(i>0&&i<1){n=la(a,b,c,d,f,e,g,h,i);q[E](n.x);r[E](n.y)}return{min:{x:$[K](0,q),y:$[K](0,r)},max:{x:Y[K](0,q),y:Y[K](0,r)}}}),ua=T(function(a,b){var c=ka(a),d=b&&ka(b);a={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null};b={x:0,y:0, +bx:0,by:0,X:0,Y:0,qx:null,qy:null};function f(q,k){var t;if(!q)return["C",k.x,k.y,k.x,k.y,k.x,k.y];!(q[0]in{T:1,Q:1})&&(k.qx=k.qy=null);switch(q[0]){case "M":k.X=q[1];k.Y=q[2];break;case "A":q=["C"][M](Qa[K](0,[k.x,k.y][M](q.slice(1))));break;case "S":t=k.x+(k.x-(k.bx||k.x));k=k.y+(k.y-(k.by||k.y));q=["C",t,k][M](q.slice(1));break;case "T":k.qx=k.x+(k.x-(k.qx||k.x));k.qy=k.y+(k.y-(k.qy||k.y));q=["C"][M](Pa(k.x,k.y,k.qx,k.qy,q[1],q[2]));break;case "Q":k.qx=q[1];k.qy=q[2];q=["C"][M](Pa(k.x,k.y,q[1], +q[2],q[3],q[4]));break;case "L":q=["C"][M](wa(k.x,k.y,q[1],q[2]));break;case "H":q=["C"][M](wa(k.x,k.y,q[1],k.y));break;case "V":q=["C"][M](wa(k.x,k.y,k.x,q[1]));break;case "Z":q=["C"][M](wa(k.x,k.y,k.X,k.Y));break}return q}function e(q,k){if(q[k][o]>7){q[k].shift();for(var t=q[k];t[o];)q.splice(k++,0,["C"][M](t.splice(0,6)));q.splice(k,1);i=Y(c[o],d&&d[o]||0)}}function g(q,k,t,L,B){if(q&&k&&q[B][0]=="M"&&k[B][0]!="M"){k.splice(B,0,["M",L.x,L.y]);t.bx=0;t.by=0;t.x=q[B][1];t.y=q[B][2];i=Y(c[o],d&& +d[o]||0)}}for(var h=0,i=Y(c[o],d&&d[o]||0);h0.5)*2-1;D(f-0.5,2)+D(e-0.5,2)>0.25&&(e=w.sqrt(0.25-D(f-0.5,2))*l+0.5)&&e!=0.5&&(e=e.toFixed(5)-1.0E-5*l)}return s});b=b[H](/\s*\-\s*/);if(d=="linear"){var h=b.shift();h=-A(h);if(isNaN(h))return null;h=[0,0,w.cos(h*w.PI/180),w.sin(h*w.PI/180)];var i=1/(Y(w.abs(h[2]),w.abs(h[3]))||1);h[2]*=i;h[3]*=i;if(h[2]<0){h[0]=-h[2];h[2]=0}if(h[3]<0){h[1]=-h[3];h[3]=0}}b=Ra(b);if(!b)return null; +i=a.getAttribute(aa);(i=i.match(/^url\(#(.*)\)$/))&&c.defs.removeChild(C.getElementById(i[1]));i=v(d+"Gradient");i.id="r"+(m._id++)[N](36);v(i,d=="radial"?{fx:f,fy:e}:{x1:h[0],y1:h[1],x2:h[2],y2:h[3]});c.defs[y](i);c=0;for(h=b[o];cb.height&&(b.height=e.y+e.height-b.y);e.x+e.width-b.x>b.width&&(b.width=e.x+e.width-b.x)}}a&&this.hide();return b};u[p].attr=function(a,b){if(this.removed)return this;if(a==null){a={};for(var c in this.attrs)if(this.attrs[z](c))a[c]=this.attrs[c];this._.rt.deg&&(a.rotation=this.rotate());(this._.sx!=1||this._.sy!= +1)&&(a.scale=this.scale());a.gradient&&a.fill=="none"&&(a.fill=a.gradient)&&delete a.gradient;return a}if(b==null&&m.is(a,ea)){if(a=="translation")return ya.call(this);if(a=="rotation")return this.rotate();if(a=="scale")return this.scale();if(a==aa&&this.attrs.fill=="none"&&this.attrs.gradient)return this.attrs.gradient;return this.attrs[a]}if(b==null&&m.is(a,U)){b={};c=0;for(var d=a.length;c1&&(a=1);f.opacity=a}b.fill&&(f.on=true);if(f.on==null||b.fill=="none")f.on=false;if(f.on&&b.fill)if(a=b.fill.match(Na)){f.src=a[1];f.type="tile"}else{f.color=m.getRGB(b.fill).hex;f.src= +s;f.type="solid";if(m.getRGB(b.fill).error&&(g.type in{circle:1,ellipse:1}||(b.fill+s).charAt()!="r")&&ma(g,b.fill)){d.fill="none";d.gradient=b.fill}}e&&c[y](f);f=c.getElementsByTagName("stroke")&&c.getElementsByTagName("stroke")[0];e=false;!f&&(e=f=R("stroke"));if(b.stroke&&b.stroke!="none"||b["stroke-width"]||b["stroke-opacity"]!=null||b["stroke-dasharray"]||b["stroke-miterlimit"]||b["stroke-linejoin"]||b["stroke-linecap"])f.on=true;(b.stroke=="none"||f.on==null||b.stroke==0||b["stroke-width"]== +0)&&(f.on=false);a=m.getRGB(b.stroke);f.on&&b.stroke&&(f.color=a.hex);a=((+d["stroke-opacity"]+1||2)-1)*((+d.opacity+1||2)-1)*((+a.o+1||2)-1);h=(A(b["stroke-width"])||1)*0.75;a<0&&(a=0);a>1&&(a=1);b["stroke-width"]==null&&(h=d["stroke-width"]);b["stroke-width"]&&(f.weight=h);h&&h<1&&(a*=h)&&(f.weight=1);f.opacity=a;b["stroke-linejoin"]&&(f.joinstyle=b["stroke-linejoin"]||"miter");f.miterlimit=b["stroke-miterlimit"]||8;b["stroke-linecap"]&&(f.endcap=b["stroke-linecap"]=="butt"?"flat":b["stroke-linecap"]== +"square"?"square":"round");if(b["stroke-dasharray"]){a={"-":"shortdash",".":"shortdot","-.":"shortdashdot","-..":"shortdashdotdot",". ":"dot","- ":"dash","--":"longdash","- .":"dashdot","--.":"longdashdot","--..":"longdashdotdot"};f.dashstyle=a[z](b["stroke-dasharray"])?a[b["stroke-dasharray"]]:s}e&&c[y](f)}if(g.type=="text"){f=g.paper.span.style;d.font&&(f.font=d.font);d["font-family"]&&(f.fontFamily=d["font-family"]);d["font-size"]&&(f.fontSize=d["font-size"]);d["font-weight"]&&(f.fontWeight=d["font-weight"]); +d["font-style"]&&(f.fontStyle=d["font-style"]);g.node.string&&(g.paper.span.innerHTML=(g.node.string+s)[I](/"));g.W=d.w=g.paper.span.offsetWidth;g.H=d.h=g.paper.span.offsetHeight;g.X=d.x;g.Y=d.y+F(g.H/2);switch(d["text-anchor"]){case "start":g.node.style["v-text-align"]="left";g.bbx=F(g.W/2);break;case "end":g.node.style["v-text-align"]="right";g.bbx=-F(g.W/2);break;default:g.node.style["v-text-align"]="center";break}}};ma=function(a,b){a.attrs=a.attrs|| +{};var c="linear",d=".5 .5";a.attrs.gradient=b;b=(b+s)[I](Ya,function(i,j,l){c="radial";if(j&&l){j=A(j);l=A(l);D(j-0.5,2)+D(l-0.5,2)>0.25&&(l=w.sqrt(0.25-D(j-0.5,2))*((l>0.5)*2-1)+0.5);d=j+P+l}return s});b=b[H](/\s*\-\s*/);if(c=="linear"){var f=b.shift();f=-A(f);if(isNaN(f))return null}var e=Ra(b);if(!e)return null;a=a.shape||a.node;b=a.getElementsByTagName(aa)[0]||R(aa);!b.parentNode&&a.appendChild(b);if(e[o]){b.on=true;b.method="none";b.color=e[0].color;b.color2=e[e[o]-1].color;a=[];for(var g=0, +h=e[o];g')}}catch(Kb){R=function(a){return C.createElement("<"+a+' xmlns="urn:schemas-microsoft.com:vml" class="rvml">')}}Aa=function(){var a=Sa[K](0,arguments),b=a.container,c=a.height,d=a.width,f=a.x;a=a.y;if(!b)throw new Error("VML container not found.");var e=new G,g=e.canvas=C.createElement("div"),h=g.style;f=f||0;a=a||0;d=d||512; +c=c||342;d==+d&&(d+="px");c==+c&&(c+="px");e.width=1000;e.height=1000;e.coordsize=ja*1000+P+ja*1000;e.coordorigin="0 0";e.span=C.createElement("span");e.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";g[y](e.span);h.cssText=m.format("width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden",d,c);if(b==1){C.body[y](g);h.left=f+"px";h.top=a+"px";h.position="absolute"}else b.firstChild?b.insertBefore(g, +b.firstChild):b[y](g);Fa.call(e,e,m.fn);return e};G[p].clear=function(){this.canvas.innerHTML=s;this.span=C.createElement("span");this.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";this.canvas[y](this.span);this.bottom=this.top=null};G[p].remove=function(){this.canvas.parentNode.removeChild(this.canvas);for(var a in this)this[a]=Xa(a);return true}}G[p].safari=/^Apple|^Google/.test(X.navigator.vendor)&&(!(X.navigator.userAgent.indexOf("Version/4.0")+ +1)||X.navigator.platform.slice(0,2)=="iP")?function(){var a=this.rect(-99,-99,this.width+99,this.height+99);X.setTimeout(function(){a.remove()})}:function(){};function Db(){this.returnValue=false}function Eb(){return this.originalEvent.preventDefault()}function Fb(){this.cancelBubble=true}function Gb(){return this.originalEvent.stopPropagation()}var Hb=function(){if(C.addEventListener)return function(a,b,c,d){var f=Ba&&Ca[b]?Ca[b]:b;function e(g){if(Ba&&Ca[z](b))for(var h=0,i=g.targetTouches&&g.targetTouches.length;h< +i;h++)if(g.targetTouches[h].target==a){i=g;g=g.targetTouches[h];g.originalEvent=i;g.preventDefault=Eb;g.stopPropagation=Gb;break}return c.call(d,g)}a.addEventListener(f,e,false);return function(){a.removeEventListener(f,e,false);return true}};else if(C.attachEvent)return function(a,b,c,d){function f(g){g=g||X.event;g.preventDefault=g.preventDefault||Db;g.stopPropagation=g.stopPropagation||Fb;return c.call(d,g)}a.attachEvent("on"+b,f);function e(){a.detachEvent("on"+b,f);return true}return e}}();for(ha= +Ma[o];ha--;)(function(a){m[a]=u[p][a]=function(b){if(m.is(b,"function")){this.events=this.events||[];this.events.push({name:a,f:b,unbind:Hb(this.shape||this.node||C,a,b,this)})}return this};m["un"+a]=u[p]["un"+a]=function(b){for(var c=this.events,d=c[o];d--;)if(c[d].name==a&&c[d].f==b){c[d].unbind();c.splice(d,1);!c.length&&delete this.events;return this}return this}})(Ma[ha]);u[p].hover=function(a,b){return this.mouseover(a).mouseout(b)};u[p].unhover=function(a,b){return this.unmouseover(a).unmouseout(b)}; +u[p].drag=function(a,b,c){this._drag={};var d=this.mousedown(function(g){(g.originalEvent?g.originalEvent:g).preventDefault();this._drag.x=g.clientX;this._drag.y=g.clientY;this._drag.id=g.identifier;b&&b.call(this,g.clientX,g.clientY);Raphael.mousemove(f).mouseup(e)});function f(g){var h=g.clientX,i=g.clientY;if(Ba)for(var j=g.touches.length,l;j--;){l=g.touches[j];if(l.identifier==d._drag.id){h=l.clientX;i=l.clientY;(g.originalEvent?g.originalEvent:g).preventDefault();break}}else g.preventDefault(); +a&&a.call(d,h-d._drag.x,i-d._drag.y,h,i)}function e(){d._drag={};Raphael.unmousemove(f).unmouseup(e);c&&c.call(d)}return this};G[p].circle=function(a,b,c){return ab(this,a||0,b||0,c||0)};G[p].rect=function(a,b,c,d,f){return bb(this,a||0,b||0,c||0,d||0,f||0)};G[p].ellipse=function(a,b,c,d){return cb(this,a||0,b||0,c||0,d||0)};G[p].path=function(a){a&&!m.is(a,ea)&&!m.is(a[0],U)&&(a+=s);return Za(m.format[K](m,arguments),this)};G[p].image=function(a,b,c,d,f){return db(this,a||"about:blank",b||0,c||0, +d||0,f||0)};G[p].text=function(a,b,c){return eb(this,a||0,b||0,c||s)};G[p].set=function(a){arguments[o]>1&&(a=Array[p].splice.call(arguments,0,arguments[o]));return new Z(a)};G[p].setSize=fb;G[p].top=G[p].bottom=null;G[p].raphael=m;function ib(){return this.x+P+this.y}u[p].resetScale=function(){if(this.removed)return this;this._.sx=1;this._.sy=1;this.attrs.scale="1 1"};u[p].scale=function(a,b,c,d){if(this.removed)return this;if(a==null&&b==null)return{x:this._.sx,y:this._.sy,toString:ib};b=b||a;!+b&& +(b=a);var f,e,g=this.attrs;if(a!=0){var h=this.getBBox(),i=h.x+h.width/2,j=h.y+h.height/2;f=a/this._.sx;e=b/this._.sy;c=+c||c==0?c:i;d=+d||d==0?d:j;h=~~(a/w.abs(a));var l=~~(b/w.abs(b)),n=this.node.style,r=c+(i-c)*f;j=d+(j-d)*e;switch(this.type){case "rect":case "image":var q=g.width*h*f,k=g.height*l*e;this.attr({height:k,r:g.r*$(h*f,l*e),width:q,x:r-q/2,y:j-k/2});break;case "circle":case "ellipse":this.attr({rx:g.rx*h*f,ry:g.ry*l*e,r:g.r*$(h*f,l*e),cx:r,cy:j});break;case "text":this.attr({x:r,y:j}); +break;case "path":i=Oa(g.path);for(var t=true,L=0,B=i[o];L=i)return r;l=r}});function Ha(a,b){return function(c,d,f){c=ua(c); +for(var e,g,h,i,j="",l={},n=0,r=0,q=c.length;rd){if(b&&!l.start){e=jb(e,g,h[1],h[2],h[3],h[4],h[5],h[6],d-n);j+=["C",e.start.x,e.start.y,e.m.x,e.m.y,e.x,e.y];if(f)return j;l.start=j;j=["M",e.x,e.y+"C",e.n.x,e.n.y,e.end.x,e.end.y,h[5],h[6]][Q]();n+=i;e=+h[5];g=+h[6];continue}if(!a&&!b){e=jb(e,g,h[1],h[2],h[3],h[4],h[5],h[6],d-n);return{x:e.x,y:e.y,alpha:e.alpha}}}n+=i;e=+h[5];g=+h[6]}j+=h}l.end=j;e=a?n: +b?l:m.findDotsAtSegment(e,g,h[1],h[2],h[3],h[4],h[5],h[6],1);e.alpha&&(e={x:e.x,y:e.y,alpha:e.alpha});return e}}var Ib=T(function(a,b,c,d,f,e,g,h){for(var i={x:0,y:0},j=0,l=0;l<1.01;l+=0.01){var n=la(a,b,c,d,f,e,g,h,l);l&&(j+=D(D(i.x-n.x,2)+D(i.y-n.y,2),0.5));i=n}return j}),kb=Ha(1),za=Ha(),Ia=Ha(0,1);u[p].getTotalLength=function(){if(this.type=="path"){if(this.node.getTotalLength)return this.node.getTotalLength();return kb(this.attrs.path)}};u[p].getPointAtLength=function(a){if(this.type=="path")return za(this.attrs.path, +a)};u[p].getSubpath=function(a,b){if(this.type=="path"){if(w.abs(this.getTotalLength()-b)<1.0E-6)return Ia(this.attrs.path,a).end;b=Ia(this.attrs.path,b,1);return a?Ia(b,a).end:b}};m.easing_formulas={linear:function(a){return a},"<":function(a){return D(a,3)},">":function(a){return D(a-1,3)+1},"<>":function(a){a*=2;if(a<1)return D(a,3)/2;a-=2;return(D(a,3)+2)/2},backIn:function(a){var b=1.70158;return a*a*((b+1)*a-b)},backOut:function(a){a-=1;var b=1.70158;return a*a*((b+1)*a+b)+1},elastic:function(a){if(a== +0||a==1)return a;var b=0.3,c=b/4;return D(2,-10*a)*w.sin((a-c)*2*w.PI/b)+1},bounce:function(a){var b=7.5625,c=2.75;if(a<1/c)a=b*a*a;else if(a<2/c){a-=1.5/c;a=b*a*a+0.75}else if(a<2.5/c){a-=2.25/c;a=b*a*a+0.9375}else{a-=2.625/c;a=b*a*a+0.984375}return a}};var S={length:0};function lb(){var a=+new Date;for(var b in S)if(b!="length"&&S[z](b)){var c=S[b];if(c.stop||c.el.removed){delete S[b];S[o]--}else{var d=a-c.start,f=c.ms,e=c.easing,g=c.from,h=c.diff,i=c.to,j=c.t,l=c.prev||0,n=c.el,r=c.callback,q= +{},k;if(d p:first-child{ + margin-top:0; +} +#facebox .content > p:last-child{ + margin-bottom:0; +} + +#facebox .close{ + position:absolute; + top:5px; + right:5px; + padding:2px; + background:#fff; +} +#facebox .close img{ + opacity:0.3; +} +#facebox .close:hover img{ + opacity:1.0; +} + +#facebox .loading { + text-align: center; +} + +#facebox .image { + text-align: center; +} + +#facebox img { + border: 0; + margin: 0; +} + +#facebox_overlay { + position: fixed; + top: 0px; + left: 0px; + height:100%; + width:100%; +} + +.facebox_hide { + z-index:-100; +} + +.facebox_overlayBG { + background-color: #000; + z-index: 99; +} +.facebox-footnote{ + margin-top:40px; +} \ No newline at end of file diff --git a/TryRuby/public/stylesheets/reset.css b/TryRuby/public/stylesheets/reset.css new file mode 100644 index 0000000..d709810 --- /dev/null +++ b/TryRuby/public/stylesheets/reset.css @@ -0,0 +1,46 @@ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, font, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td { + margin: 0; + padding: 0; + border: 0; + outline: 0; + font-weight: inherit; + font-style: inherit; + font-size: 100%; + font-family: inherit; + vertical-align: baseline; +} +/* remember to define focus styles! */ +:focus { + outline: 0; +} +body { + line-height: 1; + color: black; + background: white; +} +ol, ul { + list-style: none; +} +/* tables still need 'cellspacing="0"' in the markup */ +table { + border-collapse: separate; + border-spacing: 0; +} +caption, th, td { + text-align: left; + font-weight: normal; +} +blockquote:before, blockquote:after, +q:before, q:after { + content: ""; +} +blockquote, q { + quotes: "" ""; +} diff --git a/TryRuby/public/stylesheets/scaffold.css b/TryRuby/public/stylesheets/scaffold.css new file mode 100644 index 0000000..1ae7000 --- /dev/null +++ b/TryRuby/public/stylesheets/scaffold.css @@ -0,0 +1,56 @@ +body { background-color: #fff; color: #333; } + +body, p, ol, ul, td { + font-family: verdana, arial, helvetica, sans-serif; + font-size: 13px; + line-height: 18px; +} + +pre { + background-color: #eee; + padding: 10px; + font-size: 11px; +} + +a { color: #000; } +a:visited { color: #666; } +a:hover { color: #fff; background-color:#000; } + +div.field, div.actions { + margin-bottom: 10px; +} + +#notice { + color: green; +} + +.field_with_errors { + padding: 2px; + background-color: red; + display: table; +} + +#error_explanation { + width: 450px; + border: 2px solid red; + padding: 7px; + padding-bottom: 0; + margin-bottom: 20px; + background-color: #f0f0f0; +} + +#error_explanation h2 { + text-align: left; + font-weight: bold; + padding: 5px 5px 5px 15px; + font-size: 12px; + margin: -7px; + margin-bottom: 0px; + background-color: #c00; + color: #fff; +} + +#error_explanation ul li { + font-size: 12px; + list-style: square; +} diff --git a/TryRuby/public/tutorials/es_intro.html b/TryRuby/public/tutorials/es_intro.html new file mode 100644 index 0000000..256de2f --- /dev/null +++ b/TryRuby/public/tutorials/es_intro.html @@ -0,0 +1,666 @@ + +
      +

      Usando El Prompt

      +

      La ventana azul de arriba es el prompt de Ruby. ¡Escribe una línea de código Ruby, aprieta Enter + y velo correr!

      +

      Por ejemplo, trata de escribir algo matemático. Como: 2 + 6

      +
      \d+
      +
      +
      +

      Números & Matemática

      +

      ¡Bien! Hiciste algo de matemática. ¿Ves como la respuesta salta a la vista?

      +

      Ruby reconoce números y símbolos matemáticos. Puedes probar otras cosas como:

      +
      • 4 * 10
      • +
      • 5 - 12
      • +
      • 40 / 4
      +

      Seguro, las computadoras son habilidosas y rápidas con las matemáticas. Sigamos... ¿Quieres ver tu nombre al revés? + Escribe tu primer nombre entre comillas así: "Jimmy"

      +
      "(\w+)"
      +
      +
      +

      Decir Tu Nombre Al Revés

      +

      Perfecto, has formado un string de las letras de tu nombre. Un string + es un juego de caracteres que la computadora puede procesar.

      +

      Imagina que las letras están en una cuerda donde + se cuelga la ropa y las comillas son los broches que sostienen los bordes. Las comillas marcan el comienzo y el final.

      +

      Para invertir tu nombre, escribe: "Jimmy".reverse (¡No olvides el punto!)

      +
      "(\w+)"
      +
      +
      +

      Contando Las Letras

      +

      ¡Has usado el método reverse sobre tu nombre! Poniendo tu nombre entre comillas, + hiciste un string. Luego llamaste al método reverse, que funciona sobre un string cambiando + todas las letras de atrás para adelante.

      +

      Ahora, vamos a ver cuantas letras tiene tu nombre: "Jimmy".length

      +
      \d+
      +
      +
      +

      Repitiendo

      +

      Ahora, estoy seguro que te estarás preguntando para que sirve todo esto. Bueno, estoy seguro que habrás estado en alguna + pagina web donde te gritaron, ¡Hey, tu password es muy corto! Ves, algunos programas + usan este código tan simple.

      +

      Mira esto. Vamos a multiplicar tu nombre por 5. "Jimmy" * 5

      +
      "(\w+)"
      +
      +
      +

      Hey, Sumario #1 Listo

      +

      Vamos a ver que es lo que has aprendido en el primer minuto.

      +
        +
      • El prompt. Escribiendo código en el prompt verde obtienes + una respuesta del prompt rojo. Todo código te da una respuesta.
      • +
      • Números y strings son objetos matemáticos y de texto de Ruby.
      • +
      • Métodos Has usado métodos en Ingles como reverse + y métodos simbólicos como * (el método de multiplicación.) ¡Los métodos son acciones!
      • +
      +

      Esta es la esencia del aprendizaje. Tomar cosas simples, jugar con ellas + y trasformarlas en cosas nuevas. ¿Te sientes cómodo con todo? Te aseguro que lo estas.

      +

      Bien, vamos a hacer algo incomodo. Trata de invertir un número: 40.reverse

      +
      NoMethodError: undefined method `reverse' for (\d+):Fixnum
      +
      +
      +

      ¡Basta, Te Volviste Loco!

      +

      No puedes invertir el numero cuarenta. Supongo que puedes poner tu monitor en + frente de un espejo, pero invertir un numero no tiene sentido. Ruby lanza un + mensaje de error. Ruby te dice que no hay un método reverse para los números.

      +

      Tal vez si lo conviertes en un string: 40.to_s.reverse.

      +
      \"(\d+)\"
      +
      +
      +

      Los Chicos Son Diferentes De Las Chicas

      +

      Y los números son diferentes de los strings. Aunque puedes usar métodos en cualquier objeto + en Ruby, algunos métodos solo funcionan en cierto tipo de cosas. Pero siempre puedes + convertir entre diferentes tipos usando el método "to" de Ruby.

      +
      • to_s convierte cosas a strings.
      • +
      • to_i convierte cosas a integers (números.)
      • +
      • to_a convierte cosas a arrays.
      • +
      +

      ¿Que son los arrays?! Son listas. Escribe entre un par de corchetes: [].

      +
      \[\]
      +
      +
      +

      Mantenerse en Cola

      +

      Genial, eso es una lista vacía. Las listas guardan cosas en orden. + Como esperando en la cola para palomitas de maíz. Estas atrás de alguien y jamás + pensarías en empujarlo a un costado, ¿no es así? Y con respecto al tipo detrás de ti, + mantienes un ojo sobre el, ¿correcto?

      +

      Acá hay una lista para ti. Números de la lotería: [12, 47, 35].

      +
      \[(\d+(, )?){2,}\]
      +
      +
      +

      Uno Levanta La Mano

      +

      Una lista de números de la lotería. ¿Cual es el mayor?

      +

      Prueba: [12, 47, 35].max.

      +
      (\d+)
      +
      +
      +

      Manteniendo la Lista

      +

      Bien, bien. Pero es un fastidio el tener que reescribir esa lista, ¿no es así?

      +

      Guardemos nuestros números en un ticket de esta manera: ticket = [12, 47, 35]

      +
      \[(\d+(, )?){2,}\]
      +
      +
      +

      Ahora Escribe Ticket

      +

      Ahora, escribe: ticket

      +
      \[(\d+(, )?){2,}\]
      +
      +
      +

      Guardado, Escondido

      +

      ¡Fantástico! Te has aferrado a tus números de la lotería, escondiéndolos dentro de una + variable llamada ticket.

      +

      Vamos a poner tus números en orden, que te parece? Usa: ticket.sort!

      +
      \[(\d+(, )?){2,}\]
      +
      +
      +

      Sumario #2 Está Sobre Nosotros

      +

      Tenías una lista. Ordenaste la lista. La variable ticket ahora esta cambiada.

      +

      ¿Te diste cuenta que el método sort! tiene un claro y llamativo signo de exclamación al final? + Muchas veces los métodos de Ruby gritan así si es que alteran la variable para bien. No es nada + especial, solo una marca.

      +

      Ahora, mira como te fue en tu segundo minuto:

      +
        +
      • Errors. Si tratas de invertir un número o hacer algo sospechoso, + Ruby salteara el prompt para avisarte.
      • +
      • Arrays son listas para ordenar cosas en orden.
      • +
      • Variables guardan cosas y le dan un nombre. Usaste el + signo igual para hacerlo.
        Like: ticket = [14, 37, 18].
      • +
      +

      En total hay ocho lecciones. Estás a dos octavos de camino! + Esto es cosa simple, no te parece? Las cosas buenas están mas adelante.

      +

      Cambiemos de dirección por un momento. Rellené con un poco de poesía cierta + variable para ti. Hecha un vistazo. Escribe print poem

      +
      poem = "My toast has flown from my hand\nAnd my toast has gone to the +moon.\nBut when I saw it on television,\nPlanting our flag on Halley's +comet,\nMore still did I want to eat it.\n"
      +
      My toast (.+)
      +
      +
      +

      Desgraciadamente, Tú Odias la poesía de Tostadas

      +

      Mira, esta bien. No tiene que gustarte. Hackéalo, yo invito.

      +

      En vez de tostada, ve por un melón o algo. Prueba esto: poem['toast'] = 'honeydew'

      +

      Y luego escribe print poem para ver el nuevo poema.

      +
      My honey(.+)
      +
      +
      +

      Listo, Apuntado

      +

      Los corchetes que acabas de usar son muy comunes en Ruby. Recuerda, escribiste: poem['toast'] = 'honeydew'. Esa casilla con la palabra toast tiene corchetes a ambos lados, ¿ves?

      +

      Los +corchetes son como una mira para alinear un objetivo. Exacto. Estos +corchetes significan, "Estoy buscando ____." Listo, apuntado. Aquí estas buscando +una costada e intercambiándola por una fruta.

      +

      Aquí hay una pregunta: ¿Que pasa si volteamos el poema entero? poem.reverse +

      "\\n.ti tae ot (.+)"
      +
      +
      +

      Demasiado Invertido

      +

      Está bien, seguro. Entonces todo el poema fue puesto al revés. Letra por letra. Sin embargo, yo realmente solo quería + invertir las líneas. Mover la última línea a la primera y la primera hacia abajo a la ultima. Al revés, pero no + ése revés.

      +

      Aquí esta como lograrlo: poem.lines.to_a.reverse

      +
      \["More still did I(.+)"\]
      +
      +
      +

      Rizos de Metodos Concatenados

      +

      Dime, que es lo que ves? Que paso acá? Escribiste poem.lines.to_a.reverse y ¿que pasó?

      +

      Dos cosas pasaron. Convertiste poem en una lista usando +lines.to_a. lines decide la forma en que +el string se divide, luego to_a lo +convierte en un Array. (To array.) Diferentes métodos, como +bytes y chars pueden ser usadas en lugar de +lines. Usando lines, Ruby retornará cada línea de poem.

      +

      Luego, tu revertiste, reversed, esa lista. Tenías cada línea. Las revertiste. Eso es todo.

      +

      Vamos a hilar un método más al final de todo esto: print poem.lines.to_a.reverse.join +

      More still did I(.+)
      +
      +
      +

      De Todos los Sumarios, el #3 esta aquí

      +

      Buen espectáculo, mi amigo! El método join toma la lista de líneas revertidas y las pone juntas en un string. + (Seguro, también podrías haber usado to_s.)

      +

      Tiempo de Revisión.

      +
        +
      • Exclamaciones. Métodos pueden tener signos de exclamación (y también de interrogación) en + sus nombres. No es la gran cosa. Prueba: poem.include? "my hand"
      • +
      • Corchetes. Establece objetivos y busca cosas. Busca y reemplaza.
      • +
      • Concatenar métodos te permite hacer mas cosas juntas. Partir poem, revertirlo, + reensamblarlo: poem.lines.to_a.reverse.join
      • +
      +

      En este punto, querras manosear un poco más el poema. Una lista completa de métodos + String estan + + acá. + No temas y prueba algunos (como poem.downcase o poem.delete.)

      +

      Cuando estés listo para seguir adelante, escribe: books = {}

      +
      \{\}
      +
      +
      +

      Un Pequeñín Libro en Blanco

      +

      Has hecho un hash vacío. (también conocido como: un diccionario vacío.)

      +

      Vamos a rellenar con un libro de críticas en miniatura. Acá esta nuestro sistema de calificación:

      +
        +
      • :splendid → una obra maestra.
      • +
      • :quite_good → disfrutable, por supuesto que sí.
      • +
      • :mediocre → partes iguales de bueno y malo.
      • +
      • :quite_not_good → notablemente malo.
      • +
      • :abyssmal → una perdida de tiempo.
      • +
      +

      Para calificar un libro, pon el título entre corchetes y la calificación luego del signo igual.

      +

      Por ejemplo: books["Gravity's Rainbow"] = :splendid

      +
      :\w+
      +
      +
      +

      Mas Críticas Tamaño Bocadillo

      +

      Tú sigue, agrega mas críticas. Y, si quieres ver toda la lista, + implemente escribe: books

      +

      De nuevo, las calificaciones son: :splendid, :quite_good, :mediocre, + :quite_not_good, and :abyssmal.

      +

      Estas calificaciones no son strings. Cuando colocas dos puntos frente a una palabra simple, obtienes un + symbol. Los símbolos son más baratos que los strings (en términos de memoria de la computadora.) Si usas + una palabra una y otra vez en un programa, usa un símbolo. En vez de tener miles de + copias de una palabra en memoria, la computadora guardara el símbolo solamente una vez.

      +

      Una vez que tengas tres o cuatro libros allí + dentro, escribe: books.length.

      +
      [3-9]
      +
      +
      +

      Espera, ¿Me gustó Gravity's Rainbow?

      +

      Ves, el método length funciona sobre strings, list y hashes. Una gran cosa acerca de + Ruby es que los nombres usualmente se reutilizan, lo que significa menos nombres para recordar.

      +

      Si quisieras ver una de tus críticas hechas, vuelve a poner el título entre corchetes. Pero deja de lado el + signo igual.

      +

      Al igual que aquí: books["Gravity's Rainbow"]

      +
      :\w+
      +
      +
      +

      Hashes como Pares

      +

      Ten en mente que los hashes no mantienen las cosas en orden. Ese no es su trabajo. Solo emparejará dos + cosas: una key (llave) y un valor. En tus críticas, la key es el + titulo del libro y el valor es la calificación.

      +

      Si simplemente quieres ver los títulos de los libros que calificaste: books.keys

      +
      \[".*"\]
      +
      +
      +

      ¿Eres Duro?

      +

      ¿Estás dando duras injustas críticas? Sigamos puntuando con rigurosidad:
      ratings = Hash.new {0}

      +

      Entonces, bien, ahora vamos a contar tus críticas. Trata de seguirme. Escribe:
      + books.values.each { |rate| ratings[rate] += 1 }

      +

      (La línea vertical es el signo de tubería, probablemente lo logres con AltGr+1 con tu teclado.)

      +
      \[:.+\]
      +
      +
      +

      Un Recuento

      +

      Genial, wow! Has hecho un recuento de tus calificaciones. Escribe ratings para ver las cuenta. Este nuevo + hash muestra las calificaciones y luego el numero de veces que has dado esa calificación.

      +

      Una de las asombrosas cosas nuevas que acabamos de usar es un bloque, block. Vamos a explorar + explore these more in the next summary. más esto en el próximo sumario. Pero, básicamente, un bloque es un pedazo de código Ruby + rodeado por llaves.

      +

      Probemos otro bloque: 5.times { print "Odelay!" }

      +
      Odelay!Od.*
      +
      +
      +

      Ahora Arribamos al Sumario #4

      +

      Los bloques están siempre apegados a métodos. Como el método times, que toma el bloque y lo corre + repetidas veces. (En este caso: cinco veces.)

      +

      Esta última lección fue algo mas larga. Probablemente usaste unos tres minutos aprendiendo sobre:

      +
        +
      • Hashes. El pequeño diccionario con páginas arrugadas: {}.
      • +
      • Symbols. Pequeñas, eficientes palabras con dos puntos: :splendid.
      • +
      • Blocks. Pedazos de código que pueden ser clavados a muchos métodos de Ruby. Aquí + esta el código que usaste para crear el recuento:
        books.values.each { |rate| ratings[rate] += 1 }.
      • +
      +

      En tu computadora, probablemente tienes muchos archivos diferentes. Archivos con fotos en ellos, + archivos con programas dentro. Y los archivos usualmente se organizan en carpetas, también llamadas: + directorios.

      +

      He preparado algunos directorios para ti. Echa un vistazo: + Dir.entries "/"

      +
      \["\.", .+\]
      +
      +
      +

      La Privada Colección de Dr. Dir

      +

      Acabas de listar todo lo existente en el directorio superior. El directorio raíz, indicado + por la barra en diagonal. Conteniendo algunos programas y otros tutoriales y semejantes.

      +

      Entonces, ¿que es el método Dir.entries? Bueno, es solo un método ¿si?, + entries es el método llamado sobre la variable Dir. + Y Dir tiene una colección de métodos para chequear los archivos de los directorios.

      +

      Otra pequeña cosa de la que no hemos hablado abiertamente. Argumentos de los métodos, resaltados en verde.

      +
        +
      • Dir.entries "/": Cualquier cosa listada luego de un método + es considerado acoplamiento.
      • +
      • print poem: Ves, print es un método ordinario. + Y el poema esta acoplado. Para ser impreso.
      • +
      • print "pre", "event", "ual", "ism" posee varios argumentos, + con comas entre ellos.
      • +
      +

      Para listar solamente archivos de texto en el directorio: Dir["/*.txt"]

      +
      \["\/comics\.txt"\]
      +
      +
      +

      Ven, Lee Historietas Conmigo

      +

      El método Dir[] hace como entries pero tu buscas por archivos + archivos con carácteres de comodín. ¡Aquí, vemos esos corchetes otra vez! Te das + cuenta como todavía significan, "Estoy buscando _____.".

      +

      Mas específicamente: "Estoy buscando archivos que terminen con .txt."

      +

      Abramos este archivo con historietas de una vez. Aquí esta la manera:
      + print File.read("/comics.txt")

      +
      Achewood.+
      +
      +
      +

      Mi Comicas, Tu Comicas

      +

      ¡De acuerdo! Podemos comenzar a usar archivos para guardar cosas. Esto es excelente + porque normalmente cuando salimos de Ruby, todas nuestras variables desaparecerán. + Ruby, por si mismo, olvida estas cosas. Pero si salvamos cosas en archivos, + podemos leer esos archivos en futuras escapadas a Ruby.

      +

      Hey, y ¿adivina que? ¡El directorio /Home es tuyo! ¡Te lo entrego a ti! ¡Soy generoso! Hagamos una copia del archivo de la historieta.

      +

      Querrás hacer lo siguiente: FileUtils.copy('/comics.txt', '/Home/comics.txt') +

      Si ya has creado el archivo, usa File.delete('/Home/comics.txt') para arrojarlo a la basura.

      +
      nil
      +
      +
      +

      Tu Propio Territorio

      +

      Ok, tienes una copia. Chequéala: Dir["/Home/*.txt"]

      +

      Para agregar tu propia historieta a la lista, abramos el archivo en modo append.

      +

      Empieza asi: File.open("/Home/comics.txt", "a") do |f|.

      +
      ..
      +
      +
      +

      Y Ahora, para la Sorprendente Conclusión

      +

      Asi que tu prompt ha cambiado. ¿Lo notas? Tu prompt es doble punto ahora.

      +

      En este tutorial, este prompt significa que Ruby espera que escribas más. A + medida que vayas completando con líneas de código, los doble puntos se mantendrán + hasta que hallas finalizado.

      +

      Hot tip: si quieres parar de trabajar en el código y salirte de los doble puntos, usa el comando reset. + Si quieres volver a la pagina previa del tutorial, usa el comando back.

      +

      Aquí esta tu código. Ya has escrito la primera línea, asi que simplemente ingresa la segunda. (El \n + es el carácter de Enter.

      +
      • File.open("/Home/comics.txt", "a") do |f|
      • +
      •   f << "Cat and Girl: http://catandgirl.com/\n"
      • +
      • end
      • +
      +

      Y, como te has vuelto avanzado y capaz aquí, otro tip: puedes usar las flechas hacia + arriba y hacia abajo para editar tus viejos comandos o correrlos otra vez.

      +
      ..
      +
      +
      +

      Ruby se Sienta y Espera

      +

      Esa ultima línea agrega la historieta Cat and Girl a la lista, pero Ruby seguirá esperando + hasta que hallas terminado por completo para tomar acción.

      +

      Ahora, para finalizar el código que has empezado. Empezaste un nuevo bloque cuando escribiste do. + Hasta ahora los bloques que hemos visto usaban llaves. Esta vez usaremos do y end en lugar + de las llaves. Muchos Rubyistas usan do...end cuando el bloque ocupa varias líneas.

      +

      Terminemos ese bloque ahora mismo, con: end

      +
      • File.open("/Home/comics.txt", "a") do |f|
      • +
      •   f << "Cat and Girl: http://catandgirl.com/\n"
      • +
      • end
      • +
      +
      #.File:/Home/comics\.txt \(closed\).
      +
      +
      +

      El Reloj Clavado en el Archivo

      +

      ¡Bien, bien! Has añadido esa historieta al archivo. Puedes verlo por ti mismo: print File.read("/Home/comics.txt")

      +

      ¿Qué hora era cuando cambiaste el archivo? Veamos. Escribe: File.mtime("/Home/comics.txt")

      +
      \w+ \w+ \d+ \d{2}:\d{2}:\d{2} [+-]\d{4} \d{4}
      +
      +
      +

      Sólo la Manecilla de la Hora

      +

      Estupendo, allí esta la hora. La hora exacta en la que agregaste la historieta al archivo. El mtime te devuelve un objeto Time de Ruby.

      +

      Si sólo quieres ver la hora que era, aprieta la flecha para arriba y cambia la línea a: File.mtime("/Home/comics.txt").hour

      +
      \d+
      +
      +
      +

      Hola, ¿Quién Anda Ahí? Y el Sumario #5 Agita su Sombrero!

      +

      Bien hecho, bien hecho, bien hecho, ¡bien hecho! Realmente, realmente, realmente, realmente, ¡reaaaaaaaaalllmente!

      +

      Aquí esta tu último minuto de tu vida en retrospectiva:

      +
        +
      • Archivos. ¿Que más se puede decir? Muchos métodos para editar archivos y revisar directorios.
      • +
      • Argumentos. Los argumentos son listas de cosas mandadas en un método. Separadas con comas.
      • +
      • También hablamos sobre do y end que es otra manera de hacer un bloque.
      • +
      +

      Ahora ya sabes como usar Ruby por completo. Me refiero a que tienes lo esencial. Solo necesitas seguir + aprendiendo métodos y probar bloques más complejos.

      +

      Pero existe un lado de Ruby que no hemos hablado. Hacer tus propios métodos y clases.

      +

      Ahem! Acabemos con ello de una vez.

      +

      Empieza con: def load_comics( path )

      +
      ..
      +
      +
      +

      En Ruby, Def Leppard Significa ¡Define Leppard (un Método)!

      +

      Hey, bueno, lo hiciste. Estas haciendo tu propio método. Comenzaste con def, seguido por el nombre del método. + Y una lista de argumentos que va a necesitar el método. ¡Esto no da tanto miedo ni es peligroso!

      +

      Todo lo que debemos hacer es rellenar con Ruby y terminarlo con end.

      +

      Aquí esta el código:

      +
      • def load_comics( path )
      • +
      •   comics = {}
      • +
      •   File.foreach(path) do |line|
      • +
      •     url, name = line.split(': ')
      • +
      •     comics[url] = name.strip
      • +
      •   end
      • +
      •   comics
      • +
      • end
      • +
      +

      No necesitas indentar, si no quieres. Lo hice solo para que sea más legible.

      +
      nil
      +
      +
      +

      La Madura Fruta de tu Propia Creación

      +

      Un nuevo método ha nacido. Vamos a usarlo: comics = load_comics('/comics.txt')

      +

      Si tienes un problema, puedes haberlo escrito mal. Usa el comando back y prueba otra vez.

      +
      \{.*"Achewood"=."http://achewood.com/".*\}
      +
      +
      +

      Hey, Cool, Una Cosa de Historietas

      +

      En tu ventana de Ruby arriba, mira el código que has escrito para el método load_comics. ¿Qué esta pasando? Tu estas + pasando en la variable path y estas recibiendo la variable comics. Ruby permite filtrar el hash comics + que es devuelto al final del método.

      +

      Una cantidad de métodos se usaron para realizar el trabajo. Fíjate si puedes hallarlos.

      +
      • File.foreach es el método que abre un archivo y manda cada línea al bloque. La variable line + dentro del bloque do...end va turnando con cada línea del archivo.
      • +
      • split es un método para strings, que rompe los string en colocándolo en un array. Un hacha es arrojada sobre las comas + y las líneas se cortan en dos, dándonos la url y el nombre, name, de las historietas.
      • +
      • strip remueve los espacios extra alrededor de name. Por si acaso.
      • +
      +

      Justo allí. Bravo. Tienes las historietas en un hash de Ruby. ¿Pero ahora qué? ¿Qué tan bueno es en verdad?

      +

      Hagamos una página de links. ¿Qué te parece? Vamos a necesitar una pequeña librería que hice para ti.

      +

      Escribe: require 'popup'

      +
      true
      +
      +
      +

      El Navegador de Títere

      +

      Excelente, has cargado la librería popup. Está guardada en un archivo en el directorio Libraries. Mira: Dir["/Libraries/*"]

      +

      La librería popup contiene un puñado de métodos que he escrito y te dejaran controlar ventanas emergentes aquí en Try Ruby.

      +

      Mira, prueba esto: Popup.goto "http://google.com/"

      +
      \033\[1;JSm.*popup_goto\(.*\)\033\[m.*
      +
      +
      +

      Haciendo Links e Hilando Redes

      +

      Nuestro propio adorable, pequeño popup para manipular. también puedes rellenarlo con tus cositas. Empecemos por algo pequeño:

      +
      • Popup.make {
      • +
      •   h1 "My Links"
      • +
      •   link "Go to Google", "http://google.com/"
      • +
      • }
      • +
      +

      El termino h1 (h-uno) significa encabezado de nivel uno. En HTML, es el encabezado más grande.

      +
      \033\[1;JSm.*popup_make\(.*h1.*a href.*\)\033\[m.*
      +
      +
      +

      Los Popups son tan fáciles, es una Locura

      +

      Se ve bien, lo hiciste perfecto, tal como se te pidió. Hagamos una lista entonces.

      +

      Aquí esta como haces una lista con la librería de popup:

      +
      • Popup.make do
      • +
      •   h1 "Things To Do"
      • +
      •   list do
      • +
      •     p "Try out Ruby"
      • +
      •     p "Ride a tiger"
      • +
      •     p "(down River Euphrates)"
      • +
      •   end
      • +
      • end
      • +
      +

      El método p es la manera corta para "párrafo".

      +
      \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*li.*\)\033\[m.*
      +
      +
      +

      Expandiendo las Historietas en la Tabla

      +

      Bien, esto esta yendo maravilloso. Esto es algo simple, pero mantén en mente que no sabias nada sobre Ruby hace quince minutos atrás!<

      +

      Ultimo paso. Vamos a juntar todo, ¿sabes? ¡Juntémoslo como esos juegos de + campanillas hermosas que tintinean en los pórticos bajo la hermosa luz del sol + en la playa!

      +

      Asegúrate de que las historietas están cargadas: comics = load_comics( '/comics.txt' )

      +

      Ahora, hagamos una lista de links para cada historieta:

      +
      • Popup.make do
      • +
      •   h1 "Comics on the Web"
      • +
      •   list do
      • +
      •     comics.each do |name, url|
      • +
      •       link name, url
      • +
      •     end
      • +
      •   end
      • +
      • end
      • +
      +

      Puedes clickear en los links y leer las historietas ¡inclusive en la ventana principal! ¡Bárbaro!

      +
      \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*a href.*li.*a href.*\)\033\[m.*
      +
      +
      +

      Sumario #6 lo que Significa que has Llegado Muy Lejos

      +

      Eres un clérigo nivel 6 de Ruby. Quiero decir que buen trabajo has hecho. Vamos a revisar:

      +
        +
      • Agregaste tu propio método con def y usaste ese método load_comics varias veces.
      • +
      • Librerias. Tú usaste el método require para cargar la librería popup.
        Escribiendo: require 'popup'
      • +
      • Y como si no fuera suficiente, hiciste tu propia página web para listar los archivos de historietas. ¡Hiciste un programa real!
      • +
      +

      Entonces ¿Qué podrá venir luego? ¿Qué deberías aprender posiblemente ahora? + Ja, esta es la mejor parte. Has recorrido un largo camino y ahora descubrirás + las clases. En dos lecciones mas y ya estarás hecho.

      +

      Tempranamente, creamos un hash como este: Hash.new pruébalo.

      +
      \{\}
      +
      +
      +

      No una Clase de Escuela, Una Clase Trabajadora

      +

      Ves, las llaves vacías {} son abreviaciones para Hash.new. El método new + es usado para hacer objetos de cierta clase. (Piensa "clase" como en "clase + trabajadora" — un grupo especifico de objetos similares, tienen el + mismo trabajo, la misma camisa.)

      +

      Pregúntate esto: ¿Cómo haría mi blog en Ruby? ¿Dónde deberías + comenzar? Bien, deberías guardar tus entradas del blog en un archivo, ¿cierto? + Pero ¿cómo seguirías los títulos de las entradas y el momento en que fue creado? + Y cuando cargas el archivo, ¿cómo se vería en Ruby? ¿Sería un Hash? ¿O un Array? ¿O + un Array de Arrys? ¿O alguna otra cosa?

      Yo realmente creo que querrás usar una clase. Ya estas familiarizado con varias clases: Hash, Array, String.

      +

      Hagamos una clase nueva: class BlogEntry.

      +
      ..
      +
      +
      +

      El Relleno del Blog esta Hecho de

      +

      Has abierto una nueva clase BlogEntry. ¿De que están hechas las entradas de tu blog? Un titulo, seguro. también, + la fecha en la que fue creada. El texto entero de la entrada.

      +

      Vamos a poner el estado de ánimo, también, tal como LiveJournal. La internet ha traído de vuelta las personas de palitos y emoticones + fuera de la bancarrota.¡Que emoción!

      +

      Bueno, ya tienes la primera línea de la clase, aquí esta el resto:/p> +

      • class BlogEntry
      • +
      •   attr_accessor :title, :time, :fulltext, :mood
      • +
      • end
      • +
      +
      nil
      +
      +
      +

      Accessors Son las Extremidades Colgantes

      +

      Hey, buena clase, colega. Tienes una nueva clase BlogEntry. Para comenzar una entrada:
      entry = BlogEntry.new.

      +

      En la definición de la clase, usaste un método llamado attr_accessor. Existen varios métodos attribute + atributo, como este que agregan pequeñas configuraciones a la clase. Estos atributos son simplemente variables adosadas a la clase.

      +

      Piénsalo de este modo. Una clase es como una persona. Esa forma de estrella + del humano. Y los atributos son las extremidades, las diferentes partes que + hacen un cuerpo.

      +

      Para crear el titulo de tu entrada: entry.title = "Today Mt. Hood Was Stolen!"

      +
      ".+"
      +
      +
      +

      Un Objeto, Ese Estupendo Paquete Pequeño

      +

      Sigue adelante y pon la hora: entry.time = Time.now

      +

      Y el estado de animo: entry.mood = :sick

      +

      Y el anuncio en si: entry.fulltext = "I can't believe Mt. Hood was stolen! I am speechless! It was stolen by a giraffe who drove away + in his Cadillac Seville very nonchalant!!"

      +

      Para ver toda la configuración, simplemente escribe en el prompt: entry.

      +
      #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
      +
      +
      +

      Agilizando

      +

      Genial, tu blog es impresionante. Hey, hagamos las cosas algo mas fácil. No querrás + poner la hora asi todas las veces que postees. Solo quieres escribir el titulo, + el contenido y el emoticon rápido, ¿verdad?

      +

      Vamos a agregar un método initialize.

      +
      • class BlogEntry
      • +
      •   def initialize( title, mood, fulltext )
      • +
      •     @time = Time.now
      • +
      •     @title, @mood, @fulltext = title, mood, fulltext
      • +
      •   end
      • +
      • end
      • +
      +

      Una vez que lo hallas escrito, prueba hacer una nueva entrada: BlogEntry.new

      +
      ArgumentError: wrong number of arguments \(0 for 3\).*
      +
      +
      +

      Tu le Has Enseñado al Blog a Rechazar lo Malo

      +

      ¿Viste como usamos dentro de la clase el símbolo arroba? De este modo: @time = Time.now

      +

      Fuera de la clase, usamos accesos (accessors): entry.time = Time.now Pero dentro variables de instancia: @time = Time.now + Son exactamente lo mismo, pero expresado en dos partes diferentes de tu programa.

      +

      tu blog ahora necesita un titulo, estado de ánimo y el post para funcionar. Cuando un nuevo BlogEntry es creado, el método initialize + es usado para chequear cualquier argumento para new. ¡Uh, necesitamos tres argumentos!

      +

      Prueba de nuevo con los tres.

      +

      entry2 += BlogEntry.new( "I Left my Hoodie on the Mountain!", :confused, "I am +never going back to that mountain and I hope a giraffe steals it." )

      +
      #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
      +
      +
      +

      Una Jirafa No Ha Robado el Sumario #7

      +

      Aha, estas aquí. Y todo en una pieza. Todavía vamos a hacer tu blog realidad, pero hasta entonces, vamos a revisar, ¿bien?

      +
        +
      • Clases. Todo en Ruby es algún tipo de objeto. Las clases explican los objetos. Como ciertos objetos + trabajan. Por ejemplo, haces algunas entradas de blog y estos objetos están explicados en la clase BlogEntry. + En otras palabras: los llamas objetos del tipo BlogEntry.
      • +
      • Accessors son variables adosadas a un objeto que pueden ser usadas fuera del objeto. (entry.time = Time.now)
      • +
      • Variables de instancia son las mismas variables para accesos dentro del objeto. + Como en la definición de un método. (@time = Time.now)
      • +
      +

      Bueno, vamos a envolver las cosas, niño. Aquí esta el ultimo capitulo de la FASCINANTE épica + historia de Try Ruby! Ahora que ya has probado como todo funciona, ¿cómo vas a + usar eso alrededor de la casa y en tu tienda de comestibles? Eres una + gran persona (una de mis favoritas), pero necesitas dirección.

      +

      Vamos a terminar tu blog. Tienes entradas de blog, pero no un blog.

      +

      Pon las entradas en un array: blog = [entry, entry2]

      +
      \[#.BlogEntry:0x[0-9a-f]+.*, #.BlogEntry:0x[0-9a-f]+.*\]
      +
      +
      +

      Todo Se Trata de Combinar Cosas

      +

      Cosas hermosas pueden hacerse de partes simples de Ruby, especialmente + cuando las combinas entre ellas para formar algo nuevo. Aquí tenemos un blog + hecho de un array de clases. Y, en realidad, Ruby realmente hace buenas cosas + con este tipo de criaturas.

      +

      Aquí hay un puñado de cosas que puedes hacer con tu blog array:

      +
      • Querrás ordenar tus entradas de mas reciente a viejas. Puedes hacerlo con:
        + blog.sort_by { |entry| entry.time }.reverse
        Ve sort_by para más explicación.
      • +
      • Si quieres buscar en el blog por cualquier cosa relacionada con "cadillac":
        + blog.find_all { |entry| entry.fulltext.match(/cadillac/i) }
        + Lee mas en find_all + y match + para descubrir como funciona. También: /giraffe/i es un objeto Regexp, usado para concordar palabras.
      • +
      • Y agregar nuevas entradas con blog << new_entry
        + Y aquí la documentación del método <<.
      • +
      +

      Puedes buscar entre la lista de los métodos con los que viene Ruby en ruby-doc.org's core. + Otra buena lista hay en online pickaxe.

      +

      Un método realmente útil (probablemente yo uso esto mas que otra cosa) es map. Escribe: blog.map { |entry| entry.mood }

      +
      \[(:\w+, )+:\w+\]
      +
      +
      +

      Mira Su Cara — La Transformación Ha Comenzado

      +

      El método map recorre un array y reemplaza cada ítem con algo nuevo. ¿Dices que quieres reemplazar cada entrada de tu blog + con el nombre de Bruce Willis?. Hazlo entonces: blog.map { "Bruce Willis" }

      +

      Como el bloque siempre devuelve el string "Bruce Willis", eso es lo que obtienes. En el código que acabas de usar, la entrada entry wfue reemplazada + por solo el entry.mood.

      +

      Ahora, quiero que hagas un popup con las entradas de tu blog. Yo no te voy a + dar todo el código. Solo te voy a dar una parte.

      +
      • blog.each do |entry|
      • +
      •   h2 entry.title
      • +
      •   p entry.fulltext
      • +
      • end
      • +
      +

      Ahora, yo espero que pongas el código del popup alrededor y agregues un titulo con el nombre de tu blog usando h1. Como extra, tienes la hora de cada entrada para mostrar.

      +
      \033\[1;JSm.*popup_make\(.*h1.*h2.*li.*h2.*li.*\)\033\[m.*
      +
      +
      +

      Eres Una Especie de Gurú Web, Tengo Estrellas en Mis Ojos

      +

      Bien, ¡eso es! Este es exactamente el código que puedes usar para escribir tu + propio blog real en Ruby. Si te sientes aventurero, yo chequearía el video de + Rails videos donde muestran a un joven compañero creando un blog en 15 minutos. Solo sientete cómodo y mira.

      +

      Debo mencionar a Rails. Tú has estado aprendiendo el lenguaje Ruby, como + hablarlo. Pero Rails es grupo de librerías (algo asi como la librería de popup + que hemos estado usando.) Es un poderoso conjunto de herramientas para crear + sitios web. Si estas interesado en aprender sobre Rails, yo miraría head + por aquí directamente. ¡Empieza a usar tus habilidades en Ruby apropiadamente!

      +

      Algo que tiene Rails son métodos para manejar fechas fácilmente. Como, prueba: Time.now - 2.weeks

      +
      class Integer; def weeks; self * 7*24*60*60; end; end
      +
      \w+ \w+ \d+ \d{2}:\d{2}:\d{2} .*
      +
      +
      +

      Si Quieres Empezar Poco a Poco

      +

      Si quieres comenzar escribiendo pequeños programas en Ruby para practicar, tengo un proyecto llamado MouseHole + que es una pequeña caja de herramientas en la web para escribir programas cortos en Ruby. Puedes ver aquí algunos + scripts para ver que quiero decir.

      +

      MouseHole no es para escribir sitios web en realidad. Es para escribir + pequeños programas y correrlos dentro del navegador. Como hay un programa block + de notas para MouseHole y un programa que agrega una imagen de un ratón a los + links de la web que linkean a programas de MouseHole.

      +

      Tengo un script de MouseHole dentro de un archivo aquí mismo:
      + print File.read("/MouseHole/flickrpedia.user.rb")

      +
      .*Inserts Wikipedia links for Flickr tags.*
      +
      +
      +

      Sumario #8, El Sumario Hey-Relájate-Lo-Hiciste-Bien

      +

      Esta ultima sección se tomó un momento para relajarse, para darte algunos consejos de como + puedes usar Ruby. Si lo has disfrutado, descarga Ruby e instálalo.

      + +

      Una vez que tengas Ruby instalado, puedes usar Ruby Interactivo ejecutando el comando irb en el prompt de tu sistema. Para mas sobre Irb, esta + The Tiger's Vest para ayudarte.

      +

      Tú realmente mereces una torta doble-capa con doble-doble azúcar glaseado y + un tipo tocando una de esas guitarras que son doble-guitarra. Quiero decir + terminaste, ¡lo hiciste! No hay dudas de eso, ¡eres un gran ser certificado!

      +
      +
      + \ No newline at end of file diff --git a/TryRuby/public/tutorials/intro.html b/TryRuby/public/tutorials/intro.html new file mode 100644 index 0000000..56c1d1c --- /dev/null +++ b/TryRuby/public/tutorials/intro.html @@ -0,0 +1,680 @@ + +
      +

      Using the Prompt

      +

      The blue window above is a Ruby prompt. Type a line of Ruby code, hit Enter + and watch it run!

      +

      For example, try typing some math. Like: 2 + 6

      +
      \d+
      +
      +
      +

      Numbers & Math

      +

      Good! You did a bit of math. See how the answer popped out?

      +

      Ruby recognizes numbers and mathematic symbols. You could try some other math like:

      +
      • 4 * 10
      • +
      • 5 - 12
      • +
      • 40 / 4
      +

      Sure, computers are handy and fast for math. Let's move on. Want to see your name reversed? + Type your first name in quotes like this: "Jimmy"

      +
      "(\w+)"
      +
      +
      +

      Say Your Name Backwards

      +

      Perfect, you've formed a string from the letters of your name. A string + is a set of characters the computer can process.

      +

      Imagine the letters are on a string of + laundry line and the quotes are clothespins holding the ends. The quotes mark the beginning and end.

      +

      To reverse your name, type: "Jimmy".reverse (Don't forget the dot!)

      +
      "(\w+)"
      +
      +
      +

      Counting the Letters

      +

      You have used the reverse method on your name! By enclosing your name in + quotes, you made a string. Then you called the reverse method, which works on strings to flip + all the letters backwards.

      +

      Now, let's see how many letters are in your name: "Jimmy".length

      +
      \d+
      +
      +
      +

      On Repeat

      +

      Now, I'm sure by now you're wondering what any of this is good for. Well, I'm sure you've been to + a website that screamed, Hey, your password is too short! See, some programs + use this simple code.

      +

      Watch this. Let's multiply your name by 5. "Jimmy" * 5

      +
      "(\w+)"
      +
      +
      +

      Hey, Summary #1 Already

      +

      Let's look at what you've learned in the first minute.

      +
        +
      • The prompt. Typing code into the green prompt gives you + an answer from a red prompt. All code gives an answer.
      • +
      • Numbers and strings are Ruby's math and text objects.
      • +
      • Methods. You've used English-language methods like reverse + and symbolic methods like * (the multiplication method.) Methods are action!
      • +
      +

      This is the essence of your learning. Taking simple things, toying with + them and turning them into new things. Feeling comfortable yet? I promise you are.

      +

      Okay, let's do something uncomfortable. Try reversing a number: 40.reverse

      +
      NoMethodError: undefined method `reverse' for (\d+):Fixnum
      +
      +
      +

      Stop, You're Barking Mad!

      +

      You can't reverse the number forty. I guess you can hold your monitor up to the + mirror, but reversing a number just doesn't make sense. Ruby has tossed an error + message. Ruby is telling you there is no method reverse for numbers.

      +

      Maybe if you turn it into a string: 40.to_s.reverse.

      +
      \"(\d+)\"
      +
      +
      +

      Boys are Different From Girls

      +

      And numbers are different from strings. While you can use methods on any object + in Ruby, some methods only work on certain types of things. But you can always + convert between different types using Ruby's "to" methods.

      +
      • to_s converts things to strings.
      • +
      • to_i converts things to integers (numbers.)
      • +
      • to_a converts things to arrays.
      • +
      +

      What are arrays?! They are lists. Type in a pair of brackets: [].

      +
      \[\]
      +
      +
      +

      Standing in Line

      +

      Great, that's an empty list. Lists store things in order. + Like standing in line for popcorn. You are behind someone and you wouldn't + dream of pushing them aside, right? And the guy behind you, you've got a + close eye on him, right?

      +

      Here's a list for you. Lottery numbers: [12, 47, 35].

      +
      \[(\d+(, )?){2,}\]
      +
      +
      +

      One Raises Its Hand

      +

      A list of lottery numbers. Which one is the highest?

      +

      Try: [12, 47, 35].max.

      +
      (\d+)
      +
      +
      +

      Tucking a List Away

      +

      Good, good. But it's annoying to have to retype that list, isn't it?

      +

      Let's save our numbers inside a ticket like so: ticket = [12, 47, 35]

      +
      \[(\d+(, )?){2,}\]
      +
      +
      +

      Now Type Ticket

      +

      Now, type: ticket

      +
      \[(\d+(, )?){2,}\]
      +
      +
      +

      Saved, Tucked Away

      +

      Fantastic! You've hung on to your lotto numbers, tucking them away inside a + variable called ticket.

      +

      Let's put your lotto numbers in order, how about? Use: ticket.sort!

      +
      \[(\d+(, )?){2,}\]
      +
      +
      +

      Summary #2 is Upon Us

      +

      You had a list. You sorted the list. The ticket variable is now changed.

      +

      Did you notice that the sort! method has a big, bright exclamation at the end? + A lot of times Ruby methods shout like that if they alter the variable for good. It's nothin + special, just a mark.

      +

      Now, look how your second minute went:

      +
        +
      • Errors. If you try to reverse a number or do anything fishy, + Ruby will skip the prompt and tell you so.
      • +
      • Arrays are lists for storing things in order.
      • +
      • Variables save a thing and give it a name. You used the + equals sign to do this.
        Like: ticket = [14, 37, 18].
      • +
      +

      In all there are eight lessons. You are two-eighths of the way there! + This is simple stuff, don't you think? Good stuff up ahead.

      +

      Let's change directions for a moment. I've stuffed a bit of poetry for you in + a certain variable. Take a look. Type print poem

      +
      poem = "My toast has flown from my hand\nAnd my toast has gone to the +moon.\nBut when I saw it on television,\nPlanting our flag on Halley's +comet,\nMore still did I want to eat it.\n"
      +
      My toast (.+)
      +
      +
      +

      Sadly, You Hate Toast Poetry

      +

      Look, it's okay. You don't have to like it. Hack it up, be my guest.

      +

      Instead of toast, go for a melon or something. Try this: poem['toast'] = 'honeydew'

      +

      And then type print poem by itself to see the new poem.

      +
      My honey(.+)
      +
      +
      +

      Ready, Aim

      +

      The square brackets you just used are very common in Ruby. Remember, you typed: poem['toast'] = 'honeydew'. That box with the word toast has a square bracket on each side, see?

      +

      The +two brackets are like sights used to line up a target. Exactly. These +brackets mean, "I am looking for ____." Ready, aim. Here you're looking +for toast and swapping it out with fruit.

      +

      Here's a question: what happens when we reverse this whole poem? poem.reverse +

      "\\n.ti tae ot (.+)"
      +
      +
      +

      Too Much Reversal

      +

      Okay, sure. So the whole poem's been turned backwards, letter-by-letter. I really want to just + reverse the lines, though. Move the last line up to first and the first line down to last. Backwards, but not + that backwards.

      +

      Here's how: poem.lines.to_a.reverse

      +
      \["More still did I(.+)"\]
      +
      +
      +

      Ringlets of Chained Methods

      +

      So what do you see? What happened there? You typed poem.lines.to_a.reverse and what happened?

      +

      Two things happened. You turned the poem into a +list using lines.to_a. lines decides the way +the string is split up, then to_a converted it into an +Array. (To array.) Different methods, such +as bytes and chars can be used in place +of lines. By using lines, ruby will return each line of the poem.

      +

      Then, you reversed that list. You had each line. You reversed them. That's it.

      +

      Let's tack one more method on the end there: print poem.lines.to_a.reverse.join +

      More still did I(.+)
      +
      +
      +

      Of All the Summaries, #3 is Here Now

      +

      Good show, my friend! The join method took that list of reversed lines and put them + together into a string. (Sure, you could have also just used to_s.)

      +

      Review time.

      +
        +
      • Exclamations. Methods may have exclamations (and also question marks) + in their name. No big deal. Try: poem.include? "my hand"
      • +
      • Square brackets. Target and find things. Search and replace.
      • +
      • Chaining methods lets you get a lot more done. Break up a poem, + reverse it, reassemble it: poem.lines.to_a.reverse.join
      • +
      +

      At this point, you may want to tinker with the poem a bit more. A complete list of all + the String methods is + + here. + Go ahead and try a few (such as poem.downcase or poem.delete.)

      +

      When you're ready to move on, type: books = {}

      +
      \{\}
      +
      +
      +

      A Wee Blank Book

      +

      You've made an empty hash. (Also known as: an empty dictionary.)

      +

      We're going to stuff some miniature book reviews in this hash. Here's our rating system:

      +
        +
      • :splendid → a masterpiece.
      • +
      • :quite_good → enjoyed, sure, yes.
      • +
      • :mediocre → equal parts great and terrible.
      • +
      • :quite_not_good → notably bad.
      • +
      • :abyssmal → steaming wreck.
      • +
      +

      To rate a book, put the title in square brackets and put the rating after the equals.

      +

      For example: books["Gravity's Rainbow"] = :splendid

      +
      :\w+
      +
      +
      +

      More Bite-Size Reviews

      +

      Keep going, fill it up with reviews. And, if you want to see the whole list, + just type: books

      +

      Again, the ratings are: :splendid, :quite_good, :mediocre, + :quite_not_good, and :abyssmal.

      +

      These ratings are not strings. When you place a colon in front of a simple word, you get a + symbol. Symbols are cheaper than strings (in terms of computer memory.) If + you use a word over and over in your program, use a symbol. Rather than having thousands of + copies of that word in memory, the computer will store the symbol only once.

      +

      Once you've got three or four books in + there, type: books.length.

      +
      [3-9]
      +
      +
      +

      Wait, Did I Like Gravity's Rainbow?

      +

      See, the length method works on strings, list and hashes. One great thing about + Ruby is that names are often reused, which means fewer names you need to remember.

      +

      If you'd like to look up one of your old reviews, again put the title in the square. But leave off + the equals.

      +

      Just like this: books["Gravity's Rainbow"]

      +
      :\w+
      +
      +
      +

      Hashes as Pairs

      +

      Keep in mind that hashes won't keep things in order. That's not their job. It'll just pair up two + things: a key and a value. In your reviews, the key is the book's + title and the value is the rating.

      +

      If you want to just see the titles of the books you've reviewed: books.keys

      +
      \[".*"\]
      +
      +
      +

      Are You Harsh?

      +

      So are you giving out harsh, unfair reviews? Let's keep score with this hash:
      ratings = Hash.new {0}

      +

      Then, okay, now let's count up your reviews. Just stay with me. Type:
      + books.values.each { |rate| ratings[rate] += 1 }

      +

      (The straight line in the code is the pipe character, probably located right above the + Enter key on your keyboard.)

      +
      \[:.+\]
      +
      +
      +

      A Tally

      +

      Great, wow! You've made a scorecard of your ratings. Type ratings to see the count. + This new hash shows a rating and then the number of times you've given that rating.

      +

      One of the amazing new things we've just used is a block. We're going to + explore these more in the next summary. But, basically, a block is a bit of Ruby code surrounded + by curly braces.

      +

      Let's try another block: 5.times { print "Odelay!" }

      +
      Odelay!Od.*
      +
      +
      +

      Now Arriving at Summary #4

      +

      Blocks are always attached to methods. Like the times method, which takes the + block and runs the code over and over. (In this case: five times.)

      +

      This last lesson was a bit longer. You've probably used up three minutes learning about:

      +
        +
      • Hashes. The little dictionary with the curly pages: {}.
      • +
      • Symbols. Tiny, efficient code words with a colon: :splendid.
      • +
      • Blocks. Chunks of code which can be tacked on to many of Ruby's methods. Here's the + code you used to build a scorecard:
        books.values.each { |rate| ratings[rate] += 1 }.
      • +
      +

      On your computer, you probably have a lot of different files. Files with pictures in them, + files with programs in them. And files are often organized into folders, also called: + directories.

      +

      I've prepared a few directories for you. Take a look: + Dir.entries "/"

      +
      \["\.", .+\]
      +
      +
      +

      The Private Collection of Dr. Dir

      +

      You've just listed out everything in the top directory. The root directory, indicated + by a single slash. Containing some programs and other tutorials and such.

      +

      So, what is the Dir.entries method? Well, it's just a method, right? + entries is a method called on the Dir variable. + And Dir has a collection of methods for checking out file directories.

      +

      One other little thing we haven't really talked about openly. Method arguments, highlighted in green.

      +
        +
      • Dir.entries "/": Anything listed after a method + is considered an attachment.
      • +
      • print poem: See, print is an ordinary method. And the + poem is attached. To be printed.
      • +
      • print "pre", "event", "ual", "ism" has several arguments, with commas + between them.
      • +
      +

      To list just the text files in that directory: Dir["/*.txt"]

      +
      \["\/comics\.txt"\]
      +
      +
      +

      Come, Read Comics With Me

      +

      The Dir[] method is like entries but you search for files + with wildcard characters. Here, we see those square brackets again! Notice how + they still mean, "I am looking for _____?"

      +

      More specifically: "I am looking for files which end with .txt."

      +

      Let's crack open this comics file, then. Here's the way:
      + print File.read("/comics.txt")

      +
      Achewood.+
      +
      +
      +

      Mi Comicas, Tu Comicas

      +

      All right! We can start to use files to store things. This is great because normally when + we exit Ruby, all our variables will be gone. Ruby, by itself, forgets these things. + But if we save things in files, we can read those files in future Ruby escapades.

      +

      Hey, and guess what? The /Home directory is yours! I gave it to you! I am generous! Let's make a copy of the comics file.

      +

      You'll want to: FileUtils.copy('/comics.txt', '/Home/comics.txt') +

      If you've already created the file, use File.delete('/Home/comics.txt') to trash it.

      +
      nil
      +
      +
      +

      Your Own Turf

      +

      Okay, you've got a copy. Check it: Dir["/Home/*.txt"]

      +

      To add your own comic to the list, let's open the file in append mode.

      +

      Start like this: File.open("/Home/comics.txt", "a") do |f|.

      +
      ..
      +
      +
      +

      And Now For the Startling Conclusion

      +

      So your prompt has changed. See that? Your prompt is a double dot now.

      +

      In this tutorial, this prompt means that Ruby is expecting you to type more. + As you type in the lines of Ruby code, the double dots will continue until you + are completely finished.

      +

      Hot tip: If you want to stop working on the code and break out of the double dots, use the reset + command. If you want to go the previous page of the tutorial, use the back command.

      +

      Here's your code. You've already typed the first line, so just enter the second line. (The \n + is an Enter character.

      +
      • File.open("/Home/comics.txt", "a") do |f|
      • +
      •   f << "Cat and Girl: http://catandgirl.com/\n"
      • +
      • end
      • +
      +

      And, since you're getting so advanced and capable here, one other tip: you can use the up and down arrow keys to + edit your old commands or run them again.

      +
      ..
      +
      +
      +

      Ruby Sits Still

      +

      That last line adds the Cat and Girl comic to the list, but Ruby's going to wait until you're totally finished to + take action.

      +

      Now, to finish the code you've started. You opened a new block when you typed do. + So far the blocks we've seen have used curly braces. This time we'll be using do and end instead + of curly braces. A lot of Rubyists will use do...end when the block goes on for many lines.

      +

      Let's get that block finished now, with: end

      +
      • File.open("/Home/comics.txt", "a") do |f|
      • +
      •   f << "Cat and Girl: http://catandgirl.com/\n"
      • +
      • end
      • +
      +
      #.File:/Home/comics\.txt \(closed\).
      +
      +
      +

      The Clock Nailed To the File

      +

      Good, good! You've added that new comic to the file. You can see for yourself: print File.read("/Home/comics.txt")

      +

      What time was it when you changed the file? Let's check. Type: File.mtime("/Home/comics.txt")

      +
      \d{4}-\d+-\d+ \d{2}:\d{2}:\d{2} [+-]\d{4}
      +
      +
      +

      Just the Hour Hand

      +

      Great, there's the time. The precise time exactly when you added to the file. The mtime gives you a Ruby Time object.

      +

      If you want to check just what hour it was, hit the up arrow key and change the line to: File.mtime("/Home/comics.txt").hour

      +
      \d+
      +
      +
      +

      Hallo, Who's There? And Summary #5 Waves Its Hat!

      +

      Well done, well done, well done, well done! Truly, truly, truly, truly, truuuuuuuuly!

      +

      Here's the last few minutes of your life in review:

      +
        +
      • Files. What more can be said? Lots of methods for editing files and lookin around in directories.
      • +
      • Arguments. Arguments are a list of things sent into a method. With commas between.
      • +
      • We also spoke about do and end which are another way to make a block.
      • +
      +

      You totally know how to use Ruby now. I mean you've got down the essentials. You just need to keep learning more methods and + try out more complex blocks.

      +

      But there's one side of Ruby we haven't settled. Making your own methods and classes.

      +

      Ahem! Let's get it over with then.

      +

      Start with: def load_comics( path )

      +
      ..
      +
      +
      +

      In Ruby, Def Leppard Means Define Leppard (a Method)!

      +

      Hey, okay, you done it. You're making your own method. You started with def, followed by the name of the method. + And a list of arguments which the method will need. This isn't too scary and dangerous!

      +

      All we have to do is fill it up with Ruby and finish it up with end.

      +

      Here's the code:

      +
      • def load_comics( path )
      • +
      •   comics = {}
      • +
      •   File.foreach(path) do |line|
      • +
      •     name, url = line.split(': ')
      • +
      •     comics[name] = url.strip
      • +
      •   end
      • +
      •   comics
      • +
      • end
      • +
      +

      No need to indent, if you don't want. I just do that to make it read easier.

      +
      nil
      +
      +
      +

      The Ripened Fruit of Your Own Creation

      +

      A new method is born. Let us use it: comics = load_comics('/comics.txt')

      +

      If you have a problem, you might have mistyped. Use the back command and try again.

      +
      \{.*"Achewood"=."http://achewood.com/".*\}
      +
      +
      +

      Hey, Cool, a Comics Thing

      +

      In your Ruby window above, look at the code you've typed for the load_comics method. What is happening? You're + passing in the path variable and you're getting back the comics variable. Ruby lets the comics + hash trickle out the end of the method.

      +

      A number of methods were used to get the job done. See if you can spot them.

      +
      • File.foreach is a method which opens a file and hands each line to the block. The line + variable inside the do...end block took turns with each line in the file.
      • +
      • split is a method for strings, which breaks the string up into an array. An axe is laid on the colon + and the line is chopped in half, giving us the url and name for each comic.
      • +
      • strip removes extra spaces around the name. Just in case.
      • +
      +

      Right on. Bravo. You've got the comics in a Ruby hash. But what now? What good is this really?

      +

      Let's make a page of links. How about that? I went ahead and loaded a little library I've made for you.

      +

      Type: next. This is temporary as I updates new lessons.

      +
      true
      +
      +
      +

      Browser Puppetry

      +

      Excellent, you've loaded the popup library. It's saved in a file in the Libraries folder. See: Dir["/Libraries/*"]

      +

      The popup library contains a bunch of methods I've written which let you control a popup here on the Try Ruby site.

      +

      Here, try this: Popup.goto "http://google.com/"

      +
      \033\[1;JSm.*popup_goto\(.*\)\033\[m.*
      +
      +
      +

      Making Links and Spinning Webs

      +

      Our own lovely, little popup to manipulate. You can also fill it with your own goodies. We'll start small:

      +
      • Popup.make {
      • +
      •   h1 "My Links"
      • +
      •   link "Go to Google", "http://google.com/"
      • +
      • }
      • +
      +

      The term h1 (h-one) means a level-one header. In HTML, this is the largest size of header.

      +
      \033\[1;JSm.*popup_make\(.*h1.*a href.*\)\033\[m.*
      +
      +
      +

      Popups Are So Easy, It's Crazy

      +

      Looks good, you did it perfectly, just as you were asked. Let's make a list then.

      +

      Here's how you make a list with the popup library:

      +
      • Popup.make do
      • +
      •   h1 "Things To Do"
      • +
      •   list do
      • +
      •     p "Try out Ruby"
      • +
      •     p "Ride a tiger"
      • +
      •     p "(down River Euphrates)"
      • +
      •   end
      • +
      • end
      • +
      +

      The p method is short for "paragraph".

      +
      \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*li.*\)\033\[m.*
      +
      +
      +

      Spread the Comics on the Table

      +

      Okay, this is coming along wonderfully. This is simple stuff, but keep in mind that you didn't know any Ruby whatsoever just fifteen minutes ago!

      +

      Last +step. Let's tie it all together, you know? Let's make it chime together +like a very nice set of glistening chimes on the beach in the +maginificent sunlight!

      +

      Make sure the comics are loaded: comics = load_comics( '/comics.txt' )

      +

      Now, let's make a list of the links to each comic:

      +
      • Popup.make do
      • +
      •   h1 "Comics on the Web"
      • +
      •   list do
      • +
      •     comics.each do |name, url|
      • +
      •       link name, url
      • +
      •     end
      • +
      •   end
      • +
      • end
      • +
      +

      You can click on the links and read the comics in the little window even! Smashing!

      +
      \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*a href.*li.*a href.*\)\033\[m.*
      +
      +
      +

      Summary #6 Which Means You've Come So Far

      +

      You're a level six Ruby cleric. I mean what a great job you've done. Let's review:

      +
        +
      • You added your own method with def and you used that load_comics method several times.
      • +
      • Libraries. You used the require method to load the popup library.
        By typing: require 'popup'
      • +
      • And if that wasn't enough, you made your own web page from a list of comics in a file. You made a real program!
      • +
      +

      So +what could possibly be next? What could you possibly have to learn now? +Ha, this is the best part. You've come such a long way that we're going +to uncover classes. For two more short lessons and you're done.

      +

      Earlier, we created a hash like this: Hash.new Try it.

      +
      \{\}
      +
      +
      +

      Not a School Class, a Working Class

      +

      You see, the empty curly braces {} is a shortcut for Hash.new. The new +method is used to make objects of a certain class. (Think "class" as in +"working class" — a specific group of objects which are similar, have +the same jobs, the same shirts.)

      +

      Ask yourself this: How would I make a blog in Ruby? +Where would you start? Well, you might store your blog entries in a +file, right? But how would you keep track of the title of the entry and +the time it was posted? And when you loaded the file, how would it look +in Ruby? Would it be a Hash? Or an Array? Or an Array of Arrays? Or +something else?

      I really think you'll want to use a class. You are already familiar with many classes: Hash, Array, String.

      +

      Let's make a new class: class BlogEntry.

      +
      ..
      +
      +
      +

      The Stuff Blogs are Made of

      +

      You've opened up a new BlogEntry class. What is your blog entry made of? A title, sure. Also, a time when the entry was posted. The + full text of the entry.

      +

      We'll do a mood setting, too, just like LiveJournal. The Internet has really brought back stick people and smileys + out of bankruptcy. Emote!

      +

      Okay, so you've got the first line of the class, here's the rest:

      +
      • class BlogEntry
      • +
      •   attr_accessor :title, :time, :fulltext, :mood
      • +
      • end
      • +
      +
      nil
      +
      +
      +

      Accessors Are the Dangling Limbs

      +

      Hey, good class, man. You've got a new BlogEntry class. To start an entry:
      entry = BlogEntry.new.

      +

      In the class definition, you used a method called attr_accessor. There are many attribute methods like + this which add little settings to classes. These attributes are just variables attached to a class.

      +

      Think +of it this way. A class is like a person. That star-shaped human thing +out there. And the attributes are the dangling limbs, the different +parts that make up a body.

      +

      To set the title of your entry: entry.title = "Today Mt. Hood Was Stolen!"

      +
      ".+"
      +
      +
      +

      An Object, That Neat Little Package

      +

      Go ahead and set the post time: entry.time = Time.now

      +

      And the mood: entry.mood = :sick

      +

      And the post itself: entry.fulltext = "I can't believe Mt. Hood was stolen! I am speechless! It was stolen by a giraffe who drove away + in his Cadillac Seville very nonchalant!!"

      +

      To see all your settings, just type at the prompt: entry.

      +
      #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
      +
      +
      +

      Quickening it Up

      +

      Cool, +you're blog is awesome. Hey, let's make things a bit easier on you. +You're not going to want to set the time like that every time you post. +You just want to type in the title and the entry and the mood quickly, +right?

      +

      Let's add an initialize method.

      +
      • class BlogEntry
      • +
      •   def initialize( title, mood, fulltext )
      • +
      •     @time = Time.now
      • +
      •     @title, @mood, @fulltext = title, mood, fulltext
      • +
      •   end
      • +
      • end
      • +
      +

      Once you've got that typed in, try making a new entry: BlogEntry.new

      +
      ArgumentError: wrong number of arguments \(0 for 3\).*
      +
      +
      +

      You've Taught Your Blog to Reject Worthless Things

      +

      Did you see how inside the class we used the at-symbols? Like this: @time = Time.now

      +

      Outside the class, we use accessors: entry.time = Time.now But inside we use instance variables: @time = Time.now + They're the exact same thing, but expressed in two different places of your program.

      +

      Your blog now needs a title, a mood and a post in order to work. When a new BlogEntry is created, the initialize method + is used to check for any arguments to new. Uh, we need three arguments!

      +

      Try it again with all three.

      +

      entry2 += BlogEntry.new( "I Left my Hoodie on the Mountain!", :confused, "I am +never going back to that mountain and I hope a giraffe steals it." )

      +
      #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
      +
      +
      +

      A Giraffe Has Not Stolen Summary #7

      +

      Aha, you're here. And all in one piece. We're still going to make your blog real, but until then, let's review, okay?

      +
        +
      • Classes. Everything in Ruby is some kind of object. Classes explain objects. How a certain object works. + For example, you made a few blog entry objects and these objects are explained in the BlogEntry class. + In other words: you call them BlogEntry objects.
      • +
      • Accessors are variables attached to an object which can be used outside the object. (entry.time = Time.now)
      • +
      • Instance variables are the same variables you're using for accessors when inside the object. + Like in a method definition. (@time = Time.now)
      • +
      +

      Okay, +let's wrap things up, kid. Here's the last chapter of the GRIPPING epic +story of Try Ruby! Now that you've got a taste of how it all works, how +are you going to use it around the house and in your grocer's freezer? +You're a great person (one of my favorites), but you need guidance.

      +

      Let's finish your blog. You have blog entries, but no actual blog.

      +

      Put the entries into an array: blog = [entry, entry2]

      +
      \[#.BlogEntry:0x[0-9a-f]+.*, #.BlogEntry:0x[0-9a-f]+.*\]
      +
      +
      +

      It's All About Combining Things

      +

      Some +beautiful things can be done with the simple parts of Ruby, especially +when you combine them together into new things. Here we've got a blog +made of an array of classes. And, actually, Ruby really does good with +this kind of creature.

      +

      Here's a few things you can do with your array blog:

      +
      • You'll want to sort your entries from newest to oldest. You can do this with:
        + blog.sort_by { |entry| entry.time }.reverse
        See the sort_by explanation for more.
      • +
      • If you want to search your blog for anything related to "cadillac":
        + blog.find_all { |entry| entry.fulltext.match(/cadillac/i) }
        + Read all about find_all + and match + to figure out how that works. Also: the slashy /giraffe/i is a Regexp object, used for matching words.
      • +
      • Add new entries with blog << new_entry
        + And check out the << method documentation.
      • +
      +

      You can browse a list of all Ruby's built-in methods at ruby-doc.org's core list. + Another good list is at the online pickaxe.

      +

      One really useful method (I probably use this more than anything else) is map. Type: blog.map { |entry| entry.mood }

      +
      \[(:\w+, )+:\w+\]
      +
      +
      +

      Look at His Face — The Transformation Has Begun

      +

      The map method cycles through an array and replaces each item with something new. Say you wanted to replace each of your blog entries + with the name Bruce Willis. Do it so: blog.map { "Bruce Willis" }

      +

      Since the block always returns the string "Bruce Willis", that's what you get. In the code you just used, the entry was swapped out + for only the entry.mood.

      +

      Now, +I want you to make a popup with your blog entries. I'm not going to +give you all of the code. I'm just going to give you part of it.

      +
      • blog.each do |entry|
      • +
      •   h2 entry.title
      • +
      •   p entry.fulltext
      • +
      • end
      • +
      +

      Now, I expect you to put the popup code around it and add an h1 title with the name of your blog. For extra haroompf, have the time of each entry display.

      +
      \033\[1;JSm.*popup_make\(.*h1.*h2.*li.*h2.*li.*\)\033\[m.*
      +
      +
      +

      You are Some Kind of Web Guru, I Have Stars in My Eyes

      +

      Good, +that's it! This is exactly the code you can use to write your own real +Ruby blog. If you're feeling adventurous, I'd check out the Rails videos which show a swift young fellow creating a blog in 15 minutes. You just sit back and watch.

      +

      I +should mention Rails. You have been learning the Ruby language, how to +speak it. But Rails is a bunch of libraries (sort of like the popup +library we've been using.) It's a very powerful toolkit for building +websites. If you're interested in learning about Rails, I would head + over there right away. Start using your Ruby skills proper!

      +

      One thing Rails has is easy methods for dates. Like, try: Time.now - 2.weeks

      +
      class Integer; def weeks; self * 7*24*60*60; end; end
      +
      \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-+]\d{4}
      +
      +
      +

      If You Want to Start Small

      +

      If you'd like to start writing little Ruby programs just to practice, I have a project called MouseHole + which is a little web toolkit for writing short Ruby programs. You can look over a few + scripts to see what I mean.

      +

      MouseHole +isn't for writing web sites really. It's just for writing little +programs you run inside your browser. Like there's a notepad program +for MouseHole and a program which adds a mouse picture next to links on +the web which link to MouseHole programs.

      +

      I've got a MouseHole script inside a file here:
      + print File.read("/MouseHole/flickrpedia.user.rb")

      +
      .*Inserts Wikipedia links for Flickr tags.*
      +
      +
      +

      Summary #8, The Hey-Relax-You-Did-Good Summary

      +

      This last section took a moment to wind down, to give you some pointers as to how you can use Ruby. If you enjoyed yourself, + download Ruby and install it.

      + +

      Once you have Ruby installed, you can use Interactive Ruby by running irb on your system's prompt. For more on Irb, + there's The Tiger's Vest to help you.

      +

      You +really deserve a double-layer cake with double-double frosting and a +guy playing one of those guitars that's a double guitar. I mean you +finished, you really did! No doubt about it, you're a certified +red-blooded smartiac!

      +
      +
      + + diff --git a/TryRuby/public/tutorials/intro.html.broken b/TryRuby/public/tutorials/intro.html.broken new file mode 100755 index 0000000..5a6c27c --- /dev/null +++ b/TryRuby/public/tutorials/intro.html.broken @@ -0,0 +1,638 @@ + +
      +

      Using the Prompt

      +

      The blue window above is a Ruby prompt. Type a line of Ruby code, hit Enter + and watch it run!

      +

      For example, try typing some math. Like: 2 + 6

      +
      \d+
      +
      +
      +

      Numbers & Math

      +

      Good! You did a bit of math. See how the answer popped out?

      +

      Ruby recognizes numbers and mathematic symbols. You could try some other math like:

      +
      • 4 * 10
      • +
      • 5 - 12
      • +
      • 40 / 4
      +

      Sure, computers are handy and fast for math. Let's move on. Want to see your name reversed? + Type your first name in quotes like this: "Jimmy"

      +
      "(\w+)"
      +
      +
      +

      Say Your Name Backwards

      +

      Perfect, you've formed a string from the letters of your name. A string + is a set of characters the computer can process.

      +

      Imagine the letters are on a string of + laundry line and the quotes are clothespins holding the ends. The quotes mark the beginning and end.

      +

      To reverse your name, type: "Jimmy".reverse (Don't forget the dot!)

      +
      "(\w+)"
      +
      +
      +

      Counting the Letters

      +

      You have used the reverse method on your name! By enclosing your name in + quotes, you made a string. Then you called the reverse method, which works on strings to flip + all the letters backwards.

      +

      Now, let's see how many letters are in your name: "Jimmy".length

      +
      \d+
      +
      +
      +

      On Repeat

      +

      Now, I'm sure by now you're wondering what any of this is good for. Well, I'm sure you've been to + a website that screamed, Hey, your password is too short! See, some programs + use this simple code.

      +

      Watch this. Let's multiply your name by 5. "Jimmy" * 5

      +
      "(\w+)"
      +
      +
      +

      Hey, Summary #1 Already

      +

      Let's look at what you've learned in the first minute.

      +
        +
      • The prompt. Typing code into the green prompt gives you + an answer from a red prompt. All code gives an answer.
      • +
      • Numbers and strings are Ruby's math and text objects.
      • +
      • Methods. You've used English-language methods like reverse + and symbolic methods like * (the multiplication method.) Methods are action!
      • +
      +

      This is the essence of your learning. Taking simple things, toying with + them and turning them into new things. Feeling comfortable yet? I promise you are.

      +

      Okay, let's do something uncomfortable. Try reversing a number: 40.reverse

      +
      NoMethodError: undefined method `reverse' for (\d+):Fixnum
      +
      +
      +

      Stop, You're Barking Mad!

      +

      You can't reverse the number forty. I guess you can hold your monitor up to the + mirror, but reversing a number just doesn't make sense. Ruby has tossed an error + message. Ruby is telling you there is no method reverse for numbers.

      +

      Maybe if you turn it into a string: 40.to_s.reverse.

      +
      \"(\d+)\"
      +
      +
      +

      Boys are Different From Girls

      +

      And numbers are different from strings. While you can use methods on any object + in Ruby, some methods only work on certain types of things. But you can always + convert between different types using Ruby's "to" methods.

      +
      • to_s converts things to strings.
      • +
      • to_i converts things to integers (numbers.)
      • +
      • to_a converts things to arrays.
      • +
      +

      What are arrays?! They are lists. Type in a pair of brackets: [].

      +
      \[\]
      +
      +
      +

      Standing in Line

      +

      Great, that's an empty list. Lists store things in order. + Like standing in line for popcorn. You are behind someone and you wouldn't + dream of pushing them aside, right? And the guy behind you, you've got a + close eye on him, right?

      +

      Here's a list for you. Lottery numbers: [12, 47, 35].

      +
      \[(\d+(, )?){2,}\]
      +
      +
      +

      One Raises Its Hand

      +

      A list of lottery numbers. Which one is the highest?

      +

      Try: [12, 47, 35].max.

      +
      (\d+)
      +
      +
      +

      Tucking a List Away

      +

      Good, good. But it's annoying to have to retype that list, isn't it?

      +

      Let's save our numbers inside a ticket like so: ticket = [12, 47, 35]

      +
      \[(\d+(, )?){2,}\]
      +
      +
      +

      Now Type Ticket

      +

      Now, type: ticket

      +
      \[(\d+(, )?){2,}\]
      +
      +
      +

      Saved, Tucked Away

      +

      Fantastic! You've hung on to your lotto numbers, tucking them away inside a + variable called ticket.

      +

      Let's put your lotto numbers in order, how about? Use: ticket.sort!

      +
      \[(\d+(, )?){2,}\]
      +
      +
      +

      Summary #2 is Upon Us

      +

      You had a list. You sorted the list. The ticket variable is now changed.

      +

      Did you notice that the sort! method has a big, bright exclamation at the end? + A lot of times Ruby methods shout like that if they alter the variable for good. It's nothin + special, just a mark.

      +

      Now, look how your second minute went:

      +
        +
      • Errors. If you try to reverse a number or do anything fishy, + Ruby will skip the prompt and tell you so.
      • +
      • Arrays are lists for storing things in order.
      • +
      • Variables save a thing and give it a name. You used the + equals sign to do this.
        Like: ticket = [14, 37, 18].
      • +
      +

      In all there are eight lessons. You are two-eighths of the way there! + This is simple stuff, don't you think? Good stuff up ahead.

      +

      Let's change directions for a moment. I've stuffed a bit of poetry for you in + a certain variable. Take a look. Type print poem

      +
      poem = "My toast has flown from my hand\nAnd my toast has gone to the +moon.\nBut when I saw it on television,\nPlanting our flag on Halley's +comet,\nMore still did I want to eat it.\n"
      +
      My toast (.+)
      +
      +
      +

      Sadly, You Hate Toast Poetry

      +

      Look, it's okay. You don't have to like it. Hack it up, be my guest.

      +

      Instead of toast, go for a melon or something. Try this: poem['toast'] = 'honeydew'

      +

      And then type print poem by itself to see the new poem.

      +
      My honey(.+)
      +
      +
      +

      Ready, Aim

      +

      The square brackets you just used are very common in Ruby. Remember, you typed: poem['toast'] = 'honeydew'. That box with the word toast has a square bracket on each side, see?

      +

      The +two brackets are like sights used to line up a target. Exactly. These +brackets mean, "I am looking for ____." Ready, aim. Here you're looking +for toast and swapping it out with fruit.

      +

      Here's a question: what happens when we reverse this whole poem? poem.reverse +

      "\\n.ti tae ot (.+)"
      +
      +
      +

      Too Much Reversal

      +

      Okay, sure. So the whole poem's been turned backwards, letter-by-letter. I really want to just + reverse the lines, though. Move the last line up to first and the first line down to last. Backwards, but not + that backwards.

      +

      Here's how: poem.lines.to_a.reverse

      +
      \["More still did I(.+)"\]
      +
      +
      +

      Ringlets of Chained Methods

      +

      So what do you see? What happened there? You typed poem.lines.to_a.reverse and what happened?

      +

      Two things happened. You turned the poem into a +list using lines.to_a. lines decides the way +the string is split up, then to_a converted it into an +Array. (To array.) Different methods, such +as bytes and chars can be used in place +of lines. By using lines, ruby will return each line of the poem.

      +

      Then, you reversed that list. You had each line. You reversed them. That's it.

      +

      Let's tack one more method on the end there: print poem.lines.to_a.reverse.join +

      More still did I(.+)
      +
      +
      +

      Of All the Summaries, #3 is Here Now

      +

      Good show, my friend! The join method took that list of reversed lines and put them + together into a string. (Sure, you could have also just used to_s.)

      +

      Review time.

      +
        +
      • Exclamations. Methods may have exclamations (and also question marks) + in their name. No big deal. Try: poem.include? "my hand"
      • +
      • Square brackets. Target and find things. Search and replace.
      • +
      • Chaining methods lets you get a lot more done. Break up a poem, + reverse it, reassemble it: poem.lines.to_a.reverse.join
      • +
      +

      At this point, you may want to tinker with the poem a bit more. A complete list of all + the String methods is + + here. + Go ahead and try a few (such as poem.downcase or poem.delete.)

      +

      When you're ready to move on, type: books = {}

      +
      \{\}
      +
      +
      +

      A Wee Blank Book

      +

      You've made an empty hash. (Also known as: an empty dictionary.)

      +

      We're going to stuff some miniature book reviews in this hash. Here's our rating system:

      +
        +
      • :splendid → a masterpiece.
      • +
      • :quite_good → enjoyed, sure, yes.
      • +
      • :mediocre → equal parts great and terrible.
      • +
      • :quite_not_good → notably bad.
      • +
      • :abyssmal → steaming wreck.
      • +
      +

      To rate a book, put the title in square brackets and put the rating after the equals.

      +

      For example: books["Gravity's Rainbow"] = :splendid

      +
      :\w+
      +
      +
      +

      More Bite-Size Reviews

      +

      Keep going, fill it up with reviews. And, if you want to see the whole list, + just type: books

      +

      Again, the ratings are: :splendid, :quite_good, :mediocre, + :quite_not_good, and :abyssmal.

      +

      These ratings are not strings. When you place a colon in front of a simple word, you get a + symbol. Symbols are cheaper than strings (in terms of computer memory.) If + you use a word over and over in your program, use a symbol. Rather than having thousands of + copies of that word in memory, the computer will store the symbol only once.

      +

      Once you've got three or four books in + there, type: books.length.

      +
      [3-9]
      +
      +
      +

      Wait, Did I Like Gravity's Rainbow?

      +

      See, the length method works on strings, list and hashes. One great thing about + Ruby is that names are often reused, which means fewer names you need to remember.

      +

      If you'd like to look up one of your old reviews, again put the title in the square. But leave off + the equals.

      +

      Just like this: books["Gravity's Rainbow"]

      +
      :\w+
      +
      +
      +

      Hashes as Pairs

      +

      Keep in mind that hashes won't keep things in order. That's not their job. It'll just pair up two + things: a key and a value. In your reviews, the key is the book's + title and the value is the rating.

      +

      If you want to just see the titles of the books you've reviewed: books.keys

      +
      \[".*"\]
      +
      +
      +

      Are You Harsh?

      +

      So are you giving out harsh, unfair reviews? Let's keep score with this hash:
      ratings = Hash.new {0}

      +

      Then, okay, now let's count up your reviews. Just stay with me. Type:
      + books.values.each { |rate| ratings[rate] += 1 }

      +

      (The straight line in the code is the pipe character, probably located right above the + Enter key on your keyboard.)

      +
      \[:.+\]
      +
      +
      +

      A Tally

      +

      Great, wow! You've made a scorecard of your ratings. Type ratings to see the count. + This new hash shows a rating and then the number of times you've given that rating.

      +

      One of the amazing new things we've just used is a block. We're going to + explore these more in the next summary. But, basically, a block is a bit of Ruby code surrounded + by curly braces.

      +

      Let's try another block: 5.times { print "Odelay!" }

      +
      Odelay!Od.*
      +
      +
      +

      Now Arriving at Summary #4

      +

      Blocks are always attached to methods. Like the times method, which takes the + block and runs the code over and over. (In this case: five times.)

      +

      This last lesson was a bit longer. You've probably used up three minutes learning about:

      +
        +
      • Hashes. The little dictionary with the curly pages: {}.
      • +
      • Symbols. Tiny, efficient code words with a colon: :splendid.
      • +
      • Blocks. Chunks of code which can be tacked on to many of Ruby's methods. Here's the + code you used to build a scorecard:
        books.values.each { |rate| ratings[rate] += 1 }.
      • +
      +<<<<<<< HEAD + + +======= +

      On your computer, you probably have a lot of different files. Files with pictures in them, + files with programs in them. And files are often organized into folders, also called: + directories.

      +

      I've prepared a few directories for you. Take a look: + Dir.entries "/"

      +
      \["\.", .+\]
      +
      +
      +

      The Private Collection of Dr. Dir

      +

      You've just listed out everything in the top directory. The root directory, indicated + by a single slash. Containing some programs and other tutorials and such.

      +

      So, what is the Dir.entries method? Well, it's just a method, right? + entries is a method called on the Dir variable. + And Dir has a collection of methods for checking out file directories.

      +

      One other little thing we haven't really talked about openly. Method arguments, highlighted in green.

      +
        +
      • Dir.entries "/": Anything listed after a method + is considered an attachment.
      • +
      • print poem: See, print is an ordinary method. And the + poem is attached. To be printed.
      • +
      • print "pre", "event", "ual", "ism" has several arguments, with commas + between them.
      • +
      +

      To list just the text files in that directory: Dir["/*.txt"]

      +
      \["\/comics\.txt"\]
      +
      +
      +

      Come, Read Comics With Me

      +

      The Dir[] method is like entries but you search for files + with wildcard characters. Here, we see those square brackets again! Notice how + they still mean, "I am looking for _____?"

      +

      More specifically: "I am looking for files which end with .txt."

      +

      Let's crack open this comics file, then. Here's the way:
      + print File.read("/comics.txt")

      +
      Achewood.+
      +
      +
      +

      Mi Comicas, Tu Comicas

      +

      All right! We can start to use files to store things. This is great because normally when + we exit Ruby, all our variables will be gone. Ruby, by itself, forgets these things. + But if we save things in files, we can read those files in future Ruby escapades.

      +

      Hey, and guess what? The /Home directory is yours! I gave it to you! I am generous! Let's make a copy of the comics file.

      +

      You'll want to: FileUtils.copy('/comics.txt', '/Home/comics.txt') +

      If you've already created the file, use File.delete('/Home/comics.txt') to trash it.

      +
      nil
      +
      +
      +

      Your Own Turf

      +

      Okay, you've got a copy. Check it: Dir["/Home/*.txt"]

      +

      To add your own comic to the list, let's open the file in append mode.

      +

      Start like this: File.open("/Home/comics.txt", "a") do |f|.

      +
      ..
      +
      +
      +

      And Now For the Startling Conclusion

      +

      So your prompt has changed. See that? Your prompt is a double dot now.

      +

      In this tutorial, this prompt means that Ruby is expecting you to type more. + As you type in the lines of Ruby code, the double dots will continue until you + are completely finished.

      +

      Hot tip: If you want to stop working on the code and break out of the double dots, use the reset + command. If you want to go the previous page of the tutorial, use the back command.

      +

      Here's your code. You've already typed the first line, so just enter the second line. (The \n + is an Enter character.

      +
      • File.open("/Home/comics.txt", "a") do |f|
      • +
      •   f << "Cat and Girl: http://catandgirl.com/\n"
      • +
      • end
      • +
      +

      And, since you're getting so advanced and capable here, one other tip: you can use the up and down arrow keys to + edit your old commands or run them again.

      +
      ..
      +
      +
      +

      Ruby Sits Still

      +

      That last line adds the Cat and Girl comic to the list, but Ruby's going to wait until you're totally finished to + take action.

      +

      Now, to finish the code you've started. You opened a new block when you typed do. + So far the blocks we've seen have used curly braces. This time we'll be using do and end instead + of curly braces. A lot of Rubyists will use do...end when the block goes on for many lines.

      +

      Let's get that block finished now, with: end

      +
      • File.open("/Home/comics.txt", "a") do |f|
      • +
      •   f << "Cat and Girl: http://catandgirl.com/\n"
      • +
      • end
      • +
      +
      #.File:/Home/comics\.txt \(closed\).
      +
      +
      +

      The Clock Nailed To the File

      +

      Good, good! You've added that new comic to the file. You can see for yourself: print File.read("/Home/comics.txt")

      +

      What time was it when you changed the file? Let's check. Type: File.mtime("/Home/comics.txt")

      +
      \d{4}-\d+-\d+ \d{2}:\d{2}:\d{2} [+-]\d{4}
      +
      +
      +

      Just the Hour Hand

      +

      Great, there's the time. The precise time exactly when you added to the file. The mtime gives you a Ruby Time object.

      +

      If you want to check just what hour it was, hit the up arrow key and change the line to: File.mtime("/Home/comics.txt").hour

      +
      \d+
      +>>>>>>> nanothief/master +
      + +
      +

      Hallo, Who's There? And Summary #5 Waves Its Hat!

      +

      Well done, well done, well done, well done! Truly, truly, truly, truly, truuuuuuuuly!

      +

      Here's the last few minutes of your life in review:

      +
        +
      • Arguments. Arguments are a list of things sent into a method. With commas between.
      • +
      • We also spoke about do and end which are another way to make a block.
      • +
      +

      You totally know how to use Ruby now. I mean you've got down the essentials. You just need to keep learning more methods and + try out more complex blocks.

      +

      But there's one side of Ruby we haven't settled. Making your own methods and classes.

      +

      Ahem! Let's get it over with then.

      +
      +
      +

      In Ruby, Def Leppard Means Define Leppard (a Method)!

      +

      Hey, okay, you done it. You're making your own method. You started with def, followed by the name of the method. + And a list of arguments which the method will need. This isn't too scary and dangerous!

      +

      All we have to do is fill it up with Ruby and finish it up with end.

      +
      +
      +

      Hey, Cool, a Popup

      +

      Let's make a page of links. How about that? We'll need to load a little library I've made for you.

      +

      Type: require 'popup'

      +
      true
      +
      +
      +

      Browser Puppetry

      +

      Excellent, you've loaded the popup library.

      +

      The popup library contains a bunch of methods I've written which let you control a popup here on the Try Ruby site.

      +

      Here, try this: Popup.goto "http://google.com/"

      +
      \033\[1;JSm.*popup_goto\(.*\)\033\[m.*
      +
      +
      +

      Making Links and Spinning Webs

      +

      Our own lovely, little popup to manipulate. You can also fill it with your own goodies. We'll start small:

      +
      • Popup.make {
      • +
      •   h1 "My Links"
      • +
      •   link "Go to Google", "http://google.com/"
      • +
      • }
      • +
      +

      The term h1 (h-one) means a level-one header. In HTML, this is the largest size of header.

      +
      \033\[1;JSm.*popup_make\(.*h1.*a href.*\)\033\[m.*
      +
      +
      +

      Popups Are So Easy, It's Crazy

      +

      Looks good, you did it perfectly, just as you were asked. Let's make a list then.

      +

      Here's how you make a list with the popup library:

      +
      • Popup.make do
      • +
      •   h1 "Things To Do"
      • +
      •   list do
      • +
      •     p "Try out Ruby"
      • +
      •     p "Ride a tiger"
      • +
      •     p "(down River Euphrates)"
      • +
      •   end
      • +
      • end
      • +
      +

      The p method is short for "paragraph".

      +
      \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*li.*\)\033\[m.*
      +
      +
      +

      Spread the Comics on the Table

      +

      Okay, this is coming along wonderfully. This is simple stuff, but keep in mind that you didn't know any Ruby whatsoever just fifteen minutes ago!

      +

      Last +step. Let's tie it all together, you know? Let's make it chime together +like a very nice set of glistening chimes on the beach in the +maginificent sunlight!

      +

      Now, let's make a list of the links to each comic:

      +
      • Popup.make do
      • +
      •   h1 "Comics on the Web"
      • +
      •   list do
      • +
      •     comics.each do |name, url|
      • +
      •       link name, url
      • +
      •     end
      • +
      •   end
      • +
      • end
      • +
      +

      You can click on the links and read the comics in the little window even! Smashing!

      +
      \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*a href.*li.*a href.*\)\033\[m.*
      +
      +
      +

      Summary #6 Which Means You've Come So Far

      +

      You're a level six Ruby cleric. I mean what a great job you've done. Let's review:

      +
        +
      • You added your own method with def and you used that [coming soon]
      • +
      • You used the require method to load the popup library.
        By typing: require 'popup'
      • +
      • And if that wasn't enough, you made your own web page from a list of comics in a file no you havent. You made a real program!
      • +
      +

      So +what could possibly be next? What could you possibly have to learn now? +Ha, this is the best part. You've come such a long way that we're going +to uncover classes. For two more short lessons and you're done.

      +

      Earlier, we created a hash like this: Hash.new Try it.

      +
      \{\}
      +
      +
      +

      Not a School Class, a Working Class

      +

      You see, the empty curly braces {} is a shortcut for Hash.new. The new +method is used to make objects of a certain class. (Think "class" as in +"working class" — a specific group of objects which are similar, have +the same jobs, the same shirts.)

      +

      Ask yourself this: How would I make a blog in Ruby? +Where would you start? Well, you might store your blog entries in a +file, right? But how would you keep track of the title of the entry and +the time it was posted? And when you loaded the file, how would it look +in Ruby? Would it be a Hash? Or an Array? Or an Array of Arrays? Or +something else?

      I really think you'll want to use a class. You are already familiar with many classes: Hash, Array, String.

      +

      Let's make a new class: class BlogEntry.

      +
      ..
      +
      +
      +

      The Stuff Blogs are Made of

      +

      You've opened up a new BlogEntry class. What is your blog entry made of? A title, sure. Also, a time when the entry was posted. The + full text of the entry.

      +

      We'll do a mood setting, too, just like LiveJournal. The Internet has really brought back stick people and smileys + out of bankruptcy. Emote!

      +

      Okay, so you've got the first line of the class, here's the rest:

      +
      • class BlogEntry
      • +
      •   attr_accessor :title, :time, :fulltext, :mood
      • +
      • end
      • +
      +
      nil
      +
      +
      +

      Accessors Are the Dangling Limbs

      +

      Hey, good class, man. You've got a new BlogEntry class. To start an entry:
      entry = BlogEntry.new.

      +

      In the class definition, you used a method called attr_accessor. There are many attribute methods like + this which add little settings to classes. These attributes are just variables attached to a class.

      +

      Think +of it this way. A class is like a person. That star-shaped human thing +out there. And the attributes are the dangling limbs, the different +parts that make up a body.

      +

      To set the title of your entry: entry.title = "Today Mt. Hood Was Stolen!"

      +
      ".+"
      +
      +
      +

      An Object, That Neat Little Package

      +

      Go ahead and set the post time: entry.time = Time.now

      +

      And the mood: entry.mood = :sick

      +

      And the post itself: entry.fulltext = "I can't believe Mt. Hood was stolen! I am speechless! It was stolen by a giraffe who drove away + in his Cadillac Seville very nonchalant!!"

      +

      To see all your settings, just type at the prompt: entry.

      +
      #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
      +
      +
      +

      Quickening it Up

      +

      Cool, +you're blog is awesome. Hey, let's make things a bit easier on you. +You're not going to want to set the time like that every time you post. +You just want to type in the title and the entry and the mood quickly, +right?

      +

      Let's add an initialize method.

      +
      • class BlogEntry
      • +
      •   def initialize( title, mood, fulltext )
      • +
      •     @time = Time.now
      • +
      •     @title, @mood, @fulltext = title, mood, fulltext
      • +
      •   end
      • +
      • end
      • +
      +

      Once you've got that typed in, try making a new entry: BlogEntry.new

      +
      ArgumentError: wrong number of arguments \(0 for 3\).*
      +
      +
      +

      You've Taught Your Blog to Reject Worthless Things

      +

      Did you see how inside the class we used the at-symbols? Like this: @time = Time.now

      +

      Outside the class, we use accessors: entry.time = Time.now But inside we use instance variables: @time = Time.now + They're the exact same thing, but expressed in two different places of your program.

      +

      Your blog now needs a title, a mood and a post in order to work. When a new BlogEntry is created, the initialize method + is used to check for any arguments to new. Uh, we need three arguments!

      +

      Try it again with all three.

      +

      entry2 += BlogEntry.new( "I Left my Hoodie on the Mountain!", :confused, "I am +never going back to that mountain and I hope a giraffe steals it." )

      +
      #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
      +
      +
      +

      A Giraffe Has Not Stolen Summary #7

      +

      Aha, you're here. And all in one piece. We're still going to make your blog real, but until then, let's review, okay?

      +
        +
      • Classes. Everything in Ruby is some kind of object. Classes explain objects. How a certain object works. + For example, you made a few blog entry objects and these objects are explained in the BlogEntry class. + In other words: you call them BlogEntry objects.
      • +
      • Accessors are variables attached to an object which can be used outside the object. (entry.time = Time.now)
      • +
      • Instance variables are the same variables you're using for accessors when inside the object. + Like in a method definition. (@time = Time.now)
      • +
      +

      Okay, +let's wrap things up, kid. Here's the last chapter of the GRIPPING epic +story of Try Ruby! Now that you've got a taste of how it all works, how +are you going to use it around the house and in your grocer's freezer? +You're a great person (one of my favorites), but you need guidance.

      +

      Let's finish your blog. You have blog entries, but no actual blog.

      +

      Put the entries into an array: blog = [entry, entry2]

      +
      \[#.BlogEntry:0x[0-9a-f]+.*, #.BlogEntry:0x[0-9a-f]+.*\]
      +
      +
      +

      It's All About Combining Things

      +

      Some +beautiful things can be done with the simple parts of Ruby, especially +when you combine them together into new things. Here we've got a blog +made of an array of classes. And, actually, Ruby really does good with +this kind of creature.

      +

      Here's a few things you can do with your array blog:

      +
      • You'll want to sort your entries from newest to oldest. You can do this with:
        + blog.sort_by { |entry| entry.time }.reverse
        See the sort_by explanation for more.
      • +
      • If you want to search your blog for anything related to "cadillac":
        + blog.find_all { |entry| entry.fulltext.match(/cadillac/i) }
        + Read all about find_all + and match + to figure out how that works. Also: the slashy /giraffe/i is a Regexp object, used for matching words.
      • +
      • Add new entries with blog << new_entry
        + And check out the << method documentation.
      • +
      +

      You can browse a list of all Ruby's built-in methods at ruby-doc.org's core list. + Another good list is at the online pickaxe.

      +

      One really useful method (I probably use this more than anything else) is map. Type: blog.map { |entry| entry.mood }

      +
      \[(:\w+, )+:\w+\]
      +
      +
      +

      Look at His Face — The Transformation Has Begun

      +

      The map method cycles through an array and replaces each item with something new. Say you wanted to replace each of your blog entries + with the name Bruce Willis. Do it so: blog.map { "Bruce Willis" }

      +

      Since the block always returns the string "Bruce Willis", that's what you get. In the code you just used, the entry was swapped out + for only the entry.mood.

      +

      Now, +I want you to make a popup with your blog entries. I'm not going to +give you all of the code. I'm just going to give you part of it.

      +
      • blog.each do |entry|
      • +
      •   h2 entry.title
      • +
      •   p entry.fulltext
      • +
      • end
      • +
      +

      Now, I expect you to put the popup code around it and add an h1 title with the name of your blog. For extra haroompf, have the time of each entry display.

      +
      \033\[1;JSm.*popup_make\(.*h1.*h2.*li.*h2.*li.*\)\033\[m.*
      +
      +
      +

      You are Some Kind of Web Guru, I Have Stars in My Eyes

      +

      Good, +that's it! This is exactly the code you can use to write your own real +Ruby blog. If you're feeling adventurous, I'd check out the Rails videos which show a swift young fellow creating a blog in 15 minutes. You just sit back and watch.

      +

      I +should mention Rails. You have been learning the Ruby language, how to +speak it. But Rails is a bunch of libraries (sort of like the popup +library we've been using.) It's a very powerful toolkit for building +websites. If you're interested in learning about Rails, I would head + over there right away. Start using your Ruby skills proper!

      +

      One thing Rails has is easy methods for dates. Like, try: Time.now - 2.weeks

      +
      class Integer; def weeks; self * 7*24*60*60; end; end
      +
      \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-+]\d{4}
      +
      +
      +

      Summary #8, The Hey-Relax-You-Did-Good Summary

      +

      This last section took a moment to wind down, to give you some pointers as to how you can use Ruby. If you enjoyed yourself, + download Ruby and install it.

      + +

      Once you have Ruby installed, you can use Interactive Ruby by running irb on your system's prompt. For more on Irb, + there's The Tiger's Vest to help you.

      +

      You +really deserve a double-layer cake with double-double frosting and a +guy playing one of those guitars that's a double guitar. I mean you +finished, you really did! No doubt about it, you're a certified +red-blooded smartiac!

      +
      +
      + diff --git a/TryRuby/public/tutorials/intro_files/sick.gif b/TryRuby/public/tutorials/intro_files/sick.gif new file mode 100755 index 0000000000000000000000000000000000000000..217a67cbae60740fdc90b92e06b977cf7fc56699 GIT binary patch literal 94 zcmZ?wbhEHb|6B "37" + assigns(:irb).should be(mock_irb) + end + end + + describe "GET new" do + it "assigns a new irb as @irb" do + Irb.stub(:new) { mock_irb } + get :new + assigns(:irb).should be(mock_irb) + end + end + + describe "GET edit" do + it "assigns the requested irb as @irb" do + Irb.stub(:find).with("37") { mock_irb } + get :edit, :id => "37" + assigns(:irb).should be(mock_irb) + end + end + + describe "POST create" do + describe "with valid params" do + it "assigns a newly created irb as @irb" do + Irb.stub(:new).with({'these' => 'params'}) { mock_irb(:save => true) } + post :create, :irb => {'these' => 'params'} + assigns(:irb).should be(mock_irb) + end + + it "redirects to the created irb" do + Irb.stub(:new) { mock_irb(:save => true) } + post :create, :irb => {} + response.should redirect_to(irb_url(mock_irb)) + end + end + + describe "with invalid params" do + it "assigns a newly created but unsaved irb as @irb" do + Irb.stub(:new).with({'these' => 'params'}) { mock_irb(:save => false) } + post :create, :irb => {'these' => 'params'} + assigns(:irb).should be(mock_irb) + end + + it "re-renders the 'new' template" do + Irb.stub(:new) { mock_irb(:save => false) } + post :create, :irb => {} + response.should render_template("new") + end + end + end + + describe "PUT update" do + describe "with valid params" do + it "updates the requested irb" do + Irb.stub(:find).with("37") { mock_irb } + mock_irb.should_receive(:update_attributes).with({'these' => 'params'}) + put :update, :id => "37", :irb => {'these' => 'params'} + end + + it "assigns the requested irb as @irb" do + Irb.stub(:find) { mock_irb(:update_attributes => true) } + put :update, :id => "1" + assigns(:irb).should be(mock_irb) + end + + it "redirects to the irb" do + Irb.stub(:find) { mock_irb(:update_attributes => true) } + put :update, :id => "1" + response.should redirect_to(irb_url(mock_irb)) + end + end + + describe "with invalid params" do + it "assigns the irb as @irb" do + Irb.stub(:find) { mock_irb(:update_attributes => false) } + put :update, :id => "1" + assigns(:irb).should be(mock_irb) + end + + it "re-renders the 'edit' template" do + Irb.stub(:find) { mock_irb(:update_attributes => false) } + put :update, :id => "1" + response.should render_template("edit") + end + end + end + + describe "DELETE destroy" do + it "destroys the requested irb" do + Irb.stub(:find).with("37") { mock_irb } + mock_irb.should_receive(:destroy) + delete :destroy, :id => "37" + end + + it "redirects to the irb list" do + Irb.stub(:find) { mock_irb } + delete :destroy, :id => "1" + response.should redirect_to(irb_url) + end + end + +end diff --git a/TryRuby/spec/controllers/public_controller_spec.rb b/TryRuby/spec/controllers/public_controller_spec.rb new file mode 100644 index 0000000..61a96a3 --- /dev/null +++ b/TryRuby/spec/controllers/public_controller_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe PublicController do + +end diff --git a/TryRuby/spec/helpers/classic_helper_spec.rb b/TryRuby/spec/helpers/classic_helper_spec.rb new file mode 100644 index 0000000..2614b0f --- /dev/null +++ b/TryRuby/spec/helpers/classic_helper_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +# Specs in this file have access to a helper object that includes +# the ClassicHelper. For example: +# +# describe ClassicHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# helper.concat_strings("this","that").should == "this that" +# end +# end +# end +describe ClassicHelper do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/TryRuby/spec/helpers/irb_helper_spec.rb b/TryRuby/spec/helpers/irb_helper_spec.rb new file mode 100644 index 0000000..325a0b0 --- /dev/null +++ b/TryRuby/spec/helpers/irb_helper_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +# Specs in this file have access to a helper object that includes +# the IrbHelper. For example: +# +# describe IrbHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# helper.concat_strings("this","that").should == "this that" +# end +# end +# end +describe IrbHelper do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/TryRuby/spec/helpers/public_helper_spec.rb b/TryRuby/spec/helpers/public_helper_spec.rb new file mode 100644 index 0000000..434276a --- /dev/null +++ b/TryRuby/spec/helpers/public_helper_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +# Specs in this file have access to a helper object that includes +# the PublicHelper. For example: +# +# describe PublicHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# helper.concat_strings("this","that").should == "this that" +# end +# end +# end +describe PublicHelper do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/TryRuby/spec/models/irb_spec.rb b/TryRuby/spec/models/irb_spec.rb new file mode 100644 index 0000000..26e0fa0 --- /dev/null +++ b/TryRuby/spec/models/irb_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe Irb do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/TryRuby/spec/requests/irb_spec.rb b/TryRuby/spec/requests/irb_spec.rb new file mode 100644 index 0000000..d0c7946 --- /dev/null +++ b/TryRuby/spec/requests/irb_spec.rb @@ -0,0 +1,11 @@ +require 'spec_helper' + +describe "Irb" do + describe "GET /irb" do + it "works! (now write some real specs)" do + # Run the generator again with the --webrat flag if you want to use webrat methods/matchers + get irb_path + response.status.should be(200) + end + end +end diff --git a/TryRuby/spec/routing/irb_routing_spec.rb b/TryRuby/spec/routing/irb_routing_spec.rb new file mode 100644 index 0000000..25ea295 --- /dev/null +++ b/TryRuby/spec/routing/irb_routing_spec.rb @@ -0,0 +1,35 @@ +require "spec_helper" + +describe IrbController do + describe "routing" do + + it "recognizes and generates #index" do + { :get => "/irb" }.should route_to(:controller => "irb", :action => "index") + end + + it "recognizes and generates #new" do + { :get => "/irb/new" }.should route_to(:controller => "irb", :action => "new") + end + + it "recognizes and generates #show" do + { :get => "/irb/1" }.should route_to(:controller => "irb", :action => "show", :id => "1") + end + + it "recognizes and generates #edit" do + { :get => "/irb/1/edit" }.should route_to(:controller => "irb", :action => "edit", :id => "1") + end + + it "recognizes and generates #create" do + { :post => "/irb" }.should route_to(:controller => "irb", :action => "create") + end + + it "recognizes and generates #update" do + { :put => "/irb/1" }.should route_to(:controller => "irb", :action => "update", :id => "1") + end + + it "recognizes and generates #destroy" do + { :delete => "/irb/1" }.should route_to(:controller => "irb", :action => "destroy", :id => "1") + end + + end +end diff --git a/TryRuby/spec/spec_helper.rb b/TryRuby/spec/spec_helper.rb new file mode 100644 index 0000000..9b8b02c --- /dev/null +++ b/TryRuby/spec/spec_helper.rb @@ -0,0 +1,27 @@ +# This file is copied to spec/ when you run 'rails generate rspec:install' +ENV["RAILS_ENV"] ||= 'test' +require File.expand_path("../../config/environment", __FILE__) +require 'rspec/rails' + +# Requires supporting ruby files with custom matchers and macros, etc, +# in spec/support/ and its subdirectories. +Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} + +RSpec.configure do |config| + # == Mock Framework + # + # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line: + # + # config.mock_with :mocha + # config.mock_with :flexmock + # config.mock_with :rr + config.mock_with :rspec + + # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures + config.fixture_path = "#{::Rails.root}/spec/fixtures" + + # If you're not using ActiveRecord, or you'd prefer not to run each of your + # examples within a transaction, remove the following line or assign false + # instead of true. + config.use_transactional_fixtures = true +end diff --git a/TryRuby/spec/views/irb/edit.html.erb_spec.rb b/TryRuby/spec/views/irb/edit.html.erb_spec.rb new file mode 100644 index 0000000..5b63112 --- /dev/null +++ b/TryRuby/spec/views/irb/edit.html.erb_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +describe "irb/edit.html.erb" do + before(:each) do + @irb = assign(:irb, stub_model(Irb)) + end + + it "renders the edit irb form" do + render + + # Run the generator again with the --webrat flag if you want to use webrat matchers + assert_select "form", :action => irb_path(@irb), :method => "post" do + end + end +end diff --git a/TryRuby/spec/views/irb/index.html.erb_spec.rb b/TryRuby/spec/views/irb/index.html.erb_spec.rb new file mode 100644 index 0000000..193368a --- /dev/null +++ b/TryRuby/spec/views/irb/index.html.erb_spec.rb @@ -0,0 +1,14 @@ +require 'spec_helper' + +describe "irb/index.html.erb" do + before(:each) do + assign(:irb, [ + stub_model(Irb), + stub_model(Irb) + ]) + end + + it "renders a list of irb" do + render + end +end diff --git a/TryRuby/spec/views/irb/new.html.erb_spec.rb b/TryRuby/spec/views/irb/new.html.erb_spec.rb new file mode 100644 index 0000000..ca7c0ad --- /dev/null +++ b/TryRuby/spec/views/irb/new.html.erb_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +describe "irb/new.html.erb" do + before(:each) do + assign(:irb, stub_model(Irb).as_new_record) + end + + it "renders new irb form" do + render + + # Run the generator again with the --webrat flag if you want to use webrat matchers + assert_select "form", :action => irb_path, :method => "post" do + end + end +end diff --git a/TryRuby/spec/views/irb/show.html.erb_spec.rb b/TryRuby/spec/views/irb/show.html.erb_spec.rb new file mode 100644 index 0000000..9a12d28 --- /dev/null +++ b/TryRuby/spec/views/irb/show.html.erb_spec.rb @@ -0,0 +1,11 @@ +require 'spec_helper' + +describe "irb/show.html.erb" do + before(:each) do + @irb = assign(:irb, stub_model(Irb)) + end + + it "renders attributes in

      " do + render + end +end diff --git a/TryRuby/vendor/plugins/.gitkeep b/TryRuby/vendor/plugins/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/public/images/header.png b/public/images/header.png index 1a6a3f243063ba8e2a93933357efbd3174f581ae..d6b9aa0f3ce2e738d3d12c68b52c78175322741c 100644 GIT binary patch literal 51873 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 diff --git a/public/index.html b/public/index.html index 333c950..abc5b18 100644 --- a/public/index.html +++ b/public/index.html @@ -2,15 +2,43 @@ - try ruby! (in your browser) - - - + + try ruby! (in your browser) + + + + - - + + + + + + + + + + +

      @@ -91,5 +119,7 @@

      Got 15 minutes? Give Ruby a shot right now!

      } catch(err) {} +
      Please Support
      Try Ruby!
      + diff --git a/public/javascripts/application.js b/public/javascripts/application.js new file mode 100644 index 0000000..fe45776 --- /dev/null +++ b/public/javascripts/application.js @@ -0,0 +1,2 @@ +// Place your application-specific JavaScript functions and classes here +// This file is automatically included by javascript_include_tag :defaults diff --git a/public/javascripts/console.js b/public/javascripts/console.js new file mode 100644 index 0000000..e7e8b79 --- /dev/null +++ b/public/javascripts/console.js @@ -0,0 +1,288 @@ +jQuery.fn.debug = function() { + var msg = jqArray.args(arguments); + $("
      ").addClass("error").text(msg.join(", ")).prependTo(this); +} + +jQConsole = function(input, output) { + + var args = jqArray.args + + var input = input; + + // History + var command_history = []; + var command_selected = 0; + + var local_scope = safe_scope(); + + function hide_fn(fn) { return function() { return fn.apply(this, arguments); } } + hide_fn.desc = "A function that creates a wrapper that hides the implementation of another function"; + function queue_fn(fn, time) { if(!time) time = 0; return function() { setTimeout(fn, time); } } + queue_fn.desc = "Turns a function into a function that's called later"; + + var keys = function (o) { + var r = []; + if (typeof o != "object") return r; + for (var k in o) r.push(k); + return r; + } + var refocus = queue_fn(function() { input.blur().focus(); }); + var reset_input = queue_fn(function() { input.val("").blur().focus(); }); + function no_recurse(fn, max_depth) { + var count = 0; + if(!max_depth) max_depth = 1; + return function() { + count++; + if(count > max_depth) { + count--; return; + } else { + fn.apply(this, arguments); + } + } + } + + function hook_fn(fn, listener) { + fn.listener = function() { return listener; } + fn.apply = function(thisArg, argArray) { + if(fn == caller) return; + listener(); + return fn.apply(thisArg, argArray); + }; + } + + hook_fn(history, function() { print("Yo"); }); + + $(document).ready(page_onload); + + function page_onload() { + input = $(input); + output = $(output); + input.keypress(map_keyboard()); + $(document).click(refocus); + refocus(); + } + page_onload = hide_fn(page_onload); + + function clear() { output.html(""); } + + function history() { + return command_history.join("\n"); + } + + var keyLogging = false; + + function map_keyboard() { + var cmdKeys = keymap(); + with(cmdKeys) { + mapKeyCode(toggleKeyLogging, 120); + map(executeCommand, {keyCode:13, ctrlKey:true}); + //mapKeyCode(executeCommand, 13); + mapKeyCode(refocus, 9); + map(historyLast, {keyCode:38, ctrlKey:true}); + map(historyNext, {keyCode:40, ctrlKey:true}); + map(function() { return false; }, {keyCode:123}); + } + return function(e) { + if(keyLogging) + log("keyCode: " + e.keyCode, " shiftKey: " + e.shiftKey, " ctrlKey: " + e.ctrlKey); + resize_input(); + return cmdKeys.dispatch(e); + } + } + + function toggleKeyLogging() { keyLogging = !keyLogging; } + + function historyLast() { + command_selected = Math.max(0, command_selected - 1); + edit_command(command_history[command_selected]); + } + + function historyNext() { + command_selected = Math.min(command_history.length, command_selected + 1); + var cmd = (command_selected == command_history.length) ? "" : command_history[command_selected]; + edit_command(cmd); + } + + function tryComplete() { + + refocus(); + } + + function executeCommand(cmd) { + cmd = (!cmd) ? input.val() : cmd; + reset_input(); + var result = evalInScope(cmd, default_scope); + command_selected = command_history.length; + logCommand(cmd, result); + setTimeout(function() { input.attr("rows", 1); }, 2); + return false; + } + + function evalInScope(cmd, scope) { + try { + + //if(!scope) return eval.apply(our_scope, [cmd]); + with(scope) { + with(jQConsole.our_scope) { + return eval(cmd); + } + } + + //move_modified_scope(local_scope, global_scope); + } + catch(e) { + return e.message; + } + } + + function move_modified_scope(l, g) { + + for(var k in g) { + if(g[k] && typeof l[k] == 'undefined') { + l[k] = g[k]; + g[k] = null; + } + } + } + + function safe_scope() { + var s = {}, g = jQConsole.global_scope; + for(var k in g) { s[k] = null; } + s.global_scope = jQConsole.global_scope; + return s; + } + + var encoders = { + "object": function(o, l) { + if(o.constructor == Array) + return encode_array(o); + //return "[array]"; + return "{ " + encode_obj(o, l) + " }"; + }, + "function": function(v) { return v.toString(); }, + "string": function(v) { return "\"" + v + "\""; }, + "undefined": function() { return "undefined"; }, + _default: function(v) { return v.toString(); } + } + + function encode_array(a) { + var r = a.map(enc); + return "[" + r.join(",") + "]"; + } + + enc = function(v, l, root) { + root = root || true; + if(v == null) return (root) ? "" : "null" + l; + if(encoders[typeof v]) return encoders[typeof v](v); + //log("enc", v, l); + return encoders._default(v, l); + } + + function encode_obj(val, expand) { + if(expand <= 0) { return val.toString(); } + var r = []; + for(var i in val) { + r.push(i + ": " + enc(val[i], expand - 1, false)); + } + return r.join(",\n"); + } + + function encode_reg(s) { + return s.replace(/([\\/\t\n])/g, "\\$1"); + } + + function reg_lookup_fn(lookup) { + var re = new RegExp(encode_reg(keys(lookup).join("")), "ig"); + return re; + } + + function print(msg) { + var className = (typeof msg == "function") ? "cmd" : "print"; + msg = enc(msg, 3); + if(!msg) return; + var out = $($.PRE({"className":className}, msg)); + if(className == "cmd") { out.click(select_command); } + output.prepend(out); + } + + function logCommand(cmd, result) { + command_history.push(cmd); + if(result != undefined) { + output.prepend(jQuery.dump(result)); + } + $($.PRE({className:'cmd'}, cmd)).click(select_command).prependTo(output); + //print(result); + return cmd; + } + + function select_command() { + edit_command($(this).text()); + } + + function edit_command(cmd) { + input.val(cmd); + resize_input(); + input.get(0).select(); + } + + function log() { + var msg = args(arguments); + $("
      ").text(msg.join(", ")).prependTo(output); + } + + function resize_input() + { + setTimeout(do_resize, 0); + + function do_resize() { + var rows = input.val().split(/\n/).length + // + 1 // prevent scrollbar flickering in Mozilla + + (window.opera ? 1 : 0); // leave room for scrollbar in Opera + + // without this check, it is impossible to select text in Opera 7.60 or Opera 8.0. + if (input.attr("rows") != rows) + input.attr("rows", rows); + } + } + + var default_scope = { + "log": log, + "history": history, + alert: function(msg) { alert(msg); } + } + disable_functions(default_scope, "window,document,t1"); + + function disable_functions(obj, list) { + var list = list.split(","); + for(var i in list) { + obj[list[i]] = {}; + } + } + + return this; +}; + +jQuery.extend(jQuery.fn, { + "autoresize": function() + { + var thisp = this; + setTimeout(do_resize, 0); + + function do_resize() { + var s = thisp.val() || ""; + var rows = s.split(/\n/).length; + // + 1 // prevent scrollbar flickering in Mozilla + + (window.opera ? 1 : 0); // leave room for scrollbar in Opera + + // without this check, it is impossible to select text in Opera 7.60 or Opera 8.0. + if (thisp.attr("rows") != rows) + thisp.attr("rows", rows); + } + return this; + } +}) + + + +jQConsole.global_scope = this; +jQConsole.our_scope = {}; \ No newline at end of file diff --git a/public/javascripts/controls.js b/public/javascripts/controls.js new file mode 100644 index 0000000..ca29aef --- /dev/null +++ b/public/javascripts/controls.js @@ -0,0 +1,963 @@ +// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// (c) 2005-2008 Ivan Krstic (http://blogs.law.harvard.edu/ivan) +// (c) 2005-2008 Jon Tirsen (http://www.tirsen.com) +// Contributors: +// Richard Livsey +// Rahul Bhargava +// Rob Wills +// +// script.aculo.us is freely distributable under the terms of an MIT-style license. +// For details, see the script.aculo.us web site: http://script.aculo.us/ + +// Autocompleter.Base handles all the autocompletion functionality +// that's independent of the data source for autocompletion. This +// includes drawing the autocompletion menu, observing keyboard +// and mouse events, and similar. +// +// Specific autocompleters need to provide, at the very least, +// a getUpdatedChoices function that will be invoked every time +// the text inside the monitored textbox changes. This method +// should get the text for which to provide autocompletion by +// invoking this.getToken(), NOT by directly accessing +// this.element.value. This is to allow incremental tokenized +// autocompletion. Specific auto-completion logic (AJAX, etc) +// belongs in getUpdatedChoices. +// +// Tokenized incremental autocompletion is enabled automatically +// when an autocompleter is instantiated with the 'tokens' option +// in the options parameter, e.g.: +// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' }); +// will incrementally autocomplete with a comma as the token. +// Additionally, ',' in the above example can be replaced with +// a token array, e.g. { tokens: [',', '\n'] } which +// enables autocompletion on multiple tokens. This is most +// useful when one of the tokens is \n (a newline), as it +// allows smart autocompletion after linebreaks. + +if(typeof Effect == 'undefined') + throw("controls.js requires including script.aculo.us' effects.js library"); + +var Autocompleter = { }; +Autocompleter.Base = Class.create({ + baseInitialize: function(element, update, options) { + element = $(element); + this.element = element; + this.update = $(update); + this.hasFocus = false; + this.changed = false; + this.active = false; + this.index = 0; + this.entryCount = 0; + this.oldElementValue = this.element.value; + + if(this.setOptions) + this.setOptions(options); + else + this.options = options || { }; + + this.options.paramName = this.options.paramName || this.element.name; + this.options.tokens = this.options.tokens || []; + this.options.frequency = this.options.frequency || 0.4; + this.options.minChars = this.options.minChars || 1; + this.options.onShow = this.options.onShow || + function(element, update){ + if(!update.style.position || update.style.position=='absolute') { + update.style.position = 'absolute'; + Position.clone(element, update, { + setHeight: false, + offsetTop: element.offsetHeight + }); + } + Effect.Appear(update,{duration:0.15}); + }; + this.options.onHide = this.options.onHide || + function(element, update){ new Effect.Fade(update,{duration:0.15}) }; + + if(typeof(this.options.tokens) == 'string') + this.options.tokens = new Array(this.options.tokens); + // Force carriage returns as token delimiters anyway + if (!this.options.tokens.include('\n')) + this.options.tokens.push('\n'); + + this.observer = null; + + this.element.setAttribute('autocomplete','off'); + + Element.hide(this.update); + + Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this)); + Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this)); + }, + + show: function() { + if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update); + if(!this.iefix && + (Prototype.Browser.IE) && + (Element.getStyle(this.update, 'position')=='absolute')) { + new Insertion.After(this.update, + ''); + this.iefix = $(this.update.id+'_iefix'); + } + if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50); + }, + + fixIEOverlapping: function() { + Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)}); + this.iefix.style.zIndex = 1; + this.update.style.zIndex = 2; + Element.show(this.iefix); + }, + + hide: function() { + this.stopIndicator(); + if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update); + if(this.iefix) Element.hide(this.iefix); + }, + + startIndicator: function() { + if(this.options.indicator) Element.show(this.options.indicator); + }, + + stopIndicator: function() { + if(this.options.indicator) Element.hide(this.options.indicator); + }, + + onKeyPress: function(event) { + if(this.active) + switch(event.keyCode) { + case Event.KEY_TAB: + case Event.KEY_RETURN: + this.selectEntry(); + Event.stop(event); + case Event.KEY_ESC: + this.hide(); + this.active = false; + Event.stop(event); + return; + case Event.KEY_LEFT: + case Event.KEY_RIGHT: + return; + case Event.KEY_UP: + this.markPrevious(); + this.render(); + Event.stop(event); + return; + case Event.KEY_DOWN: + this.markNext(); + this.render(); + Event.stop(event); + return; + } + else + if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || + (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return; + + this.changed = true; + this.hasFocus = true; + + if(this.observer) clearTimeout(this.observer); + this.observer = + setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); + }, + + activate: function() { + this.changed = false; + this.hasFocus = true; + this.getUpdatedChoices(); + }, + + onHover: function(event) { + var element = Event.findElement(event, 'LI'); + if(this.index != element.autocompleteIndex) + { + this.index = element.autocompleteIndex; + this.render(); + } + Event.stop(event); + }, + + onClick: function(event) { + var element = Event.findElement(event, 'LI'); + this.index = element.autocompleteIndex; + this.selectEntry(); + this.hide(); + }, + + onBlur: function(event) { + // needed to make click events working + setTimeout(this.hide.bind(this), 250); + this.hasFocus = false; + this.active = false; + }, + + render: function() { + if(this.entryCount > 0) { + for (var i = 0; i < this.entryCount; i++) + this.index==i ? + Element.addClassName(this.getEntry(i),"selected") : + Element.removeClassName(this.getEntry(i),"selected"); + if(this.hasFocus) { + this.show(); + this.active = true; + } + } else { + this.active = false; + this.hide(); + } + }, + + markPrevious: function() { + if(this.index > 0) this.index--; + else this.index = this.entryCount-1; + this.getEntry(this.index).scrollIntoView(true); + }, + + markNext: function() { + if(this.index < this.entryCount-1) this.index++; + else this.index = 0; + this.getEntry(this.index).scrollIntoView(false); + }, + + getEntry: function(index) { + return this.update.firstChild.childNodes[index]; + }, + + getCurrentEntry: function() { + return this.getEntry(this.index); + }, + + selectEntry: function() { + this.active = false; + this.updateElement(this.getCurrentEntry()); + }, + + updateElement: function(selectedElement) { + if (this.options.updateElement) { + this.options.updateElement(selectedElement); + return; + } + var value = ''; + if (this.options.select) { + var nodes = $(selectedElement).select('.' + this.options.select) || []; + if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); + } else + value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); + + var bounds = this.getTokenBounds(); + if (bounds[0] != -1) { + var newValue = this.element.value.substr(0, bounds[0]); + var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/); + if (whitespace) + newValue += whitespace[0]; + this.element.value = newValue + value + this.element.value.substr(bounds[1]); + } else { + this.element.value = value; + } + this.oldElementValue = this.element.value; + this.element.focus(); + + if (this.options.afterUpdateElement) + this.options.afterUpdateElement(this.element, selectedElement); + }, + + updateChoices: function(choices) { + if(!this.changed && this.hasFocus) { + this.update.innerHTML = choices; + Element.cleanWhitespace(this.update); + Element.cleanWhitespace(this.update.down()); + + if(this.update.firstChild && this.update.down().childNodes) { + this.entryCount = + this.update.down().childNodes.length; + for (var i = 0; i < this.entryCount; i++) { + var entry = this.getEntry(i); + entry.autocompleteIndex = i; + this.addObservers(entry); + } + } else { + this.entryCount = 0; + } + + this.stopIndicator(); + this.index = 0; + + if(this.entryCount==1 && this.options.autoSelect) { + this.selectEntry(); + this.hide(); + } else { + this.render(); + } + } + }, + + addObservers: function(element) { + Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this)); + Event.observe(element, "click", this.onClick.bindAsEventListener(this)); + }, + + onObserverEvent: function() { + this.changed = false; + this.tokenBounds = null; + if(this.getToken().length>=this.options.minChars) { + this.getUpdatedChoices(); + } else { + this.active = false; + this.hide(); + } + this.oldElementValue = this.element.value; + }, + + getToken: function() { + var bounds = this.getTokenBounds(); + return this.element.value.substring(bounds[0], bounds[1]).strip(); + }, + + getTokenBounds: function() { + if (null != this.tokenBounds) return this.tokenBounds; + var value = this.element.value; + if (value.strip().empty()) return [-1, 0]; + var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue); + var offset = (diff == this.oldElementValue.length ? 1 : 0); + var prevTokenPos = -1, nextTokenPos = value.length; + var tp; + for (var index = 0, l = this.options.tokens.length; index < l; ++index) { + tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1); + if (tp > prevTokenPos) prevTokenPos = tp; + tp = value.indexOf(this.options.tokens[index], diff + offset); + if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp; + } + return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]); + } +}); + +Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) { + var boundary = Math.min(newS.length, oldS.length); + for (var index = 0; index < boundary; ++index) + if (newS[index] != oldS[index]) + return index; + return boundary; +}; + +Ajax.Autocompleter = Class.create(Autocompleter.Base, { + initialize: function(element, update, url, options) { + this.baseInitialize(element, update, options); + this.options.asynchronous = true; + this.options.onComplete = this.onComplete.bind(this); + this.options.defaultParams = this.options.parameters || null; + this.url = url; + }, + + getUpdatedChoices: function() { + this.startIndicator(); + + var entry = encodeURIComponent(this.options.paramName) + '=' + + encodeURIComponent(this.getToken()); + + this.options.parameters = this.options.callback ? + this.options.callback(this.element, entry) : entry; + + if(this.options.defaultParams) + this.options.parameters += '&' + this.options.defaultParams; + + new Ajax.Request(this.url, this.options); + }, + + onComplete: function(request) { + this.updateChoices(request.responseText); + } +}); + +// The local array autocompleter. Used when you'd prefer to +// inject an array of autocompletion options into the page, rather +// than sending out Ajax queries, which can be quite slow sometimes. +// +// The constructor takes four parameters. The first two are, as usual, +// the id of the monitored textbox, and id of the autocompletion menu. +// The third is the array you want to autocomplete from, and the fourth +// is the options block. +// +// Extra local autocompletion options: +// - choices - How many autocompletion choices to offer +// +// - partialSearch - If false, the autocompleter will match entered +// text only at the beginning of strings in the +// autocomplete array. Defaults to true, which will +// match text at the beginning of any *word* in the +// strings in the autocomplete array. If you want to +// search anywhere in the string, additionally set +// the option fullSearch to true (default: off). +// +// - fullSsearch - Search anywhere in autocomplete array strings. +// +// - partialChars - How many characters to enter before triggering +// a partial match (unlike minChars, which defines +// how many characters are required to do any match +// at all). Defaults to 2. +// +// - ignoreCase - Whether to ignore case when autocompleting. +// Defaults to true. +// +// It's possible to pass in a custom function as the 'selector' +// option, if you prefer to write your own autocompletion logic. +// In that case, the other options above will not apply unless +// you support them. + +Autocompleter.Local = Class.create(Autocompleter.Base, { + initialize: function(element, update, array, options) { + this.baseInitialize(element, update, options); + this.options.array = array; + }, + + getUpdatedChoices: function() { + this.updateChoices(this.options.selector(this)); + }, + + setOptions: function(options) { + this.options = Object.extend({ + choices: 10, + partialSearch: true, + partialChars: 2, + ignoreCase: true, + fullSearch: false, + selector: function(instance) { + var ret = []; // Beginning matches + var partial = []; // Inside matches + var entry = instance.getToken(); + var count = 0; + + for (var i = 0; i < instance.options.array.length && + ret.length < instance.options.choices ; i++) { + + var elem = instance.options.array[i]; + var foundPos = instance.options.ignoreCase ? + elem.toLowerCase().indexOf(entry.toLowerCase()) : + elem.indexOf(entry); + + while (foundPos != -1) { + if (foundPos == 0 && elem.length != entry.length) { + ret.push("
    2. " + elem.substr(0, entry.length) + "" + + elem.substr(entry.length) + "
    3. "); + break; + } else if (entry.length >= instance.options.partialChars && + instance.options.partialSearch && foundPos != -1) { + if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) { + partial.push("
    4. " + elem.substr(0, foundPos) + "" + + elem.substr(foundPos, entry.length) + "" + elem.substr( + foundPos + entry.length) + "
    5. "); + break; + } + } + + foundPos = instance.options.ignoreCase ? + elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : + elem.indexOf(entry, foundPos + 1); + + } + } + if (partial.length) + ret = ret.concat(partial.slice(0, instance.options.choices - ret.length)); + return "
        " + ret.join('') + "
      "; + } + }, options || { }); + } +}); + +// AJAX in-place editor and collection editor +// Full rewrite by Christophe Porteneuve (April 2007). + +// Use this if you notice weird scrolling problems on some browsers, +// the DOM might be a bit confused when this gets called so do this +// waits 1 ms (with setTimeout) until it does the activation +Field.scrollFreeActivate = function(field) { + setTimeout(function() { + Field.activate(field); + }, 1); +}; + +Ajax.InPlaceEditor = Class.create({ + initialize: function(element, url, options) { + this.url = url; + this.element = element = $(element); + this.prepareOptions(); + this._controls = { }; + arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!! + Object.extend(this.options, options || { }); + if (!this.options.formId && this.element.id) { + this.options.formId = this.element.id + '-inplaceeditor'; + if ($(this.options.formId)) + this.options.formId = ''; + } + if (this.options.externalControl) + this.options.externalControl = $(this.options.externalControl); + if (!this.options.externalControl) + this.options.externalControlOnly = false; + this._originalBackground = this.element.getStyle('background-color') || 'transparent'; + this.element.title = this.options.clickToEditText; + this._boundCancelHandler = this.handleFormCancellation.bind(this); + this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this); + this._boundFailureHandler = this.handleAJAXFailure.bind(this); + this._boundSubmitHandler = this.handleFormSubmission.bind(this); + this._boundWrapperHandler = this.wrapUp.bind(this); + this.registerListeners(); + }, + checkForEscapeOrReturn: function(e) { + if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return; + if (Event.KEY_ESC == e.keyCode) + this.handleFormCancellation(e); + else if (Event.KEY_RETURN == e.keyCode) + this.handleFormSubmission(e); + }, + createControl: function(mode, handler, extraClasses) { + var control = this.options[mode + 'Control']; + var text = this.options[mode + 'Text']; + if ('button' == control) { + var btn = document.createElement('input'); + btn.type = 'submit'; + btn.value = text; + btn.className = 'editor_' + mode + '_button'; + if ('cancel' == mode) + btn.onclick = this._boundCancelHandler; + this._form.appendChild(btn); + this._controls[mode] = btn; + } else if ('link' == control) { + var link = document.createElement('a'); + link.href = '#'; + link.appendChild(document.createTextNode(text)); + link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler; + link.className = 'editor_' + mode + '_link'; + if (extraClasses) + link.className += ' ' + extraClasses; + this._form.appendChild(link); + this._controls[mode] = link; + } + }, + createEditField: function() { + var text = (this.options.loadTextURL ? this.options.loadingText : this.getText()); + var fld; + if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) { + fld = document.createElement('input'); + fld.type = 'text'; + var size = this.options.size || this.options.cols || 0; + if (0 < size) fld.size = size; + } else { + fld = document.createElement('textarea'); + fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows); + fld.cols = this.options.cols || 40; + } + fld.name = this.options.paramName; + fld.value = text; // No HTML breaks conversion anymore + fld.className = 'editor_field'; + if (this.options.submitOnBlur) + fld.onblur = this._boundSubmitHandler; + this._controls.editor = fld; + if (this.options.loadTextURL) + this.loadExternalText(); + this._form.appendChild(this._controls.editor); + }, + createForm: function() { + var ipe = this; + function addText(mode, condition) { + var text = ipe.options['text' + mode + 'Controls']; + if (!text || condition === false) return; + ipe._form.appendChild(document.createTextNode(text)); + }; + this._form = $(document.createElement('form')); + this._form.id = this.options.formId; + this._form.addClassName(this.options.formClassName); + this._form.onsubmit = this._boundSubmitHandler; + this.createEditField(); + if ('textarea' == this._controls.editor.tagName.toLowerCase()) + this._form.appendChild(document.createElement('br')); + if (this.options.onFormCustomization) + this.options.onFormCustomization(this, this._form); + addText('Before', this.options.okControl || this.options.cancelControl); + this.createControl('ok', this._boundSubmitHandler); + addText('Between', this.options.okControl && this.options.cancelControl); + this.createControl('cancel', this._boundCancelHandler, 'editor_cancel'); + addText('After', this.options.okControl || this.options.cancelControl); + }, + destroy: function() { + if (this._oldInnerHTML) + this.element.innerHTML = this._oldInnerHTML; + this.leaveEditMode(); + this.unregisterListeners(); + }, + enterEditMode: function(e) { + if (this._saving || this._editing) return; + this._editing = true; + this.triggerCallback('onEnterEditMode'); + if (this.options.externalControl) + this.options.externalControl.hide(); + this.element.hide(); + this.createForm(); + this.element.parentNode.insertBefore(this._form, this.element); + if (!this.options.loadTextURL) + this.postProcessEditField(); + if (e) Event.stop(e); + }, + enterHover: function(e) { + if (this.options.hoverClassName) + this.element.addClassName(this.options.hoverClassName); + if (this._saving) return; + this.triggerCallback('onEnterHover'); + }, + getText: function() { + return this.element.innerHTML.unescapeHTML(); + }, + handleAJAXFailure: function(transport) { + this.triggerCallback('onFailure', transport); + if (this._oldInnerHTML) { + this.element.innerHTML = this._oldInnerHTML; + this._oldInnerHTML = null; + } + }, + handleFormCancellation: function(e) { + this.wrapUp(); + if (e) Event.stop(e); + }, + handleFormSubmission: function(e) { + var form = this._form; + var value = $F(this._controls.editor); + this.prepareSubmission(); + var params = this.options.callback(form, value) || ''; + if (Object.isString(params)) + params = params.toQueryParams(); + params.editorId = this.element.id; + if (this.options.htmlResponse) { + var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions); + Object.extend(options, { + parameters: params, + onComplete: this._boundWrapperHandler, + onFailure: this._boundFailureHandler + }); + new Ajax.Updater({ success: this.element }, this.url, options); + } else { + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: params, + onComplete: this._boundWrapperHandler, + onFailure: this._boundFailureHandler + }); + new Ajax.Request(this.url, options); + } + if (e) Event.stop(e); + }, + leaveEditMode: function() { + this.element.removeClassName(this.options.savingClassName); + this.removeForm(); + this.leaveHover(); + this.element.style.backgroundColor = this._originalBackground; + this.element.show(); + if (this.options.externalControl) + this.options.externalControl.show(); + this._saving = false; + this._editing = false; + this._oldInnerHTML = null; + this.triggerCallback('onLeaveEditMode'); + }, + leaveHover: function(e) { + if (this.options.hoverClassName) + this.element.removeClassName(this.options.hoverClassName); + if (this._saving) return; + this.triggerCallback('onLeaveHover'); + }, + loadExternalText: function() { + this._form.addClassName(this.options.loadingClassName); + this._controls.editor.disabled = true; + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: 'editorId=' + encodeURIComponent(this.element.id), + onComplete: Prototype.emptyFunction, + onSuccess: function(transport) { + this._form.removeClassName(this.options.loadingClassName); + var text = transport.responseText; + if (this.options.stripLoadedTextTags) + text = text.stripTags(); + this._controls.editor.value = text; + this._controls.editor.disabled = false; + this.postProcessEditField(); + }.bind(this), + onFailure: this._boundFailureHandler + }); + new Ajax.Request(this.options.loadTextURL, options); + }, + postProcessEditField: function() { + var fpc = this.options.fieldPostCreation; + if (fpc) + $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate'](); + }, + prepareOptions: function() { + this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions); + Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks); + [this._extraDefaultOptions].flatten().compact().each(function(defs) { + Object.extend(this.options, defs); + }.bind(this)); + }, + prepareSubmission: function() { + this._saving = true; + this.removeForm(); + this.leaveHover(); + this.showSaving(); + }, + registerListeners: function() { + this._listeners = { }; + var listener; + $H(Ajax.InPlaceEditor.Listeners).each(function(pair) { + listener = this[pair.value].bind(this); + this._listeners[pair.key] = listener; + if (!this.options.externalControlOnly) + this.element.observe(pair.key, listener); + if (this.options.externalControl) + this.options.externalControl.observe(pair.key, listener); + }.bind(this)); + }, + removeForm: function() { + if (!this._form) return; + this._form.remove(); + this._form = null; + this._controls = { }; + }, + showSaving: function() { + this._oldInnerHTML = this.element.innerHTML; + this.element.innerHTML = this.options.savingText; + this.element.addClassName(this.options.savingClassName); + this.element.style.backgroundColor = this._originalBackground; + this.element.show(); + }, + triggerCallback: function(cbName, arg) { + if ('function' == typeof this.options[cbName]) { + this.options[cbName](this, arg); + } + }, + unregisterListeners: function() { + $H(this._listeners).each(function(pair) { + if (!this.options.externalControlOnly) + this.element.stopObserving(pair.key, pair.value); + if (this.options.externalControl) + this.options.externalControl.stopObserving(pair.key, pair.value); + }.bind(this)); + }, + wrapUp: function(transport) { + this.leaveEditMode(); + // Can't use triggerCallback due to backward compatibility: requires + // binding + direct element + this._boundComplete(transport, this.element); + } +}); + +Object.extend(Ajax.InPlaceEditor.prototype, { + dispose: Ajax.InPlaceEditor.prototype.destroy +}); + +Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, { + initialize: function($super, element, url, options) { + this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions; + $super(element, url, options); + }, + + createEditField: function() { + var list = document.createElement('select'); + list.name = this.options.paramName; + list.size = 1; + this._controls.editor = list; + this._collection = this.options.collection || []; + if (this.options.loadCollectionURL) + this.loadCollection(); + else + this.checkForExternalText(); + this._form.appendChild(this._controls.editor); + }, + + loadCollection: function() { + this._form.addClassName(this.options.loadingClassName); + this.showLoadingText(this.options.loadingCollectionText); + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: 'editorId=' + encodeURIComponent(this.element.id), + onComplete: Prototype.emptyFunction, + onSuccess: function(transport) { + var js = transport.responseText.strip(); + if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check + throw('Server returned an invalid collection representation.'); + this._collection = eval(js); + this.checkForExternalText(); + }.bind(this), + onFailure: this.onFailure + }); + new Ajax.Request(this.options.loadCollectionURL, options); + }, + + showLoadingText: function(text) { + this._controls.editor.disabled = true; + var tempOption = this._controls.editor.firstChild; + if (!tempOption) { + tempOption = document.createElement('option'); + tempOption.value = ''; + this._controls.editor.appendChild(tempOption); + tempOption.selected = true; + } + tempOption.update((text || '').stripScripts().stripTags()); + }, + + checkForExternalText: function() { + this._text = this.getText(); + if (this.options.loadTextURL) + this.loadExternalText(); + else + this.buildOptionList(); + }, + + loadExternalText: function() { + this.showLoadingText(this.options.loadingText); + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: 'editorId=' + encodeURIComponent(this.element.id), + onComplete: Prototype.emptyFunction, + onSuccess: function(transport) { + this._text = transport.responseText.strip(); + this.buildOptionList(); + }.bind(this), + onFailure: this.onFailure + }); + new Ajax.Request(this.options.loadTextURL, options); + }, + + buildOptionList: function() { + this._form.removeClassName(this.options.loadingClassName); + this._collection = this._collection.map(function(entry) { + return 2 === entry.length ? entry : [entry, entry].flatten(); + }); + var marker = ('value' in this.options) ? this.options.value : this._text; + var textFound = this._collection.any(function(entry) { + return entry[0] == marker; + }.bind(this)); + this._controls.editor.update(''); + var option; + this._collection.each(function(entry, index) { + option = document.createElement('option'); + option.value = entry[0]; + option.selected = textFound ? entry[0] == marker : 0 == index; + option.appendChild(document.createTextNode(entry[1])); + this._controls.editor.appendChild(option); + }.bind(this)); + this._controls.editor.disabled = false; + Field.scrollFreeActivate(this._controls.editor); + } +}); + +//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! **** +//**** This only exists for a while, in order to let **** +//**** users adapt to the new API. Read up on the new **** +//**** API and convert your code to it ASAP! **** + +Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) { + if (!options) return; + function fallback(name, expr) { + if (name in options || expr === undefined) return; + options[name] = expr; + }; + fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' : + options.cancelLink == options.cancelButton == false ? false : undefined))); + fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' : + options.okLink == options.okButton == false ? false : undefined))); + fallback('highlightColor', options.highlightcolor); + fallback('highlightEndColor', options.highlightendcolor); +}; + +Object.extend(Ajax.InPlaceEditor, { + DefaultOptions: { + ajaxOptions: { }, + autoRows: 3, // Use when multi-line w/ rows == 1 + cancelControl: 'link', // 'link'|'button'|false + cancelText: 'cancel', + clickToEditText: 'Click to edit', + externalControl: null, // id|elt + externalControlOnly: false, + fieldPostCreation: 'activate', // 'activate'|'focus'|false + formClassName: 'inplaceeditor-form', + formId: null, // id|elt + highlightColor: '#ffff99', + highlightEndColor: '#ffffff', + hoverClassName: '', + htmlResponse: true, + loadingClassName: 'inplaceeditor-loading', + loadingText: 'Loading...', + okControl: 'button', // 'link'|'button'|false + okText: 'ok', + paramName: 'value', + rows: 1, // If 1 and multi-line, uses autoRows + savingClassName: 'inplaceeditor-saving', + savingText: 'Saving...', + size: 0, + stripLoadedTextTags: false, + submitOnBlur: false, + textAfterControls: '', + textBeforeControls: '', + textBetweenControls: '' + }, + DefaultCallbacks: { + callback: function(form) { + return Form.serialize(form); + }, + onComplete: function(transport, element) { + // For backward compatibility, this one is bound to the IPE, and passes + // the element directly. It was too often customized, so we don't break it. + new Effect.Highlight(element, { + startcolor: this.options.highlightColor, keepBackgroundImage: true }); + }, + onEnterEditMode: null, + onEnterHover: function(ipe) { + ipe.element.style.backgroundColor = ipe.options.highlightColor; + if (ipe._effect) + ipe._effect.cancel(); + }, + onFailure: function(transport, ipe) { + alert('Error communication with the server: ' + transport.responseText.stripTags()); + }, + onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls. + onLeaveEditMode: null, + onLeaveHover: function(ipe) { + ipe._effect = new Effect.Highlight(ipe.element, { + startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor, + restorecolor: ipe._originalBackground, keepBackgroundImage: true + }); + } + }, + Listeners: { + click: 'enterEditMode', + keydown: 'checkForEscapeOrReturn', + mouseover: 'enterHover', + mouseout: 'leaveHover' + } +}); + +Ajax.InPlaceCollectionEditor.DefaultOptions = { + loadingCollectionText: 'Loading options...' +}; + +// Delayed observer, like Form.Element.Observer, +// but waits for delay after last key input +// Ideal for live-search fields + +Form.Element.DelayedObserver = Class.create({ + initialize: function(element, delay, callback) { + this.delay = delay || 0.5; + this.element = $(element); + this.callback = callback; + this.timer = null; + this.lastValue = $F(this.element); + Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this)); + }, + delayedListener: function(event) { + if(this.lastValue == $F(this.element)) return; + if(this.timer) clearTimeout(this.timer); + this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000); + this.lastValue = $F(this.element); + }, + onTimerEvent: function() { + this.timer = null; + this.callback(this.element, $F(this.element)); + } +}); \ No newline at end of file diff --git a/public/javascripts/dragdrop.js b/public/javascripts/dragdrop.js new file mode 100644 index 0000000..07229f9 --- /dev/null +++ b/public/javascripts/dragdrop.js @@ -0,0 +1,973 @@ +// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// (c) 2005-2008 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz) +// +// script.aculo.us is freely distributable under the terms of an MIT-style license. +// For details, see the script.aculo.us web site: http://script.aculo.us/ + +if(Object.isUndefined(Effect)) + throw("dragdrop.js requires including script.aculo.us' effects.js library"); + +var Droppables = { + drops: [], + + remove: function(element) { + this.drops = this.drops.reject(function(d) { return d.element==$(element) }); + }, + + add: function(element) { + element = $(element); + var options = Object.extend({ + greedy: true, + hoverclass: null, + tree: false + }, arguments[1] || { }); + + // cache containers + if(options.containment) { + options._containers = []; + var containment = options.containment; + if(Object.isArray(containment)) { + containment.each( function(c) { options._containers.push($(c)) }); + } else { + options._containers.push($(containment)); + } + } + + if(options.accept) options.accept = [options.accept].flatten(); + + Element.makePositioned(element); // fix IE + options.element = element; + + this.drops.push(options); + }, + + findDeepestChild: function(drops) { + deepest = drops[0]; + + for (i = 1; i < drops.length; ++i) + if (Element.isParent(drops[i].element, deepest.element)) + deepest = drops[i]; + + return deepest; + }, + + isContained: function(element, drop) { + var containmentNode; + if(drop.tree) { + containmentNode = element.treeNode; + } else { + containmentNode = element.parentNode; + } + return drop._containers.detect(function(c) { return containmentNode == c }); + }, + + isAffected: function(point, element, drop) { + return ( + (drop.element!=element) && + ((!drop._containers) || + this.isContained(element, drop)) && + ((!drop.accept) || + (Element.classNames(element).detect( + function(v) { return drop.accept.include(v) } ) )) && + Position.within(drop.element, point[0], point[1]) ); + }, + + deactivate: function(drop) { + if(drop.hoverclass) + Element.removeClassName(drop.element, drop.hoverclass); + this.last_active = null; + }, + + activate: function(drop) { + if(drop.hoverclass) + Element.addClassName(drop.element, drop.hoverclass); + this.last_active = drop; + }, + + show: function(point, element) { + if(!this.drops.length) return; + var drop, affected = []; + + this.drops.each( function(drop) { + if(Droppables.isAffected(point, element, drop)) + affected.push(drop); + }); + + if(affected.length>0) + drop = Droppables.findDeepestChild(affected); + + if(this.last_active && this.last_active != drop) this.deactivate(this.last_active); + if (drop) { + Position.within(drop.element, point[0], point[1]); + if(drop.onHover) + drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); + + if (drop != this.last_active) Droppables.activate(drop); + } + }, + + fire: function(event, element) { + if(!this.last_active) return; + Position.prepare(); + + if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active)) + if (this.last_active.onDrop) { + this.last_active.onDrop(element, this.last_active.element, event); + return true; + } + }, + + reset: function() { + if(this.last_active) + this.deactivate(this.last_active); + } +}; + +var Draggables = { + drags: [], + observers: [], + + register: function(draggable) { + if(this.drags.length == 0) { + this.eventMouseUp = this.endDrag.bindAsEventListener(this); + this.eventMouseMove = this.updateDrag.bindAsEventListener(this); + this.eventKeypress = this.keyPress.bindAsEventListener(this); + + Event.observe(document, "mouseup", this.eventMouseUp); + Event.observe(document, "mousemove", this.eventMouseMove); + Event.observe(document, "keypress", this.eventKeypress); + } + this.drags.push(draggable); + }, + + unregister: function(draggable) { + this.drags = this.drags.reject(function(d) { return d==draggable }); + if(this.drags.length == 0) { + Event.stopObserving(document, "mouseup", this.eventMouseUp); + Event.stopObserving(document, "mousemove", this.eventMouseMove); + Event.stopObserving(document, "keypress", this.eventKeypress); + } + }, + + activate: function(draggable) { + if(draggable.options.delay) { + this._timeout = setTimeout(function() { + Draggables._timeout = null; + window.focus(); + Draggables.activeDraggable = draggable; + }.bind(this), draggable.options.delay); + } else { + window.focus(); // allows keypress events if window isn't currently focused, fails for Safari + this.activeDraggable = draggable; + } + }, + + deactivate: function() { + this.activeDraggable = null; + }, + + updateDrag: function(event) { + if(!this.activeDraggable) return; + var pointer = [Event.pointerX(event), Event.pointerY(event)]; + // Mozilla-based browsers fire successive mousemove events with + // the same coordinates, prevent needless redrawing (moz bug?) + if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return; + this._lastPointer = pointer; + + this.activeDraggable.updateDrag(event, pointer); + }, + + endDrag: function(event) { + if(this._timeout) { + clearTimeout(this._timeout); + this._timeout = null; + } + if(!this.activeDraggable) return; + this._lastPointer = null; + this.activeDraggable.endDrag(event); + this.activeDraggable = null; + }, + + keyPress: function(event) { + if(this.activeDraggable) + this.activeDraggable.keyPress(event); + }, + + addObserver: function(observer) { + this.observers.push(observer); + this._cacheObserverCallbacks(); + }, + + removeObserver: function(element) { // element instead of observer fixes mem leaks + this.observers = this.observers.reject( function(o) { return o.element==element }); + this._cacheObserverCallbacks(); + }, + + notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag' + if(this[eventName+'Count'] > 0) + this.observers.each( function(o) { + if(o[eventName]) o[eventName](eventName, draggable, event); + }); + if(draggable.options[eventName]) draggable.options[eventName](draggable, event); + }, + + _cacheObserverCallbacks: function() { + ['onStart','onEnd','onDrag'].each( function(eventName) { + Draggables[eventName+'Count'] = Draggables.observers.select( + function(o) { return o[eventName]; } + ).length; + }); + } +}; + +/*--------------------------------------------------------------------------*/ + +var Draggable = Class.create({ + initialize: function(element) { + var defaults = { + handle: false, + reverteffect: function(element, top_offset, left_offset) { + var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02; + new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur, + queue: {scope:'_draggable', position:'end'} + }); + }, + endeffect: function(element) { + var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0; + new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity, + queue: {scope:'_draggable', position:'end'}, + afterFinish: function(){ + Draggable._dragging[element] = false + } + }); + }, + zindex: 1000, + revert: false, + quiet: false, + scroll: false, + scrollSensitivity: 20, + scrollSpeed: 15, + snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] } + delay: 0 + }; + + if(!arguments[1] || Object.isUndefined(arguments[1].endeffect)) + Object.extend(defaults, { + starteffect: function(element) { + element._opacity = Element.getOpacity(element); + Draggable._dragging[element] = true; + new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7}); + } + }); + + var options = Object.extend(defaults, arguments[1] || { }); + + this.element = $(element); + + if(options.handle && Object.isString(options.handle)) + this.handle = this.element.down('.'+options.handle, 0); + + if(!this.handle) this.handle = $(options.handle); + if(!this.handle) this.handle = this.element; + + if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) { + options.scroll = $(options.scroll); + this._isScrollChild = Element.childOf(this.element, options.scroll); + } + + Element.makePositioned(this.element); // fix IE + + this.options = options; + this.dragging = false; + + this.eventMouseDown = this.initDrag.bindAsEventListener(this); + Event.observe(this.handle, "mousedown", this.eventMouseDown); + + Draggables.register(this); + }, + + destroy: function() { + Event.stopObserving(this.handle, "mousedown", this.eventMouseDown); + Draggables.unregister(this); + }, + + currentDelta: function() { + return([ + parseInt(Element.getStyle(this.element,'left') || '0'), + parseInt(Element.getStyle(this.element,'top') || '0')]); + }, + + initDrag: function(event) { + if(!Object.isUndefined(Draggable._dragging[this.element]) && + Draggable._dragging[this.element]) return; + if(Event.isLeftClick(event)) { + // abort on form elements, fixes a Firefox issue + var src = Event.element(event); + if((tag_name = src.tagName.toUpperCase()) && ( + tag_name=='INPUT' || + tag_name=='SELECT' || + tag_name=='OPTION' || + tag_name=='BUTTON' || + tag_name=='TEXTAREA')) return; + + var pointer = [Event.pointerX(event), Event.pointerY(event)]; + var pos = Position.cumulativeOffset(this.element); + this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) }); + + Draggables.activate(this); + Event.stop(event); + } + }, + + startDrag: function(event) { + this.dragging = true; + if(!this.delta) + this.delta = this.currentDelta(); + + if(this.options.zindex) { + this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0); + this.element.style.zIndex = this.options.zindex; + } + + if(this.options.ghosting) { + this._clone = this.element.cloneNode(true); + this._originallyAbsolute = (this.element.getStyle('position') == 'absolute'); + if (!this._originallyAbsolute) + Position.absolutize(this.element); + this.element.parentNode.insertBefore(this._clone, this.element); + } + + if(this.options.scroll) { + if (this.options.scroll == window) { + var where = this._getWindowScroll(this.options.scroll); + this.originalScrollLeft = where.left; + this.originalScrollTop = where.top; + } else { + this.originalScrollLeft = this.options.scroll.scrollLeft; + this.originalScrollTop = this.options.scroll.scrollTop; + } + } + + Draggables.notify('onStart', this, event); + + if(this.options.starteffect) this.options.starteffect(this.element); + }, + + updateDrag: function(event, pointer) { + if(!this.dragging) this.startDrag(event); + + if(!this.options.quiet){ + Position.prepare(); + Droppables.show(pointer, this.element); + } + + Draggables.notify('onDrag', this, event); + + this.draw(pointer); + if(this.options.change) this.options.change(this); + + if(this.options.scroll) { + this.stopScrolling(); + + var p; + if (this.options.scroll == window) { + with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; } + } else { + p = Position.page(this.options.scroll); + p[0] += this.options.scroll.scrollLeft + Position.deltaX; + p[1] += this.options.scroll.scrollTop + Position.deltaY; + p.push(p[0]+this.options.scroll.offsetWidth); + p.push(p[1]+this.options.scroll.offsetHeight); + } + var speed = [0,0]; + if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity); + if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity); + if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity); + if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity); + this.startScrolling(speed); + } + + // fix AppleWebKit rendering + if(Prototype.Browser.WebKit) window.scrollBy(0,0); + + Event.stop(event); + }, + + finishDrag: function(event, success) { + this.dragging = false; + + if(this.options.quiet){ + Position.prepare(); + var pointer = [Event.pointerX(event), Event.pointerY(event)]; + Droppables.show(pointer, this.element); + } + + if(this.options.ghosting) { + if (!this._originallyAbsolute) + Position.relativize(this.element); + delete this._originallyAbsolute; + Element.remove(this._clone); + this._clone = null; + } + + var dropped = false; + if(success) { + dropped = Droppables.fire(event, this.element); + if (!dropped) dropped = false; + } + if(dropped && this.options.onDropped) this.options.onDropped(this.element); + Draggables.notify('onEnd', this, event); + + var revert = this.options.revert; + if(revert && Object.isFunction(revert)) revert = revert(this.element); + + var d = this.currentDelta(); + if(revert && this.options.reverteffect) { + if (dropped == 0 || revert != 'failure') + this.options.reverteffect(this.element, + d[1]-this.delta[1], d[0]-this.delta[0]); + } else { + this.delta = d; + } + + if(this.options.zindex) + this.element.style.zIndex = this.originalZ; + + if(this.options.endeffect) + this.options.endeffect(this.element); + + Draggables.deactivate(this); + Droppables.reset(); + }, + + keyPress: function(event) { + if(event.keyCode!=Event.KEY_ESC) return; + this.finishDrag(event, false); + Event.stop(event); + }, + + endDrag: function(event) { + if(!this.dragging) return; + this.stopScrolling(); + this.finishDrag(event, true); + Event.stop(event); + }, + + draw: function(point) { + var pos = Position.cumulativeOffset(this.element); + if(this.options.ghosting) { + var r = Position.realOffset(this.element); + pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY; + } + + var d = this.currentDelta(); + pos[0] -= d[0]; pos[1] -= d[1]; + + if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) { + pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft; + pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop; + } + + var p = [0,1].map(function(i){ + return (point[i]-pos[i]-this.offset[i]) + }.bind(this)); + + if(this.options.snap) { + if(Object.isFunction(this.options.snap)) { + p = this.options.snap(p[0],p[1],this); + } else { + if(Object.isArray(this.options.snap)) { + p = p.map( function(v, i) { + return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this)); + } else { + p = p.map( function(v) { + return (v/this.options.snap).round()*this.options.snap }.bind(this)); + } + }} + + var style = this.element.style; + if((!this.options.constraint) || (this.options.constraint=='horizontal')) + style.left = p[0] + "px"; + if((!this.options.constraint) || (this.options.constraint=='vertical')) + style.top = p[1] + "px"; + + if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering + }, + + stopScrolling: function() { + if(this.scrollInterval) { + clearInterval(this.scrollInterval); + this.scrollInterval = null; + Draggables._lastScrollPointer = null; + } + }, + + startScrolling: function(speed) { + if(!(speed[0] || speed[1])) return; + this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed]; + this.lastScrolled = new Date(); + this.scrollInterval = setInterval(this.scroll.bind(this), 10); + }, + + scroll: function() { + var current = new Date(); + var delta = current - this.lastScrolled; + this.lastScrolled = current; + if(this.options.scroll == window) { + with (this._getWindowScroll(this.options.scroll)) { + if (this.scrollSpeed[0] || this.scrollSpeed[1]) { + var d = delta / 1000; + this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] ); + } + } + } else { + this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; + this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000; + } + + Position.prepare(); + Droppables.show(Draggables._lastPointer, this.element); + Draggables.notify('onDrag', this); + if (this._isScrollChild) { + Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer); + Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000; + Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000; + if (Draggables._lastScrollPointer[0] < 0) + Draggables._lastScrollPointer[0] = 0; + if (Draggables._lastScrollPointer[1] < 0) + Draggables._lastScrollPointer[1] = 0; + this.draw(Draggables._lastScrollPointer); + } + + if(this.options.change) this.options.change(this); + }, + + _getWindowScroll: function(w) { + var T, L, W, H; + with (w.document) { + if (w.document.documentElement && documentElement.scrollTop) { + T = documentElement.scrollTop; + L = documentElement.scrollLeft; + } else if (w.document.body) { + T = body.scrollTop; + L = body.scrollLeft; + } + if (w.innerWidth) { + W = w.innerWidth; + H = w.innerHeight; + } else if (w.document.documentElement && documentElement.clientWidth) { + W = documentElement.clientWidth; + H = documentElement.clientHeight; + } else { + W = body.offsetWidth; + H = body.offsetHeight; + } + } + return { top: T, left: L, width: W, height: H }; + } +}); + +Draggable._dragging = { }; + +/*--------------------------------------------------------------------------*/ + +var SortableObserver = Class.create({ + initialize: function(element, observer) { + this.element = $(element); + this.observer = observer; + this.lastValue = Sortable.serialize(this.element); + }, + + onStart: function() { + this.lastValue = Sortable.serialize(this.element); + }, + + onEnd: function() { + Sortable.unmark(); + if(this.lastValue != Sortable.serialize(this.element)) + this.observer(this.element) + } +}); + +var Sortable = { + SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/, + + sortables: { }, + + _findRootElement: function(element) { + while (element.tagName.toUpperCase() != "BODY") { + if(element.id && Sortable.sortables[element.id]) return element; + element = element.parentNode; + } + }, + + options: function(element) { + element = Sortable._findRootElement($(element)); + if(!element) return; + return Sortable.sortables[element.id]; + }, + + destroy: function(element){ + element = $(element); + var s = Sortable.sortables[element.id]; + + if(s) { + Draggables.removeObserver(s.element); + s.droppables.each(function(d){ Droppables.remove(d) }); + s.draggables.invoke('destroy'); + + delete Sortable.sortables[s.element.id]; + } + }, + + create: function(element) { + element = $(element); + var options = Object.extend({ + element: element, + tag: 'li', // assumes li children, override with tag: 'tagname' + dropOnEmpty: false, + tree: false, + treeTag: 'ul', + overlap: 'vertical', // one of 'vertical', 'horizontal' + constraint: 'vertical', // one of 'vertical', 'horizontal', false + containment: element, // also takes array of elements (or id's); or false + handle: false, // or a CSS class + only: false, + delay: 0, + hoverclass: null, + ghosting: false, + quiet: false, + scroll: false, + scrollSensitivity: 20, + scrollSpeed: 15, + format: this.SERIALIZE_RULE, + + // these take arrays of elements or ids and can be + // used for better initialization performance + elements: false, + handles: false, + + onChange: Prototype.emptyFunction, + onUpdate: Prototype.emptyFunction + }, arguments[1] || { }); + + // clear any old sortable with same element + this.destroy(element); + + // build options for the draggables + var options_for_draggable = { + revert: true, + quiet: options.quiet, + scroll: options.scroll, + scrollSpeed: options.scrollSpeed, + scrollSensitivity: options.scrollSensitivity, + delay: options.delay, + ghosting: options.ghosting, + constraint: options.constraint, + handle: options.handle }; + + if(options.starteffect) + options_for_draggable.starteffect = options.starteffect; + + if(options.reverteffect) + options_for_draggable.reverteffect = options.reverteffect; + else + if(options.ghosting) options_for_draggable.reverteffect = function(element) { + element.style.top = 0; + element.style.left = 0; + }; + + if(options.endeffect) + options_for_draggable.endeffect = options.endeffect; + + if(options.zindex) + options_for_draggable.zindex = options.zindex; + + // build options for the droppables + var options_for_droppable = { + overlap: options.overlap, + containment: options.containment, + tree: options.tree, + hoverclass: options.hoverclass, + onHover: Sortable.onHover + }; + + var options_for_tree = { + onHover: Sortable.onEmptyHover, + overlap: options.overlap, + containment: options.containment, + hoverclass: options.hoverclass + }; + + // fix for gecko engine + Element.cleanWhitespace(element); + + options.draggables = []; + options.droppables = []; + + // drop on empty handling + if(options.dropOnEmpty || options.tree) { + Droppables.add(element, options_for_tree); + options.droppables.push(element); + } + + (options.elements || this.findElements(element, options) || []).each( function(e,i) { + var handle = options.handles ? $(options.handles[i]) : + (options.handle ? $(e).select('.' + options.handle)[0] : e); + options.draggables.push( + new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); + Droppables.add(e, options_for_droppable); + if(options.tree) e.treeNode = element; + options.droppables.push(e); + }); + + if(options.tree) { + (Sortable.findTreeElements(element, options) || []).each( function(e) { + Droppables.add(e, options_for_tree); + e.treeNode = element; + options.droppables.push(e); + }); + } + + // keep reference + this.sortables[element.id] = options; + + // for onupdate + Draggables.addObserver(new SortableObserver(element, options.onUpdate)); + + }, + + // return all suitable-for-sortable elements in a guaranteed order + findElements: function(element, options) { + return Element.findChildren( + element, options.only, options.tree ? true : false, options.tag); + }, + + findTreeElements: function(element, options) { + return Element.findChildren( + element, options.only, options.tree ? true : false, options.treeTag); + }, + + onHover: function(element, dropon, overlap) { + if(Element.isParent(dropon, element)) return; + + if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) { + return; + } else if(overlap>0.5) { + Sortable.mark(dropon, 'before'); + if(dropon.previousSibling != element) { + var oldParentNode = element.parentNode; + element.style.visibility = "hidden"; // fix gecko rendering + dropon.parentNode.insertBefore(element, dropon); + if(dropon.parentNode!=oldParentNode) + Sortable.options(oldParentNode).onChange(element); + Sortable.options(dropon.parentNode).onChange(element); + } + } else { + Sortable.mark(dropon, 'after'); + var nextElement = dropon.nextSibling || null; + if(nextElement != element) { + var oldParentNode = element.parentNode; + element.style.visibility = "hidden"; // fix gecko rendering + dropon.parentNode.insertBefore(element, nextElement); + if(dropon.parentNode!=oldParentNode) + Sortable.options(oldParentNode).onChange(element); + Sortable.options(dropon.parentNode).onChange(element); + } + } + }, + + onEmptyHover: function(element, dropon, overlap) { + var oldParentNode = element.parentNode; + var droponOptions = Sortable.options(dropon); + + if(!Element.isParent(dropon, element)) { + var index; + + var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only}); + var child = null; + + if(children) { + var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap); + + for (index = 0; index < children.length; index += 1) { + if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) { + offset -= Element.offsetSize (children[index], droponOptions.overlap); + } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) { + child = index + 1 < children.length ? children[index + 1] : null; + break; + } else { + child = children[index]; + break; + } + } + } + + dropon.insertBefore(element, child); + + Sortable.options(oldParentNode).onChange(element); + droponOptions.onChange(element); + } + }, + + unmark: function() { + if(Sortable._marker) Sortable._marker.hide(); + }, + + mark: function(dropon, position) { + // mark on ghosting only + var sortable = Sortable.options(dropon.parentNode); + if(sortable && !sortable.ghosting) return; + + if(!Sortable._marker) { + Sortable._marker = + ($('dropmarker') || Element.extend(document.createElement('DIV'))). + hide().addClassName('dropmarker').setStyle({position:'absolute'}); + document.getElementsByTagName("body").item(0).appendChild(Sortable._marker); + } + var offsets = Position.cumulativeOffset(dropon); + Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'}); + + if(position=='after') + if(sortable.overlap == 'horizontal') + Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'}); + else + Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'}); + + Sortable._marker.show(); + }, + + _tree: function(element, options, parent) { + var children = Sortable.findElements(element, options) || []; + + for (var i = 0; i < children.length; ++i) { + var match = children[i].id.match(options.format); + + if (!match) continue; + + var child = { + id: encodeURIComponent(match ? match[1] : null), + element: element, + parent: parent, + children: [], + position: parent.children.length, + container: $(children[i]).down(options.treeTag) + }; + + /* Get the element containing the children and recurse over it */ + if (child.container) + this._tree(child.container, options, child); + + parent.children.push (child); + } + + return parent; + }, + + tree: function(element) { + element = $(element); + var sortableOptions = this.options(element); + var options = Object.extend({ + tag: sortableOptions.tag, + treeTag: sortableOptions.treeTag, + only: sortableOptions.only, + name: element.id, + format: sortableOptions.format + }, arguments[1] || { }); + + var root = { + id: null, + parent: null, + children: [], + container: element, + position: 0 + }; + + return Sortable._tree(element, options, root); + }, + + /* Construct a [i] index for a particular node */ + _constructIndex: function(node) { + var index = ''; + do { + if (node.id) index = '[' + node.position + ']' + index; + } while ((node = node.parent) != null); + return index; + }, + + sequence: function(element) { + element = $(element); + var options = Object.extend(this.options(element), arguments[1] || { }); + + return $(this.findElements(element, options) || []).map( function(item) { + return item.id.match(options.format) ? item.id.match(options.format)[1] : ''; + }); + }, + + setSequence: function(element, new_sequence) { + element = $(element); + var options = Object.extend(this.options(element), arguments[2] || { }); + + var nodeMap = { }; + this.findElements(element, options).each( function(n) { + if (n.id.match(options.format)) + nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode]; + n.parentNode.removeChild(n); + }); + + new_sequence.each(function(ident) { + var n = nodeMap[ident]; + if (n) { + n[1].appendChild(n[0]); + delete nodeMap[ident]; + } + }); + }, + + serialize: function(element) { + element = $(element); + var options = Object.extend(Sortable.options(element), arguments[1] || { }); + var name = encodeURIComponent( + (arguments[1] && arguments[1].name) ? arguments[1].name : element.id); + + if (options.tree) { + return Sortable.tree(element, arguments[1]).children.map( function (item) { + return [name + Sortable._constructIndex(item) + "[id]=" + + encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)); + }).flatten().join('&'); + } else { + return Sortable.sequence(element, arguments[1]).map( function(item) { + return name + "[]=" + encodeURIComponent(item); + }).join('&'); + } + } +}; + +// Returns true if child is contained within element +Element.isParent = function(child, element) { + if (!child.parentNode || child == element) return false; + if (child.parentNode == element) return true; + return Element.isParent(child.parentNode, element); +}; + +Element.findChildren = function(element, only, recursive, tagName) { + if(!element.hasChildNodes()) return null; + tagName = tagName.toUpperCase(); + if(only) only = [only].flatten(); + var elements = []; + $A(element.childNodes).each( function(e) { + if(e.tagName && e.tagName.toUpperCase()==tagName && + (!only || (Element.classNames(e).detect(function(v) { return only.include(v) })))) + elements.push(e); + if(recursive) { + var grandchildren = Element.findChildren(e, only, recursive, tagName); + if(grandchildren) elements.push(grandchildren); + } + }); + + return (elements.length>0 ? elements.flatten() : []); +}; + +Element.offsetSize = function (element, type) { + return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')]; +}; \ No newline at end of file diff --git a/public/javascripts/effects.js b/public/javascripts/effects.js new file mode 100644 index 0000000..5a639d2 --- /dev/null +++ b/public/javascripts/effects.js @@ -0,0 +1,1128 @@ +// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// Contributors: +// Justin Palmer (http://encytemedia.com/) +// Mark Pilgrim (http://diveintomark.org/) +// Martin Bialasinki +// +// script.aculo.us is freely distributable under the terms of an MIT-style license. +// For details, see the script.aculo.us web site: http://script.aculo.us/ + +// converts rgb() and #xxx to #xxxxxx format, +// returns self (or first argument) if not convertable +String.prototype.parseColor = function() { + var color = '#'; + if (this.slice(0,4) == 'rgb(') { + var cols = this.slice(4,this.length-1).split(','); + var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); + } else { + if (this.slice(0,1) == '#') { + if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); + if (this.length==7) color = this.toLowerCase(); + } + } + return (color.length==7 ? color : (arguments[0] || this)); +}; + +/*--------------------------------------------------------------------------*/ + +Element.collectTextNodes = function(element) { + return $A($(element).childNodes).collect( function(node) { + return (node.nodeType==3 ? node.nodeValue : + (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); + }).flatten().join(''); +}; + +Element.collectTextNodesIgnoreClass = function(element, className) { + return $A($(element).childNodes).collect( function(node) { + return (node.nodeType==3 ? node.nodeValue : + ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? + Element.collectTextNodesIgnoreClass(node, className) : '')); + }).flatten().join(''); +}; + +Element.setContentZoom = function(element, percent) { + element = $(element); + element.setStyle({fontSize: (percent/100) + 'em'}); + if (Prototype.Browser.WebKit) window.scrollBy(0,0); + return element; +}; + +Element.getInlineOpacity = function(element){ + return $(element).style.opacity || ''; +}; + +Element.forceRerendering = function(element) { + try { + element = $(element); + var n = document.createTextNode(' '); + element.appendChild(n); + element.removeChild(n); + } catch(e) { } +}; + +/*--------------------------------------------------------------------------*/ + +var Effect = { + _elementDoesNotExistError: { + name: 'ElementDoesNotExistError', + message: 'The specified DOM element does not exist, but is required for this effect to operate' + }, + Transitions: { + linear: Prototype.K, + sinoidal: function(pos) { + return (-Math.cos(pos*Math.PI)/2) + .5; + }, + reverse: function(pos) { + return 1-pos; + }, + flicker: function(pos) { + var pos = ((-Math.cos(pos*Math.PI)/4) + .75) + Math.random()/4; + return pos > 1 ? 1 : pos; + }, + wobble: function(pos) { + return (-Math.cos(pos*Math.PI*(9*pos))/2) + .5; + }, + pulse: function(pos, pulses) { + return (-Math.cos((pos*((pulses||5)-.5)*2)*Math.PI)/2) + .5; + }, + spring: function(pos) { + return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6)); + }, + none: function(pos) { + return 0; + }, + full: function(pos) { + return 1; + } + }, + DefaultOptions: { + duration: 1.0, // seconds + fps: 100, // 100= assume 66fps max. + sync: false, // true for combining + from: 0.0, + to: 1.0, + delay: 0.0, + queue: 'parallel' + }, + tagifyText: function(element) { + var tagifyStyle = 'position:relative'; + if (Prototype.Browser.IE) tagifyStyle += ';zoom:1'; + + element = $(element); + $A(element.childNodes).each( function(child) { + if (child.nodeType==3) { + child.nodeValue.toArray().each( function(character) { + element.insertBefore( + new Element('span', {style: tagifyStyle}).update( + character == ' ' ? String.fromCharCode(160) : character), + child); + }); + Element.remove(child); + } + }); + }, + multiple: function(element, effect) { + var elements; + if (((typeof element == 'object') || + Object.isFunction(element)) && + (element.length)) + elements = element; + else + elements = $(element).childNodes; + + var options = Object.extend({ + speed: 0.1, + delay: 0.0 + }, arguments[2] || { }); + var masterDelay = options.delay; + + $A(elements).each( function(element, index) { + new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); + }); + }, + PAIRS: { + 'slide': ['SlideDown','SlideUp'], + 'blind': ['BlindDown','BlindUp'], + 'appear': ['Appear','Fade'] + }, + toggle: function(element, effect) { + element = $(element); + effect = (effect || 'appear').toLowerCase(); + var options = Object.extend({ + queue: { position:'end', scope:(element.id || 'global'), limit: 1 } + }, arguments[2] || { }); + Effect[element.visible() ? + Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); + } +}; + +Effect.DefaultOptions.transition = Effect.Transitions.sinoidal; + +/* ------------- core effects ------------- */ + +Effect.ScopedQueue = Class.create(Enumerable, { + initialize: function() { + this.effects = []; + this.interval = null; + }, + _each: function(iterator) { + this.effects._each(iterator); + }, + add: function(effect) { + var timestamp = new Date().getTime(); + + var position = Object.isString(effect.options.queue) ? + effect.options.queue : effect.options.queue.position; + + switch(position) { + case 'front': + // move unstarted effects after this effect + this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { + e.startOn += effect.finishOn; + e.finishOn += effect.finishOn; + }); + break; + case 'with-last': + timestamp = this.effects.pluck('startOn').max() || timestamp; + break; + case 'end': + // start effect after last queued effect has finished + timestamp = this.effects.pluck('finishOn').max() || timestamp; + break; + } + + effect.startOn += timestamp; + effect.finishOn += timestamp; + + if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) + this.effects.push(effect); + + if (!this.interval) + this.interval = setInterval(this.loop.bind(this), 15); + }, + remove: function(effect) { + this.effects = this.effects.reject(function(e) { return e==effect }); + if (this.effects.length == 0) { + clearInterval(this.interval); + this.interval = null; + } + }, + loop: function() { + var timePos = new Date().getTime(); + for(var i=0, len=this.effects.length;i= this.startOn) { + if (timePos >= this.finishOn) { + this.render(1.0); + this.cancel(); + this.event('beforeFinish'); + if (this.finish) this.finish(); + this.event('afterFinish'); + return; + } + var pos = (timePos - this.startOn) / this.totalTime, + frame = (pos * this.totalFrames).round(); + if (frame > this.currentFrame) { + this.render(pos); + this.currentFrame = frame; + } + } + }, + cancel: function() { + if (!this.options.sync) + Effect.Queues.get(Object.isString(this.options.queue) ? + 'global' : this.options.queue.scope).remove(this); + this.state = 'finished'; + }, + event: function(eventName) { + if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); + if (this.options[eventName]) this.options[eventName](this); + }, + inspect: function() { + var data = $H(); + for(property in this) + if (!Object.isFunction(this[property])) data.set(property, this[property]); + return '#'; + } +}); + +Effect.Parallel = Class.create(Effect.Base, { + initialize: function(effects) { + this.effects = effects || []; + this.start(arguments[1]); + }, + update: function(position) { + this.effects.invoke('render', position); + }, + finish: function(position) { + this.effects.each( function(effect) { + effect.render(1.0); + effect.cancel(); + effect.event('beforeFinish'); + if (effect.finish) effect.finish(position); + effect.event('afterFinish'); + }); + } +}); + +Effect.Tween = Class.create(Effect.Base, { + initialize: function(object, from, to) { + object = Object.isString(object) ? $(object) : object; + var args = $A(arguments), method = args.last(), + options = args.length == 5 ? args[3] : null; + this.method = Object.isFunction(method) ? method.bind(object) : + Object.isFunction(object[method]) ? object[method].bind(object) : + function(value) { object[method] = value }; + this.start(Object.extend({ from: from, to: to }, options || { })); + }, + update: function(position) { + this.method(position); + } +}); + +Effect.Event = Class.create(Effect.Base, { + initialize: function() { + this.start(Object.extend({ duration: 0 }, arguments[0] || { })); + }, + update: Prototype.emptyFunction +}); + +Effect.Opacity = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + // make this work on IE on elements without 'layout' + if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) + this.element.setStyle({zoom: 1}); + var options = Object.extend({ + from: this.element.getOpacity() || 0.0, + to: 1.0 + }, arguments[1] || { }); + this.start(options); + }, + update: function(position) { + this.element.setOpacity(position); + } +}); + +Effect.Move = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ + x: 0, + y: 0, + mode: 'relative' + }, arguments[1] || { }); + this.start(options); + }, + setup: function() { + this.element.makePositioned(); + this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); + this.originalTop = parseFloat(this.element.getStyle('top') || '0'); + if (this.options.mode == 'absolute') { + this.options.x = this.options.x - this.originalLeft; + this.options.y = this.options.y - this.originalTop; + } + }, + update: function(position) { + this.element.setStyle({ + left: (this.options.x * position + this.originalLeft).round() + 'px', + top: (this.options.y * position + this.originalTop).round() + 'px' + }); + } +}); + +// for backwards compatibility +Effect.MoveBy = function(element, toTop, toLeft) { + return new Effect.Move(element, + Object.extend({ x: toLeft, y: toTop }, arguments[3] || { })); +}; + +Effect.Scale = Class.create(Effect.Base, { + initialize: function(element, percent) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ + scaleX: true, + scaleY: true, + scaleContent: true, + scaleFromCenter: false, + scaleMode: 'box', // 'box' or 'contents' or { } with provided values + scaleFrom: 100.0, + scaleTo: percent + }, arguments[2] || { }); + this.start(options); + }, + setup: function() { + this.restoreAfterFinish = this.options.restoreAfterFinish || false; + this.elementPositioning = this.element.getStyle('position'); + + this.originalStyle = { }; + ['top','left','width','height','fontSize'].each( function(k) { + this.originalStyle[k] = this.element.style[k]; + }.bind(this)); + + this.originalTop = this.element.offsetTop; + this.originalLeft = this.element.offsetLeft; + + var fontSize = this.element.getStyle('font-size') || '100%'; + ['em','px','%','pt'].each( function(fontSizeType) { + if (fontSize.indexOf(fontSizeType)>0) { + this.fontSize = parseFloat(fontSize); + this.fontSizeType = fontSizeType; + } + }.bind(this)); + + this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; + + this.dims = null; + if (this.options.scaleMode=='box') + this.dims = [this.element.offsetHeight, this.element.offsetWidth]; + if (/^content/.test(this.options.scaleMode)) + this.dims = [this.element.scrollHeight, this.element.scrollWidth]; + if (!this.dims) + this.dims = [this.options.scaleMode.originalHeight, + this.options.scaleMode.originalWidth]; + }, + update: function(position) { + var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); + if (this.options.scaleContent && this.fontSize) + this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); + this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); + }, + finish: function(position) { + if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); + }, + setDimensions: function(height, width) { + var d = { }; + if (this.options.scaleX) d.width = width.round() + 'px'; + if (this.options.scaleY) d.height = height.round() + 'px'; + if (this.options.scaleFromCenter) { + var topd = (height - this.dims[0])/2; + var leftd = (width - this.dims[1])/2; + if (this.elementPositioning == 'absolute') { + if (this.options.scaleY) d.top = this.originalTop-topd + 'px'; + if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; + } else { + if (this.options.scaleY) d.top = -topd + 'px'; + if (this.options.scaleX) d.left = -leftd + 'px'; + } + } + this.element.setStyle(d); + } +}); + +Effect.Highlight = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { }); + this.start(options); + }, + setup: function() { + // Prevent executing on elements not in the layout flow + if (this.element.getStyle('display')=='none') { this.cancel(); return; } + // Disable background image during the effect + this.oldStyle = { }; + if (!this.options.keepBackgroundImage) { + this.oldStyle.backgroundImage = this.element.getStyle('background-image'); + this.element.setStyle({backgroundImage: 'none'}); + } + if (!this.options.endcolor) + this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); + if (!this.options.restorecolor) + this.options.restorecolor = this.element.getStyle('background-color'); + // init color calculations + this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); + this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this)); + }, + update: function(position) { + this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ + return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) }); + }, + finish: function() { + this.element.setStyle(Object.extend(this.oldStyle, { + backgroundColor: this.options.restorecolor + })); + } +}); + +Effect.ScrollTo = function(element) { + var options = arguments[1] || { }, + scrollOffsets = document.viewport.getScrollOffsets(), + elementOffsets = $(element).cumulativeOffset(); + + if (options.offset) elementOffsets[1] += options.offset; + + return new Effect.Tween(null, + scrollOffsets.top, + elementOffsets[1], + options, + function(p){ scrollTo(scrollOffsets.left, p.round()); } + ); +}; + +/* ------------- combination effects ------------- */ + +Effect.Fade = function(element) { + element = $(element); + var oldOpacity = element.getInlineOpacity(); + var options = Object.extend({ + from: element.getOpacity() || 1.0, + to: 0.0, + afterFinishInternal: function(effect) { + if (effect.options.to!=0) return; + effect.element.hide().setStyle({opacity: oldOpacity}); + } + }, arguments[1] || { }); + return new Effect.Opacity(element,options); +}; + +Effect.Appear = function(element) { + element = $(element); + var options = Object.extend({ + from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), + to: 1.0, + // force Safari to render floated elements properly + afterFinishInternal: function(effect) { + effect.element.forceRerendering(); + }, + beforeSetup: function(effect) { + effect.element.setOpacity(effect.options.from).show(); + }}, arguments[1] || { }); + return new Effect.Opacity(element,options); +}; + +Effect.Puff = function(element) { + element = $(element); + var oldStyle = { + opacity: element.getInlineOpacity(), + position: element.getStyle('position'), + top: element.style.top, + left: element.style.left, + width: element.style.width, + height: element.style.height + }; + return new Effect.Parallel( + [ new Effect.Scale(element, 200, + { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), + new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], + Object.extend({ duration: 1.0, + beforeSetupInternal: function(effect) { + Position.absolutize(effect.effects[0].element); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide().setStyle(oldStyle); } + }, arguments[1] || { }) + ); +}; + +Effect.BlindUp = function(element) { + element = $(element); + element.makeClipping(); + return new Effect.Scale(element, 0, + Object.extend({ scaleContent: false, + scaleX: false, + restoreAfterFinish: true, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping(); + } + }, arguments[1] || { }) + ); +}; + +Effect.BlindDown = function(element) { + element = $(element); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, 100, Object.extend({ + scaleContent: false, + scaleX: false, + scaleFrom: 0, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makeClipping().setStyle({height: '0px'}).show(); + }, + afterFinishInternal: function(effect) { + effect.element.undoClipping(); + } + }, arguments[1] || { })); +}; + +Effect.SwitchOff = function(element) { + element = $(element); + var oldOpacity = element.getInlineOpacity(); + return new Effect.Appear(element, Object.extend({ + duration: 0.4, + from: 0, + transition: Effect.Transitions.flicker, + afterFinishInternal: function(effect) { + new Effect.Scale(effect.element, 1, { + duration: 0.3, scaleFromCenter: true, + scaleX: false, scaleContent: false, restoreAfterFinish: true, + beforeSetup: function(effect) { + effect.element.makePositioned().makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity}); + } + }); + } + }, arguments[1] || { })); +}; + +Effect.DropOut = function(element) { + element = $(element); + var oldStyle = { + top: element.getStyle('top'), + left: element.getStyle('left'), + opacity: element.getInlineOpacity() }; + return new Effect.Parallel( + [ new Effect.Move(element, {x: 0, y: 100, sync: true }), + new Effect.Opacity(element, { sync: true, to: 0.0 }) ], + Object.extend( + { duration: 0.5, + beforeSetup: function(effect) { + effect.effects[0].element.makePositioned(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle); + } + }, arguments[1] || { })); +}; + +Effect.Shake = function(element) { + element = $(element); + var options = Object.extend({ + distance: 20, + duration: 0.5 + }, arguments[1] || {}); + var distance = parseFloat(options.distance); + var split = parseFloat(options.duration) / 10.0; + var oldStyle = { + top: element.getStyle('top'), + left: element.getStyle('left') }; + return new Effect.Move(element, + { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) { + effect.element.undoPositioned().setStyle(oldStyle); + }}); }}); }}); }}); }}); }}); +}; + +Effect.SlideDown = function(element) { + element = $(element).cleanWhitespace(); + // SlideDown need to have the content of the element wrapped in a container element with fixed height! + var oldInnerBottom = element.down().getStyle('bottom'); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, 100, Object.extend({ + scaleContent: false, + scaleX: false, + scaleFrom: window.opera ? 0 : 1, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makePositioned(); + effect.element.down().makePositioned(); + if (window.opera) effect.element.setStyle({top: ''}); + effect.element.makeClipping().setStyle({height: '0px'}).show(); + }, + afterUpdateInternal: function(effect) { + effect.element.down().setStyle({bottom: + (effect.dims[0] - effect.element.clientHeight) + 'px' }); + }, + afterFinishInternal: function(effect) { + effect.element.undoClipping().undoPositioned(); + effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); } + }, arguments[1] || { }) + ); +}; + +Effect.SlideUp = function(element) { + element = $(element).cleanWhitespace(); + var oldInnerBottom = element.down().getStyle('bottom'); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, window.opera ? 0 : 1, + Object.extend({ scaleContent: false, + scaleX: false, + scaleMode: 'box', + scaleFrom: 100, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makePositioned(); + effect.element.down().makePositioned(); + if (window.opera) effect.element.setStyle({top: ''}); + effect.element.makeClipping().show(); + }, + afterUpdateInternal: function(effect) { + effect.element.down().setStyle({bottom: + (effect.dims[0] - effect.element.clientHeight) + 'px' }); + }, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping().undoPositioned(); + effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); + } + }, arguments[1] || { }) + ); +}; + +// Bug in opera makes the TD containing this element expand for a instance after finish +Effect.Squish = function(element) { + return new Effect.Scale(element, window.opera ? 1 : 0, { + restoreAfterFinish: true, + beforeSetup: function(effect) { + effect.element.makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping(); + } + }); +}; + +Effect.Grow = function(element) { + element = $(element); + var options = Object.extend({ + direction: 'center', + moveTransition: Effect.Transitions.sinoidal, + scaleTransition: Effect.Transitions.sinoidal, + opacityTransition: Effect.Transitions.full + }, arguments[1] || { }); + var oldStyle = { + top: element.style.top, + left: element.style.left, + height: element.style.height, + width: element.style.width, + opacity: element.getInlineOpacity() }; + + var dims = element.getDimensions(); + var initialMoveX, initialMoveY; + var moveX, moveY; + + switch (options.direction) { + case 'top-left': + initialMoveX = initialMoveY = moveX = moveY = 0; + break; + case 'top-right': + initialMoveX = dims.width; + initialMoveY = moveY = 0; + moveX = -dims.width; + break; + case 'bottom-left': + initialMoveX = moveX = 0; + initialMoveY = dims.height; + moveY = -dims.height; + break; + case 'bottom-right': + initialMoveX = dims.width; + initialMoveY = dims.height; + moveX = -dims.width; + moveY = -dims.height; + break; + case 'center': + initialMoveX = dims.width / 2; + initialMoveY = dims.height / 2; + moveX = -dims.width / 2; + moveY = -dims.height / 2; + break; + } + + return new Effect.Move(element, { + x: initialMoveX, + y: initialMoveY, + duration: 0.01, + beforeSetup: function(effect) { + effect.element.hide().makeClipping().makePositioned(); + }, + afterFinishInternal: function(effect) { + new Effect.Parallel( + [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), + new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), + new Effect.Scale(effect.element, 100, { + scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, + sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) + ], Object.extend({ + beforeSetup: function(effect) { + effect.effects[0].element.setStyle({height: '0px'}).show(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle); + } + }, options) + ); + } + }); +}; + +Effect.Shrink = function(element) { + element = $(element); + var options = Object.extend({ + direction: 'center', + moveTransition: Effect.Transitions.sinoidal, + scaleTransition: Effect.Transitions.sinoidal, + opacityTransition: Effect.Transitions.none + }, arguments[1] || { }); + var oldStyle = { + top: element.style.top, + left: element.style.left, + height: element.style.height, + width: element.style.width, + opacity: element.getInlineOpacity() }; + + var dims = element.getDimensions(); + var moveX, moveY; + + switch (options.direction) { + case 'top-left': + moveX = moveY = 0; + break; + case 'top-right': + moveX = dims.width; + moveY = 0; + break; + case 'bottom-left': + moveX = 0; + moveY = dims.height; + break; + case 'bottom-right': + moveX = dims.width; + moveY = dims.height; + break; + case 'center': + moveX = dims.width / 2; + moveY = dims.height / 2; + break; + } + + return new Effect.Parallel( + [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), + new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), + new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) + ], Object.extend({ + beforeStartInternal: function(effect) { + effect.effects[0].element.makePositioned().makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); } + }, options) + ); +}; + +Effect.Pulsate = function(element) { + element = $(element); + var options = arguments[1] || { }, + oldOpacity = element.getInlineOpacity(), + transition = options.transition || Effect.Transitions.linear, + reverser = function(pos){ + return 1 - transition((-Math.cos((pos*(options.pulses||5)*2)*Math.PI)/2) + .5); + }; + + return new Effect.Opacity(element, + Object.extend(Object.extend({ duration: 2.0, from: 0, + afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } + }, options), {transition: reverser})); +}; + +Effect.Fold = function(element) { + element = $(element); + var oldStyle = { + top: element.style.top, + left: element.style.left, + width: element.style.width, + height: element.style.height }; + element.makeClipping(); + return new Effect.Scale(element, 5, Object.extend({ + scaleContent: false, + scaleX: false, + afterFinishInternal: function(effect) { + new Effect.Scale(element, 1, { + scaleContent: false, + scaleY: false, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping().setStyle(oldStyle); + } }); + }}, arguments[1] || { })); +}; + +Effect.Morph = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ + style: { } + }, arguments[1] || { }); + + if (!Object.isString(options.style)) this.style = $H(options.style); + else { + if (options.style.include(':')) + this.style = options.style.parseStyle(); + else { + this.element.addClassName(options.style); + this.style = $H(this.element.getStyles()); + this.element.removeClassName(options.style); + var css = this.element.getStyles(); + this.style = this.style.reject(function(style) { + return style.value == css[style.key]; + }); + options.afterFinishInternal = function(effect) { + effect.element.addClassName(effect.options.style); + effect.transforms.each(function(transform) { + effect.element.style[transform.style] = ''; + }); + }; + } + } + this.start(options); + }, + + setup: function(){ + function parseColor(color){ + if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff'; + color = color.parseColor(); + return $R(0,2).map(function(i){ + return parseInt( color.slice(i*2+1,i*2+3), 16 ); + }); + } + this.transforms = this.style.map(function(pair){ + var property = pair[0], value = pair[1], unit = null; + + if (value.parseColor('#zzzzzz') != '#zzzzzz') { + value = value.parseColor(); + unit = 'color'; + } else if (property == 'opacity') { + value = parseFloat(value); + if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) + this.element.setStyle({zoom: 1}); + } else if (Element.CSS_LENGTH.test(value)) { + var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); + value = parseFloat(components[1]); + unit = (components.length == 3) ? components[2] : null; + } + + var originalValue = this.element.getStyle(property); + return { + style: property.camelize(), + originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), + targetValue: unit=='color' ? parseColor(value) : value, + unit: unit + }; + }.bind(this)).reject(function(transform){ + return ( + (transform.originalValue == transform.targetValue) || + ( + transform.unit != 'color' && + (isNaN(transform.originalValue) || isNaN(transform.targetValue)) + ) + ); + }); + }, + update: function(position) { + var style = { }, transform, i = this.transforms.length; + while(i--) + style[(transform = this.transforms[i]).style] = + transform.unit=='color' ? '#'+ + (Math.round(transform.originalValue[0]+ + (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() + + (Math.round(transform.originalValue[1]+ + (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() + + (Math.round(transform.originalValue[2]+ + (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() : + (transform.originalValue + + (transform.targetValue - transform.originalValue) * position).toFixed(3) + + (transform.unit === null ? '' : transform.unit); + this.element.setStyle(style, true); + } +}); + +Effect.Transform = Class.create({ + initialize: function(tracks){ + this.tracks = []; + this.options = arguments[1] || { }; + this.addTracks(tracks); + }, + addTracks: function(tracks){ + tracks.each(function(track){ + track = $H(track); + var data = track.values().first(); + this.tracks.push($H({ + ids: track.keys().first(), + effect: Effect.Morph, + options: { style: data } + })); + }.bind(this)); + return this; + }, + play: function(){ + return new Effect.Parallel( + this.tracks.map(function(track){ + var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options'); + var elements = [$(ids) || $$(ids)].flatten(); + return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) }); + }).flatten(), + this.options + ); + } +}); + +Element.CSS_PROPERTIES = $w( + 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + + 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' + + 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' + + 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' + + 'fontSize fontWeight height left letterSpacing lineHeight ' + + 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+ + 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' + + 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' + + 'right textIndent top width wordSpacing zIndex'); + +Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; + +String.__parseStyleElement = document.createElement('div'); +String.prototype.parseStyle = function(){ + var style, styleRules = $H(); + if (Prototype.Browser.WebKit) + style = new Element('div',{style:this}).style; + else { + String.__parseStyleElement.innerHTML = '
      '; + style = String.__parseStyleElement.childNodes[0].style; + } + + Element.CSS_PROPERTIES.each(function(property){ + if (style[property]) styleRules.set(property, style[property]); + }); + + if (Prototype.Browser.IE && this.include('opacity')) + styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]); + + return styleRules; +}; + +if (document.defaultView && document.defaultView.getComputedStyle) { + Element.getStyles = function(element) { + var css = document.defaultView.getComputedStyle($(element), null); + return Element.CSS_PROPERTIES.inject({ }, function(styles, property) { + styles[property] = css[property]; + return styles; + }); + }; +} else { + Element.getStyles = function(element) { + element = $(element); + var css = element.currentStyle, styles; + styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) { + results[property] = css[property]; + return results; + }); + if (!styles.opacity) styles.opacity = element.getOpacity(); + return styles; + }; +} + +Effect.Methods = { + morph: function(element, style) { + element = $(element); + new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { })); + return element; + }, + visualEffect: function(element, effect, options) { + element = $(element); + var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1); + new Effect[klass](element, options); + return element; + }, + highlight: function(element, options) { + element = $(element); + new Effect.Highlight(element, options); + return element; + } +}; + +$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+ + 'pulsate shake puff squish switchOff dropOut').each( + function(effect) { + Effect.Methods[effect] = function(element, options){ + element = $(element); + Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options); + return element; + }; + } +); + +$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each( + function(f) { Effect.Methods[f] = Element[f]; } +); + +Element.addMethods(Effect.Methods); \ No newline at end of file diff --git a/public/javascripts/facebox.js b/public/javascripts/facebox.js new file mode 100755 index 0000000..5ad90ed --- /dev/null +++ b/public/javascripts/facebox.js @@ -0,0 +1,309 @@ +/* + * Facebox (for jQuery) + * version: 1.2 (05/05/2008) + * @requires jQuery v1.2 or later + * + * Examples at http://famspam.com/facebox/ + * + * Licensed under the MIT: + * http://www.opensource.org/licenses/mit-license.php + * + * Copyright 2007, 2008 Chris Wanstrath [ chris@ozmm.org ] + * + * Usage: + * + * jQuery(document).ready(function() { + * jQuery('a[rel*=facebox]').facebox() + * }) + * + * Terms + * Loads the #terms div in the box + * + * Terms + * Loads the terms.html page in the box + * + * Terms + * Loads the terms.png image in the box + * + * + * You can also use it programmatically: + * + * jQuery.facebox('some html') + * jQuery.facebox('some html', 'my-groovy-style') + * + * The above will open a facebox with "some html" as the content. + * + * jQuery.facebox(function($) { + * $.get('blah.html', function(data) { $.facebox(data) }) + * }) + * + * The above will show a loading screen before the passed function is called, + * allowing for a better ajaxy experience. + * + * The facebox function can also display an ajax page, an image, or the contents of a div: + * + * jQuery.facebox({ ajax: 'remote.html' }) + * jQuery.facebox({ ajax: 'remote.html' }, 'my-groovy-style') + * jQuery.facebox({ image: 'stairs.jpg' }) + * jQuery.facebox({ image: 'stairs.jpg' }, 'my-groovy-style') + * jQuery.facebox({ div: '#box' }) + * jQuery.facebox({ div: '#box' }, 'my-groovy-style') + * + * Want to close the facebox? Trigger the 'close.facebox' document event: + * + * jQuery(document).trigger('close.facebox') + * + * Facebox also has a bunch of other hooks: + * + * loading.facebox + * beforeReveal.facebox + * reveal.facebox (aliased as 'afterReveal.facebox') + * init.facebox + * afterClose.facebox + * + * Simply bind a function to any of these hooks: + * + * $(document).bind('reveal.facebox', function() { ...stuff to do after the facebox and contents are revealed... }) + * + */ +(function($) { + $.facebox = function(data, klass) { + $.facebox.loading() + + if (data.ajax) fillFaceboxFromAjax(data.ajax, klass) + else if (data.image) fillFaceboxFromImage(data.image, klass) + else if (data.div) fillFaceboxFromHref(data.div, klass) + else if ($.isFunction(data)) data.call($) + else $.facebox.reveal(data, klass) + } + + /* + * Public, $.facebox methods + */ + + $.extend($.facebox, { + settings: { + opacity : 0.2, + overlay : true, + loadingImage : '/facebox/loading.gif', + closeImage : '/facebox/closelabel.png', + imageTypes : [ 'png', 'jpg', 'jpeg', 'gif' ], + faceboxHtml : '\ + ' + }, + + loading: function() { + init() + if ($('#facebox .loading').length == 1) return true + showOverlay() + + $('#facebox .content').empty() + $('#facebox .body').children().hide().end(). + append('
      ') + + $('#facebox').css({ + top: getPageScroll()[1] + (getPageHeight() / 10), + left: $(window).width() / 2 - 205 + }).show() + + $(document).bind('keydown.facebox', function(e) { + if (e.keyCode == 27) $.facebox.close() + return true + }) + $(document).trigger('loading.facebox') + }, + + reveal: function(data, klass) { + $(document).trigger('beforeReveal.facebox') + if (klass) $('#facebox .content').addClass(klass) + $('#facebox .content').append(data) + $('#facebox .loading').remove() + $('#facebox .body').children().fadeIn('normal') + $('#facebox').css('left', $(window).width() / 2 - ($('#facebox .popup').width() / 2)) + $(document).trigger('reveal.facebox').trigger('afterReveal.facebox') + }, + + close: function() { + $(document).trigger('close.facebox') + return false + } + }) + + /* + * Public, $.fn methods + */ + + $.fn.facebox = function(settings) { + if ($(this).length == 0) return + + init(settings) + + function clickHandler() { + $.facebox.loading(true) + + // support for rel="facebox.inline_popup" syntax, to add a class + // also supports deprecated "facebox[.inline_popup]" syntax + var klass = this.rel.match(/facebox\[?\.(\w+)\]?/) + if (klass) klass = klass[1] + + fillFaceboxFromHref(this.href, klass) + return false + } + + return this.bind('click.facebox', clickHandler) + } + + /* + * Private methods + */ + + // called one time to setup facebox on this page + function init(settings) { + if ($.facebox.settings.inited) return true + else $.facebox.settings.inited = true + + $(document).trigger('init.facebox') + makeCompatible() + + var imageTypes = $.facebox.settings.imageTypes.join('|') + $.facebox.settings.imageTypesRegexp = new RegExp('\.(' + imageTypes + ')$', 'i') + + if (settings) $.extend($.facebox.settings, settings) + $('body').append($.facebox.settings.faceboxHtml) + + var preload = [ new Image(), new Image() ] + preload[0].src = $.facebox.settings.closeImage + preload[1].src = $.facebox.settings.loadingImage + + $('#facebox').find('.b:first, .bl').each(function() { + preload.push(new Image()) + preload.slice(-1).src = $(this).css('background-image').replace(/url\((.+)\)/, '$1') + }) + + $('#facebox .close').click($.facebox.close) + $('#facebox .close_image').attr('src', $.facebox.settings.closeImage) + } + + // getPageScroll() by quirksmode.com + function getPageScroll() { + var xScroll, yScroll; + if (self.pageYOffset) { + yScroll = self.pageYOffset; + xScroll = self.pageXOffset; + } else if (document.documentElement && document.documentElement.scrollTop) { // Explorer 6 Strict + yScroll = document.documentElement.scrollTop; + xScroll = document.documentElement.scrollLeft; + } else if (document.body) {// all other Explorers + yScroll = document.body.scrollTop; + xScroll = document.body.scrollLeft; + } + return new Array(xScroll,yScroll) + } + + // Adapted from getPageSize() by quirksmode.com + function getPageHeight() { + var windowHeight + if (self.innerHeight) { // all except Explorer + windowHeight = self.innerHeight; + } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode + windowHeight = document.documentElement.clientHeight; + } else if (document.body) { // other Explorers + windowHeight = document.body.clientHeight; + } + return windowHeight + } + + // Backwards compatibility + function makeCompatible() { + var $s = $.facebox.settings + + $s.loadingImage = $s.loading_image || $s.loadingImage + $s.closeImage = $s.close_image || $s.closeImage + $s.imageTypes = $s.image_types || $s.imageTypes + $s.faceboxHtml = $s.facebox_html || $s.faceboxHtml + } + + // Figures out what you want to display and displays it + // formats are: + // div: #id + // image: blah.extension + // ajax: anything else + function fillFaceboxFromHref(href, klass) { + // div + if (href.match(/#/)) { + var url = window.location.href.split('#')[0] + var target = href.replace(url,'') + if (target == '#') return + $.facebox.reveal($(target).html(), klass) + + // image + } else if (href.match($.facebox.settings.imageTypesRegexp)) { + fillFaceboxFromImage(href, klass) + // ajax + } else { + fillFaceboxFromAjax(href, klass) + } + } + + function fillFaceboxFromImage(href, klass) { + var image = new Image() + image.onload = function() { + $.facebox.reveal('
      ', klass) + } + image.src = href + } + + function fillFaceboxFromAjax(href, klass) { + $.get(href, function(data) { $.facebox.reveal(data, klass) }) + } + + function skipOverlay() { + return $.facebox.settings.overlay == false || $.facebox.settings.opacity === null + } + + function showOverlay() { + if (skipOverlay()) return + + if ($('#facebox_overlay').length == 0) + $("body").append('
      ') + + $('#facebox_overlay').hide().addClass("facebox_overlayBG") + .css('opacity', $.facebox.settings.opacity) + .click(function() { $(document).trigger('close.facebox') }) + .fadeIn(200) + return false + } + + function hideOverlay() { + if (skipOverlay()) return + + $('#facebox_overlay').fadeOut(200, function(){ + $("#facebox_overlay").removeClass("facebox_overlayBG") + $("#facebox_overlay").addClass("facebox_hide") + $("#facebox_overlay").remove() + }) + + return false + } + + /* + * Bindings + */ + + $(document).bind('close.facebox', function() { + $(document).unbind('keydown.facebox') + $('#facebox').fadeOut(function() { + $('#facebox .content').removeClass().addClass('content') + $('#facebox .loading').remove() + $(document).trigger('afterClose.facebox') + }) + hideOverlay() + }) + +})(jQuery); diff --git a/public/javascripts/index.html b/public/javascripts/index.html new file mode 100755 index 0000000..e933af9 --- /dev/null +++ b/public/javascripts/index.html @@ -0,0 +1,8 @@ + + + + + +

      you shouldn't be here.. kicking you out!

      + + diff --git a/public/javascripts/irb.js b/public/javascripts/irb.js new file mode 100755 index 0000000..b4cb354 --- /dev/null +++ b/public/javascripts/irb.js @@ -0,0 +1,110 @@ +// +// Copyright (c) 2008 why the lucky stiff +// Copyright (c) 2010 Andrew McElroy +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +var allStretch; +var helpPages; +var chapPages; +var defaultPage; +var toot = window.location.search.substr(1) + +//the main function, call to the effect object +function dumpAlert(obj) { + props = []; + for ( var i in obj ) { + props.push( "" + i + ": " + obj[i] ); + } + alert( props ); +} +window.onload = function() { + defaultPage = $('#helpstone .stretcher').html(); + + window.irb = new MouseApp.Irb('#irb', { + rows: 13, + name: 'IRB', + greeting: "%+r Interactive ruby ready. %-r", + ps: '\033[1;31m>>\033[m', + user: 'guest', + host: 'tryruby', + // original: irbUrl: '/irb', + irbUrl: '/tryruby/run', + init: function () { + helpPages = $(".stretcher"); + chapPages = new Array(); + for (var i = 0; i < helpPages.length; i++ ) { + var cls = helpPages[i].className.split(' '); + for (var j = 0; j < cls.length; j++) { + if (cls[j] == 'chapmark') { + chapPages.push([i, helpPages[i]]); + break; + } + } + } + }, + loadTutorial: function (id, instruct) { + $.ajax({ + url: '/tutorials/' + id , + type: 'GET', + complete: function (r) { + $('#helpstone').html("
      " + defaultPage + "
      " + r.responseText); + window.irb.init(); + window.irb.showHelp(0); + } + }); + }, + showChapter: function (n) { + if (n >= chapPages.length) return; + this.setHelpPage(chapPages[n][0], chapPages[n][1]); + }, + showHelp: function (n) { + if (n >= helpPages.length) return; + this.setHelpPage(n, helpPages[n]); + }, + popup_goto: function (u) { + $('#lilBrowser').show().css({left: '40px', top: '40px'}); + $('#lbIframe').attr('src', u); + }, + popup_make: function (s) { + $('#lilBrowser').show().css({left: '40px', top: '40px'}); + $('#lbIframe').get(0).onIframeLoad = function () { + alert($(this).html()); + alert("$(this).html()"); + return s; + }; + //$('#lbIframe').attr({src: '/blank.html'}); + src = s.replace(/\\/g, "\\\\").replace(/\"/g, "\\\""); + $('#lbIframe').attr({src: "javascript:\"" + src + "\""}); + // $('# + }, + popup_close: function () { + $('#lilBrowser').hide(); + } + }); + + if ( !toot ) { + toot = 'intro'; + } + try { + window.irb.options.loadTutorial( toot, true ); + } catch (e) {} +} diff --git a/public/javascripts/jQuery.irb.js b/public/javascripts/jQuery.irb.js new file mode 100644 index 0000000..765858d --- /dev/null +++ b/public/javascripts/jQuery.irb.js @@ -0,0 +1,1641 @@ +//Try Ruby 1.5 (defacto version Number) +// March 14 2011 + +// large parts of this file are lifted from Try Haskell ( which lifted parts from try ruby without copyright notice >:-/ ) + +// Thus it is fair to include the following banner if/until there is no try haskell code left/ only code that originally existed in try ruby in the +//first place. + + // Try Haskell 1.0.1 + // Tue Feb 23 18:34:48 GMT 2010 + // + // Copyright 2010 Chris Done. All rights reserved. + // + // Redistribution and use in source and binary forms, with or without + // modification, are permitted provided that the following conditions + // are met: + // + // 1. Redistributions of source code must retain the above + // copyright notice, this list of conditions and the following + // disclaimer. + // 2. Redistributions in binary form must reproduce the above + // copyright notice, this list of conditions and the following + // disclaimer in the documentation and/or other materials + // provided with the distribution. + // + // THIS SOFTWARE IS PROVIDED BY CHRIS DONE ``AS IS'' AND ANY EXPRESS + // OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + // ARE DISCLAIMED. IN NO EVENT SHALL CHRIS DONE OR CONTRIBUTORS BE + // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + // OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + // DAMAGE. + // The views and conclusions contained in the software and + // documentation are those of the authors and should not be + // interpreted as representing official policies, either expressed or + // implied, of Chris Done. + // + // TESTED ON + // Internet Explorer 6 + // Opera 10.01 + // Chromium 4.0.237.0 (Ubuntu build 31094) + // Firefox 3.5.8 + + //IOS 4.3 (all devices) + +// Temporary fix +function opera() { + return navigator.userAgent.indexOf("Opera") == 0; +} + +function encodeHex(str) { + var result = ""; + for (var i = 0; i < str.length; i++) { + result += "%" + pad(toHex(str.charCodeAt(i) & 0xff), 2, '0'); + } + return result; +} + +//var handleJSON = function(a){ alert('Unassigned JSONP: ' + a); } +var hexv = { + "00": 0, + "01": 1, + "02": 2, + "03": 3, + "04": 4, + "05": 5, + "06": 6, + "07": 7, + "08": 8, + "09": 9, + "0A": 10, + "0B": 11, + "0C": 12, + "0D": 13, + "0E": 14, + "0F": 15, + "10": 16, + "11": 17, + "12": 18, + "13": 19, + "14": 20, + "15": 21, + "16": 22, + "17": 23, + "18": 24, + "19": 25, + "1A": 26, + "1B": 27, + "1C": 28, + "1D": 29, + "1E": 30, + "1F": 31, + "20": 32, + "21": 33, + "22": 34, + "23": 35, + "24": 36, + "25": 37, + "26": 38, + "27": 39, + "28": 40, + "29": 41, + "2A": 42, + "2B": 43, + "2C": 44, + "2D": 45, + "2E": 46, + "2F": 47, + "30": 48, + "31": 49, + "32": 50, + "33": 51, + "34": 52, + "35": 53, + "36": 54, + "37": 55, + "38": 56, + "39": 57, + "3A": 58, + "3B": 59, + "3C": 60, + "3D": 61, + "3E": 62, + "3F": 63, + "40": 64, + "41": 65, + "42": 66, + "43": 67, + "44": 68, + "45": 69, + "46": 70, + "47": 71, + "48": 72, + "49": 73, + "4A": 74, + "4B": 75, + "4C": 76, + "4D": 77, + "4E": 78, + "4F": 79, + "50": 80, + "51": 81, + "52": 82, + "53": 83, + "54": 84, + "55": 85, + "56": 86, + "57": 87, + "58": 88, + "59": 89, + "5A": 90, + "5B": 91, + "5C": 92, + "5D": 93, + "5E": 94, + "5F": 95, + "60": 96, + "61": 97, + "62": 98, + "63": 99, + "64": 100, + "65": 101, + "66": 102, + "67": 103, + "68": 104, + "69": 105, + "6A": 106, + "6B": 107, + "6C": 108, + "6D": 109, + "6E": 110, + "6F": 111, + "70": 112, + "71": 113, + "72": 114, + "73": 115, + "74": 116, + "75": 117, + "76": 118, + "77": 119, + "78": 120, + "79": 121, + "7A": 122, + "7B": 123, + "7C": 124, + "7D": 125, + "7E": 126, + "7F": 127, + "80": 128, + "81": 129, + "82": 130, + "83": 131, + "84": 132, + "85": 133, + "86": 134, + "87": 135, + "88": 136, + "89": 137, + "8A": 138, + "8B": 139, + "8C": 140, + "8D": 141, + "8E": 142, + "8F": 143, + "90": 144, + "91": 145, + "92": 146, + "93": 147, + "94": 148, + "95": 149, + "96": 150, + "97": 151, + "98": 152, + "99": 153, + "9A": 154, + "9B": 155, + "9C": 156, + "9D": 157, + "9E": 158, + "9F": 159, + "A0": 160, + "A1": 161, + "A2": 162, + "A3": 163, + "A4": 164, + "A5": 165, + "A6": 166, + "A7": 167, + "A8": 168, + "A9": 169, + "AA": 170, + "AB": 171, + "AC": 172, + "AD": 173, + "AE": 174, + "AF": 175, + "B0": 176, + "B1": 177, + "B2": 178, + "B3": 179, + "B4": 180, + "B5": 181, + "B6": 182, + "B7": 183, + "B8": 184, + "B9": 185, + "BA": 186, + "BB": 187, + "BC": 188, + "BD": 189, + "BE": 190, + "BF": 191, + "C0": 192, + "C1": 193, + "C2": 194, + "C3": 195, + "C4": 196, + "C5": 197, + "C6": 198, + "C7": 199, + "C8": 200, + "C9": 201, + "CA": 202, + "CB": 203, + "CC": 204, + "CD": 205, + "CE": 206, + "CF": 207, + "D0": 208, + "D1": 209, + "D2": 210, + "D3": 211, + "D4": 212, + "D5": 213, + "D6": 214, + "D7": 215, + "D8": 216, + "D9": 217, + "DA": 218, + "DB": 219, + "DC": 220, + "DD": 221, + "DE": 222, + "DF": 223, + "E0": 224, + "E1": 225, + "E2": 226, + "E3": 227, + "E4": 228, + "E5": 229, + "E6": 230, + "E7": 231, + "E8": 232, + "E9": 233, + "EA": 234, + "EB": 235, + "EC": 236, + "ED": 237, + "EE": 238, + "EF": 239, + "F0": 240, + "F1": 241, + "F2": 242, + "F3": 243, + "F4": 244, + "F5": 245, + "F6": 246, + "F7": 247, + "F8": 248, + "F9": 249, + "FA": 250, + "FB": 251, + "FC": 252, + "FD": 253, + "FE": 254, + "FF": 255 +}; + +function pad(str, len, pad) { + var result = str; + for (var i = str.length; i < len; i++) { + result = pad + result; + } + return result; +} + +var digitArray = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'); + +function toHex(n) { + var result = '' + var start = true; + for (var i = 32; i > 0;) { + i -= 4; + var digit = (n >> i) & 0xf; + if (!start || digit != 0) { + start = false; + result += digitArray[digit]; + } + } + return (result == '' ? '0': result); +} + + (function($) { + var raphaelPaper; + var raphaelObjs; + var tutorialGuide; + + // I don't like this at all... I intend to make this pull via ajax from a key value data store. + var pages = + [ + //////////////////////////////////////////////////////////////////////// + // Lesson 1 + // Simple addition + { + lesson: 1, + title: 'Basics; numbers, strings, etc.', + guide: + '

      ' + rmsg(['Learning By Numbers', 'Music is Math', 'Back to Basics']) + + '

      ' + + "

      To kick off let's try some maths out. Up there you can" + + " type in Haskell expressions. Try this out: 5 + 7

      " + }, + { + guide: function(result) { + if (!result) result = { + expr: '5+7', + result: 12 + }; + var complied = result.expr.replace(/ /g, '') == "5+7"; + var who = complied ? 'we': 'you'; + return '

      ' + rmsg(['Your first Haskell expression', + "First Time's a Charm"]) + '

      ' + + '

      Well done, you typed it perfect! You got back the number' + + ' ' + result.result + '. Just what ' + who + ' wanted. ' + + "

      Let's try something completely different." + + " Type in your name like this:" + + ' "chris"

      ' + }, + trigger: function(result) { + return result.type == "(Num t) => t" || + result.type == "Integer" || + result.type == "Int"; + } + }, + // Strings & types + { + guide: function(result) { + if (!result) result = { + expr: '"chris"', + result: "\"chris\"" + }; + var n = unString(result.result); + if (n) n = ", " + n; + n += "!"; + return '

      ' + rmsg(['Types of values', "What's in a name?"]) + + '

      ' + + '

      Hi there' + htmlEncode(n) + + (n != "!" ? " That's a pretty name. Honest.": "") + + " You're getting the hang of this!

      " + + "

      Note: You can chat to Haskell programmers while learning here, enter chat to start it." + + " You will join the official IRC channel of the Haskell community!

      " + + "

      Each time, you're getting back the value of the expression. So " + + "far, just a number and a list of characters.

      " + + "

      You can have lists of other stuff, too. Let's see your " + + " lottery numbers: [42,13,22]

      " + }, + trigger: function(result) { + return result.type == "[Char]" + || result.type == "String"; + } + }, + // Overview of lesson 1 + { + guide: function(result) { + if (!result) result = { + result: "[42,13,22]" + }; + return '

      ' + rmsg(["Lesson 1 done already!"]) + + '

      ' + + "

      Great, you made a list of numbers! If you win we'll split" + + " the winnings, right?

      " + + "

      Let's see what you've learned so far:

      " + + "
        " + + "
      1. How to write maths and lists of things.
      2. " + + "
      " + + "

      You can do stuff with lists. Maybe you want the lottery " + + "numbers sorted in the right order, try this: " + + "sort " + result.result + "

      " + }, + trigger: function(result) { + return result.expr.match(/^[ ]*\[[0-9, ]+\][ ]*$/) && + result.type == "(Num t) => [t]"; + } + }, + /////////////////////////////////////////////////////////////////////// + // Lesson 2 - Functions + // Functions on lists + { + lesson: 2, + title: 'Simple Functions', + guide: function(result) { + if (!result) result = { + result: "[13,23,30]" + }; + return '

      ' + rmsg(["We put the funk in function"]) + + '

      ' + + "

      Congratulations, you just used a function." + + " They're how you get things done in Haskell." + + "

      As you might've guessed, we got back " + + htmlEncode(result.result) + + ".

      Ever wanted an evil twin nemesis? Me too. " + + "Luckily, you can sort lists of characters, or " + + "strings" + + ", in the same way as numbers! sort \"chris\"

      " + }, + trigger: function(result) { + return result.expr.match(/sort/) && + result.type == "(Num t, Ord t) => [t]"; + } + }, + // Tuples + { + guide: function(result) { + if (!result) result = { + result: "\"chirs\"" + }; + nemesis = htmlEncode(unString(result.result)); + return '

      ' + + rmsg(["Tuples, because sometimes one value ain't enough!"]) + + '

      ' + + "

      Watch out for " + nemesis + "! You should keep their credentials for the police.

      " + + "

      My nemesis is 28 years of age: " + + "(28,\"chirs\")

      " + }, + trigger: function(result) { + return result.expr.match(/sort/) && + result.type == "[Char]"; + } + }, + // Functions on tuples + { + guide: function(result) { + if (!result) result = { + result: "(28,\"chirs\")" + }; + var age = result.result.match(/^\(([0-9]+)+/); + var villain = htmlEncode(result.result.replace(/\\"/g, '"')); + return '

      ' + + rmsg(["We'll keep them safe, don't worry about it."]) + + '

      ' + + "

      Is " + (age ? age[1] : "that") + " a normal age for a " + + "super-villain?

      " + + "

      You just wrote a tuple. It's a way to keep a bunch of values together in Haskell. " + + "You can put as many as you like in there:

      " + + "
      • (1,\"hats\",23/35)
      • (\"Shaggy\",\"Daphnie\",\"Velma\")
      " + + "

      Actually, let's say our villain is " + + "" + villain + "" + + ", how do you get their age?

      " + + "fst " + villain + "" + }, + trigger: function(result) { + return result.expr.match(/\([0-9]+,[ ]*"[^"]+"\)/) && + result.type == "(Num t) => (t, [Char])"; + } + }, + // Summary of lesson 2 + { + guide: function(result) { + return '

      ' + + rmsg(["Lesson 2 done! Wow, great job!", + "Lesson 2 completo!"]) + + '

      ' + + + "

      Good job! You got the age back from the tuple! Didn't " + + " even break a sweat, did you? The fst function " + + "just gets the first value. It's called \"fst\" because " + + "it's used a lot in Haskell so it really needs to be short!

      " + + + "

      Time to take a rest and see what you learned:

      " + + "
        " + + "
      1. Functions can be used on lists of any type.
      2. " + + "
      3. We can stuff values into tuples.
      4. " + + "
      5. Getting the values back from tuples is easy.
      6. " + + "
      " + + + "

      Now let's say you want " + + " to use a value more than once, how would you do it? " + + "To make our lives easier, we can say:

      " + + + "let x = 4 in x * x" + }, + trigger: function(result) { + return result.expr.match(/fst/) && + result.type == "(Num t) => t"; + } + }, + { + guide: function(result) { + return "

      Let them eat cake

      " + + + "

      You just bound a variable. " + + "That is, you bound x to the expression 4, " + + " and then you can write x in some code (the body) and " + + " it will mean the same as if you'd written 4.

      " + + + "

      It's like this: let var = expression in body

      " + + + "The in part just separates the expression from the body.

      " + + + "

      For example try: " + + "let x = 8 * 10 in x + x

      " + + + "

      So if we wanted to get the age of our villain, we could do:

      " + + + "let villain = (28,\"chirs\") in fst villain" + + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]+x[ ]*=[ ]*[0-9]+[ ]*in[ ]*x[ ]*\*[ ]*x/) && + result.type == "(Num t) => t"; + } + }, + { + guide: function(result) { + return "

      Basics over, let's go!

      " + + "

      Next, let's take a short detour to learn about " + + "syntactic sugar. " + + "Try typing this out:

      " + + "

      'a' : []

      " + + "

      Or skip to lesson4 to learn about functions," + + " the meat of Haskell!"; + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]+villain[ ]*=[ ]*\([0-9]+,[ ]*"[^"]+"\)[ ]*in[ ]+fst[ ]+villain[ ]*/) && + result.type == "(Num t) => t"; + } + }, + // Lesson 3: Syntactic sugar + { + lesson: 3, + title: 'Syntactic Sugar', + guide: function(result) { + return '

      ' + + rmsg(["You constructed a list!"]) + + '

      ' + + "

      Well done, that was tricky syntax. You used the (:) " + + "function. It takes two values, some value and a list, and " + + " constructs a new list" + + " out of them. We call it 'cons' for short.

      " + + "

      'a' is " + + "the character 'a', [] is an empty list. So " + + "tacking 'a' at the start of an empty list just " + + "makes a list ['a']!

      " + + "

      But thankfully we don't have to type out " + + "'a' : 'b' : [] every time to we want to make a " + + "list of characters; we can use " + + "syntactic sugar and just write" + + " ['a','b']. Don't believe me, check this!

      " + + "'a' : 'b' : [] == ['a','b']" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*'a'[ ]*:[ ]*\[\][ ]*/) && + result.type == "[Char]"; + } + }, + // Booleans and string syntactic sugar + { + guide: function(result) { + return '

      ' + + rmsg(["You're on fire!"]) + + '

      ' + + "

      You're handling this syntax really well, nice!

      " + + "

      You just got a boolean value back, and it said " + + "True. That means they're equal!

      " + + "

      One final demonstration on syntactic sugar for now:

      " + + "['a','b','c'] == \"abc\"" + }, + trigger: function(result) { + return result.type == "Bool" && + result.expr.replace(/[^':\[\]\=,]/g, '') == "'':'':[]==['','']"; + } + }, + // Summary of syntactic sugar section + { + guide: function(result) { + return '

      ' + + rmsg(["Lesson 3 over! Syntactic sugar is sweet"]) + + '

      ' + + "

      Let's have a gander at what you learned:

      " + + "
        " + + "
      1. In 'a' : [], : is really just " + + " another function, just clever looking.
      2. " + + "
      3. Pretty functions like this are written like (:) when " + + " you talk about them.
      4. " + + "
      5. A list of characters ['a','b'] can just be written " + + "\"ab\". Much easier!
      6. " + + "
      " + + "

      Phew! You're getting pretty deep! Your arch nemesis, " + + nemesis + ", is gonna try to steal your " + rmsg(['mojo', + 'pizza']) + + "! Let's learn a bit more about functions and passing " + + "them around. Try this:

      map (+1) [1..5]

      "; + }, + trigger: function(result) { + return result.expr.replace(/[^\]\[',=\"]?/g, '') == "['','','']==\"\"" && + result.type == "Bool"; + } + }, + { + lesson: 4, + title: 'Functions, reloaded; passing, defining, etc.', + guide: function() { + var title = + rmsg(["Functions [of a Geisha]", + "Functions, functors, functoids, funky", + "Functions: Expanded fo' real"]); + return "

      " + title + "

      " + + + "

      Here's where the magic begins!

      " + + + "

      You just passed the (+1) " + + "function to the map function.

      " + + + "

      You can try other things like (remember: click to insert them):

      " + + + "
        " + + "
      • map (*99) [1..10]
      • " + + "
      • map (/5) [13,24,52,42]
      • " + + "
      • filter (>5) [62,3,25,7,1,9]
      • " + + "
      " + + + "

      Note that a tuple is different to a list because you can do this:

      " + + "(1,\"George\")" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*map[ ]+\(\+1\)[ ]*\[1..5\][ ]*$/) && + result.type == "(Num a, Enum a) => [a]"; + } + }, + { + guide: function(result) { + return "

      Lists and Tuples

      " + + + "

      You can only " + + " have a list of numbers or a list of characters, whereas in a tuple you can throw anything in!

      " + + + "

      We've also seen that you can make a new list with (:) that joins two values together, like:

      " + + "

      1 : [2,3]

      " + + + "

      But we can't do this with tuples! You can only write a tuple and then look at what's inside. You can't make new ones on the fly like a list." + + + "

      Let's write our own functions! It's really easy. How about something simple:

      " + + "let square x = x * x in square " + rmsg([52, 10, 3]) + "" + + }, + trigger: function(result) { + return result.expr.match(/^[ ]*\(1,"[^"]+"\)[ ]*$/) && + result.type == "(Num t) => (t, [Char])"; + } + }, + { + guide: function(result) { + return "

      Let there be functions

      " + + "

      Nice one! I think you're getting used to the let syntax.

      " + + "

      You defined a function. You can read it as, as for a given " + + "parameter called x, square of " + + "x is x * x." + + "

      Some others you can try are:

      " + + "
      • let add1 x = x + 1 in add1 5
      • " + + "
      • let second x = snd x in second (3,4)
      • " + + "
      " + + "

      Let's go crazy and use our square function with map:

      " + + "let square x = x * x in map square [1..10]" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]*square[ ]+x[ ]*=[ ]*x[ ]*\*[ ]*x[ ]*in[ ]*square[ ]+[0-9]+/) && + result.type == "(Num t) => t"; + } + }, + { + guide: function(result) { + if (!result || !result.value) result = { + value: "[1,4,9,16,25,36,49,64,81,100]" + }; + return "

      Let there be functions

      " + + + "

      That's so cool! You described a simple function square and then " + + "you just passed it to another function (map) and got back " + + htmlEncode(result.value) + ", exactly what you expected!

      " + + + "

      Haskell is pretty good at composing things together like this. " + + "Some other things you can try are:

      " + + + "
        " + + "
      • let add1 x = x + 1 in map add1 [1,5,7]
      • " + + "
      • let take5s = filter (==5) in take5s [1,5,2,5,3,5]
      • " + + "
      • let take5s = filter (==5) in map take5s [[1,5],[5],[1,1]]
      • " + + "
      " + + + "

      Did you get back what you expected?

      " + + + "

      One more example for text; how do you upcase a letter?

      " + + + "

      toUpper 'a'

      " + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]+square[ ]+x[ ]*=[ ]*x[ ]*\*[ ]*x[ ]*in[ ]+map[ ]+square[ ]*\[1..10\][ ]*$/) && + result.type == "(Num a, Enum a) => [a]"; + } + }, + { + guide: function(result) { + return "

      Exercise time!

      " + + + "

      Easy! Remember: characters are written like 'a' and " + + "strings (lists of characters) are written like \"a\"." + + + "

      I need you to use toUpper capitalise my whole name, " + + "\"Chris\". Give it a try." + + " You can do it, I believe in you!

      " + + + '

      Spoiler: map toUpper "Chris"

      ' + }, + trigger: function(result) { + return result.expr.match(/^toUpper 'a'$/) && + result.type == "Char"; + } + }, + { + guide: function(result) { + return "

      Lesson 4 complete!

      " + + + "

      Brilliant! You're making excellent progress! " + + "You just passed toUpper to map. No problem.

      " + + + "

      Let's go over what you've learned in this lesson:

      " + + + "
        " + + "
      1. Functions like map take other functions as parameters.
      2. " + + "
      3. Functions like (+1), (>5) and " + + "square can be passed to other functions.
      4. " + + "
      5. Defining functions is just a case of writing what " + + "to do with the parameters.
      6. " + "
      " + + + "

      Let's check out pattern matching; a way to " + + "get values from other values using patterns. Try this:

      " + + "

      let (a,b) = (10,12) in a * 2

      " + + + "

      Or you can skip this section and go to straight to lesson6; types!

      " + }, + trigger: function(result) { + return result.type == "[Char]" && + result.expr.match(/^map[ ]+toUpper/); + } + }, + { + lesson: 5, + title: 'Pattern Matching', + guide: function(result) { + var title = + rmsg(["And therefore, patterns emerge in nature.", + "And Then Patterns", + "Pattern matching!"]) + return "

      " + title + "

      " + + + "

      Jolly good show!

      " + + "

      So you had a value (10,12) and matched " + + "it against a pattern (a,b), then you were able" + + " to do stuff with the a and b!" + + + "

      Note: Pattern matching (a,b) against " + + "(1,2) to get the a is the same as" + + " doing fst (1,2), like you did in step7!

      " + + + "

      A pattern always matches the way the " + + "value was originally constructed. Remember that \"abc\" is " + + "syntactic sugar for 'a' : 'b' : 'c' : [].

      " + + + "

      So you can get the characters from a string with patterns:

      " + + + "let (a:b:c:[]) = \"xyz\" in a" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]+\(a,b\)[ ]+=[ ]+\(10,12\)[ ]+in[ ]+a[ ]*\*[ ]*2[ ]*$/) && + result.type == "(Num t) => t"; + } + }, + { + guide: function(result) { + return "

      " + rmsg(["Ignorance is bliss", "Ignoring values"]) + "

      " + + + "

      You're getting into tricky syntax, huh? I know you can handle it!

      " + + + "

      If you just want some of the values, you can ignore the others with _ (underscore) like this:

      " + + + "

      let (a:_:_:_) = \"xyz\" in a

      " + + + "

      In fact, (a:b:c:d) is short-hand for " + + "(a:(b:(c:d))), so you can just ignore the rest in one go:

      " + + + "let (a:_) = \"xyz\" in a" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]+\(a:b:c:\[\]\)[ ]*=[ ]*\"xyz\"[ ]*in[ ]+a[ ]*$/) && + result.type == "Char"; + } + }, + { + guide: function(result) { + return "

      " + rmsg(["Exercise!", "Show me the money!"]) + "

      " + + + "

      Try to get the 'a' value from this value using pattern matching:

      " + + "

      (10,\"abc\")

      " + + + "

      Spoiler: let (_,(a:_)) = (10,\"abc\") in a

      " + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]*\(a:_\)[ ]*=[ ]*"xyz"[ ]*in[ ]*a[ ]*$/) && + result.type == "Char"; + } + }, + { + guide: function(result) { + return "

      " + rmsg(["Well done!", "Brilliant!", "Perfetto!"]) + "

      " + + + "

      Wizard! I think you've got pattern-matching down.

      " + + + "

      If you're still a bit unsure, here are some other things you can try:

      " + + + "
        " + + "
      • let _:_:c:_ = \"abcd\" in c
      • " + + "
      • let [a,b,c] = \"cat\" in (a,b,c)
      • " + + "
      " + + + "

      You can also grab a whole value and pattern match on it (have your cake and eat it too):

      " + + + "let abc@(a,b,c) = (10,20,30) in (abc,a,b,c)" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]*\(_,\(?a:_\)?\)[ ]*=[ ]*\(10,\"abc\"\)[ ]*in[ ]*a[ ]*$/) && + result.type == "Char"; + } + }, + { + guide: function(result) { + return "

      " + rmsg(["And that's the end of that chapter"]) + "

      " + + + "

      That was easy, right?

      " + + + "

      Let's go over what you've learned in this lesson:

      " + + + "
        " + + "
      1. Values are pattern matched, or deconstructed, by writing however they were constructed.
      2. " + + "
      3. Patterns let you use the values that you match.
      4. " + + "
      5. You can ignore whichever values you want.
      6. " + + "
      7. You can pattern match and keep hold of the original value too.
      8. " + + "
      " + + + "

      Now we get to the Deep Ones. Types!

      " + + + "

      Consider the following value: 'a'

      " + + }, + trigger: function(result) { + return result.type == "(Num t, Num t1, Num t2) => ((t, t1, t2), t, t1, t2)"; + } + }, + { + lesson: 6, + title: 'Types', + guide: function(result) { + showTypes = true; + return "

      " + rmsg(["Types", "What's in a Type?", "Types & Values"]) + "

      " + + "

      What's this? Something new!

      " + + + "

      In Haskell there are types of values. Every value belongs to a type. To demonstrate this fact, I've sneakily enabled types to be " + + "shown of every value in the console from now on.

      " + + + "

      The type of the value 'a' is Char (short for 'character', but you guessed that, right?).

      " + + + "

      You've seen the type of a character, now what about" + + " a list of characters?

      " + + "\"Spartacus\"" + }, + trigger: function(result) { + return result.type == 'Char'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

      " + rmsg(["Lists of stuff, types"]) + "

      " + + + "

      I'm Spartacus!

      " + + + "

      Okay, so a list of characters has type [Char].

      " + + + "

      Notice that when we write a :: X it means the value a has type X. It's just a short-hand called a signature.

      " + + + "

      If you just want the type of a value, without actually evaluating it, you can just type:

      " + + ":t toUpper" + }, + trigger: function(result) { + return result.expr.match(/"[^"]+"/) && + result.type == '[Char]'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

      " + rmsg(["Function types"]) + "

      " + + + "

      Woah! Hold your blinkin' 'orses! The type of toUpper reads: Char -> Char

      " + + + "

      It's pretty easy; a -> b means function from a to b. " + + "So

      toUpper :: Char -> Char means: for a" + + " given character (Char value) a, toUpper a has type Char.

      " + + + "

      Some other things you can try are:

      " + + + "
      • :t words
      • " + + "
      • :t unwords
      • " + + "
      • :t True
      • " + + "
      • :t not
      • " + + "
      " + + + "

      The words function is pretty handy. Want to get a list of words from a sentence?

      " + + "words \"There's jam in my pants.\"" + }, + trigger: function(result) { + return result.type == 'Char -> Char'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

      " + rmsg(["Mid-way review"]) + "

      " + + + "

      The type of words was String -> [String]. You got a list of strings back! Just what you expected, right?

      " + + + "

      Let's take a rest in the middle of this lesson and go over what we've learned:

      " + + + "
        " + + "
      1. All values in Haskell have a type. We describe the types of values with signatures, like True :: Bool.
      2. " + + "
      3. Functions are values too, and they have types, notated a -> b.
      4. " + + "
      5. Functions can be defined for any type to any other type.
      6. " + + "
      7. Humble reader has a thing for jammy pants.
      8. " + + "
      " + + + "

      But what if you have a type that can contain values of any type, like a tuple?

      " + + ":t fst" + + }, + trigger: function(result) { + return result.expr.match(/^[ ]*words[ ]*\"[^"]+\"[ ]*$/) && + result.type == '[String]'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

      " + rmsg(["Polymorphic functions"]) + "

      " + + + "

      Remember this one? I know you do! fst (1,2) is 1, right?

      " + + "

      We read its type

      " + + "

      fst :: (a, b) -> a

      " + + "

      as: for all types a and b, the fst has type (a,b) to a. So the fst " + + "function works on a pair of values of any types! We call such a function polymorphic." + + "

      " + + "

      Remember the drop function? Maybe you don't. I don't! Let's check out its type:

      " + + "

      :t drop

      " + }, + trigger: function(result) { + return result.type == '(a, b) -> a'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

      " + rmsg(["Multi parameter functions"]) + "

      " + + + "

      So the drop function has type

      Int -> [a] -> [a].

      " + + + "

      This is something new. You've got two arrows! Relax. You can read

      " + + "

      a -> b -> c as a -> (b -> c)

      " + + + "

      In other words, drop is a function from integers (Int values) to functions of lists to lists ([a] -> [a] values). Drop is a function to another function.

      " + + + "

      Check for yourself! :t drop 3

      " + }, + trigger: function(result) { + return result.type == 'Int -> [a] -> [a]'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

      " + rmsg(["Partial application"]) + "

      " + + + "

      You've got a function of type [a] -> [a]! The drop function is considered a multi-parameter function. Remember the map function? Its parameters were a function and a list. Just another multi-parameter function.

      " + + + "

      You can add another parameter and, hey presto, you get a list!

      " + + + "drop 3 \"hello!\"" + + }, + trigger: function(result) { + return result.type == '[a] -> [a]'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

      " + rmsg(["Higher order functions"]) + "

      " + + + "

      'Lo bob! You've already used the map function loads. I wonder if you can guess its type?

      " + + + "

      map :: (a -> b) -> [a] -> [b] (spoiler)

      " + + + "

      It's okay to peek! Have a go at guessing these: filter, take

      " + + + "

      Tip: You can use parantheses to use more than one function. You want to double all the numbers over five? Psch!

      " + + "map (*2) (filter (>5) [10,2,16,9,4])" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*drop[ ]*[0-9]+[ ]*"[^"]+"[ ]*$/) && + result.type == '[Char]'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

      " + rmsg(["Phew! Rest time!"]) + "

      " + + + "

      Wow! You're doing so great! Have a look at what you know now!

      " + + + "
        " + + "
      1. Function parameters can be polymorphic; any type!
      2. " + + "
      3. Functions can have multiple parameters by returning more functions.
      4. " + + "
      5. You can wrap expressions in parentheses and apply functions to them as a whole value.
      6. " + + "
      " + + + "

      You're really making great progress. Don't hesitate to sit and play in the console between chapters to get a good feel of it!

      " + + + "

      Stay tuned for more chapters on type classes and the meaning of :t 1, :t (*), etc.

      " + + learnMore + }, + trigger: function(result) { + return result.type == '(Num a, Ord a) => [a]'; + } + } + ]; + // + // var webchat; + // + // function runWebchat() { + // if (!webchat) { + // // Create webchat frame + // var webchat = + // $(''); + // webchat.attr('width', 635); + // webchat.attr('height', 500); + // webchat.css('float', 'left'); + // webchat.css('webkit-border-radius', '3px'); + // webchat.css('moz-border-radius', '3px'); + // webchat.css('border-radius', '3px'); + // webchat.css('border', '5px solid #eeeeee'); + // + // // Extend page wrap to fit console and chat + // $('.page-wrap').css({ + // width: '1250px' + // }); + // $('.primary-content').css('margin-left', 0); + // $('.page-wrap').append(webchat.css('margin-left', '5px')); + // } + // } + + var pageTrigger = -1; + var notices = []; + var controller; + // Console controller + var learnMore; + + //////////////////////////////////////////////////////////////////////// + // Unshow a string + function unString(str) { + return str.replace(/^"(.*)"$/, "$1").replace(/\\"/, '"'); + } + + //////////////////////////////////////////////////////////////////////// + // Random message from a list of messages + function rmsg(choices) { + return choices[Math.floor((Math.random() * 100) % choices.length)]; + } + + // Simple HTML encoding + // Simply replace '<', '>' and '&' + // TODO: Use jQuery's .html() trick, or grab a proper, fast + // HTML encoder. + function htmlEncode(text, shy) { + return ( + ('' + text).replace(/&/g, '&') + .replace(/'); + handleJSON = function(r) { + script.remove(); + func(r); + }; + script.attr('src', url); + $('body').append(script); + } + + + var console = $('.console'); + controller = console.console({ + promptLabel: '> ', + continuedPromptLabel: ' .. ', /*not quiet right but good enough*/ + cancelHandle: function() { + controller.commandRef.ignore = true; + controller.finishCommand(); + controller.report(); + }, + + commandHandle: function(line, report) { + + controller.ajaxloader = $('

      Loading...

      '); + var commandRef = {}; + controller.currentLine = line; + controller.commandRef = commandRef; + controller.report = report; + if (tellAboutRet) tellAboutRet.fadeOut(function() { + $(this).remove(); + }); + + if (libTrigger(line, report)) return; + controller.inner.append(controller.ajaxloader); + controller.scrollToBottom(); + + jsonp("http://localhost:3030/tryruby/run/?cmd=" + encodeHex(line), + function(resp) { + if (commandRef.ignore) { + return; + } + controller.finishCommand(); + var result = resp; + if (pageTrigger > -1 && result.expr) { + triggerTutorialPage(pageTrigger, result); + } + if (result.type) { + if (pageTrigger == 24) showTypes = false; + handleSuccess(report, result); + } else if (result.error) { + report( + [{ + msg: result.error, + className: "jquery-console-message-error jquery-console-message-compile-error" + }] + ); + notice('compile-error', + "A compile-time error! " + + "It just means the expression wasn't quite right. " + + "Try again.", + 'prompt'); + } else if (result.exception) { + var err = limitsError(result.exception); + report( + [{ + msg: err, + className: "jquery-console-message-error jquery-console-message-exception" + }] + ); + if (err == result.exception) { + notice('compile-error', + "A run-time error! The expression was right but the" + + " result didn't make sense. Check your expression and try again.", + 'prompt'); + } + } else if (result.internal) { + report( + [{ + msg: limitsError(result.internal), + className: "jquery-console-message-error jquery-console-message-internal" + }] + ); + } else if (result.bind) { + report(); + } else if (result.result) { + if (result.expr.match(/^:modules/)) { + report( + [{ + msg: result.result.replace(/[\["\]]/g, '') + .replace(/,/g, ', '), + className: "jquery-console-message-type" + }]); + } + } + }); + + }, + + charInsertTrigger: function() { + var t = notice('tellaboutreturn', + "Hit Return when you're " + + "finished typing your expression."); + if (t) tellAboutRet = t; + return true; + }, + autofocus: true, + promptHistory: true, + historyPreserveColumn: true, + welcomeMessage: 'Interactive ruby ready' + }); + + controller.finishCommand = function() { + controller.ajaxloader.remove(); + $('.jquery-console-prompt :last').each(function() { + lastLine = controller.currentLine; + if (!$(this).hasClass('prompt-done')) { + $(this).addClass('prompt-done'); + $(this).click(function() { + controller.promptText(controller.currentLine); + }); + } + }); + } + + makeGuidSamplesClickable(); + + var match = window.location.href.match(/#([0-9]+)$/); + if (match) { + pageTrigger = match[1] - 1; + setTutorialPage(undefined, match[1] - 1); + } + + var match = window.location.href.match(/\?input=([^&]+)/); + if (match) { + controller.promptText(urlDecode(match[1])); + controller.inner.click(); + controller.typer.consoleControl(13); + } + }); + + function urlDecode(encodedString) { + var output = encodedString; + var binVal, + thisString; + var myregexp = /(%[^%]{2})/; + while ((match = myregexp.exec(output)) != null + && match.length > 1 + && match[1] != '') { + binVal = parseInt(match[1].substr(1), 16); + thisString = String.fromCharCode(binVal); + output = output.replace(match[1], thisString); + } + return output; + } + + function makeGuidSamplesClickable() { + $('.chapmark code').each(function() { + $(this).css('cursor', 'pointer'); + $(this).attr('title', 'Click me to insert "' + + $(this).text() + '" into the console.'); + $(this).click(function() { + controller.promptText($(this).text()); + controller.inner.click(); + }); + }); + } + + String.prototype.trim = function() { + return this.replace(/^[\t ]*(.*)[\t ]*$/, '$1'); + }; + + //////////////////////////////////////////////////////////////////////// + // Trigger console commands + function libTrigger(line, report) { + switch (line.trim()) { + case 'help': + { + setTutorialPage(undefined, 0); + report(); + pageTrigger = 0; + return true; + } + case 'back': + { + if (pageTrigger > 0) { + setTutorialPage(undefined, pageTrigger - 1); + pageTrigger--; + report(); + return true; + } + break; + } + case 'lessons': + { + var lessons = $('
        '); + for (var i = 0; i < pages.length; i++) { + if (pages[i].lesson) { + lessons.append($('
      1. '). + html('lesson' + pages[i].lesson + ' - ' + + pages[i].title)); + } + } + var lessonsList = '

        Lessons

        ' + lessons.html(); + tutorialGuide.animate({ + opacity: 0, + height: 0 + }, + 'fast', + function() { + tutorialGuide.html(lessonsList); + tutorialGuide.css({ + height: 'auto' + }); + tutorialGuide.animate({ + opacity: 1 + }, + 'fast'); + makeGuidSamplesClickable(); + }); + report(); + return true; + } + default: + { + if (line.trim() == 'chat') { + notice('irc', + 'Enter your nick on the right hand side and hit Connect!', + 'prompt'); + report(); + runWebchat(); + return true; + } + + var m = line.trim().match(/^link(.*)/); + if (m) { + var data; + if (m[1]) data = m[1].trim(); + else if (lastLine) data = lastLine; + if (data) { + var addr = '?input=' + encodeHex(data); + report([{ + msg: '', + className: 'latest-link' + }]); + var link = $(''). + text('link for ' + data).click(function() { + window.location.href = $(this).attr('href'); + return false; + }); + $('.latest-link').html(link).removeClass('latest-link'); + return true; + } + } + + var m = line.trim().match(/^step([0-9]+)/); + if (m) { + if ((m[1] * 1) <= pages.length) { + setTutorialPage(undefined, m[1] - 1); + report(); + pageTrigger = m[1] - 1; + return true; + } + } + var m = line.trim().match(/^help ([0-9]+)/); + if (m) { + for (var i = 0; i < pages.length; i++) { + if (pages[i].lesson == m[1] * 1) { + setTutorialPage(undefined, i); + report(); + pageTrigger = i; + return true; + } + } + } + } + }; + }; + + //////////////////////////////////////////////////////////////////////// + // Change the tutorial page + function setTutorialPage(result, n) { + if (pages[n]) { + window.location.href = '#' + (1 * n + 1); + tutorialGuide.find('#helpstone').remove(); + tutorialGuide.animate({ + opacity: 0, + height: 0 + }, + 'fast', + function() { + if (typeof(pages[n].guide) == 'function') + tutorialGuide.html(pages[n].guide(result)); + else + tutorialGuide.html(pages[n].guide); + var back = ''; + if (pageTrigger > 0) + back = 'You\'re at step' + (n + 1) + + '. Type back to go back.'; + else + back = 'You\'re at step' + (n + 1) + '. Type step' + (n + 1) + + ' to return here.'; + if (true) tutorialGuide + .append('
        ' + back + '
        ') + .append('
        Lesson: ' + + searchLessonBack(n) + + '
        '); + tutorialGuide.css({ + height: 'auto' + }); + tutorialGuide.animate({ + opacity: 1 + }, + 'fast'); + makeGuidSamplesClickable(); + }); + } + }; + + function searchLessonBack(page) { + for (var i = page; i >= 0; i--) { + if (pages[i].lesson) return pages[i].lesson; + } + return "1"; + } + + //////////////////////////////////////////////////////////////////////// + // Trigger a page according to a result + function triggerTutorialPage(n, result) { + n++; + if (pages[n] && (typeof(pages[n].trigger) == 'function') + && pages[n].trigger(result)) { + pageTrigger++; + setTutorialPage(result, n); + } + }; + + //////////////////////////////////////////////////////////////////////// + // Trigger various libraries after JSONRPC returned + function handleSuccess(report, result) { + if (result.type.match(/^Graphics\.Raphael\.Raphael[\r\n ]/)) { + runRaphael(result.result); + report(); + } + if (result.type.match(/standard/)) { + var hashrocket = ''; + var msg_value = ' => '; + if (result.result == null) { + hashrocket = ' => ' + msg_value = ''; + } + report( + [{ + msg: msg_value + result.output + hashrocket + result.result, + className: "jquery-console-message-value" + }]); + } + + if (result.type.match(/error/)) { + + report( + [{ + msg: result.error, + className: "jquery-console-message-value" + }]); + } + + if (result.type.match(/illegal/)) { + + report( + [{ + msg: 'You are not allowed to run that command!', + className: "jquery-console-message-value" + }]); + } + + + if (result.type.match(/line_continuation/)) { + report( + [{ + msg: '..', + className: "jquery-console-prompt-label" + }]); + } + + }; + + //////////////////////////////////////////////////////////////////////// + // Raphael support + function runRaphael(expr) { + raphaelPaper.clear(); + $('#raphael').parent().parent().slideDown(function() { + var exprs = expr.split(/\n/g); + for (var i = 0; i < exprs.length; i++) + raphaelRunExpr(exprs[i]); + }); + } + function raphaelRunExpr(expr) { + var expr = expr.split(/ /g); + switch (expr[0]) { + case 'new': + { + switch (expr[2]) { + case 'circle': + { + var x = expr[3], + y = expr[4], + radius = expr[5]; + var circle = raphaelPaper.circle(x * 1, y * 1, radius * 1); + circle.attr("fill", "#7360a4"); + break; + } + } + } + } + } + + function notice(name, msg, style) { + if (opera()) return; + if (!notices[name]) { + notices[name] = name; + return controller.notice(msg, style); + } + } + + function limitsError(str) { + if (str == "Terminated!") { + notice('terminated', + "This error means it took to long to work" + + " out on the server.", + 'fadeout'); + return "Terminated!"; + } else if (str == "Time limit exceeded.") { + notice('exceeded', + "This error means it took to long to work out on the server. " + + "Try again.", + 'fadeout'); + return "Terminated! Try again."; + } + return str; + } + +})(jQuery); diff --git a/public/javascripts/jquery-1.3.2.min.js b/public/javascripts/jquery-1.3.2.min.js new file mode 100644 index 0000000..b1ae21d --- /dev/null +++ b/public/javascripts/jquery-1.3.2.min.js @@ -0,0 +1,19 @@ +/* + * jQuery JavaScript Library v1.3.2 + * http://jquery.com/ + * + * Copyright (c) 2009 John Resig + * Dual licensed under the MIT and GPL licenses. + * http://docs.jquery.com/License + * + * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) + * Revision: 6246 + */ +(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("",""]||!O.indexOf("",""]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
        "]||!O.indexOf("",""]||(!O.indexOf("",""]||!O.indexOf("",""]||!o.support.htmlSerialize&&[1,"div
        ","
        "]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}}); +/* + * Sizzle CSS Selector Engine - v0.9.3 + * Copyright 2009, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return UT[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="

        ";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="
        ";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("
        ").append(M.responseText.replace(//g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='
        ';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})(); \ No newline at end of file diff --git a/public/javascripts/jquery-1.4.2.min.js b/public/javascripts/jquery-1.4.2.min.js new file mode 100644 index 0000000..7c24308 --- /dev/null +++ b/public/javascripts/jquery-1.4.2.min.js @@ -0,0 +1,154 @@ +/*! + * jQuery JavaScript Library v1.4.2 + * http://jquery.com/ + * + * Copyright 2010, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2010, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Sat Feb 13 22:33:48 2010 -0500 + */ +(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, +Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& +(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, +a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== +"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, +function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
        a"; +var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, +parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= +false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= +s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, +applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; +else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, +a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== +w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, +cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= +c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); +a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, +function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); +k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), +C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B=0){a.type= +e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& +f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; +if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", +e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, +"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, +d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, +e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); +t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| +g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, +CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, +g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, +text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, +setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= +h[3];l=0;for(m=h.length;l=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== +"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, +h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& +q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; +if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="

        ";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); +(function(){var g=s.createElement("div");g.innerHTML="
        ";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: +function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var j=d;j0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= +{},i;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== +"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", +d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? +a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== +1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"},F={option:[1,""],legend:[1,"
        ","
        "],thead:[1,"","
        "],tr:[2,"","
        "],td:[3,"","
        "],col:[2,"","
        "],area:[1,"",""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
        ","
        "];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= +c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, +wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, +prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, +this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); +return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, +""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); +return this}else{e=0;for(var j=d.length;e0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", +""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===""&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= +c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? +c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= +function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= +Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, +"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= +a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= +a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=//gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!== +"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("
        ").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this}, +serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), +function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href, +global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&& +e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)? +"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache=== +false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B= +false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since", +c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E|| +d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x); +g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status=== +1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b=== +"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional; +if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration=== +"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]|| +c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start; +this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now= +this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem, +e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b
        "; +a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b); +c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a, +d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top- +f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset": +"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in +e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window); diff --git a/public/javascripts/jquery.console.js b/public/javascripts/jquery.console.js new file mode 100644 index 0000000..d45390d --- /dev/null +++ b/public/javascripts/jquery.console.js @@ -0,0 +1,609 @@ +// JQuery Console 1.0 +// Sun Feb 21 20:28:47 GMT 2010 +// +// Copyright 2010 Chris Done, Simon David Pratt. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above +// copyright notice, this list of conditions and the following +// disclaimer. +// +// 2. Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// TESTED ON +// Internet Explorer 6 +// Opera 10.01 +// Chromium 4.0.237.0 (Ubuntu build 31094) +// Firefox 3.5.8, 3.6.2 (Mac) +// Safari 4.0.5 (6531.22.7) (Mac) +// Google Chrome 5.0.375.55 (Mac) + +(function($){ + $.fn.console = function(config){ + //////////////////////////////////////////////////////////////////////// + // Constants + // Some are enums, data types, others just for optimisation + var keyCodes = { + // left + 37: moveBackward, + // right + 39: moveForward, + // up + 38: previousHistory, + // down + 40: nextHistory, + // backspace + 8: backDelete, + // delete + 46: forwardDelete, + // end + 35: moveToEnd, + // start + 36: moveToStart, + // return + 13: commandTrigger, + // tab + 18: doNothing + }; + var ctrlCodes = { + // C-a + 65: moveToStart, + // C-e + 69: moveToEnd, + // C-d + 68: forwardDelete, + // C-n + 78: nextHistory, + // C-p + 80: previousHistory, + // C-b + 66: moveBackward, + // C-f + 70: moveForward, + // C-k + 75: deleteUntilEnd + }; + var altCodes = { + // M-f + 70: moveToNextWord, + // M-b + 66: moveToPreviousWord, + // M-d + 68: deleteNextWord + }; + var cursor = ' '; + // Opera only works with this character, not or ­, + // but IE6 displays this character, which is bad, so just use + // it on Opera. + var wbr = $.browser.opera? '​' : ''; + + //////////////////////////////////////////////////////////////////////// + // Globals + var container = $(this); + var inner = $('
        '); + var typer = $(''); + // Prompt + var promptBox; + var prompt; + var promptLabel = config && config.promptLabel? config.promptLabel : "> "; + var column = 0; + var promptText = ''; + var restoreText = ''; + // Prompt history stack + var history = []; + var ringn = 0; + // For reasons unknown to The Sword of Michael himself, Opera + // triggers and sends a key character when you hit various + // keys like PgUp, End, etc. So there is no way of knowing + // when a user has typed '#' or End. My solution is in the + // typer.keydown and typer.keypress functions; I use the + // variable below to ignore the keypress event if the keydown + // event succeeds. + var cancelKeyPress = 0; + // When this value is false, the prompt will not respond to input + var acceptInput = true; + // When this value is true, the command has been canceled + var cancelCommand = false; + + // External exports object + var extern = {}; + + //////////////////////////////////////////////////////////////////////// + // Main entry point + (function(){ + container.append(inner); + inner.append(typer); + typer.css({position:'absolute',top:0,left:'-9999px'}); + if (config.welcomeMessage) + message(config.welcomeMessage,'jquery-console-welcome'); + newPromptBox(); + if (config.autofocus) { + inner.addClass('jquery-console-focus'); + typer.focus(); + setTimeout(function(){ + inner.addClass('jquery-console-focus'); + typer.focus(); + },100); + } + extern.inner = inner; + extern.typer = typer; + extern.scrollToBottom = scrollToBottom; + })(); + + //////////////////////////////////////////////////////////////////////// + // Reset terminal + extern.reset = function(){ + var welcome = true; + inner.parent().fadeOut(function(){ + inner.find('div').each(function(){ + if (!welcome) + $(this).remove(); + welcome = false; + }); + newPromptBox(); + inner.parent().fadeIn(function(){ + inner.addClass('jquery-console-focus'); + typer.focus(); + }); + }); + }; + + //////////////////////////////////////////////////////////////////////// + // Reset terminal + extern.notice = function(msg,style){ + var n = $('
        ').append($('
        ').text(msg)) + .css({visibility:'hidden'}); + container.append(n); + var focused = true; + if (style=='fadeout') + setTimeout(function(){ + n.fadeOut(function(){ + n.remove(); + }); + },4000); + else if (style=='prompt') { + var a = $('
        '); + n.append(a); + focused = false; + a.click(function(){ n.fadeOut(function(){ n.remove();inner.css({opacity:1}) }); }); + } + var h = n.height(); + n.css({height:'0px',visibility:'visible'}) + .animate({height:h+'px'},function(){ + if (!focused) inner.css({opacity:0.5}); + }); + n.css('cursor','default'); + return n; + }; + + //////////////////////////////////////////////////////////////////////// + // Make a new prompt box + function newPromptBox() { + column = 0; + promptText = ''; + ringn = 0; // Reset the position of the history ring + enableInput(); + promptBox = $('
        '); + var label = $(''); + promptBox.append(label.text(promptLabel).show()); + prompt = $(''); + promptBox.append(prompt); + inner.append(promptBox); + updatePromptDisplay(); + }; + + //////////////////////////////////////////////////////////////////////// + // Handle setting focus + container.click(function(){ + inner.addClass('jquery-console-focus'); + inner.removeClass('jquery-console-nofocus'); + typer.focus(); + scrollToBottom(); + return false; + }); + + //////////////////////////////////////////////////////////////////////// + // Handle losing focus + typer.blur(function(){ + inner.removeClass('jquery-console-focus'); + inner.addClass('jquery-console-nofocus'); + }); + + //////////////////////////////////////////////////////////////////////// + // Handle key hit before translation + // For picking up control characters like up/left/down/right + + typer.keydown(function(e){ + cancelKeyPress = 0; + var keyCode = e.keyCode; + // C-c: cancel the execution + if(e.ctrlKey && keyCode == 67) { + cancelKeyPress = keyCode; + cancelExecution(); + return false; + } + if (acceptInput) { + if (keyCode in keyCodes) { + cancelKeyPress = keyCode; + (keyCodes[keyCode])(); + return false; + } else if (e.ctrlKey && keyCode in ctrlCodes) { + cancelKeyPress = keyCode; + (ctrlCodes[keyCode])(); + return false; + } else if (e.altKey && keyCode in altCodes) { + cancelKeyPress = keyCode; + (altCodes[keyCode])(); + return false; + } + } + }); + + //////////////////////////////////////////////////////////////////////// + // Handle key press + typer.keypress(function(e){ + var keyCode = e.keyCode || e.which; + if (isIgnorableKey(e)) { + return false; + } + if (acceptInput && cancelKeyPress != keyCode && keyCode >= 32){ + if (cancelKeyPress) return false; + if (typeof config.charInsertTrigger == 'undefined' || + (typeof config.charInsertTrigger == 'function' && + config.charInsertTrigger(keyCode,promptText))) + typer.consoleInsert(keyCode); + } + if ($.browser.webkit) return false; + }); + + function isIgnorableKey(e) { + // for now just filter alt+tab that we receive on some platforms when + // user switches windows (goes away from the browser) + return ((e.keyCode == keyCodes.tab || e.keyCode == 192) && e.altKey); + }; + + //////////////////////////////////////////////////////////////////////// + // Rotate through the command history + function rotateHistory(n){ + if (history.length == 0) return; + ringn += n; + if (ringn < 0) ringn = history.length; + else if (ringn > history.length) ringn = 0; + var prevText = promptText; + if (ringn == 0) { + promptText = restoreText; + } else { + promptText = history[ringn - 1]; + } + if (config.historyPreserveColumn) { + if (promptText.length < column + 1) { + column = promptText.length; + } else if (column == 0) { + column = promptText.length; + } + } else if (config.historyColumnAtEnd) { + column = promptText.length; + } else { + column = 0; + } + updatePromptDisplay(); + }; + + function previousHistory() { + rotateHistory(-1); + }; + + function nextHistory() { + rotateHistory(1); + }; + + // Add something to the history ring + function addToHistory(line){ + history.push(line); + restoreText = ''; + }; + + // Delete the character at the current position + function deleteCharAtPos(){ + if (column < promptText.length){ + promptText = + promptText.substring(0,column) + + promptText.substring(column+1); + restoreText = promptText; + return true; + } else return false; + }; + + function backDelete() { + if (moveColumn(-1)){ + deleteCharAtPos(); + updatePromptDisplay(); + } + }; + + function forwardDelete() { + if (deleteCharAtPos()) + updatePromptDisplay(); + }; + + function deleteUntilEnd() { + while(deleteCharAtPos()) { + updatePromptDisplay(); + } + }; + + function deleteNextWord() { + // A word is defined within this context as a series of alphanumeric + // characters. + // Delete up to the next alphanumeric character + while(column < promptText.length && + !isCharAlphanumeric(promptText[column])) { + deleteCharAtPos(); + updatePromptDisplay(); + } + // Then, delete until the next non-alphanumeric character + while(column < promptText.length && + isCharAlphanumeric(promptText[column])) { + deleteCharAtPos(); + updatePromptDisplay(); + } + }; + + //////////////////////////////////////////////////////////////////////// + // Validate command and trigger it if valid, or show a validation error + function commandTrigger() { + var line = promptText; + if (typeof config.commandValidate == 'function') { + var ret = config.commandValidate(line); + if (ret == true || ret == false) { + if (ret) { + handleCommand(); + } + } else { + commandResult(ret,"jquery-console-message-error"); + } + } else { + handleCommand(); + } + }; + + // Scroll to the bottom of the view + function scrollToBottom() { + inner.attr({ scrollTop: inner.attr("scrollHeight") });; + }; + + function cancelExecution() { + if(typeof config.cancelHandle == 'function') { + config.cancelHandle(); + } + } + + //////////////////////////////////////////////////////////////////////// + // Handle a command + function handleCommand() { + if (typeof config.commandHandle == 'function') { + disableInput(); + addToHistory(promptText); + var ret = config.commandHandle(promptText,function(msgs){ + commandResult(msgs); + }); + if (typeof ret == 'boolean') { + if (ret) { + // Command succeeded without a result. + commandResult(); + } else { + commandResult('Command failed.', + "jquery-console-message-error"); + } + } else if (typeof ret == "string") { + commandResult(ret,"jquery-console-message-success"); + } else if (typeof ret == 'object' && ret.length) { + commandResult(ret); + } + } + }; + + //////////////////////////////////////////////////////////////////////// + // Disable input + function disableInput() { + acceptInput = false; + }; + + // Enable input + function enableInput() { + acceptInput = true; + } + + //////////////////////////////////////////////////////////////////////// + // Reset the prompt in invalid command + function commandResult(msg,className) { + column = -1; + updatePromptDisplay(); + if (typeof msg == 'string') { + message(msg,className); + } else { + for (var x in msg) { + var ret = msg[x]; + message(ret.msg,ret.className); + } + } + newPromptBox(); + }; + + //////////////////////////////////////////////////////////////////////// + // Display a message + function message(msg,className) { + var mesg = $('
        '); + if (className) mesg.addClass(className); + mesg.filledText(msg).hide(); + inner.append(mesg); + mesg.show(); + }; + + //////////////////////////////////////////////////////////////////////// + // Handle normal character insertion + typer.consoleInsert = function(keyCode){ + // TODO: remove redundant indirection + var char = String.fromCharCode(keyCode); + var before = promptText.substring(0,column); + var after = promptText.substring(column); + promptText = before + char + after; + moveColumn(1); + restoreText = promptText; + updatePromptDisplay(); + }; + + //////////////////////////////////////////////////////////////////////// + // Move to another column relative to this one + // Negative means go back, positive means go forward. + function moveColumn(n){ + if (column + n >= 0 && column + n <= promptText.length){ + column += n; + return true; + } else return false; + }; + + function moveForward() { + if(moveColumn(1)) { + updatePromptDisplay(); + return true; + } + return false; + }; + + function moveBackward() { + if(moveColumn(-1)) { + updatePromptDisplay(); + return true; + } + return false; + }; + + function moveToStart() { + if (moveColumn(-column)) + updatePromptDisplay(); + }; + + function moveToEnd() { + if (moveColumn(promptText.length-column)) + updatePromptDisplay(); + }; + + function moveToNextWord() { + while(column < promptText.length && + !isCharAlphanumeric(promptText[column]) && + moveForward()) { + } + while(column < promptText.length && + isCharAlphanumeric(promptText[column]) && + moveForward()) { + } + }; + + function moveToPreviousWord() { + // Move backward until we find the first alphanumeric + while(column -1 >= 0 && + !isCharAlphanumeric(promptText[column-1]) && + moveBackward()) { + } + // Move until we find the first non-alphanumeric + while(column -1 >= 0 && + isCharAlphanumeric(promptText[column-1]) && + moveBackward()) { + } + }; + + function isCharAlphanumeric(charToTest) { + if(typeof charToTest == 'string') { + var code = charToTest.charCodeAt(); + return (code >= 'A'.charCodeAt() && code <= 'Z'.charCodeAt()) || + (code >= 'a'.charCodeAt() && code <= 'z'.charCodeAt()) || + (code >= '0'.charCodeAt() && code <= '9'.charCodeAt()); + } + return false; + }; + + function doNothing() {}; + + extern.promptText = function(text){ + if (text) { + promptText = text; + if (column > promptText.length) + column = promptText.length; + updatePromptDisplay(); + } + return promptText; + }; + + //////////////////////////////////////////////////////////////////////// + // Update the prompt display + function updatePromptDisplay(){ + var line = promptText; + var html = ''; + if (column > 0 && line == ''){ + // When we have an empty line just display a cursor. + html = cursor; + } else if (column == promptText.length){ + // We're at the end of the line, so we need to display + // the text *and* cursor. + html = htmlEncode(line) + cursor; + } else { + // Grab the current character, if there is one, and + // make it the current cursor. + var before = line.substring(0, column); + var current = line.substring(column,column+1); + if (current){ + current = + '' + + htmlEncode(current) + + ''; + } + var after = line.substring(column+1); + html = htmlEncode(before) + current + htmlEncode(after); + } + prompt.html(html); + scrollToBottom(); + }; + + // Simple HTML encoding + // Simply replace '<', '>' and '&' + // TODO: Use jQuery's .html() trick, or grab a proper, fast + // HTML encoder. + function htmlEncode(text){ + return ( + text.replace(/&/g,'&') + .replace(/&]{10})/g,'$1­' + wbr) + ); + }; + + return extern; + }; + // Simple utility for printing messages + $.fn.filledText = function(txt){ + $(this).text(txt); + $(this).html($(this).html().replace(/\n/g,'
        ')); + return this; + }; +})(jQuery); diff --git a/public/javascripts/jquery.console.min.js b/public/javascripts/jquery.console.min.js new file mode 100644 index 0000000..7ae1e6b --- /dev/null +++ b/public/javascripts/jquery.console.min.js @@ -0,0 +1 @@ +(function($){$.fn.console=function(config){var keyCodes={left:37,right:39,up:38,down:40,back:8,del:46,end:35,start:36,ret:13};var cursor=' ';var wbr=$.browser.opera?'​':'';var container=$(this);var inner=$('
        ');var typer=$('');var promptBox;var prompt;var promptLabel=config&&config.promptLabel?config.promptLabel:"> ";var column=0;var promptText='';var restoreText='';var history=[];var ringn=0;var cancelKeyPress=0;var extern={};(function(){container.append(inner);inner.append(typer);typer.css({position:'absolute',top:0,left:'-999px'});if(config.welcomeMessage)message(config.welcomeMessage,'jquery-console-welcome');newPromptBox();if(config.autofocus){inner.addClass('jquery-console-focus');typer.focus();setTimeout(function(){inner.addClass('jquery-console-focus');typer.focus()},100)}})();extern.reset=function(){var welcome=true;inner.parent().fadeOut(function(){inner.find('div').each(function(){if(!welcome)$(this).remove();welcome=false});newPromptBox();inner.parent().fadeIn(function(){inner.addClass('jquery-console-focus');typer.focus()})})};function newPromptBox(){column=0;promptText='';promptBox=$('
        ');var label=$('');promptBox.append(label.text(promptLabel).show());prompt=$('');promptBox.append(prompt);inner.append(promptBox);updatePromptDisplay()};container.click(function(){inner.addClass('jquery-console-focus');inner.removeClass('jquery-console-nofocus');typer.focus();scrollToBottom();return false});typer.blur(function(){inner.removeClass('jquery-console-focus');inner.addClass('jquery-console-nofocus')});typer.keydown(function(e){cancelKeyPress=0;var keyCode=e.keyCode;if(isControlCharacter(keyCode)){cancelKeyPress=keyCode;if(!typer.consoleControl(keyCode)){return false}}});typer.keypress(function(e){var keyCode=e.keyCode||e.which;if(cancelKeyPress!=keyCode&&keyCode>=32){if(cancelKeyPress)return false;typer.consoleInsert(keyCode)}if($.browser.webkit)return false});function isControlCharacter(keyCode){return((keyCode>=keyCodes.left&&keyCode<=keyCodes.down)||keyCode==keyCodes.back||keyCode==keyCodes.del||keyCode==keyCodes.end||keyCode==keyCodes.start||keyCode==keyCodes.ret)};typer.consoleControl=function(keyCode){switch(keyCode){case keyCodes.left:{moveColumn(-1);updatePromptDisplay();return false;break}case keyCodes.right:{moveColumn(1);updatePromptDisplay();return false;break}case keyCodes.back:{if(moveColumn(-1)){deleteCharAtPos();updatePromptDisplay()}return false;break}case keyCodes.del:{if(deleteCharAtPos())updatePromptDisplay();return false;break}case keyCodes.end:{if(moveColumn(promptText.length-column))updatePromptDisplay();return false;break}case keyCodes.start:{if(moveColumn(-column))updatePromptDisplay();return false;break}case keyCodes.ret:{commandTrigger();return false}case keyCodes.up:{rotateHistory(-1);return false}case keyCodes.down:{rotateHistory(1);return false}default:}};function rotateHistory(n){if(history.length==0)return;ringn+=n;if(ringn<0)ringn=history.length;else if(ringn>history.length)ringn=0;var prevText=promptText;if(ringn==0){promptText=restoreText}else{promptText=history[ringn-1]}if(config.historyPreserveColumn){if(promptText.length
        ');if(className)mesg.addClass(className);mesg.filledText(msg).hide();inner.append(mesg);mesg.show()};typer.consoleInsert=function(keyCode){var char=String.fromCharCode(keyCode);var before=promptText.substring(0,column);var after=promptText.substring(column);promptText=before+char+after;moveColumn(1);restoreText=promptText;updatePromptDisplay()};function moveColumn(n){if(column+n>=0&&column+n<=promptText.length){column+=n;return true}else return false};function updatePromptDisplay(){var line=promptText;var html='';if(column>0&&line==''){html=cursor}else if(column==promptText.length){html=htmlEncode(line)+cursor}else{var before=line.substring(0,column);var current=line.substring(column,column+1);if(current){current=''+htmlEncode(current)+''}var after=line.substring(column+1);html=htmlEncode(before)+current+htmlEncode(after)}prompt.html(html);scrollToBottom()};function htmlEncode(text){return(text.replace(/&/g,'&').replace(/&]{10})/g,'$1­'+wbr))};return extern};$.fn.filledText=function(txt){$(this).text(txt);$(this).html($(this).html().replace(/\n/g,'
        '));return this}})(jQuery); \ No newline at end of file diff --git a/public/javascripts/jquery.js b/public/javascripts/jquery.js new file mode 100755 index 0000000..3747929 --- /dev/null +++ b/public/javascripts/jquery.js @@ -0,0 +1,32 @@ +/* + * jQuery 1.2.3 - New Wave Javascript + * + * Copyright (c) 2008 John Resig (jquery.com) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * $Date: 2008-02-06 00:21:25 -0500 (Wed, 06 Feb 2008) $ + * $Rev: 4663 $ + */ +(function(){if(window.jQuery)var _jQuery=window.jQuery;var jQuery=window.jQuery=function(selector,context){return new jQuery.prototype.init(selector,context);};if(window.$)var _$=window.$;window.$=jQuery;var quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;var isSimple=/^.[^:#\[\.]*$/;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;return this;}else if(typeof selector=="string"){var match=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1])selector=jQuery.clean([match[1]],context);else{var elem=document.getElementById(match[3]);if(elem)if(elem.id!=match[3])return jQuery().find(selector);else{this[0]=elem;this.length=1;return this;}else +selector=[];}}else +return new jQuery(context).find(selector);}else if(jQuery.isFunction(selector))return new jQuery(document)[jQuery.fn.ready?"ready":"load"](selector);return this.setArray(selector.constructor==Array&&selector||(selector.jquery||selector.length&&selector!=window&&!selector.nodeType&&selector[0]!=undefined&&selector[0].nodeType)&&jQuery.makeArray(selector)||[selector]);},jquery:"1.2.3",size:function(){return this.length;},length:0,get:function(num){return num==undefined?jQuery.makeArray(this):this[num];},pushStack:function(elems){var ret=jQuery(elems);ret.prevObject=this;return ret;},setArray:function(elems){this.length=0;Array.prototype.push.apply(this,elems);return this;},each:function(callback,args){return jQuery.each(this,callback,args);},index:function(elem){var ret=-1;this.each(function(i){if(this==elem)ret=i;});return ret;},attr:function(name,value,type){var options=name;if(name.constructor==String)if(value==undefined)return this.length&&jQuery[type||"attr"](this[0],name)||undefined;else{options={};options[name]=value;}return this.each(function(i){for(name in options)jQuery.attr(type?this.style:this,name,jQuery.prop(this,options[name],type,i,name));});},css:function(key,value){if((key=='width'||key=='height')&&parseFloat(value)<0)value=undefined;return this.attr(key,value,"curCSS");},text:function(text){if(typeof text!="object"&&text!=null)return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(text));var ret="";jQuery.each(text||this,function(){jQuery.each(this.childNodes,function(){if(this.nodeType!=8)ret+=this.nodeType!=1?this.nodeValue:jQuery.fn.text([this]);});});return ret;},wrapAll:function(html){if(this[0])jQuery(html,this[0].ownerDocument).clone().insertBefore(this[0]).map(function(){var elem=this;while(elem.firstChild)elem=elem.firstChild;return elem;}).append(this);return this;},wrapInner:function(html){return this.each(function(){jQuery(this).contents().wrapAll(html);});},wrap:function(html){return this.each(function(){jQuery(this).wrapAll(html);});},append:function(){return this.domManip(arguments,true,false,function(elem){if(this.nodeType==1)this.appendChild(elem);});},prepend:function(){return this.domManip(arguments,true,true,function(elem){if(this.nodeType==1)this.insertBefore(elem,this.firstChild);});},before:function(){return this.domManip(arguments,false,false,function(elem){this.parentNode.insertBefore(elem,this);});},after:function(){return this.domManip(arguments,false,true,function(elem){this.parentNode.insertBefore(elem,this.nextSibling);});},end:function(){return this.prevObject||jQuery([]);},find:function(selector){var elems=jQuery.map(this,function(elem){return jQuery.find(selector,elem);});return this.pushStack(/[^+>] [^+>]/.test(selector)||selector.indexOf("..")>-1?jQuery.unique(elems):elems);},clone:function(events){var ret=this.map(function(){if(jQuery.browser.msie&&!jQuery.isXMLDoc(this)){var clone=this.cloneNode(true),container=document.createElement("div");container.appendChild(clone);return jQuery.clean([container.innerHTML])[0];}else +return this.cloneNode(true);});var clone=ret.find("*").andSelf().each(function(){if(this[expando]!=undefined)this[expando]=null;});if(events===true)this.find("*").andSelf().each(function(i){if(this.nodeType==3)return;var events=jQuery.data(this,"events");for(var type in events)for(var handler in events[type])jQuery.event.add(clone[i],type,events[type][handler],events[type][handler].data);});return ret;},filter:function(selector){return this.pushStack(jQuery.isFunction(selector)&&jQuery.grep(this,function(elem,i){return selector.call(elem,i);})||jQuery.multiFilter(selector,this));},not:function(selector){if(selector.constructor==String)if(isSimple.test(selector))return this.pushStack(jQuery.multiFilter(selector,this,true));else +selector=jQuery.multiFilter(selector,this);var isArrayLike=selector.length&&selector[selector.length-1]!==undefined&&!selector.nodeType;return this.filter(function(){return isArrayLike?jQuery.inArray(this,selector)<0:this!=selector;});},add:function(selector){return!selector?this:this.pushStack(jQuery.merge(this.get(),selector.constructor==String?jQuery(selector).get():selector.length!=undefined&&(!selector.nodeName||jQuery.nodeName(selector,"form"))?selector:[selector]));},is:function(selector){return selector?jQuery.multiFilter(selector,this).length>0:false;},hasClass:function(selector){return this.is("."+selector);},val:function(value){if(value==undefined){if(this.length){var elem=this[0];if(jQuery.nodeName(elem,"select")){var index=elem.selectedIndex,values=[],options=elem.options,one=elem.type=="select-one";if(index<0)return null;for(var i=one?index:0,max=one?index+1:options.length;i=0||jQuery.inArray(this.name,value)>=0);else if(jQuery.nodeName(this,"select")){var values=value.constructor==Array?value:[value];jQuery("option",this).each(function(){this.selected=(jQuery.inArray(this.value,values)>=0||jQuery.inArray(this.text,values)>=0);});if(!values.length)this.selectedIndex=-1;}else +this.value=value;});},html:function(value){return value==undefined?(this.length?this[0].innerHTML:null):this.empty().append(value);},replaceWith:function(value){return this.after(value).remove();},eq:function(i){return this.slice(i,i+1);},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments));},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem);}));},andSelf:function(){return this.add(this.prevObject);},data:function(key,value){var parts=key.split(".");parts[1]=parts[1]?"."+parts[1]:"";if(value==null){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data==undefined&&this.length)data=jQuery.data(this[0],key);return data==null&&parts[1]?this.data(parts[0]):data;}else +return this.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){jQuery.data(this,key,value);});},removeData:function(key){return this.each(function(){jQuery.removeData(this,key);});},domManip:function(args,table,reverse,callback){var clone=this.length>1,elems;return this.each(function(){if(!elems){elems=jQuery.clean(args,this.ownerDocument);if(reverse)elems.reverse();}var obj=this;if(table&&jQuery.nodeName(this,"table")&&jQuery.nodeName(elems[0],"tr"))obj=this.getElementsByTagName("tbody")[0]||this.appendChild(this.ownerDocument.createElement("tbody"));var scripts=jQuery([]);jQuery.each(elems,function(){var elem=clone?jQuery(this).clone(true)[0]:this;if(jQuery.nodeName(elem,"script")){scripts=scripts.add(elem);}else{if(elem.nodeType==1)scripts=scripts.add(jQuery("script",elem).remove());callback.call(obj,elem);}});scripts.each(evalScript);});}};jQuery.prototype.init.prototype=jQuery.prototype;function evalScript(i,elem){if(elem.src)jQuery.ajax({url:elem.src,async:false,dataType:"script"});else +jQuery.globalEval(elem.text||elem.textContent||elem.innerHTML||"");if(elem.parentNode)elem.parentNode.removeChild(elem);}jQuery.extend=jQuery.fn.extend=function(){var target=arguments[0]||{},i=1,length=arguments.length,deep=false,options;if(target.constructor==Boolean){deep=target;target=arguments[1]||{};i=2;}if(typeof target!="object"&&typeof target!="function")target={};if(length==1){target=this;i=0;}for(;i-1;}},swap:function(elem,options,callback){var old={};for(var name in options){old[name]=elem.style[name];elem.style[name]=options[name];}callback.call(elem);for(var name in options)elem.style[name]=old[name];},css:function(elem,name,force){if(name=="width"||name=="height"){var val,props={position:"absolute",visibility:"hidden",display:"block"},which=name=="width"?["Left","Right"]:["Top","Bottom"];function getWH(){val=name=="width"?elem.offsetWidth:elem.offsetHeight;var padding=0,border=0;jQuery.each(which,function(){padding+=parseFloat(jQuery.curCSS(elem,"padding"+this,true))||0;border+=parseFloat(jQuery.curCSS(elem,"border"+this+"Width",true))||0;});val-=Math.round(padding+border);}if(jQuery(elem).is(":visible"))getWH();else +jQuery.swap(elem,props,getWH);return Math.max(0,val);}return jQuery.curCSS(elem,name,force);},curCSS:function(elem,name,force){var ret;function color(elem){if(!jQuery.browser.safari)return false;var ret=document.defaultView.getComputedStyle(elem,null);return!ret||ret.getPropertyValue("color")=="";}if(name=="opacity"&&jQuery.browser.msie){ret=jQuery.attr(elem.style,"opacity");return ret==""?"1":ret;}if(jQuery.browser.opera&&name=="display"){var save=elem.style.outline;elem.style.outline="0 solid black";elem.style.outline=save;}if(name.match(/float/i))name=styleFloat;if(!force&&elem.style&&elem.style[name])ret=elem.style[name];else if(document.defaultView&&document.defaultView.getComputedStyle){if(name.match(/float/i))name="float";name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var getComputedStyle=document.defaultView.getComputedStyle(elem,null);if(getComputedStyle&&!color(elem))ret=getComputedStyle.getPropertyValue(name);else{var swap=[],stack=[];for(var a=elem;a&&color(a);a=a.parentNode)stack.unshift(a);for(var i=0;i]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+">";});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("",""]||!tags.indexOf("",""]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
        "]||!tags.indexOf("",""]||(!tags.indexOf("",""]||!tags.indexOf("",""]||jQuery.browser.msie&&[1,"div
        ","
        "]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--)div=div.lastChild;if(jQuery.browser.msie){var tbody=!tags.indexOf(""&&tags.indexOf("=0;--j)if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length)tbody[j].parentNode.removeChild(tbody[j]);if(/^\s/.test(elem))div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]),div.firstChild);}elem=jQuery.makeArray(div.childNodes);}if(elem.length===0&&(!jQuery.nodeName(elem,"form")&&!jQuery.nodeName(elem,"select")))return;if(elem[0]==undefined||jQuery.nodeName(elem,"form")||elem.options)ret.push(elem);else +ret=jQuery.merge(ret,elem);});return ret;},attr:function(elem,name,value){if(!elem||elem.nodeType==3||elem.nodeType==8)return undefined;var fix=jQuery.isXMLDoc(elem)?{}:jQuery.props;if(name=="selected"&&jQuery.browser.safari)elem.parentNode.selectedIndex;if(fix[name]){if(value!=undefined)elem[fix[name]]=value;return elem[fix[name]];}else if(jQuery.browser.msie&&name=="style")return jQuery.attr(elem.style,"cssText",value);else if(value==undefined&&jQuery.browser.msie&&jQuery.nodeName(elem,"form")&&(name=="action"||name=="method"))return elem.getAttributeNode(name).nodeValue;else if(elem.tagName){if(value!=undefined){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode)throw"type property can't be changed";elem.setAttribute(name,""+value);}if(jQuery.browser.msie&&/href|src/.test(name)&&!jQuery.isXMLDoc(elem))return elem.getAttribute(name,2);return elem.getAttribute(name);}else{if(name=="opacity"&&jQuery.browser.msie){if(value!=undefined){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+(parseFloat(value).toString()=="NaN"?"":"alpha(opacity="+value*100+")");}return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100).toString():"";}name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase();});if(value!=undefined)elem[name]=value;return elem[name];}},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"");},makeArray:function(array){var ret=[];if(typeof array!="array")for(var i=0,length=array.length;i*",this).remove();while(this.firstChild)this.removeChild(this.firstChild);}},function(name,fn){jQuery.fn[name]=function(){return this.each(fn,arguments);};});jQuery.each(["Height","Width"],function(i,name){var type=name.toLowerCase();jQuery.fn[type]=function(size){return this[0]==window?jQuery.browser.opera&&document.body["client"+name]||jQuery.browser.safari&&window["inner"+name]||document.compatMode=="CSS1Compat"&&document.documentElement["client"+name]||document.body["client"+name]:this[0]==document?Math.max(Math.max(document.body["scroll"+name],document.documentElement["scroll"+name]),Math.max(document.body["offset"+name],document.documentElement["offset"+name])):size==undefined?(this.length?jQuery.css(this[0],type):null):this.css(type,size.constructor==String?size:size+"px");};});var chars=jQuery.browser.safari&&parseInt(jQuery.browser.version)<417?"(?:[\\w*_-]|\\\\.)":"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",quickChild=new RegExp("^>\\s*("+chars+"+)"),quickID=new RegExp("^("+chars+"+)(#)("+chars+"+)"),quickClass=new RegExp("^([#.]?)("+chars+"*)");jQuery.extend({expr:{"":function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},"#":function(a,i,m){return a.getAttribute("id")==m[2];},":":{lt:function(a,i,m){return im[3]-0;},nth:function(a,i,m){return m[3]-0==i;},eq:function(a,i,m){return m[3]-0==i;},first:function(a,i){return i==0;},last:function(a,i,m,r){return i==r.length-1;},even:function(a,i){return i%2==0;},odd:function(a,i){return i%2;},"first-child":function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},"last-child":function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},"only-child":function(a){return!jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},parent:function(a){return a.firstChild;},empty:function(a){return!a.firstChild;},contains:function(a,i,m){return(a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},visible:function(a){return"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},hidden:function(a){return"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},enabled:function(a){return!a.disabled;},disabled:function(a){return a.disabled;},checked:function(a){return a.checked;},selected:function(a){return a.selected||jQuery.attr(a,"selected");},text:function(a){return"text"==a.type;},radio:function(a){return"radio"==a.type;},checkbox:function(a){return"checkbox"==a.type;},file:function(a){return"file"==a.type;},password:function(a){return"password"==a.type;},submit:function(a){return"submit"==a.type;},image:function(a){return"image"==a.type;},reset:function(a){return"reset"==a.type;},button:function(a){return"button"==a.type||jQuery.nodeName(a,"button");},input:function(a){return/input|select|textarea|button/i.test(a.nodeName);},has:function(a,i,m){return jQuery.find(m[3],a).length;},header:function(a){return/h\d/i.test(a.nodeName);},animated:function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}}},parse:[/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,new RegExp("^([:.#]*)("+chars+"+)")],multiFilter:function(expr,elems,not){var old,cur=[];while(expr&&expr!=old){old=expr;var f=jQuery.filter(expr,elems,not);expr=f.t.replace(/^\s*,\s*/,"");cur=not?elems=f.r:jQuery.merge(cur,f.r);}return cur;},find:function(t,context){if(typeof t!="string")return[t];if(context&&context.nodeType!=1&&context.nodeType!=9)return[];context=context||document;var ret=[context],done=[],last,nodeName;while(t&&last!=t){var r=[];last=t;t=jQuery.trim(t);var foundToken=false;var re=quickChild;var m=re.exec(t);if(m){nodeName=m[1].toUpperCase();for(var i=0;ret[i];i++)for(var c=ret[i].firstChild;c;c=c.nextSibling)if(c.nodeType==1&&(nodeName=="*"||c.nodeName.toUpperCase()==nodeName))r.push(c);ret=r;t=t.replace(re,"");if(t.indexOf(" ")==0)continue;foundToken=true;}else{re=/^([>+~])\s*(\w*)/i;if((m=re.exec(t))!=null){r=[];var merge={};nodeName=m[2].toUpperCase();m=m[1];for(var j=0,rl=ret.length;j=0;if(!not&&pass||not&&!pass)tmp.push(r[i]);}return tmp;},filter:function(t,r,not){var last;while(t&&t!=last){last=t;var p=jQuery.parse,m;for(var i=0;p[i];i++){m=p[i].exec(t);if(m){t=t.substring(m[0].length);m[2]=m[2].replace(/\\/g,"");break;}}if(!m)break;if(m[1]==":"&&m[2]=="not")r=isSimple.test(m[3])?jQuery.filter(m[3],r,true).r:jQuery(r).not(m[3]);else if(m[1]==".")r=jQuery.classFilter(r,m[2],not);else if(m[1]=="["){var tmp=[],type=m[3];for(var i=0,rl=r.length;i=0)^not)tmp.push(a);}r=tmp;}else if(m[1]==":"&&m[2]=="nth-child"){var merge={},tmp=[],test=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3]=="even"&&"2n"||m[3]=="odd"&&"2n+1"||!/\D/.test(m[3])&&"0n+"+m[3]||m[3]),first=(test[1]+(test[2]||1))-0,last=test[3]-0;for(var i=0,rl=r.length;i=0)add=true;if(add^not)tmp.push(node);}r=tmp;}else{var fn=jQuery.expr[m[1]];if(typeof fn=="object")fn=fn[m[2]];if(typeof fn=="string")fn=eval("false||function(a,i){return "+fn+";}");r=jQuery.grep(r,function(elem,i){return fn(elem,i,m,r);},not);}}return{r:r,t:t};},dir:function(elem,dir){var matched=[];var cur=elem[dir];while(cur&&cur!=document){if(cur.nodeType==1)matched.push(cur);cur=cur[dir];}return matched;},nth:function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir])if(cur.nodeType==1&&++num==result)break;return cur;},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType==1&&(!elem||n!=elem))r.push(n);}return r;}});jQuery.event={add:function(elem,types,handler,data){if(elem.nodeType==3||elem.nodeType==8)return;if(jQuery.browser.msie&&elem.setInterval!=undefined)elem=window;if(!handler.guid)handler.guid=this.guid++;if(data!=undefined){var fn=handler;handler=function(){return fn.apply(this,arguments);};handler.data=data;handler.guid=fn.guid;}var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){var val;if(typeof jQuery=="undefined"||jQuery.event.triggered)return val;val=jQuery.event.handle.apply(arguments.callee.elem,arguments);return val;});handle.elem=elem;jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];handler.type=parts[1];var handlers=events[type];if(!handlers){handlers=events[type]={};if(!jQuery.event.special[type]||jQuery.event.special[type].setup.call(elem)===false){if(elem.addEventListener)elem.addEventListener(type,handle,false);else if(elem.attachEvent)elem.attachEvent("on"+type,handle);}}handlers[handler.guid]=handler;jQuery.event.global[type]=true;});elem=null;},guid:1,global:{},remove:function(elem,types,handler){if(elem.nodeType==3||elem.nodeType==8)return;var events=jQuery.data(elem,"events"),ret,index;if(events){if(types==undefined||(typeof types=="string"&&types.charAt(0)=="."))for(var type in events)this.remove(elem,type+(types||""));else{if(types.type){handler=types.handler;types=types.type;}jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];if(events[type]){if(handler)delete events[type][handler.guid];else +for(handler in events[type])if(!parts[1]||events[type][handler].type==parts[1])delete events[type][handler];for(ret in events[type])break;if(!ret){if(!jQuery.event.special[type]||jQuery.event.special[type].teardown.call(elem)===false){if(elem.removeEventListener)elem.removeEventListener(type,jQuery.data(elem,"handle"),false);else if(elem.detachEvent)elem.detachEvent("on"+type,jQuery.data(elem,"handle"));}ret=null;delete events[type];}}});}for(ret in events)break;if(!ret){var handle=jQuery.data(elem,"handle");if(handle)handle.elem=null;jQuery.removeData(elem,"events");jQuery.removeData(elem,"handle");}}},trigger:function(type,data,elem,donative,extra){data=jQuery.makeArray(data||[]);if(type.indexOf("!")>=0){type=type.slice(0,-1);var exclusive=true;}if(!elem){if(this.global[type])jQuery("*").add([window,document]).trigger(type,data);}else{if(elem.nodeType==3||elem.nodeType==8)return undefined;var val,ret,fn=jQuery.isFunction(elem[type]||null),event=!data[0]||!data[0].preventDefault;if(event)data.unshift(this.fix({type:type,target:elem}));data[0].type=type;if(exclusive)data[0].exclusive=true;if(jQuery.isFunction(jQuery.data(elem,"handle")))val=jQuery.data(elem,"handle").apply(elem,data);if(!fn&&elem["on"+type]&&elem["on"+type].apply(elem,data)===false)val=false;if(event)data.shift();if(extra&&jQuery.isFunction(extra)){ret=extra.apply(elem,val==null?data:data.concat(val));if(ret!==undefined)val=ret;}if(fn&&donative!==false&&val!==false&&!(jQuery.nodeName(elem,'a')&&type=="click")){this.triggered=true;try{elem[type]();}catch(e){}}this.triggered=false;}return val;},handle:function(event){var val;event=jQuery.event.fix(event||window.event||{});var parts=event.type.split(".");event.type=parts[0];var handlers=jQuery.data(this,"events")&&jQuery.data(this,"events")[event.type],args=Array.prototype.slice.call(arguments,1);args.unshift(event);for(var j in handlers){var handler=handlers[j];args[0].handler=handler;args[0].data=handler.data;if(!parts[1]&&!event.exclusive||handler.type==parts[1]){var ret=handler.apply(this,args);if(val!==false)val=ret;if(ret===false){event.preventDefault();event.stopPropagation();}}}if(jQuery.browser.msie)event.target=event.preventDefault=event.stopPropagation=event.handler=event.data=null;return val;},fix:function(event){var originalEvent=event;event=jQuery.extend({},originalEvent);event.preventDefault=function(){if(originalEvent.preventDefault)originalEvent.preventDefault();originalEvent.returnValue=false;};event.stopPropagation=function(){if(originalEvent.stopPropagation)originalEvent.stopPropagation();originalEvent.cancelBubble=true;};if(!event.target)event.target=event.srcElement||document;if(event.target.nodeType==3)event.target=originalEvent.target.parentNode;if(!event.relatedTarget&&event.fromElement)event.relatedTarget=event.fromElement==event.target?event.toElement:event.fromElement;if(event.pageX==null&&event.clientX!=null){var doc=document.documentElement,body=document.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc.clientTop||0);}if(!event.which&&((event.charCode||event.charCode===0)?event.charCode:event.keyCode))event.which=event.charCode||event.keyCode;if(!event.metaKey&&event.ctrlKey)event.metaKey=event.ctrlKey;if(!event.which&&event.button)event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)));return event;},special:{ready:{setup:function(){bindReady();return;},teardown:function(){return;}},mouseenter:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseover",jQuery.event.special.mouseenter.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseover",jQuery.event.special.mouseenter.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseenter";return jQuery.event.handle.apply(this,arguments);}},mouseleave:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseout",jQuery.event.special.mouseleave.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseout",jQuery.event.special.mouseleave.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseleave";return jQuery.event.handle.apply(this,arguments);}}}};jQuery.fn.extend({bind:function(type,data,fn){return type=="unload"?this.one(type,data,fn):this.each(function(){jQuery.event.add(this,type,fn||data,fn&&data);});},one:function(type,data,fn){return this.each(function(){jQuery.event.add(this,type,function(event){jQuery(this).unbind(event);return(fn||data).apply(this,arguments);},fn&&data);});},unbind:function(type,fn){return this.each(function(){jQuery.event.remove(this,type,fn);});},trigger:function(type,data,fn){return this.each(function(){jQuery.event.trigger(type,data,this,true,fn);});},triggerHandler:function(type,data,fn){if(this[0])return jQuery.event.trigger(type,data,this[0],false,fn);return undefined;},toggle:function(){var args=arguments;return this.click(function(event){this.lastToggle=0==this.lastToggle?1:0;event.preventDefault();return args[this.lastToggle].apply(this,arguments)||false;});},hover:function(fnOver,fnOut){return this.bind('mouseenter',fnOver).bind('mouseleave',fnOut);},ready:function(fn){bindReady();if(jQuery.isReady)fn.call(document,jQuery);else +jQuery.readyList.push(function(){return fn.call(this,jQuery);});return this;}});jQuery.extend({isReady:false,readyList:[],ready:function(){if(!jQuery.isReady){jQuery.isReady=true;if(jQuery.readyList){jQuery.each(jQuery.readyList,function(){this.apply(document);});jQuery.readyList=null;}jQuery(document).triggerHandler("ready");}}});var readyBound=false;function bindReady(){if(readyBound)return;readyBound=true;if(document.addEventListener&&!jQuery.browser.opera)document.addEventListener("DOMContentLoaded",jQuery.ready,false);if(jQuery.browser.msie&&window==top)(function(){if(jQuery.isReady)return;try{document.documentElement.doScroll("left");}catch(error){setTimeout(arguments.callee,0);return;}jQuery.ready();})();if(jQuery.browser.opera)document.addEventListener("DOMContentLoaded",function(){if(jQuery.isReady)return;for(var i=0;i=0){var selector=url.slice(off,url.length);url=url.slice(0,off);}callback=callback||function(){};var type="GET";if(params)if(jQuery.isFunction(params)){callback=params;params=null;}else{params=jQuery.param(params);type="POST";}var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(res,status){if(status=="success"||status=="notmodified")self.html(selector?jQuery("
        ").append(res.responseText.replace(//g,"")).find(selector):res.responseText);self.each(callback,[res.responseText,status,res]);}});return this;},serialize:function(){return jQuery.param(this.serializeArray());},serializeArray:function(){return this.map(function(){return jQuery.nodeName(this,"form")?jQuery.makeArray(this.elements):this;}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type));}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:val.constructor==Array?jQuery.map(val,function(val,i){return{name:elem.name,value:val};}):{name:elem.name,value:val};}).get();}});jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(i,o){jQuery.fn[o]=function(f){return this.bind(o,f);};});var jsc=(new Date).getTime();jQuery.extend({get:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data=null;}return jQuery.ajax({type:"GET",url:url,data:data,success:callback,dataType:type});},getScript:function(url,callback){return jQuery.get(url,null,callback,"script");},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},post:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data={};}return jQuery.ajax({type:"POST",url:url,data:data,success:callback,dataType:type});},ajaxSetup:function(settings){jQuery.extend(jQuery.ajaxSettings,settings);},ajaxSettings:{global:true,type:"GET",timeout:0,contentType:"application/x-www-form-urlencoded",processData:true,async:true,data:null,username:null,password:null,accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(s){var jsonp,jsre=/=\?(&|$)/g,status,data;s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));if(s.data&&s.processData&&typeof s.data!="string")s.data=jQuery.param(s.data);if(s.dataType=="jsonp"){if(s.type.toLowerCase()=="get"){if(!s.url.match(jsre))s.url+=(s.url.match(/\?/)?"&":"?")+(s.jsonp||"callback")+"=?";}else if(!s.data||!s.data.match(jsre))s.data=(s.data?s.data+"&":"")+(s.jsonp||"callback")+"=?";s.dataType="json";}if(s.dataType=="json"&&(s.data&&s.data.match(jsre)||s.url.match(jsre))){jsonp="jsonp"+jsc++;if(s.data)s.data=(s.data+"").replace(jsre,"="+jsonp+"$1");s.url=s.url.replace(jsre,"="+jsonp+"$1");s.dataType="script";window[jsonp]=function(tmp){data=tmp;success();complete();window[jsonp]=undefined;try{delete window[jsonp];}catch(e){}if(head)head.removeChild(script);};}if(s.dataType=="script"&&s.cache==null)s.cache=false;if(s.cache===false&&s.type.toLowerCase()=="get"){var ts=(new Date()).getTime();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"");}if(s.data&&s.type.toLowerCase()=="get"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null;}if(s.global&&!jQuery.active++)jQuery.event.trigger("ajaxStart");if((!s.url.indexOf("http")||!s.url.indexOf("//"))&&s.dataType=="script"&&s.type.toLowerCase()=="get"){var head=document.getElementsByTagName("head")[0];var script=document.createElement("script");script.src=s.url;if(s.scriptCharset)script.charset=s.scriptCharset;if(!jsonp){var done=false;script.onload=script.onreadystatechange=function(){if(!done&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){done=true;success();complete();head.removeChild(script);}};}head.appendChild(script);return undefined;}var requestDone=false;var xml=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();xml.open(s.type,s.url,s.async,s.username,s.password);try{if(s.data)xml.setRequestHeader("Content-Type",s.contentType);if(s.ifModified)xml.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT");xml.setRequestHeader("X-Requested-With","XMLHttpRequest");xml.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default);}catch(e){}if(s.beforeSend)s.beforeSend(xml);if(s.global)jQuery.event.trigger("ajaxSend",[xml,s]);var onreadystatechange=function(isTimeout){if(!requestDone&&xml&&(xml.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null;}status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xml)&&"error"||s.ifModified&&jQuery.httpNotModified(xml,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xml,s.dataType);}catch(e){status="parsererror";}}if(status=="success"){var modRes;try{modRes=xml.getResponseHeader("Last-Modified");}catch(e){}if(s.ifModified&&modRes)jQuery.lastModified[s.url]=modRes;if(!jsonp)success();}else +jQuery.handleError(s,xml,status);complete();if(s.async)xml=null;}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0)setTimeout(function(){if(xml){xml.abort();if(!requestDone)onreadystatechange("timeout");}},s.timeout);}try{xml.send(s.data);}catch(e){jQuery.handleError(s,xml,null,e);}if(!s.async)onreadystatechange();function success(){if(s.success)s.success(data,status);if(s.global)jQuery.event.trigger("ajaxSuccess",[xml,s]);}function complete(){if(s.complete)s.complete(xml,status);if(s.global)jQuery.event.trigger("ajaxComplete",[xml,s]);if(s.global&&!--jQuery.active)jQuery.event.trigger("ajaxStop");}return xml;},handleError:function(s,xml,status,e){if(s.error)s.error(xml,status,e);if(s.global)jQuery.event.trigger("ajaxError",[xml,s,e]);},active:0,httpSuccess:function(r){try{return!r.status&&location.protocol=="file:"||(r.status>=200&&r.status<300)||r.status==304||r.status==1223||jQuery.browser.safari&&r.status==undefined;}catch(e){}return false;},httpNotModified:function(xml,url){try{var xmlRes=xml.getResponseHeader("Last-Modified");return xml.status==304||xmlRes==jQuery.lastModified[url]||jQuery.browser.safari&&xml.status==undefined;}catch(e){}return false;},httpData:function(r,type){var ct=r.getResponseHeader("content-type");var xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0;var data=xml?r.responseXML:r.responseText;if(xml&&data.documentElement.tagName=="parsererror")throw"parsererror";if(type=="script")jQuery.globalEval(data);if(type=="json")data=eval("("+data+")");return data;},param:function(a){var s=[];if(a.constructor==Array||a.jquery)jQuery.each(a,function(){s.push(encodeURIComponent(this.name)+"="+encodeURIComponent(this.value));});else +for(var j in a)if(a[j]&&a[j].constructor==Array)jQuery.each(a[j],function(){s.push(encodeURIComponent(j)+"="+encodeURIComponent(this));});else +s.push(encodeURIComponent(j)+"="+encodeURIComponent(a[j]));return s.join("&").replace(/%20/g,"+");}});jQuery.fn.extend({show:function(speed,callback){return speed?this.animate({height:"show",width:"show",opacity:"show"},speed,callback):this.filter(":hidden").each(function(){this.style.display=this.oldblock||"";if(jQuery.css(this,"display")=="none"){var elem=jQuery("<"+this.tagName+" />").appendTo("body");this.style.display=elem.css("display");if(this.style.display=="none")this.style.display="block";elem.remove();}}).end();},hide:function(speed,callback){return speed?this.animate({height:"hide",width:"hide",opacity:"hide"},speed,callback):this.filter(":visible").each(function(){this.oldblock=this.oldblock||jQuery.css(this,"display");this.style.display="none";}).end();},_toggle:jQuery.fn.toggle,toggle:function(fn,fn2){return jQuery.isFunction(fn)&&jQuery.isFunction(fn2)?this._toggle(fn,fn2):fn?this.animate({height:"toggle",width:"toggle",opacity:"toggle"},fn,fn2):this.each(function(){jQuery(this)[jQuery(this).is(":hidden")?"show":"hide"]();});},slideDown:function(speed,callback){return this.animate({height:"show"},speed,callback);},slideUp:function(speed,callback){return this.animate({height:"hide"},speed,callback);},slideToggle:function(speed,callback){return this.animate({height:"toggle"},speed,callback);},fadeIn:function(speed,callback){return this.animate({opacity:"show"},speed,callback);},fadeOut:function(speed,callback){return this.animate({opacity:"hide"},speed,callback);},fadeTo:function(speed,to,callback){return this.animate({opacity:to},speed,callback);},animate:function(prop,speed,easing,callback){var optall=jQuery.speed(speed,easing,callback);return this[optall.queue===false?"each":"queue"](function(){if(this.nodeType!=1)return false;var opt=jQuery.extend({},optall);var hidden=jQuery(this).is(":hidden"),self=this;for(var p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden)return jQuery.isFunction(opt.complete)&&opt.complete.apply(this);if(p=="height"||p=="width"){opt.display=jQuery.css(this,"display");opt.overflow=this.style.overflow;}}if(opt.overflow!=null)this.style.overflow="hidden";opt.curAnim=jQuery.extend({},prop);jQuery.each(prop,function(name,val){var e=new jQuery.fx(self,opt,name);if(/toggle|show|hide/.test(val))e[val=="toggle"?hidden?"show":"hide":val](prop);else{var parts=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),start=e.cur(true)||0;if(parts){var end=parseFloat(parts[2]),unit=parts[3]||"px";if(unit!="px"){self.style[name]=(end||1)+unit;start=((end||1)/e.cur(true))*start;self.style[name]=start+unit;}if(parts[1])end=((parts[1]=="-="?-1:1)*end)+start;e.custom(start,end,unit);}else +e.custom(start,val,"");}});return true;});},queue:function(type,fn){if(jQuery.isFunction(type)||(type&&type.constructor==Array)){fn=type;type="fx";}if(!type||(typeof type=="string"&&!fn))return queue(this[0],type);return this.each(function(){if(fn.constructor==Array)queue(this,type,fn);else{queue(this,type).push(fn);if(queue(this,type).length==1)fn.apply(this);}});},stop:function(clearQueue,gotoEnd){var timers=jQuery.timers;if(clearQueue)this.queue([]);this.each(function(){for(var i=timers.length-1;i>=0;i--)if(timers[i].elem==this){if(gotoEnd)timers[i](true);timers.splice(i,1);}});if(!gotoEnd)this.dequeue();return this;}});var queue=function(elem,type,array){if(!elem)return undefined;type=type||"fx";var q=jQuery.data(elem,type+"queue");if(!q||array)q=jQuery.data(elem,type+"queue",array?jQuery.makeArray(array):[]);return q;};jQuery.fn.dequeue=function(type){type=type||"fx";return this.each(function(){var q=queue(this,type);q.shift();if(q.length)q[0].apply(this);});};jQuery.extend({speed:function(speed,easing,fn){var opt=speed&&speed.constructor==Object?speed:{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&easing.constructor!=Function&&easing};opt.duration=(opt.duration&&opt.duration.constructor==Number?opt.duration:{slow:600,fast:200}[opt.duration])||400;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false)jQuery(this).dequeue();if(jQuery.isFunction(opt.old))opt.old.apply(this);};return opt;},easing:{linear:function(p,n,firstNum,diff){return firstNum+diff*p;},swing:function(p,n,firstNum,diff){return((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum;}},timers:[],timerId:null,fx:function(elem,options,prop){this.options=options;this.elem=elem;this.prop=prop;if(!options.orig)options.orig={};}});jQuery.fx.prototype={update:function(){if(this.options.step)this.options.step.apply(this.elem,[this.now,this]);(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);if(this.prop=="height"||this.prop=="width")this.elem.style.display="block";},cur:function(force){if(this.elem[this.prop]!=null&&this.elem.style[this.prop]==null)return this.elem[this.prop];var r=parseFloat(jQuery.css(this.elem,this.prop,force));return r&&r>-10000?r:parseFloat(jQuery.curCSS(this.elem,this.prop))||0;},custom:function(from,to,unit){this.startTime=(new Date()).getTime();this.start=from;this.end=to;this.unit=unit||this.unit||"px";this.now=this.start;this.pos=this.state=0;this.update();var self=this;function t(gotoEnd){return self.step(gotoEnd);}t.elem=this.elem;jQuery.timers.push(t);if(jQuery.timerId==null){jQuery.timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;ithis.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var done=true;for(var i in this.options.curAnim)if(this.options.curAnim[i]!==true)done=false;if(done){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(jQuery.css(this.elem,"display")=="none")this.elem.style.display="block";}if(this.options.hide)this.elem.style.display="none";if(this.options.hide||this.options.show)for(var p in this.options.curAnim)jQuery.attr(this.elem.style,p,this.options.orig[p]);}if(done&&jQuery.isFunction(this.options.complete))this.options.complete.apply(this.elem);return false;}else{var n=t-this.startTime;this.state=n/this.options.duration;this.pos=jQuery.easing[this.options.easing||(jQuery.easing.swing?"swing":"linear")](this.state,n,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update();}return true;}};jQuery.fx.step={scrollLeft:function(fx){fx.elem.scrollLeft=fx.now;},scrollTop:function(fx){fx.elem.scrollTop=fx.now;},opacity:function(fx){jQuery.attr(fx.elem.style,"opacity",fx.now);},_default:function(fx){fx.elem.style[fx.prop]=fx.now+fx.unit;}};jQuery.fn.offset=function(){var left=0,top=0,elem=this[0],results;if(elem)with(jQuery.browser){var parent=elem.parentNode,offsetChild=elem,offsetParent=elem.offsetParent,doc=elem.ownerDocument,safari2=safari&&parseInt(version)<522&&!/adobeair/i.test(userAgent),fixed=jQuery.css(elem,"position")=="fixed";if(elem.getBoundingClientRect){var box=elem.getBoundingClientRect();add(box.left+Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),box.top+Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));add(-doc.documentElement.clientLeft,-doc.documentElement.clientTop);}else{add(elem.offsetLeft,elem.offsetTop);while(offsetParent){add(offsetParent.offsetLeft,offsetParent.offsetTop);if(mozilla&&!/^t(able|d|h)$/i.test(offsetParent.tagName)||safari&&!safari2)border(offsetParent);if(!fixed&&jQuery.css(offsetParent,"position")=="fixed")fixed=true;offsetChild=/^body$/i.test(offsetParent.tagName)?offsetChild:offsetParent;offsetParent=offsetParent.offsetParent;}while(parent&&parent.tagName&&!/^body|html$/i.test(parent.tagName)){if(!/^inline|table.*$/i.test(jQuery.css(parent,"display")))add(-parent.scrollLeft,-parent.scrollTop);if(mozilla&&jQuery.css(parent,"overflow")!="visible")border(parent);parent=parent.parentNode;}if((safari2&&(fixed||jQuery.css(offsetChild,"position")=="absolute"))||(mozilla&&jQuery.css(offsetChild,"position")!="absolute"))add(-doc.body.offsetLeft,-doc.body.offsetTop);if(fixed)add(Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));}results={top:top,left:left};}function border(elem){add(jQuery.curCSS(elem,"borderLeftWidth",true),jQuery.curCSS(elem,"borderTopWidth",true));}function add(l,t){left+=parseInt(l)||0;top+=parseInt(t)||0;}return results;};})(); \ No newline at end of file diff --git a/public/javascripts/json2.js b/public/javascripts/json2.js new file mode 100644 index 0000000..d4f4541 --- /dev/null +++ b/public/javascripts/json2.js @@ -0,0 +1 @@ +if(!this.JSON){this.JSON={}}(function(){function f(n){return n<10?'0'+n:n}if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+'-'+f(this.getUTCMonth()+1)+'-'+f(this.getUTCDate())+'T'+f(this.getUTCHours())+':'+f(this.getUTCMinutes())+':'+f(this.getUTCSeconds())+'Z':null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key)}if(typeof rep==='function'){value=rep.call(holder,key,value)}switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null'}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object Array]'){length=value.length;for(i=0;i)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, +Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& +(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, +a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== +"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, +function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
        a"; +var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, +parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= +false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= +s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, +applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; +else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, +a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== +w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, +cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= +c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); +a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, +function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); +k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), +C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B=0){a.type= +e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& +f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; +if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", +e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, +"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, +d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, +e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); +t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| +g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, +CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, +g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, +text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, +setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= +h[3];l=0;for(m=h.length;l=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== +"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, +h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& +q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; +if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="

        ";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); +(function(){var g=s.createElement("div");g.innerHTML="
        ";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: +function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var j=d;j0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= +{},i;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== +"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", +d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? +a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== +1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"},F={option:[1,""],legend:[1,"
        ","
        "],thead:[1,"","
        "],tr:[2,"","
        "],td:[3,"","
        "],col:[2,"","
        "],area:[1,"",""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
        ","
        "];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= +c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, +wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, +prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, +this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); +return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, +""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); +return this}else{e=0;for(var j=d.length;e0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", +""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===""&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= +c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? +c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= +function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= +Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, +"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= +a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= +a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=//gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!== +"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("
        ").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this}, +serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), +function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href, +global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&& +e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)? +"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache=== +false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B= +false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since", +c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E|| +d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x); +g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status=== +1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b=== +"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional; +if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration=== +"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]|| +c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start; +this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now= +this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem, +e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b
        "; +a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b); +c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a, +d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top- +f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset": +"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in +e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window); +/*json2.js*/ +if(!this.JSON){this.JSON={}}(function(){function f(n){return n<10?'0'+n:n}if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+'-'+f(this.getUTCMonth()+1)+'-'+f(this.getUTCDate())+'T'+f(this.getUTCHours())+':'+f(this.getUTCMinutes())+':'+f(this.getUTCSeconds())+'Z':null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key)}if(typeof rep==='function'){value=rep.call(holder,key,value)}switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null'}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object Array]'){length=value.length;for(i=0;i
        ');var typer=$('');var promptBox;var prompt;var promptLabel=config&&config.promptLabel?config.promptLabel:"> ";var column=0;var promptText='';var restoreText='';var history=[];var ringn=0;var cancelKeyPress=0;var extern={};(function(){container.append(inner);inner.append(typer);typer.css({position:'absolute',top:0,left:'-999px'});if(config.welcomeMessage)message(config.welcomeMessage,'jquery-console-welcome');newPromptBox();if(config.autofocus){inner.addClass('jquery-console-focus');typer.focus();setTimeout(function(){inner.addClass('jquery-console-focus');typer.focus()},100)}})();extern.reset=function(){var welcome=true;inner.parent().fadeOut(function(){inner.find('div').each(function(){if(!welcome)$(this).remove();welcome=false});newPromptBox();inner.parent().fadeIn(function(){inner.addClass('jquery-console-focus');typer.focus()})})};function newPromptBox(){column=0;promptText='';promptBox=$('
        ');var label=$('');promptBox.append(label.text(promptLabel).show());prompt=$('');promptBox.append(prompt);inner.append(promptBox);updatePromptDisplay()};container.click(function(){inner.addClass('jquery-console-focus');inner.removeClass('jquery-console-nofocus');typer.focus();scrollToBottom();return false});typer.blur(function(){inner.removeClass('jquery-console-focus');inner.addClass('jquery-console-nofocus')});typer.keydown(function(e){cancelKeyPress=0;var keyCode=e.keyCode;if(isControlCharacter(keyCode)){cancelKeyPress=keyCode;if(!typer.consoleControl(keyCode)){return false}}});typer.keypress(function(e){var keyCode=e.keyCode||e.which;if(cancelKeyPress!=keyCode&&keyCode>=32){if(cancelKeyPress)return false;typer.consoleInsert(keyCode)}if($.browser.webkit)return false});function isControlCharacter(keyCode){return((keyCode>=keyCodes.left&&keyCode<=keyCodes.down)||keyCode==keyCodes.back||keyCode==keyCodes.del||keyCode==keyCodes.end||keyCode==keyCodes.start||keyCode==keyCodes.ret)};typer.consoleControl=function(keyCode){switch(keyCode){case keyCodes.left:{moveColumn(-1);updatePromptDisplay();return false;break}case keyCodes.right:{moveColumn(1);updatePromptDisplay();return false;break}case keyCodes.back:{if(moveColumn(-1)){deleteCharAtPos();updatePromptDisplay()}return false;break}case keyCodes.del:{if(deleteCharAtPos())updatePromptDisplay();return false;break}case keyCodes.end:{if(moveColumn(promptText.length-column))updatePromptDisplay();return false;break}case keyCodes.start:{if(moveColumn(-column))updatePromptDisplay();return false;break}case keyCodes.ret:{commandTrigger();return false}case keyCodes.up:{rotateHistory(-1);return false}case keyCodes.down:{rotateHistory(1);return false}default:}};function rotateHistory(n){if(history.length==0)return;ringn+=n;if(ringn<0)ringn=history.length;else if(ringn>history.length)ringn=0;var prevText=promptText;if(ringn==0){promptText=restoreText}else{promptText=history[ringn-1]}if(config.historyPreserveColumn){if(promptText.length
        ');if(className)mesg.addClass(className);mesg.filledText(msg).hide();inner.append(mesg);mesg.show()};typer.consoleInsert=function(keyCode){var char=String.fromCharCode(keyCode);var before=promptText.substring(0,column);var after=promptText.substring(column);promptText=before+char+after;moveColumn(1);restoreText=promptText;updatePromptDisplay()};function moveColumn(n){if(column+n>=0&&column+n<=promptText.length){column+=n;return true}else return false};function updatePromptDisplay(){var line=promptText;var html='';if(column>0&&line==''){html=cursor}else if(column==promptText.length){html=htmlEncode(line)+cursor}else{var before=line.substring(0,column);var current=line.substring(column,column+1);if(current){current=''+htmlEncode(current)+''}var after=line.substring(column+1);html=htmlEncode(before)+current+htmlEncode(after)}prompt.html(html);scrollToBottom()};function htmlEncode(text){return(text.replace(/&/g,'&').replace(/&]{10})/g,'$1­'+wbr))};return extern};$.fn.filledText=function(txt){$(this).text(txt);$(this).html($(this).html().replace(/\n/g,'
        '));return this}})(jQuery); diff --git a/public/javascripts/mouseapp_2.js b/public/javascripts/mouseapp_2.js new file mode 100755 index 0000000..de5c777 --- /dev/null +++ b/public/javascripts/mouseapp_2.js @@ -0,0 +1,913 @@ +// +// Copyright (c) 2008 why the lucky stiff +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +var MouseApp = { + Version: '0.12', + CharCodes: { + 0: ' ', 1: ' ', 9: ' ', + 32: ' ', 34: '"', 38: '&', + 60: '<', 62: '>', 127: '◊', + 0x20AC: '€' + }, + KeyCodes: { + Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 33, PageDown: 34, + End: 35, Home: 36, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 45, + Delete: 46, F1: 112, F2: 113, F3: 114, F4: 115, F5: 116, F6: 117, + F7: 118, F8: 119, F10: 121 + }, + CodeKeys: {}, + Modes: { 1: 'b', 2: 'u', 4: 'i', 8: 'strike' }, + ModeIds: { r: 1, u: 2, i: 4, s: 8 }, + Colors: ['black', 'blue', 'green', + 'cyan', 'red', 'purple', 'brown', + 'gray', 'dark_gray', 'lt_blue', + 'lt_green', 'lt_cyan', 'lt_red', + 'lt_purple', 'yellow', 'white'] +} +//some of these are patently false, because I need to get on a real keyboard-- not a macbook. +if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1){ + MouseApp.KeyCodes = { + Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, + End: 63275, Home: 63273, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 632325, + Delete: 46, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, + F7: 63242, F8: 63243, F10: 63244 + } + +} + +//even though I am tempted to combine chrome and opera into the same if statment, I will refrain for now +// i dont have proper access to a proper keyboard and there might be a single difference between the two +if (navigator.userAgent.indexOf("Opera") > -1){ + MouseApp.KeyCodes = { + Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, + End: 63275, Home: 63273, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 632325, + Delete: 46, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, + F7: 63242, F8: 63243, F10: 63244 + } + +} + +// i am going to comment this out, since this seems un needed. if it past december 15 2009 and this +// is still commented it, please del me +//if ( navigator.appVersion.indexOf('AppleWebKit') > 0 ) { +// MouseApp.KeyCodes = { +// Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, +// End: 63275, Home: 63273, Left: 63234, Up: 63232, Right: 63235, Down: 63233, Insert: 632325, +// Delete: 63272, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, +// F7: 63242, F8: 63243, F10: 63244 +// };// +//} +for ( var k in MouseApp.KeyCodes ) { + MouseApp.CodeKeys[MouseApp.KeyCodes[k]] = k; +} + +MouseApp.isPrintable = function(ch) { + return (ch >= 32); +}; + +MouseApp.Base = function(){}; +MouseApp.Base.prototype = { + setOptions: function(options) { + this.options = { + columns: 72, rows: 24, indent: 2, + title: 'MouseApp', + blinkRate: 500, + ps: '>', + greeting:'%+r Terminal ready. %-r' + } + $.extend(this.options, options || {}); + } +} + +MouseApp.Manager = new Object(); +$.extend(MouseApp.Manager, { + observeTerm: function(term) { + this.activeTerm = term; + if ( this.observingKeyboard ) return; + var mgr = this; + if ( term.input ) { + term.input.keypress(function(e) { mgr.onKeyPress(e) }); + if (!window.opera) term.input.keydown(function(e) { mgr.onKeyDown(e) }); + else window.setInterval(function(){term.input.focus()},1); + } else { + if (!window.opera) $(document).keydown(function(e) { mgr.onKeyDown(e) }); + $(document).keypress(function(e) { mgr.onKeyPress(e) }); + } + this.observingKeyboard = true; + }, + + onKeyDown: function(e) { + e = (e) ? e : ((event) ? event : null); + if ( e && MouseApp.CodeKeys[e.keyCode] ) { + if ( window.event ) { + this.sendKeyPress(e); + } + this.blockEvent(e); + return false; + } + return true; + }, + + onKeyPress: function(e) { + if ( !window.opera && window.event && e.keyCode != 13 && e.keyCode != 8 ) { + e.charCode = e.keyCode; e.keyCode = null; + } + if ( e.keyCode == 191 ) { /* FF 1.0.x sends this upsy quizy -- ignore */ + return; + } + return this.sendKeyPress(e); + }, + + sendKeyPress: function(e) { + var term = MouseApp.Manager.activeTerm; + term.cursorOff(); + b = term.onKeyPress(e); + term.cursorOn(); + return b; + }, + + blockEvent: function (e) { + e.cancelBubble=true; + if (window.event && !window.opera) e.keyCode=0; + if (e.stopPropagation) e.stopPropagation(); + if (e.preventDefault) e.preventDefault(); + } +}); + +/* Basic text window functionality */ +MouseApp.Window = function(element, options) { + this.element = $(element); + this.setOptions(options); + this.initWindow(); +}; + +$.extend(MouseApp.Window.prototype, (new MouseApp.Base()), { + initWindow: function() { + var html = ''; + for ( var i = 0; i < this.options.rows; i++ ) { + html += "
         
        \n"; + } + this.element.html(html); + this.typingOn(); + if (this.options.input) { + this.input = $(this.options.input); + this.input.focus(); + } + MouseApp.Manager.observeTerm(this); + this.clear(); + this.cursorOn(); + this.painting = true; + this.element.css({visibility: 'visible'}); + }, + + text: function() { + var str = ""; + for (var i = 0; i < this.screen.length; i++ ) { + for (var j = 0; j < this.options.columns; j++ ) { + var ch = this.screen[i][j]; + if ( ch[0] != 0 ) { + str += String.fromCharCode(ch[0]); + } + } + } + return str; + }, + + clear: function() { + this.rpos = 0; + this.cpos = 0; + this.screen = []; + this.element.html(''); + this.screen[0] = this.fillRow(this.options.columns, 0); + this.paint(0); + }, + + typingOn: function() { this.typing = true; }, + typingOff: function() { this.typing = false; }, + + cursorOn: function() { + if ( this.blinker ) { + clearInterval( this.blinker ); + } + this.underblink = this.screen[this.rpos][this.cpos][1]; + MouseApp.Manager.activeTerm.blink(); + this.blinker = setInterval(function(){MouseApp.Manager.activeTerm.blink();}, this.options.blinkRate); + this.cursor = true; + }, + + cursorOff: function() { + if ( this.blinker ) { + clearInterval( this.blinker ); + } + if ( this.cursor ) { + this.screen[this.rpos][this.cpos][1] = this.underblink; + this.paint(this.rpos); + this.cursor = false; + } + }, + + blink: function() { + if ( this == MouseApp.Manager.activeTerm ) { + var mode = this.screen[this.rpos][this.cpos][1]; + this.screen[this.rpos][this.cpos][1] = ( mode & 1 ) ? mode & 4094 : mode | 1; + this.paint(this.rpos); + } + }, + + fillRow: function(len, ch, mode) { + ary = [] + for (var i = 0; i < len; i++) { + ary[i] = [ch, mode]; + } + return ary; + }, + + paint: function(start, end) { + if (!this.painting) return; + + if (!end) end = start; + for (var row = start; row <= end && row < this.screen.length; row++) { + var html = ''; + var mode = 0; + var fcolor = 0; + var bcolor = 0; + var spans = 0; + for (var i = 0; i < this.options.columns; i++ ) { + var c = this.screen[row][i][0]; + var m = this.screen[row][i][1] & 15; // 4 mode bits + var f = (this.screen[row][i][1] & (15 << 4)) >> 4; // 4 foreground bits + var b = (this.screen[row][i][1] & (15 << 8)) >> 8; // 4 background bits + if ( m != mode ) { + if ( MouseApp.Modes[mode] ) html += ""; + if ( MouseApp.Modes[m] ) html += "<" + MouseApp.Modes[m] + ">"; + mode = m; + } + if ( ( f != fcolor && f == 0 ) || ( b != bcolor && b == 0 ) ) { + for ( var s = 0; s < spans; s++ ) html += ""; + fcolor = 0; bcolor = 0; + } + if ( f != fcolor ) { + if ( MouseApp.Colors[f] ) { + html += ""; + spans++; + } + fcolor = f; + } + if ( b != bcolor ) { + if ( MouseApp.Colors[b] ) html += ""; + spans++; bcolor = b; + } + html += MouseApp.CharCodes[c] ? MouseApp.CharCodes[c] : String.fromCharCode(c); + } + if ( MouseApp.Modes[mode] ) html += ""; + for ( var s = 0; s < spans; s++ ) html += ""; + var new_id = this.element.attr('id') + '_' + row; + if (!$('#' + new_id).get(0)) { + this.element.append("
         
        "); + this.scrollAllTheWayDown(); + } + $('#' + new_id).html(html); + } + }, + + onAfterKey: function() { + this.scrollAllTheWayDown(); + }, + + highlightLine: function(i) { + if (i >= 0 && i < this.screen.length) + { + $("#" + this.element.attr('id') + "_" + i); + } + }, + + scrollToLine: function(i) { + var p = this.element[0].parentNode; + if ( p.scrollHeight > p.clientHeight ) { + p.scrollTop = (p.scrollHeight - p.clientHeight); + } + }, + + scrollAllTheWayDown: function() { + var p = this.element[0].parentNode; + if ( p.scrollHeight > p.clientHeight ) { + p.scrollTop = (p.scrollHeight - p.clientHeight); + } + }, + + putc: function(ch, mode) { + if ( ch == 13 ) { + return; + } else if ( ch == 10 ) { + this.screen[this.rpos][this.cpos] = [ch, mode]; + this.advanceLine(); + } else { + this.screen[this.rpos][this.cpos] = [ch, mode]; + this.paint(this.rpos); + this.advance(); + } + }, + + zpad: function(n) { + if (n < 10) n = "0" + n; + return n; + }, + + puts: function(str, mode) { + if ( !str ) return; + var p = this.painting; + var r = this.rpos; + this.painting = false; + for ( var i = 0; i < str.length; i++ ) { + this.insertc(str.charCodeAt(i), mode); + } + this.painting = p; + this.paint(r, this.rpos); + }, + + advance: function() { + this.cpos++; + if ( this.cpos >= this.options.columns ) { + this.advanceLine(); + } + }, + + advanceLine: function() { + this.cpos = 0; + this.rpos++; + this.ensureRow(this.rpos); + this.paint(this.rpos, this.screen.length - 1); + }, + + fwdc: function() { + var r = this.rpos; + var c = this.cpos; + if ( c < this.options.columns - 1 ) { + c++; + } else if ( r < this.screen.length - 1 ) { + r++; + c = 0; + } + var ch = (c == 0 ? this.screen[r-1][this.options.columns-1] : this.screen[r][c-1]); + if ( MouseApp.isPrintable(ch[0]) ) { + this.rpos = r; + this.cpos = c; + } + }, + + fwdLine: function() { + if ( this.rpos >= this.screen.length - 1 ) return; + this.rpos++; + while ( this.cpos > 0 && !MouseApp.isPrintable(this.screen[this.rpos][this.cpos - 1][0]) ) { + this.cpos--; + } + }, + + backc: function() { + var r = this.rpos; + var c = this.cpos; + if ( c > 0 ) { + c--; + } else if ( r > 0 ) { + c = this.options.columns - 1; + r--; + } + if ( MouseApp.isPrintable(this.screen[r][c][0]) ) { + this.rpos = r; + this.cpos = c; + return true; + } + return false; + }, + + getTypingStart: function() { + var c = this.cpos; + if ( !MouseApp.isPrintable(this.screen[this.rpos][c][0]) ) { + c--; + } + var pos = null; + for ( var r = this.rpos; r >= 0; r-- ) { + while ( c >= 0 ) { + if ( !MouseApp.isPrintable(this.screen[r][c][0]) ) { + return pos; + } + pos = [r, c]; + c--; + } + c = this.options.columns - 1; + } + }, + + getTypingEnd: function(mod) { + var c = this.cpos; + if ( !MouseApp.isPrintable(this.screen[this.rpos][c][0]) ) { + c--; + } + var pos = null; + for ( var r = this.rpos; r < this.screen.length; r++ ) { + while ( c < this.options.columns ) { + if ( !this.screen[r] || !this.screen[r][c] || !MouseApp.isPrintable(this.screen[r][c][0]) ) { + if (!mod) return pos; + mod--; + } + pos = [r, c]; + c++; + } + c = 0; + } + }, + + getTypingAt: function(start, end) { + var r = start[0]; + var c = start[1]; + var str = ''; + while ( r < end[0] || c <= end[1] ) { + if ( c < this.options.columns ) { + str += String.fromCharCode(this.screen[r][c][0]); + c++; + } else { + c = 0; + r++; + } + } + return str; + }, + + ensureRow: function(r) { + if (!this.screen[r]) { + this.screen[r] = this.fillRow(this.options.columns, 0); + } + }, + + insertc: function(ch, mode) { + var r = this.rpos; var c = this.cpos; + var end = this.getTypingEnd(+1); + if (end) { + var thisc = null; + var lastc = this.screen[this.rpos][this.cpos]; + while ( r < end[0] || c <= end[1] ) { + if ( c < this.options.columns ) { + thisc = this.screen[r][c]; + this.screen[r][c] = lastc; + lastc = thisc; + c++; + } else { + c = 0; + r++; + this.ensureRow(r); + } + } + this.paint(this.rpos, end[0]); + } + this.putc(ch, mode); + }, + + delc: function() { + /* end of line */ + if ( MouseApp.isPrintable(this.screen[this.rpos][this.cpos][0]) ) { + var end = this.getTypingEnd(); + var thisc = null; + var lastc = [0, 0]; + while ( this.rpos < end[0] || this.cpos <= end[1] ) { + if ( end[1] >= 0 ) { + thisc = this.screen[end[0]][end[1]]; + this.screen[end[0]][end[1]] = lastc; + lastc = thisc; + end[1]--; + } else { + end[1] = this.options.columns - 1; + this.paint(end[0]); + end[0]--; + } + } + } + }, + + backspace: function() { + /* end of line */ + if ( !MouseApp.isPrintable(this.screen[this.rpos][this.cpos][0]) ) { + this.backc(); + this.screen[this.rpos][this.cpos] = [0, 0]; + } else { + if ( this.backc() ) this.delc(); + } + }, + + backLine: function() { + if ( this.rpos < 1 ) return; + this.rpos--; + while ( this.cpos > 0 && !MouseApp.isPrintable(this.screen[this.rpos][this.cpos - 1][0]) ) { + this.cpos--; + } + }, + + onKeyPress: function(e) { + var ch = e.keyCode; + var key_name = MouseApp.CodeKeys[ch]; + if (window.opera && !e.altKey && e.keyCode != 13 && e.keyCode != 8) key_name = null; + ch = (e.which || e.charCode || e.keyCode); + if (e.which) ch = e.which; + if (!key_name) { key_name = String.fromCharCode(ch); } + if (e.ctrlKey) { key_name = 'Ctrl' + key_name; } + + // alert([e.keyCode, e.which, key_name, this['onKey' + key_name]]); + if (this.typing && this.onAnyKey) this.onAnyKey(key_name); + if (key_name && this['onKey' + key_name]) { + if (this.typing) this['onKey' + key_name](); + MouseApp.Manager.blockEvent(e); + if (this.typing && this.onAfterKey) this.onAfterKey(key_name, true); + return false; + } + if (!e.ctrlKey) { + if (MouseApp.isPrintable(ch)) { + if (this.typing) this.insertc(ch, 0); + MouseApp.Manager.blockEvent(e); + if (this.typing && this.onAfterKey) this.onAfterKey(key_name, true); + return false; + } + } + if (this.typing && this.onAfterKey) this.onAfterKey(key_name, false); + return true; + }, + onKeyHome: function() { + var s = this.getTypingStart(); + this.rpos = s[0]; this.cpos = s[1]; + }, + onKeyEnd: function() { + var e = this.getTypingEnd(+1); + this.rpos = e[0]; this.cpos = e[1]; + }, + onKeyInsert: function() { }, + onKeyDelete: function() { this.delc(); }, + onKeyUp: function() { this.backLine(); }, + onKeyLeft: function() { this.backc(); }, + onKeyRight: function() { this.fwdc(); }, + onKeyDown: function() { this.fwdLine(); }, + onKeyBackspace: function() { this.backspace(); }, + onKeyEnter: function() { this.insertc(10, 0); }, + onKeyTab: function() { + this.insertc(32, 0); + while (this.cpos % this.options.indent != 0) this.insertc(32, 0); + } +}); + +/* Terminal running moush */ +MouseApp.Terminal = function(element, options) { + this.element = $(element); + this.setOptions(options); + this.initWindow(); + this.setup(); +}; + +$.extend(MouseApp.Terminal.prototype, MouseApp.Window.prototype, { + setup: function() { + this.history = []; + this.backupNum = this.historyNum = this.commandNum = 0; + if (this.onStart) { + this.onStart(); + } else { + this.write(this.options.greeting + "\n", true); + this.prompt(); + } + }, + + prompt: function(ps, pt) { + if (!ps) { + ps = this.options.ps; pt = true; + } + this.write(ps, pt); + this.putc(1, 0); + this.typingOn(); + }, + + getCommand: function() { + var s = this.getTypingStart(); + var e = this.getTypingEnd(); + if (!s || !e) return; + return this.getTypingAt(s, e); + }, + + clearCommand: function() { + var s = this.getTypingStart(); + var e = this.getTypingEnd(); + if (!s || !e) return; + var r = s[0]; + var c = s[1]; + this.rpos = r; this.cpos = c; + while ( r < e[0] || c <= e[1] ) { + if ( c < this.options.columns ) { + this.screen[r][c] = [0, 0]; + c++; + } else { + c = 0; + this.paint(r); + r++; + } + } + this.paint(r); + }, + + write: function(str, pcodes) { + var p = this.painting; + var r = this.rpos; + this.painting = false; + var mode = 0; + var today = new Date(); + for ( var i = 0; i < str.length; i++ ) { + if ( str.substr(i,1) == "\n" ) { + this.advanceLine(); + continue; + } else if ( str.substr(i,1) == "\033" ) { + if ( str.substr(i+1,2) == "[m" ) { + mode = 0; + i += 2; + continue; + } + if ( str.substr(i+1,5) == "[0;0m" ) { + mode = 0; + i += 5; + continue; + } + var colors = str.substr(i+1,7).match(/^\[(\d);(\d+)m/); + if ( colors ) { + var colCode = parseInt( colors[2] ); + var color = colCode % 10; + if ( colors[1] == '1' ) { + color += 8; + } + if ( colCode / 10 == 4 ) { + color = color << 4; + } + mode = (mode & 15) + color << 4; + i += colors[0].length; + continue; + } + } else if ( str.substr(i,1) == '%' && pcodes ) { + var s2 = str.substr(i,2); + switch ( s2 ) { + case '%h': + this.puts(this.options.host, mode); + i++; + continue; + case '%l': + this.puts(this.options.name, mode); + i++; + continue; + case '%n': + this.advanceLine(); + i++; + continue; + case '%s': + this.puts("moush", mode); + i++; + continue; + case '%t': + this.puts(this.zpad(today.getHours()) + ":" + this.zpad(today.getMinutes()) + ":" + + this.zpad(today.getSeconds()), mode); + i++; + continue; + case '%u': + this.puts(this.options.user, mode); + i++; + continue; + case '%v': + this.puts(MouseApp.Version, mode); + i++; + continue; + case '%!': + this.puts(this.historyNum.toString(), mode); + i++; + continue; + case '%#': + this.puts(this.commandNum.toString(), mode); + i++; + continue; + case '%+': + var kind = str.substr(i+2, 1); + if ( MouseApp.ModeIds[kind] ) { + mode = mode | MouseApp.ModeIds[kind]; + i += 2; + continue; + } + break; + case '%-': + var kind = str.substr(i+2, 1); + if ( MouseApp.ModeIds[kind] ) { + mode = mode & ( 4095 - MouseApp.ModeIds[kind] ); + i += 2; + continue; + } + break; + } + } + this.putc(str.charCodeAt(i), mode); + } + this.painting = p; + this.paint(r, this.rpos); + }, + + onKeyUp: function() { + if ( this.backupNum == 0 ) return; + if ( this.backupNum == this.historyNum ) { + this.history[this.historyNum] = this.getCommand(); + } + this.clearCommand(); + this.backupNum--; + this.puts(this.history[this.backupNum]); + }, + onKeyDown: function() { + if ( this.backupNum >= this.historyNum ) return; + this.clearCommand(); + this.backupNum++; + this.puts(this.history[this.backupNum]); + }, + onKeyEnter: function() { + var cmd = this.getCommand(); + if (cmd) { + this.history[this.historyNum] = cmd; + this.backupNum = ++this.historyNum; + } + this.commandNum++; + this.advanceLine(); + if (cmd) { + var str = this.onCommand(cmd); + if (str) { + if ( str.substr(str.length - 1, 1) != "\n" ) { + str += "\n"; + } + this.write(str); + } + } + this.prompt(); + }, + onCommand: function(line) { + // this.puts("Echoing: " + line + "\n"); + if ( line == "clear" ) { + this.clear(); + } else { + return "\033[1;37m\033[0;44mYou typed:\033[m " + line; + } + } +}); + +/* Notepad sort of editor */ +MouseApp.Notepad = function(element, options) { + this.element = $(element); + this.setOptions(options); + this.initWindow(); + this.history = []; + this.lineno = 0; +}; + +$.extend(MouseApp.Notepad.prototype, MouseApp.Window.prototype, { + csave: function() { + if ( this.cpos_save ) { + this.cpos = this.cpos_save; + } else { + this.cpos_save = this.cpos; + } + }, + onKeyUp: function() { if ( this.rpos < 1 ) { return; } this.csave(); this.backLine(); }, + onKeyDown: function() { if ( this.rpos < this.screen.length - 1 ) { this.csave(); this.fwdLine(); } }, + onAfterKey: function(key, st) { + if ( st && !(key == 'Up' || key == 'Down') ) { + this.cpos_save = null; + } + }, + insertc: function(ch, mode) { + if (ch == 10) { + this.element.append("
         
        "); + this.screen.splice(this.rpos + 1, 0, this.fillRow(this.options.columns, 0)); + var c = this.cpos; var c2 = 0; + while (c < this.options.columns) + { + if (this.screen[this.rpos][c] == 0) break; + this.screen[this.rpos + 1][c2] = this.screen[this.rpos][c]; + this.screen[this.rpos][c] = [0, 0]; + c++; c2++; + } + this.paint(this.rpos); + if (MouseApp.isPrintable(this.screen[this.rpos][c])) + { + var r = this.rpos; var c = this.cpos; + this.rpos += 1; this.cpos = c2; + this.delc(); + this.rpos = r; this.cpos = c; + } + this.putc(ch, mode); + if (this.rpos == this.screen.length - 1) + this.scrollAllTheWayDown(); + } else { + var c = this.cpos + 1; + var lastc = this.screen[this.rpos][this.cpos]; + this.putc(ch, mode); + for ( var r = this.rpos; r < this.screen.length; r++ ) { + while (c < this.options.columns) + { + var tmpc = this.screen[r][c]; + if (lastc[0] == 0) + break; + this.screen[r][c] = lastc; + lastc = tmpc; + c++; + } + if (c < this.options.columns) { + break; + } + c = 0; + } + } + }, + + backc: function() { + var r = this.rpos; + var c = this.cpos - 1; + for ( var r = this.rpos; r >= 0; r-- ) { + while ( c >= 0 ) { + this.rpos = r; + this.cpos = c; + if ( this.screen[r][c][0] != 0 ) { + this.paint(r); + return true; + } + this.screen[r][c] = [0, 0]; + c--; + } + c = this.options.columns - 1; + } + return false; + }, + delc: function() { + var c = this.cpos + 1; + for ( var r = this.rpos; r < this.screen.length; r++ ) { + while ( c < this.options.columns ) { + if ( this.screen[r][c][0] != 0 ) { + break; + } + c++; + } + if ( c < this.options.columns ) break; + c = 0; + } + + if (r >= this.screen.length) return; + + var r2 = this.rpos; + var c2 = this.cpos; + for ( var r2 = this.rpos; r2 < this.screen.length; r2++ ) { + while (c2 < this.options.columns) + { + if (this.screen[r][c][0] == 0) + break; + this.screen[r2][c2] = this.screen[r][c]; + c2++; + c++; + if (c >= this.options.columns) { + r++; + if (r >= this.options.rows) break; + c = 0; + } + } + if (c2 < this.options.columns) { + while (c2 < this.options.columns) { + this.screen[r2][c2] = [0, 0]; + c2++; + } + break; + } + c2 = 0; + } + + if (r != r2 && r < this.screen.length) + { + this.screen.splice(r, 1); + $("#" + this.element.attr('id') + "_" + this.screen.length).remove(); + } + this.paint(this.rpos, this.screen.length); + }, + onKeyBackspace: function() { + if (this.backc()) this.delc(); + } + +}); diff --git a/public/javascripts/mouseirb_2.js b/public/javascripts/mouseirb_2.js new file mode 100755 index 0000000..0fa5f12 --- /dev/null +++ b/public/javascripts/mouseirb_2.js @@ -0,0 +1,179 @@ +// +// Copyright (c) 2008 why the lucky stiff +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// + +/* Irb running moush */ +MouseApp.Irb = function(element, options) { + this.element = $(element); + this.setOptions(options); + this.showHelp = this.options.showHelp; + if ( this.options.showChapter ) { + this.showChapter = this.options.showChapter; + } + if ( this.options.init ) { + this.init = this.options.init; + } + this.initWindow(); + this.setup(); + this.helpPage = null; + this.irbInit = false; +}; + +$.extend(MouseApp.Irb.prototype, MouseApp.Terminal.prototype, { + cmdToQuery: function(cmd) { + return "cmd=" + escape(cmd.replace(/</g, '<').replace(/>/g, '>'). + replace(/&/g, '&').replace(/\r?\n/g, "\n")).replace(/\+/g, "%2B"); + }, + + fireOffCmd: function(cmd, func) { + var irb = this; + if (!this.irbInit) + { + $.ajax({url: this.options.irbUrl + "?" + this.cmdToQuery("!INIT!IRB!"), type: "GET", + complete: (function(r) { irb.irbInit = true; irb.fireOffCmd(cmd, func); })}); + } + else + { + $.ajax({url: this.options.irbUrl + "?" + this.cmdToQuery(cmd), type: "GET", + complete: func}); + } + }, + + reply: function(str) { + var raw = str.replace(/\033\[(\d);(\d+)m/g, ''); + this.checkAnswer(raw); + if (!str.match(/^(\.\.)+$/)) { + if ( str[str.length - 1] != "\n" ) { + str += "\n"; + } + js_payload = /\033\[1;JSm(.*)\033\[m/; + js_in = str.match(js_payload); + if (js_in) { + try { + js_in = eval(js_in[1]); + } catch (e) {} + str = str.replace(js_payload, ''); + } + var pr_re = new RegExp("(^|\\n)=>"); + if ( str.match( pr_re ) ) { + str = str.replace(new RegExp("(^|\\n)=>"), "$1\033[1;34m=>\033[m"); + } else { + str = str.replace(new RegExp("(^|\\n)= (.+?) ="), "$1\033[1;33m$2\033[m"); + } + this.write(str); + this.prompt(); + } else { + this.prompt("\033[1;32m" + ".." + "\033[m", true); + this.puts(str.replace(/\./g, ' '), 0); + } + }, + + setHelpPage: function(n, page) { + if (this.helpPage) + $(this.helpPage.ele).hide('fast'); + this.helpPage = {index: n, ele: page}; + match = this.scanHelpPageFor('load'); + if (match != -1) + { + this.fireOffCmd(match, (function(r) { + $(page).show('fast'); + })); + } + else + { + $(page).show('fast'); + } + }, + + scanHelpPageFor: function(eleClass) { + match = $("div." + eleClass, this.helpPage.ele); + if ( match[0] ) return match[0].innerHTML; + else return -1; + }, + + checkAnswer: function(str) { + if ( this.helpPage ) { + match = this.scanHelpPageFor('answer'); + if ( match != -1 ) { + if ( str.match( new RegExp('^\s*=> ' + match + '\s*$', 'm') ) ) { + this.showHelp(this.helpPage.index + 1); + } + } else { + match = this.scanHelpPageFor('stdout'); + if ( match != -1 ) { + if ( match == '' ) { + if ( str == '' || str == null ) this.showHelp(this.helpPage.index + 1); + } else if ( str.match( new RegExp('^\s*' + match + '$', 'm') ) ) { + this.showHelp(this.helpPage.index + 1); + } + } + } + } + }, + + onKeyCtrld: function() { + this.clearCommand(); + this.puts("reset"); + this.onKeyEnter(); + }, + + onKeyEnter: function() { + this.typingOff(); + var cmd = this.getCommand(); + if (cmd) { + this.history[this.historyNum] = cmd; + this.backupNum = ++this.historyNum; + } + this.commandNum++; + this.advanceLine(); + if (cmd) { + if ( cmd == "clear" ) { + this.clear(); + this.prompt(); + } else if ( cmd.match(/^(back)$/) ) { + if (this.helpPage && this.helpPage.index >= 1) { + this.showHelp(this.helpPage.index - 1); + } + this.prompt(); + } else if ( cmd.match(/^(next)$/) ) { + if (this.helpPage) { + this.showHelp(this.helpPage.index + 1); + } + this.prompt(); + } else if ( cmd.match(/^(help|wtf\?*)$/) ) { + this.showHelp(1); + this.prompt(); + } else if ( regs = cmd.match(/^(help|wtf\?*)\s+#?(\d+)\s*$/) ) { + this.showChapter(parseInt(regs[2])); + this.prompt(); + } else { + var term = this; + this.fireOffCmd(cmd, (function(r) { term.reply(r.responseText ? r.responseText : ''); })); + } + } else { + this.prompt(); + } + } +}); + diff --git a/public/javascripts/raphael-min.js b/public/javascripts/raphael-min.js new file mode 100644 index 0000000..4a99e3e --- /dev/null +++ b/public/javascripts/raphael-min.js @@ -0,0 +1,113 @@ +/* + * Raphael 1.4.3 - JavaScript Vector Library + * + * Copyright (c) 2010 Dmitry Baranovskiy (http://raphaeljs.com) + * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. + */ +Raphael=function(){function m(){if(m.is(arguments[0],U)){for(var a=arguments[0],b=Aa[K](m,a.splice(0,3+m.is(a[0],O))),c=b.set(),d=0,f=a[o];d

        ";if(ha.childNodes[o]!=2)return m.type=null;ha=null}m.svg=!(m.vml=m.type=="VML");G[p]=m[p];m._id=0;m._oid=0;m.fn={};m.is=function(a,b){b=ca.call(b);return b=="object"&&a===Object(a)||b=="undefined"&&typeof a==b||b=="null"&&a==null||ca.call(ob.call(a).slice(8,-1))==b};m.setWindow=function(a){X=a;C=X.document};function ra(a){if(m.vml){var b=/^\s+|\s+$/g;ra=T(function(d){var f;d=(d+s)[I](b, +s);try{var e=new X.ActiveXObject("htmlfile");e.write("");e.close();f=e.body}catch(g){f=X.createPopup().document.body}e=f.createTextRange();try{f.style.color=d;var h=e.queryCommandValue("ForeColor");h=(h&255)<<16|h&65280|(h&16711680)>>>16;return"#"+("000000"+h[N](16)).slice(-6)}catch(i){return"none"}})}else{var c=C.createElement("i");c.title="Rapha\u00ebl Colour Picker";c.style.display="none";C.body[y](c);ra=T(function(d){c.style.color=d;return C.defaultView.getComputedStyle(c,s).getPropertyValue("color")})}return ra(a)} +function qb(){return"hsb("+[this.h,this.s,this.b]+")"}function rb(){return this.hex}m.hsb2rgb=T(function(a,b,c){if(m.is(a,"object")&&"h"in a&&"s"in a&&"b"in a){c=a.b;b=a.s;a=a.h}var d;if(c==0)return{r:0,g:0,b:0,hex:"#000"};if(a>1||b>1||c>1){a/=255;b/=255;c/=255}d=~~(a*6);a=a*6-d;var f=c*(1-b),e=c*(1-b*a),g=c*(1-b*(1-a));a=[c,e,f,f,g,c,c][d];b=[g,c,c,e,f,f,g][d];d=[f,f,g,c,c,e,f][d];a*=255;b*=255;d*=255;c={r:a,g:b,b:d,toString:rb};a=(~~a)[N](16);b=(~~b)[N](16);d=(~~d)[N](16);a=a[I](ga,"0");b=b[I](ga, +"0");d=d[I](ga,"0");c.hex="#"+a+b+d;return c},m);m.rgb2hsb=T(function(a,b,c){if(m.is(a,"object")&&"r"in a&&"g"in a&&"b"in a){c=a.b;b=a.g;a=a.r}if(m.is(a,ea)){var d=m.getRGB(a);a=d.r;b=d.g;c=d.b}if(a>1||b>1||c>1){a/=255;b/=255;c/=255}var f=Y(a,b,c),e=$(a,b,c);d=f;if(e==f)return{h:0,s:0,b:f};else{var g=f-e;e=g/f;a=a==f?(b-c)/g:b==f?2+(c-a)/g:4+(a-b)/g;a/=6;a<0&&a++;a>1&&a--}return{h:a,s:e,b:d,toString:qb}},m);var sb=/,?([achlmqrstvxz]),?/gi,sa=/\s*,\s*/,tb={hs:1,rg:1};m._path2string=function(){return this.join(",")[I](sb, +"$1")};function T(a,b,c){function d(){var f=Array[p].slice.call(arguments,0),e=f[Q]("\u25ba"),g=d.cache=d.cache||{},h=d.count=d.count||[];if(g[z](e))return c?c(g[e]):g[e];h[o]>=1000&&delete g[h.shift()];h[E](e);g[e]=a[K](b,f);return c?c(g[e]):g[e]}return d}m.getRGB=T(function(a){if(!a||(a+=s).indexOf("-")+1)return{r:-1,g:-1,b:-1,hex:"none",error:1};if(a=="none")return{r:-1,g:-1,b:-1,hex:"none"};!(tb[z](a.substring(0,2))||a.charAt()=="#")&&(a=ra(a));var b,c,d,f,e;if(a=a.match(pb)){if(a[2]){d=da(a[2].substring(5), +16);c=da(a[2].substring(3,5),16);b=da(a[2].substring(1,3),16)}if(a[3]){d=da((e=a[3].charAt(3))+e,16);c=da((e=a[3].charAt(2))+e,16);b=da((e=a[3].charAt(1))+e,16)}if(a[4]){a=a[4][H](sa);b=A(a[0]);c=A(a[1]);d=A(a[2]);f=A(a[3])}if(a[5]){a=a[5][H](sa);b=A(a[0])*2.55;c=A(a[1])*2.55;d=A(a[2])*2.55;f=A(a[3])}if(a[6]){a=a[6][H](sa);b=A(a[0]);c=A(a[1]);d=A(a[2]);return m.hsb2rgb(b,c,d)}if(a[7]){a=a[7][H](sa);b=A(a[0])*2.55;c=A(a[1])*2.55;d=A(a[2])*2.55;return m.hsb2rgb(b,c,d)}a={r:b,g:c,b:d};b=(~~b)[N](16); +c=(~~c)[N](16);d=(~~d)[N](16);b=b[I](ga,"0");c=c[I](ga,"0");d=d[I](ga,"0");a.hex="#"+b+c+d;isFinite(A(f))&&(a.o=f);return a}return{r:-1,g:-1,b:-1,hex:"none",error:1}},m);m.getColor=function(a){a=this.getColor.start=this.getColor.start||{h:0,s:1,b:a||0.75};var b=this.hsb2rgb(a.h,a.s,a.b);a.h+=0.075;if(a.h>1){a.h=0;a.s-=0.2;a.s<=0&&(this.getColor.start={h:0,s:1,b:a.b})}return b.hex};m.getColor.reset=function(){delete this.start};var ub=/([achlmqstvz])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig, +vb=/(-?\d*\.?\d*(?:e[-+]?\d+)?)\s*,?\s*/ig;m.parsePathString=T(function(a){if(!a)return null;var b={a:7,c:6,h:1,l:2,m:2,q:4,s:4,t:2,v:1,z:0},c=[];if(m.is(a,U)&&m.is(a[0],U))c=ta(a);c[o]||(a+s)[I](ub,function(d,f,e){var g=[];d=ca.call(f);e[I](vb,function(h,i){i&&g[E](+i)});if(d=="m"&&g[o]>2){c[E]([f][M](g.splice(0,2)));d="l";f=f=="m"?"l":"L"}for(;g[o]>=b[d];){c[E]([f][M](g.splice(0,b[d])));if(!b[d])break}});c[N]=m._path2string;return c});m.findDotsAtSegment=function(a,b,c,d,f,e,g,h,i){var j=1-i,l= +D(j,3)*a+D(j,2)*3*i*c+j*3*i*i*f+D(i,3)*g;j=D(j,3)*b+D(j,2)*3*i*d+j*3*i*i*e+D(i,3)*h;var n=a+2*i*(c-a)+i*i*(f-2*c+a),r=b+2*i*(d-b)+i*i*(e-2*d+b),q=c+2*i*(f-c)+i*i*(g-2*f+c),k=d+2*i*(e-d)+i*i*(h-2*e+d);a=(1-i)*a+i*c;b=(1-i)*b+i*d;f=(1-i)*f+i*g;e=(1-i)*e+i*h;h=90-w.atan((n-q)/(r-k))*180/w.PI;(n>q||r1){B=w.sqrt(B);c=B*c;d=B*d}B=c*c;var L=d*d;B=(e==g?-1:1)*w.sqrt(w.abs((B*L-B*x*x-L*k*k)/(B*x*x+L*k*k)));e=B*c*x/d+(a+h)/2;var B= +B*-d*k/c+(b+i)/2,x=w.asin(((b-B)/d).toFixed(7));k=w.asin(((i-B)/d).toFixed(7));x=ak)x-=l*2;if(!g&&k>x)k-=l*2}l=k-x;if(w.abs(l)>n){q=k;l=h;L=i;k=x+n*(g&&k>x?1:-1);h=e+c*w.cos(k);i=B+d*w.sin(k);q=Qa(h,i,c,d,f,0,g,l,L,[k,q,e,B])}l=k-x;f=w.cos(x);e=w.sin(x);g=w.cos(k);k=w.sin(k);l=w.tan(l/4);c=4/3*c*l;l=4/3*d*l;d=[a,b];a=[a+c*e,b-l*f];b=[h+c*k,i-l*g];h=[h,i];a[0]=2*d[0]-a[0];a[1]=2*d[1]-a[1];if(j)return[a,b,h][M](q);else{q=[a,b,h][M](q)[Q]()[H](","); +j=[];h=0;for(i=q[o];h1000000000000&&(n=0.5);w.abs(i)>1000000000000&&(i=0.5);if(n>0&&n<1){n=la(a,b,c,d,f,e,g,h,n);q[E](n.x);r[E](n.y)}if(i> +0&&i<1){n=la(a,b,c,d,f,e,g,h,i);q[E](n.x);r[E](n.y)}i=e-2*d+b-(h-2*e+d);j=2*(d-b)-2*(e-d);l=b-d;n=(-j+w.sqrt(j*j-4*i*l))/2/i;i=(-j-w.sqrt(j*j-4*i*l))/2/i;w.abs(n)>1000000000000&&(n=0.5);w.abs(i)>1000000000000&&(i=0.5);if(n>0&&n<1){n=la(a,b,c,d,f,e,g,h,n);q[E](n.x);r[E](n.y)}if(i>0&&i<1){n=la(a,b,c,d,f,e,g,h,i);q[E](n.x);r[E](n.y)}return{min:{x:$[K](0,q),y:$[K](0,r)},max:{x:Y[K](0,q),y:Y[K](0,r)}}}),ua=T(function(a,b){var c=ka(a),d=b&&ka(b);a={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null};b={x:0,y:0, +bx:0,by:0,X:0,Y:0,qx:null,qy:null};function f(q,k){var t;if(!q)return["C",k.x,k.y,k.x,k.y,k.x,k.y];!(q[0]in{T:1,Q:1})&&(k.qx=k.qy=null);switch(q[0]){case "M":k.X=q[1];k.Y=q[2];break;case "A":q=["C"][M](Qa[K](0,[k.x,k.y][M](q.slice(1))));break;case "S":t=k.x+(k.x-(k.bx||k.x));k=k.y+(k.y-(k.by||k.y));q=["C",t,k][M](q.slice(1));break;case "T":k.qx=k.x+(k.x-(k.qx||k.x));k.qy=k.y+(k.y-(k.qy||k.y));q=["C"][M](Pa(k.x,k.y,k.qx,k.qy,q[1],q[2]));break;case "Q":k.qx=q[1];k.qy=q[2];q=["C"][M](Pa(k.x,k.y,q[1], +q[2],q[3],q[4]));break;case "L":q=["C"][M](wa(k.x,k.y,q[1],q[2]));break;case "H":q=["C"][M](wa(k.x,k.y,q[1],k.y));break;case "V":q=["C"][M](wa(k.x,k.y,k.x,q[1]));break;case "Z":q=["C"][M](wa(k.x,k.y,k.X,k.Y));break}return q}function e(q,k){if(q[k][o]>7){q[k].shift();for(var t=q[k];t[o];)q.splice(k++,0,["C"][M](t.splice(0,6)));q.splice(k,1);i=Y(c[o],d&&d[o]||0)}}function g(q,k,t,L,B){if(q&&k&&q[B][0]=="M"&&k[B][0]!="M"){k.splice(B,0,["M",L.x,L.y]);t.bx=0;t.by=0;t.x=q[B][1];t.y=q[B][2];i=Y(c[o],d&& +d[o]||0)}}for(var h=0,i=Y(c[o],d&&d[o]||0);h0.5)*2-1;D(f-0.5,2)+D(e-0.5,2)>0.25&&(e=w.sqrt(0.25-D(f-0.5,2))*l+0.5)&&e!=0.5&&(e=e.toFixed(5)-1.0E-5*l)}return s});b=b[H](/\s*\-\s*/);if(d=="linear"){var h=b.shift();h=-A(h);if(isNaN(h))return null;h=[0,0,w.cos(h*w.PI/180),w.sin(h*w.PI/180)];var i=1/(Y(w.abs(h[2]),w.abs(h[3]))||1);h[2]*=i;h[3]*=i;if(h[2]<0){h[0]=-h[2];h[2]=0}if(h[3]<0){h[1]=-h[3];h[3]=0}}b=Ra(b);if(!b)return null; +i=a.getAttribute(aa);(i=i.match(/^url\(#(.*)\)$/))&&c.defs.removeChild(C.getElementById(i[1]));i=v(d+"Gradient");i.id="r"+(m._id++)[N](36);v(i,d=="radial"?{fx:f,fy:e}:{x1:h[0],y1:h[1],x2:h[2],y2:h[3]});c.defs[y](i);c=0;for(h=b[o];cb.height&&(b.height=e.y+e.height-b.y);e.x+e.width-b.x>b.width&&(b.width=e.x+e.width-b.x)}}a&&this.hide();return b};u[p].attr=function(a,b){if(this.removed)return this;if(a==null){a={};for(var c in this.attrs)if(this.attrs[z](c))a[c]=this.attrs[c];this._.rt.deg&&(a.rotation=this.rotate());(this._.sx!=1||this._.sy!= +1)&&(a.scale=this.scale());a.gradient&&a.fill=="none"&&(a.fill=a.gradient)&&delete a.gradient;return a}if(b==null&&m.is(a,ea)){if(a=="translation")return ya.call(this);if(a=="rotation")return this.rotate();if(a=="scale")return this.scale();if(a==aa&&this.attrs.fill=="none"&&this.attrs.gradient)return this.attrs.gradient;return this.attrs[a]}if(b==null&&m.is(a,U)){b={};c=0;for(var d=a.length;c1&&(a=1);f.opacity=a}b.fill&&(f.on=true);if(f.on==null||b.fill=="none")f.on=false;if(f.on&&b.fill)if(a=b.fill.match(Na)){f.src=a[1];f.type="tile"}else{f.color=m.getRGB(b.fill).hex;f.src= +s;f.type="solid";if(m.getRGB(b.fill).error&&(g.type in{circle:1,ellipse:1}||(b.fill+s).charAt()!="r")&&ma(g,b.fill)){d.fill="none";d.gradient=b.fill}}e&&c[y](f);f=c.getElementsByTagName("stroke")&&c.getElementsByTagName("stroke")[0];e=false;!f&&(e=f=R("stroke"));if(b.stroke&&b.stroke!="none"||b["stroke-width"]||b["stroke-opacity"]!=null||b["stroke-dasharray"]||b["stroke-miterlimit"]||b["stroke-linejoin"]||b["stroke-linecap"])f.on=true;(b.stroke=="none"||f.on==null||b.stroke==0||b["stroke-width"]== +0)&&(f.on=false);a=m.getRGB(b.stroke);f.on&&b.stroke&&(f.color=a.hex);a=((+d["stroke-opacity"]+1||2)-1)*((+d.opacity+1||2)-1)*((+a.o+1||2)-1);h=(A(b["stroke-width"])||1)*0.75;a<0&&(a=0);a>1&&(a=1);b["stroke-width"]==null&&(h=d["stroke-width"]);b["stroke-width"]&&(f.weight=h);h&&h<1&&(a*=h)&&(f.weight=1);f.opacity=a;b["stroke-linejoin"]&&(f.joinstyle=b["stroke-linejoin"]||"miter");f.miterlimit=b["stroke-miterlimit"]||8;b["stroke-linecap"]&&(f.endcap=b["stroke-linecap"]=="butt"?"flat":b["stroke-linecap"]== +"square"?"square":"round");if(b["stroke-dasharray"]){a={"-":"shortdash",".":"shortdot","-.":"shortdashdot","-..":"shortdashdotdot",". ":"dot","- ":"dash","--":"longdash","- .":"dashdot","--.":"longdashdot","--..":"longdashdotdot"};f.dashstyle=a[z](b["stroke-dasharray"])?a[b["stroke-dasharray"]]:s}e&&c[y](f)}if(g.type=="text"){f=g.paper.span.style;d.font&&(f.font=d.font);d["font-family"]&&(f.fontFamily=d["font-family"]);d["font-size"]&&(f.fontSize=d["font-size"]);d["font-weight"]&&(f.fontWeight=d["font-weight"]); +d["font-style"]&&(f.fontStyle=d["font-style"]);g.node.string&&(g.paper.span.innerHTML=(g.node.string+s)[I](/"));g.W=d.w=g.paper.span.offsetWidth;g.H=d.h=g.paper.span.offsetHeight;g.X=d.x;g.Y=d.y+F(g.H/2);switch(d["text-anchor"]){case "start":g.node.style["v-text-align"]="left";g.bbx=F(g.W/2);break;case "end":g.node.style["v-text-align"]="right";g.bbx=-F(g.W/2);break;default:g.node.style["v-text-align"]="center";break}}};ma=function(a,b){a.attrs=a.attrs|| +{};var c="linear",d=".5 .5";a.attrs.gradient=b;b=(b+s)[I](Ya,function(i,j,l){c="radial";if(j&&l){j=A(j);l=A(l);D(j-0.5,2)+D(l-0.5,2)>0.25&&(l=w.sqrt(0.25-D(j-0.5,2))*((l>0.5)*2-1)+0.5);d=j+P+l}return s});b=b[H](/\s*\-\s*/);if(c=="linear"){var f=b.shift();f=-A(f);if(isNaN(f))return null}var e=Ra(b);if(!e)return null;a=a.shape||a.node;b=a.getElementsByTagName(aa)[0]||R(aa);!b.parentNode&&a.appendChild(b);if(e[o]){b.on=true;b.method="none";b.color=e[0].color;b.color2=e[e[o]-1].color;a=[];for(var g=0, +h=e[o];g')}}catch(Kb){R=function(a){return C.createElement("<"+a+' xmlns="urn:schemas-microsoft.com:vml" class="rvml">')}}Aa=function(){var a=Sa[K](0,arguments),b=a.container,c=a.height,d=a.width,f=a.x;a=a.y;if(!b)throw new Error("VML container not found.");var e=new G,g=e.canvas=C.createElement("div"),h=g.style;f=f||0;a=a||0;d=d||512; +c=c||342;d==+d&&(d+="px");c==+c&&(c+="px");e.width=1000;e.height=1000;e.coordsize=ja*1000+P+ja*1000;e.coordorigin="0 0";e.span=C.createElement("span");e.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";g[y](e.span);h.cssText=m.format("width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden",d,c);if(b==1){C.body[y](g);h.left=f+"px";h.top=a+"px";h.position="absolute"}else b.firstChild?b.insertBefore(g, +b.firstChild):b[y](g);Fa.call(e,e,m.fn);return e};G[p].clear=function(){this.canvas.innerHTML=s;this.span=C.createElement("span");this.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";this.canvas[y](this.span);this.bottom=this.top=null};G[p].remove=function(){this.canvas.parentNode.removeChild(this.canvas);for(var a in this)this[a]=Xa(a);return true}}G[p].safari=/^Apple|^Google/.test(X.navigator.vendor)&&(!(X.navigator.userAgent.indexOf("Version/4.0")+ +1)||X.navigator.platform.slice(0,2)=="iP")?function(){var a=this.rect(-99,-99,this.width+99,this.height+99);X.setTimeout(function(){a.remove()})}:function(){};function Db(){this.returnValue=false}function Eb(){return this.originalEvent.preventDefault()}function Fb(){this.cancelBubble=true}function Gb(){return this.originalEvent.stopPropagation()}var Hb=function(){if(C.addEventListener)return function(a,b,c,d){var f=Ba&&Ca[b]?Ca[b]:b;function e(g){if(Ba&&Ca[z](b))for(var h=0,i=g.targetTouches&&g.targetTouches.length;h< +i;h++)if(g.targetTouches[h].target==a){i=g;g=g.targetTouches[h];g.originalEvent=i;g.preventDefault=Eb;g.stopPropagation=Gb;break}return c.call(d,g)}a.addEventListener(f,e,false);return function(){a.removeEventListener(f,e,false);return true}};else if(C.attachEvent)return function(a,b,c,d){function f(g){g=g||X.event;g.preventDefault=g.preventDefault||Db;g.stopPropagation=g.stopPropagation||Fb;return c.call(d,g)}a.attachEvent("on"+b,f);function e(){a.detachEvent("on"+b,f);return true}return e}}();for(ha= +Ma[o];ha--;)(function(a){m[a]=u[p][a]=function(b){if(m.is(b,"function")){this.events=this.events||[];this.events.push({name:a,f:b,unbind:Hb(this.shape||this.node||C,a,b,this)})}return this};m["un"+a]=u[p]["un"+a]=function(b){for(var c=this.events,d=c[o];d--;)if(c[d].name==a&&c[d].f==b){c[d].unbind();c.splice(d,1);!c.length&&delete this.events;return this}return this}})(Ma[ha]);u[p].hover=function(a,b){return this.mouseover(a).mouseout(b)};u[p].unhover=function(a,b){return this.unmouseover(a).unmouseout(b)}; +u[p].drag=function(a,b,c){this._drag={};var d=this.mousedown(function(g){(g.originalEvent?g.originalEvent:g).preventDefault();this._drag.x=g.clientX;this._drag.y=g.clientY;this._drag.id=g.identifier;b&&b.call(this,g.clientX,g.clientY);Raphael.mousemove(f).mouseup(e)});function f(g){var h=g.clientX,i=g.clientY;if(Ba)for(var j=g.touches.length,l;j--;){l=g.touches[j];if(l.identifier==d._drag.id){h=l.clientX;i=l.clientY;(g.originalEvent?g.originalEvent:g).preventDefault();break}}else g.preventDefault(); +a&&a.call(d,h-d._drag.x,i-d._drag.y,h,i)}function e(){d._drag={};Raphael.unmousemove(f).unmouseup(e);c&&c.call(d)}return this};G[p].circle=function(a,b,c){return ab(this,a||0,b||0,c||0)};G[p].rect=function(a,b,c,d,f){return bb(this,a||0,b||0,c||0,d||0,f||0)};G[p].ellipse=function(a,b,c,d){return cb(this,a||0,b||0,c||0,d||0)};G[p].path=function(a){a&&!m.is(a,ea)&&!m.is(a[0],U)&&(a+=s);return Za(m.format[K](m,arguments),this)};G[p].image=function(a,b,c,d,f){return db(this,a||"about:blank",b||0,c||0, +d||0,f||0)};G[p].text=function(a,b,c){return eb(this,a||0,b||0,c||s)};G[p].set=function(a){arguments[o]>1&&(a=Array[p].splice.call(arguments,0,arguments[o]));return new Z(a)};G[p].setSize=fb;G[p].top=G[p].bottom=null;G[p].raphael=m;function ib(){return this.x+P+this.y}u[p].resetScale=function(){if(this.removed)return this;this._.sx=1;this._.sy=1;this.attrs.scale="1 1"};u[p].scale=function(a,b,c,d){if(this.removed)return this;if(a==null&&b==null)return{x:this._.sx,y:this._.sy,toString:ib};b=b||a;!+b&& +(b=a);var f,e,g=this.attrs;if(a!=0){var h=this.getBBox(),i=h.x+h.width/2,j=h.y+h.height/2;f=a/this._.sx;e=b/this._.sy;c=+c||c==0?c:i;d=+d||d==0?d:j;h=~~(a/w.abs(a));var l=~~(b/w.abs(b)),n=this.node.style,r=c+(i-c)*f;j=d+(j-d)*e;switch(this.type){case "rect":case "image":var q=g.width*h*f,k=g.height*l*e;this.attr({height:k,r:g.r*$(h*f,l*e),width:q,x:r-q/2,y:j-k/2});break;case "circle":case "ellipse":this.attr({rx:g.rx*h*f,ry:g.ry*l*e,r:g.r*$(h*f,l*e),cx:r,cy:j});break;case "text":this.attr({x:r,y:j}); +break;case "path":i=Oa(g.path);for(var t=true,L=0,B=i[o];L=i)return r;l=r}});function Ha(a,b){return function(c,d,f){c=ua(c); +for(var e,g,h,i,j="",l={},n=0,r=0,q=c.length;rd){if(b&&!l.start){e=jb(e,g,h[1],h[2],h[3],h[4],h[5],h[6],d-n);j+=["C",e.start.x,e.start.y,e.m.x,e.m.y,e.x,e.y];if(f)return j;l.start=j;j=["M",e.x,e.y+"C",e.n.x,e.n.y,e.end.x,e.end.y,h[5],h[6]][Q]();n+=i;e=+h[5];g=+h[6];continue}if(!a&&!b){e=jb(e,g,h[1],h[2],h[3],h[4],h[5],h[6],d-n);return{x:e.x,y:e.y,alpha:e.alpha}}}n+=i;e=+h[5];g=+h[6]}j+=h}l.end=j;e=a?n: +b?l:m.findDotsAtSegment(e,g,h[1],h[2],h[3],h[4],h[5],h[6],1);e.alpha&&(e={x:e.x,y:e.y,alpha:e.alpha});return e}}var Ib=T(function(a,b,c,d,f,e,g,h){for(var i={x:0,y:0},j=0,l=0;l<1.01;l+=0.01){var n=la(a,b,c,d,f,e,g,h,l);l&&(j+=D(D(i.x-n.x,2)+D(i.y-n.y,2),0.5));i=n}return j}),kb=Ha(1),za=Ha(),Ia=Ha(0,1);u[p].getTotalLength=function(){if(this.type=="path"){if(this.node.getTotalLength)return this.node.getTotalLength();return kb(this.attrs.path)}};u[p].getPointAtLength=function(a){if(this.type=="path")return za(this.attrs.path, +a)};u[p].getSubpath=function(a,b){if(this.type=="path"){if(w.abs(this.getTotalLength()-b)<1.0E-6)return Ia(this.attrs.path,a).end;b=Ia(this.attrs.path,b,1);return a?Ia(b,a).end:b}};m.easing_formulas={linear:function(a){return a},"<":function(a){return D(a,3)},">":function(a){return D(a-1,3)+1},"<>":function(a){a*=2;if(a<1)return D(a,3)/2;a-=2;return(D(a,3)+2)/2},backIn:function(a){var b=1.70158;return a*a*((b+1)*a-b)},backOut:function(a){a-=1;var b=1.70158;return a*a*((b+1)*a+b)+1},elastic:function(a){if(a== +0||a==1)return a;var b=0.3,c=b/4;return D(2,-10*a)*w.sin((a-c)*2*w.PI/b)+1},bounce:function(a){var b=7.5625,c=2.75;if(a<1/c)a=b*a*a;else if(a<2/c){a-=1.5/c;a=b*a*a+0.75}else if(a<2.5/c){a-=2.25/c;a=b*a*a+0.9375}else{a-=2.625/c;a=b*a*a+0.984375}return a}};var S={length:0};function lb(){var a=+new Date;for(var b in S)if(b!="length"&&S[z](b)){var c=S[b];if(c.stop||c.el.removed){delete S[b];S[o]--}else{var d=a-c.start,f=c.ms,e=c.easing,g=c.from,h=c.diff,i=c.to,j=c.t,l=c.prev||0,n=c.el,r=c.callback,q= +{},k;if(d p:first-child{ + margin-top:0; +} +#facebox .content > p:last-child{ + margin-bottom:0; +} + +#facebox .close{ + position:absolute; + top:5px; + right:5px; + padding:2px; + background:#fff; +} +#facebox .close img{ + opacity:0.3; +} +#facebox .close:hover img{ + opacity:1.0; +} + +#facebox .loading { + text-align: center; +} + +#facebox .image { + text-align: center; +} + +#facebox img { + border: 0; + margin: 0; +} + +#facebox_overlay { + position: fixed; + top: 0px; + left: 0px; + height:100%; + width:100%; +} + +.facebox_hide { + z-index:-100; +} + +.facebox_overlayBG { + background-color: #000; + z-index: 99; +} +.facebox-footnote{ + margin-top:40px; +} \ No newline at end of file diff --git a/public/stylesheets/reset.css b/public/stylesheets/reset.css new file mode 100644 index 0000000..d709810 --- /dev/null +++ b/public/stylesheets/reset.css @@ -0,0 +1,46 @@ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, font, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td { + margin: 0; + padding: 0; + border: 0; + outline: 0; + font-weight: inherit; + font-style: inherit; + font-size: 100%; + font-family: inherit; + vertical-align: baseline; +} +/* remember to define focus styles! */ +:focus { + outline: 0; +} +body { + line-height: 1; + color: black; + background: white; +} +ol, ul { + list-style: none; +} +/* tables still need 'cellspacing="0"' in the markup */ +table { + border-collapse: separate; + border-spacing: 0; +} +caption, th, td { + text-align: left; + font-weight: normal; +} +blockquote:before, blockquote:after, +q:before, q:after { + content: ""; +} +blockquote, q { + quotes: "" ""; +} diff --git a/public/stylesheets/scaffold.css b/public/stylesheets/scaffold.css new file mode 100644 index 0000000..1ae7000 --- /dev/null +++ b/public/stylesheets/scaffold.css @@ -0,0 +1,56 @@ +body { background-color: #fff; color: #333; } + +body, p, ol, ul, td { + font-family: verdana, arial, helvetica, sans-serif; + font-size: 13px; + line-height: 18px; +} + +pre { + background-color: #eee; + padding: 10px; + font-size: 11px; +} + +a { color: #000; } +a:visited { color: #666; } +a:hover { color: #fff; background-color:#000; } + +div.field, div.actions { + margin-bottom: 10px; +} + +#notice { + color: green; +} + +.field_with_errors { + padding: 2px; + background-color: red; + display: table; +} + +#error_explanation { + width: 450px; + border: 2px solid red; + padding: 7px; + padding-bottom: 0; + margin-bottom: 20px; + background-color: #f0f0f0; +} + +#error_explanation h2 { + text-align: left; + font-weight: bold; + padding: 5px 5px 5px 15px; + font-size: 12px; + margin: -7px; + margin-bottom: 0px; + background-color: #c00; + color: #fff; +} + +#error_explanation ul li { + font-size: 12px; + list-style: square; +} diff --git a/public/stylesheets/site.css b/public/stylesheets/site.css new file mode 100755 index 0000000..62b1526 --- /dev/null +++ b/public/stylesheets/site.css @@ -0,0 +1,378 @@ +body { + font-family: verdana, arial, sans-serif; + font-size: 14px; + text-align: center; +} +h1, h2, h3, h4 { + font-family: georgia, serif; + margin: 10px 45px; padding: 0; +} +h1 { + color: #333; + font-size: 48px; + font-weight: normal; + margin: 10px 0px; +} +h3 { + color: white; + font-size: 21px; + font-weight: normal; +} +a,a:link,a:visited { + text-decoration: none; + color: #57ad11; +} +a:hover { + text-decoration: underline; + color: #57ad11; +} +a:active { + text-decoration: underline; + color: #dddddd; +} +input.keyboard-selector-input { + position: fixed; + top: 0; + _position: absolute; + _top: expression(eval(document.body.scrollTop)); + left: -300px; +} +.container { + width: 678px; + margin: 0 auto; + text-align: left; +} +.content { + width: 712px; + background: url(/images/tile.png) repeat-y; +} +#lilBrowser { + position: absolute; + background-color: white; + top: -540px; + left: -440px; + width: 510px; + height: 430px; + padding: 5px; + border: solid 1px #444; + z-index: 100; +} +h3#lbTitle { + color: #444; + font-family: verdana, arial, sans-serif; + font-size: small; + float:left; + line-height: 90%; + margin: 0; padding: 3px; +} +p#lbClose { + font-size: small; + float: right; + margin: 0; padding: 3px; +} +p#lbClose a { + display: inline; +} +.shellwin { + width: 712px; + padding-left: 12px; + background: url(/images/background.png) no-repeat; +} + +/* tutorial panes */ +.stretcher { + color: #f1f1ff; + display: none; + margin: 0; + padding: 0; + padding-left: 12px; + background: url(/images/tile.png) repeat-y; +} +.stretcher a, .stretcher a:link, .stretcher a:visited, .stretcher a:active { + text-decoration: none; + color: #a7ed91; +} +.stretcher a:hover { + text-decoration: underline; + color: #b7fd91; +} +.stretcher p { + margin: 10px 16px; +} +.stretcher dl, .stretcher ul { + background-color: white; + color: #333; + padding: 4px 8px; + font-size: 12px; + margin-left: 16px; + list-style: none; +} +.stretcher li { + margin: 6px; +} +.stretcher p code { + background-color: #874a20; + color: #fedeec; + padding: 1px 4px; +} +.stretcher p code.cmd { + background-color: #eeeeec; + color: #204a87; +} +.stretcher dt { + font-weight: bold; +} + +.chapmark { + padding: 6px 0; + margin-left: 12px; + margin-right: 22px; + color: #553; + background: #efefe1; +} +.chapmark h3 { + color: #335; +} +.chapmark a, .chapmark a:link, .chapmark a:visited, .chapmark a:active { + text-decoration: none; + color: #372d61; +} +.chapmark a:hover { + text-decoration: underline; + color: #477d51; +} +.note { color: #ddc; text-align: center; font-size: xx-small; } +ul li strong { color: #286; border-bottom: solid 2px #cca; } +ul li code { background-color: #f1f1f1; padding: 1px 3px; border-bottom: solid 2px #ddd; } +ul li code.faded { color: #899; } +code strong { background-color: #dcffb9; padding: 1px 3px; } +ul.commands li strong { display: block; float: left; width: 60px; border: none; } + +/* irb terminal */ +.terminal { + background-color: #ffffff; + border: solid 1px #204a87; + width: 678px; + height: 240px; + overflow: auto; +} +.console { + padding: 4px; margin-left: -50px; + font-family: "Andale Mono", courier, fixed, monospace; + font-size: 14px; + line-height: 16px; + color: #204a87; + text-align: left; + width: 664px; + height:220px; +} + +.console div b { + background-color: #874a20; + color: #fedeac; +} +div.answer, div.stdout, div.no_answer, div.load { + display: none; +} + +/* terminal escape colors */ +span.fore_black { color: #2e3436; } +span.fore_dark_gray { color: #888a85; } +span.fore_gray { color: #babdb6; } +span.fore_white { color: #eeeeec; } +span.fore_blue { color: #204a87; } +span.fore_lt_blue { color: #729fcf; } +span.fore_green { color: #788600; font-weight: bold; } +span.fore_lt_green { color: #cbe134; } +span.fore_cyan { color: #c4a000; } /* using cyan for yellows */ +span.fore_lt_cyan { color: #fc994f; } +span.fore_red { color: #a40000; } +span.fore_lt_red { color: #ef2929; font-weight: bold; } +span.fore_purple { color: #5c3566; } +span.fore_lt_purple { color: #ad7fa8; } +span.fore_brown { color: #8f5972; } +span.fore_lt_brown { color: #b9b9de; } +span.back_black { background-color: #2e3436; } +span.back_dark_gray { background-color: #888a85; } +span.back_gray { background-color: #babdb6; } +span.back_white { background-color: #eeeeec; } +span.back_blue { background-color: #204a87; } +span.back_lt_blue { background-color: #729fcf; } +span.back_green { background-color: #788600; } +span.back_lt_green { background-color: #cbe134; } +span.back_cyan { background-color: #c4a000; } /* using cyan for yellows */ +span.back_lt_cyan { background-color: #fce94f; } +span.back_red { background-color: #a40000; } +span.back_lt_red { background-color: #ef2929; } +span.back_purple { background-color: #5c3566; } +span.back_lt_purple { background-color: #ad7fa8; } +span.back_brown { background-color: #8f5902; } +span.back_lt_brown { background-color: #b9b96e; } + +/** no ways***/ + +div.main-wrapper-bottom { + height:4px;background-position: 0px -80px; background-repeat: no-repeat; + font-size:0 /* IE6, go figure */ +} +div.main-wrapper-borders { + background-position: -1731px 0; padding:15px; + background-repeat:repeat-y; +} +div.console-wrapper { + margin:0px auto ;width:566px; + cursor:text; + font-family:monospace; +} +div.console-wrapper-top { + height:3px;background-position: -50px -48px; background-repeat: no-repeat; + font-size:0 /* IE6, go figure */ +} +div.console-wrapper-bottom { + height:3px;background-position: -50px -51px; background-repeat: no-repeat; + font-size:0 /* IE6, go figure */ +} +div.console-wrapper-borders { + background-position: 0px 0px; padding:1px; + background-repeat:repeat-y; +} +div.guide-wrapper { + color:#fff; width:566px;margin-left:2px +} +div.guide-wrapper-top { + height:4px;background-position: 0 -65px; + font-size:0 /* IE6, go figure */ +} +div.guide-wrapper-bottom { + height:4px;background-position: 0 -70px; + font-size:0 /* IE6, go figure */ +} +div.guide-wrapper-borders { + background-position: -1166px 0px;padding:15px; + background-repeat:repeat-y; +} + +div.footer-wrapper-borders { + background-position: -566px 0px; padding:10px; + background-repeat:repeat-y; + font-size:12px +} +h1.main-header { + text-indent:-9999px; background-position: -49px 0px; + background-repeat: no-repeat; + width:318px; height:48px; margin-bottom:20px; + float:left +} + +div.footer { + line-height: 1.3em; +} + div.console div.jquery-console-inner +{ height:100%; overflow:auto; background:white} +div.console div.jquery-console-prompt-box +{ color:#437375; font-family:monospace; margin-top:0.5em; } +div.console div.jquery-console-prompt-box .prompt-done +{ cursor: pointer } +div.console div.jquery-console-prompt-box .prompt-done:hover +{ background:#453D5B; color: white; } +div.console div.jquery-console-focus span.jquery-console-cursor +{ background:#666; color:#fff; } +div.console div.jquery-console-message-error { + color:#ef0505; font-family:sans-serif; font-weight:bold; + padding-top:0.25em +} +div.console div.jquery-console-message-value +{ color:#000; font-family:monospace;padding-top:0.25em; font-weight: bold; } +div.console div.jquery-console-message-type +{ color:#382567; font-family:monospace;padding-left:0em;padding-top:0.25em; font-size:.9em } +div.console span.jquery-console-prompt-label { font-weight:bold } +div.console div.jquery-console-welcome { font-family:"DejaVu Sans",sans-serif; } + +div.share-wrapper { font-size:12px;padding:10px 0em 0em 10px } +div.share-wrapper strong { font-weight: bold } + +.clearfix:after { content:"."; display:block; height:0; clear:both; visibility:hidden } +div.menu { + float:right; + margin-right:2px; + margin-top:40px; + margin-bottom:5px +} +a.reset-btn { + float:left; + display:block; + width:59px; + height:24px; + background-position: -427px -18px; background-repeat: no-repeat; +} +a.reset-btn span { display:none } + +div.clear { clear:both } + + +div.console-wrapper .notice { + position:absolute; + bottom:0;right:0; + margin:1px; + background:#eee; + color:black; + padding:10px; + font-size:12px; + font-family:sans-serif; + font-weight:bold; +} +p.ajax-loader { background:url(../images/ajax-loader.gif); width:16px; height:16px;text-indent:-9999px } + +.notice a { padding:3px;background:#333;color:white} +.notice .action { text-align: right } + +/* Support Try Ruby! */ + + +a.trigger{ +position: absolute; +text-decoration: none; +top: 80px; right: 0; +font-size: 14px; +letter-spacing:-1px; +font-family: verdana, helvetica, arial, sans-serif; +color:#fff; +padding: 10px 10px 10px 10px; +font-weight: 500; +background:#333333 url(images/plus.png) 15% 55% no-repeat; +border:1px solid #444444; +-moz-border-radius-topleft: 20px; +-webkit-border-top-left-radius: 20px; +-moz-border-radius-bottomleft: 20px; +-webkit-border-bottom-left-radius: 20px; +-moz-border-radius-bottomright: 0px; +-webkit-border-bottom-right-radius: 0px; +display: block; +} + +a.trigger:hover{ +position: absolute; +text-decoration: none; +top: 80px; right: 0; +font-size: 14px; +letter-spacing:-1px; +font-family: verdana, helvetica, arial, sans-serif; +color:#fff; +padding: 10px 10px 10px 10px; +font-weight: 500; +background: green; +border:1px solid #444444; +-moz-border-radius-topleft: 20px; +-webkit-border-top-left-radius: 20px; +-moz-border-radius-bottomleft: 20px; +-webkit-border-bottom-left-radius: 20px; +-moz-border-radius-bottomright: 0px; +-webkit-border-bottom-right-radius: 0px; +display: block; +} + +a.active.trigger { +background:#222222 url(images/minus.png) 15% 55% no-repeat; +} + + \ No newline at end of file diff --git a/tryruby/Gemfile b/tryruby/Gemfile index 649c6bb..668de60 100644 --- a/tryruby/Gemfile +++ b/tryruby/Gemfile @@ -1,16 +1,46 @@ -source :rubygems +source 'http://rubygems.org' -gem "rails", '2.3.5' +gem 'rails', '3.0.5' -# Specify your favourite web server (only one). -#gem 'unicorn', :group => :development -#gem 'mongrel', :group => :development +# Bundle edge Rails instead: +# gem 'rails', :git => 'git://github.com/rails/rails.git' +gem 'mysql2' +gem 'fakefs', '0.2.1', :git => "http://github.com/defunkt/fakefs.git", :ref => "aa0cb96b8ebc81287a2e", :require => 'fakefs/safe' +# Use unicorn as the web server +# gem 'unicorn' +gem 'i18n' +# Deploy with Capistrano +# gem 'capistrano' + +gem 'devise' + +# To use debugger (ruby-debug for Ruby 1.8.7+, ruby-debug19 for Ruby 1.9.2+) +# gem 'ruby-debug' +# gem 'ruby-debug19', :require => 'ruby-debug' +gem 'jquery-rails' gem 'ruby_parser' +gem 'racc' + +#gem 'ruby2ruby' +#gem 'newrelic_rpm' +#gem 'madmimi' +#gem 'delayed_job' +#gem 'dalli' +# Bundle the extra gems: +# gem 'bj' + +gem 'nokogiri' +# gem 'sqlite3-ruby', :require => 'sqlite3' +# gem 'aws-s3', :require => 'aws/s3' -group :test do - gem 'test-unit', '2.1.1' - gem 'fakefs', '0.2.1', :git => "http://github.com/defunkt/fakefs.git", :ref => "aa0cb96b8ebc81287a2e", :require => 'fakefs/safe' - gem 'hpricot' - gem 'ruby-debug19' -end \ No newline at end of file +# Bundle gems for the local environment. Make sure to +# put test-only gems in this group so their generators +# and rake tasks are available in development mode: +# group :development, :test do + gem 'capybara' + gem 'rspec-rails' + gem 'cucumber-rails' + #gem 'factory-girl' + +# end diff --git a/tryruby/README b/tryruby/README index 79bc20e..fe7013d 100644 --- a/tryruby/README +++ b/tryruby/README @@ -1,21 +1,256 @@ -=README +== Welcome to Rails -This is a highly experimental version of tryruby -I realize putting try ruby is rails is going to be controversial. -My origional idea was to use sinatra. Maybe I will use both. +Rails is a web-application framework that includes everything needed to create +database-backed web applications according to the Model-View-Control pattern. -What is driving this decision is: -* the desire to move away from explictly needing to state where the ruby interpreter is -* an admission that I need to become rack based, rails is a cheap way out -* more people know rails within the ruby world then not (sorry its true) -* I need to be able to extend this eaiser, if I tried to add even 30 lessons in its current form, it would not be as fun as inside rails -* rspec-rails I understand way better than rspec some random script. +This pattern splits the view (also called the presentation) into "dumb" +templates that are primarily responsible for inserting pre-built data in between +HTML tags. The model contains the "smart" domain objects (such as Account, +Product, Person, Post) that holds all the business logic and knows how to +persist themselves to a database. The controller handles the incoming requests +(such as Save New Account, Update Product, Show Post) by manipulating the model +and directing data to the view. -so why am I not using camping, simple, I am not sure how maintained camping is. -What about merb? I admit, I don't know merb and with rails 3.0 won't I be getting the benefits of merb anyway? +In Rails, the model is handled by what's called an object-relational mapping +layer entitled Active Record. This layer allows you to present the data from +database rows as objects and embellish these data objects with business logic +methods. You can read more about Active Record in +link:files/vendor/rails/activerecord/README.html. -I will contact everyone who has a fork of this project to notify them of if and when I plan on making the architectual switch before hand. +The controller and view are handled by the Action Pack, which handles both +layers by its two parts: Action View and Action Controller. These two layers +are bundled in a single package due to their heavy interdependence. This is +unlike the relationship between the Active Record and Action Pack that is much +more separate. Each of these packages can be used independently outside of +Rails. You can read more about Action Pack in +link:files/vendor/rails/actionpack/README.html. -Thanks. -In the meanwhile, ignore this branch. +== Getting Started + +1. At the command prompt, create a new Rails application: + rails new myapp (where myapp is the application name) + +2. Change directory to myapp and start the web server: + cd myapp; rails server (run with --help for options) + +3. Go to http://localhost:3000/ and you'll see: + "Welcome aboard: You're riding Ruby on Rails!" + +4. Follow the guidelines to start developing your application. You can find +the following resources handy: + +* The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html +* Ruby on Rails Tutorial Book: http://www.railstutorial.org/ + + +== Debugging Rails + +Sometimes your application goes wrong. Fortunately there are a lot of tools that +will help you debug it and get it back on the rails. + +First area to check is the application log files. Have "tail -f" commands +running on the server.log and development.log. Rails will automatically display +debugging and runtime information to these files. Debugging info will also be +shown in the browser on requests from 127.0.0.1. + +You can also log your own messages directly into the log file from your code +using the Ruby logger class from inside your controllers. Example: + + class WeblogController < ActionController::Base + def destroy + @weblog = Weblog.find(params[:id]) + @weblog.destroy + logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!") + end + end + +The result will be a message in your log file along the lines of: + + Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1! + +More information on how to use the logger is at http://www.ruby-doc.org/core/ + +Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are +several books available online as well: + +* Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe) +* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide) + +These two books will bring you up to speed on the Ruby language and also on +programming in general. + + +== Debugger + +Debugger support is available through the debugger command when you start your +Mongrel or WEBrick server with --debugger. This means that you can break out of +execution at any point in the code, investigate and change the model, and then, +resume execution! You need to install ruby-debug to run the server in debugging +mode. With gems, use sudo gem install ruby-debug. Example: + + class WeblogController < ActionController::Base + def index + @posts = Post.find(:all) + debugger + end + end + +So the controller will accept the action, run the first line, then present you +with a IRB prompt in the server window. Here you can do things like: + + >> @posts.inspect + => "[#nil, "body"=>nil, "id"=>"1"}>, + #"Rails", "body"=>"Only ten..", "id"=>"2"}>]" + >> @posts.first.title = "hello from a debugger" + => "hello from a debugger" + +...and even better, you can examine how your runtime objects actually work: + + >> f = @posts.first + => #nil, "body"=>nil, "id"=>"1"}> + >> f. + Display all 152 possibilities? (y or n) + +Finally, when you're ready to resume execution, you can enter "cont". + + +== Console + +The console is a Ruby shell, which allows you to interact with your +application's domain model. Here you'll have all parts of the application +configured, just like it is when the application is running. You can inspect +domain models, change values, and save to the database. Starting the script +without arguments will launch it in the development environment. + +To start the console, run rails console from the application +directory. + +Options: + +* Passing the -s, --sandbox argument will rollback any modifications + made to the database. +* Passing an environment name as an argument will load the corresponding + environment. Example: rails console production. + +To reload your controllers and models after launching the console run +reload! + +More information about irb can be found at: +link:http://www.rubycentral.com/pickaxe/irb.html + + +== dbconsole + +You can go to the command line of your database directly through rails +dbconsole. You would be connected to the database with the credentials +defined in database.yml. Starting the script without arguments will connect you +to the development database. Passing an argument will connect you to a different +database, like rails dbconsole production. Currently works for MySQL, +PostgreSQL and SQLite 3. + +== Description of Contents + +The default directory structure of a generated Ruby on Rails application: + + |-- app + | |-- controllers + | |-- helpers + | |-- mailers + | |-- models + | `-- views + | `-- layouts + |-- config + | |-- environments + | |-- initializers + | `-- locales + |-- db + |-- doc + |-- lib + | `-- tasks + |-- log + |-- public + | |-- images + | |-- javascripts + | `-- stylesheets + |-- script + |-- test + | |-- fixtures + | |-- functional + | |-- integration + | |-- performance + | `-- unit + |-- tmp + | |-- cache + | |-- pids + | |-- sessions + | `-- sockets + `-- vendor + `-- plugins + +app + Holds all the code that's specific to this particular application. + +app/controllers + Holds controllers that should be named like weblogs_controller.rb for + automated URL mapping. All controllers should descend from + ApplicationController which itself descends from ActionController::Base. + +app/models + Holds models that should be named like post.rb. Models descend from + ActiveRecord::Base by default. + +app/views + Holds the template files for the view that should be named like + weblogs/index.html.erb for the WeblogsController#index action. All views use + eRuby syntax by default. + +app/views/layouts + Holds the template files for layouts to be used with views. This models the + common header/footer method of wrapping views. In your views, define a layout + using the layout :default and create a file named default.html.erb. + Inside default.html.erb, call <% yield %> to render the view using this + layout. + +app/helpers + Holds view helpers that should be named like weblogs_helper.rb. These are + generated for you automatically when using generators for controllers. + Helpers can be used to wrap functionality for your views into methods. + +config + Configuration files for the Rails environment, the routing map, the database, + and other dependencies. + +db + Contains the database schema in schema.rb. db/migrate contains all the + sequence of Migrations for your schema. + +doc + This directory is where your application documentation will be stored when + generated using rake doc:app + +lib + Application specific libraries. Basically, any kind of custom code that + doesn't belong under controllers, models, or helpers. This directory is in + the load path. + +public + The directory available for the web server. Contains subdirectories for + images, stylesheets, and javascripts. Also contains the dispatchers and the + default HTML files. This should be set as the DOCUMENT_ROOT of your web + server. + +script + Helper scripts for automation and generation. + +test + Unit and functional tests along with fixtures. When using the rails generate + command, template test files will be generated for you and placed in this + directory. + +vendor + External libraries that the application depends on. Also includes the plugins + subdirectory. If the app has frozen rails, those gems also go here, under + vendor/rails/. This directory is in the load path. diff --git a/tryruby/Rakefile b/tryruby/Rakefile index 3bb0e85..79dd5f3 100644 --- a/tryruby/Rakefile +++ b/tryruby/Rakefile @@ -1,10 +1,7 @@ # Add your own tasks in files placed in lib/tasks ending in .rake, # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. -require(File.join(File.dirname(__FILE__), 'config', 'boot')) - +require File.expand_path('../config/application', __FILE__) require 'rake' -require 'rake/testtask' -require 'rake/rdoctask' -require 'tasks/rails' +TryRuby::Application.load_tasks diff --git a/tryruby/app/controllers/application_controller.rb b/tryruby/app/controllers/application_controller.rb index 02c13e5..b0f4608 100644 --- a/tryruby/app/controllers/application_controller.rb +++ b/tryruby/app/controllers/application_controller.rb @@ -1,15 +1,24 @@ # Filters added to this controller apply to all controllers in the application. # Likewise, all the methods added will be available for all controllers. +require './lib/tryruby' class ApplicationController < ActionController::Base +# attr_accessor :past_commands, :current_statement, :start_time +=begin + #attr_accessor :session + TryRuby.session = session + + TryRuby.session['start_time'] ||= Time.now + TryRuby.session['current_statement'] ||= '' + TryRuby.session['past_commands'] ||= '' + helper :all # include all helpers, all the time protect_from_forgery # See ActionController::RequestForgeryProtection for details # Scrub sensitive parameters from your log # filter_parameter_logging :password #class << self - attr_accessor :session - TryRuby.session = TryRuby::Session.new +=end # not needed #end end diff --git a/tryruby/app/controllers/tryruby_controller.rb b/tryruby/app/controllers/tryruby_controller.rb index 88f6513..912866a 100644 --- a/tryruby/app/controllers/tryruby_controller.rb +++ b/tryruby/app/controllers/tryruby_controller.rb @@ -1,11 +1,14 @@ -require './lib/tryruby' class TryrubyController < ApplicationController layout 'tryruby' - attr_accessor :past_commands, :current_statement, :start_time def run - render :text => run_script(params[:cmd]) - end + @cmd=params[:cmd] + + @a= run_script(@cmd) +@b = "handleJSON({\"type\": #{@a.type.to_json}, \"output\":#{@a.output.to_json},\"result\":#{@a.result.inspect.to_json}, \"error\": #{@a.error.inspect.to_json}})" + + render :json => @b + end private @@ -15,7 +18,7 @@ def run_script(command) # rescue StandardError => e # e.message + ". On the " - TryRuby.run_line(command).format + TryRuby.run_line(command) # end # return "=> #{output}" + ", says yoda" diff --git a/tryruby/app/helpers/application_helper.rb b/tryruby/app/helpers/application_helper.rb index 22a7940..d995b05 100644 --- a/tryruby/app/helpers/application_helper.rb +++ b/tryruby/app/helpers/application_helper.rb @@ -1,3 +1,18 @@ -# Methods added to this helper will be available to all templates in the application. module ApplicationHelper + + def google_analytics_js + ua_code = "UA-2365371-3" + '' + + end + end diff --git a/tryruby/app/views/layouts/tryruby.rhtml b/tryruby/app/views/layouts/tryruby.rhtml index 7d7fadc..2600200 100644 --- a/tryruby/app/views/layouts/tryruby.rhtml +++ b/tryruby/app/views/layouts/tryruby.rhtml @@ -4,40 +4,81 @@ try ruby! (in your browser) - - - - - + + + + - - + + + + + + + + + + + + + -
        - -
        +
        +
        +
        + + + <%= render :partial => 'tryruby/donate' %> + +

        A Popup Browser

        [x]

        - <%= yield %> +
        -
        + -
        -
        -
        + +
        + + +
        +
        +
        +
        +
        +
        +
        +
        -
        +

        Got 15 minutes? Give Ruby a shot right now!

        Ruby is a programming language from Japan (available at ruby-lang.org) @@ -79,8 +120,7 @@ Allows you to skip to the next section of a lesson.

        - - + +Please Support
        Try Ruby!
        + diff --git a/tryruby/app/views/tryruby/index.rhtml b/tryruby/app/views/tryruby/index.rhtml index 091d348..c95b8f7 100644 --- a/tryruby/app/views/tryruby/index.rhtml +++ b/tryruby/app/views/tryruby/index.rhtml @@ -1 +1,11 @@ - \ No newline at end of file + +
        +
        +
        +
        +
        +
        +
        +
        + + diff --git a/tryruby/config/boot.rb b/tryruby/config/boot.rb index 9ee835a..4489e58 100644 --- a/tryruby/config/boot.rb +++ b/tryruby/config/boot.rb @@ -1,124 +1,6 @@ -# Don't change this file! -# Configure your app in config/environment.rb and config/environments/*.rb +require 'rubygems' -RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT) +# Set up gems listed in the Gemfile. +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) -module Rails - class << self - def boot! - unless booted? - preinitialize - pick_boot.run - end - end - - def booted? - defined? Rails::Initializer - end - - def pick_boot - (vendor_rails? ? VendorBoot : GemBoot).new - end - - def vendor_rails? - File.exist?("#{RAILS_ROOT}/vendor/rails") - end - - def preinitialize - load(preinitializer_path) if File.exist?(preinitializer_path) - end - - def preinitializer_path - "#{RAILS_ROOT}/config/preinitializer.rb" - end - end - - class Boot - def run - load_initializer - Rails::Initializer.run(:set_load_path) - end - end - - class VendorBoot < Boot - def load_initializer - require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer" - Rails::Initializer.run(:install_gem_spec_stubs) - Rails::GemDependency.add_frozen_gem_path - end - end - - class GemBoot < Boot - def load_initializer - self.class.load_rubygems - load_rails_gem - require 'initializer' - end - - def load_rails_gem - if version = self.class.gem_version - gem 'rails', version - else - gem 'rails' - end - rescue Gem::LoadError => load_error - $stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.) - exit 1 - end - - class << self - def rubygems_version - Gem::RubyGemsVersion rescue nil - end - - def gem_version - if defined? RAILS_GEM_VERSION - RAILS_GEM_VERSION - elsif ENV.include?('RAILS_GEM_VERSION') - ENV['RAILS_GEM_VERSION'] - else - parse_gem_version(read_environment_rb) - end - end - - def load_rubygems - min_version = '1.3.2' - require 'rubygems' - unless rubygems_version >= min_version - $stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.) - exit 1 - end - - rescue LoadError - $stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org) - exit 1 - end - - def parse_gem_version(text) - $1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/ - end - - private - def read_environment_rb - File.read("#{RAILS_ROOT}/config/environment.rb") - end - end - end -end - -class Rails::Boot - def run - load_initializer - - Rails::Initializer.class_eval do - def load_gems - @bundler_loaded ||= Bundler.require :default, Rails.env - end - end - - Rails::Initializer.run(:set_load_path) - end -end - -# All that for this: -Rails.boot! +require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) diff --git a/tryruby/config/database.yml b/tryruby/config/database.yml index 854cff5..48e775d 100644 --- a/tryruby/config/database.yml +++ b/tryruby/config/database.yml @@ -1,20 +1,32 @@ -# SQLite version 3.x -# gem install sqlite3-ruby (not necessary on OS X Leopard) -development: - +development: + adapter: mysql2 + database: tryruby_development + username: root + password: root + pool: 5 + timeout: 5000 + host: 127.0.0.1 # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: - adapter: sqlite3 - database: db/test.sqlite3 - pool: 5 - timeout: 5000 + adapter: mysql2 + database: tryruby_test + username: root + password: root + pool: 5 + timeout: 5000 + host: 127.0.0.1 production: - adapter: sqlite3 - database: db/production.sqlite3 - pool: 5 - timeout: 5000 + adapter: mysql2 + database: tryruby_production + username: root + password: root + pool: 5 + timeout: 5000 + host: localhost +cucumber: + <<: *test \ No newline at end of file diff --git a/tryruby/config/environment.rb b/tryruby/config/environment.rb index dec1ee9..1c5d67b 100644 --- a/tryruby/config/environment.rb +++ b/tryruby/config/environment.rb @@ -1,45 +1,5 @@ -# Be sure to restart your server when you modify this file +# Load the rails application +require File.expand_path('../application', __FILE__) -# Specifies gem version of Rails to use when vendor/rails is not present -RAILS_GEM_VERSION = '2.3.5' unless defined? RAILS_GEM_VERSION - -# Bootstrap the Rails environment, frameworks, and default configuration -require File.join(File.dirname(__FILE__), 'boot') - -Rails::Initializer.run do |config| - config.frameworks -= [:active_record] - # Settings in config/environments/* take precedence over those specified here. - # Application configuration should go into files in config/initializers - # -- all .rb files in that directory are automatically loaded. - - # Add additional load paths for your own custom dirs - # config.load_paths += %W( #{RAILS_ROOT}/extras ) - - # Specify gems that this application depends on and have them installed with rake gems:install - # config.gem "bj" - # config.gem "hpricot", :version => '0.6', :source => "http://code.whytheluckystiff.net" - # config.gem "sqlite3-ruby", :lib => "sqlite3" - # config.gem "aws-s3", :lib => "aws/s3" - - # Only load the plugins named here, in the order given (default is alphabetical). - # :all can be used as a placeholder for all plugins not explicitly named - # config.plugins = [ :exception_notification, :ssl_requirement, :all ] - - # Skip frameworks you're not going to use. To use Rails without a database, - # you must remove the Active Record framework. - # config.frameworks -= [ :active_record, :active_resource, :action_mailer ] - - # Activate observers that should always be running - # config.active_record.observers = :cacher, :garbage_collector, :forum_observer - - # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. - # Run "rake -D time" for a list of tasks for finding time zone names. - config.time_zone = 'UTC' - - # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. - # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}')] - # config.i18n.default_locale = :de -end - -#equire 'irb' -#require 'tryruby_runner' +# Initialize the rails application +TryRuby::Application.initialize! diff --git a/tryruby/config/environments/development.rb b/tryruby/config/environments/development.rb index 85c9a60..43463ef 100644 --- a/tryruby/config/environments/development.rb +++ b/tryruby/config/environments/development.rb @@ -1,17 +1,26 @@ -# Settings specified here will take precedence over those in config/environment.rb +TryRuby::Application.configure do + # Settings specified here will take precedence over those in config/application.rb -# In the development environment your application's code is reloaded on -# every request. This slows down response time but is perfect for development -# since you don't have to restart the webserver when you make code changes. -config.cache_classes = false + # In the development environment your application's code is reloaded on + # every request. This slows down response time but is perfect for development + # since you don't have to restart the webserver when you make code changes. + config.cache_classes = false -# Log error messages when you accidentally call methods on nil. -config.whiny_nils = true + # Log error messages when you accidentally call methods on nil. + config.whiny_nils = true -# Show full error reports and disable caching -config.action_controller.consider_all_requests_local = true -config.action_view.debug_rjs = true -config.action_controller.perform_caching = false + # Show full error reports and disable caching + config.consider_all_requests_local = true + config.action_view.debug_rjs = true + config.action_controller.perform_caching = false + + # Don't care if the mailer can't send + config.action_mailer.raise_delivery_errors = false + + # Print deprecation notices to the Rails logger + config.active_support.deprecation = :log + + # Only use best-standards-support built into browsers + config.action_dispatch.best_standards_support = :builtin +end -# Don't care if the mailer can't send -config.action_mailer.raise_delivery_errors = false \ No newline at end of file diff --git a/tryruby/config/environments/production.rb b/tryruby/config/environments/production.rb index 27119d2..3827776 100644 --- a/tryruby/config/environments/production.rb +++ b/tryruby/config/environments/production.rb @@ -1,28 +1,49 @@ -# Settings specified here will take precedence over those in config/environment.rb +TryRuby::Application.configure do + # Settings specified here will take precedence over those in config/application.rb -# The production environment is meant for finished, "live" apps. -# Code is not reloaded between requests -config.cache_classes = true + # The production environment is meant for finished, "live" apps. + # Code is not reloaded between requests + config.cache_classes = true -# Full error reports are disabled and caching is turned on -config.action_controller.consider_all_requests_local = false -config.action_controller.perform_caching = true -config.action_view.cache_template_loading = true + # Full error reports are disabled and caching is turned on + config.consider_all_requests_local = false + config.action_controller.perform_caching = true -# See everything in the log (default is :info) -# config.log_level = :debug + # Specifies the header that your server uses for sending files + config.action_dispatch.x_sendfile_header = "X-Sendfile" -# Use a different logger for distributed setups -# config.logger = SyslogLogger.new + # For nginx: + # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' -# Use a different cache store in production -# config.cache_store = :mem_cache_store + # If you have no front-end server that supports something like X-Sendfile, + # just comment this out and Rails will serve the files -# Enable serving of images, stylesheets, and javascripts from an asset server -# config.action_controller.asset_host = "http://assets.example.com" + # See everything in the log (default is :info) + # config.log_level = :debug -# Disable delivery errors, bad email addresses will be ignored -# config.action_mailer.raise_delivery_errors = false + # Use a different logger for distributed setups + # config.logger = SyslogLogger.new -# Enable threaded mode -# config.threadsafe! \ No newline at end of file + # Use a different cache store in production + # config.cache_store = :mem_cache_store + + # Disable Rails's static asset server + # In production, Apache or nginx will already do this + config.serve_static_assets = false + + # Enable serving of images, stylesheets, and javascripts from an asset server + # config.action_controller.asset_host = "http://assets.example.com" + + # Disable delivery errors, bad email addresses will be ignored + # config.action_mailer.raise_delivery_errors = false + + # Enable threaded mode + # config.threadsafe! + + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation can not be found) + config.i18n.fallbacks = true + + # Send deprecation notices to registered listeners + config.active_support.deprecation = :notify +end diff --git a/tryruby/config/environments/test.rb b/tryruby/config/environments/test.rb index d6f80a4..7127cbe 100644 --- a/tryruby/config/environments/test.rb +++ b/tryruby/config/environments/test.rb @@ -1,28 +1,35 @@ -# Settings specified here will take precedence over those in config/environment.rb - -# The test environment is used exclusively to run your application's -# test suite. You never need to work with it otherwise. Remember that -# your test database is "scratch space" for the test suite and is wiped -# and recreated between test runs. Don't rely on the data there! -config.cache_classes = true - -# Log error messages when you accidentally call methods on nil. -config.whiny_nils = true - -# Show full error reports and disable caching -config.action_controller.consider_all_requests_local = true -config.action_controller.perform_caching = false -config.action_view.cache_template_loading = true - -# Disable request forgery protection in test environment -config.action_controller.allow_forgery_protection = false - -# Tell Action Mailer not to deliver emails to the real world. -# The :test delivery method accumulates sent emails in the -# ActionMailer::Base.deliveries array. -config.action_mailer.delivery_method = :test - -# Use SQL instead of Active Record's schema dumper when creating the test database. -# This is necessary if your schema can't be completely dumped by the schema dumper, -# like if you have constraints or database-specific column types -# config.active_record.schema_format = :sql \ No newline at end of file +TryRuby::Application.configure do + # Settings specified here will take precedence over those in config/application.rb + + # The test environment is used exclusively to run your application's + # test suite. You never need to work with it otherwise. Remember that + # your test database is "scratch space" for the test suite and is wiped + # and recreated between test runs. Don't rely on the data there! + config.cache_classes = true + + # Log error messages when you accidentally call methods on nil. + config.whiny_nils = true + + # Show full error reports and disable caching + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Raise exceptions instead of rendering exception templates + config.action_dispatch.show_exceptions = false + + # Disable request forgery protection in test environment + config.action_controller.allow_forgery_protection = false + + # Tell Action Mailer not to deliver emails to the real world. + # The :test delivery method accumulates sent emails in the + # ActionMailer::Base.deliveries array. + config.action_mailer.delivery_method = :test + + # Use SQL instead of Active Record's schema dumper when creating the test database. + # This is necessary if your schema can't be completely dumped by the schema dumper, + # like if you have constraints or database-specific column types + # config.active_record.schema_format = :sql + + # Print deprecation notices to the stderr + config.active_support.deprecation = :stderr +end diff --git a/tryruby/config/initializers/backtrace_silencers.rb b/tryruby/config/initializers/backtrace_silencers.rb index c2169ed..59385cd 100644 --- a/tryruby/config/initializers/backtrace_silencers.rb +++ b/tryruby/config/initializers/backtrace_silencers.rb @@ -3,5 +3,5 @@ # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } -# You can also remove all the silencers if you're trying do debug a problem that might steem from framework code. -# Rails.backtrace_cleaner.remove_silencers! \ No newline at end of file +# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. +# Rails.backtrace_cleaner.remove_silencers! diff --git a/tryruby/config/initializers/inflections.rb b/tryruby/config/initializers/inflections.rb index d531b8b..d250860 100644 --- a/tryruby/config/initializers/inflections.rb +++ b/tryruby/config/initializers/inflections.rb @@ -1,10 +1,10 @@ # Be sure to restart your server when you modify this file. -# Add new inflection rules using the following format +# Add new inflection rules using the following format # (all these examples are active by default): -# ActiveSupport::Inflector.inflections do |inflect| + ActiveSupport::Inflector.inflections do |inflect| # inflect.plural /^(ox)$/i, '\1en' # inflect.singular /^(ox)en/i, '\1' -# inflect.irregular 'person', 'people' + inflect.irregular 'irb', 'irb' # inflect.uncountable %w( fish sheep ) -# end + end diff --git a/tryruby/config/initializers/session_store.rb b/tryruby/config/initializers/session_store.rb index b8817bb..5551e13 100644 --- a/tryruby/config/initializers/session_store.rb +++ b/tryruby/config/initializers/session_store.rb @@ -1,15 +1,8 @@ # Be sure to restart your server when you modify this file. -# Your secret key for verifying cookie session data integrity. -# If you change this key, all old sessions will become invalid! -# Make sure the secret is at least 30 characters and all random, -# no regular words or you'll be exposed to dictionary attacks. -ActionController::Base.session = { - :key => '_tryruby_session', - :secret => '522523ceaba8ca180200d1931128947224663751e03dc442c9cba14d758b80fe166eb4bb2c0b2521a78152e0ae5c3e29237bc826aadb55b8182b1b293af75163' -} +TryRuby::Application.config.session_store :cookie_store, :key => '_TryRuby_session' # Use the database for sessions instead of the cookie-based default, # which shouldn't be used to store highly confidential information -# (create the session table with "rake db:sessions:create") -# ActionController::Base.session_store = :active_record_store +# (create the session table with "rails generate session_migration") +# TryRuby::Application.config.session_store :active_record_store diff --git a/tryruby/config/locales/en.yml b/tryruby/config/locales/en.yml index f265c06..a747bfa 100644 --- a/tryruby/config/locales/en.yml +++ b/tryruby/config/locales/en.yml @@ -2,4 +2,4 @@ # See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points. en: - hello: "Hello world" \ No newline at end of file + hello: "Hello world" diff --git a/tryruby/config/routes.rb b/tryruby/config/routes.rb index cc9cbdb..3d5bd3f 100644 --- a/tryruby/config/routes.rb +++ b/tryruby/config/routes.rb @@ -1,7 +1,64 @@ -ActionController::Routing::Routes.draw do |map| - # You can have the root of your site routed with map.root -- just remember to delete public/index.html. - map.root :controller => "tryruby" - - map.connect ':controller/:action/:id' - map.connect ':controller/:action/:id.:format' +TryRuby::Application.routes.draw do + resources :irb + + # The priority is based upon order of creation: + # first created -> highest priority. + root :to => "tryruby#index" + match '/tryruby/run' => 'tryruby#run' + # connect ':controller/:action/:id' + # connect ':controller/:action/:id.:format' + + # Sample of regular route: + # match 'products/:id' => 'catalog#view' + # Keep in mind you can assign values other than :controller and :action + + # Sample of named route: + # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase + # This route can be invoked with purchase_url(:id => product.id) + + # Sample resource route (maps HTTP verbs to controller actions automatically): + # resources :products + + # Sample resource route with options: + # resources :products do + # member do + # get 'short' + # post 'toggle' + # end + # + # collection do + # get 'sold' + # end + # end + + # Sample resource route with sub-resources: + # resources :products do + # resources :comments, :sales + # resource :seller + # end + + # Sample resource route with more complex sub-resources + # resources :products do + # resources :comments + # resources :sales do + # get 'recent', :on => :collection + # end + # end + + # Sample resource route within a namespace: + # namespace :admin do + # # Directs /admin/products/* to Admin::ProductsController + # # (app/controllers/admin/products_controller.rb) + # resources :products + # end + + # You can have the root of your site routed with "root" + # just remember to delete public/index.html. + # root :to => "welcome#index" + + # See how all your routes lay out with "rake routes" + + # This is a legacy wild controller route that's not recommended for RESTful applications. + # Note: This route will make all actions in every controller accessible via GET requests. + # match ':controller(/:action(/:id(.:format)))' end diff --git a/tryruby/db/seeds.rb b/tryruby/db/seeds.rb index 3174d0c..664d8c7 100644 --- a/tryruby/db/seeds.rb +++ b/tryruby/db/seeds.rb @@ -2,6 +2,6 @@ # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). # # Examples: -# +# # cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }]) -# Major.create(:name => 'Daley', :city => cities.first) +# Mayor.create(:name => 'Daley', :city => cities.first) diff --git a/tryruby/lib/tryruby.rb b/tryruby/lib/tryruby.rb index e6933a8..4bd5b04 100644 --- a/tryruby/lib/tryruby.rb +++ b/tryruby/lib/tryruby.rb @@ -3,6 +3,8 @@ require 'setup.rb' require 'fakefs/safe' + + module FakeFS class Dir @@ -252,7 +254,7 @@ def run_line(code) result = Thread.new { eval cmd, TOPLEVEL_BINDING }.value rescue SecurityError => e puts e - return Output.illegal + return Output.illegal :illegal => e, :output => get_stdout rescue Exception => e return Output.error :error => e, :output => get_stdout ensure diff --git a/tryruby/public/images/header.png b/tryruby/public/images/header.png index 1a6a3f243063ba8e2a93933357efbd3174f581ae..d6b9aa0f3ce2e738d3d12c68b52c78175322741c 100644 GIT binary patch literal 51873 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 diff --git a/tryruby/public/javascripts/jquery.console.js b/tryruby/public/javascripts/jquery.console.js index 651da47..d45390d 100644 --- a/tryruby/public/javascripts/jquery.console.js +++ b/tryruby/public/javascripts/jquery.console.js @@ -1,7 +1,7 @@ // JQuery Console 1.0 // Sun Feb 21 20:28:47 GMT 2010 // -// Copyright 2010 Chris Done. All rights reserved. +// Copyright 2010 Chris Done, Simon David Pratt. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions @@ -10,43 +10,86 @@ // 1. Redistributions of source code must retain the above // copyright notice, this list of conditions and the following // disclaimer. - +// // 2. Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following // disclaimer in the documentation and/or other materials // provided with the distribution. // -// THIS SOFTWARE IS PROVIDED BY CHRIS DONE ``AS IS'' AND ANY EXPRESS -// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL CHRIS DONE OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -// OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -// DAMAGE. - -// The views and conclusions contained in the software and -// documentation are those of the authors and should not be -// interpreted as representing official policies, either expressed or -// implied, of Chris Done. -// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + // TESTED ON // Internet Explorer 6 // Opera 10.01 // Chromium 4.0.237.0 (Ubuntu build 31094) -// Firefox 3.5.8 +// Firefox 3.5.8, 3.6.2 (Mac) +// Safari 4.0.5 (6531.22.7) (Mac) +// Google Chrome 5.0.375.55 (Mac) (function($){ $.fn.console = function(config){ //////////////////////////////////////////////////////////////////////// // Constants // Some are enums, data types, others just for optimisation - var keyCodes = { left:37,right:39,up:38,down:40,back:8,del:46, - end:35,start:36,ret:13 }; + var keyCodes = { + // left + 37: moveBackward, + // right + 39: moveForward, + // up + 38: previousHistory, + // down + 40: nextHistory, + // backspace + 8: backDelete, + // delete + 46: forwardDelete, + // end + 35: moveToEnd, + // start + 36: moveToStart, + // return + 13: commandTrigger, + // tab + 18: doNothing + }; + var ctrlCodes = { + // C-a + 65: moveToStart, + // C-e + 69: moveToEnd, + // C-d + 68: forwardDelete, + // C-n + 78: nextHistory, + // C-p + 80: previousHistory, + // C-b + 66: moveBackward, + // C-f + 70: moveForward, + // C-k + 75: deleteUntilEnd + }; + var altCodes = { + // M-f + 70: moveToNextWord, + // M-b + 66: moveToPreviousWord, + // M-d + 68: deleteNextWord + }; var cursor = ' '; // Opera only works with this character, not or ­, // but IE6 displays this character, which is bad, so just use @@ -76,6 +119,10 @@ // variable below to ignore the keypress event if the keydown // event succeeds. var cancelKeyPress = 0; + // When this value is false, the prompt will not respond to input + var acceptInput = true; + // When this value is true, the command has been canceled + var cancelCommand = false; // External exports object var extern = {}; @@ -98,6 +145,7 @@ },100); } extern.inner = inner; + extern.typer = typer; extern.scrollToBottom = scrollToBottom; })(); @@ -152,6 +200,8 @@ function newPromptBox() { column = 0; promptText = ''; + ringn = 0; // Reset the position of the history ring + enableInput(); promptBox = $('
        '); var label = $(''); promptBox.append(label.text(promptLabel).show()); @@ -185,93 +235,50 @@ typer.keydown(function(e){ cancelKeyPress = 0; var keyCode = e.keyCode; - if (isControlCharacter(keyCode)) { - cancelKeyPress = keyCode; - if (!typer.consoleControl(keyCode)) { - return false; - } - } + // C-c: cancel the execution + if(e.ctrlKey && keyCode == 67) { + cancelKeyPress = keyCode; + cancelExecution(); + return false; + } + if (acceptInput) { + if (keyCode in keyCodes) { + cancelKeyPress = keyCode; + (keyCodes[keyCode])(); + return false; + } else if (e.ctrlKey && keyCode in ctrlCodes) { + cancelKeyPress = keyCode; + (ctrlCodes[keyCode])(); + return false; + } else if (e.altKey && keyCode in altCodes) { + cancelKeyPress = keyCode; + (altCodes[keyCode])(); + return false; + } + } }); //////////////////////////////////////////////////////////////////////// // Handle key press typer.keypress(function(e){ var keyCode = e.keyCode || e.which; - if (cancelKeyPress != keyCode && keyCode >= 32){ + if (isIgnorableKey(e)) { + return false; + } + if (acceptInput && cancelKeyPress != keyCode && keyCode >= 32){ if (cancelKeyPress) return false; - if (typeof config.charInsertTrigger == 'function' && - config.charInsertTrigger(keyCode)) + if (typeof config.charInsertTrigger == 'undefined' || + (typeof config.charInsertTrigger == 'function' && + config.charInsertTrigger(keyCode,promptText))) typer.consoleInsert(keyCode); } if ($.browser.webkit) return false; }); - // Is a keycode a contorl character? - // E.g. up, down, left, right, backspc, return, etc. - function isControlCharacter(keyCode){ - // TODO: Make more precise/fast. - return ( - (keyCode >= keyCodes.left && keyCode <= keyCodes.down) - || keyCode == keyCodes.back || keyCode == keyCodes.del - || keyCode == keyCodes.end || keyCode == keyCodes.start - || keyCode == keyCodes.ret - ); - }; - - //////////////////////////////////////////////////////////////////////// - // Handle console control keys - // E.g. up, down, left, right, backspc, return, etc. - typer.consoleControl = function(keyCode){ - switch (keyCode){ - case keyCodes.left:{ - moveColumn(-1); - updatePromptDisplay(); - return false; - break; - } - case keyCodes.right:{ - moveColumn(1); - updatePromptDisplay(); - return false; - break; - } - case keyCodes.back:{ - if (moveColumn(-1)){ - deleteCharAtPos(); - updatePromptDisplay(); - } - return false; - break; - } - case keyCodes.del:{ - if (deleteCharAtPos()) - updatePromptDisplay(); - return false; - break; - } - case keyCodes.end:{ - if (moveColumn(promptText.length-column)) - updatePromptDisplay(); - return false; - break; - } - case keyCodes.start:{ - if (moveColumn(-column)) - updatePromptDisplay(); - return false; - break; - } - case keyCodes.ret:{ - commandTrigger(); return false; - } - case keyCodes.up:{ - rotateHistory(-1); return false; - } - case keyCodes.down:{ - rotateHistory(1); return false; - } - default: //alert("Unknown control character: " + keyCode); - } + function isIgnorableKey(e) { + // for now just filter alt+tab that we receive on some platforms when + // user switches windows (goes away from the browser) + return ((e.keyCode == keyCodes.tab || e.keyCode == 192) && e.altKey); }; //////////////////////////////////////////////////////////////////////// @@ -301,6 +308,14 @@ updatePromptDisplay(); }; + function previousHistory() { + rotateHistory(-1); + }; + + function nextHistory() { + rotateHistory(1); + }; + // Add something to the history ring function addToHistory(line){ history.push(line); @@ -309,7 +324,7 @@ // Delete the character at the current position function deleteCharAtPos(){ - if (promptText != ''){ + if (column < promptText.length){ promptText = promptText.substring(0,column) + promptText.substring(column+1); @@ -318,6 +333,41 @@ } else return false; }; + function backDelete() { + if (moveColumn(-1)){ + deleteCharAtPos(); + updatePromptDisplay(); + } + }; + + function forwardDelete() { + if (deleteCharAtPos()) + updatePromptDisplay(); + }; + + function deleteUntilEnd() { + while(deleteCharAtPos()) { + updatePromptDisplay(); + } + }; + + function deleteNextWord() { + // A word is defined within this context as a series of alphanumeric + // characters. + // Delete up to the next alphanumeric character + while(column < promptText.length && + !isCharAlphanumeric(promptText[column])) { + deleteCharAtPos(); + updatePromptDisplay(); + } + // Then, delete until the next non-alphanumeric character + while(column < promptText.length && + isCharAlphanumeric(promptText[column])) { + deleteCharAtPos(); + updatePromptDisplay(); + } + }; + //////////////////////////////////////////////////////////////////////// // Validate command and trigger it if valid, or show a validation error function commandTrigger() { @@ -341,35 +391,48 @@ inner.attr({ scrollTop: inner.attr("scrollHeight") });; }; + function cancelExecution() { + if(typeof config.cancelHandle == 'function') { + config.cancelHandle(); + } + } + //////////////////////////////////////////////////////////////////////// // Handle a command function handleCommand() { if (typeof config.commandHandle == 'function') { + disableInput(); + addToHistory(promptText); var ret = config.commandHandle(promptText,function(msgs){ commandResult(msgs); }); if (typeof ret == 'boolean') { if (ret) { // Command succeeded without a result. - addToHistory(promptText); commandResult(); } else { - addToHistory(promptText); commandResult('Command failed.', "jquery-console-message-error"); } } else if (typeof ret == "string") { - addToHistory(promptText); commandResult(ret,"jquery-console-message-success"); - } else if (typeof ret == 'undefined') { - addToHistory(promptText); - } else if (ret.length) { - addToHistory(promptText); + } else if (typeof ret == 'object' && ret.length) { commandResult(ret); } } }; + //////////////////////////////////////////////////////////////////////// + // Disable input + function disableInput() { + acceptInput = false; + }; + + // Enable input + function enableInput() { + acceptInput = true; + } + //////////////////////////////////////////////////////////////////////// // Reset the prompt in invalid command function commandResult(msg,className) { @@ -419,6 +482,78 @@ } else return false; }; + function moveForward() { + if(moveColumn(1)) { + updatePromptDisplay(); + return true; + } + return false; + }; + + function moveBackward() { + if(moveColumn(-1)) { + updatePromptDisplay(); + return true; + } + return false; + }; + + function moveToStart() { + if (moveColumn(-column)) + updatePromptDisplay(); + }; + + function moveToEnd() { + if (moveColumn(promptText.length-column)) + updatePromptDisplay(); + }; + + function moveToNextWord() { + while(column < promptText.length && + !isCharAlphanumeric(promptText[column]) && + moveForward()) { + } + while(column < promptText.length && + isCharAlphanumeric(promptText[column]) && + moveForward()) { + } + }; + + function moveToPreviousWord() { + // Move backward until we find the first alphanumeric + while(column -1 >= 0 && + !isCharAlphanumeric(promptText[column-1]) && + moveBackward()) { + } + // Move until we find the first non-alphanumeric + while(column -1 >= 0 && + isCharAlphanumeric(promptText[column-1]) && + moveBackward()) { + } + }; + + function isCharAlphanumeric(charToTest) { + if(typeof charToTest == 'string') { + var code = charToTest.charCodeAt(); + return (code >= 'A'.charCodeAt() && code <= 'Z'.charCodeAt()) || + (code >= 'a'.charCodeAt() && code <= 'z'.charCodeAt()) || + (code >= '0'.charCodeAt() && code <= '9'.charCodeAt()); + } + return false; + }; + + function doNothing() {}; + + extern.promptText = function(text){ + if (text) { + promptText = text; + if (column > promptText.length) + column = promptText.length; + updatePromptDisplay(); + } + return promptText; + }; + //////////////////////////////////////////////////////////////////////// // Update the prompt display function updatePromptDisplay(){ diff --git a/tryruby/public/stylesheets/site.css b/tryruby/public/stylesheets/site.css index 307347e..62b1526 100755 --- a/tryruby/public/stylesheets/site.css +++ b/tryruby/public/stylesheets/site.css @@ -5,7 +5,7 @@ body { } h1, h2, h3, h4 { font-family: georgia, serif; - margin: 10px 16px; padding: 0; + margin: 10px 45px; padding: 0; } h1 { color: #333; @@ -37,12 +37,12 @@ input.keyboard-selector-input { _top: expression(eval(document.body.scrollTop)); left: -300px; } -#container { +.container { width: 678px; margin: 0 auto; text-align: left; } -#content { +.content { width: 712px; background: url(/images/tile.png) repeat-y; } @@ -73,7 +73,7 @@ p#lbClose { p#lbClose a { display: inline; } -#shellwin { +.shellwin { width: 712px; padding-left: 12px; background: url(/images/background.png) no-repeat; @@ -149,26 +149,25 @@ code strong { background-color: #dcffb9; padding: 1px 3px; } ul.commands li strong { display: block; float: left; width: 60px; border: none; } /* irb terminal */ -#terminal { - background-color: #f2f2f0; +.terminal { + background-color: #ffffff; border: solid 1px #204a87; width: 678px; height: 240px; overflow: auto; } -#irb { - visibility: hidden; - padding: 4px; margin: 0; +.console { + padding: 4px; margin-left: -50px; font-family: "Andale Mono", courier, fixed, monospace; font-size: 14px; line-height: 16px; color: #204a87; text-align: left; + width: 664px; + height:220px; } -#irb div { - margin: 0; padding: 0; -} -#irb div b { + +.console div b { background-color: #874a20; color: #fedeac; } @@ -209,3 +208,171 @@ span.back_purple { background-color: #5c3566; } span.back_lt_purple { background-color: #ad7fa8; } span.back_brown { background-color: #8f5902; } span.back_lt_brown { background-color: #b9b96e; } + +/** no ways***/ + +div.main-wrapper-bottom { + height:4px;background-position: 0px -80px; background-repeat: no-repeat; + font-size:0 /* IE6, go figure */ +} +div.main-wrapper-borders { + background-position: -1731px 0; padding:15px; + background-repeat:repeat-y; +} +div.console-wrapper { + margin:0px auto ;width:566px; + cursor:text; + font-family:monospace; +} +div.console-wrapper-top { + height:3px;background-position: -50px -48px; background-repeat: no-repeat; + font-size:0 /* IE6, go figure */ +} +div.console-wrapper-bottom { + height:3px;background-position: -50px -51px; background-repeat: no-repeat; + font-size:0 /* IE6, go figure */ +} +div.console-wrapper-borders { + background-position: 0px 0px; padding:1px; + background-repeat:repeat-y; +} +div.guide-wrapper { + color:#fff; width:566px;margin-left:2px +} +div.guide-wrapper-top { + height:4px;background-position: 0 -65px; + font-size:0 /* IE6, go figure */ +} +div.guide-wrapper-bottom { + height:4px;background-position: 0 -70px; + font-size:0 /* IE6, go figure */ +} +div.guide-wrapper-borders { + background-position: -1166px 0px;padding:15px; + background-repeat:repeat-y; +} + +div.footer-wrapper-borders { + background-position: -566px 0px; padding:10px; + background-repeat:repeat-y; + font-size:12px +} +h1.main-header { + text-indent:-9999px; background-position: -49px 0px; + background-repeat: no-repeat; + width:318px; height:48px; margin-bottom:20px; + float:left +} + +div.footer { + line-height: 1.3em; +} + div.console div.jquery-console-inner +{ height:100%; overflow:auto; background:white} +div.console div.jquery-console-prompt-box +{ color:#437375; font-family:monospace; margin-top:0.5em; } +div.console div.jquery-console-prompt-box .prompt-done +{ cursor: pointer } +div.console div.jquery-console-prompt-box .prompt-done:hover +{ background:#453D5B; color: white; } +div.console div.jquery-console-focus span.jquery-console-cursor +{ background:#666; color:#fff; } +div.console div.jquery-console-message-error { + color:#ef0505; font-family:sans-serif; font-weight:bold; + padding-top:0.25em +} +div.console div.jquery-console-message-value +{ color:#000; font-family:monospace;padding-top:0.25em; font-weight: bold; } +div.console div.jquery-console-message-type +{ color:#382567; font-family:monospace;padding-left:0em;padding-top:0.25em; font-size:.9em } +div.console span.jquery-console-prompt-label { font-weight:bold } +div.console div.jquery-console-welcome { font-family:"DejaVu Sans",sans-serif; } + +div.share-wrapper { font-size:12px;padding:10px 0em 0em 10px } +div.share-wrapper strong { font-weight: bold } + +.clearfix:after { content:"."; display:block; height:0; clear:both; visibility:hidden } +div.menu { + float:right; + margin-right:2px; + margin-top:40px; + margin-bottom:5px +} +a.reset-btn { + float:left; + display:block; + width:59px; + height:24px; + background-position: -427px -18px; background-repeat: no-repeat; +} +a.reset-btn span { display:none } + +div.clear { clear:both } + + +div.console-wrapper .notice { + position:absolute; + bottom:0;right:0; + margin:1px; + background:#eee; + color:black; + padding:10px; + font-size:12px; + font-family:sans-serif; + font-weight:bold; +} +p.ajax-loader { background:url(../images/ajax-loader.gif); width:16px; height:16px;text-indent:-9999px } + +.notice a { padding:3px;background:#333;color:white} +.notice .action { text-align: right } + +/* Support Try Ruby! */ + + +a.trigger{ +position: absolute; +text-decoration: none; +top: 80px; right: 0; +font-size: 14px; +letter-spacing:-1px; +font-family: verdana, helvetica, arial, sans-serif; +color:#fff; +padding: 10px 10px 10px 10px; +font-weight: 500; +background:#333333 url(images/plus.png) 15% 55% no-repeat; +border:1px solid #444444; +-moz-border-radius-topleft: 20px; +-webkit-border-top-left-radius: 20px; +-moz-border-radius-bottomleft: 20px; +-webkit-border-bottom-left-radius: 20px; +-moz-border-radius-bottomright: 0px; +-webkit-border-bottom-right-radius: 0px; +display: block; +} + +a.trigger:hover{ +position: absolute; +text-decoration: none; +top: 80px; right: 0; +font-size: 14px; +letter-spacing:-1px; +font-family: verdana, helvetica, arial, sans-serif; +color:#fff; +padding: 10px 10px 10px 10px; +font-weight: 500; +background: green; +border:1px solid #444444; +-moz-border-radius-topleft: 20px; +-webkit-border-top-left-radius: 20px; +-moz-border-radius-bottomleft: 20px; +-webkit-border-bottom-left-radius: 20px; +-moz-border-radius-bottomright: 0px; +-webkit-border-bottom-right-radius: 0px; +display: block; +} + +a.active.trigger { +background:#222222 url(images/minus.png) 15% 55% no-repeat; +} + + \ No newline at end of file diff --git a/tryruby/test/performance/browsing_test.rb b/tryruby/test/performance/browsing_test.rb index 4b60558..867fc8c 100644 --- a/tryruby/test/performance/browsing_test.rb +++ b/tryruby/test/performance/browsing_test.rb @@ -1,8 +1,8 @@ require 'test_helper' -require 'performance_test_help' +require 'rails/performance_test_help' # Profiling results for each test method are written to tmp/performance. -class BrowsingTest < ActionController::PerformanceTest +class BrowsingTest < ActionDispatch::PerformanceTest def test_homepage get '/' end diff --git a/tryruby/test/test_helper.rb b/tryruby/test/test_helper.rb index 24632d8..8bf1192 100644 --- a/tryruby/test/test_helper.rb +++ b/tryruby/test/test_helper.rb @@ -1,60 +1,13 @@ ENV["RAILS_ENV"] = "test" -require File.expand_path(File.dirname(__FILE__) + "/../config/environment") -require 'test_help' -require 'rexml/document' -require 'hpricot' - -class Integer - def weeks - self * 7*24*60*60 - end -end - - -def run_script(session,line) - TryRuby.run_line(line) -end - -class TryRubyTestSession < TryRuby::Session - def initialize - @current_includes = [] - end - - attr_accessor :start_time, :current_statement - attr_accessor :nesting_level, :past_commands, :current_includes -end +require File.expand_path('../../config/environment', __FILE__) +require 'rails/test_help' class ActiveSupport::TestCase - # Transactional fixtures accelerate your tests by wrapping each test method - # in a transaction that's rolled back on completion. This ensures that the - # test database remains unchanged so your fixtures don't have to be reloaded - # between every test method. Fewer database queries means faster tests. - # - # Read Mike Clark's excellent walkthrough at - # http://clarkware.com/cgi/blosxom/2005/10/24#Rails10FastTesting - # - # Every Active Record database supports transactions except MyISAM tables - # in MySQL. Turn off transactional fixtures in this case; however, if you - # don't care one way or the other, switching from MyISAM to InnoDB tables - # is recommended. - # - # The only drawback to using transactional fixtures is when you actually - # need to test transactions. Since your test is bracketed by a transaction, - # any transactions started in your code will be automatically rolled back. - #self.use_transactional_fixtures = true - - # Instantiated fixtures are slow, but give you @david where otherwise you - # would need people(:david). If you don't want to migrate your existing - # test cases which use the @david style and don't mind the speed hit (each - # instantiated fixtures translates to a database query per test method), - # then set this back to true. - #self.use_instantiated_fixtures = false - # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order. # # Note: You'll currently still have to declare fixtures explicitly in integration tests # -- they do not yet inherit this setting - #fixtures :all + fixtures :all # Add more helper methods to be used by all tests here... end diff --git a/tryruby/tmp/pids/server.pid b/tryruby/tmp/pids/server.pid index ade6218..3acadad 100644 --- a/tryruby/tmp/pids/server.pid +++ b/tryruby/tmp/pids/server.pid @@ -1 +1 @@ -4772 \ No newline at end of file +48625 \ No newline at end of file From cb755c682984f33b934560271aa5021ac9546d3a Mon Sep 17 00:00:00 2001 From: Andrew McElroy Date: Mon, 21 Mar 2011 12:35:12 -0500 Subject: [PATCH 05/16] further updates --- public/index.html | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/public/index.html b/public/index.html index abc5b18..566f947 100644 --- a/public/index.html +++ b/public/index.html @@ -44,6 +44,47 @@
        +
        From 5a0a210b091ad0bc6fa41874c864a891e9e194f6 Mon Sep 17 00:00:00 2001 From: Andrew McElroy Date: Fri, 8 Jul 2011 17:21:51 -0500 Subject: [PATCH 06/16] hopefully i dont have duplicate directories --- non-rack-legacy/public/.gitignore | 2 + non-rack-legacy/public/blank.html | 4 + non-rack-legacy/public/comics.txt | 4 + non-rack-legacy/public/es_index.html | 96 + non-rack-legacy/public/images/background.png | Bin 0 -> 35315 bytes non-rack-legacy/public/images/footer.png | Bin 0 -> 6840 bytes non-rack-legacy/public/images/header.png | Bin 0 -> 51873 bytes non-rack-legacy/public/images/index.html | 8 + non-rack-legacy/public/images/tile.png | Bin 0 -> 305 bytes non-rack-legacy/public/index.html | 166 ++ non-rack-legacy/public/irb.cgi | 38 + .../public/javascripts/application.js | 2 + non-rack-legacy/public/javascripts/console.js | 288 +++ .../public/javascripts/controls.js | 963 ++++++++++ .../public/javascripts/dragdrop.js | 973 ++++++++++ non-rack-legacy/public/javascripts/effects.js | 1128 +++++++++++ non-rack-legacy/public/javascripts/facebox.js | 309 ++++ non-rack-legacy/public/javascripts/index.html | 8 + non-rack-legacy/public/javascripts/irb.js | 110 ++ .../public/javascripts/jQuery.irb.js | 1641 +++++++++++++++++ .../public/javascripts/jquery-1.3.2.min.js | 19 + .../public/javascripts/jquery-1.4.2.min.js | 154 ++ .../public/javascripts/jquery.console.js | 609 ++++++ .../public/javascripts/jquery.console.min.js | 1 + non-rack-legacy/public/javascripts/jquery.js | 32 + non-rack-legacy/public/javascripts/json2.js | 1 + non-rack-legacy/public/javascripts/lib.min.js | 159 ++ .../public/javascripts/mouseapp_2.js | 913 +++++++++ .../public/javascripts/mouseirb_2.js | 179 ++ .../public/javascripts/raphael-min.js | 113 ++ non-rack-legacy/public/js/index.html | 8 + non-rack-legacy/public/js/irb.js | 110 ++ non-rack-legacy/public/js/jquery-1.3.2.min.js | 19 + non-rack-legacy/public/js/jquery.js | 32 + non-rack-legacy/public/js/mouseapp_2.js | 913 +++++++++ non-rack-legacy/public/js/mouseirb_2.js | 179 ++ non-rack-legacy/public/keypress_test.html | 37 + non-rack-legacy/public/moods/index.html | 8 + non-rack-legacy/public/moods/sick.gif | Bin 0 -> 94 bytes non-rack-legacy/public/popup.rb | 114 ++ non-rack-legacy/public/setup.rb | 67 + non-rack-legacy/public/site.css | 211 +++ .../public/stylesheets/facebox.css | 83 + non-rack-legacy/public/stylesheets/reset.css | 46 + .../public/stylesheets/scaffold.css | 56 + non-rack-legacy/public/stylesheets/site.css | 378 ++++ non-rack-legacy/public/test.rb | 633 +++++++ non-rack-legacy/public/tryruby.rb | 174 ++ .../public/tutorials/es_intro.html | 666 +++++++ non-rack-legacy/public/tutorials/intro.html | 680 +++++++ .../public/tutorials/intro.html.broken | 638 +++++++ .../public/tutorials/intro_files/sick.gif | Bin 0 -> 94 bytes 52 files changed, 12972 insertions(+) create mode 100644 non-rack-legacy/public/.gitignore create mode 100755 non-rack-legacy/public/blank.html create mode 100755 non-rack-legacy/public/comics.txt create mode 100644 non-rack-legacy/public/es_index.html create mode 100755 non-rack-legacy/public/images/background.png create mode 100755 non-rack-legacy/public/images/footer.png create mode 100644 non-rack-legacy/public/images/header.png create mode 100755 non-rack-legacy/public/images/index.html create mode 100755 non-rack-legacy/public/images/tile.png create mode 100644 non-rack-legacy/public/index.html create mode 100755 non-rack-legacy/public/irb.cgi create mode 100644 non-rack-legacy/public/javascripts/application.js create mode 100644 non-rack-legacy/public/javascripts/console.js create mode 100644 non-rack-legacy/public/javascripts/controls.js create mode 100644 non-rack-legacy/public/javascripts/dragdrop.js create mode 100644 non-rack-legacy/public/javascripts/effects.js create mode 100755 non-rack-legacy/public/javascripts/facebox.js create mode 100755 non-rack-legacy/public/javascripts/index.html create mode 100755 non-rack-legacy/public/javascripts/irb.js create mode 100644 non-rack-legacy/public/javascripts/jQuery.irb.js create mode 100644 non-rack-legacy/public/javascripts/jquery-1.3.2.min.js create mode 100644 non-rack-legacy/public/javascripts/jquery-1.4.2.min.js create mode 100644 non-rack-legacy/public/javascripts/jquery.console.js create mode 100644 non-rack-legacy/public/javascripts/jquery.console.min.js create mode 100755 non-rack-legacy/public/javascripts/jquery.js create mode 100644 non-rack-legacy/public/javascripts/json2.js create mode 100644 non-rack-legacy/public/javascripts/lib.min.js create mode 100755 non-rack-legacy/public/javascripts/mouseapp_2.js create mode 100755 non-rack-legacy/public/javascripts/mouseirb_2.js create mode 100644 non-rack-legacy/public/javascripts/raphael-min.js create mode 100755 non-rack-legacy/public/js/index.html create mode 100755 non-rack-legacy/public/js/irb.js create mode 100644 non-rack-legacy/public/js/jquery-1.3.2.min.js create mode 100755 non-rack-legacy/public/js/jquery.js create mode 100755 non-rack-legacy/public/js/mouseapp_2.js create mode 100755 non-rack-legacy/public/js/mouseirb_2.js create mode 100644 non-rack-legacy/public/keypress_test.html create mode 100755 non-rack-legacy/public/moods/index.html create mode 100755 non-rack-legacy/public/moods/sick.gif create mode 100755 non-rack-legacy/public/popup.rb create mode 100644 non-rack-legacy/public/setup.rb create mode 100755 non-rack-legacy/public/site.css create mode 100755 non-rack-legacy/public/stylesheets/facebox.css create mode 100644 non-rack-legacy/public/stylesheets/reset.css create mode 100644 non-rack-legacy/public/stylesheets/scaffold.css create mode 100755 non-rack-legacy/public/stylesheets/site.css create mode 100755 non-rack-legacy/public/test.rb create mode 100644 non-rack-legacy/public/tryruby.rb create mode 100644 non-rack-legacy/public/tutorials/es_intro.html create mode 100644 non-rack-legacy/public/tutorials/intro.html create mode 100755 non-rack-legacy/public/tutorials/intro.html.broken create mode 100755 non-rack-legacy/public/tutorials/intro_files/sick.gif diff --git a/non-rack-legacy/public/.gitignore b/non-rack-legacy/public/.gitignore new file mode 100644 index 0000000..a1632ab --- /dev/null +++ b/non-rack-legacy/public/.gitignore @@ -0,0 +1,2 @@ +tmp/ + diff --git a/non-rack-legacy/public/blank.html b/non-rack-legacy/public/blank.html new file mode 100755 index 0000000..7879e1c --- /dev/null +++ b/non-rack-legacy/public/blank.html @@ -0,0 +1,4 @@ + + + + diff --git a/non-rack-legacy/public/comics.txt b/non-rack-legacy/public/comics.txt new file mode 100755 index 0000000..7dfc8e6 --- /dev/null +++ b/non-rack-legacy/public/comics.txt @@ -0,0 +1,4 @@ +Achewood: http://achewood.com/ +Dinosaur Comics: http://qwantz.com/ +Perry Bible Fellowship: http://cheston.com/pbf/archive.html +Get Your War On: http://mnftiu.cc/ diff --git a/non-rack-legacy/public/es_index.html b/non-rack-legacy/public/es_index.html new file mode 100644 index 0000000..7519e36 --- /dev/null +++ b/non-rack-legacy/public/es_index.html @@ -0,0 +1,96 @@ + + + + + try ruby! (en tu navegador) + + + + + + + + + +
        + +
        +
        +
        + +

        A Popup Browser

        +

        [x]

        +
        + +
        +
        + +
        +
        +
        +
        +
        +
        +

        ¿Tienes 15 minutos? ¡Prueba Ruby ahora mismo!

        +

        Ruby es un lenguaje de programación de Japón + (disponible en ruby-lang.org) + que está revolucionando la web. + La belleza de Ruby se encuentra en su balance entre la simplicidad y el poder.

        + +

        Prueba código Ruby en el prompt de arriba. Además de los métodos + originales de Ruby, los siguientes comandos están disponibles:

        +
          +
        • help + Empieza el tutorial interactivo de 15 minutos. ¡Creeme, es muy básico!
        • +
        • help 2 + Salta al capítulo 2.
        • + +
        • clear + Limpia la pantalla. Útil si tu navegador empieza a alerdarce. + Tu historial de comandos será recordado. +
        • back + Retrocede una pantalla en el tutorial.
        • +
        • reset + Resetea el interprete. (o Ctrl-D!)
        • +
        • next + Te permite saltear la siguiente lección
        • + +
        • time + Detiene el reloj. Imprime cuanto tiempo tu sesión estuvo abierta.
        • +
        +

        Si te pasa de dejar o refrescar la página, tu sesión seguirá aquí a menos que + se deje inactiva por diez minutos.

        +
        +
        +
        + +
        +
        ¿Atrapado en los dos puntos? Unas comillas o algo fue dejado abierto. Escribe: reset o aprieta Ctrl-D.
        +
        + +

        This place was sired by why the lucky stiff. + Please contact me using the email address at that link.is maintained by Andrew McElroy and David Miani. For support issues, please post a ticket or contact Sophrinix on github.
        Por asuntos de traducción, mandar un ticket o contactarse con Cristian Re (leizzer) en Github.
        +

        + +
        + + + + + + + + + + diff --git a/non-rack-legacy/public/images/background.png b/non-rack-legacy/public/images/background.png new file mode 100755 index 0000000000000000000000000000000000000000..3a2dee031614731e46c00b5f8416d471908af982 GIT binary patch literal 35315 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 b}X6WEoFQ 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 + + + + +

        you shouldn't be here.. kicking you out!

        + + diff --git a/non-rack-legacy/public/images/tile.png b/non-rack-legacy/public/images/tile.png new file mode 100755 index 0000000000000000000000000000000000000000..399139f26d14e29a407d8b4bb8473ad2279edc41 GIT binary patch literal 305 zcmV-10nYx3P)e#ZdVeV@YYlo&$tx`(sO@ILaF1IwM9!1&Y00000NkvXXu0mjf DW=Vhn literal 0 HcmV?d00001 diff --git a/non-rack-legacy/public/index.html b/non-rack-legacy/public/index.html new file mode 100644 index 0000000..566f947 --- /dev/null +++ b/non-rack-legacy/public/index.html @@ -0,0 +1,166 @@ + + + + + + try ruby! (in your browser) + + + + + + + + + + + + + + + + + + +
        + +
        + +
        +
        + +

        A Popup Browser

        +

        [x]

        +
        + +
        +
        + +
        +
        +
        +
        +
        +
        +

        Got 15 minutes? Give Ruby a shot right now!

        +

        Ruby is a programming language from Japan + (available at ruby-lang.org) + which is revolutionizing the web. + The beauty of Ruby is found in its balance between simplicity and power.

        + +

        Try out Ruby code in the prompt above. In addition + to Ruby's builtin methods, the following commands are available:

        +
          +
        • help + Start the 15 minute interactive tutorial. Trust me, it's very basic!
        • +
        • help 2 + Hop to chapter two.
        • + +
        • clear + Clear screen. Useful if your browser starts slowing down. + Your command history will be remembered. +
        • back + Go back one screen in the tutorial.
        • +
        • reset + Reset the interpreter if you get too deep. (or Ctrl-D!)
        • +
        • next +Allows you to skip to the next section of a lesson.
        • + +
        • time + A stopwatch. Prints the time your session has been open.
        • +
        +

        If you happen to leave or refresh the page, your session will still be here for + unless it is left inactive for ten minutes.

        +
        +
        +
        + +
        +
        Trapped in double dots? A quote or something was left open. Type: reset or hit Ctrl-D.
        +
        + +

        This place was sired by why the lucky stiff. + Please contact me using the email address at that link.is maintained by Andrew McElroy and David Miani. For support issues, please post a ticket or contact Sophrinix on github. +

        + +
        + + + + + + + + +Please Support
        Try Ruby!
        + + + diff --git a/non-rack-legacy/public/irb.cgi b/non-rack-legacy/public/irb.cgi new file mode 100755 index 0000000..9bf2d06 --- /dev/null +++ b/non-rack-legacy/public/irb.cgi @@ -0,0 +1,38 @@ +#!/usr/local/bin/ruby + +require './tryruby.rb' +require 'cgi' +require 'cgi/session' +require 'cgi/session/pstore' +require './popup.rb' + +class TryRubyCGISession# < TryRuby::Session + attr_accessor :cgi, :session + + def initialize + @session = CGI::Session.new @cgi = CGI.new, + 'database_manager' => CGI::Session::PStore, # use PStore + 'session_key' => 'trb_sess_id', # custom $session key + 'session_expires' => Time.now + 60 * 60, # 60 minute timeout + 'prefix' => 'pstore_sid_', #Pstore option + 'tmpdir' => 'tmp' # Temp Directory for sessions + + + @session['start_time'] ||= Time.now + @session['current_statement'] ||= '' + @session['past_commands'] ||= '' + end + + def header + @cgi.header 'text/plain' + end + + [:current_statement, :past_commands, :start_time].each do |accessor| + define_method(accessor) { @session[accessor.to_s] } + define_method(:"#{accessor.to_s}=") { |new_val| @session[accessor.to_s] = new_val } + end +end + +TryRuby.session = TryRubyCGISession.new + +print TryRuby.session.header + TryRuby.run_line(TryRuby.session.cgi['cmd']).format diff --git a/non-rack-legacy/public/javascripts/application.js b/non-rack-legacy/public/javascripts/application.js new file mode 100644 index 0000000..fe45776 --- /dev/null +++ b/non-rack-legacy/public/javascripts/application.js @@ -0,0 +1,2 @@ +// Place your application-specific JavaScript functions and classes here +// This file is automatically included by javascript_include_tag :defaults diff --git a/non-rack-legacy/public/javascripts/console.js b/non-rack-legacy/public/javascripts/console.js new file mode 100644 index 0000000..e7e8b79 --- /dev/null +++ b/non-rack-legacy/public/javascripts/console.js @@ -0,0 +1,288 @@ +jQuery.fn.debug = function() { + var msg = jqArray.args(arguments); + $("
        ").addClass("error").text(msg.join(", ")).prependTo(this); +} + +jQConsole = function(input, output) { + + var args = jqArray.args + + var input = input; + + // History + var command_history = []; + var command_selected = 0; + + var local_scope = safe_scope(); + + function hide_fn(fn) { return function() { return fn.apply(this, arguments); } } + hide_fn.desc = "A function that creates a wrapper that hides the implementation of another function"; + function queue_fn(fn, time) { if(!time) time = 0; return function() { setTimeout(fn, time); } } + queue_fn.desc = "Turns a function into a function that's called later"; + + var keys = function (o) { + var r = []; + if (typeof o != "object") return r; + for (var k in o) r.push(k); + return r; + } + var refocus = queue_fn(function() { input.blur().focus(); }); + var reset_input = queue_fn(function() { input.val("").blur().focus(); }); + function no_recurse(fn, max_depth) { + var count = 0; + if(!max_depth) max_depth = 1; + return function() { + count++; + if(count > max_depth) { + count--; return; + } else { + fn.apply(this, arguments); + } + } + } + + function hook_fn(fn, listener) { + fn.listener = function() { return listener; } + fn.apply = function(thisArg, argArray) { + if(fn == caller) return; + listener(); + return fn.apply(thisArg, argArray); + }; + } + + hook_fn(history, function() { print("Yo"); }); + + $(document).ready(page_onload); + + function page_onload() { + input = $(input); + output = $(output); + input.keypress(map_keyboard()); + $(document).click(refocus); + refocus(); + } + page_onload = hide_fn(page_onload); + + function clear() { output.html(""); } + + function history() { + return command_history.join("\n"); + } + + var keyLogging = false; + + function map_keyboard() { + var cmdKeys = keymap(); + with(cmdKeys) { + mapKeyCode(toggleKeyLogging, 120); + map(executeCommand, {keyCode:13, ctrlKey:true}); + //mapKeyCode(executeCommand, 13); + mapKeyCode(refocus, 9); + map(historyLast, {keyCode:38, ctrlKey:true}); + map(historyNext, {keyCode:40, ctrlKey:true}); + map(function() { return false; }, {keyCode:123}); + } + return function(e) { + if(keyLogging) + log("keyCode: " + e.keyCode, " shiftKey: " + e.shiftKey, " ctrlKey: " + e.ctrlKey); + resize_input(); + return cmdKeys.dispatch(e); + } + } + + function toggleKeyLogging() { keyLogging = !keyLogging; } + + function historyLast() { + command_selected = Math.max(0, command_selected - 1); + edit_command(command_history[command_selected]); + } + + function historyNext() { + command_selected = Math.min(command_history.length, command_selected + 1); + var cmd = (command_selected == command_history.length) ? "" : command_history[command_selected]; + edit_command(cmd); + } + + function tryComplete() { + + refocus(); + } + + function executeCommand(cmd) { + cmd = (!cmd) ? input.val() : cmd; + reset_input(); + var result = evalInScope(cmd, default_scope); + command_selected = command_history.length; + logCommand(cmd, result); + setTimeout(function() { input.attr("rows", 1); }, 2); + return false; + } + + function evalInScope(cmd, scope) { + try { + + //if(!scope) return eval.apply(our_scope, [cmd]); + with(scope) { + with(jQConsole.our_scope) { + return eval(cmd); + } + } + + //move_modified_scope(local_scope, global_scope); + } + catch(e) { + return e.message; + } + } + + function move_modified_scope(l, g) { + + for(var k in g) { + if(g[k] && typeof l[k] == 'undefined') { + l[k] = g[k]; + g[k] = null; + } + } + } + + function safe_scope() { + var s = {}, g = jQConsole.global_scope; + for(var k in g) { s[k] = null; } + s.global_scope = jQConsole.global_scope; + return s; + } + + var encoders = { + "object": function(o, l) { + if(o.constructor == Array) + return encode_array(o); + //return "[array]"; + return "{ " + encode_obj(o, l) + " }"; + }, + "function": function(v) { return v.toString(); }, + "string": function(v) { return "\"" + v + "\""; }, + "undefined": function() { return "undefined"; }, + _default: function(v) { return v.toString(); } + } + + function encode_array(a) { + var r = a.map(enc); + return "[" + r.join(",") + "]"; + } + + enc = function(v, l, root) { + root = root || true; + if(v == null) return (root) ? "" : "null" + l; + if(encoders[typeof v]) return encoders[typeof v](v); + //log("enc", v, l); + return encoders._default(v, l); + } + + function encode_obj(val, expand) { + if(expand <= 0) { return val.toString(); } + var r = []; + for(var i in val) { + r.push(i + ": " + enc(val[i], expand - 1, false)); + } + return r.join(",\n"); + } + + function encode_reg(s) { + return s.replace(/([\\/\t\n])/g, "\\$1"); + } + + function reg_lookup_fn(lookup) { + var re = new RegExp(encode_reg(keys(lookup).join("")), "ig"); + return re; + } + + function print(msg) { + var className = (typeof msg == "function") ? "cmd" : "print"; + msg = enc(msg, 3); + if(!msg) return; + var out = $($.PRE({"className":className}, msg)); + if(className == "cmd") { out.click(select_command); } + output.prepend(out); + } + + function logCommand(cmd, result) { + command_history.push(cmd); + if(result != undefined) { + output.prepend(jQuery.dump(result)); + } + $($.PRE({className:'cmd'}, cmd)).click(select_command).prependTo(output); + //print(result); + return cmd; + } + + function select_command() { + edit_command($(this).text()); + } + + function edit_command(cmd) { + input.val(cmd); + resize_input(); + input.get(0).select(); + } + + function log() { + var msg = args(arguments); + $("
        ").text(msg.join(", ")).prependTo(output); + } + + function resize_input() + { + setTimeout(do_resize, 0); + + function do_resize() { + var rows = input.val().split(/\n/).length + // + 1 // prevent scrollbar flickering in Mozilla + + (window.opera ? 1 : 0); // leave room for scrollbar in Opera + + // without this check, it is impossible to select text in Opera 7.60 or Opera 8.0. + if (input.attr("rows") != rows) + input.attr("rows", rows); + } + } + + var default_scope = { + "log": log, + "history": history, + alert: function(msg) { alert(msg); } + } + disable_functions(default_scope, "window,document,t1"); + + function disable_functions(obj, list) { + var list = list.split(","); + for(var i in list) { + obj[list[i]] = {}; + } + } + + return this; +}; + +jQuery.extend(jQuery.fn, { + "autoresize": function() + { + var thisp = this; + setTimeout(do_resize, 0); + + function do_resize() { + var s = thisp.val() || ""; + var rows = s.split(/\n/).length; + // + 1 // prevent scrollbar flickering in Mozilla + + (window.opera ? 1 : 0); // leave room for scrollbar in Opera + + // without this check, it is impossible to select text in Opera 7.60 or Opera 8.0. + if (thisp.attr("rows") != rows) + thisp.attr("rows", rows); + } + return this; + } +}) + + + +jQConsole.global_scope = this; +jQConsole.our_scope = {}; \ No newline at end of file diff --git a/non-rack-legacy/public/javascripts/controls.js b/non-rack-legacy/public/javascripts/controls.js new file mode 100644 index 0000000..ca29aef --- /dev/null +++ b/non-rack-legacy/public/javascripts/controls.js @@ -0,0 +1,963 @@ +// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// (c) 2005-2008 Ivan Krstic (http://blogs.law.harvard.edu/ivan) +// (c) 2005-2008 Jon Tirsen (http://www.tirsen.com) +// Contributors: +// Richard Livsey +// Rahul Bhargava +// Rob Wills +// +// script.aculo.us is freely distributable under the terms of an MIT-style license. +// For details, see the script.aculo.us web site: http://script.aculo.us/ + +// Autocompleter.Base handles all the autocompletion functionality +// that's independent of the data source for autocompletion. This +// includes drawing the autocompletion menu, observing keyboard +// and mouse events, and similar. +// +// Specific autocompleters need to provide, at the very least, +// a getUpdatedChoices function that will be invoked every time +// the text inside the monitored textbox changes. This method +// should get the text for which to provide autocompletion by +// invoking this.getToken(), NOT by directly accessing +// this.element.value. This is to allow incremental tokenized +// autocompletion. Specific auto-completion logic (AJAX, etc) +// belongs in getUpdatedChoices. +// +// Tokenized incremental autocompletion is enabled automatically +// when an autocompleter is instantiated with the 'tokens' option +// in the options parameter, e.g.: +// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' }); +// will incrementally autocomplete with a comma as the token. +// Additionally, ',' in the above example can be replaced with +// a token array, e.g. { tokens: [',', '\n'] } which +// enables autocompletion on multiple tokens. This is most +// useful when one of the tokens is \n (a newline), as it +// allows smart autocompletion after linebreaks. + +if(typeof Effect == 'undefined') + throw("controls.js requires including script.aculo.us' effects.js library"); + +var Autocompleter = { }; +Autocompleter.Base = Class.create({ + baseInitialize: function(element, update, options) { + element = $(element); + this.element = element; + this.update = $(update); + this.hasFocus = false; + this.changed = false; + this.active = false; + this.index = 0; + this.entryCount = 0; + this.oldElementValue = this.element.value; + + if(this.setOptions) + this.setOptions(options); + else + this.options = options || { }; + + this.options.paramName = this.options.paramName || this.element.name; + this.options.tokens = this.options.tokens || []; + this.options.frequency = this.options.frequency || 0.4; + this.options.minChars = this.options.minChars || 1; + this.options.onShow = this.options.onShow || + function(element, update){ + if(!update.style.position || update.style.position=='absolute') { + update.style.position = 'absolute'; + Position.clone(element, update, { + setHeight: false, + offsetTop: element.offsetHeight + }); + } + Effect.Appear(update,{duration:0.15}); + }; + this.options.onHide = this.options.onHide || + function(element, update){ new Effect.Fade(update,{duration:0.15}) }; + + if(typeof(this.options.tokens) == 'string') + this.options.tokens = new Array(this.options.tokens); + // Force carriage returns as token delimiters anyway + if (!this.options.tokens.include('\n')) + this.options.tokens.push('\n'); + + this.observer = null; + + this.element.setAttribute('autocomplete','off'); + + Element.hide(this.update); + + Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this)); + Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this)); + }, + + show: function() { + if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update); + if(!this.iefix && + (Prototype.Browser.IE) && + (Element.getStyle(this.update, 'position')=='absolute')) { + new Insertion.After(this.update, + ''); + this.iefix = $(this.update.id+'_iefix'); + } + if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50); + }, + + fixIEOverlapping: function() { + Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)}); + this.iefix.style.zIndex = 1; + this.update.style.zIndex = 2; + Element.show(this.iefix); + }, + + hide: function() { + this.stopIndicator(); + if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update); + if(this.iefix) Element.hide(this.iefix); + }, + + startIndicator: function() { + if(this.options.indicator) Element.show(this.options.indicator); + }, + + stopIndicator: function() { + if(this.options.indicator) Element.hide(this.options.indicator); + }, + + onKeyPress: function(event) { + if(this.active) + switch(event.keyCode) { + case Event.KEY_TAB: + case Event.KEY_RETURN: + this.selectEntry(); + Event.stop(event); + case Event.KEY_ESC: + this.hide(); + this.active = false; + Event.stop(event); + return; + case Event.KEY_LEFT: + case Event.KEY_RIGHT: + return; + case Event.KEY_UP: + this.markPrevious(); + this.render(); + Event.stop(event); + return; + case Event.KEY_DOWN: + this.markNext(); + this.render(); + Event.stop(event); + return; + } + else + if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || + (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return; + + this.changed = true; + this.hasFocus = true; + + if(this.observer) clearTimeout(this.observer); + this.observer = + setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); + }, + + activate: function() { + this.changed = false; + this.hasFocus = true; + this.getUpdatedChoices(); + }, + + onHover: function(event) { + var element = Event.findElement(event, 'LI'); + if(this.index != element.autocompleteIndex) + { + this.index = element.autocompleteIndex; + this.render(); + } + Event.stop(event); + }, + + onClick: function(event) { + var element = Event.findElement(event, 'LI'); + this.index = element.autocompleteIndex; + this.selectEntry(); + this.hide(); + }, + + onBlur: function(event) { + // needed to make click events working + setTimeout(this.hide.bind(this), 250); + this.hasFocus = false; + this.active = false; + }, + + render: function() { + if(this.entryCount > 0) { + for (var i = 0; i < this.entryCount; i++) + this.index==i ? + Element.addClassName(this.getEntry(i),"selected") : + Element.removeClassName(this.getEntry(i),"selected"); + if(this.hasFocus) { + this.show(); + this.active = true; + } + } else { + this.active = false; + this.hide(); + } + }, + + markPrevious: function() { + if(this.index > 0) this.index--; + else this.index = this.entryCount-1; + this.getEntry(this.index).scrollIntoView(true); + }, + + markNext: function() { + if(this.index < this.entryCount-1) this.index++; + else this.index = 0; + this.getEntry(this.index).scrollIntoView(false); + }, + + getEntry: function(index) { + return this.update.firstChild.childNodes[index]; + }, + + getCurrentEntry: function() { + return this.getEntry(this.index); + }, + + selectEntry: function() { + this.active = false; + this.updateElement(this.getCurrentEntry()); + }, + + updateElement: function(selectedElement) { + if (this.options.updateElement) { + this.options.updateElement(selectedElement); + return; + } + var value = ''; + if (this.options.select) { + var nodes = $(selectedElement).select('.' + this.options.select) || []; + if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); + } else + value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); + + var bounds = this.getTokenBounds(); + if (bounds[0] != -1) { + var newValue = this.element.value.substr(0, bounds[0]); + var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/); + if (whitespace) + newValue += whitespace[0]; + this.element.value = newValue + value + this.element.value.substr(bounds[1]); + } else { + this.element.value = value; + } + this.oldElementValue = this.element.value; + this.element.focus(); + + if (this.options.afterUpdateElement) + this.options.afterUpdateElement(this.element, selectedElement); + }, + + updateChoices: function(choices) { + if(!this.changed && this.hasFocus) { + this.update.innerHTML = choices; + Element.cleanWhitespace(this.update); + Element.cleanWhitespace(this.update.down()); + + if(this.update.firstChild && this.update.down().childNodes) { + this.entryCount = + this.update.down().childNodes.length; + for (var i = 0; i < this.entryCount; i++) { + var entry = this.getEntry(i); + entry.autocompleteIndex = i; + this.addObservers(entry); + } + } else { + this.entryCount = 0; + } + + this.stopIndicator(); + this.index = 0; + + if(this.entryCount==1 && this.options.autoSelect) { + this.selectEntry(); + this.hide(); + } else { + this.render(); + } + } + }, + + addObservers: function(element) { + Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this)); + Event.observe(element, "click", this.onClick.bindAsEventListener(this)); + }, + + onObserverEvent: function() { + this.changed = false; + this.tokenBounds = null; + if(this.getToken().length>=this.options.minChars) { + this.getUpdatedChoices(); + } else { + this.active = false; + this.hide(); + } + this.oldElementValue = this.element.value; + }, + + getToken: function() { + var bounds = this.getTokenBounds(); + return this.element.value.substring(bounds[0], bounds[1]).strip(); + }, + + getTokenBounds: function() { + if (null != this.tokenBounds) return this.tokenBounds; + var value = this.element.value; + if (value.strip().empty()) return [-1, 0]; + var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue); + var offset = (diff == this.oldElementValue.length ? 1 : 0); + var prevTokenPos = -1, nextTokenPos = value.length; + var tp; + for (var index = 0, l = this.options.tokens.length; index < l; ++index) { + tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1); + if (tp > prevTokenPos) prevTokenPos = tp; + tp = value.indexOf(this.options.tokens[index], diff + offset); + if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp; + } + return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]); + } +}); + +Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) { + var boundary = Math.min(newS.length, oldS.length); + for (var index = 0; index < boundary; ++index) + if (newS[index] != oldS[index]) + return index; + return boundary; +}; + +Ajax.Autocompleter = Class.create(Autocompleter.Base, { + initialize: function(element, update, url, options) { + this.baseInitialize(element, update, options); + this.options.asynchronous = true; + this.options.onComplete = this.onComplete.bind(this); + this.options.defaultParams = this.options.parameters || null; + this.url = url; + }, + + getUpdatedChoices: function() { + this.startIndicator(); + + var entry = encodeURIComponent(this.options.paramName) + '=' + + encodeURIComponent(this.getToken()); + + this.options.parameters = this.options.callback ? + this.options.callback(this.element, entry) : entry; + + if(this.options.defaultParams) + this.options.parameters += '&' + this.options.defaultParams; + + new Ajax.Request(this.url, this.options); + }, + + onComplete: function(request) { + this.updateChoices(request.responseText); + } +}); + +// The local array autocompleter. Used when you'd prefer to +// inject an array of autocompletion options into the page, rather +// than sending out Ajax queries, which can be quite slow sometimes. +// +// The constructor takes four parameters. The first two are, as usual, +// the id of the monitored textbox, and id of the autocompletion menu. +// The third is the array you want to autocomplete from, and the fourth +// is the options block. +// +// Extra local autocompletion options: +// - choices - How many autocompletion choices to offer +// +// - partialSearch - If false, the autocompleter will match entered +// text only at the beginning of strings in the +// autocomplete array. Defaults to true, which will +// match text at the beginning of any *word* in the +// strings in the autocomplete array. If you want to +// search anywhere in the string, additionally set +// the option fullSearch to true (default: off). +// +// - fullSsearch - Search anywhere in autocomplete array strings. +// +// - partialChars - How many characters to enter before triggering +// a partial match (unlike minChars, which defines +// how many characters are required to do any match +// at all). Defaults to 2. +// +// - ignoreCase - Whether to ignore case when autocompleting. +// Defaults to true. +// +// It's possible to pass in a custom function as the 'selector' +// option, if you prefer to write your own autocompletion logic. +// In that case, the other options above will not apply unless +// you support them. + +Autocompleter.Local = Class.create(Autocompleter.Base, { + initialize: function(element, update, array, options) { + this.baseInitialize(element, update, options); + this.options.array = array; + }, + + getUpdatedChoices: function() { + this.updateChoices(this.options.selector(this)); + }, + + setOptions: function(options) { + this.options = Object.extend({ + choices: 10, + partialSearch: true, + partialChars: 2, + ignoreCase: true, + fullSearch: false, + selector: function(instance) { + var ret = []; // Beginning matches + var partial = []; // Inside matches + var entry = instance.getToken(); + var count = 0; + + for (var i = 0; i < instance.options.array.length && + ret.length < instance.options.choices ; i++) { + + var elem = instance.options.array[i]; + var foundPos = instance.options.ignoreCase ? + elem.toLowerCase().indexOf(entry.toLowerCase()) : + elem.indexOf(entry); + + while (foundPos != -1) { + if (foundPos == 0 && elem.length != entry.length) { + ret.push("
      2. " + elem.substr(0, entry.length) + "" + + elem.substr(entry.length) + "
      3. "); + break; + } else if (entry.length >= instance.options.partialChars && + instance.options.partialSearch && foundPos != -1) { + if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) { + partial.push("
      4. " + elem.substr(0, foundPos) + "" + + elem.substr(foundPos, entry.length) + "" + elem.substr( + foundPos + entry.length) + "
      5. "); + break; + } + } + + foundPos = instance.options.ignoreCase ? + elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : + elem.indexOf(entry, foundPos + 1); + + } + } + if (partial.length) + ret = ret.concat(partial.slice(0, instance.options.choices - ret.length)); + return "
          " + ret.join('') + "
        "; + } + }, options || { }); + } +}); + +// AJAX in-place editor and collection editor +// Full rewrite by Christophe Porteneuve (April 2007). + +// Use this if you notice weird scrolling problems on some browsers, +// the DOM might be a bit confused when this gets called so do this +// waits 1 ms (with setTimeout) until it does the activation +Field.scrollFreeActivate = function(field) { + setTimeout(function() { + Field.activate(field); + }, 1); +}; + +Ajax.InPlaceEditor = Class.create({ + initialize: function(element, url, options) { + this.url = url; + this.element = element = $(element); + this.prepareOptions(); + this._controls = { }; + arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!! + Object.extend(this.options, options || { }); + if (!this.options.formId && this.element.id) { + this.options.formId = this.element.id + '-inplaceeditor'; + if ($(this.options.formId)) + this.options.formId = ''; + } + if (this.options.externalControl) + this.options.externalControl = $(this.options.externalControl); + if (!this.options.externalControl) + this.options.externalControlOnly = false; + this._originalBackground = this.element.getStyle('background-color') || 'transparent'; + this.element.title = this.options.clickToEditText; + this._boundCancelHandler = this.handleFormCancellation.bind(this); + this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this); + this._boundFailureHandler = this.handleAJAXFailure.bind(this); + this._boundSubmitHandler = this.handleFormSubmission.bind(this); + this._boundWrapperHandler = this.wrapUp.bind(this); + this.registerListeners(); + }, + checkForEscapeOrReturn: function(e) { + if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return; + if (Event.KEY_ESC == e.keyCode) + this.handleFormCancellation(e); + else if (Event.KEY_RETURN == e.keyCode) + this.handleFormSubmission(e); + }, + createControl: function(mode, handler, extraClasses) { + var control = this.options[mode + 'Control']; + var text = this.options[mode + 'Text']; + if ('button' == control) { + var btn = document.createElement('input'); + btn.type = 'submit'; + btn.value = text; + btn.className = 'editor_' + mode + '_button'; + if ('cancel' == mode) + btn.onclick = this._boundCancelHandler; + this._form.appendChild(btn); + this._controls[mode] = btn; + } else if ('link' == control) { + var link = document.createElement('a'); + link.href = '#'; + link.appendChild(document.createTextNode(text)); + link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler; + link.className = 'editor_' + mode + '_link'; + if (extraClasses) + link.className += ' ' + extraClasses; + this._form.appendChild(link); + this._controls[mode] = link; + } + }, + createEditField: function() { + var text = (this.options.loadTextURL ? this.options.loadingText : this.getText()); + var fld; + if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) { + fld = document.createElement('input'); + fld.type = 'text'; + var size = this.options.size || this.options.cols || 0; + if (0 < size) fld.size = size; + } else { + fld = document.createElement('textarea'); + fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows); + fld.cols = this.options.cols || 40; + } + fld.name = this.options.paramName; + fld.value = text; // No HTML breaks conversion anymore + fld.className = 'editor_field'; + if (this.options.submitOnBlur) + fld.onblur = this._boundSubmitHandler; + this._controls.editor = fld; + if (this.options.loadTextURL) + this.loadExternalText(); + this._form.appendChild(this._controls.editor); + }, + createForm: function() { + var ipe = this; + function addText(mode, condition) { + var text = ipe.options['text' + mode + 'Controls']; + if (!text || condition === false) return; + ipe._form.appendChild(document.createTextNode(text)); + }; + this._form = $(document.createElement('form')); + this._form.id = this.options.formId; + this._form.addClassName(this.options.formClassName); + this._form.onsubmit = this._boundSubmitHandler; + this.createEditField(); + if ('textarea' == this._controls.editor.tagName.toLowerCase()) + this._form.appendChild(document.createElement('br')); + if (this.options.onFormCustomization) + this.options.onFormCustomization(this, this._form); + addText('Before', this.options.okControl || this.options.cancelControl); + this.createControl('ok', this._boundSubmitHandler); + addText('Between', this.options.okControl && this.options.cancelControl); + this.createControl('cancel', this._boundCancelHandler, 'editor_cancel'); + addText('After', this.options.okControl || this.options.cancelControl); + }, + destroy: function() { + if (this._oldInnerHTML) + this.element.innerHTML = this._oldInnerHTML; + this.leaveEditMode(); + this.unregisterListeners(); + }, + enterEditMode: function(e) { + if (this._saving || this._editing) return; + this._editing = true; + this.triggerCallback('onEnterEditMode'); + if (this.options.externalControl) + this.options.externalControl.hide(); + this.element.hide(); + this.createForm(); + this.element.parentNode.insertBefore(this._form, this.element); + if (!this.options.loadTextURL) + this.postProcessEditField(); + if (e) Event.stop(e); + }, + enterHover: function(e) { + if (this.options.hoverClassName) + this.element.addClassName(this.options.hoverClassName); + if (this._saving) return; + this.triggerCallback('onEnterHover'); + }, + getText: function() { + return this.element.innerHTML.unescapeHTML(); + }, + handleAJAXFailure: function(transport) { + this.triggerCallback('onFailure', transport); + if (this._oldInnerHTML) { + this.element.innerHTML = this._oldInnerHTML; + this._oldInnerHTML = null; + } + }, + handleFormCancellation: function(e) { + this.wrapUp(); + if (e) Event.stop(e); + }, + handleFormSubmission: function(e) { + var form = this._form; + var value = $F(this._controls.editor); + this.prepareSubmission(); + var params = this.options.callback(form, value) || ''; + if (Object.isString(params)) + params = params.toQueryParams(); + params.editorId = this.element.id; + if (this.options.htmlResponse) { + var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions); + Object.extend(options, { + parameters: params, + onComplete: this._boundWrapperHandler, + onFailure: this._boundFailureHandler + }); + new Ajax.Updater({ success: this.element }, this.url, options); + } else { + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: params, + onComplete: this._boundWrapperHandler, + onFailure: this._boundFailureHandler + }); + new Ajax.Request(this.url, options); + } + if (e) Event.stop(e); + }, + leaveEditMode: function() { + this.element.removeClassName(this.options.savingClassName); + this.removeForm(); + this.leaveHover(); + this.element.style.backgroundColor = this._originalBackground; + this.element.show(); + if (this.options.externalControl) + this.options.externalControl.show(); + this._saving = false; + this._editing = false; + this._oldInnerHTML = null; + this.triggerCallback('onLeaveEditMode'); + }, + leaveHover: function(e) { + if (this.options.hoverClassName) + this.element.removeClassName(this.options.hoverClassName); + if (this._saving) return; + this.triggerCallback('onLeaveHover'); + }, + loadExternalText: function() { + this._form.addClassName(this.options.loadingClassName); + this._controls.editor.disabled = true; + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: 'editorId=' + encodeURIComponent(this.element.id), + onComplete: Prototype.emptyFunction, + onSuccess: function(transport) { + this._form.removeClassName(this.options.loadingClassName); + var text = transport.responseText; + if (this.options.stripLoadedTextTags) + text = text.stripTags(); + this._controls.editor.value = text; + this._controls.editor.disabled = false; + this.postProcessEditField(); + }.bind(this), + onFailure: this._boundFailureHandler + }); + new Ajax.Request(this.options.loadTextURL, options); + }, + postProcessEditField: function() { + var fpc = this.options.fieldPostCreation; + if (fpc) + $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate'](); + }, + prepareOptions: function() { + this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions); + Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks); + [this._extraDefaultOptions].flatten().compact().each(function(defs) { + Object.extend(this.options, defs); + }.bind(this)); + }, + prepareSubmission: function() { + this._saving = true; + this.removeForm(); + this.leaveHover(); + this.showSaving(); + }, + registerListeners: function() { + this._listeners = { }; + var listener; + $H(Ajax.InPlaceEditor.Listeners).each(function(pair) { + listener = this[pair.value].bind(this); + this._listeners[pair.key] = listener; + if (!this.options.externalControlOnly) + this.element.observe(pair.key, listener); + if (this.options.externalControl) + this.options.externalControl.observe(pair.key, listener); + }.bind(this)); + }, + removeForm: function() { + if (!this._form) return; + this._form.remove(); + this._form = null; + this._controls = { }; + }, + showSaving: function() { + this._oldInnerHTML = this.element.innerHTML; + this.element.innerHTML = this.options.savingText; + this.element.addClassName(this.options.savingClassName); + this.element.style.backgroundColor = this._originalBackground; + this.element.show(); + }, + triggerCallback: function(cbName, arg) { + if ('function' == typeof this.options[cbName]) { + this.options[cbName](this, arg); + } + }, + unregisterListeners: function() { + $H(this._listeners).each(function(pair) { + if (!this.options.externalControlOnly) + this.element.stopObserving(pair.key, pair.value); + if (this.options.externalControl) + this.options.externalControl.stopObserving(pair.key, pair.value); + }.bind(this)); + }, + wrapUp: function(transport) { + this.leaveEditMode(); + // Can't use triggerCallback due to backward compatibility: requires + // binding + direct element + this._boundComplete(transport, this.element); + } +}); + +Object.extend(Ajax.InPlaceEditor.prototype, { + dispose: Ajax.InPlaceEditor.prototype.destroy +}); + +Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, { + initialize: function($super, element, url, options) { + this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions; + $super(element, url, options); + }, + + createEditField: function() { + var list = document.createElement('select'); + list.name = this.options.paramName; + list.size = 1; + this._controls.editor = list; + this._collection = this.options.collection || []; + if (this.options.loadCollectionURL) + this.loadCollection(); + else + this.checkForExternalText(); + this._form.appendChild(this._controls.editor); + }, + + loadCollection: function() { + this._form.addClassName(this.options.loadingClassName); + this.showLoadingText(this.options.loadingCollectionText); + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: 'editorId=' + encodeURIComponent(this.element.id), + onComplete: Prototype.emptyFunction, + onSuccess: function(transport) { + var js = transport.responseText.strip(); + if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check + throw('Server returned an invalid collection representation.'); + this._collection = eval(js); + this.checkForExternalText(); + }.bind(this), + onFailure: this.onFailure + }); + new Ajax.Request(this.options.loadCollectionURL, options); + }, + + showLoadingText: function(text) { + this._controls.editor.disabled = true; + var tempOption = this._controls.editor.firstChild; + if (!tempOption) { + tempOption = document.createElement('option'); + tempOption.value = ''; + this._controls.editor.appendChild(tempOption); + tempOption.selected = true; + } + tempOption.update((text || '').stripScripts().stripTags()); + }, + + checkForExternalText: function() { + this._text = this.getText(); + if (this.options.loadTextURL) + this.loadExternalText(); + else + this.buildOptionList(); + }, + + loadExternalText: function() { + this.showLoadingText(this.options.loadingText); + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: 'editorId=' + encodeURIComponent(this.element.id), + onComplete: Prototype.emptyFunction, + onSuccess: function(transport) { + this._text = transport.responseText.strip(); + this.buildOptionList(); + }.bind(this), + onFailure: this.onFailure + }); + new Ajax.Request(this.options.loadTextURL, options); + }, + + buildOptionList: function() { + this._form.removeClassName(this.options.loadingClassName); + this._collection = this._collection.map(function(entry) { + return 2 === entry.length ? entry : [entry, entry].flatten(); + }); + var marker = ('value' in this.options) ? this.options.value : this._text; + var textFound = this._collection.any(function(entry) { + return entry[0] == marker; + }.bind(this)); + this._controls.editor.update(''); + var option; + this._collection.each(function(entry, index) { + option = document.createElement('option'); + option.value = entry[0]; + option.selected = textFound ? entry[0] == marker : 0 == index; + option.appendChild(document.createTextNode(entry[1])); + this._controls.editor.appendChild(option); + }.bind(this)); + this._controls.editor.disabled = false; + Field.scrollFreeActivate(this._controls.editor); + } +}); + +//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! **** +//**** This only exists for a while, in order to let **** +//**** users adapt to the new API. Read up on the new **** +//**** API and convert your code to it ASAP! **** + +Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) { + if (!options) return; + function fallback(name, expr) { + if (name in options || expr === undefined) return; + options[name] = expr; + }; + fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' : + options.cancelLink == options.cancelButton == false ? false : undefined))); + fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' : + options.okLink == options.okButton == false ? false : undefined))); + fallback('highlightColor', options.highlightcolor); + fallback('highlightEndColor', options.highlightendcolor); +}; + +Object.extend(Ajax.InPlaceEditor, { + DefaultOptions: { + ajaxOptions: { }, + autoRows: 3, // Use when multi-line w/ rows == 1 + cancelControl: 'link', // 'link'|'button'|false + cancelText: 'cancel', + clickToEditText: 'Click to edit', + externalControl: null, // id|elt + externalControlOnly: false, + fieldPostCreation: 'activate', // 'activate'|'focus'|false + formClassName: 'inplaceeditor-form', + formId: null, // id|elt + highlightColor: '#ffff99', + highlightEndColor: '#ffffff', + hoverClassName: '', + htmlResponse: true, + loadingClassName: 'inplaceeditor-loading', + loadingText: 'Loading...', + okControl: 'button', // 'link'|'button'|false + okText: 'ok', + paramName: 'value', + rows: 1, // If 1 and multi-line, uses autoRows + savingClassName: 'inplaceeditor-saving', + savingText: 'Saving...', + size: 0, + stripLoadedTextTags: false, + submitOnBlur: false, + textAfterControls: '', + textBeforeControls: '', + textBetweenControls: '' + }, + DefaultCallbacks: { + callback: function(form) { + return Form.serialize(form); + }, + onComplete: function(transport, element) { + // For backward compatibility, this one is bound to the IPE, and passes + // the element directly. It was too often customized, so we don't break it. + new Effect.Highlight(element, { + startcolor: this.options.highlightColor, keepBackgroundImage: true }); + }, + onEnterEditMode: null, + onEnterHover: function(ipe) { + ipe.element.style.backgroundColor = ipe.options.highlightColor; + if (ipe._effect) + ipe._effect.cancel(); + }, + onFailure: function(transport, ipe) { + alert('Error communication with the server: ' + transport.responseText.stripTags()); + }, + onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls. + onLeaveEditMode: null, + onLeaveHover: function(ipe) { + ipe._effect = new Effect.Highlight(ipe.element, { + startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor, + restorecolor: ipe._originalBackground, keepBackgroundImage: true + }); + } + }, + Listeners: { + click: 'enterEditMode', + keydown: 'checkForEscapeOrReturn', + mouseover: 'enterHover', + mouseout: 'leaveHover' + } +}); + +Ajax.InPlaceCollectionEditor.DefaultOptions = { + loadingCollectionText: 'Loading options...' +}; + +// Delayed observer, like Form.Element.Observer, +// but waits for delay after last key input +// Ideal for live-search fields + +Form.Element.DelayedObserver = Class.create({ + initialize: function(element, delay, callback) { + this.delay = delay || 0.5; + this.element = $(element); + this.callback = callback; + this.timer = null; + this.lastValue = $F(this.element); + Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this)); + }, + delayedListener: function(event) { + if(this.lastValue == $F(this.element)) return; + if(this.timer) clearTimeout(this.timer); + this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000); + this.lastValue = $F(this.element); + }, + onTimerEvent: function() { + this.timer = null; + this.callback(this.element, $F(this.element)); + } +}); \ No newline at end of file diff --git a/non-rack-legacy/public/javascripts/dragdrop.js b/non-rack-legacy/public/javascripts/dragdrop.js new file mode 100644 index 0000000..07229f9 --- /dev/null +++ b/non-rack-legacy/public/javascripts/dragdrop.js @@ -0,0 +1,973 @@ +// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// (c) 2005-2008 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz) +// +// script.aculo.us is freely distributable under the terms of an MIT-style license. +// For details, see the script.aculo.us web site: http://script.aculo.us/ + +if(Object.isUndefined(Effect)) + throw("dragdrop.js requires including script.aculo.us' effects.js library"); + +var Droppables = { + drops: [], + + remove: function(element) { + this.drops = this.drops.reject(function(d) { return d.element==$(element) }); + }, + + add: function(element) { + element = $(element); + var options = Object.extend({ + greedy: true, + hoverclass: null, + tree: false + }, arguments[1] || { }); + + // cache containers + if(options.containment) { + options._containers = []; + var containment = options.containment; + if(Object.isArray(containment)) { + containment.each( function(c) { options._containers.push($(c)) }); + } else { + options._containers.push($(containment)); + } + } + + if(options.accept) options.accept = [options.accept].flatten(); + + Element.makePositioned(element); // fix IE + options.element = element; + + this.drops.push(options); + }, + + findDeepestChild: function(drops) { + deepest = drops[0]; + + for (i = 1; i < drops.length; ++i) + if (Element.isParent(drops[i].element, deepest.element)) + deepest = drops[i]; + + return deepest; + }, + + isContained: function(element, drop) { + var containmentNode; + if(drop.tree) { + containmentNode = element.treeNode; + } else { + containmentNode = element.parentNode; + } + return drop._containers.detect(function(c) { return containmentNode == c }); + }, + + isAffected: function(point, element, drop) { + return ( + (drop.element!=element) && + ((!drop._containers) || + this.isContained(element, drop)) && + ((!drop.accept) || + (Element.classNames(element).detect( + function(v) { return drop.accept.include(v) } ) )) && + Position.within(drop.element, point[0], point[1]) ); + }, + + deactivate: function(drop) { + if(drop.hoverclass) + Element.removeClassName(drop.element, drop.hoverclass); + this.last_active = null; + }, + + activate: function(drop) { + if(drop.hoverclass) + Element.addClassName(drop.element, drop.hoverclass); + this.last_active = drop; + }, + + show: function(point, element) { + if(!this.drops.length) return; + var drop, affected = []; + + this.drops.each( function(drop) { + if(Droppables.isAffected(point, element, drop)) + affected.push(drop); + }); + + if(affected.length>0) + drop = Droppables.findDeepestChild(affected); + + if(this.last_active && this.last_active != drop) this.deactivate(this.last_active); + if (drop) { + Position.within(drop.element, point[0], point[1]); + if(drop.onHover) + drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); + + if (drop != this.last_active) Droppables.activate(drop); + } + }, + + fire: function(event, element) { + if(!this.last_active) return; + Position.prepare(); + + if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active)) + if (this.last_active.onDrop) { + this.last_active.onDrop(element, this.last_active.element, event); + return true; + } + }, + + reset: function() { + if(this.last_active) + this.deactivate(this.last_active); + } +}; + +var Draggables = { + drags: [], + observers: [], + + register: function(draggable) { + if(this.drags.length == 0) { + this.eventMouseUp = this.endDrag.bindAsEventListener(this); + this.eventMouseMove = this.updateDrag.bindAsEventListener(this); + this.eventKeypress = this.keyPress.bindAsEventListener(this); + + Event.observe(document, "mouseup", this.eventMouseUp); + Event.observe(document, "mousemove", this.eventMouseMove); + Event.observe(document, "keypress", this.eventKeypress); + } + this.drags.push(draggable); + }, + + unregister: function(draggable) { + this.drags = this.drags.reject(function(d) { return d==draggable }); + if(this.drags.length == 0) { + Event.stopObserving(document, "mouseup", this.eventMouseUp); + Event.stopObserving(document, "mousemove", this.eventMouseMove); + Event.stopObserving(document, "keypress", this.eventKeypress); + } + }, + + activate: function(draggable) { + if(draggable.options.delay) { + this._timeout = setTimeout(function() { + Draggables._timeout = null; + window.focus(); + Draggables.activeDraggable = draggable; + }.bind(this), draggable.options.delay); + } else { + window.focus(); // allows keypress events if window isn't currently focused, fails for Safari + this.activeDraggable = draggable; + } + }, + + deactivate: function() { + this.activeDraggable = null; + }, + + updateDrag: function(event) { + if(!this.activeDraggable) return; + var pointer = [Event.pointerX(event), Event.pointerY(event)]; + // Mozilla-based browsers fire successive mousemove events with + // the same coordinates, prevent needless redrawing (moz bug?) + if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return; + this._lastPointer = pointer; + + this.activeDraggable.updateDrag(event, pointer); + }, + + endDrag: function(event) { + if(this._timeout) { + clearTimeout(this._timeout); + this._timeout = null; + } + if(!this.activeDraggable) return; + this._lastPointer = null; + this.activeDraggable.endDrag(event); + this.activeDraggable = null; + }, + + keyPress: function(event) { + if(this.activeDraggable) + this.activeDraggable.keyPress(event); + }, + + addObserver: function(observer) { + this.observers.push(observer); + this._cacheObserverCallbacks(); + }, + + removeObserver: function(element) { // element instead of observer fixes mem leaks + this.observers = this.observers.reject( function(o) { return o.element==element }); + this._cacheObserverCallbacks(); + }, + + notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag' + if(this[eventName+'Count'] > 0) + this.observers.each( function(o) { + if(o[eventName]) o[eventName](eventName, draggable, event); + }); + if(draggable.options[eventName]) draggable.options[eventName](draggable, event); + }, + + _cacheObserverCallbacks: function() { + ['onStart','onEnd','onDrag'].each( function(eventName) { + Draggables[eventName+'Count'] = Draggables.observers.select( + function(o) { return o[eventName]; } + ).length; + }); + } +}; + +/*--------------------------------------------------------------------------*/ + +var Draggable = Class.create({ + initialize: function(element) { + var defaults = { + handle: false, + reverteffect: function(element, top_offset, left_offset) { + var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02; + new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur, + queue: {scope:'_draggable', position:'end'} + }); + }, + endeffect: function(element) { + var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0; + new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity, + queue: {scope:'_draggable', position:'end'}, + afterFinish: function(){ + Draggable._dragging[element] = false + } + }); + }, + zindex: 1000, + revert: false, + quiet: false, + scroll: false, + scrollSensitivity: 20, + scrollSpeed: 15, + snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] } + delay: 0 + }; + + if(!arguments[1] || Object.isUndefined(arguments[1].endeffect)) + Object.extend(defaults, { + starteffect: function(element) { + element._opacity = Element.getOpacity(element); + Draggable._dragging[element] = true; + new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7}); + } + }); + + var options = Object.extend(defaults, arguments[1] || { }); + + this.element = $(element); + + if(options.handle && Object.isString(options.handle)) + this.handle = this.element.down('.'+options.handle, 0); + + if(!this.handle) this.handle = $(options.handle); + if(!this.handle) this.handle = this.element; + + if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) { + options.scroll = $(options.scroll); + this._isScrollChild = Element.childOf(this.element, options.scroll); + } + + Element.makePositioned(this.element); // fix IE + + this.options = options; + this.dragging = false; + + this.eventMouseDown = this.initDrag.bindAsEventListener(this); + Event.observe(this.handle, "mousedown", this.eventMouseDown); + + Draggables.register(this); + }, + + destroy: function() { + Event.stopObserving(this.handle, "mousedown", this.eventMouseDown); + Draggables.unregister(this); + }, + + currentDelta: function() { + return([ + parseInt(Element.getStyle(this.element,'left') || '0'), + parseInt(Element.getStyle(this.element,'top') || '0')]); + }, + + initDrag: function(event) { + if(!Object.isUndefined(Draggable._dragging[this.element]) && + Draggable._dragging[this.element]) return; + if(Event.isLeftClick(event)) { + // abort on form elements, fixes a Firefox issue + var src = Event.element(event); + if((tag_name = src.tagName.toUpperCase()) && ( + tag_name=='INPUT' || + tag_name=='SELECT' || + tag_name=='OPTION' || + tag_name=='BUTTON' || + tag_name=='TEXTAREA')) return; + + var pointer = [Event.pointerX(event), Event.pointerY(event)]; + var pos = Position.cumulativeOffset(this.element); + this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) }); + + Draggables.activate(this); + Event.stop(event); + } + }, + + startDrag: function(event) { + this.dragging = true; + if(!this.delta) + this.delta = this.currentDelta(); + + if(this.options.zindex) { + this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0); + this.element.style.zIndex = this.options.zindex; + } + + if(this.options.ghosting) { + this._clone = this.element.cloneNode(true); + this._originallyAbsolute = (this.element.getStyle('position') == 'absolute'); + if (!this._originallyAbsolute) + Position.absolutize(this.element); + this.element.parentNode.insertBefore(this._clone, this.element); + } + + if(this.options.scroll) { + if (this.options.scroll == window) { + var where = this._getWindowScroll(this.options.scroll); + this.originalScrollLeft = where.left; + this.originalScrollTop = where.top; + } else { + this.originalScrollLeft = this.options.scroll.scrollLeft; + this.originalScrollTop = this.options.scroll.scrollTop; + } + } + + Draggables.notify('onStart', this, event); + + if(this.options.starteffect) this.options.starteffect(this.element); + }, + + updateDrag: function(event, pointer) { + if(!this.dragging) this.startDrag(event); + + if(!this.options.quiet){ + Position.prepare(); + Droppables.show(pointer, this.element); + } + + Draggables.notify('onDrag', this, event); + + this.draw(pointer); + if(this.options.change) this.options.change(this); + + if(this.options.scroll) { + this.stopScrolling(); + + var p; + if (this.options.scroll == window) { + with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; } + } else { + p = Position.page(this.options.scroll); + p[0] += this.options.scroll.scrollLeft + Position.deltaX; + p[1] += this.options.scroll.scrollTop + Position.deltaY; + p.push(p[0]+this.options.scroll.offsetWidth); + p.push(p[1]+this.options.scroll.offsetHeight); + } + var speed = [0,0]; + if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity); + if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity); + if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity); + if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity); + this.startScrolling(speed); + } + + // fix AppleWebKit rendering + if(Prototype.Browser.WebKit) window.scrollBy(0,0); + + Event.stop(event); + }, + + finishDrag: function(event, success) { + this.dragging = false; + + if(this.options.quiet){ + Position.prepare(); + var pointer = [Event.pointerX(event), Event.pointerY(event)]; + Droppables.show(pointer, this.element); + } + + if(this.options.ghosting) { + if (!this._originallyAbsolute) + Position.relativize(this.element); + delete this._originallyAbsolute; + Element.remove(this._clone); + this._clone = null; + } + + var dropped = false; + if(success) { + dropped = Droppables.fire(event, this.element); + if (!dropped) dropped = false; + } + if(dropped && this.options.onDropped) this.options.onDropped(this.element); + Draggables.notify('onEnd', this, event); + + var revert = this.options.revert; + if(revert && Object.isFunction(revert)) revert = revert(this.element); + + var d = this.currentDelta(); + if(revert && this.options.reverteffect) { + if (dropped == 0 || revert != 'failure') + this.options.reverteffect(this.element, + d[1]-this.delta[1], d[0]-this.delta[0]); + } else { + this.delta = d; + } + + if(this.options.zindex) + this.element.style.zIndex = this.originalZ; + + if(this.options.endeffect) + this.options.endeffect(this.element); + + Draggables.deactivate(this); + Droppables.reset(); + }, + + keyPress: function(event) { + if(event.keyCode!=Event.KEY_ESC) return; + this.finishDrag(event, false); + Event.stop(event); + }, + + endDrag: function(event) { + if(!this.dragging) return; + this.stopScrolling(); + this.finishDrag(event, true); + Event.stop(event); + }, + + draw: function(point) { + var pos = Position.cumulativeOffset(this.element); + if(this.options.ghosting) { + var r = Position.realOffset(this.element); + pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY; + } + + var d = this.currentDelta(); + pos[0] -= d[0]; pos[1] -= d[1]; + + if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) { + pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft; + pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop; + } + + var p = [0,1].map(function(i){ + return (point[i]-pos[i]-this.offset[i]) + }.bind(this)); + + if(this.options.snap) { + if(Object.isFunction(this.options.snap)) { + p = this.options.snap(p[0],p[1],this); + } else { + if(Object.isArray(this.options.snap)) { + p = p.map( function(v, i) { + return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this)); + } else { + p = p.map( function(v) { + return (v/this.options.snap).round()*this.options.snap }.bind(this)); + } + }} + + var style = this.element.style; + if((!this.options.constraint) || (this.options.constraint=='horizontal')) + style.left = p[0] + "px"; + if((!this.options.constraint) || (this.options.constraint=='vertical')) + style.top = p[1] + "px"; + + if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering + }, + + stopScrolling: function() { + if(this.scrollInterval) { + clearInterval(this.scrollInterval); + this.scrollInterval = null; + Draggables._lastScrollPointer = null; + } + }, + + startScrolling: function(speed) { + if(!(speed[0] || speed[1])) return; + this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed]; + this.lastScrolled = new Date(); + this.scrollInterval = setInterval(this.scroll.bind(this), 10); + }, + + scroll: function() { + var current = new Date(); + var delta = current - this.lastScrolled; + this.lastScrolled = current; + if(this.options.scroll == window) { + with (this._getWindowScroll(this.options.scroll)) { + if (this.scrollSpeed[0] || this.scrollSpeed[1]) { + var d = delta / 1000; + this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] ); + } + } + } else { + this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; + this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000; + } + + Position.prepare(); + Droppables.show(Draggables._lastPointer, this.element); + Draggables.notify('onDrag', this); + if (this._isScrollChild) { + Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer); + Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000; + Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000; + if (Draggables._lastScrollPointer[0] < 0) + Draggables._lastScrollPointer[0] = 0; + if (Draggables._lastScrollPointer[1] < 0) + Draggables._lastScrollPointer[1] = 0; + this.draw(Draggables._lastScrollPointer); + } + + if(this.options.change) this.options.change(this); + }, + + _getWindowScroll: function(w) { + var T, L, W, H; + with (w.document) { + if (w.document.documentElement && documentElement.scrollTop) { + T = documentElement.scrollTop; + L = documentElement.scrollLeft; + } else if (w.document.body) { + T = body.scrollTop; + L = body.scrollLeft; + } + if (w.innerWidth) { + W = w.innerWidth; + H = w.innerHeight; + } else if (w.document.documentElement && documentElement.clientWidth) { + W = documentElement.clientWidth; + H = documentElement.clientHeight; + } else { + W = body.offsetWidth; + H = body.offsetHeight; + } + } + return { top: T, left: L, width: W, height: H }; + } +}); + +Draggable._dragging = { }; + +/*--------------------------------------------------------------------------*/ + +var SortableObserver = Class.create({ + initialize: function(element, observer) { + this.element = $(element); + this.observer = observer; + this.lastValue = Sortable.serialize(this.element); + }, + + onStart: function() { + this.lastValue = Sortable.serialize(this.element); + }, + + onEnd: function() { + Sortable.unmark(); + if(this.lastValue != Sortable.serialize(this.element)) + this.observer(this.element) + } +}); + +var Sortable = { + SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/, + + sortables: { }, + + _findRootElement: function(element) { + while (element.tagName.toUpperCase() != "BODY") { + if(element.id && Sortable.sortables[element.id]) return element; + element = element.parentNode; + } + }, + + options: function(element) { + element = Sortable._findRootElement($(element)); + if(!element) return; + return Sortable.sortables[element.id]; + }, + + destroy: function(element){ + element = $(element); + var s = Sortable.sortables[element.id]; + + if(s) { + Draggables.removeObserver(s.element); + s.droppables.each(function(d){ Droppables.remove(d) }); + s.draggables.invoke('destroy'); + + delete Sortable.sortables[s.element.id]; + } + }, + + create: function(element) { + element = $(element); + var options = Object.extend({ + element: element, + tag: 'li', // assumes li children, override with tag: 'tagname' + dropOnEmpty: false, + tree: false, + treeTag: 'ul', + overlap: 'vertical', // one of 'vertical', 'horizontal' + constraint: 'vertical', // one of 'vertical', 'horizontal', false + containment: element, // also takes array of elements (or id's); or false + handle: false, // or a CSS class + only: false, + delay: 0, + hoverclass: null, + ghosting: false, + quiet: false, + scroll: false, + scrollSensitivity: 20, + scrollSpeed: 15, + format: this.SERIALIZE_RULE, + + // these take arrays of elements or ids and can be + // used for better initialization performance + elements: false, + handles: false, + + onChange: Prototype.emptyFunction, + onUpdate: Prototype.emptyFunction + }, arguments[1] || { }); + + // clear any old sortable with same element + this.destroy(element); + + // build options for the draggables + var options_for_draggable = { + revert: true, + quiet: options.quiet, + scroll: options.scroll, + scrollSpeed: options.scrollSpeed, + scrollSensitivity: options.scrollSensitivity, + delay: options.delay, + ghosting: options.ghosting, + constraint: options.constraint, + handle: options.handle }; + + if(options.starteffect) + options_for_draggable.starteffect = options.starteffect; + + if(options.reverteffect) + options_for_draggable.reverteffect = options.reverteffect; + else + if(options.ghosting) options_for_draggable.reverteffect = function(element) { + element.style.top = 0; + element.style.left = 0; + }; + + if(options.endeffect) + options_for_draggable.endeffect = options.endeffect; + + if(options.zindex) + options_for_draggable.zindex = options.zindex; + + // build options for the droppables + var options_for_droppable = { + overlap: options.overlap, + containment: options.containment, + tree: options.tree, + hoverclass: options.hoverclass, + onHover: Sortable.onHover + }; + + var options_for_tree = { + onHover: Sortable.onEmptyHover, + overlap: options.overlap, + containment: options.containment, + hoverclass: options.hoverclass + }; + + // fix for gecko engine + Element.cleanWhitespace(element); + + options.draggables = []; + options.droppables = []; + + // drop on empty handling + if(options.dropOnEmpty || options.tree) { + Droppables.add(element, options_for_tree); + options.droppables.push(element); + } + + (options.elements || this.findElements(element, options) || []).each( function(e,i) { + var handle = options.handles ? $(options.handles[i]) : + (options.handle ? $(e).select('.' + options.handle)[0] : e); + options.draggables.push( + new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); + Droppables.add(e, options_for_droppable); + if(options.tree) e.treeNode = element; + options.droppables.push(e); + }); + + if(options.tree) { + (Sortable.findTreeElements(element, options) || []).each( function(e) { + Droppables.add(e, options_for_tree); + e.treeNode = element; + options.droppables.push(e); + }); + } + + // keep reference + this.sortables[element.id] = options; + + // for onupdate + Draggables.addObserver(new SortableObserver(element, options.onUpdate)); + + }, + + // return all suitable-for-sortable elements in a guaranteed order + findElements: function(element, options) { + return Element.findChildren( + element, options.only, options.tree ? true : false, options.tag); + }, + + findTreeElements: function(element, options) { + return Element.findChildren( + element, options.only, options.tree ? true : false, options.treeTag); + }, + + onHover: function(element, dropon, overlap) { + if(Element.isParent(dropon, element)) return; + + if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) { + return; + } else if(overlap>0.5) { + Sortable.mark(dropon, 'before'); + if(dropon.previousSibling != element) { + var oldParentNode = element.parentNode; + element.style.visibility = "hidden"; // fix gecko rendering + dropon.parentNode.insertBefore(element, dropon); + if(dropon.parentNode!=oldParentNode) + Sortable.options(oldParentNode).onChange(element); + Sortable.options(dropon.parentNode).onChange(element); + } + } else { + Sortable.mark(dropon, 'after'); + var nextElement = dropon.nextSibling || null; + if(nextElement != element) { + var oldParentNode = element.parentNode; + element.style.visibility = "hidden"; // fix gecko rendering + dropon.parentNode.insertBefore(element, nextElement); + if(dropon.parentNode!=oldParentNode) + Sortable.options(oldParentNode).onChange(element); + Sortable.options(dropon.parentNode).onChange(element); + } + } + }, + + onEmptyHover: function(element, dropon, overlap) { + var oldParentNode = element.parentNode; + var droponOptions = Sortable.options(dropon); + + if(!Element.isParent(dropon, element)) { + var index; + + var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only}); + var child = null; + + if(children) { + var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap); + + for (index = 0; index < children.length; index += 1) { + if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) { + offset -= Element.offsetSize (children[index], droponOptions.overlap); + } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) { + child = index + 1 < children.length ? children[index + 1] : null; + break; + } else { + child = children[index]; + break; + } + } + } + + dropon.insertBefore(element, child); + + Sortable.options(oldParentNode).onChange(element); + droponOptions.onChange(element); + } + }, + + unmark: function() { + if(Sortable._marker) Sortable._marker.hide(); + }, + + mark: function(dropon, position) { + // mark on ghosting only + var sortable = Sortable.options(dropon.parentNode); + if(sortable && !sortable.ghosting) return; + + if(!Sortable._marker) { + Sortable._marker = + ($('dropmarker') || Element.extend(document.createElement('DIV'))). + hide().addClassName('dropmarker').setStyle({position:'absolute'}); + document.getElementsByTagName("body").item(0).appendChild(Sortable._marker); + } + var offsets = Position.cumulativeOffset(dropon); + Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'}); + + if(position=='after') + if(sortable.overlap == 'horizontal') + Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'}); + else + Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'}); + + Sortable._marker.show(); + }, + + _tree: function(element, options, parent) { + var children = Sortable.findElements(element, options) || []; + + for (var i = 0; i < children.length; ++i) { + var match = children[i].id.match(options.format); + + if (!match) continue; + + var child = { + id: encodeURIComponent(match ? match[1] : null), + element: element, + parent: parent, + children: [], + position: parent.children.length, + container: $(children[i]).down(options.treeTag) + }; + + /* Get the element containing the children and recurse over it */ + if (child.container) + this._tree(child.container, options, child); + + parent.children.push (child); + } + + return parent; + }, + + tree: function(element) { + element = $(element); + var sortableOptions = this.options(element); + var options = Object.extend({ + tag: sortableOptions.tag, + treeTag: sortableOptions.treeTag, + only: sortableOptions.only, + name: element.id, + format: sortableOptions.format + }, arguments[1] || { }); + + var root = { + id: null, + parent: null, + children: [], + container: element, + position: 0 + }; + + return Sortable._tree(element, options, root); + }, + + /* Construct a [i] index for a particular node */ + _constructIndex: function(node) { + var index = ''; + do { + if (node.id) index = '[' + node.position + ']' + index; + } while ((node = node.parent) != null); + return index; + }, + + sequence: function(element) { + element = $(element); + var options = Object.extend(this.options(element), arguments[1] || { }); + + return $(this.findElements(element, options) || []).map( function(item) { + return item.id.match(options.format) ? item.id.match(options.format)[1] : ''; + }); + }, + + setSequence: function(element, new_sequence) { + element = $(element); + var options = Object.extend(this.options(element), arguments[2] || { }); + + var nodeMap = { }; + this.findElements(element, options).each( function(n) { + if (n.id.match(options.format)) + nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode]; + n.parentNode.removeChild(n); + }); + + new_sequence.each(function(ident) { + var n = nodeMap[ident]; + if (n) { + n[1].appendChild(n[0]); + delete nodeMap[ident]; + } + }); + }, + + serialize: function(element) { + element = $(element); + var options = Object.extend(Sortable.options(element), arguments[1] || { }); + var name = encodeURIComponent( + (arguments[1] && arguments[1].name) ? arguments[1].name : element.id); + + if (options.tree) { + return Sortable.tree(element, arguments[1]).children.map( function (item) { + return [name + Sortable._constructIndex(item) + "[id]=" + + encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)); + }).flatten().join('&'); + } else { + return Sortable.sequence(element, arguments[1]).map( function(item) { + return name + "[]=" + encodeURIComponent(item); + }).join('&'); + } + } +}; + +// Returns true if child is contained within element +Element.isParent = function(child, element) { + if (!child.parentNode || child == element) return false; + if (child.parentNode == element) return true; + return Element.isParent(child.parentNode, element); +}; + +Element.findChildren = function(element, only, recursive, tagName) { + if(!element.hasChildNodes()) return null; + tagName = tagName.toUpperCase(); + if(only) only = [only].flatten(); + var elements = []; + $A(element.childNodes).each( function(e) { + if(e.tagName && e.tagName.toUpperCase()==tagName && + (!only || (Element.classNames(e).detect(function(v) { return only.include(v) })))) + elements.push(e); + if(recursive) { + var grandchildren = Element.findChildren(e, only, recursive, tagName); + if(grandchildren) elements.push(grandchildren); + } + }); + + return (elements.length>0 ? elements.flatten() : []); +}; + +Element.offsetSize = function (element, type) { + return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')]; +}; \ No newline at end of file diff --git a/non-rack-legacy/public/javascripts/effects.js b/non-rack-legacy/public/javascripts/effects.js new file mode 100644 index 0000000..5a639d2 --- /dev/null +++ b/non-rack-legacy/public/javascripts/effects.js @@ -0,0 +1,1128 @@ +// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// Contributors: +// Justin Palmer (http://encytemedia.com/) +// Mark Pilgrim (http://diveintomark.org/) +// Martin Bialasinki +// +// script.aculo.us is freely distributable under the terms of an MIT-style license. +// For details, see the script.aculo.us web site: http://script.aculo.us/ + +// converts rgb() and #xxx to #xxxxxx format, +// returns self (or first argument) if not convertable +String.prototype.parseColor = function() { + var color = '#'; + if (this.slice(0,4) == 'rgb(') { + var cols = this.slice(4,this.length-1).split(','); + var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); + } else { + if (this.slice(0,1) == '#') { + if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); + if (this.length==7) color = this.toLowerCase(); + } + } + return (color.length==7 ? color : (arguments[0] || this)); +}; + +/*--------------------------------------------------------------------------*/ + +Element.collectTextNodes = function(element) { + return $A($(element).childNodes).collect( function(node) { + return (node.nodeType==3 ? node.nodeValue : + (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); + }).flatten().join(''); +}; + +Element.collectTextNodesIgnoreClass = function(element, className) { + return $A($(element).childNodes).collect( function(node) { + return (node.nodeType==3 ? node.nodeValue : + ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? + Element.collectTextNodesIgnoreClass(node, className) : '')); + }).flatten().join(''); +}; + +Element.setContentZoom = function(element, percent) { + element = $(element); + element.setStyle({fontSize: (percent/100) + 'em'}); + if (Prototype.Browser.WebKit) window.scrollBy(0,0); + return element; +}; + +Element.getInlineOpacity = function(element){ + return $(element).style.opacity || ''; +}; + +Element.forceRerendering = function(element) { + try { + element = $(element); + var n = document.createTextNode(' '); + element.appendChild(n); + element.removeChild(n); + } catch(e) { } +}; + +/*--------------------------------------------------------------------------*/ + +var Effect = { + _elementDoesNotExistError: { + name: 'ElementDoesNotExistError', + message: 'The specified DOM element does not exist, but is required for this effect to operate' + }, + Transitions: { + linear: Prototype.K, + sinoidal: function(pos) { + return (-Math.cos(pos*Math.PI)/2) + .5; + }, + reverse: function(pos) { + return 1-pos; + }, + flicker: function(pos) { + var pos = ((-Math.cos(pos*Math.PI)/4) + .75) + Math.random()/4; + return pos > 1 ? 1 : pos; + }, + wobble: function(pos) { + return (-Math.cos(pos*Math.PI*(9*pos))/2) + .5; + }, + pulse: function(pos, pulses) { + return (-Math.cos((pos*((pulses||5)-.5)*2)*Math.PI)/2) + .5; + }, + spring: function(pos) { + return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6)); + }, + none: function(pos) { + return 0; + }, + full: function(pos) { + return 1; + } + }, + DefaultOptions: { + duration: 1.0, // seconds + fps: 100, // 100= assume 66fps max. + sync: false, // true for combining + from: 0.0, + to: 1.0, + delay: 0.0, + queue: 'parallel' + }, + tagifyText: function(element) { + var tagifyStyle = 'position:relative'; + if (Prototype.Browser.IE) tagifyStyle += ';zoom:1'; + + element = $(element); + $A(element.childNodes).each( function(child) { + if (child.nodeType==3) { + child.nodeValue.toArray().each( function(character) { + element.insertBefore( + new Element('span', {style: tagifyStyle}).update( + character == ' ' ? String.fromCharCode(160) : character), + child); + }); + Element.remove(child); + } + }); + }, + multiple: function(element, effect) { + var elements; + if (((typeof element == 'object') || + Object.isFunction(element)) && + (element.length)) + elements = element; + else + elements = $(element).childNodes; + + var options = Object.extend({ + speed: 0.1, + delay: 0.0 + }, arguments[2] || { }); + var masterDelay = options.delay; + + $A(elements).each( function(element, index) { + new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); + }); + }, + PAIRS: { + 'slide': ['SlideDown','SlideUp'], + 'blind': ['BlindDown','BlindUp'], + 'appear': ['Appear','Fade'] + }, + toggle: function(element, effect) { + element = $(element); + effect = (effect || 'appear').toLowerCase(); + var options = Object.extend({ + queue: { position:'end', scope:(element.id || 'global'), limit: 1 } + }, arguments[2] || { }); + Effect[element.visible() ? + Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); + } +}; + +Effect.DefaultOptions.transition = Effect.Transitions.sinoidal; + +/* ------------- core effects ------------- */ + +Effect.ScopedQueue = Class.create(Enumerable, { + initialize: function() { + this.effects = []; + this.interval = null; + }, + _each: function(iterator) { + this.effects._each(iterator); + }, + add: function(effect) { + var timestamp = new Date().getTime(); + + var position = Object.isString(effect.options.queue) ? + effect.options.queue : effect.options.queue.position; + + switch(position) { + case 'front': + // move unstarted effects after this effect + this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { + e.startOn += effect.finishOn; + e.finishOn += effect.finishOn; + }); + break; + case 'with-last': + timestamp = this.effects.pluck('startOn').max() || timestamp; + break; + case 'end': + // start effect after last queued effect has finished + timestamp = this.effects.pluck('finishOn').max() || timestamp; + break; + } + + effect.startOn += timestamp; + effect.finishOn += timestamp; + + if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) + this.effects.push(effect); + + if (!this.interval) + this.interval = setInterval(this.loop.bind(this), 15); + }, + remove: function(effect) { + this.effects = this.effects.reject(function(e) { return e==effect }); + if (this.effects.length == 0) { + clearInterval(this.interval); + this.interval = null; + } + }, + loop: function() { + var timePos = new Date().getTime(); + for(var i=0, len=this.effects.length;i= this.startOn) { + if (timePos >= this.finishOn) { + this.render(1.0); + this.cancel(); + this.event('beforeFinish'); + if (this.finish) this.finish(); + this.event('afterFinish'); + return; + } + var pos = (timePos - this.startOn) / this.totalTime, + frame = (pos * this.totalFrames).round(); + if (frame > this.currentFrame) { + this.render(pos); + this.currentFrame = frame; + } + } + }, + cancel: function() { + if (!this.options.sync) + Effect.Queues.get(Object.isString(this.options.queue) ? + 'global' : this.options.queue.scope).remove(this); + this.state = 'finished'; + }, + event: function(eventName) { + if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); + if (this.options[eventName]) this.options[eventName](this); + }, + inspect: function() { + var data = $H(); + for(property in this) + if (!Object.isFunction(this[property])) data.set(property, this[property]); + return '#'; + } +}); + +Effect.Parallel = Class.create(Effect.Base, { + initialize: function(effects) { + this.effects = effects || []; + this.start(arguments[1]); + }, + update: function(position) { + this.effects.invoke('render', position); + }, + finish: function(position) { + this.effects.each( function(effect) { + effect.render(1.0); + effect.cancel(); + effect.event('beforeFinish'); + if (effect.finish) effect.finish(position); + effect.event('afterFinish'); + }); + } +}); + +Effect.Tween = Class.create(Effect.Base, { + initialize: function(object, from, to) { + object = Object.isString(object) ? $(object) : object; + var args = $A(arguments), method = args.last(), + options = args.length == 5 ? args[3] : null; + this.method = Object.isFunction(method) ? method.bind(object) : + Object.isFunction(object[method]) ? object[method].bind(object) : + function(value) { object[method] = value }; + this.start(Object.extend({ from: from, to: to }, options || { })); + }, + update: function(position) { + this.method(position); + } +}); + +Effect.Event = Class.create(Effect.Base, { + initialize: function() { + this.start(Object.extend({ duration: 0 }, arguments[0] || { })); + }, + update: Prototype.emptyFunction +}); + +Effect.Opacity = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + // make this work on IE on elements without 'layout' + if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) + this.element.setStyle({zoom: 1}); + var options = Object.extend({ + from: this.element.getOpacity() || 0.0, + to: 1.0 + }, arguments[1] || { }); + this.start(options); + }, + update: function(position) { + this.element.setOpacity(position); + } +}); + +Effect.Move = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ + x: 0, + y: 0, + mode: 'relative' + }, arguments[1] || { }); + this.start(options); + }, + setup: function() { + this.element.makePositioned(); + this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); + this.originalTop = parseFloat(this.element.getStyle('top') || '0'); + if (this.options.mode == 'absolute') { + this.options.x = this.options.x - this.originalLeft; + this.options.y = this.options.y - this.originalTop; + } + }, + update: function(position) { + this.element.setStyle({ + left: (this.options.x * position + this.originalLeft).round() + 'px', + top: (this.options.y * position + this.originalTop).round() + 'px' + }); + } +}); + +// for backwards compatibility +Effect.MoveBy = function(element, toTop, toLeft) { + return new Effect.Move(element, + Object.extend({ x: toLeft, y: toTop }, arguments[3] || { })); +}; + +Effect.Scale = Class.create(Effect.Base, { + initialize: function(element, percent) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ + scaleX: true, + scaleY: true, + scaleContent: true, + scaleFromCenter: false, + scaleMode: 'box', // 'box' or 'contents' or { } with provided values + scaleFrom: 100.0, + scaleTo: percent + }, arguments[2] || { }); + this.start(options); + }, + setup: function() { + this.restoreAfterFinish = this.options.restoreAfterFinish || false; + this.elementPositioning = this.element.getStyle('position'); + + this.originalStyle = { }; + ['top','left','width','height','fontSize'].each( function(k) { + this.originalStyle[k] = this.element.style[k]; + }.bind(this)); + + this.originalTop = this.element.offsetTop; + this.originalLeft = this.element.offsetLeft; + + var fontSize = this.element.getStyle('font-size') || '100%'; + ['em','px','%','pt'].each( function(fontSizeType) { + if (fontSize.indexOf(fontSizeType)>0) { + this.fontSize = parseFloat(fontSize); + this.fontSizeType = fontSizeType; + } + }.bind(this)); + + this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; + + this.dims = null; + if (this.options.scaleMode=='box') + this.dims = [this.element.offsetHeight, this.element.offsetWidth]; + if (/^content/.test(this.options.scaleMode)) + this.dims = [this.element.scrollHeight, this.element.scrollWidth]; + if (!this.dims) + this.dims = [this.options.scaleMode.originalHeight, + this.options.scaleMode.originalWidth]; + }, + update: function(position) { + var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); + if (this.options.scaleContent && this.fontSize) + this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); + this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); + }, + finish: function(position) { + if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); + }, + setDimensions: function(height, width) { + var d = { }; + if (this.options.scaleX) d.width = width.round() + 'px'; + if (this.options.scaleY) d.height = height.round() + 'px'; + if (this.options.scaleFromCenter) { + var topd = (height - this.dims[0])/2; + var leftd = (width - this.dims[1])/2; + if (this.elementPositioning == 'absolute') { + if (this.options.scaleY) d.top = this.originalTop-topd + 'px'; + if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; + } else { + if (this.options.scaleY) d.top = -topd + 'px'; + if (this.options.scaleX) d.left = -leftd + 'px'; + } + } + this.element.setStyle(d); + } +}); + +Effect.Highlight = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { }); + this.start(options); + }, + setup: function() { + // Prevent executing on elements not in the layout flow + if (this.element.getStyle('display')=='none') { this.cancel(); return; } + // Disable background image during the effect + this.oldStyle = { }; + if (!this.options.keepBackgroundImage) { + this.oldStyle.backgroundImage = this.element.getStyle('background-image'); + this.element.setStyle({backgroundImage: 'none'}); + } + if (!this.options.endcolor) + this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); + if (!this.options.restorecolor) + this.options.restorecolor = this.element.getStyle('background-color'); + // init color calculations + this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); + this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this)); + }, + update: function(position) { + this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ + return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) }); + }, + finish: function() { + this.element.setStyle(Object.extend(this.oldStyle, { + backgroundColor: this.options.restorecolor + })); + } +}); + +Effect.ScrollTo = function(element) { + var options = arguments[1] || { }, + scrollOffsets = document.viewport.getScrollOffsets(), + elementOffsets = $(element).cumulativeOffset(); + + if (options.offset) elementOffsets[1] += options.offset; + + return new Effect.Tween(null, + scrollOffsets.top, + elementOffsets[1], + options, + function(p){ scrollTo(scrollOffsets.left, p.round()); } + ); +}; + +/* ------------- combination effects ------------- */ + +Effect.Fade = function(element) { + element = $(element); + var oldOpacity = element.getInlineOpacity(); + var options = Object.extend({ + from: element.getOpacity() || 1.0, + to: 0.0, + afterFinishInternal: function(effect) { + if (effect.options.to!=0) return; + effect.element.hide().setStyle({opacity: oldOpacity}); + } + }, arguments[1] || { }); + return new Effect.Opacity(element,options); +}; + +Effect.Appear = function(element) { + element = $(element); + var options = Object.extend({ + from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), + to: 1.0, + // force Safari to render floated elements properly + afterFinishInternal: function(effect) { + effect.element.forceRerendering(); + }, + beforeSetup: function(effect) { + effect.element.setOpacity(effect.options.from).show(); + }}, arguments[1] || { }); + return new Effect.Opacity(element,options); +}; + +Effect.Puff = function(element) { + element = $(element); + var oldStyle = { + opacity: element.getInlineOpacity(), + position: element.getStyle('position'), + top: element.style.top, + left: element.style.left, + width: element.style.width, + height: element.style.height + }; + return new Effect.Parallel( + [ new Effect.Scale(element, 200, + { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), + new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], + Object.extend({ duration: 1.0, + beforeSetupInternal: function(effect) { + Position.absolutize(effect.effects[0].element); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide().setStyle(oldStyle); } + }, arguments[1] || { }) + ); +}; + +Effect.BlindUp = function(element) { + element = $(element); + element.makeClipping(); + return new Effect.Scale(element, 0, + Object.extend({ scaleContent: false, + scaleX: false, + restoreAfterFinish: true, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping(); + } + }, arguments[1] || { }) + ); +}; + +Effect.BlindDown = function(element) { + element = $(element); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, 100, Object.extend({ + scaleContent: false, + scaleX: false, + scaleFrom: 0, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makeClipping().setStyle({height: '0px'}).show(); + }, + afterFinishInternal: function(effect) { + effect.element.undoClipping(); + } + }, arguments[1] || { })); +}; + +Effect.SwitchOff = function(element) { + element = $(element); + var oldOpacity = element.getInlineOpacity(); + return new Effect.Appear(element, Object.extend({ + duration: 0.4, + from: 0, + transition: Effect.Transitions.flicker, + afterFinishInternal: function(effect) { + new Effect.Scale(effect.element, 1, { + duration: 0.3, scaleFromCenter: true, + scaleX: false, scaleContent: false, restoreAfterFinish: true, + beforeSetup: function(effect) { + effect.element.makePositioned().makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity}); + } + }); + } + }, arguments[1] || { })); +}; + +Effect.DropOut = function(element) { + element = $(element); + var oldStyle = { + top: element.getStyle('top'), + left: element.getStyle('left'), + opacity: element.getInlineOpacity() }; + return new Effect.Parallel( + [ new Effect.Move(element, {x: 0, y: 100, sync: true }), + new Effect.Opacity(element, { sync: true, to: 0.0 }) ], + Object.extend( + { duration: 0.5, + beforeSetup: function(effect) { + effect.effects[0].element.makePositioned(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle); + } + }, arguments[1] || { })); +}; + +Effect.Shake = function(element) { + element = $(element); + var options = Object.extend({ + distance: 20, + duration: 0.5 + }, arguments[1] || {}); + var distance = parseFloat(options.distance); + var split = parseFloat(options.duration) / 10.0; + var oldStyle = { + top: element.getStyle('top'), + left: element.getStyle('left') }; + return new Effect.Move(element, + { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) { + effect.element.undoPositioned().setStyle(oldStyle); + }}); }}); }}); }}); }}); }}); +}; + +Effect.SlideDown = function(element) { + element = $(element).cleanWhitespace(); + // SlideDown need to have the content of the element wrapped in a container element with fixed height! + var oldInnerBottom = element.down().getStyle('bottom'); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, 100, Object.extend({ + scaleContent: false, + scaleX: false, + scaleFrom: window.opera ? 0 : 1, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makePositioned(); + effect.element.down().makePositioned(); + if (window.opera) effect.element.setStyle({top: ''}); + effect.element.makeClipping().setStyle({height: '0px'}).show(); + }, + afterUpdateInternal: function(effect) { + effect.element.down().setStyle({bottom: + (effect.dims[0] - effect.element.clientHeight) + 'px' }); + }, + afterFinishInternal: function(effect) { + effect.element.undoClipping().undoPositioned(); + effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); } + }, arguments[1] || { }) + ); +}; + +Effect.SlideUp = function(element) { + element = $(element).cleanWhitespace(); + var oldInnerBottom = element.down().getStyle('bottom'); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, window.opera ? 0 : 1, + Object.extend({ scaleContent: false, + scaleX: false, + scaleMode: 'box', + scaleFrom: 100, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makePositioned(); + effect.element.down().makePositioned(); + if (window.opera) effect.element.setStyle({top: ''}); + effect.element.makeClipping().show(); + }, + afterUpdateInternal: function(effect) { + effect.element.down().setStyle({bottom: + (effect.dims[0] - effect.element.clientHeight) + 'px' }); + }, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping().undoPositioned(); + effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); + } + }, arguments[1] || { }) + ); +}; + +// Bug in opera makes the TD containing this element expand for a instance after finish +Effect.Squish = function(element) { + return new Effect.Scale(element, window.opera ? 1 : 0, { + restoreAfterFinish: true, + beforeSetup: function(effect) { + effect.element.makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping(); + } + }); +}; + +Effect.Grow = function(element) { + element = $(element); + var options = Object.extend({ + direction: 'center', + moveTransition: Effect.Transitions.sinoidal, + scaleTransition: Effect.Transitions.sinoidal, + opacityTransition: Effect.Transitions.full + }, arguments[1] || { }); + var oldStyle = { + top: element.style.top, + left: element.style.left, + height: element.style.height, + width: element.style.width, + opacity: element.getInlineOpacity() }; + + var dims = element.getDimensions(); + var initialMoveX, initialMoveY; + var moveX, moveY; + + switch (options.direction) { + case 'top-left': + initialMoveX = initialMoveY = moveX = moveY = 0; + break; + case 'top-right': + initialMoveX = dims.width; + initialMoveY = moveY = 0; + moveX = -dims.width; + break; + case 'bottom-left': + initialMoveX = moveX = 0; + initialMoveY = dims.height; + moveY = -dims.height; + break; + case 'bottom-right': + initialMoveX = dims.width; + initialMoveY = dims.height; + moveX = -dims.width; + moveY = -dims.height; + break; + case 'center': + initialMoveX = dims.width / 2; + initialMoveY = dims.height / 2; + moveX = -dims.width / 2; + moveY = -dims.height / 2; + break; + } + + return new Effect.Move(element, { + x: initialMoveX, + y: initialMoveY, + duration: 0.01, + beforeSetup: function(effect) { + effect.element.hide().makeClipping().makePositioned(); + }, + afterFinishInternal: function(effect) { + new Effect.Parallel( + [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), + new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), + new Effect.Scale(effect.element, 100, { + scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, + sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) + ], Object.extend({ + beforeSetup: function(effect) { + effect.effects[0].element.setStyle({height: '0px'}).show(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle); + } + }, options) + ); + } + }); +}; + +Effect.Shrink = function(element) { + element = $(element); + var options = Object.extend({ + direction: 'center', + moveTransition: Effect.Transitions.sinoidal, + scaleTransition: Effect.Transitions.sinoidal, + opacityTransition: Effect.Transitions.none + }, arguments[1] || { }); + var oldStyle = { + top: element.style.top, + left: element.style.left, + height: element.style.height, + width: element.style.width, + opacity: element.getInlineOpacity() }; + + var dims = element.getDimensions(); + var moveX, moveY; + + switch (options.direction) { + case 'top-left': + moveX = moveY = 0; + break; + case 'top-right': + moveX = dims.width; + moveY = 0; + break; + case 'bottom-left': + moveX = 0; + moveY = dims.height; + break; + case 'bottom-right': + moveX = dims.width; + moveY = dims.height; + break; + case 'center': + moveX = dims.width / 2; + moveY = dims.height / 2; + break; + } + + return new Effect.Parallel( + [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), + new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), + new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) + ], Object.extend({ + beforeStartInternal: function(effect) { + effect.effects[0].element.makePositioned().makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); } + }, options) + ); +}; + +Effect.Pulsate = function(element) { + element = $(element); + var options = arguments[1] || { }, + oldOpacity = element.getInlineOpacity(), + transition = options.transition || Effect.Transitions.linear, + reverser = function(pos){ + return 1 - transition((-Math.cos((pos*(options.pulses||5)*2)*Math.PI)/2) + .5); + }; + + return new Effect.Opacity(element, + Object.extend(Object.extend({ duration: 2.0, from: 0, + afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } + }, options), {transition: reverser})); +}; + +Effect.Fold = function(element) { + element = $(element); + var oldStyle = { + top: element.style.top, + left: element.style.left, + width: element.style.width, + height: element.style.height }; + element.makeClipping(); + return new Effect.Scale(element, 5, Object.extend({ + scaleContent: false, + scaleX: false, + afterFinishInternal: function(effect) { + new Effect.Scale(element, 1, { + scaleContent: false, + scaleY: false, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping().setStyle(oldStyle); + } }); + }}, arguments[1] || { })); +}; + +Effect.Morph = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ + style: { } + }, arguments[1] || { }); + + if (!Object.isString(options.style)) this.style = $H(options.style); + else { + if (options.style.include(':')) + this.style = options.style.parseStyle(); + else { + this.element.addClassName(options.style); + this.style = $H(this.element.getStyles()); + this.element.removeClassName(options.style); + var css = this.element.getStyles(); + this.style = this.style.reject(function(style) { + return style.value == css[style.key]; + }); + options.afterFinishInternal = function(effect) { + effect.element.addClassName(effect.options.style); + effect.transforms.each(function(transform) { + effect.element.style[transform.style] = ''; + }); + }; + } + } + this.start(options); + }, + + setup: function(){ + function parseColor(color){ + if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff'; + color = color.parseColor(); + return $R(0,2).map(function(i){ + return parseInt( color.slice(i*2+1,i*2+3), 16 ); + }); + } + this.transforms = this.style.map(function(pair){ + var property = pair[0], value = pair[1], unit = null; + + if (value.parseColor('#zzzzzz') != '#zzzzzz') { + value = value.parseColor(); + unit = 'color'; + } else if (property == 'opacity') { + value = parseFloat(value); + if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) + this.element.setStyle({zoom: 1}); + } else if (Element.CSS_LENGTH.test(value)) { + var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); + value = parseFloat(components[1]); + unit = (components.length == 3) ? components[2] : null; + } + + var originalValue = this.element.getStyle(property); + return { + style: property.camelize(), + originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), + targetValue: unit=='color' ? parseColor(value) : value, + unit: unit + }; + }.bind(this)).reject(function(transform){ + return ( + (transform.originalValue == transform.targetValue) || + ( + transform.unit != 'color' && + (isNaN(transform.originalValue) || isNaN(transform.targetValue)) + ) + ); + }); + }, + update: function(position) { + var style = { }, transform, i = this.transforms.length; + while(i--) + style[(transform = this.transforms[i]).style] = + transform.unit=='color' ? '#'+ + (Math.round(transform.originalValue[0]+ + (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() + + (Math.round(transform.originalValue[1]+ + (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() + + (Math.round(transform.originalValue[2]+ + (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() : + (transform.originalValue + + (transform.targetValue - transform.originalValue) * position).toFixed(3) + + (transform.unit === null ? '' : transform.unit); + this.element.setStyle(style, true); + } +}); + +Effect.Transform = Class.create({ + initialize: function(tracks){ + this.tracks = []; + this.options = arguments[1] || { }; + this.addTracks(tracks); + }, + addTracks: function(tracks){ + tracks.each(function(track){ + track = $H(track); + var data = track.values().first(); + this.tracks.push($H({ + ids: track.keys().first(), + effect: Effect.Morph, + options: { style: data } + })); + }.bind(this)); + return this; + }, + play: function(){ + return new Effect.Parallel( + this.tracks.map(function(track){ + var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options'); + var elements = [$(ids) || $$(ids)].flatten(); + return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) }); + }).flatten(), + this.options + ); + } +}); + +Element.CSS_PROPERTIES = $w( + 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + + 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' + + 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' + + 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' + + 'fontSize fontWeight height left letterSpacing lineHeight ' + + 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+ + 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' + + 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' + + 'right textIndent top width wordSpacing zIndex'); + +Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; + +String.__parseStyleElement = document.createElement('div'); +String.prototype.parseStyle = function(){ + var style, styleRules = $H(); + if (Prototype.Browser.WebKit) + style = new Element('div',{style:this}).style; + else { + String.__parseStyleElement.innerHTML = '
        '; + style = String.__parseStyleElement.childNodes[0].style; + } + + Element.CSS_PROPERTIES.each(function(property){ + if (style[property]) styleRules.set(property, style[property]); + }); + + if (Prototype.Browser.IE && this.include('opacity')) + styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]); + + return styleRules; +}; + +if (document.defaultView && document.defaultView.getComputedStyle) { + Element.getStyles = function(element) { + var css = document.defaultView.getComputedStyle($(element), null); + return Element.CSS_PROPERTIES.inject({ }, function(styles, property) { + styles[property] = css[property]; + return styles; + }); + }; +} else { + Element.getStyles = function(element) { + element = $(element); + var css = element.currentStyle, styles; + styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) { + results[property] = css[property]; + return results; + }); + if (!styles.opacity) styles.opacity = element.getOpacity(); + return styles; + }; +} + +Effect.Methods = { + morph: function(element, style) { + element = $(element); + new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { })); + return element; + }, + visualEffect: function(element, effect, options) { + element = $(element); + var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1); + new Effect[klass](element, options); + return element; + }, + highlight: function(element, options) { + element = $(element); + new Effect.Highlight(element, options); + return element; + } +}; + +$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+ + 'pulsate shake puff squish switchOff dropOut').each( + function(effect) { + Effect.Methods[effect] = function(element, options){ + element = $(element); + Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options); + return element; + }; + } +); + +$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each( + function(f) { Effect.Methods[f] = Element[f]; } +); + +Element.addMethods(Effect.Methods); \ No newline at end of file diff --git a/non-rack-legacy/public/javascripts/facebox.js b/non-rack-legacy/public/javascripts/facebox.js new file mode 100755 index 0000000..5ad90ed --- /dev/null +++ b/non-rack-legacy/public/javascripts/facebox.js @@ -0,0 +1,309 @@ +/* + * Facebox (for jQuery) + * version: 1.2 (05/05/2008) + * @requires jQuery v1.2 or later + * + * Examples at http://famspam.com/facebox/ + * + * Licensed under the MIT: + * http://www.opensource.org/licenses/mit-license.php + * + * Copyright 2007, 2008 Chris Wanstrath [ chris@ozmm.org ] + * + * Usage: + * + * jQuery(document).ready(function() { + * jQuery('a[rel*=facebox]').facebox() + * }) + * + * Terms + * Loads the #terms div in the box + * + * Terms + * Loads the terms.html page in the box + * + * Terms + * Loads the terms.png image in the box + * + * + * You can also use it programmatically: + * + * jQuery.facebox('some html') + * jQuery.facebox('some html', 'my-groovy-style') + * + * The above will open a facebox with "some html" as the content. + * + * jQuery.facebox(function($) { + * $.get('blah.html', function(data) { $.facebox(data) }) + * }) + * + * The above will show a loading screen before the passed function is called, + * allowing for a better ajaxy experience. + * + * The facebox function can also display an ajax page, an image, or the contents of a div: + * + * jQuery.facebox({ ajax: 'remote.html' }) + * jQuery.facebox({ ajax: 'remote.html' }, 'my-groovy-style') + * jQuery.facebox({ image: 'stairs.jpg' }) + * jQuery.facebox({ image: 'stairs.jpg' }, 'my-groovy-style') + * jQuery.facebox({ div: '#box' }) + * jQuery.facebox({ div: '#box' }, 'my-groovy-style') + * + * Want to close the facebox? Trigger the 'close.facebox' document event: + * + * jQuery(document).trigger('close.facebox') + * + * Facebox also has a bunch of other hooks: + * + * loading.facebox + * beforeReveal.facebox + * reveal.facebox (aliased as 'afterReveal.facebox') + * init.facebox + * afterClose.facebox + * + * Simply bind a function to any of these hooks: + * + * $(document).bind('reveal.facebox', function() { ...stuff to do after the facebox and contents are revealed... }) + * + */ +(function($) { + $.facebox = function(data, klass) { + $.facebox.loading() + + if (data.ajax) fillFaceboxFromAjax(data.ajax, klass) + else if (data.image) fillFaceboxFromImage(data.image, klass) + else if (data.div) fillFaceboxFromHref(data.div, klass) + else if ($.isFunction(data)) data.call($) + else $.facebox.reveal(data, klass) + } + + /* + * Public, $.facebox methods + */ + + $.extend($.facebox, { + settings: { + opacity : 0.2, + overlay : true, + loadingImage : '/facebox/loading.gif', + closeImage : '/facebox/closelabel.png', + imageTypes : [ 'png', 'jpg', 'jpeg', 'gif' ], + faceboxHtml : '\ + ' + }, + + loading: function() { + init() + if ($('#facebox .loading').length == 1) return true + showOverlay() + + $('#facebox .content').empty() + $('#facebox .body').children().hide().end(). + append('
        ') + + $('#facebox').css({ + top: getPageScroll()[1] + (getPageHeight() / 10), + left: $(window).width() / 2 - 205 + }).show() + + $(document).bind('keydown.facebox', function(e) { + if (e.keyCode == 27) $.facebox.close() + return true + }) + $(document).trigger('loading.facebox') + }, + + reveal: function(data, klass) { + $(document).trigger('beforeReveal.facebox') + if (klass) $('#facebox .content').addClass(klass) + $('#facebox .content').append(data) + $('#facebox .loading').remove() + $('#facebox .body').children().fadeIn('normal') + $('#facebox').css('left', $(window).width() / 2 - ($('#facebox .popup').width() / 2)) + $(document).trigger('reveal.facebox').trigger('afterReveal.facebox') + }, + + close: function() { + $(document).trigger('close.facebox') + return false + } + }) + + /* + * Public, $.fn methods + */ + + $.fn.facebox = function(settings) { + if ($(this).length == 0) return + + init(settings) + + function clickHandler() { + $.facebox.loading(true) + + // support for rel="facebox.inline_popup" syntax, to add a class + // also supports deprecated "facebox[.inline_popup]" syntax + var klass = this.rel.match(/facebox\[?\.(\w+)\]?/) + if (klass) klass = klass[1] + + fillFaceboxFromHref(this.href, klass) + return false + } + + return this.bind('click.facebox', clickHandler) + } + + /* + * Private methods + */ + + // called one time to setup facebox on this page + function init(settings) { + if ($.facebox.settings.inited) return true + else $.facebox.settings.inited = true + + $(document).trigger('init.facebox') + makeCompatible() + + var imageTypes = $.facebox.settings.imageTypes.join('|') + $.facebox.settings.imageTypesRegexp = new RegExp('\.(' + imageTypes + ')$', 'i') + + if (settings) $.extend($.facebox.settings, settings) + $('body').append($.facebox.settings.faceboxHtml) + + var preload = [ new Image(), new Image() ] + preload[0].src = $.facebox.settings.closeImage + preload[1].src = $.facebox.settings.loadingImage + + $('#facebox').find('.b:first, .bl').each(function() { + preload.push(new Image()) + preload.slice(-1).src = $(this).css('background-image').replace(/url\((.+)\)/, '$1') + }) + + $('#facebox .close').click($.facebox.close) + $('#facebox .close_image').attr('src', $.facebox.settings.closeImage) + } + + // getPageScroll() by quirksmode.com + function getPageScroll() { + var xScroll, yScroll; + if (self.pageYOffset) { + yScroll = self.pageYOffset; + xScroll = self.pageXOffset; + } else if (document.documentElement && document.documentElement.scrollTop) { // Explorer 6 Strict + yScroll = document.documentElement.scrollTop; + xScroll = document.documentElement.scrollLeft; + } else if (document.body) {// all other Explorers + yScroll = document.body.scrollTop; + xScroll = document.body.scrollLeft; + } + return new Array(xScroll,yScroll) + } + + // Adapted from getPageSize() by quirksmode.com + function getPageHeight() { + var windowHeight + if (self.innerHeight) { // all except Explorer + windowHeight = self.innerHeight; + } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode + windowHeight = document.documentElement.clientHeight; + } else if (document.body) { // other Explorers + windowHeight = document.body.clientHeight; + } + return windowHeight + } + + // Backwards compatibility + function makeCompatible() { + var $s = $.facebox.settings + + $s.loadingImage = $s.loading_image || $s.loadingImage + $s.closeImage = $s.close_image || $s.closeImage + $s.imageTypes = $s.image_types || $s.imageTypes + $s.faceboxHtml = $s.facebox_html || $s.faceboxHtml + } + + // Figures out what you want to display and displays it + // formats are: + // div: #id + // image: blah.extension + // ajax: anything else + function fillFaceboxFromHref(href, klass) { + // div + if (href.match(/#/)) { + var url = window.location.href.split('#')[0] + var target = href.replace(url,'') + if (target == '#') return + $.facebox.reveal($(target).html(), klass) + + // image + } else if (href.match($.facebox.settings.imageTypesRegexp)) { + fillFaceboxFromImage(href, klass) + // ajax + } else { + fillFaceboxFromAjax(href, klass) + } + } + + function fillFaceboxFromImage(href, klass) { + var image = new Image() + image.onload = function() { + $.facebox.reveal('
        ', klass) + } + image.src = href + } + + function fillFaceboxFromAjax(href, klass) { + $.get(href, function(data) { $.facebox.reveal(data, klass) }) + } + + function skipOverlay() { + return $.facebox.settings.overlay == false || $.facebox.settings.opacity === null + } + + function showOverlay() { + if (skipOverlay()) return + + if ($('#facebox_overlay').length == 0) + $("body").append('
        ') + + $('#facebox_overlay').hide().addClass("facebox_overlayBG") + .css('opacity', $.facebox.settings.opacity) + .click(function() { $(document).trigger('close.facebox') }) + .fadeIn(200) + return false + } + + function hideOverlay() { + if (skipOverlay()) return + + $('#facebox_overlay').fadeOut(200, function(){ + $("#facebox_overlay").removeClass("facebox_overlayBG") + $("#facebox_overlay").addClass("facebox_hide") + $("#facebox_overlay").remove() + }) + + return false + } + + /* + * Bindings + */ + + $(document).bind('close.facebox', function() { + $(document).unbind('keydown.facebox') + $('#facebox').fadeOut(function() { + $('#facebox .content').removeClass().addClass('content') + $('#facebox .loading').remove() + $(document).trigger('afterClose.facebox') + }) + hideOverlay() + }) + +})(jQuery); diff --git a/non-rack-legacy/public/javascripts/index.html b/non-rack-legacy/public/javascripts/index.html new file mode 100755 index 0000000..e933af9 --- /dev/null +++ b/non-rack-legacy/public/javascripts/index.html @@ -0,0 +1,8 @@ + + + + + +

        you shouldn't be here.. kicking you out!

        + + diff --git a/non-rack-legacy/public/javascripts/irb.js b/non-rack-legacy/public/javascripts/irb.js new file mode 100755 index 0000000..b4cb354 --- /dev/null +++ b/non-rack-legacy/public/javascripts/irb.js @@ -0,0 +1,110 @@ +// +// Copyright (c) 2008 why the lucky stiff +// Copyright (c) 2010 Andrew McElroy +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +var allStretch; +var helpPages; +var chapPages; +var defaultPage; +var toot = window.location.search.substr(1) + +//the main function, call to the effect object +function dumpAlert(obj) { + props = []; + for ( var i in obj ) { + props.push( "" + i + ": " + obj[i] ); + } + alert( props ); +} +window.onload = function() { + defaultPage = $('#helpstone .stretcher').html(); + + window.irb = new MouseApp.Irb('#irb', { + rows: 13, + name: 'IRB', + greeting: "%+r Interactive ruby ready. %-r", + ps: '\033[1;31m>>\033[m', + user: 'guest', + host: 'tryruby', + // original: irbUrl: '/irb', + irbUrl: '/tryruby/run', + init: function () { + helpPages = $(".stretcher"); + chapPages = new Array(); + for (var i = 0; i < helpPages.length; i++ ) { + var cls = helpPages[i].className.split(' '); + for (var j = 0; j < cls.length; j++) { + if (cls[j] == 'chapmark') { + chapPages.push([i, helpPages[i]]); + break; + } + } + } + }, + loadTutorial: function (id, instruct) { + $.ajax({ + url: '/tutorials/' + id , + type: 'GET', + complete: function (r) { + $('#helpstone').html("
        " + defaultPage + "
        " + r.responseText); + window.irb.init(); + window.irb.showHelp(0); + } + }); + }, + showChapter: function (n) { + if (n >= chapPages.length) return; + this.setHelpPage(chapPages[n][0], chapPages[n][1]); + }, + showHelp: function (n) { + if (n >= helpPages.length) return; + this.setHelpPage(n, helpPages[n]); + }, + popup_goto: function (u) { + $('#lilBrowser').show().css({left: '40px', top: '40px'}); + $('#lbIframe').attr('src', u); + }, + popup_make: function (s) { + $('#lilBrowser').show().css({left: '40px', top: '40px'}); + $('#lbIframe').get(0).onIframeLoad = function () { + alert($(this).html()); + alert("$(this).html()"); + return s; + }; + //$('#lbIframe').attr({src: '/blank.html'}); + src = s.replace(/\\/g, "\\\\").replace(/\"/g, "\\\""); + $('#lbIframe').attr({src: "javascript:\"" + src + "\""}); + // $('# + }, + popup_close: function () { + $('#lilBrowser').hide(); + } + }); + + if ( !toot ) { + toot = 'intro'; + } + try { + window.irb.options.loadTutorial( toot, true ); + } catch (e) {} +} diff --git a/non-rack-legacy/public/javascripts/jQuery.irb.js b/non-rack-legacy/public/javascripts/jQuery.irb.js new file mode 100644 index 0000000..765858d --- /dev/null +++ b/non-rack-legacy/public/javascripts/jQuery.irb.js @@ -0,0 +1,1641 @@ +//Try Ruby 1.5 (defacto version Number) +// March 14 2011 + +// large parts of this file are lifted from Try Haskell ( which lifted parts from try ruby without copyright notice >:-/ ) + +// Thus it is fair to include the following banner if/until there is no try haskell code left/ only code that originally existed in try ruby in the +//first place. + + // Try Haskell 1.0.1 + // Tue Feb 23 18:34:48 GMT 2010 + // + // Copyright 2010 Chris Done. All rights reserved. + // + // Redistribution and use in source and binary forms, with or without + // modification, are permitted provided that the following conditions + // are met: + // + // 1. Redistributions of source code must retain the above + // copyright notice, this list of conditions and the following + // disclaimer. + // 2. Redistributions in binary form must reproduce the above + // copyright notice, this list of conditions and the following + // disclaimer in the documentation and/or other materials + // provided with the distribution. + // + // THIS SOFTWARE IS PROVIDED BY CHRIS DONE ``AS IS'' AND ANY EXPRESS + // OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + // ARE DISCLAIMED. IN NO EVENT SHALL CHRIS DONE OR CONTRIBUTORS BE + // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + // OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + // DAMAGE. + // The views and conclusions contained in the software and + // documentation are those of the authors and should not be + // interpreted as representing official policies, either expressed or + // implied, of Chris Done. + // + // TESTED ON + // Internet Explorer 6 + // Opera 10.01 + // Chromium 4.0.237.0 (Ubuntu build 31094) + // Firefox 3.5.8 + + //IOS 4.3 (all devices) + +// Temporary fix +function opera() { + return navigator.userAgent.indexOf("Opera") == 0; +} + +function encodeHex(str) { + var result = ""; + for (var i = 0; i < str.length; i++) { + result += "%" + pad(toHex(str.charCodeAt(i) & 0xff), 2, '0'); + } + return result; +} + +//var handleJSON = function(a){ alert('Unassigned JSONP: ' + a); } +var hexv = { + "00": 0, + "01": 1, + "02": 2, + "03": 3, + "04": 4, + "05": 5, + "06": 6, + "07": 7, + "08": 8, + "09": 9, + "0A": 10, + "0B": 11, + "0C": 12, + "0D": 13, + "0E": 14, + "0F": 15, + "10": 16, + "11": 17, + "12": 18, + "13": 19, + "14": 20, + "15": 21, + "16": 22, + "17": 23, + "18": 24, + "19": 25, + "1A": 26, + "1B": 27, + "1C": 28, + "1D": 29, + "1E": 30, + "1F": 31, + "20": 32, + "21": 33, + "22": 34, + "23": 35, + "24": 36, + "25": 37, + "26": 38, + "27": 39, + "28": 40, + "29": 41, + "2A": 42, + "2B": 43, + "2C": 44, + "2D": 45, + "2E": 46, + "2F": 47, + "30": 48, + "31": 49, + "32": 50, + "33": 51, + "34": 52, + "35": 53, + "36": 54, + "37": 55, + "38": 56, + "39": 57, + "3A": 58, + "3B": 59, + "3C": 60, + "3D": 61, + "3E": 62, + "3F": 63, + "40": 64, + "41": 65, + "42": 66, + "43": 67, + "44": 68, + "45": 69, + "46": 70, + "47": 71, + "48": 72, + "49": 73, + "4A": 74, + "4B": 75, + "4C": 76, + "4D": 77, + "4E": 78, + "4F": 79, + "50": 80, + "51": 81, + "52": 82, + "53": 83, + "54": 84, + "55": 85, + "56": 86, + "57": 87, + "58": 88, + "59": 89, + "5A": 90, + "5B": 91, + "5C": 92, + "5D": 93, + "5E": 94, + "5F": 95, + "60": 96, + "61": 97, + "62": 98, + "63": 99, + "64": 100, + "65": 101, + "66": 102, + "67": 103, + "68": 104, + "69": 105, + "6A": 106, + "6B": 107, + "6C": 108, + "6D": 109, + "6E": 110, + "6F": 111, + "70": 112, + "71": 113, + "72": 114, + "73": 115, + "74": 116, + "75": 117, + "76": 118, + "77": 119, + "78": 120, + "79": 121, + "7A": 122, + "7B": 123, + "7C": 124, + "7D": 125, + "7E": 126, + "7F": 127, + "80": 128, + "81": 129, + "82": 130, + "83": 131, + "84": 132, + "85": 133, + "86": 134, + "87": 135, + "88": 136, + "89": 137, + "8A": 138, + "8B": 139, + "8C": 140, + "8D": 141, + "8E": 142, + "8F": 143, + "90": 144, + "91": 145, + "92": 146, + "93": 147, + "94": 148, + "95": 149, + "96": 150, + "97": 151, + "98": 152, + "99": 153, + "9A": 154, + "9B": 155, + "9C": 156, + "9D": 157, + "9E": 158, + "9F": 159, + "A0": 160, + "A1": 161, + "A2": 162, + "A3": 163, + "A4": 164, + "A5": 165, + "A6": 166, + "A7": 167, + "A8": 168, + "A9": 169, + "AA": 170, + "AB": 171, + "AC": 172, + "AD": 173, + "AE": 174, + "AF": 175, + "B0": 176, + "B1": 177, + "B2": 178, + "B3": 179, + "B4": 180, + "B5": 181, + "B6": 182, + "B7": 183, + "B8": 184, + "B9": 185, + "BA": 186, + "BB": 187, + "BC": 188, + "BD": 189, + "BE": 190, + "BF": 191, + "C0": 192, + "C1": 193, + "C2": 194, + "C3": 195, + "C4": 196, + "C5": 197, + "C6": 198, + "C7": 199, + "C8": 200, + "C9": 201, + "CA": 202, + "CB": 203, + "CC": 204, + "CD": 205, + "CE": 206, + "CF": 207, + "D0": 208, + "D1": 209, + "D2": 210, + "D3": 211, + "D4": 212, + "D5": 213, + "D6": 214, + "D7": 215, + "D8": 216, + "D9": 217, + "DA": 218, + "DB": 219, + "DC": 220, + "DD": 221, + "DE": 222, + "DF": 223, + "E0": 224, + "E1": 225, + "E2": 226, + "E3": 227, + "E4": 228, + "E5": 229, + "E6": 230, + "E7": 231, + "E8": 232, + "E9": 233, + "EA": 234, + "EB": 235, + "EC": 236, + "ED": 237, + "EE": 238, + "EF": 239, + "F0": 240, + "F1": 241, + "F2": 242, + "F3": 243, + "F4": 244, + "F5": 245, + "F6": 246, + "F7": 247, + "F8": 248, + "F9": 249, + "FA": 250, + "FB": 251, + "FC": 252, + "FD": 253, + "FE": 254, + "FF": 255 +}; + +function pad(str, len, pad) { + var result = str; + for (var i = str.length; i < len; i++) { + result = pad + result; + } + return result; +} + +var digitArray = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'); + +function toHex(n) { + var result = '' + var start = true; + for (var i = 32; i > 0;) { + i -= 4; + var digit = (n >> i) & 0xf; + if (!start || digit != 0) { + start = false; + result += digitArray[digit]; + } + } + return (result == '' ? '0': result); +} + + (function($) { + var raphaelPaper; + var raphaelObjs; + var tutorialGuide; + + // I don't like this at all... I intend to make this pull via ajax from a key value data store. + var pages = + [ + //////////////////////////////////////////////////////////////////////// + // Lesson 1 + // Simple addition + { + lesson: 1, + title: 'Basics; numbers, strings, etc.', + guide: + '

        ' + rmsg(['Learning By Numbers', 'Music is Math', 'Back to Basics']) + + '

        ' + + "

        To kick off let's try some maths out. Up there you can" + + " type in Haskell expressions. Try this out: 5 + 7

        " + }, + { + guide: function(result) { + if (!result) result = { + expr: '5+7', + result: 12 + }; + var complied = result.expr.replace(/ /g, '') == "5+7"; + var who = complied ? 'we': 'you'; + return '

        ' + rmsg(['Your first Haskell expression', + "First Time's a Charm"]) + '

        ' + + '

        Well done, you typed it perfect! You got back the number' + + ' ' + result.result + '. Just what ' + who + ' wanted. ' + + "

        Let's try something completely different." + + " Type in your name like this:" + + ' "chris"

        ' + }, + trigger: function(result) { + return result.type == "(Num t) => t" || + result.type == "Integer" || + result.type == "Int"; + } + }, + // Strings & types + { + guide: function(result) { + if (!result) result = { + expr: '"chris"', + result: "\"chris\"" + }; + var n = unString(result.result); + if (n) n = ", " + n; + n += "!"; + return '

        ' + rmsg(['Types of values', "What's in a name?"]) + + '

        ' + + '

        Hi there' + htmlEncode(n) + + (n != "!" ? " That's a pretty name. Honest.": "") + + " You're getting the hang of this!

        " + + "

        Note: You can chat to Haskell programmers while learning here, enter chat to start it." + + " You will join the official IRC channel of the Haskell community!

        " + + "

        Each time, you're getting back the value of the expression. So " + + "far, just a number and a list of characters.

        " + + "

        You can have lists of other stuff, too. Let's see your " + + " lottery numbers: [42,13,22]

        " + }, + trigger: function(result) { + return result.type == "[Char]" + || result.type == "String"; + } + }, + // Overview of lesson 1 + { + guide: function(result) { + if (!result) result = { + result: "[42,13,22]" + }; + return '

        ' + rmsg(["Lesson 1 done already!"]) + + '

        ' + + "

        Great, you made a list of numbers! If you win we'll split" + + " the winnings, right?

        " + + "

        Let's see what you've learned so far:

        " + + "
          " + + "
        1. How to write maths and lists of things.
        2. " + + "
        " + + "

        You can do stuff with lists. Maybe you want the lottery " + + "numbers sorted in the right order, try this: " + + "sort " + result.result + "

        " + }, + trigger: function(result) { + return result.expr.match(/^[ ]*\[[0-9, ]+\][ ]*$/) && + result.type == "(Num t) => [t]"; + } + }, + /////////////////////////////////////////////////////////////////////// + // Lesson 2 - Functions + // Functions on lists + { + lesson: 2, + title: 'Simple Functions', + guide: function(result) { + if (!result) result = { + result: "[13,23,30]" + }; + return '

        ' + rmsg(["We put the funk in function"]) + + '

        ' + + "

        Congratulations, you just used a function." + + " They're how you get things done in Haskell." + + "

        As you might've guessed, we got back " + + htmlEncode(result.result) + + ".

        Ever wanted an evil twin nemesis? Me too. " + + "Luckily, you can sort lists of characters, or " + + "strings" + + ", in the same way as numbers! sort \"chris\"

        " + }, + trigger: function(result) { + return result.expr.match(/sort/) && + result.type == "(Num t, Ord t) => [t]"; + } + }, + // Tuples + { + guide: function(result) { + if (!result) result = { + result: "\"chirs\"" + }; + nemesis = htmlEncode(unString(result.result)); + return '

        ' + + rmsg(["Tuples, because sometimes one value ain't enough!"]) + + '

        ' + + "

        Watch out for " + nemesis + "! You should keep their credentials for the police.

        " + + "

        My nemesis is 28 years of age: " + + "(28,\"chirs\")

        " + }, + trigger: function(result) { + return result.expr.match(/sort/) && + result.type == "[Char]"; + } + }, + // Functions on tuples + { + guide: function(result) { + if (!result) result = { + result: "(28,\"chirs\")" + }; + var age = result.result.match(/^\(([0-9]+)+/); + var villain = htmlEncode(result.result.replace(/\\"/g, '"')); + return '

        ' + + rmsg(["We'll keep them safe, don't worry about it."]) + + '

        ' + + "

        Is " + (age ? age[1] : "that") + " a normal age for a " + + "super-villain?

        " + + "

        You just wrote a tuple. It's a way to keep a bunch of values together in Haskell. " + + "You can put as many as you like in there:

        " + + "
        • (1,\"hats\",23/35)
        • (\"Shaggy\",\"Daphnie\",\"Velma\")
        " + + "

        Actually, let's say our villain is " + + "" + villain + "" + + ", how do you get their age?

        " + + "fst " + villain + "" + }, + trigger: function(result) { + return result.expr.match(/\([0-9]+,[ ]*"[^"]+"\)/) && + result.type == "(Num t) => (t, [Char])"; + } + }, + // Summary of lesson 2 + { + guide: function(result) { + return '

        ' + + rmsg(["Lesson 2 done! Wow, great job!", + "Lesson 2 completo!"]) + + '

        ' + + + "

        Good job! You got the age back from the tuple! Didn't " + + " even break a sweat, did you? The fst function " + + "just gets the first value. It's called \"fst\" because " + + "it's used a lot in Haskell so it really needs to be short!

        " + + + "

        Time to take a rest and see what you learned:

        " + + "
          " + + "
        1. Functions can be used on lists of any type.
        2. " + + "
        3. We can stuff values into tuples.
        4. " + + "
        5. Getting the values back from tuples is easy.
        6. " + + "
        " + + + "

        Now let's say you want " + + " to use a value more than once, how would you do it? " + + "To make our lives easier, we can say:

        " + + + "let x = 4 in x * x" + }, + trigger: function(result) { + return result.expr.match(/fst/) && + result.type == "(Num t) => t"; + } + }, + { + guide: function(result) { + return "

        Let them eat cake

        " + + + "

        You just bound a variable. " + + "That is, you bound x to the expression 4, " + + " and then you can write x in some code (the body) and " + + " it will mean the same as if you'd written 4.

        " + + + "

        It's like this: let var = expression in body

        " + + + "The in part just separates the expression from the body.

        " + + + "

        For example try: " + + "let x = 8 * 10 in x + x

        " + + + "

        So if we wanted to get the age of our villain, we could do:

        " + + + "let villain = (28,\"chirs\") in fst villain" + + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]+x[ ]*=[ ]*[0-9]+[ ]*in[ ]*x[ ]*\*[ ]*x/) && + result.type == "(Num t) => t"; + } + }, + { + guide: function(result) { + return "

        Basics over, let's go!

        " + + "

        Next, let's take a short detour to learn about " + + "syntactic sugar. " + + "Try typing this out:

        " + + "

        'a' : []

        " + + "

        Or skip to lesson4 to learn about functions," + + " the meat of Haskell!"; + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]+villain[ ]*=[ ]*\([0-9]+,[ ]*"[^"]+"\)[ ]*in[ ]+fst[ ]+villain[ ]*/) && + result.type == "(Num t) => t"; + } + }, + // Lesson 3: Syntactic sugar + { + lesson: 3, + title: 'Syntactic Sugar', + guide: function(result) { + return '

        ' + + rmsg(["You constructed a list!"]) + + '

        ' + + "

        Well done, that was tricky syntax. You used the (:) " + + "function. It takes two values, some value and a list, and " + + " constructs a new list" + + " out of them. We call it 'cons' for short.

        " + + "

        'a' is " + + "the character 'a', [] is an empty list. So " + + "tacking 'a' at the start of an empty list just " + + "makes a list ['a']!

        " + + "

        But thankfully we don't have to type out " + + "'a' : 'b' : [] every time to we want to make a " + + "list of characters; we can use " + + "syntactic sugar and just write" + + " ['a','b']. Don't believe me, check this!

        " + + "'a' : 'b' : [] == ['a','b']" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*'a'[ ]*:[ ]*\[\][ ]*/) && + result.type == "[Char]"; + } + }, + // Booleans and string syntactic sugar + { + guide: function(result) { + return '

        ' + + rmsg(["You're on fire!"]) + + '

        ' + + "

        You're handling this syntax really well, nice!

        " + + "

        You just got a boolean value back, and it said " + + "True. That means they're equal!

        " + + "

        One final demonstration on syntactic sugar for now:

        " + + "['a','b','c'] == \"abc\"" + }, + trigger: function(result) { + return result.type == "Bool" && + result.expr.replace(/[^':\[\]\=,]/g, '') == "'':'':[]==['','']"; + } + }, + // Summary of syntactic sugar section + { + guide: function(result) { + return '

        ' + + rmsg(["Lesson 3 over! Syntactic sugar is sweet"]) + + '

        ' + + "

        Let's have a gander at what you learned:

        " + + "
          " + + "
        1. In 'a' : [], : is really just " + + " another function, just clever looking.
        2. " + + "
        3. Pretty functions like this are written like (:) when " + + " you talk about them.
        4. " + + "
        5. A list of characters ['a','b'] can just be written " + + "\"ab\". Much easier!
        6. " + + "
        " + + "

        Phew! You're getting pretty deep! Your arch nemesis, " + + nemesis + ", is gonna try to steal your " + rmsg(['mojo', + 'pizza']) + + "! Let's learn a bit more about functions and passing " + + "them around. Try this:

        map (+1) [1..5]

        "; + }, + trigger: function(result) { + return result.expr.replace(/[^\]\[',=\"]?/g, '') == "['','','']==\"\"" && + result.type == "Bool"; + } + }, + { + lesson: 4, + title: 'Functions, reloaded; passing, defining, etc.', + guide: function() { + var title = + rmsg(["Functions [of a Geisha]", + "Functions, functors, functoids, funky", + "Functions: Expanded fo' real"]); + return "

        " + title + "

        " + + + "

        Here's where the magic begins!

        " + + + "

        You just passed the (+1) " + + "function to the map function.

        " + + + "

        You can try other things like (remember: click to insert them):

        " + + + "
          " + + "
        • map (*99) [1..10]
        • " + + "
        • map (/5) [13,24,52,42]
        • " + + "
        • filter (>5) [62,3,25,7,1,9]
        • " + + "
        " + + + "

        Note that a tuple is different to a list because you can do this:

        " + + "(1,\"George\")" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*map[ ]+\(\+1\)[ ]*\[1..5\][ ]*$/) && + result.type == "(Num a, Enum a) => [a]"; + } + }, + { + guide: function(result) { + return "

        Lists and Tuples

        " + + + "

        You can only " + + " have a list of numbers or a list of characters, whereas in a tuple you can throw anything in!

        " + + + "

        We've also seen that you can make a new list with (:) that joins two values together, like:

        " + + "

        1 : [2,3]

        " + + + "

        But we can't do this with tuples! You can only write a tuple and then look at what's inside. You can't make new ones on the fly like a list." + + + "

        Let's write our own functions! It's really easy. How about something simple:

        " + + "let square x = x * x in square " + rmsg([52, 10, 3]) + "" + + }, + trigger: function(result) { + return result.expr.match(/^[ ]*\(1,"[^"]+"\)[ ]*$/) && + result.type == "(Num t) => (t, [Char])"; + } + }, + { + guide: function(result) { + return "

        Let there be functions

        " + + "

        Nice one! I think you're getting used to the let syntax.

        " + + "

        You defined a function. You can read it as, as for a given " + + "parameter called x, square of " + + "x is x * x." + + "

        Some others you can try are:

        " + + "
        • let add1 x = x + 1 in add1 5
        • " + + "
        • let second x = snd x in second (3,4)
        • " + + "
        " + + "

        Let's go crazy and use our square function with map:

        " + + "let square x = x * x in map square [1..10]" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]*square[ ]+x[ ]*=[ ]*x[ ]*\*[ ]*x[ ]*in[ ]*square[ ]+[0-9]+/) && + result.type == "(Num t) => t"; + } + }, + { + guide: function(result) { + if (!result || !result.value) result = { + value: "[1,4,9,16,25,36,49,64,81,100]" + }; + return "

        Let there be functions

        " + + + "

        That's so cool! You described a simple function square and then " + + "you just passed it to another function (map) and got back " + + htmlEncode(result.value) + ", exactly what you expected!

        " + + + "

        Haskell is pretty good at composing things together like this. " + + "Some other things you can try are:

        " + + + "
          " + + "
        • let add1 x = x + 1 in map add1 [1,5,7]
        • " + + "
        • let take5s = filter (==5) in take5s [1,5,2,5,3,5]
        • " + + "
        • let take5s = filter (==5) in map take5s [[1,5],[5],[1,1]]
        • " + + "
        " + + + "

        Did you get back what you expected?

        " + + + "

        One more example for text; how do you upcase a letter?

        " + + + "

        toUpper 'a'

        " + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]+square[ ]+x[ ]*=[ ]*x[ ]*\*[ ]*x[ ]*in[ ]+map[ ]+square[ ]*\[1..10\][ ]*$/) && + result.type == "(Num a, Enum a) => [a]"; + } + }, + { + guide: function(result) { + return "

        Exercise time!

        " + + + "

        Easy! Remember: characters are written like 'a' and " + + "strings (lists of characters) are written like \"a\"." + + + "

        I need you to use toUpper capitalise my whole name, " + + "\"Chris\". Give it a try." + + " You can do it, I believe in you!

        " + + + '

        Spoiler: map toUpper "Chris"

        ' + }, + trigger: function(result) { + return result.expr.match(/^toUpper 'a'$/) && + result.type == "Char"; + } + }, + { + guide: function(result) { + return "

        Lesson 4 complete!

        " + + + "

        Brilliant! You're making excellent progress! " + + "You just passed toUpper to map. No problem.

        " + + + "

        Let's go over what you've learned in this lesson:

        " + + + "
          " + + "
        1. Functions like map take other functions as parameters.
        2. " + + "
        3. Functions like (+1), (>5) and " + + "square can be passed to other functions.
        4. " + + "
        5. Defining functions is just a case of writing what " + + "to do with the parameters.
        6. " + "
        " + + + "

        Let's check out pattern matching; a way to " + + "get values from other values using patterns. Try this:

        " + + "

        let (a,b) = (10,12) in a * 2

        " + + + "

        Or you can skip this section and go to straight to lesson6; types!

        " + }, + trigger: function(result) { + return result.type == "[Char]" && + result.expr.match(/^map[ ]+toUpper/); + } + }, + { + lesson: 5, + title: 'Pattern Matching', + guide: function(result) { + var title = + rmsg(["And therefore, patterns emerge in nature.", + "And Then Patterns", + "Pattern matching!"]) + return "

        " + title + "

        " + + + "

        Jolly good show!

        " + + "

        So you had a value (10,12) and matched " + + "it against a pattern (a,b), then you were able" + + " to do stuff with the a and b!" + + + "

        Note: Pattern matching (a,b) against " + + "(1,2) to get the a is the same as" + + " doing fst (1,2), like you did in step7!

        " + + + "

        A pattern always matches the way the " + + "value was originally constructed. Remember that \"abc\" is " + + "syntactic sugar for 'a' : 'b' : 'c' : [].

        " + + + "

        So you can get the characters from a string with patterns:

        " + + + "let (a:b:c:[]) = \"xyz\" in a" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]+\(a,b\)[ ]+=[ ]+\(10,12\)[ ]+in[ ]+a[ ]*\*[ ]*2[ ]*$/) && + result.type == "(Num t) => t"; + } + }, + { + guide: function(result) { + return "

        " + rmsg(["Ignorance is bliss", "Ignoring values"]) + "

        " + + + "

        You're getting into tricky syntax, huh? I know you can handle it!

        " + + + "

        If you just want some of the values, you can ignore the others with _ (underscore) like this:

        " + + + "

        let (a:_:_:_) = \"xyz\" in a

        " + + + "

        In fact, (a:b:c:d) is short-hand for " + + "(a:(b:(c:d))), so you can just ignore the rest in one go:

        " + + + "let (a:_) = \"xyz\" in a" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]+\(a:b:c:\[\]\)[ ]*=[ ]*\"xyz\"[ ]*in[ ]+a[ ]*$/) && + result.type == "Char"; + } + }, + { + guide: function(result) { + return "

        " + rmsg(["Exercise!", "Show me the money!"]) + "

        " + + + "

        Try to get the 'a' value from this value using pattern matching:

        " + + "

        (10,\"abc\")

        " + + + "

        Spoiler: let (_,(a:_)) = (10,\"abc\") in a

        " + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]*\(a:_\)[ ]*=[ ]*"xyz"[ ]*in[ ]*a[ ]*$/) && + result.type == "Char"; + } + }, + { + guide: function(result) { + return "

        " + rmsg(["Well done!", "Brilliant!", "Perfetto!"]) + "

        " + + + "

        Wizard! I think you've got pattern-matching down.

        " + + + "

        If you're still a bit unsure, here are some other things you can try:

        " + + + "
          " + + "
        • let _:_:c:_ = \"abcd\" in c
        • " + + "
        • let [a,b,c] = \"cat\" in (a,b,c)
        • " + + "
        " + + + "

        You can also grab a whole value and pattern match on it (have your cake and eat it too):

        " + + + "let abc@(a,b,c) = (10,20,30) in (abc,a,b,c)" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]*\(_,\(?a:_\)?\)[ ]*=[ ]*\(10,\"abc\"\)[ ]*in[ ]*a[ ]*$/) && + result.type == "Char"; + } + }, + { + guide: function(result) { + return "

        " + rmsg(["And that's the end of that chapter"]) + "

        " + + + "

        That was easy, right?

        " + + + "

        Let's go over what you've learned in this lesson:

        " + + + "
          " + + "
        1. Values are pattern matched, or deconstructed, by writing however they were constructed.
        2. " + + "
        3. Patterns let you use the values that you match.
        4. " + + "
        5. You can ignore whichever values you want.
        6. " + + "
        7. You can pattern match and keep hold of the original value too.
        8. " + + "
        " + + + "

        Now we get to the Deep Ones. Types!

        " + + + "

        Consider the following value: 'a'

        " + + }, + trigger: function(result) { + return result.type == "(Num t, Num t1, Num t2) => ((t, t1, t2), t, t1, t2)"; + } + }, + { + lesson: 6, + title: 'Types', + guide: function(result) { + showTypes = true; + return "

        " + rmsg(["Types", "What's in a Type?", "Types & Values"]) + "

        " + + "

        What's this? Something new!

        " + + + "

        In Haskell there are types of values. Every value belongs to a type. To demonstrate this fact, I've sneakily enabled types to be " + + "shown of every value in the console from now on.

        " + + + "

        The type of the value 'a' is Char (short for 'character', but you guessed that, right?).

        " + + + "

        You've seen the type of a character, now what about" + + " a list of characters?

        " + + "\"Spartacus\"" + }, + trigger: function(result) { + return result.type == 'Char'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

        " + rmsg(["Lists of stuff, types"]) + "

        " + + + "

        I'm Spartacus!

        " + + + "

        Okay, so a list of characters has type [Char].

        " + + + "

        Notice that when we write a :: X it means the value a has type X. It's just a short-hand called a signature.

        " + + + "

        If you just want the type of a value, without actually evaluating it, you can just type:

        " + + ":t toUpper" + }, + trigger: function(result) { + return result.expr.match(/"[^"]+"/) && + result.type == '[Char]'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

        " + rmsg(["Function types"]) + "

        " + + + "

        Woah! Hold your blinkin' 'orses! The type of toUpper reads: Char -> Char

        " + + + "

        It's pretty easy; a -> b means function from a to b. " + + "So

        toUpper :: Char -> Char means: for a" + + " given character (Char value) a, toUpper a has type Char.

        " + + + "

        Some other things you can try are:

        " + + + "
        • :t words
        • " + + "
        • :t unwords
        • " + + "
        • :t True
        • " + + "
        • :t not
        • " + + "
        " + + + "

        The words function is pretty handy. Want to get a list of words from a sentence?

        " + + "words \"There's jam in my pants.\"" + }, + trigger: function(result) { + return result.type == 'Char -> Char'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

        " + rmsg(["Mid-way review"]) + "

        " + + + "

        The type of words was String -> [String]. You got a list of strings back! Just what you expected, right?

        " + + + "

        Let's take a rest in the middle of this lesson and go over what we've learned:

        " + + + "
          " + + "
        1. All values in Haskell have a type. We describe the types of values with signatures, like True :: Bool.
        2. " + + "
        3. Functions are values too, and they have types, notated a -> b.
        4. " + + "
        5. Functions can be defined for any type to any other type.
        6. " + + "
        7. Humble reader has a thing for jammy pants.
        8. " + + "
        " + + + "

        But what if you have a type that can contain values of any type, like a tuple?

        " + + ":t fst" + + }, + trigger: function(result) { + return result.expr.match(/^[ ]*words[ ]*\"[^"]+\"[ ]*$/) && + result.type == '[String]'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

        " + rmsg(["Polymorphic functions"]) + "

        " + + + "

        Remember this one? I know you do! fst (1,2) is 1, right?

        " + + "

        We read its type

        " + + "

        fst :: (a, b) -> a

        " + + "

        as: for all types a and b, the fst has type (a,b) to a. So the fst " + + "function works on a pair of values of any types! We call such a function polymorphic." + + "

        " + + "

        Remember the drop function? Maybe you don't. I don't! Let's check out its type:

        " + + "

        :t drop

        " + }, + trigger: function(result) { + return result.type == '(a, b) -> a'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

        " + rmsg(["Multi parameter functions"]) + "

        " + + + "

        So the drop function has type

        Int -> [a] -> [a].

        " + + + "

        This is something new. You've got two arrows! Relax. You can read

        " + + "

        a -> b -> c as a -> (b -> c)

        " + + + "

        In other words, drop is a function from integers (Int values) to functions of lists to lists ([a] -> [a] values). Drop is a function to another function.

        " + + + "

        Check for yourself! :t drop 3

        " + }, + trigger: function(result) { + return result.type == 'Int -> [a] -> [a]'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

        " + rmsg(["Partial application"]) + "

        " + + + "

        You've got a function of type [a] -> [a]! The drop function is considered a multi-parameter function. Remember the map function? Its parameters were a function and a list. Just another multi-parameter function.

        " + + + "

        You can add another parameter and, hey presto, you get a list!

        " + + + "drop 3 \"hello!\"" + + }, + trigger: function(result) { + return result.type == '[a] -> [a]'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

        " + rmsg(["Higher order functions"]) + "

        " + + + "

        'Lo bob! You've already used the map function loads. I wonder if you can guess its type?

        " + + + "

        map :: (a -> b) -> [a] -> [b] (spoiler)

        " + + + "

        It's okay to peek! Have a go at guessing these: filter, take

        " + + + "

        Tip: You can use parantheses to use more than one function. You want to double all the numbers over five? Psch!

        " + + "map (*2) (filter (>5) [10,2,16,9,4])" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*drop[ ]*[0-9]+[ ]*"[^"]+"[ ]*$/) && + result.type == '[Char]'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

        " + rmsg(["Phew! Rest time!"]) + "

        " + + + "

        Wow! You're doing so great! Have a look at what you know now!

        " + + + "
          " + + "
        1. Function parameters can be polymorphic; any type!
        2. " + + "
        3. Functions can have multiple parameters by returning more functions.
        4. " + + "
        5. You can wrap expressions in parentheses and apply functions to them as a whole value.
        6. " + + "
        " + + + "

        You're really making great progress. Don't hesitate to sit and play in the console between chapters to get a good feel of it!

        " + + + "

        Stay tuned for more chapters on type classes and the meaning of :t 1, :t (*), etc.

        " + + learnMore + }, + trigger: function(result) { + return result.type == '(Num a, Ord a) => [a]'; + } + } + ]; + // + // var webchat; + // + // function runWebchat() { + // if (!webchat) { + // // Create webchat frame + // var webchat = + // $(''); + // webchat.attr('width', 635); + // webchat.attr('height', 500); + // webchat.css('float', 'left'); + // webchat.css('webkit-border-radius', '3px'); + // webchat.css('moz-border-radius', '3px'); + // webchat.css('border-radius', '3px'); + // webchat.css('border', '5px solid #eeeeee'); + // + // // Extend page wrap to fit console and chat + // $('.page-wrap').css({ + // width: '1250px' + // }); + // $('.primary-content').css('margin-left', 0); + // $('.page-wrap').append(webchat.css('margin-left', '5px')); + // } + // } + + var pageTrigger = -1; + var notices = []; + var controller; + // Console controller + var learnMore; + + //////////////////////////////////////////////////////////////////////// + // Unshow a string + function unString(str) { + return str.replace(/^"(.*)"$/, "$1").replace(/\\"/, '"'); + } + + //////////////////////////////////////////////////////////////////////// + // Random message from a list of messages + function rmsg(choices) { + return choices[Math.floor((Math.random() * 100) % choices.length)]; + } + + // Simple HTML encoding + // Simply replace '<', '>' and '&' + // TODO: Use jQuery's .html() trick, or grab a proper, fast + // HTML encoder. + function htmlEncode(text, shy) { + return ( + ('' + text).replace(/&/g, '&') + .replace(/'); + handleJSON = function(r) { + script.remove(); + func(r); + }; + script.attr('src', url); + $('body').append(script); + } + + + var console = $('.console'); + controller = console.console({ + promptLabel: '> ', + continuedPromptLabel: ' .. ', /*not quiet right but good enough*/ + cancelHandle: function() { + controller.commandRef.ignore = true; + controller.finishCommand(); + controller.report(); + }, + + commandHandle: function(line, report) { + + controller.ajaxloader = $('

        Loading...

        '); + var commandRef = {}; + controller.currentLine = line; + controller.commandRef = commandRef; + controller.report = report; + if (tellAboutRet) tellAboutRet.fadeOut(function() { + $(this).remove(); + }); + + if (libTrigger(line, report)) return; + controller.inner.append(controller.ajaxloader); + controller.scrollToBottom(); + + jsonp("http://localhost:3030/tryruby/run/?cmd=" + encodeHex(line), + function(resp) { + if (commandRef.ignore) { + return; + } + controller.finishCommand(); + var result = resp; + if (pageTrigger > -1 && result.expr) { + triggerTutorialPage(pageTrigger, result); + } + if (result.type) { + if (pageTrigger == 24) showTypes = false; + handleSuccess(report, result); + } else if (result.error) { + report( + [{ + msg: result.error, + className: "jquery-console-message-error jquery-console-message-compile-error" + }] + ); + notice('compile-error', + "A compile-time error! " + + "It just means the expression wasn't quite right. " + + "Try again.", + 'prompt'); + } else if (result.exception) { + var err = limitsError(result.exception); + report( + [{ + msg: err, + className: "jquery-console-message-error jquery-console-message-exception" + }] + ); + if (err == result.exception) { + notice('compile-error', + "A run-time error! The expression was right but the" + + " result didn't make sense. Check your expression and try again.", + 'prompt'); + } + } else if (result.internal) { + report( + [{ + msg: limitsError(result.internal), + className: "jquery-console-message-error jquery-console-message-internal" + }] + ); + } else if (result.bind) { + report(); + } else if (result.result) { + if (result.expr.match(/^:modules/)) { + report( + [{ + msg: result.result.replace(/[\["\]]/g, '') + .replace(/,/g, ', '), + className: "jquery-console-message-type" + }]); + } + } + }); + + }, + + charInsertTrigger: function() { + var t = notice('tellaboutreturn', + "Hit Return when you're " + + "finished typing your expression."); + if (t) tellAboutRet = t; + return true; + }, + autofocus: true, + promptHistory: true, + historyPreserveColumn: true, + welcomeMessage: 'Interactive ruby ready' + }); + + controller.finishCommand = function() { + controller.ajaxloader.remove(); + $('.jquery-console-prompt :last').each(function() { + lastLine = controller.currentLine; + if (!$(this).hasClass('prompt-done')) { + $(this).addClass('prompt-done'); + $(this).click(function() { + controller.promptText(controller.currentLine); + }); + } + }); + } + + makeGuidSamplesClickable(); + + var match = window.location.href.match(/#([0-9]+)$/); + if (match) { + pageTrigger = match[1] - 1; + setTutorialPage(undefined, match[1] - 1); + } + + var match = window.location.href.match(/\?input=([^&]+)/); + if (match) { + controller.promptText(urlDecode(match[1])); + controller.inner.click(); + controller.typer.consoleControl(13); + } + }); + + function urlDecode(encodedString) { + var output = encodedString; + var binVal, + thisString; + var myregexp = /(%[^%]{2})/; + while ((match = myregexp.exec(output)) != null + && match.length > 1 + && match[1] != '') { + binVal = parseInt(match[1].substr(1), 16); + thisString = String.fromCharCode(binVal); + output = output.replace(match[1], thisString); + } + return output; + } + + function makeGuidSamplesClickable() { + $('.chapmark code').each(function() { + $(this).css('cursor', 'pointer'); + $(this).attr('title', 'Click me to insert "' + + $(this).text() + '" into the console.'); + $(this).click(function() { + controller.promptText($(this).text()); + controller.inner.click(); + }); + }); + } + + String.prototype.trim = function() { + return this.replace(/^[\t ]*(.*)[\t ]*$/, '$1'); + }; + + //////////////////////////////////////////////////////////////////////// + // Trigger console commands + function libTrigger(line, report) { + switch (line.trim()) { + case 'help': + { + setTutorialPage(undefined, 0); + report(); + pageTrigger = 0; + return true; + } + case 'back': + { + if (pageTrigger > 0) { + setTutorialPage(undefined, pageTrigger - 1); + pageTrigger--; + report(); + return true; + } + break; + } + case 'lessons': + { + var lessons = $('
          '); + for (var i = 0; i < pages.length; i++) { + if (pages[i].lesson) { + lessons.append($('
        1. '). + html('lesson' + pages[i].lesson + ' - ' + + pages[i].title)); + } + } + var lessonsList = '

          Lessons

          ' + lessons.html(); + tutorialGuide.animate({ + opacity: 0, + height: 0 + }, + 'fast', + function() { + tutorialGuide.html(lessonsList); + tutorialGuide.css({ + height: 'auto' + }); + tutorialGuide.animate({ + opacity: 1 + }, + 'fast'); + makeGuidSamplesClickable(); + }); + report(); + return true; + } + default: + { + if (line.trim() == 'chat') { + notice('irc', + 'Enter your nick on the right hand side and hit Connect!', + 'prompt'); + report(); + runWebchat(); + return true; + } + + var m = line.trim().match(/^link(.*)/); + if (m) { + var data; + if (m[1]) data = m[1].trim(); + else if (lastLine) data = lastLine; + if (data) { + var addr = '?input=' + encodeHex(data); + report([{ + msg: '', + className: 'latest-link' + }]); + var link = $(''). + text('link for ' + data).click(function() { + window.location.href = $(this).attr('href'); + return false; + }); + $('.latest-link').html(link).removeClass('latest-link'); + return true; + } + } + + var m = line.trim().match(/^step([0-9]+)/); + if (m) { + if ((m[1] * 1) <= pages.length) { + setTutorialPage(undefined, m[1] - 1); + report(); + pageTrigger = m[1] - 1; + return true; + } + } + var m = line.trim().match(/^help ([0-9]+)/); + if (m) { + for (var i = 0; i < pages.length; i++) { + if (pages[i].lesson == m[1] * 1) { + setTutorialPage(undefined, i); + report(); + pageTrigger = i; + return true; + } + } + } + } + }; + }; + + //////////////////////////////////////////////////////////////////////// + // Change the tutorial page + function setTutorialPage(result, n) { + if (pages[n]) { + window.location.href = '#' + (1 * n + 1); + tutorialGuide.find('#helpstone').remove(); + tutorialGuide.animate({ + opacity: 0, + height: 0 + }, + 'fast', + function() { + if (typeof(pages[n].guide) == 'function') + tutorialGuide.html(pages[n].guide(result)); + else + tutorialGuide.html(pages[n].guide); + var back = ''; + if (pageTrigger > 0) + back = 'You\'re at step' + (n + 1) + + '. Type back to go back.'; + else + back = 'You\'re at step' + (n + 1) + '. Type step' + (n + 1) + + ' to return here.'; + if (true) tutorialGuide + .append('
          ' + back + '
          ') + .append('
          Lesson: ' + + searchLessonBack(n) + + '
          '); + tutorialGuide.css({ + height: 'auto' + }); + tutorialGuide.animate({ + opacity: 1 + }, + 'fast'); + makeGuidSamplesClickable(); + }); + } + }; + + function searchLessonBack(page) { + for (var i = page; i >= 0; i--) { + if (pages[i].lesson) return pages[i].lesson; + } + return "1"; + } + + //////////////////////////////////////////////////////////////////////// + // Trigger a page according to a result + function triggerTutorialPage(n, result) { + n++; + if (pages[n] && (typeof(pages[n].trigger) == 'function') + && pages[n].trigger(result)) { + pageTrigger++; + setTutorialPage(result, n); + } + }; + + //////////////////////////////////////////////////////////////////////// + // Trigger various libraries after JSONRPC returned + function handleSuccess(report, result) { + if (result.type.match(/^Graphics\.Raphael\.Raphael[\r\n ]/)) { + runRaphael(result.result); + report(); + } + if (result.type.match(/standard/)) { + var hashrocket = ''; + var msg_value = ' => '; + if (result.result == null) { + hashrocket = ' => ' + msg_value = ''; + } + report( + [{ + msg: msg_value + result.output + hashrocket + result.result, + className: "jquery-console-message-value" + }]); + } + + if (result.type.match(/error/)) { + + report( + [{ + msg: result.error, + className: "jquery-console-message-value" + }]); + } + + if (result.type.match(/illegal/)) { + + report( + [{ + msg: 'You are not allowed to run that command!', + className: "jquery-console-message-value" + }]); + } + + + if (result.type.match(/line_continuation/)) { + report( + [{ + msg: '..', + className: "jquery-console-prompt-label" + }]); + } + + }; + + //////////////////////////////////////////////////////////////////////// + // Raphael support + function runRaphael(expr) { + raphaelPaper.clear(); + $('#raphael').parent().parent().slideDown(function() { + var exprs = expr.split(/\n/g); + for (var i = 0; i < exprs.length; i++) + raphaelRunExpr(exprs[i]); + }); + } + function raphaelRunExpr(expr) { + var expr = expr.split(/ /g); + switch (expr[0]) { + case 'new': + { + switch (expr[2]) { + case 'circle': + { + var x = expr[3], + y = expr[4], + radius = expr[5]; + var circle = raphaelPaper.circle(x * 1, y * 1, radius * 1); + circle.attr("fill", "#7360a4"); + break; + } + } + } + } + } + + function notice(name, msg, style) { + if (opera()) return; + if (!notices[name]) { + notices[name] = name; + return controller.notice(msg, style); + } + } + + function limitsError(str) { + if (str == "Terminated!") { + notice('terminated', + "This error means it took to long to work" + + " out on the server.", + 'fadeout'); + return "Terminated!"; + } else if (str == "Time limit exceeded.") { + notice('exceeded', + "This error means it took to long to work out on the server. " + + "Try again.", + 'fadeout'); + return "Terminated! Try again."; + } + return str; + } + +})(jQuery); diff --git a/non-rack-legacy/public/javascripts/jquery-1.3.2.min.js b/non-rack-legacy/public/javascripts/jquery-1.3.2.min.js new file mode 100644 index 0000000..b1ae21d --- /dev/null +++ b/non-rack-legacy/public/javascripts/jquery-1.3.2.min.js @@ -0,0 +1,19 @@ +/* + * jQuery JavaScript Library v1.3.2 + * http://jquery.com/ + * + * Copyright (c) 2009 John Resig + * Dual licensed under the MIT and GPL licenses. + * http://docs.jquery.com/License + * + * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) + * Revision: 6246 + */ +(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("",""]||!O.indexOf("",""]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
          "]||!O.indexOf("",""]||(!O.indexOf("",""]||!O.indexOf("",""]||!o.support.htmlSerialize&&[1,"div
          ","
          "]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}}); +/* + * Sizzle CSS Selector Engine - v0.9.3 + * Copyright 2009, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return UT[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="

          ";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="
          ";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("
          ").append(M.responseText.replace(//g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='
          ';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})(); \ No newline at end of file diff --git a/non-rack-legacy/public/javascripts/jquery-1.4.2.min.js b/non-rack-legacy/public/javascripts/jquery-1.4.2.min.js new file mode 100644 index 0000000..7c24308 --- /dev/null +++ b/non-rack-legacy/public/javascripts/jquery-1.4.2.min.js @@ -0,0 +1,154 @@ +/*! + * jQuery JavaScript Library v1.4.2 + * http://jquery.com/ + * + * Copyright 2010, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2010, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Sat Feb 13 22:33:48 2010 -0500 + */ +(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, +Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& +(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, +a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== +"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, +function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
          a"; +var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, +parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= +false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= +s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, +applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; +else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, +a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== +w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, +cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= +c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); +a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, +function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); +k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), +C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B=0){a.type= +e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& +f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; +if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", +e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, +"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, +d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, +e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); +t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| +g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, +CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, +g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, +text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, +setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= +h[3];l=0;for(m=h.length;l=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== +"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, +h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& +q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; +if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="

          ";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); +(function(){var g=s.createElement("div");g.innerHTML="
          ";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: +function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var j=d;j0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= +{},i;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== +"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", +d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? +a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== +1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"},F={option:[1,""],legend:[1,"
          ","
          "],thead:[1,"","
          "],tr:[2,"","
          "],td:[3,"","
          "],col:[2,"","
          "],area:[1,"",""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
          ","
          "];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= +c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, +wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, +prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, +this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); +return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, +""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); +return this}else{e=0;for(var j=d.length;e0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", +""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===""&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= +c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? +c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= +function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= +Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, +"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= +a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= +a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=//gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!== +"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("
          ").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this}, +serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), +function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href, +global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&& +e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)? +"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache=== +false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B= +false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since", +c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E|| +d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x); +g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status=== +1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b=== +"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional; +if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration=== +"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]|| +c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start; +this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now= +this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem, +e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b
          "; +a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b); +c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a, +d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top- +f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset": +"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in +e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window); diff --git a/non-rack-legacy/public/javascripts/jquery.console.js b/non-rack-legacy/public/javascripts/jquery.console.js new file mode 100644 index 0000000..d45390d --- /dev/null +++ b/non-rack-legacy/public/javascripts/jquery.console.js @@ -0,0 +1,609 @@ +// JQuery Console 1.0 +// Sun Feb 21 20:28:47 GMT 2010 +// +// Copyright 2010 Chris Done, Simon David Pratt. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above +// copyright notice, this list of conditions and the following +// disclaimer. +// +// 2. Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// TESTED ON +// Internet Explorer 6 +// Opera 10.01 +// Chromium 4.0.237.0 (Ubuntu build 31094) +// Firefox 3.5.8, 3.6.2 (Mac) +// Safari 4.0.5 (6531.22.7) (Mac) +// Google Chrome 5.0.375.55 (Mac) + +(function($){ + $.fn.console = function(config){ + //////////////////////////////////////////////////////////////////////// + // Constants + // Some are enums, data types, others just for optimisation + var keyCodes = { + // left + 37: moveBackward, + // right + 39: moveForward, + // up + 38: previousHistory, + // down + 40: nextHistory, + // backspace + 8: backDelete, + // delete + 46: forwardDelete, + // end + 35: moveToEnd, + // start + 36: moveToStart, + // return + 13: commandTrigger, + // tab + 18: doNothing + }; + var ctrlCodes = { + // C-a + 65: moveToStart, + // C-e + 69: moveToEnd, + // C-d + 68: forwardDelete, + // C-n + 78: nextHistory, + // C-p + 80: previousHistory, + // C-b + 66: moveBackward, + // C-f + 70: moveForward, + // C-k + 75: deleteUntilEnd + }; + var altCodes = { + // M-f + 70: moveToNextWord, + // M-b + 66: moveToPreviousWord, + // M-d + 68: deleteNextWord + }; + var cursor = ' '; + // Opera only works with this character, not or ­, + // but IE6 displays this character, which is bad, so just use + // it on Opera. + var wbr = $.browser.opera? '​' : ''; + + //////////////////////////////////////////////////////////////////////// + // Globals + var container = $(this); + var inner = $('
          '); + var typer = $(''); + // Prompt + var promptBox; + var prompt; + var promptLabel = config && config.promptLabel? config.promptLabel : "> "; + var column = 0; + var promptText = ''; + var restoreText = ''; + // Prompt history stack + var history = []; + var ringn = 0; + // For reasons unknown to The Sword of Michael himself, Opera + // triggers and sends a key character when you hit various + // keys like PgUp, End, etc. So there is no way of knowing + // when a user has typed '#' or End. My solution is in the + // typer.keydown and typer.keypress functions; I use the + // variable below to ignore the keypress event if the keydown + // event succeeds. + var cancelKeyPress = 0; + // When this value is false, the prompt will not respond to input + var acceptInput = true; + // When this value is true, the command has been canceled + var cancelCommand = false; + + // External exports object + var extern = {}; + + //////////////////////////////////////////////////////////////////////// + // Main entry point + (function(){ + container.append(inner); + inner.append(typer); + typer.css({position:'absolute',top:0,left:'-9999px'}); + if (config.welcomeMessage) + message(config.welcomeMessage,'jquery-console-welcome'); + newPromptBox(); + if (config.autofocus) { + inner.addClass('jquery-console-focus'); + typer.focus(); + setTimeout(function(){ + inner.addClass('jquery-console-focus'); + typer.focus(); + },100); + } + extern.inner = inner; + extern.typer = typer; + extern.scrollToBottom = scrollToBottom; + })(); + + //////////////////////////////////////////////////////////////////////// + // Reset terminal + extern.reset = function(){ + var welcome = true; + inner.parent().fadeOut(function(){ + inner.find('div').each(function(){ + if (!welcome) + $(this).remove(); + welcome = false; + }); + newPromptBox(); + inner.parent().fadeIn(function(){ + inner.addClass('jquery-console-focus'); + typer.focus(); + }); + }); + }; + + //////////////////////////////////////////////////////////////////////// + // Reset terminal + extern.notice = function(msg,style){ + var n = $('
          ').append($('
          ').text(msg)) + .css({visibility:'hidden'}); + container.append(n); + var focused = true; + if (style=='fadeout') + setTimeout(function(){ + n.fadeOut(function(){ + n.remove(); + }); + },4000); + else if (style=='prompt') { + var a = $('
          '); + n.append(a); + focused = false; + a.click(function(){ n.fadeOut(function(){ n.remove();inner.css({opacity:1}) }); }); + } + var h = n.height(); + n.css({height:'0px',visibility:'visible'}) + .animate({height:h+'px'},function(){ + if (!focused) inner.css({opacity:0.5}); + }); + n.css('cursor','default'); + return n; + }; + + //////////////////////////////////////////////////////////////////////// + // Make a new prompt box + function newPromptBox() { + column = 0; + promptText = ''; + ringn = 0; // Reset the position of the history ring + enableInput(); + promptBox = $('
          '); + var label = $(''); + promptBox.append(label.text(promptLabel).show()); + prompt = $(''); + promptBox.append(prompt); + inner.append(promptBox); + updatePromptDisplay(); + }; + + //////////////////////////////////////////////////////////////////////// + // Handle setting focus + container.click(function(){ + inner.addClass('jquery-console-focus'); + inner.removeClass('jquery-console-nofocus'); + typer.focus(); + scrollToBottom(); + return false; + }); + + //////////////////////////////////////////////////////////////////////// + // Handle losing focus + typer.blur(function(){ + inner.removeClass('jquery-console-focus'); + inner.addClass('jquery-console-nofocus'); + }); + + //////////////////////////////////////////////////////////////////////// + // Handle key hit before translation + // For picking up control characters like up/left/down/right + + typer.keydown(function(e){ + cancelKeyPress = 0; + var keyCode = e.keyCode; + // C-c: cancel the execution + if(e.ctrlKey && keyCode == 67) { + cancelKeyPress = keyCode; + cancelExecution(); + return false; + } + if (acceptInput) { + if (keyCode in keyCodes) { + cancelKeyPress = keyCode; + (keyCodes[keyCode])(); + return false; + } else if (e.ctrlKey && keyCode in ctrlCodes) { + cancelKeyPress = keyCode; + (ctrlCodes[keyCode])(); + return false; + } else if (e.altKey && keyCode in altCodes) { + cancelKeyPress = keyCode; + (altCodes[keyCode])(); + return false; + } + } + }); + + //////////////////////////////////////////////////////////////////////// + // Handle key press + typer.keypress(function(e){ + var keyCode = e.keyCode || e.which; + if (isIgnorableKey(e)) { + return false; + } + if (acceptInput && cancelKeyPress != keyCode && keyCode >= 32){ + if (cancelKeyPress) return false; + if (typeof config.charInsertTrigger == 'undefined' || + (typeof config.charInsertTrigger == 'function' && + config.charInsertTrigger(keyCode,promptText))) + typer.consoleInsert(keyCode); + } + if ($.browser.webkit) return false; + }); + + function isIgnorableKey(e) { + // for now just filter alt+tab that we receive on some platforms when + // user switches windows (goes away from the browser) + return ((e.keyCode == keyCodes.tab || e.keyCode == 192) && e.altKey); + }; + + //////////////////////////////////////////////////////////////////////// + // Rotate through the command history + function rotateHistory(n){ + if (history.length == 0) return; + ringn += n; + if (ringn < 0) ringn = history.length; + else if (ringn > history.length) ringn = 0; + var prevText = promptText; + if (ringn == 0) { + promptText = restoreText; + } else { + promptText = history[ringn - 1]; + } + if (config.historyPreserveColumn) { + if (promptText.length < column + 1) { + column = promptText.length; + } else if (column == 0) { + column = promptText.length; + } + } else if (config.historyColumnAtEnd) { + column = promptText.length; + } else { + column = 0; + } + updatePromptDisplay(); + }; + + function previousHistory() { + rotateHistory(-1); + }; + + function nextHistory() { + rotateHistory(1); + }; + + // Add something to the history ring + function addToHistory(line){ + history.push(line); + restoreText = ''; + }; + + // Delete the character at the current position + function deleteCharAtPos(){ + if (column < promptText.length){ + promptText = + promptText.substring(0,column) + + promptText.substring(column+1); + restoreText = promptText; + return true; + } else return false; + }; + + function backDelete() { + if (moveColumn(-1)){ + deleteCharAtPos(); + updatePromptDisplay(); + } + }; + + function forwardDelete() { + if (deleteCharAtPos()) + updatePromptDisplay(); + }; + + function deleteUntilEnd() { + while(deleteCharAtPos()) { + updatePromptDisplay(); + } + }; + + function deleteNextWord() { + // A word is defined within this context as a series of alphanumeric + // characters. + // Delete up to the next alphanumeric character + while(column < promptText.length && + !isCharAlphanumeric(promptText[column])) { + deleteCharAtPos(); + updatePromptDisplay(); + } + // Then, delete until the next non-alphanumeric character + while(column < promptText.length && + isCharAlphanumeric(promptText[column])) { + deleteCharAtPos(); + updatePromptDisplay(); + } + }; + + //////////////////////////////////////////////////////////////////////// + // Validate command and trigger it if valid, or show a validation error + function commandTrigger() { + var line = promptText; + if (typeof config.commandValidate == 'function') { + var ret = config.commandValidate(line); + if (ret == true || ret == false) { + if (ret) { + handleCommand(); + } + } else { + commandResult(ret,"jquery-console-message-error"); + } + } else { + handleCommand(); + } + }; + + // Scroll to the bottom of the view + function scrollToBottom() { + inner.attr({ scrollTop: inner.attr("scrollHeight") });; + }; + + function cancelExecution() { + if(typeof config.cancelHandle == 'function') { + config.cancelHandle(); + } + } + + //////////////////////////////////////////////////////////////////////// + // Handle a command + function handleCommand() { + if (typeof config.commandHandle == 'function') { + disableInput(); + addToHistory(promptText); + var ret = config.commandHandle(promptText,function(msgs){ + commandResult(msgs); + }); + if (typeof ret == 'boolean') { + if (ret) { + // Command succeeded without a result. + commandResult(); + } else { + commandResult('Command failed.', + "jquery-console-message-error"); + } + } else if (typeof ret == "string") { + commandResult(ret,"jquery-console-message-success"); + } else if (typeof ret == 'object' && ret.length) { + commandResult(ret); + } + } + }; + + //////////////////////////////////////////////////////////////////////// + // Disable input + function disableInput() { + acceptInput = false; + }; + + // Enable input + function enableInput() { + acceptInput = true; + } + + //////////////////////////////////////////////////////////////////////// + // Reset the prompt in invalid command + function commandResult(msg,className) { + column = -1; + updatePromptDisplay(); + if (typeof msg == 'string') { + message(msg,className); + } else { + for (var x in msg) { + var ret = msg[x]; + message(ret.msg,ret.className); + } + } + newPromptBox(); + }; + + //////////////////////////////////////////////////////////////////////// + // Display a message + function message(msg,className) { + var mesg = $('
          '); + if (className) mesg.addClass(className); + mesg.filledText(msg).hide(); + inner.append(mesg); + mesg.show(); + }; + + //////////////////////////////////////////////////////////////////////// + // Handle normal character insertion + typer.consoleInsert = function(keyCode){ + // TODO: remove redundant indirection + var char = String.fromCharCode(keyCode); + var before = promptText.substring(0,column); + var after = promptText.substring(column); + promptText = before + char + after; + moveColumn(1); + restoreText = promptText; + updatePromptDisplay(); + }; + + //////////////////////////////////////////////////////////////////////// + // Move to another column relative to this one + // Negative means go back, positive means go forward. + function moveColumn(n){ + if (column + n >= 0 && column + n <= promptText.length){ + column += n; + return true; + } else return false; + }; + + function moveForward() { + if(moveColumn(1)) { + updatePromptDisplay(); + return true; + } + return false; + }; + + function moveBackward() { + if(moveColumn(-1)) { + updatePromptDisplay(); + return true; + } + return false; + }; + + function moveToStart() { + if (moveColumn(-column)) + updatePromptDisplay(); + }; + + function moveToEnd() { + if (moveColumn(promptText.length-column)) + updatePromptDisplay(); + }; + + function moveToNextWord() { + while(column < promptText.length && + !isCharAlphanumeric(promptText[column]) && + moveForward()) { + } + while(column < promptText.length && + isCharAlphanumeric(promptText[column]) && + moveForward()) { + } + }; + + function moveToPreviousWord() { + // Move backward until we find the first alphanumeric + while(column -1 >= 0 && + !isCharAlphanumeric(promptText[column-1]) && + moveBackward()) { + } + // Move until we find the first non-alphanumeric + while(column -1 >= 0 && + isCharAlphanumeric(promptText[column-1]) && + moveBackward()) { + } + }; + + function isCharAlphanumeric(charToTest) { + if(typeof charToTest == 'string') { + var code = charToTest.charCodeAt(); + return (code >= 'A'.charCodeAt() && code <= 'Z'.charCodeAt()) || + (code >= 'a'.charCodeAt() && code <= 'z'.charCodeAt()) || + (code >= '0'.charCodeAt() && code <= '9'.charCodeAt()); + } + return false; + }; + + function doNothing() {}; + + extern.promptText = function(text){ + if (text) { + promptText = text; + if (column > promptText.length) + column = promptText.length; + updatePromptDisplay(); + } + return promptText; + }; + + //////////////////////////////////////////////////////////////////////// + // Update the prompt display + function updatePromptDisplay(){ + var line = promptText; + var html = ''; + if (column > 0 && line == ''){ + // When we have an empty line just display a cursor. + html = cursor; + } else if (column == promptText.length){ + // We're at the end of the line, so we need to display + // the text *and* cursor. + html = htmlEncode(line) + cursor; + } else { + // Grab the current character, if there is one, and + // make it the current cursor. + var before = line.substring(0, column); + var current = line.substring(column,column+1); + if (current){ + current = + '' + + htmlEncode(current) + + ''; + } + var after = line.substring(column+1); + html = htmlEncode(before) + current + htmlEncode(after); + } + prompt.html(html); + scrollToBottom(); + }; + + // Simple HTML encoding + // Simply replace '<', '>' and '&' + // TODO: Use jQuery's .html() trick, or grab a proper, fast + // HTML encoder. + function htmlEncode(text){ + return ( + text.replace(/&/g,'&') + .replace(/&]{10})/g,'$1­' + wbr) + ); + }; + + return extern; + }; + // Simple utility for printing messages + $.fn.filledText = function(txt){ + $(this).text(txt); + $(this).html($(this).html().replace(/\n/g,'
          ')); + return this; + }; +})(jQuery); diff --git a/non-rack-legacy/public/javascripts/jquery.console.min.js b/non-rack-legacy/public/javascripts/jquery.console.min.js new file mode 100644 index 0000000..7ae1e6b --- /dev/null +++ b/non-rack-legacy/public/javascripts/jquery.console.min.js @@ -0,0 +1 @@ +(function($){$.fn.console=function(config){var keyCodes={left:37,right:39,up:38,down:40,back:8,del:46,end:35,start:36,ret:13};var cursor=' ';var wbr=$.browser.opera?'​':'';var container=$(this);var inner=$('
          ');var typer=$('');var promptBox;var prompt;var promptLabel=config&&config.promptLabel?config.promptLabel:"> ";var column=0;var promptText='';var restoreText='';var history=[];var ringn=0;var cancelKeyPress=0;var extern={};(function(){container.append(inner);inner.append(typer);typer.css({position:'absolute',top:0,left:'-999px'});if(config.welcomeMessage)message(config.welcomeMessage,'jquery-console-welcome');newPromptBox();if(config.autofocus){inner.addClass('jquery-console-focus');typer.focus();setTimeout(function(){inner.addClass('jquery-console-focus');typer.focus()},100)}})();extern.reset=function(){var welcome=true;inner.parent().fadeOut(function(){inner.find('div').each(function(){if(!welcome)$(this).remove();welcome=false});newPromptBox();inner.parent().fadeIn(function(){inner.addClass('jquery-console-focus');typer.focus()})})};function newPromptBox(){column=0;promptText='';promptBox=$('
          ');var label=$('');promptBox.append(label.text(promptLabel).show());prompt=$('');promptBox.append(prompt);inner.append(promptBox);updatePromptDisplay()};container.click(function(){inner.addClass('jquery-console-focus');inner.removeClass('jquery-console-nofocus');typer.focus();scrollToBottom();return false});typer.blur(function(){inner.removeClass('jquery-console-focus');inner.addClass('jquery-console-nofocus')});typer.keydown(function(e){cancelKeyPress=0;var keyCode=e.keyCode;if(isControlCharacter(keyCode)){cancelKeyPress=keyCode;if(!typer.consoleControl(keyCode)){return false}}});typer.keypress(function(e){var keyCode=e.keyCode||e.which;if(cancelKeyPress!=keyCode&&keyCode>=32){if(cancelKeyPress)return false;typer.consoleInsert(keyCode)}if($.browser.webkit)return false});function isControlCharacter(keyCode){return((keyCode>=keyCodes.left&&keyCode<=keyCodes.down)||keyCode==keyCodes.back||keyCode==keyCodes.del||keyCode==keyCodes.end||keyCode==keyCodes.start||keyCode==keyCodes.ret)};typer.consoleControl=function(keyCode){switch(keyCode){case keyCodes.left:{moveColumn(-1);updatePromptDisplay();return false;break}case keyCodes.right:{moveColumn(1);updatePromptDisplay();return false;break}case keyCodes.back:{if(moveColumn(-1)){deleteCharAtPos();updatePromptDisplay()}return false;break}case keyCodes.del:{if(deleteCharAtPos())updatePromptDisplay();return false;break}case keyCodes.end:{if(moveColumn(promptText.length-column))updatePromptDisplay();return false;break}case keyCodes.start:{if(moveColumn(-column))updatePromptDisplay();return false;break}case keyCodes.ret:{commandTrigger();return false}case keyCodes.up:{rotateHistory(-1);return false}case keyCodes.down:{rotateHistory(1);return false}default:}};function rotateHistory(n){if(history.length==0)return;ringn+=n;if(ringn<0)ringn=history.length;else if(ringn>history.length)ringn=0;var prevText=promptText;if(ringn==0){promptText=restoreText}else{promptText=history[ringn-1]}if(config.historyPreserveColumn){if(promptText.length
          ');if(className)mesg.addClass(className);mesg.filledText(msg).hide();inner.append(mesg);mesg.show()};typer.consoleInsert=function(keyCode){var char=String.fromCharCode(keyCode);var before=promptText.substring(0,column);var after=promptText.substring(column);promptText=before+char+after;moveColumn(1);restoreText=promptText;updatePromptDisplay()};function moveColumn(n){if(column+n>=0&&column+n<=promptText.length){column+=n;return true}else return false};function updatePromptDisplay(){var line=promptText;var html='';if(column>0&&line==''){html=cursor}else if(column==promptText.length){html=htmlEncode(line)+cursor}else{var before=line.substring(0,column);var current=line.substring(column,column+1);if(current){current=''+htmlEncode(current)+''}var after=line.substring(column+1);html=htmlEncode(before)+current+htmlEncode(after)}prompt.html(html);scrollToBottom()};function htmlEncode(text){return(text.replace(/&/g,'&').replace(/&]{10})/g,'$1­'+wbr))};return extern};$.fn.filledText=function(txt){$(this).text(txt);$(this).html($(this).html().replace(/\n/g,'
          '));return this}})(jQuery); \ No newline at end of file diff --git a/non-rack-legacy/public/javascripts/jquery.js b/non-rack-legacy/public/javascripts/jquery.js new file mode 100755 index 0000000..3747929 --- /dev/null +++ b/non-rack-legacy/public/javascripts/jquery.js @@ -0,0 +1,32 @@ +/* + * jQuery 1.2.3 - New Wave Javascript + * + * Copyright (c) 2008 John Resig (jquery.com) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * $Date: 2008-02-06 00:21:25 -0500 (Wed, 06 Feb 2008) $ + * $Rev: 4663 $ + */ +(function(){if(window.jQuery)var _jQuery=window.jQuery;var jQuery=window.jQuery=function(selector,context){return new jQuery.prototype.init(selector,context);};if(window.$)var _$=window.$;window.$=jQuery;var quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;var isSimple=/^.[^:#\[\.]*$/;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;return this;}else if(typeof selector=="string"){var match=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1])selector=jQuery.clean([match[1]],context);else{var elem=document.getElementById(match[3]);if(elem)if(elem.id!=match[3])return jQuery().find(selector);else{this[0]=elem;this.length=1;return this;}else +selector=[];}}else +return new jQuery(context).find(selector);}else if(jQuery.isFunction(selector))return new jQuery(document)[jQuery.fn.ready?"ready":"load"](selector);return this.setArray(selector.constructor==Array&&selector||(selector.jquery||selector.length&&selector!=window&&!selector.nodeType&&selector[0]!=undefined&&selector[0].nodeType)&&jQuery.makeArray(selector)||[selector]);},jquery:"1.2.3",size:function(){return this.length;},length:0,get:function(num){return num==undefined?jQuery.makeArray(this):this[num];},pushStack:function(elems){var ret=jQuery(elems);ret.prevObject=this;return ret;},setArray:function(elems){this.length=0;Array.prototype.push.apply(this,elems);return this;},each:function(callback,args){return jQuery.each(this,callback,args);},index:function(elem){var ret=-1;this.each(function(i){if(this==elem)ret=i;});return ret;},attr:function(name,value,type){var options=name;if(name.constructor==String)if(value==undefined)return this.length&&jQuery[type||"attr"](this[0],name)||undefined;else{options={};options[name]=value;}return this.each(function(i){for(name in options)jQuery.attr(type?this.style:this,name,jQuery.prop(this,options[name],type,i,name));});},css:function(key,value){if((key=='width'||key=='height')&&parseFloat(value)<0)value=undefined;return this.attr(key,value,"curCSS");},text:function(text){if(typeof text!="object"&&text!=null)return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(text));var ret="";jQuery.each(text||this,function(){jQuery.each(this.childNodes,function(){if(this.nodeType!=8)ret+=this.nodeType!=1?this.nodeValue:jQuery.fn.text([this]);});});return ret;},wrapAll:function(html){if(this[0])jQuery(html,this[0].ownerDocument).clone().insertBefore(this[0]).map(function(){var elem=this;while(elem.firstChild)elem=elem.firstChild;return elem;}).append(this);return this;},wrapInner:function(html){return this.each(function(){jQuery(this).contents().wrapAll(html);});},wrap:function(html){return this.each(function(){jQuery(this).wrapAll(html);});},append:function(){return this.domManip(arguments,true,false,function(elem){if(this.nodeType==1)this.appendChild(elem);});},prepend:function(){return this.domManip(arguments,true,true,function(elem){if(this.nodeType==1)this.insertBefore(elem,this.firstChild);});},before:function(){return this.domManip(arguments,false,false,function(elem){this.parentNode.insertBefore(elem,this);});},after:function(){return this.domManip(arguments,false,true,function(elem){this.parentNode.insertBefore(elem,this.nextSibling);});},end:function(){return this.prevObject||jQuery([]);},find:function(selector){var elems=jQuery.map(this,function(elem){return jQuery.find(selector,elem);});return this.pushStack(/[^+>] [^+>]/.test(selector)||selector.indexOf("..")>-1?jQuery.unique(elems):elems);},clone:function(events){var ret=this.map(function(){if(jQuery.browser.msie&&!jQuery.isXMLDoc(this)){var clone=this.cloneNode(true),container=document.createElement("div");container.appendChild(clone);return jQuery.clean([container.innerHTML])[0];}else +return this.cloneNode(true);});var clone=ret.find("*").andSelf().each(function(){if(this[expando]!=undefined)this[expando]=null;});if(events===true)this.find("*").andSelf().each(function(i){if(this.nodeType==3)return;var events=jQuery.data(this,"events");for(var type in events)for(var handler in events[type])jQuery.event.add(clone[i],type,events[type][handler],events[type][handler].data);});return ret;},filter:function(selector){return this.pushStack(jQuery.isFunction(selector)&&jQuery.grep(this,function(elem,i){return selector.call(elem,i);})||jQuery.multiFilter(selector,this));},not:function(selector){if(selector.constructor==String)if(isSimple.test(selector))return this.pushStack(jQuery.multiFilter(selector,this,true));else +selector=jQuery.multiFilter(selector,this);var isArrayLike=selector.length&&selector[selector.length-1]!==undefined&&!selector.nodeType;return this.filter(function(){return isArrayLike?jQuery.inArray(this,selector)<0:this!=selector;});},add:function(selector){return!selector?this:this.pushStack(jQuery.merge(this.get(),selector.constructor==String?jQuery(selector).get():selector.length!=undefined&&(!selector.nodeName||jQuery.nodeName(selector,"form"))?selector:[selector]));},is:function(selector){return selector?jQuery.multiFilter(selector,this).length>0:false;},hasClass:function(selector){return this.is("."+selector);},val:function(value){if(value==undefined){if(this.length){var elem=this[0];if(jQuery.nodeName(elem,"select")){var index=elem.selectedIndex,values=[],options=elem.options,one=elem.type=="select-one";if(index<0)return null;for(var i=one?index:0,max=one?index+1:options.length;i=0||jQuery.inArray(this.name,value)>=0);else if(jQuery.nodeName(this,"select")){var values=value.constructor==Array?value:[value];jQuery("option",this).each(function(){this.selected=(jQuery.inArray(this.value,values)>=0||jQuery.inArray(this.text,values)>=0);});if(!values.length)this.selectedIndex=-1;}else +this.value=value;});},html:function(value){return value==undefined?(this.length?this[0].innerHTML:null):this.empty().append(value);},replaceWith:function(value){return this.after(value).remove();},eq:function(i){return this.slice(i,i+1);},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments));},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem);}));},andSelf:function(){return this.add(this.prevObject);},data:function(key,value){var parts=key.split(".");parts[1]=parts[1]?"."+parts[1]:"";if(value==null){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data==undefined&&this.length)data=jQuery.data(this[0],key);return data==null&&parts[1]?this.data(parts[0]):data;}else +return this.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){jQuery.data(this,key,value);});},removeData:function(key){return this.each(function(){jQuery.removeData(this,key);});},domManip:function(args,table,reverse,callback){var clone=this.length>1,elems;return this.each(function(){if(!elems){elems=jQuery.clean(args,this.ownerDocument);if(reverse)elems.reverse();}var obj=this;if(table&&jQuery.nodeName(this,"table")&&jQuery.nodeName(elems[0],"tr"))obj=this.getElementsByTagName("tbody")[0]||this.appendChild(this.ownerDocument.createElement("tbody"));var scripts=jQuery([]);jQuery.each(elems,function(){var elem=clone?jQuery(this).clone(true)[0]:this;if(jQuery.nodeName(elem,"script")){scripts=scripts.add(elem);}else{if(elem.nodeType==1)scripts=scripts.add(jQuery("script",elem).remove());callback.call(obj,elem);}});scripts.each(evalScript);});}};jQuery.prototype.init.prototype=jQuery.prototype;function evalScript(i,elem){if(elem.src)jQuery.ajax({url:elem.src,async:false,dataType:"script"});else +jQuery.globalEval(elem.text||elem.textContent||elem.innerHTML||"");if(elem.parentNode)elem.parentNode.removeChild(elem);}jQuery.extend=jQuery.fn.extend=function(){var target=arguments[0]||{},i=1,length=arguments.length,deep=false,options;if(target.constructor==Boolean){deep=target;target=arguments[1]||{};i=2;}if(typeof target!="object"&&typeof target!="function")target={};if(length==1){target=this;i=0;}for(;i-1;}},swap:function(elem,options,callback){var old={};for(var name in options){old[name]=elem.style[name];elem.style[name]=options[name];}callback.call(elem);for(var name in options)elem.style[name]=old[name];},css:function(elem,name,force){if(name=="width"||name=="height"){var val,props={position:"absolute",visibility:"hidden",display:"block"},which=name=="width"?["Left","Right"]:["Top","Bottom"];function getWH(){val=name=="width"?elem.offsetWidth:elem.offsetHeight;var padding=0,border=0;jQuery.each(which,function(){padding+=parseFloat(jQuery.curCSS(elem,"padding"+this,true))||0;border+=parseFloat(jQuery.curCSS(elem,"border"+this+"Width",true))||0;});val-=Math.round(padding+border);}if(jQuery(elem).is(":visible"))getWH();else +jQuery.swap(elem,props,getWH);return Math.max(0,val);}return jQuery.curCSS(elem,name,force);},curCSS:function(elem,name,force){var ret;function color(elem){if(!jQuery.browser.safari)return false;var ret=document.defaultView.getComputedStyle(elem,null);return!ret||ret.getPropertyValue("color")=="";}if(name=="opacity"&&jQuery.browser.msie){ret=jQuery.attr(elem.style,"opacity");return ret==""?"1":ret;}if(jQuery.browser.opera&&name=="display"){var save=elem.style.outline;elem.style.outline="0 solid black";elem.style.outline=save;}if(name.match(/float/i))name=styleFloat;if(!force&&elem.style&&elem.style[name])ret=elem.style[name];else if(document.defaultView&&document.defaultView.getComputedStyle){if(name.match(/float/i))name="float";name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var getComputedStyle=document.defaultView.getComputedStyle(elem,null);if(getComputedStyle&&!color(elem))ret=getComputedStyle.getPropertyValue(name);else{var swap=[],stack=[];for(var a=elem;a&&color(a);a=a.parentNode)stack.unshift(a);for(var i=0;i]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+">";});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("",""]||!tags.indexOf("",""]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
          "]||!tags.indexOf("",""]||(!tags.indexOf("",""]||!tags.indexOf("",""]||jQuery.browser.msie&&[1,"div
          ","
          "]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--)div=div.lastChild;if(jQuery.browser.msie){var tbody=!tags.indexOf(""&&tags.indexOf("=0;--j)if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length)tbody[j].parentNode.removeChild(tbody[j]);if(/^\s/.test(elem))div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]),div.firstChild);}elem=jQuery.makeArray(div.childNodes);}if(elem.length===0&&(!jQuery.nodeName(elem,"form")&&!jQuery.nodeName(elem,"select")))return;if(elem[0]==undefined||jQuery.nodeName(elem,"form")||elem.options)ret.push(elem);else +ret=jQuery.merge(ret,elem);});return ret;},attr:function(elem,name,value){if(!elem||elem.nodeType==3||elem.nodeType==8)return undefined;var fix=jQuery.isXMLDoc(elem)?{}:jQuery.props;if(name=="selected"&&jQuery.browser.safari)elem.parentNode.selectedIndex;if(fix[name]){if(value!=undefined)elem[fix[name]]=value;return elem[fix[name]];}else if(jQuery.browser.msie&&name=="style")return jQuery.attr(elem.style,"cssText",value);else if(value==undefined&&jQuery.browser.msie&&jQuery.nodeName(elem,"form")&&(name=="action"||name=="method"))return elem.getAttributeNode(name).nodeValue;else if(elem.tagName){if(value!=undefined){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode)throw"type property can't be changed";elem.setAttribute(name,""+value);}if(jQuery.browser.msie&&/href|src/.test(name)&&!jQuery.isXMLDoc(elem))return elem.getAttribute(name,2);return elem.getAttribute(name);}else{if(name=="opacity"&&jQuery.browser.msie){if(value!=undefined){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+(parseFloat(value).toString()=="NaN"?"":"alpha(opacity="+value*100+")");}return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100).toString():"";}name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase();});if(value!=undefined)elem[name]=value;return elem[name];}},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"");},makeArray:function(array){var ret=[];if(typeof array!="array")for(var i=0,length=array.length;i*",this).remove();while(this.firstChild)this.removeChild(this.firstChild);}},function(name,fn){jQuery.fn[name]=function(){return this.each(fn,arguments);};});jQuery.each(["Height","Width"],function(i,name){var type=name.toLowerCase();jQuery.fn[type]=function(size){return this[0]==window?jQuery.browser.opera&&document.body["client"+name]||jQuery.browser.safari&&window["inner"+name]||document.compatMode=="CSS1Compat"&&document.documentElement["client"+name]||document.body["client"+name]:this[0]==document?Math.max(Math.max(document.body["scroll"+name],document.documentElement["scroll"+name]),Math.max(document.body["offset"+name],document.documentElement["offset"+name])):size==undefined?(this.length?jQuery.css(this[0],type):null):this.css(type,size.constructor==String?size:size+"px");};});var chars=jQuery.browser.safari&&parseInt(jQuery.browser.version)<417?"(?:[\\w*_-]|\\\\.)":"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",quickChild=new RegExp("^>\\s*("+chars+"+)"),quickID=new RegExp("^("+chars+"+)(#)("+chars+"+)"),quickClass=new RegExp("^([#.]?)("+chars+"*)");jQuery.extend({expr:{"":function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},"#":function(a,i,m){return a.getAttribute("id")==m[2];},":":{lt:function(a,i,m){return im[3]-0;},nth:function(a,i,m){return m[3]-0==i;},eq:function(a,i,m){return m[3]-0==i;},first:function(a,i){return i==0;},last:function(a,i,m,r){return i==r.length-1;},even:function(a,i){return i%2==0;},odd:function(a,i){return i%2;},"first-child":function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},"last-child":function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},"only-child":function(a){return!jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},parent:function(a){return a.firstChild;},empty:function(a){return!a.firstChild;},contains:function(a,i,m){return(a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},visible:function(a){return"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},hidden:function(a){return"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},enabled:function(a){return!a.disabled;},disabled:function(a){return a.disabled;},checked:function(a){return a.checked;},selected:function(a){return a.selected||jQuery.attr(a,"selected");},text:function(a){return"text"==a.type;},radio:function(a){return"radio"==a.type;},checkbox:function(a){return"checkbox"==a.type;},file:function(a){return"file"==a.type;},password:function(a){return"password"==a.type;},submit:function(a){return"submit"==a.type;},image:function(a){return"image"==a.type;},reset:function(a){return"reset"==a.type;},button:function(a){return"button"==a.type||jQuery.nodeName(a,"button");},input:function(a){return/input|select|textarea|button/i.test(a.nodeName);},has:function(a,i,m){return jQuery.find(m[3],a).length;},header:function(a){return/h\d/i.test(a.nodeName);},animated:function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}}},parse:[/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,new RegExp("^([:.#]*)("+chars+"+)")],multiFilter:function(expr,elems,not){var old,cur=[];while(expr&&expr!=old){old=expr;var f=jQuery.filter(expr,elems,not);expr=f.t.replace(/^\s*,\s*/,"");cur=not?elems=f.r:jQuery.merge(cur,f.r);}return cur;},find:function(t,context){if(typeof t!="string")return[t];if(context&&context.nodeType!=1&&context.nodeType!=9)return[];context=context||document;var ret=[context],done=[],last,nodeName;while(t&&last!=t){var r=[];last=t;t=jQuery.trim(t);var foundToken=false;var re=quickChild;var m=re.exec(t);if(m){nodeName=m[1].toUpperCase();for(var i=0;ret[i];i++)for(var c=ret[i].firstChild;c;c=c.nextSibling)if(c.nodeType==1&&(nodeName=="*"||c.nodeName.toUpperCase()==nodeName))r.push(c);ret=r;t=t.replace(re,"");if(t.indexOf(" ")==0)continue;foundToken=true;}else{re=/^([>+~])\s*(\w*)/i;if((m=re.exec(t))!=null){r=[];var merge={};nodeName=m[2].toUpperCase();m=m[1];for(var j=0,rl=ret.length;j=0;if(!not&&pass||not&&!pass)tmp.push(r[i]);}return tmp;},filter:function(t,r,not){var last;while(t&&t!=last){last=t;var p=jQuery.parse,m;for(var i=0;p[i];i++){m=p[i].exec(t);if(m){t=t.substring(m[0].length);m[2]=m[2].replace(/\\/g,"");break;}}if(!m)break;if(m[1]==":"&&m[2]=="not")r=isSimple.test(m[3])?jQuery.filter(m[3],r,true).r:jQuery(r).not(m[3]);else if(m[1]==".")r=jQuery.classFilter(r,m[2],not);else if(m[1]=="["){var tmp=[],type=m[3];for(var i=0,rl=r.length;i=0)^not)tmp.push(a);}r=tmp;}else if(m[1]==":"&&m[2]=="nth-child"){var merge={},tmp=[],test=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3]=="even"&&"2n"||m[3]=="odd"&&"2n+1"||!/\D/.test(m[3])&&"0n+"+m[3]||m[3]),first=(test[1]+(test[2]||1))-0,last=test[3]-0;for(var i=0,rl=r.length;i=0)add=true;if(add^not)tmp.push(node);}r=tmp;}else{var fn=jQuery.expr[m[1]];if(typeof fn=="object")fn=fn[m[2]];if(typeof fn=="string")fn=eval("false||function(a,i){return "+fn+";}");r=jQuery.grep(r,function(elem,i){return fn(elem,i,m,r);},not);}}return{r:r,t:t};},dir:function(elem,dir){var matched=[];var cur=elem[dir];while(cur&&cur!=document){if(cur.nodeType==1)matched.push(cur);cur=cur[dir];}return matched;},nth:function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir])if(cur.nodeType==1&&++num==result)break;return cur;},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType==1&&(!elem||n!=elem))r.push(n);}return r;}});jQuery.event={add:function(elem,types,handler,data){if(elem.nodeType==3||elem.nodeType==8)return;if(jQuery.browser.msie&&elem.setInterval!=undefined)elem=window;if(!handler.guid)handler.guid=this.guid++;if(data!=undefined){var fn=handler;handler=function(){return fn.apply(this,arguments);};handler.data=data;handler.guid=fn.guid;}var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){var val;if(typeof jQuery=="undefined"||jQuery.event.triggered)return val;val=jQuery.event.handle.apply(arguments.callee.elem,arguments);return val;});handle.elem=elem;jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];handler.type=parts[1];var handlers=events[type];if(!handlers){handlers=events[type]={};if(!jQuery.event.special[type]||jQuery.event.special[type].setup.call(elem)===false){if(elem.addEventListener)elem.addEventListener(type,handle,false);else if(elem.attachEvent)elem.attachEvent("on"+type,handle);}}handlers[handler.guid]=handler;jQuery.event.global[type]=true;});elem=null;},guid:1,global:{},remove:function(elem,types,handler){if(elem.nodeType==3||elem.nodeType==8)return;var events=jQuery.data(elem,"events"),ret,index;if(events){if(types==undefined||(typeof types=="string"&&types.charAt(0)=="."))for(var type in events)this.remove(elem,type+(types||""));else{if(types.type){handler=types.handler;types=types.type;}jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];if(events[type]){if(handler)delete events[type][handler.guid];else +for(handler in events[type])if(!parts[1]||events[type][handler].type==parts[1])delete events[type][handler];for(ret in events[type])break;if(!ret){if(!jQuery.event.special[type]||jQuery.event.special[type].teardown.call(elem)===false){if(elem.removeEventListener)elem.removeEventListener(type,jQuery.data(elem,"handle"),false);else if(elem.detachEvent)elem.detachEvent("on"+type,jQuery.data(elem,"handle"));}ret=null;delete events[type];}}});}for(ret in events)break;if(!ret){var handle=jQuery.data(elem,"handle");if(handle)handle.elem=null;jQuery.removeData(elem,"events");jQuery.removeData(elem,"handle");}}},trigger:function(type,data,elem,donative,extra){data=jQuery.makeArray(data||[]);if(type.indexOf("!")>=0){type=type.slice(0,-1);var exclusive=true;}if(!elem){if(this.global[type])jQuery("*").add([window,document]).trigger(type,data);}else{if(elem.nodeType==3||elem.nodeType==8)return undefined;var val,ret,fn=jQuery.isFunction(elem[type]||null),event=!data[0]||!data[0].preventDefault;if(event)data.unshift(this.fix({type:type,target:elem}));data[0].type=type;if(exclusive)data[0].exclusive=true;if(jQuery.isFunction(jQuery.data(elem,"handle")))val=jQuery.data(elem,"handle").apply(elem,data);if(!fn&&elem["on"+type]&&elem["on"+type].apply(elem,data)===false)val=false;if(event)data.shift();if(extra&&jQuery.isFunction(extra)){ret=extra.apply(elem,val==null?data:data.concat(val));if(ret!==undefined)val=ret;}if(fn&&donative!==false&&val!==false&&!(jQuery.nodeName(elem,'a')&&type=="click")){this.triggered=true;try{elem[type]();}catch(e){}}this.triggered=false;}return val;},handle:function(event){var val;event=jQuery.event.fix(event||window.event||{});var parts=event.type.split(".");event.type=parts[0];var handlers=jQuery.data(this,"events")&&jQuery.data(this,"events")[event.type],args=Array.prototype.slice.call(arguments,1);args.unshift(event);for(var j in handlers){var handler=handlers[j];args[0].handler=handler;args[0].data=handler.data;if(!parts[1]&&!event.exclusive||handler.type==parts[1]){var ret=handler.apply(this,args);if(val!==false)val=ret;if(ret===false){event.preventDefault();event.stopPropagation();}}}if(jQuery.browser.msie)event.target=event.preventDefault=event.stopPropagation=event.handler=event.data=null;return val;},fix:function(event){var originalEvent=event;event=jQuery.extend({},originalEvent);event.preventDefault=function(){if(originalEvent.preventDefault)originalEvent.preventDefault();originalEvent.returnValue=false;};event.stopPropagation=function(){if(originalEvent.stopPropagation)originalEvent.stopPropagation();originalEvent.cancelBubble=true;};if(!event.target)event.target=event.srcElement||document;if(event.target.nodeType==3)event.target=originalEvent.target.parentNode;if(!event.relatedTarget&&event.fromElement)event.relatedTarget=event.fromElement==event.target?event.toElement:event.fromElement;if(event.pageX==null&&event.clientX!=null){var doc=document.documentElement,body=document.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc.clientTop||0);}if(!event.which&&((event.charCode||event.charCode===0)?event.charCode:event.keyCode))event.which=event.charCode||event.keyCode;if(!event.metaKey&&event.ctrlKey)event.metaKey=event.ctrlKey;if(!event.which&&event.button)event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)));return event;},special:{ready:{setup:function(){bindReady();return;},teardown:function(){return;}},mouseenter:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseover",jQuery.event.special.mouseenter.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseover",jQuery.event.special.mouseenter.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseenter";return jQuery.event.handle.apply(this,arguments);}},mouseleave:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseout",jQuery.event.special.mouseleave.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseout",jQuery.event.special.mouseleave.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseleave";return jQuery.event.handle.apply(this,arguments);}}}};jQuery.fn.extend({bind:function(type,data,fn){return type=="unload"?this.one(type,data,fn):this.each(function(){jQuery.event.add(this,type,fn||data,fn&&data);});},one:function(type,data,fn){return this.each(function(){jQuery.event.add(this,type,function(event){jQuery(this).unbind(event);return(fn||data).apply(this,arguments);},fn&&data);});},unbind:function(type,fn){return this.each(function(){jQuery.event.remove(this,type,fn);});},trigger:function(type,data,fn){return this.each(function(){jQuery.event.trigger(type,data,this,true,fn);});},triggerHandler:function(type,data,fn){if(this[0])return jQuery.event.trigger(type,data,this[0],false,fn);return undefined;},toggle:function(){var args=arguments;return this.click(function(event){this.lastToggle=0==this.lastToggle?1:0;event.preventDefault();return args[this.lastToggle].apply(this,arguments)||false;});},hover:function(fnOver,fnOut){return this.bind('mouseenter',fnOver).bind('mouseleave',fnOut);},ready:function(fn){bindReady();if(jQuery.isReady)fn.call(document,jQuery);else +jQuery.readyList.push(function(){return fn.call(this,jQuery);});return this;}});jQuery.extend({isReady:false,readyList:[],ready:function(){if(!jQuery.isReady){jQuery.isReady=true;if(jQuery.readyList){jQuery.each(jQuery.readyList,function(){this.apply(document);});jQuery.readyList=null;}jQuery(document).triggerHandler("ready");}}});var readyBound=false;function bindReady(){if(readyBound)return;readyBound=true;if(document.addEventListener&&!jQuery.browser.opera)document.addEventListener("DOMContentLoaded",jQuery.ready,false);if(jQuery.browser.msie&&window==top)(function(){if(jQuery.isReady)return;try{document.documentElement.doScroll("left");}catch(error){setTimeout(arguments.callee,0);return;}jQuery.ready();})();if(jQuery.browser.opera)document.addEventListener("DOMContentLoaded",function(){if(jQuery.isReady)return;for(var i=0;i=0){var selector=url.slice(off,url.length);url=url.slice(0,off);}callback=callback||function(){};var type="GET";if(params)if(jQuery.isFunction(params)){callback=params;params=null;}else{params=jQuery.param(params);type="POST";}var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(res,status){if(status=="success"||status=="notmodified")self.html(selector?jQuery("
          ").append(res.responseText.replace(//g,"")).find(selector):res.responseText);self.each(callback,[res.responseText,status,res]);}});return this;},serialize:function(){return jQuery.param(this.serializeArray());},serializeArray:function(){return this.map(function(){return jQuery.nodeName(this,"form")?jQuery.makeArray(this.elements):this;}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type));}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:val.constructor==Array?jQuery.map(val,function(val,i){return{name:elem.name,value:val};}):{name:elem.name,value:val};}).get();}});jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(i,o){jQuery.fn[o]=function(f){return this.bind(o,f);};});var jsc=(new Date).getTime();jQuery.extend({get:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data=null;}return jQuery.ajax({type:"GET",url:url,data:data,success:callback,dataType:type});},getScript:function(url,callback){return jQuery.get(url,null,callback,"script");},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},post:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data={};}return jQuery.ajax({type:"POST",url:url,data:data,success:callback,dataType:type});},ajaxSetup:function(settings){jQuery.extend(jQuery.ajaxSettings,settings);},ajaxSettings:{global:true,type:"GET",timeout:0,contentType:"application/x-www-form-urlencoded",processData:true,async:true,data:null,username:null,password:null,accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(s){var jsonp,jsre=/=\?(&|$)/g,status,data;s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));if(s.data&&s.processData&&typeof s.data!="string")s.data=jQuery.param(s.data);if(s.dataType=="jsonp"){if(s.type.toLowerCase()=="get"){if(!s.url.match(jsre))s.url+=(s.url.match(/\?/)?"&":"?")+(s.jsonp||"callback")+"=?";}else if(!s.data||!s.data.match(jsre))s.data=(s.data?s.data+"&":"")+(s.jsonp||"callback")+"=?";s.dataType="json";}if(s.dataType=="json"&&(s.data&&s.data.match(jsre)||s.url.match(jsre))){jsonp="jsonp"+jsc++;if(s.data)s.data=(s.data+"").replace(jsre,"="+jsonp+"$1");s.url=s.url.replace(jsre,"="+jsonp+"$1");s.dataType="script";window[jsonp]=function(tmp){data=tmp;success();complete();window[jsonp]=undefined;try{delete window[jsonp];}catch(e){}if(head)head.removeChild(script);};}if(s.dataType=="script"&&s.cache==null)s.cache=false;if(s.cache===false&&s.type.toLowerCase()=="get"){var ts=(new Date()).getTime();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"");}if(s.data&&s.type.toLowerCase()=="get"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null;}if(s.global&&!jQuery.active++)jQuery.event.trigger("ajaxStart");if((!s.url.indexOf("http")||!s.url.indexOf("//"))&&s.dataType=="script"&&s.type.toLowerCase()=="get"){var head=document.getElementsByTagName("head")[0];var script=document.createElement("script");script.src=s.url;if(s.scriptCharset)script.charset=s.scriptCharset;if(!jsonp){var done=false;script.onload=script.onreadystatechange=function(){if(!done&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){done=true;success();complete();head.removeChild(script);}};}head.appendChild(script);return undefined;}var requestDone=false;var xml=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();xml.open(s.type,s.url,s.async,s.username,s.password);try{if(s.data)xml.setRequestHeader("Content-Type",s.contentType);if(s.ifModified)xml.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT");xml.setRequestHeader("X-Requested-With","XMLHttpRequest");xml.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default);}catch(e){}if(s.beforeSend)s.beforeSend(xml);if(s.global)jQuery.event.trigger("ajaxSend",[xml,s]);var onreadystatechange=function(isTimeout){if(!requestDone&&xml&&(xml.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null;}status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xml)&&"error"||s.ifModified&&jQuery.httpNotModified(xml,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xml,s.dataType);}catch(e){status="parsererror";}}if(status=="success"){var modRes;try{modRes=xml.getResponseHeader("Last-Modified");}catch(e){}if(s.ifModified&&modRes)jQuery.lastModified[s.url]=modRes;if(!jsonp)success();}else +jQuery.handleError(s,xml,status);complete();if(s.async)xml=null;}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0)setTimeout(function(){if(xml){xml.abort();if(!requestDone)onreadystatechange("timeout");}},s.timeout);}try{xml.send(s.data);}catch(e){jQuery.handleError(s,xml,null,e);}if(!s.async)onreadystatechange();function success(){if(s.success)s.success(data,status);if(s.global)jQuery.event.trigger("ajaxSuccess",[xml,s]);}function complete(){if(s.complete)s.complete(xml,status);if(s.global)jQuery.event.trigger("ajaxComplete",[xml,s]);if(s.global&&!--jQuery.active)jQuery.event.trigger("ajaxStop");}return xml;},handleError:function(s,xml,status,e){if(s.error)s.error(xml,status,e);if(s.global)jQuery.event.trigger("ajaxError",[xml,s,e]);},active:0,httpSuccess:function(r){try{return!r.status&&location.protocol=="file:"||(r.status>=200&&r.status<300)||r.status==304||r.status==1223||jQuery.browser.safari&&r.status==undefined;}catch(e){}return false;},httpNotModified:function(xml,url){try{var xmlRes=xml.getResponseHeader("Last-Modified");return xml.status==304||xmlRes==jQuery.lastModified[url]||jQuery.browser.safari&&xml.status==undefined;}catch(e){}return false;},httpData:function(r,type){var ct=r.getResponseHeader("content-type");var xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0;var data=xml?r.responseXML:r.responseText;if(xml&&data.documentElement.tagName=="parsererror")throw"parsererror";if(type=="script")jQuery.globalEval(data);if(type=="json")data=eval("("+data+")");return data;},param:function(a){var s=[];if(a.constructor==Array||a.jquery)jQuery.each(a,function(){s.push(encodeURIComponent(this.name)+"="+encodeURIComponent(this.value));});else +for(var j in a)if(a[j]&&a[j].constructor==Array)jQuery.each(a[j],function(){s.push(encodeURIComponent(j)+"="+encodeURIComponent(this));});else +s.push(encodeURIComponent(j)+"="+encodeURIComponent(a[j]));return s.join("&").replace(/%20/g,"+");}});jQuery.fn.extend({show:function(speed,callback){return speed?this.animate({height:"show",width:"show",opacity:"show"},speed,callback):this.filter(":hidden").each(function(){this.style.display=this.oldblock||"";if(jQuery.css(this,"display")=="none"){var elem=jQuery("<"+this.tagName+" />").appendTo("body");this.style.display=elem.css("display");if(this.style.display=="none")this.style.display="block";elem.remove();}}).end();},hide:function(speed,callback){return speed?this.animate({height:"hide",width:"hide",opacity:"hide"},speed,callback):this.filter(":visible").each(function(){this.oldblock=this.oldblock||jQuery.css(this,"display");this.style.display="none";}).end();},_toggle:jQuery.fn.toggle,toggle:function(fn,fn2){return jQuery.isFunction(fn)&&jQuery.isFunction(fn2)?this._toggle(fn,fn2):fn?this.animate({height:"toggle",width:"toggle",opacity:"toggle"},fn,fn2):this.each(function(){jQuery(this)[jQuery(this).is(":hidden")?"show":"hide"]();});},slideDown:function(speed,callback){return this.animate({height:"show"},speed,callback);},slideUp:function(speed,callback){return this.animate({height:"hide"},speed,callback);},slideToggle:function(speed,callback){return this.animate({height:"toggle"},speed,callback);},fadeIn:function(speed,callback){return this.animate({opacity:"show"},speed,callback);},fadeOut:function(speed,callback){return this.animate({opacity:"hide"},speed,callback);},fadeTo:function(speed,to,callback){return this.animate({opacity:to},speed,callback);},animate:function(prop,speed,easing,callback){var optall=jQuery.speed(speed,easing,callback);return this[optall.queue===false?"each":"queue"](function(){if(this.nodeType!=1)return false;var opt=jQuery.extend({},optall);var hidden=jQuery(this).is(":hidden"),self=this;for(var p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden)return jQuery.isFunction(opt.complete)&&opt.complete.apply(this);if(p=="height"||p=="width"){opt.display=jQuery.css(this,"display");opt.overflow=this.style.overflow;}}if(opt.overflow!=null)this.style.overflow="hidden";opt.curAnim=jQuery.extend({},prop);jQuery.each(prop,function(name,val){var e=new jQuery.fx(self,opt,name);if(/toggle|show|hide/.test(val))e[val=="toggle"?hidden?"show":"hide":val](prop);else{var parts=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),start=e.cur(true)||0;if(parts){var end=parseFloat(parts[2]),unit=parts[3]||"px";if(unit!="px"){self.style[name]=(end||1)+unit;start=((end||1)/e.cur(true))*start;self.style[name]=start+unit;}if(parts[1])end=((parts[1]=="-="?-1:1)*end)+start;e.custom(start,end,unit);}else +e.custom(start,val,"");}});return true;});},queue:function(type,fn){if(jQuery.isFunction(type)||(type&&type.constructor==Array)){fn=type;type="fx";}if(!type||(typeof type=="string"&&!fn))return queue(this[0],type);return this.each(function(){if(fn.constructor==Array)queue(this,type,fn);else{queue(this,type).push(fn);if(queue(this,type).length==1)fn.apply(this);}});},stop:function(clearQueue,gotoEnd){var timers=jQuery.timers;if(clearQueue)this.queue([]);this.each(function(){for(var i=timers.length-1;i>=0;i--)if(timers[i].elem==this){if(gotoEnd)timers[i](true);timers.splice(i,1);}});if(!gotoEnd)this.dequeue();return this;}});var queue=function(elem,type,array){if(!elem)return undefined;type=type||"fx";var q=jQuery.data(elem,type+"queue");if(!q||array)q=jQuery.data(elem,type+"queue",array?jQuery.makeArray(array):[]);return q;};jQuery.fn.dequeue=function(type){type=type||"fx";return this.each(function(){var q=queue(this,type);q.shift();if(q.length)q[0].apply(this);});};jQuery.extend({speed:function(speed,easing,fn){var opt=speed&&speed.constructor==Object?speed:{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&easing.constructor!=Function&&easing};opt.duration=(opt.duration&&opt.duration.constructor==Number?opt.duration:{slow:600,fast:200}[opt.duration])||400;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false)jQuery(this).dequeue();if(jQuery.isFunction(opt.old))opt.old.apply(this);};return opt;},easing:{linear:function(p,n,firstNum,diff){return firstNum+diff*p;},swing:function(p,n,firstNum,diff){return((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum;}},timers:[],timerId:null,fx:function(elem,options,prop){this.options=options;this.elem=elem;this.prop=prop;if(!options.orig)options.orig={};}});jQuery.fx.prototype={update:function(){if(this.options.step)this.options.step.apply(this.elem,[this.now,this]);(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);if(this.prop=="height"||this.prop=="width")this.elem.style.display="block";},cur:function(force){if(this.elem[this.prop]!=null&&this.elem.style[this.prop]==null)return this.elem[this.prop];var r=parseFloat(jQuery.css(this.elem,this.prop,force));return r&&r>-10000?r:parseFloat(jQuery.curCSS(this.elem,this.prop))||0;},custom:function(from,to,unit){this.startTime=(new Date()).getTime();this.start=from;this.end=to;this.unit=unit||this.unit||"px";this.now=this.start;this.pos=this.state=0;this.update();var self=this;function t(gotoEnd){return self.step(gotoEnd);}t.elem=this.elem;jQuery.timers.push(t);if(jQuery.timerId==null){jQuery.timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;ithis.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var done=true;for(var i in this.options.curAnim)if(this.options.curAnim[i]!==true)done=false;if(done){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(jQuery.css(this.elem,"display")=="none")this.elem.style.display="block";}if(this.options.hide)this.elem.style.display="none";if(this.options.hide||this.options.show)for(var p in this.options.curAnim)jQuery.attr(this.elem.style,p,this.options.orig[p]);}if(done&&jQuery.isFunction(this.options.complete))this.options.complete.apply(this.elem);return false;}else{var n=t-this.startTime;this.state=n/this.options.duration;this.pos=jQuery.easing[this.options.easing||(jQuery.easing.swing?"swing":"linear")](this.state,n,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update();}return true;}};jQuery.fx.step={scrollLeft:function(fx){fx.elem.scrollLeft=fx.now;},scrollTop:function(fx){fx.elem.scrollTop=fx.now;},opacity:function(fx){jQuery.attr(fx.elem.style,"opacity",fx.now);},_default:function(fx){fx.elem.style[fx.prop]=fx.now+fx.unit;}};jQuery.fn.offset=function(){var left=0,top=0,elem=this[0],results;if(elem)with(jQuery.browser){var parent=elem.parentNode,offsetChild=elem,offsetParent=elem.offsetParent,doc=elem.ownerDocument,safari2=safari&&parseInt(version)<522&&!/adobeair/i.test(userAgent),fixed=jQuery.css(elem,"position")=="fixed";if(elem.getBoundingClientRect){var box=elem.getBoundingClientRect();add(box.left+Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),box.top+Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));add(-doc.documentElement.clientLeft,-doc.documentElement.clientTop);}else{add(elem.offsetLeft,elem.offsetTop);while(offsetParent){add(offsetParent.offsetLeft,offsetParent.offsetTop);if(mozilla&&!/^t(able|d|h)$/i.test(offsetParent.tagName)||safari&&!safari2)border(offsetParent);if(!fixed&&jQuery.css(offsetParent,"position")=="fixed")fixed=true;offsetChild=/^body$/i.test(offsetParent.tagName)?offsetChild:offsetParent;offsetParent=offsetParent.offsetParent;}while(parent&&parent.tagName&&!/^body|html$/i.test(parent.tagName)){if(!/^inline|table.*$/i.test(jQuery.css(parent,"display")))add(-parent.scrollLeft,-parent.scrollTop);if(mozilla&&jQuery.css(parent,"overflow")!="visible")border(parent);parent=parent.parentNode;}if((safari2&&(fixed||jQuery.css(offsetChild,"position")=="absolute"))||(mozilla&&jQuery.css(offsetChild,"position")!="absolute"))add(-doc.body.offsetLeft,-doc.body.offsetTop);if(fixed)add(Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));}results={top:top,left:left};}function border(elem){add(jQuery.curCSS(elem,"borderLeftWidth",true),jQuery.curCSS(elem,"borderTopWidth",true));}function add(l,t){left+=parseInt(l)||0;top+=parseInt(t)||0;}return results;};})(); \ No newline at end of file diff --git a/non-rack-legacy/public/javascripts/json2.js b/non-rack-legacy/public/javascripts/json2.js new file mode 100644 index 0000000..d4f4541 --- /dev/null +++ b/non-rack-legacy/public/javascripts/json2.js @@ -0,0 +1 @@ +if(!this.JSON){this.JSON={}}(function(){function f(n){return n<10?'0'+n:n}if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+'-'+f(this.getUTCMonth()+1)+'-'+f(this.getUTCDate())+'T'+f(this.getUTCHours())+':'+f(this.getUTCMinutes())+':'+f(this.getUTCSeconds())+'Z':null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key)}if(typeof rep==='function'){value=rep.call(holder,key,value)}switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null'}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object Array]'){length=value.length;for(i=0;i)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, +Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& +(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, +a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== +"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, +function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
          a"; +var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, +parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= +false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= +s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, +applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; +else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, +a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== +w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, +cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= +c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); +a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, +function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); +k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), +C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B=0){a.type= +e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& +f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; +if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", +e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, +"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, +d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, +e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); +t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| +g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, +CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, +g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, +text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, +setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= +h[3];l=0;for(m=h.length;l=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== +"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, +h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& +q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; +if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="

          ";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); +(function(){var g=s.createElement("div");g.innerHTML="
          ";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: +function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var j=d;j0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= +{},i;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== +"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", +d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? +a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== +1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"},F={option:[1,""],legend:[1,"
          ","
          "],thead:[1,"","
          "],tr:[2,"","
          "],td:[3,"","
          "],col:[2,"","
          "],area:[1,"",""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
          ","
          "];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= +c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, +wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, +prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, +this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); +return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, +""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); +return this}else{e=0;for(var j=d.length;e0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", +""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===""&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= +c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? +c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= +function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= +Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, +"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= +a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= +a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=//gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!== +"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("
          ").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this}, +serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), +function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href, +global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&& +e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)? +"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache=== +false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B= +false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since", +c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E|| +d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x); +g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status=== +1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b=== +"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional; +if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration=== +"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]|| +c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start; +this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now= +this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem, +e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b
          "; +a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b); +c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a, +d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top- +f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset": +"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in +e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window); +/*json2.js*/ +if(!this.JSON){this.JSON={}}(function(){function f(n){return n<10?'0'+n:n}if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+'-'+f(this.getUTCMonth()+1)+'-'+f(this.getUTCDate())+'T'+f(this.getUTCHours())+':'+f(this.getUTCMinutes())+':'+f(this.getUTCSeconds())+'Z':null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key)}if(typeof rep==='function'){value=rep.call(holder,key,value)}switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null'}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object Array]'){length=value.length;for(i=0;i
          ');var typer=$('');var promptBox;var prompt;var promptLabel=config&&config.promptLabel?config.promptLabel:"> ";var column=0;var promptText='';var restoreText='';var history=[];var ringn=0;var cancelKeyPress=0;var extern={};(function(){container.append(inner);inner.append(typer);typer.css({position:'absolute',top:0,left:'-999px'});if(config.welcomeMessage)message(config.welcomeMessage,'jquery-console-welcome');newPromptBox();if(config.autofocus){inner.addClass('jquery-console-focus');typer.focus();setTimeout(function(){inner.addClass('jquery-console-focus');typer.focus()},100)}})();extern.reset=function(){var welcome=true;inner.parent().fadeOut(function(){inner.find('div').each(function(){if(!welcome)$(this).remove();welcome=false});newPromptBox();inner.parent().fadeIn(function(){inner.addClass('jquery-console-focus');typer.focus()})})};function newPromptBox(){column=0;promptText='';promptBox=$('
          ');var label=$('');promptBox.append(label.text(promptLabel).show());prompt=$('');promptBox.append(prompt);inner.append(promptBox);updatePromptDisplay()};container.click(function(){inner.addClass('jquery-console-focus');inner.removeClass('jquery-console-nofocus');typer.focus();scrollToBottom();return false});typer.blur(function(){inner.removeClass('jquery-console-focus');inner.addClass('jquery-console-nofocus')});typer.keydown(function(e){cancelKeyPress=0;var keyCode=e.keyCode;if(isControlCharacter(keyCode)){cancelKeyPress=keyCode;if(!typer.consoleControl(keyCode)){return false}}});typer.keypress(function(e){var keyCode=e.keyCode||e.which;if(cancelKeyPress!=keyCode&&keyCode>=32){if(cancelKeyPress)return false;typer.consoleInsert(keyCode)}if($.browser.webkit)return false});function isControlCharacter(keyCode){return((keyCode>=keyCodes.left&&keyCode<=keyCodes.down)||keyCode==keyCodes.back||keyCode==keyCodes.del||keyCode==keyCodes.end||keyCode==keyCodes.start||keyCode==keyCodes.ret)};typer.consoleControl=function(keyCode){switch(keyCode){case keyCodes.left:{moveColumn(-1);updatePromptDisplay();return false;break}case keyCodes.right:{moveColumn(1);updatePromptDisplay();return false;break}case keyCodes.back:{if(moveColumn(-1)){deleteCharAtPos();updatePromptDisplay()}return false;break}case keyCodes.del:{if(deleteCharAtPos())updatePromptDisplay();return false;break}case keyCodes.end:{if(moveColumn(promptText.length-column))updatePromptDisplay();return false;break}case keyCodes.start:{if(moveColumn(-column))updatePromptDisplay();return false;break}case keyCodes.ret:{commandTrigger();return false}case keyCodes.up:{rotateHistory(-1);return false}case keyCodes.down:{rotateHistory(1);return false}default:}};function rotateHistory(n){if(history.length==0)return;ringn+=n;if(ringn<0)ringn=history.length;else if(ringn>history.length)ringn=0;var prevText=promptText;if(ringn==0){promptText=restoreText}else{promptText=history[ringn-1]}if(config.historyPreserveColumn){if(promptText.length
          ');if(className)mesg.addClass(className);mesg.filledText(msg).hide();inner.append(mesg);mesg.show()};typer.consoleInsert=function(keyCode){var char=String.fromCharCode(keyCode);var before=promptText.substring(0,column);var after=promptText.substring(column);promptText=before+char+after;moveColumn(1);restoreText=promptText;updatePromptDisplay()};function moveColumn(n){if(column+n>=0&&column+n<=promptText.length){column+=n;return true}else return false};function updatePromptDisplay(){var line=promptText;var html='';if(column>0&&line==''){html=cursor}else if(column==promptText.length){html=htmlEncode(line)+cursor}else{var before=line.substring(0,column);var current=line.substring(column,column+1);if(current){current=''+htmlEncode(current)+''}var after=line.substring(column+1);html=htmlEncode(before)+current+htmlEncode(after)}prompt.html(html);scrollToBottom()};function htmlEncode(text){return(text.replace(/&/g,'&').replace(/&]{10})/g,'$1­'+wbr))};return extern};$.fn.filledText=function(txt){$(this).text(txt);$(this).html($(this).html().replace(/\n/g,'
          '));return this}})(jQuery); diff --git a/non-rack-legacy/public/javascripts/mouseapp_2.js b/non-rack-legacy/public/javascripts/mouseapp_2.js new file mode 100755 index 0000000..de5c777 --- /dev/null +++ b/non-rack-legacy/public/javascripts/mouseapp_2.js @@ -0,0 +1,913 @@ +// +// Copyright (c) 2008 why the lucky stiff +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +var MouseApp = { + Version: '0.12', + CharCodes: { + 0: ' ', 1: ' ', 9: ' ', + 32: ' ', 34: '"', 38: '&', + 60: '<', 62: '>', 127: '◊', + 0x20AC: '€' + }, + KeyCodes: { + Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 33, PageDown: 34, + End: 35, Home: 36, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 45, + Delete: 46, F1: 112, F2: 113, F3: 114, F4: 115, F5: 116, F6: 117, + F7: 118, F8: 119, F10: 121 + }, + CodeKeys: {}, + Modes: { 1: 'b', 2: 'u', 4: 'i', 8: 'strike' }, + ModeIds: { r: 1, u: 2, i: 4, s: 8 }, + Colors: ['black', 'blue', 'green', + 'cyan', 'red', 'purple', 'brown', + 'gray', 'dark_gray', 'lt_blue', + 'lt_green', 'lt_cyan', 'lt_red', + 'lt_purple', 'yellow', 'white'] +} +//some of these are patently false, because I need to get on a real keyboard-- not a macbook. +if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1){ + MouseApp.KeyCodes = { + Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, + End: 63275, Home: 63273, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 632325, + Delete: 46, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, + F7: 63242, F8: 63243, F10: 63244 + } + +} + +//even though I am tempted to combine chrome and opera into the same if statment, I will refrain for now +// i dont have proper access to a proper keyboard and there might be a single difference between the two +if (navigator.userAgent.indexOf("Opera") > -1){ + MouseApp.KeyCodes = { + Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, + End: 63275, Home: 63273, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 632325, + Delete: 46, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, + F7: 63242, F8: 63243, F10: 63244 + } + +} + +// i am going to comment this out, since this seems un needed. if it past december 15 2009 and this +// is still commented it, please del me +//if ( navigator.appVersion.indexOf('AppleWebKit') > 0 ) { +// MouseApp.KeyCodes = { +// Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, +// End: 63275, Home: 63273, Left: 63234, Up: 63232, Right: 63235, Down: 63233, Insert: 632325, +// Delete: 63272, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, +// F7: 63242, F8: 63243, F10: 63244 +// };// +//} +for ( var k in MouseApp.KeyCodes ) { + MouseApp.CodeKeys[MouseApp.KeyCodes[k]] = k; +} + +MouseApp.isPrintable = function(ch) { + return (ch >= 32); +}; + +MouseApp.Base = function(){}; +MouseApp.Base.prototype = { + setOptions: function(options) { + this.options = { + columns: 72, rows: 24, indent: 2, + title: 'MouseApp', + blinkRate: 500, + ps: '>', + greeting:'%+r Terminal ready. %-r' + } + $.extend(this.options, options || {}); + } +} + +MouseApp.Manager = new Object(); +$.extend(MouseApp.Manager, { + observeTerm: function(term) { + this.activeTerm = term; + if ( this.observingKeyboard ) return; + var mgr = this; + if ( term.input ) { + term.input.keypress(function(e) { mgr.onKeyPress(e) }); + if (!window.opera) term.input.keydown(function(e) { mgr.onKeyDown(e) }); + else window.setInterval(function(){term.input.focus()},1); + } else { + if (!window.opera) $(document).keydown(function(e) { mgr.onKeyDown(e) }); + $(document).keypress(function(e) { mgr.onKeyPress(e) }); + } + this.observingKeyboard = true; + }, + + onKeyDown: function(e) { + e = (e) ? e : ((event) ? event : null); + if ( e && MouseApp.CodeKeys[e.keyCode] ) { + if ( window.event ) { + this.sendKeyPress(e); + } + this.blockEvent(e); + return false; + } + return true; + }, + + onKeyPress: function(e) { + if ( !window.opera && window.event && e.keyCode != 13 && e.keyCode != 8 ) { + e.charCode = e.keyCode; e.keyCode = null; + } + if ( e.keyCode == 191 ) { /* FF 1.0.x sends this upsy quizy -- ignore */ + return; + } + return this.sendKeyPress(e); + }, + + sendKeyPress: function(e) { + var term = MouseApp.Manager.activeTerm; + term.cursorOff(); + b = term.onKeyPress(e); + term.cursorOn(); + return b; + }, + + blockEvent: function (e) { + e.cancelBubble=true; + if (window.event && !window.opera) e.keyCode=0; + if (e.stopPropagation) e.stopPropagation(); + if (e.preventDefault) e.preventDefault(); + } +}); + +/* Basic text window functionality */ +MouseApp.Window = function(element, options) { + this.element = $(element); + this.setOptions(options); + this.initWindow(); +}; + +$.extend(MouseApp.Window.prototype, (new MouseApp.Base()), { + initWindow: function() { + var html = ''; + for ( var i = 0; i < this.options.rows; i++ ) { + html += "
           
          \n"; + } + this.element.html(html); + this.typingOn(); + if (this.options.input) { + this.input = $(this.options.input); + this.input.focus(); + } + MouseApp.Manager.observeTerm(this); + this.clear(); + this.cursorOn(); + this.painting = true; + this.element.css({visibility: 'visible'}); + }, + + text: function() { + var str = ""; + for (var i = 0; i < this.screen.length; i++ ) { + for (var j = 0; j < this.options.columns; j++ ) { + var ch = this.screen[i][j]; + if ( ch[0] != 0 ) { + str += String.fromCharCode(ch[0]); + } + } + } + return str; + }, + + clear: function() { + this.rpos = 0; + this.cpos = 0; + this.screen = []; + this.element.html(''); + this.screen[0] = this.fillRow(this.options.columns, 0); + this.paint(0); + }, + + typingOn: function() { this.typing = true; }, + typingOff: function() { this.typing = false; }, + + cursorOn: function() { + if ( this.blinker ) { + clearInterval( this.blinker ); + } + this.underblink = this.screen[this.rpos][this.cpos][1]; + MouseApp.Manager.activeTerm.blink(); + this.blinker = setInterval(function(){MouseApp.Manager.activeTerm.blink();}, this.options.blinkRate); + this.cursor = true; + }, + + cursorOff: function() { + if ( this.blinker ) { + clearInterval( this.blinker ); + } + if ( this.cursor ) { + this.screen[this.rpos][this.cpos][1] = this.underblink; + this.paint(this.rpos); + this.cursor = false; + } + }, + + blink: function() { + if ( this == MouseApp.Manager.activeTerm ) { + var mode = this.screen[this.rpos][this.cpos][1]; + this.screen[this.rpos][this.cpos][1] = ( mode & 1 ) ? mode & 4094 : mode | 1; + this.paint(this.rpos); + } + }, + + fillRow: function(len, ch, mode) { + ary = [] + for (var i = 0; i < len; i++) { + ary[i] = [ch, mode]; + } + return ary; + }, + + paint: function(start, end) { + if (!this.painting) return; + + if (!end) end = start; + for (var row = start; row <= end && row < this.screen.length; row++) { + var html = ''; + var mode = 0; + var fcolor = 0; + var bcolor = 0; + var spans = 0; + for (var i = 0; i < this.options.columns; i++ ) { + var c = this.screen[row][i][0]; + var m = this.screen[row][i][1] & 15; // 4 mode bits + var f = (this.screen[row][i][1] & (15 << 4)) >> 4; // 4 foreground bits + var b = (this.screen[row][i][1] & (15 << 8)) >> 8; // 4 background bits + if ( m != mode ) { + if ( MouseApp.Modes[mode] ) html += ""; + if ( MouseApp.Modes[m] ) html += "<" + MouseApp.Modes[m] + ">"; + mode = m; + } + if ( ( f != fcolor && f == 0 ) || ( b != bcolor && b == 0 ) ) { + for ( var s = 0; s < spans; s++ ) html += ""; + fcolor = 0; bcolor = 0; + } + if ( f != fcolor ) { + if ( MouseApp.Colors[f] ) { + html += ""; + spans++; + } + fcolor = f; + } + if ( b != bcolor ) { + if ( MouseApp.Colors[b] ) html += ""; + spans++; bcolor = b; + } + html += MouseApp.CharCodes[c] ? MouseApp.CharCodes[c] : String.fromCharCode(c); + } + if ( MouseApp.Modes[mode] ) html += ""; + for ( var s = 0; s < spans; s++ ) html += ""; + var new_id = this.element.attr('id') + '_' + row; + if (!$('#' + new_id).get(0)) { + this.element.append("
           
          "); + this.scrollAllTheWayDown(); + } + $('#' + new_id).html(html); + } + }, + + onAfterKey: function() { + this.scrollAllTheWayDown(); + }, + + highlightLine: function(i) { + if (i >= 0 && i < this.screen.length) + { + $("#" + this.element.attr('id') + "_" + i); + } + }, + + scrollToLine: function(i) { + var p = this.element[0].parentNode; + if ( p.scrollHeight > p.clientHeight ) { + p.scrollTop = (p.scrollHeight - p.clientHeight); + } + }, + + scrollAllTheWayDown: function() { + var p = this.element[0].parentNode; + if ( p.scrollHeight > p.clientHeight ) { + p.scrollTop = (p.scrollHeight - p.clientHeight); + } + }, + + putc: function(ch, mode) { + if ( ch == 13 ) { + return; + } else if ( ch == 10 ) { + this.screen[this.rpos][this.cpos] = [ch, mode]; + this.advanceLine(); + } else { + this.screen[this.rpos][this.cpos] = [ch, mode]; + this.paint(this.rpos); + this.advance(); + } + }, + + zpad: function(n) { + if (n < 10) n = "0" + n; + return n; + }, + + puts: function(str, mode) { + if ( !str ) return; + var p = this.painting; + var r = this.rpos; + this.painting = false; + for ( var i = 0; i < str.length; i++ ) { + this.insertc(str.charCodeAt(i), mode); + } + this.painting = p; + this.paint(r, this.rpos); + }, + + advance: function() { + this.cpos++; + if ( this.cpos >= this.options.columns ) { + this.advanceLine(); + } + }, + + advanceLine: function() { + this.cpos = 0; + this.rpos++; + this.ensureRow(this.rpos); + this.paint(this.rpos, this.screen.length - 1); + }, + + fwdc: function() { + var r = this.rpos; + var c = this.cpos; + if ( c < this.options.columns - 1 ) { + c++; + } else if ( r < this.screen.length - 1 ) { + r++; + c = 0; + } + var ch = (c == 0 ? this.screen[r-1][this.options.columns-1] : this.screen[r][c-1]); + if ( MouseApp.isPrintable(ch[0]) ) { + this.rpos = r; + this.cpos = c; + } + }, + + fwdLine: function() { + if ( this.rpos >= this.screen.length - 1 ) return; + this.rpos++; + while ( this.cpos > 0 && !MouseApp.isPrintable(this.screen[this.rpos][this.cpos - 1][0]) ) { + this.cpos--; + } + }, + + backc: function() { + var r = this.rpos; + var c = this.cpos; + if ( c > 0 ) { + c--; + } else if ( r > 0 ) { + c = this.options.columns - 1; + r--; + } + if ( MouseApp.isPrintable(this.screen[r][c][0]) ) { + this.rpos = r; + this.cpos = c; + return true; + } + return false; + }, + + getTypingStart: function() { + var c = this.cpos; + if ( !MouseApp.isPrintable(this.screen[this.rpos][c][0]) ) { + c--; + } + var pos = null; + for ( var r = this.rpos; r >= 0; r-- ) { + while ( c >= 0 ) { + if ( !MouseApp.isPrintable(this.screen[r][c][0]) ) { + return pos; + } + pos = [r, c]; + c--; + } + c = this.options.columns - 1; + } + }, + + getTypingEnd: function(mod) { + var c = this.cpos; + if ( !MouseApp.isPrintable(this.screen[this.rpos][c][0]) ) { + c--; + } + var pos = null; + for ( var r = this.rpos; r < this.screen.length; r++ ) { + while ( c < this.options.columns ) { + if ( !this.screen[r] || !this.screen[r][c] || !MouseApp.isPrintable(this.screen[r][c][0]) ) { + if (!mod) return pos; + mod--; + } + pos = [r, c]; + c++; + } + c = 0; + } + }, + + getTypingAt: function(start, end) { + var r = start[0]; + var c = start[1]; + var str = ''; + while ( r < end[0] || c <= end[1] ) { + if ( c < this.options.columns ) { + str += String.fromCharCode(this.screen[r][c][0]); + c++; + } else { + c = 0; + r++; + } + } + return str; + }, + + ensureRow: function(r) { + if (!this.screen[r]) { + this.screen[r] = this.fillRow(this.options.columns, 0); + } + }, + + insertc: function(ch, mode) { + var r = this.rpos; var c = this.cpos; + var end = this.getTypingEnd(+1); + if (end) { + var thisc = null; + var lastc = this.screen[this.rpos][this.cpos]; + while ( r < end[0] || c <= end[1] ) { + if ( c < this.options.columns ) { + thisc = this.screen[r][c]; + this.screen[r][c] = lastc; + lastc = thisc; + c++; + } else { + c = 0; + r++; + this.ensureRow(r); + } + } + this.paint(this.rpos, end[0]); + } + this.putc(ch, mode); + }, + + delc: function() { + /* end of line */ + if ( MouseApp.isPrintable(this.screen[this.rpos][this.cpos][0]) ) { + var end = this.getTypingEnd(); + var thisc = null; + var lastc = [0, 0]; + while ( this.rpos < end[0] || this.cpos <= end[1] ) { + if ( end[1] >= 0 ) { + thisc = this.screen[end[0]][end[1]]; + this.screen[end[0]][end[1]] = lastc; + lastc = thisc; + end[1]--; + } else { + end[1] = this.options.columns - 1; + this.paint(end[0]); + end[0]--; + } + } + } + }, + + backspace: function() { + /* end of line */ + if ( !MouseApp.isPrintable(this.screen[this.rpos][this.cpos][0]) ) { + this.backc(); + this.screen[this.rpos][this.cpos] = [0, 0]; + } else { + if ( this.backc() ) this.delc(); + } + }, + + backLine: function() { + if ( this.rpos < 1 ) return; + this.rpos--; + while ( this.cpos > 0 && !MouseApp.isPrintable(this.screen[this.rpos][this.cpos - 1][0]) ) { + this.cpos--; + } + }, + + onKeyPress: function(e) { + var ch = e.keyCode; + var key_name = MouseApp.CodeKeys[ch]; + if (window.opera && !e.altKey && e.keyCode != 13 && e.keyCode != 8) key_name = null; + ch = (e.which || e.charCode || e.keyCode); + if (e.which) ch = e.which; + if (!key_name) { key_name = String.fromCharCode(ch); } + if (e.ctrlKey) { key_name = 'Ctrl' + key_name; } + + // alert([e.keyCode, e.which, key_name, this['onKey' + key_name]]); + if (this.typing && this.onAnyKey) this.onAnyKey(key_name); + if (key_name && this['onKey' + key_name]) { + if (this.typing) this['onKey' + key_name](); + MouseApp.Manager.blockEvent(e); + if (this.typing && this.onAfterKey) this.onAfterKey(key_name, true); + return false; + } + if (!e.ctrlKey) { + if (MouseApp.isPrintable(ch)) { + if (this.typing) this.insertc(ch, 0); + MouseApp.Manager.blockEvent(e); + if (this.typing && this.onAfterKey) this.onAfterKey(key_name, true); + return false; + } + } + if (this.typing && this.onAfterKey) this.onAfterKey(key_name, false); + return true; + }, + onKeyHome: function() { + var s = this.getTypingStart(); + this.rpos = s[0]; this.cpos = s[1]; + }, + onKeyEnd: function() { + var e = this.getTypingEnd(+1); + this.rpos = e[0]; this.cpos = e[1]; + }, + onKeyInsert: function() { }, + onKeyDelete: function() { this.delc(); }, + onKeyUp: function() { this.backLine(); }, + onKeyLeft: function() { this.backc(); }, + onKeyRight: function() { this.fwdc(); }, + onKeyDown: function() { this.fwdLine(); }, + onKeyBackspace: function() { this.backspace(); }, + onKeyEnter: function() { this.insertc(10, 0); }, + onKeyTab: function() { + this.insertc(32, 0); + while (this.cpos % this.options.indent != 0) this.insertc(32, 0); + } +}); + +/* Terminal running moush */ +MouseApp.Terminal = function(element, options) { + this.element = $(element); + this.setOptions(options); + this.initWindow(); + this.setup(); +}; + +$.extend(MouseApp.Terminal.prototype, MouseApp.Window.prototype, { + setup: function() { + this.history = []; + this.backupNum = this.historyNum = this.commandNum = 0; + if (this.onStart) { + this.onStart(); + } else { + this.write(this.options.greeting + "\n", true); + this.prompt(); + } + }, + + prompt: function(ps, pt) { + if (!ps) { + ps = this.options.ps; pt = true; + } + this.write(ps, pt); + this.putc(1, 0); + this.typingOn(); + }, + + getCommand: function() { + var s = this.getTypingStart(); + var e = this.getTypingEnd(); + if (!s || !e) return; + return this.getTypingAt(s, e); + }, + + clearCommand: function() { + var s = this.getTypingStart(); + var e = this.getTypingEnd(); + if (!s || !e) return; + var r = s[0]; + var c = s[1]; + this.rpos = r; this.cpos = c; + while ( r < e[0] || c <= e[1] ) { + if ( c < this.options.columns ) { + this.screen[r][c] = [0, 0]; + c++; + } else { + c = 0; + this.paint(r); + r++; + } + } + this.paint(r); + }, + + write: function(str, pcodes) { + var p = this.painting; + var r = this.rpos; + this.painting = false; + var mode = 0; + var today = new Date(); + for ( var i = 0; i < str.length; i++ ) { + if ( str.substr(i,1) == "\n" ) { + this.advanceLine(); + continue; + } else if ( str.substr(i,1) == "\033" ) { + if ( str.substr(i+1,2) == "[m" ) { + mode = 0; + i += 2; + continue; + } + if ( str.substr(i+1,5) == "[0;0m" ) { + mode = 0; + i += 5; + continue; + } + var colors = str.substr(i+1,7).match(/^\[(\d);(\d+)m/); + if ( colors ) { + var colCode = parseInt( colors[2] ); + var color = colCode % 10; + if ( colors[1] == '1' ) { + color += 8; + } + if ( colCode / 10 == 4 ) { + color = color << 4; + } + mode = (mode & 15) + color << 4; + i += colors[0].length; + continue; + } + } else if ( str.substr(i,1) == '%' && pcodes ) { + var s2 = str.substr(i,2); + switch ( s2 ) { + case '%h': + this.puts(this.options.host, mode); + i++; + continue; + case '%l': + this.puts(this.options.name, mode); + i++; + continue; + case '%n': + this.advanceLine(); + i++; + continue; + case '%s': + this.puts("moush", mode); + i++; + continue; + case '%t': + this.puts(this.zpad(today.getHours()) + ":" + this.zpad(today.getMinutes()) + ":" + + this.zpad(today.getSeconds()), mode); + i++; + continue; + case '%u': + this.puts(this.options.user, mode); + i++; + continue; + case '%v': + this.puts(MouseApp.Version, mode); + i++; + continue; + case '%!': + this.puts(this.historyNum.toString(), mode); + i++; + continue; + case '%#': + this.puts(this.commandNum.toString(), mode); + i++; + continue; + case '%+': + var kind = str.substr(i+2, 1); + if ( MouseApp.ModeIds[kind] ) { + mode = mode | MouseApp.ModeIds[kind]; + i += 2; + continue; + } + break; + case '%-': + var kind = str.substr(i+2, 1); + if ( MouseApp.ModeIds[kind] ) { + mode = mode & ( 4095 - MouseApp.ModeIds[kind] ); + i += 2; + continue; + } + break; + } + } + this.putc(str.charCodeAt(i), mode); + } + this.painting = p; + this.paint(r, this.rpos); + }, + + onKeyUp: function() { + if ( this.backupNum == 0 ) return; + if ( this.backupNum == this.historyNum ) { + this.history[this.historyNum] = this.getCommand(); + } + this.clearCommand(); + this.backupNum--; + this.puts(this.history[this.backupNum]); + }, + onKeyDown: function() { + if ( this.backupNum >= this.historyNum ) return; + this.clearCommand(); + this.backupNum++; + this.puts(this.history[this.backupNum]); + }, + onKeyEnter: function() { + var cmd = this.getCommand(); + if (cmd) { + this.history[this.historyNum] = cmd; + this.backupNum = ++this.historyNum; + } + this.commandNum++; + this.advanceLine(); + if (cmd) { + var str = this.onCommand(cmd); + if (str) { + if ( str.substr(str.length - 1, 1) != "\n" ) { + str += "\n"; + } + this.write(str); + } + } + this.prompt(); + }, + onCommand: function(line) { + // this.puts("Echoing: " + line + "\n"); + if ( line == "clear" ) { + this.clear(); + } else { + return "\033[1;37m\033[0;44mYou typed:\033[m " + line; + } + } +}); + +/* Notepad sort of editor */ +MouseApp.Notepad = function(element, options) { + this.element = $(element); + this.setOptions(options); + this.initWindow(); + this.history = []; + this.lineno = 0; +}; + +$.extend(MouseApp.Notepad.prototype, MouseApp.Window.prototype, { + csave: function() { + if ( this.cpos_save ) { + this.cpos = this.cpos_save; + } else { + this.cpos_save = this.cpos; + } + }, + onKeyUp: function() { if ( this.rpos < 1 ) { return; } this.csave(); this.backLine(); }, + onKeyDown: function() { if ( this.rpos < this.screen.length - 1 ) { this.csave(); this.fwdLine(); } }, + onAfterKey: function(key, st) { + if ( st && !(key == 'Up' || key == 'Down') ) { + this.cpos_save = null; + } + }, + insertc: function(ch, mode) { + if (ch == 10) { + this.element.append("
           
          "); + this.screen.splice(this.rpos + 1, 0, this.fillRow(this.options.columns, 0)); + var c = this.cpos; var c2 = 0; + while (c < this.options.columns) + { + if (this.screen[this.rpos][c] == 0) break; + this.screen[this.rpos + 1][c2] = this.screen[this.rpos][c]; + this.screen[this.rpos][c] = [0, 0]; + c++; c2++; + } + this.paint(this.rpos); + if (MouseApp.isPrintable(this.screen[this.rpos][c])) + { + var r = this.rpos; var c = this.cpos; + this.rpos += 1; this.cpos = c2; + this.delc(); + this.rpos = r; this.cpos = c; + } + this.putc(ch, mode); + if (this.rpos == this.screen.length - 1) + this.scrollAllTheWayDown(); + } else { + var c = this.cpos + 1; + var lastc = this.screen[this.rpos][this.cpos]; + this.putc(ch, mode); + for ( var r = this.rpos; r < this.screen.length; r++ ) { + while (c < this.options.columns) + { + var tmpc = this.screen[r][c]; + if (lastc[0] == 0) + break; + this.screen[r][c] = lastc; + lastc = tmpc; + c++; + } + if (c < this.options.columns) { + break; + } + c = 0; + } + } + }, + + backc: function() { + var r = this.rpos; + var c = this.cpos - 1; + for ( var r = this.rpos; r >= 0; r-- ) { + while ( c >= 0 ) { + this.rpos = r; + this.cpos = c; + if ( this.screen[r][c][0] != 0 ) { + this.paint(r); + return true; + } + this.screen[r][c] = [0, 0]; + c--; + } + c = this.options.columns - 1; + } + return false; + }, + delc: function() { + var c = this.cpos + 1; + for ( var r = this.rpos; r < this.screen.length; r++ ) { + while ( c < this.options.columns ) { + if ( this.screen[r][c][0] != 0 ) { + break; + } + c++; + } + if ( c < this.options.columns ) break; + c = 0; + } + + if (r >= this.screen.length) return; + + var r2 = this.rpos; + var c2 = this.cpos; + for ( var r2 = this.rpos; r2 < this.screen.length; r2++ ) { + while (c2 < this.options.columns) + { + if (this.screen[r][c][0] == 0) + break; + this.screen[r2][c2] = this.screen[r][c]; + c2++; + c++; + if (c >= this.options.columns) { + r++; + if (r >= this.options.rows) break; + c = 0; + } + } + if (c2 < this.options.columns) { + while (c2 < this.options.columns) { + this.screen[r2][c2] = [0, 0]; + c2++; + } + break; + } + c2 = 0; + } + + if (r != r2 && r < this.screen.length) + { + this.screen.splice(r, 1); + $("#" + this.element.attr('id') + "_" + this.screen.length).remove(); + } + this.paint(this.rpos, this.screen.length); + }, + onKeyBackspace: function() { + if (this.backc()) this.delc(); + } + +}); diff --git a/non-rack-legacy/public/javascripts/mouseirb_2.js b/non-rack-legacy/public/javascripts/mouseirb_2.js new file mode 100755 index 0000000..0fa5f12 --- /dev/null +++ b/non-rack-legacy/public/javascripts/mouseirb_2.js @@ -0,0 +1,179 @@ +// +// Copyright (c) 2008 why the lucky stiff +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// + +/* Irb running moush */ +MouseApp.Irb = function(element, options) { + this.element = $(element); + this.setOptions(options); + this.showHelp = this.options.showHelp; + if ( this.options.showChapter ) { + this.showChapter = this.options.showChapter; + } + if ( this.options.init ) { + this.init = this.options.init; + } + this.initWindow(); + this.setup(); + this.helpPage = null; + this.irbInit = false; +}; + +$.extend(MouseApp.Irb.prototype, MouseApp.Terminal.prototype, { + cmdToQuery: function(cmd) { + return "cmd=" + escape(cmd.replace(/</g, '<').replace(/>/g, '>'). + replace(/&/g, '&').replace(/\r?\n/g, "\n")).replace(/\+/g, "%2B"); + }, + + fireOffCmd: function(cmd, func) { + var irb = this; + if (!this.irbInit) + { + $.ajax({url: this.options.irbUrl + "?" + this.cmdToQuery("!INIT!IRB!"), type: "GET", + complete: (function(r) { irb.irbInit = true; irb.fireOffCmd(cmd, func); })}); + } + else + { + $.ajax({url: this.options.irbUrl + "?" + this.cmdToQuery(cmd), type: "GET", + complete: func}); + } + }, + + reply: function(str) { + var raw = str.replace(/\033\[(\d);(\d+)m/g, ''); + this.checkAnswer(raw); + if (!str.match(/^(\.\.)+$/)) { + if ( str[str.length - 1] != "\n" ) { + str += "\n"; + } + js_payload = /\033\[1;JSm(.*)\033\[m/; + js_in = str.match(js_payload); + if (js_in) { + try { + js_in = eval(js_in[1]); + } catch (e) {} + str = str.replace(js_payload, ''); + } + var pr_re = new RegExp("(^|\\n)=>"); + if ( str.match( pr_re ) ) { + str = str.replace(new RegExp("(^|\\n)=>"), "$1\033[1;34m=>\033[m"); + } else { + str = str.replace(new RegExp("(^|\\n)= (.+?) ="), "$1\033[1;33m$2\033[m"); + } + this.write(str); + this.prompt(); + } else { + this.prompt("\033[1;32m" + ".." + "\033[m", true); + this.puts(str.replace(/\./g, ' '), 0); + } + }, + + setHelpPage: function(n, page) { + if (this.helpPage) + $(this.helpPage.ele).hide('fast'); + this.helpPage = {index: n, ele: page}; + match = this.scanHelpPageFor('load'); + if (match != -1) + { + this.fireOffCmd(match, (function(r) { + $(page).show('fast'); + })); + } + else + { + $(page).show('fast'); + } + }, + + scanHelpPageFor: function(eleClass) { + match = $("div." + eleClass, this.helpPage.ele); + if ( match[0] ) return match[0].innerHTML; + else return -1; + }, + + checkAnswer: function(str) { + if ( this.helpPage ) { + match = this.scanHelpPageFor('answer'); + if ( match != -1 ) { + if ( str.match( new RegExp('^\s*=> ' + match + '\s*$', 'm') ) ) { + this.showHelp(this.helpPage.index + 1); + } + } else { + match = this.scanHelpPageFor('stdout'); + if ( match != -1 ) { + if ( match == '' ) { + if ( str == '' || str == null ) this.showHelp(this.helpPage.index + 1); + } else if ( str.match( new RegExp('^\s*' + match + '$', 'm') ) ) { + this.showHelp(this.helpPage.index + 1); + } + } + } + } + }, + + onKeyCtrld: function() { + this.clearCommand(); + this.puts("reset"); + this.onKeyEnter(); + }, + + onKeyEnter: function() { + this.typingOff(); + var cmd = this.getCommand(); + if (cmd) { + this.history[this.historyNum] = cmd; + this.backupNum = ++this.historyNum; + } + this.commandNum++; + this.advanceLine(); + if (cmd) { + if ( cmd == "clear" ) { + this.clear(); + this.prompt(); + } else if ( cmd.match(/^(back)$/) ) { + if (this.helpPage && this.helpPage.index >= 1) { + this.showHelp(this.helpPage.index - 1); + } + this.prompt(); + } else if ( cmd.match(/^(next)$/) ) { + if (this.helpPage) { + this.showHelp(this.helpPage.index + 1); + } + this.prompt(); + } else if ( cmd.match(/^(help|wtf\?*)$/) ) { + this.showHelp(1); + this.prompt(); + } else if ( regs = cmd.match(/^(help|wtf\?*)\s+#?(\d+)\s*$/) ) { + this.showChapter(parseInt(regs[2])); + this.prompt(); + } else { + var term = this; + this.fireOffCmd(cmd, (function(r) { term.reply(r.responseText ? r.responseText : ''); })); + } + } else { + this.prompt(); + } + } +}); + diff --git a/non-rack-legacy/public/javascripts/raphael-min.js b/non-rack-legacy/public/javascripts/raphael-min.js new file mode 100644 index 0000000..4a99e3e --- /dev/null +++ b/non-rack-legacy/public/javascripts/raphael-min.js @@ -0,0 +1,113 @@ +/* + * Raphael 1.4.3 - JavaScript Vector Library + * + * Copyright (c) 2010 Dmitry Baranovskiy (http://raphaeljs.com) + * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. + */ +Raphael=function(){function m(){if(m.is(arguments[0],U)){for(var a=arguments[0],b=Aa[K](m,a.splice(0,3+m.is(a[0],O))),c=b.set(),d=0,f=a[o];d

          ";if(ha.childNodes[o]!=2)return m.type=null;ha=null}m.svg=!(m.vml=m.type=="VML");G[p]=m[p];m._id=0;m._oid=0;m.fn={};m.is=function(a,b){b=ca.call(b);return b=="object"&&a===Object(a)||b=="undefined"&&typeof a==b||b=="null"&&a==null||ca.call(ob.call(a).slice(8,-1))==b};m.setWindow=function(a){X=a;C=X.document};function ra(a){if(m.vml){var b=/^\s+|\s+$/g;ra=T(function(d){var f;d=(d+s)[I](b, +s);try{var e=new X.ActiveXObject("htmlfile");e.write("");e.close();f=e.body}catch(g){f=X.createPopup().document.body}e=f.createTextRange();try{f.style.color=d;var h=e.queryCommandValue("ForeColor");h=(h&255)<<16|h&65280|(h&16711680)>>>16;return"#"+("000000"+h[N](16)).slice(-6)}catch(i){return"none"}})}else{var c=C.createElement("i");c.title="Rapha\u00ebl Colour Picker";c.style.display="none";C.body[y](c);ra=T(function(d){c.style.color=d;return C.defaultView.getComputedStyle(c,s).getPropertyValue("color")})}return ra(a)} +function qb(){return"hsb("+[this.h,this.s,this.b]+")"}function rb(){return this.hex}m.hsb2rgb=T(function(a,b,c){if(m.is(a,"object")&&"h"in a&&"s"in a&&"b"in a){c=a.b;b=a.s;a=a.h}var d;if(c==0)return{r:0,g:0,b:0,hex:"#000"};if(a>1||b>1||c>1){a/=255;b/=255;c/=255}d=~~(a*6);a=a*6-d;var f=c*(1-b),e=c*(1-b*a),g=c*(1-b*(1-a));a=[c,e,f,f,g,c,c][d];b=[g,c,c,e,f,f,g][d];d=[f,f,g,c,c,e,f][d];a*=255;b*=255;d*=255;c={r:a,g:b,b:d,toString:rb};a=(~~a)[N](16);b=(~~b)[N](16);d=(~~d)[N](16);a=a[I](ga,"0");b=b[I](ga, +"0");d=d[I](ga,"0");c.hex="#"+a+b+d;return c},m);m.rgb2hsb=T(function(a,b,c){if(m.is(a,"object")&&"r"in a&&"g"in a&&"b"in a){c=a.b;b=a.g;a=a.r}if(m.is(a,ea)){var d=m.getRGB(a);a=d.r;b=d.g;c=d.b}if(a>1||b>1||c>1){a/=255;b/=255;c/=255}var f=Y(a,b,c),e=$(a,b,c);d=f;if(e==f)return{h:0,s:0,b:f};else{var g=f-e;e=g/f;a=a==f?(b-c)/g:b==f?2+(c-a)/g:4+(a-b)/g;a/=6;a<0&&a++;a>1&&a--}return{h:a,s:e,b:d,toString:qb}},m);var sb=/,?([achlmqrstvxz]),?/gi,sa=/\s*,\s*/,tb={hs:1,rg:1};m._path2string=function(){return this.join(",")[I](sb, +"$1")};function T(a,b,c){function d(){var f=Array[p].slice.call(arguments,0),e=f[Q]("\u25ba"),g=d.cache=d.cache||{},h=d.count=d.count||[];if(g[z](e))return c?c(g[e]):g[e];h[o]>=1000&&delete g[h.shift()];h[E](e);g[e]=a[K](b,f);return c?c(g[e]):g[e]}return d}m.getRGB=T(function(a){if(!a||(a+=s).indexOf("-")+1)return{r:-1,g:-1,b:-1,hex:"none",error:1};if(a=="none")return{r:-1,g:-1,b:-1,hex:"none"};!(tb[z](a.substring(0,2))||a.charAt()=="#")&&(a=ra(a));var b,c,d,f,e;if(a=a.match(pb)){if(a[2]){d=da(a[2].substring(5), +16);c=da(a[2].substring(3,5),16);b=da(a[2].substring(1,3),16)}if(a[3]){d=da((e=a[3].charAt(3))+e,16);c=da((e=a[3].charAt(2))+e,16);b=da((e=a[3].charAt(1))+e,16)}if(a[4]){a=a[4][H](sa);b=A(a[0]);c=A(a[1]);d=A(a[2]);f=A(a[3])}if(a[5]){a=a[5][H](sa);b=A(a[0])*2.55;c=A(a[1])*2.55;d=A(a[2])*2.55;f=A(a[3])}if(a[6]){a=a[6][H](sa);b=A(a[0]);c=A(a[1]);d=A(a[2]);return m.hsb2rgb(b,c,d)}if(a[7]){a=a[7][H](sa);b=A(a[0])*2.55;c=A(a[1])*2.55;d=A(a[2])*2.55;return m.hsb2rgb(b,c,d)}a={r:b,g:c,b:d};b=(~~b)[N](16); +c=(~~c)[N](16);d=(~~d)[N](16);b=b[I](ga,"0");c=c[I](ga,"0");d=d[I](ga,"0");a.hex="#"+b+c+d;isFinite(A(f))&&(a.o=f);return a}return{r:-1,g:-1,b:-1,hex:"none",error:1}},m);m.getColor=function(a){a=this.getColor.start=this.getColor.start||{h:0,s:1,b:a||0.75};var b=this.hsb2rgb(a.h,a.s,a.b);a.h+=0.075;if(a.h>1){a.h=0;a.s-=0.2;a.s<=0&&(this.getColor.start={h:0,s:1,b:a.b})}return b.hex};m.getColor.reset=function(){delete this.start};var ub=/([achlmqstvz])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig, +vb=/(-?\d*\.?\d*(?:e[-+]?\d+)?)\s*,?\s*/ig;m.parsePathString=T(function(a){if(!a)return null;var b={a:7,c:6,h:1,l:2,m:2,q:4,s:4,t:2,v:1,z:0},c=[];if(m.is(a,U)&&m.is(a[0],U))c=ta(a);c[o]||(a+s)[I](ub,function(d,f,e){var g=[];d=ca.call(f);e[I](vb,function(h,i){i&&g[E](+i)});if(d=="m"&&g[o]>2){c[E]([f][M](g.splice(0,2)));d="l";f=f=="m"?"l":"L"}for(;g[o]>=b[d];){c[E]([f][M](g.splice(0,b[d])));if(!b[d])break}});c[N]=m._path2string;return c});m.findDotsAtSegment=function(a,b,c,d,f,e,g,h,i){var j=1-i,l= +D(j,3)*a+D(j,2)*3*i*c+j*3*i*i*f+D(i,3)*g;j=D(j,3)*b+D(j,2)*3*i*d+j*3*i*i*e+D(i,3)*h;var n=a+2*i*(c-a)+i*i*(f-2*c+a),r=b+2*i*(d-b)+i*i*(e-2*d+b),q=c+2*i*(f-c)+i*i*(g-2*f+c),k=d+2*i*(e-d)+i*i*(h-2*e+d);a=(1-i)*a+i*c;b=(1-i)*b+i*d;f=(1-i)*f+i*g;e=(1-i)*e+i*h;h=90-w.atan((n-q)/(r-k))*180/w.PI;(n>q||r1){B=w.sqrt(B);c=B*c;d=B*d}B=c*c;var L=d*d;B=(e==g?-1:1)*w.sqrt(w.abs((B*L-B*x*x-L*k*k)/(B*x*x+L*k*k)));e=B*c*x/d+(a+h)/2;var B= +B*-d*k/c+(b+i)/2,x=w.asin(((b-B)/d).toFixed(7));k=w.asin(((i-B)/d).toFixed(7));x=ak)x-=l*2;if(!g&&k>x)k-=l*2}l=k-x;if(w.abs(l)>n){q=k;l=h;L=i;k=x+n*(g&&k>x?1:-1);h=e+c*w.cos(k);i=B+d*w.sin(k);q=Qa(h,i,c,d,f,0,g,l,L,[k,q,e,B])}l=k-x;f=w.cos(x);e=w.sin(x);g=w.cos(k);k=w.sin(k);l=w.tan(l/4);c=4/3*c*l;l=4/3*d*l;d=[a,b];a=[a+c*e,b-l*f];b=[h+c*k,i-l*g];h=[h,i];a[0]=2*d[0]-a[0];a[1]=2*d[1]-a[1];if(j)return[a,b,h][M](q);else{q=[a,b,h][M](q)[Q]()[H](","); +j=[];h=0;for(i=q[o];h1000000000000&&(n=0.5);w.abs(i)>1000000000000&&(i=0.5);if(n>0&&n<1){n=la(a,b,c,d,f,e,g,h,n);q[E](n.x);r[E](n.y)}if(i> +0&&i<1){n=la(a,b,c,d,f,e,g,h,i);q[E](n.x);r[E](n.y)}i=e-2*d+b-(h-2*e+d);j=2*(d-b)-2*(e-d);l=b-d;n=(-j+w.sqrt(j*j-4*i*l))/2/i;i=(-j-w.sqrt(j*j-4*i*l))/2/i;w.abs(n)>1000000000000&&(n=0.5);w.abs(i)>1000000000000&&(i=0.5);if(n>0&&n<1){n=la(a,b,c,d,f,e,g,h,n);q[E](n.x);r[E](n.y)}if(i>0&&i<1){n=la(a,b,c,d,f,e,g,h,i);q[E](n.x);r[E](n.y)}return{min:{x:$[K](0,q),y:$[K](0,r)},max:{x:Y[K](0,q),y:Y[K](0,r)}}}),ua=T(function(a,b){var c=ka(a),d=b&&ka(b);a={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null};b={x:0,y:0, +bx:0,by:0,X:0,Y:0,qx:null,qy:null};function f(q,k){var t;if(!q)return["C",k.x,k.y,k.x,k.y,k.x,k.y];!(q[0]in{T:1,Q:1})&&(k.qx=k.qy=null);switch(q[0]){case "M":k.X=q[1];k.Y=q[2];break;case "A":q=["C"][M](Qa[K](0,[k.x,k.y][M](q.slice(1))));break;case "S":t=k.x+(k.x-(k.bx||k.x));k=k.y+(k.y-(k.by||k.y));q=["C",t,k][M](q.slice(1));break;case "T":k.qx=k.x+(k.x-(k.qx||k.x));k.qy=k.y+(k.y-(k.qy||k.y));q=["C"][M](Pa(k.x,k.y,k.qx,k.qy,q[1],q[2]));break;case "Q":k.qx=q[1];k.qy=q[2];q=["C"][M](Pa(k.x,k.y,q[1], +q[2],q[3],q[4]));break;case "L":q=["C"][M](wa(k.x,k.y,q[1],q[2]));break;case "H":q=["C"][M](wa(k.x,k.y,q[1],k.y));break;case "V":q=["C"][M](wa(k.x,k.y,k.x,q[1]));break;case "Z":q=["C"][M](wa(k.x,k.y,k.X,k.Y));break}return q}function e(q,k){if(q[k][o]>7){q[k].shift();for(var t=q[k];t[o];)q.splice(k++,0,["C"][M](t.splice(0,6)));q.splice(k,1);i=Y(c[o],d&&d[o]||0)}}function g(q,k,t,L,B){if(q&&k&&q[B][0]=="M"&&k[B][0]!="M"){k.splice(B,0,["M",L.x,L.y]);t.bx=0;t.by=0;t.x=q[B][1];t.y=q[B][2];i=Y(c[o],d&& +d[o]||0)}}for(var h=0,i=Y(c[o],d&&d[o]||0);h0.5)*2-1;D(f-0.5,2)+D(e-0.5,2)>0.25&&(e=w.sqrt(0.25-D(f-0.5,2))*l+0.5)&&e!=0.5&&(e=e.toFixed(5)-1.0E-5*l)}return s});b=b[H](/\s*\-\s*/);if(d=="linear"){var h=b.shift();h=-A(h);if(isNaN(h))return null;h=[0,0,w.cos(h*w.PI/180),w.sin(h*w.PI/180)];var i=1/(Y(w.abs(h[2]),w.abs(h[3]))||1);h[2]*=i;h[3]*=i;if(h[2]<0){h[0]=-h[2];h[2]=0}if(h[3]<0){h[1]=-h[3];h[3]=0}}b=Ra(b);if(!b)return null; +i=a.getAttribute(aa);(i=i.match(/^url\(#(.*)\)$/))&&c.defs.removeChild(C.getElementById(i[1]));i=v(d+"Gradient");i.id="r"+(m._id++)[N](36);v(i,d=="radial"?{fx:f,fy:e}:{x1:h[0],y1:h[1],x2:h[2],y2:h[3]});c.defs[y](i);c=0;for(h=b[o];cb.height&&(b.height=e.y+e.height-b.y);e.x+e.width-b.x>b.width&&(b.width=e.x+e.width-b.x)}}a&&this.hide();return b};u[p].attr=function(a,b){if(this.removed)return this;if(a==null){a={};for(var c in this.attrs)if(this.attrs[z](c))a[c]=this.attrs[c];this._.rt.deg&&(a.rotation=this.rotate());(this._.sx!=1||this._.sy!= +1)&&(a.scale=this.scale());a.gradient&&a.fill=="none"&&(a.fill=a.gradient)&&delete a.gradient;return a}if(b==null&&m.is(a,ea)){if(a=="translation")return ya.call(this);if(a=="rotation")return this.rotate();if(a=="scale")return this.scale();if(a==aa&&this.attrs.fill=="none"&&this.attrs.gradient)return this.attrs.gradient;return this.attrs[a]}if(b==null&&m.is(a,U)){b={};c=0;for(var d=a.length;c1&&(a=1);f.opacity=a}b.fill&&(f.on=true);if(f.on==null||b.fill=="none")f.on=false;if(f.on&&b.fill)if(a=b.fill.match(Na)){f.src=a[1];f.type="tile"}else{f.color=m.getRGB(b.fill).hex;f.src= +s;f.type="solid";if(m.getRGB(b.fill).error&&(g.type in{circle:1,ellipse:1}||(b.fill+s).charAt()!="r")&&ma(g,b.fill)){d.fill="none";d.gradient=b.fill}}e&&c[y](f);f=c.getElementsByTagName("stroke")&&c.getElementsByTagName("stroke")[0];e=false;!f&&(e=f=R("stroke"));if(b.stroke&&b.stroke!="none"||b["stroke-width"]||b["stroke-opacity"]!=null||b["stroke-dasharray"]||b["stroke-miterlimit"]||b["stroke-linejoin"]||b["stroke-linecap"])f.on=true;(b.stroke=="none"||f.on==null||b.stroke==0||b["stroke-width"]== +0)&&(f.on=false);a=m.getRGB(b.stroke);f.on&&b.stroke&&(f.color=a.hex);a=((+d["stroke-opacity"]+1||2)-1)*((+d.opacity+1||2)-1)*((+a.o+1||2)-1);h=(A(b["stroke-width"])||1)*0.75;a<0&&(a=0);a>1&&(a=1);b["stroke-width"]==null&&(h=d["stroke-width"]);b["stroke-width"]&&(f.weight=h);h&&h<1&&(a*=h)&&(f.weight=1);f.opacity=a;b["stroke-linejoin"]&&(f.joinstyle=b["stroke-linejoin"]||"miter");f.miterlimit=b["stroke-miterlimit"]||8;b["stroke-linecap"]&&(f.endcap=b["stroke-linecap"]=="butt"?"flat":b["stroke-linecap"]== +"square"?"square":"round");if(b["stroke-dasharray"]){a={"-":"shortdash",".":"shortdot","-.":"shortdashdot","-..":"shortdashdotdot",". ":"dot","- ":"dash","--":"longdash","- .":"dashdot","--.":"longdashdot","--..":"longdashdotdot"};f.dashstyle=a[z](b["stroke-dasharray"])?a[b["stroke-dasharray"]]:s}e&&c[y](f)}if(g.type=="text"){f=g.paper.span.style;d.font&&(f.font=d.font);d["font-family"]&&(f.fontFamily=d["font-family"]);d["font-size"]&&(f.fontSize=d["font-size"]);d["font-weight"]&&(f.fontWeight=d["font-weight"]); +d["font-style"]&&(f.fontStyle=d["font-style"]);g.node.string&&(g.paper.span.innerHTML=(g.node.string+s)[I](/"));g.W=d.w=g.paper.span.offsetWidth;g.H=d.h=g.paper.span.offsetHeight;g.X=d.x;g.Y=d.y+F(g.H/2);switch(d["text-anchor"]){case "start":g.node.style["v-text-align"]="left";g.bbx=F(g.W/2);break;case "end":g.node.style["v-text-align"]="right";g.bbx=-F(g.W/2);break;default:g.node.style["v-text-align"]="center";break}}};ma=function(a,b){a.attrs=a.attrs|| +{};var c="linear",d=".5 .5";a.attrs.gradient=b;b=(b+s)[I](Ya,function(i,j,l){c="radial";if(j&&l){j=A(j);l=A(l);D(j-0.5,2)+D(l-0.5,2)>0.25&&(l=w.sqrt(0.25-D(j-0.5,2))*((l>0.5)*2-1)+0.5);d=j+P+l}return s});b=b[H](/\s*\-\s*/);if(c=="linear"){var f=b.shift();f=-A(f);if(isNaN(f))return null}var e=Ra(b);if(!e)return null;a=a.shape||a.node;b=a.getElementsByTagName(aa)[0]||R(aa);!b.parentNode&&a.appendChild(b);if(e[o]){b.on=true;b.method="none";b.color=e[0].color;b.color2=e[e[o]-1].color;a=[];for(var g=0, +h=e[o];g')}}catch(Kb){R=function(a){return C.createElement("<"+a+' xmlns="urn:schemas-microsoft.com:vml" class="rvml">')}}Aa=function(){var a=Sa[K](0,arguments),b=a.container,c=a.height,d=a.width,f=a.x;a=a.y;if(!b)throw new Error("VML container not found.");var e=new G,g=e.canvas=C.createElement("div"),h=g.style;f=f||0;a=a||0;d=d||512; +c=c||342;d==+d&&(d+="px");c==+c&&(c+="px");e.width=1000;e.height=1000;e.coordsize=ja*1000+P+ja*1000;e.coordorigin="0 0";e.span=C.createElement("span");e.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";g[y](e.span);h.cssText=m.format("width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden",d,c);if(b==1){C.body[y](g);h.left=f+"px";h.top=a+"px";h.position="absolute"}else b.firstChild?b.insertBefore(g, +b.firstChild):b[y](g);Fa.call(e,e,m.fn);return e};G[p].clear=function(){this.canvas.innerHTML=s;this.span=C.createElement("span");this.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";this.canvas[y](this.span);this.bottom=this.top=null};G[p].remove=function(){this.canvas.parentNode.removeChild(this.canvas);for(var a in this)this[a]=Xa(a);return true}}G[p].safari=/^Apple|^Google/.test(X.navigator.vendor)&&(!(X.navigator.userAgent.indexOf("Version/4.0")+ +1)||X.navigator.platform.slice(0,2)=="iP")?function(){var a=this.rect(-99,-99,this.width+99,this.height+99);X.setTimeout(function(){a.remove()})}:function(){};function Db(){this.returnValue=false}function Eb(){return this.originalEvent.preventDefault()}function Fb(){this.cancelBubble=true}function Gb(){return this.originalEvent.stopPropagation()}var Hb=function(){if(C.addEventListener)return function(a,b,c,d){var f=Ba&&Ca[b]?Ca[b]:b;function e(g){if(Ba&&Ca[z](b))for(var h=0,i=g.targetTouches&&g.targetTouches.length;h< +i;h++)if(g.targetTouches[h].target==a){i=g;g=g.targetTouches[h];g.originalEvent=i;g.preventDefault=Eb;g.stopPropagation=Gb;break}return c.call(d,g)}a.addEventListener(f,e,false);return function(){a.removeEventListener(f,e,false);return true}};else if(C.attachEvent)return function(a,b,c,d){function f(g){g=g||X.event;g.preventDefault=g.preventDefault||Db;g.stopPropagation=g.stopPropagation||Fb;return c.call(d,g)}a.attachEvent("on"+b,f);function e(){a.detachEvent("on"+b,f);return true}return e}}();for(ha= +Ma[o];ha--;)(function(a){m[a]=u[p][a]=function(b){if(m.is(b,"function")){this.events=this.events||[];this.events.push({name:a,f:b,unbind:Hb(this.shape||this.node||C,a,b,this)})}return this};m["un"+a]=u[p]["un"+a]=function(b){for(var c=this.events,d=c[o];d--;)if(c[d].name==a&&c[d].f==b){c[d].unbind();c.splice(d,1);!c.length&&delete this.events;return this}return this}})(Ma[ha]);u[p].hover=function(a,b){return this.mouseover(a).mouseout(b)};u[p].unhover=function(a,b){return this.unmouseover(a).unmouseout(b)}; +u[p].drag=function(a,b,c){this._drag={};var d=this.mousedown(function(g){(g.originalEvent?g.originalEvent:g).preventDefault();this._drag.x=g.clientX;this._drag.y=g.clientY;this._drag.id=g.identifier;b&&b.call(this,g.clientX,g.clientY);Raphael.mousemove(f).mouseup(e)});function f(g){var h=g.clientX,i=g.clientY;if(Ba)for(var j=g.touches.length,l;j--;){l=g.touches[j];if(l.identifier==d._drag.id){h=l.clientX;i=l.clientY;(g.originalEvent?g.originalEvent:g).preventDefault();break}}else g.preventDefault(); +a&&a.call(d,h-d._drag.x,i-d._drag.y,h,i)}function e(){d._drag={};Raphael.unmousemove(f).unmouseup(e);c&&c.call(d)}return this};G[p].circle=function(a,b,c){return ab(this,a||0,b||0,c||0)};G[p].rect=function(a,b,c,d,f){return bb(this,a||0,b||0,c||0,d||0,f||0)};G[p].ellipse=function(a,b,c,d){return cb(this,a||0,b||0,c||0,d||0)};G[p].path=function(a){a&&!m.is(a,ea)&&!m.is(a[0],U)&&(a+=s);return Za(m.format[K](m,arguments),this)};G[p].image=function(a,b,c,d,f){return db(this,a||"about:blank",b||0,c||0, +d||0,f||0)};G[p].text=function(a,b,c){return eb(this,a||0,b||0,c||s)};G[p].set=function(a){arguments[o]>1&&(a=Array[p].splice.call(arguments,0,arguments[o]));return new Z(a)};G[p].setSize=fb;G[p].top=G[p].bottom=null;G[p].raphael=m;function ib(){return this.x+P+this.y}u[p].resetScale=function(){if(this.removed)return this;this._.sx=1;this._.sy=1;this.attrs.scale="1 1"};u[p].scale=function(a,b,c,d){if(this.removed)return this;if(a==null&&b==null)return{x:this._.sx,y:this._.sy,toString:ib};b=b||a;!+b&& +(b=a);var f,e,g=this.attrs;if(a!=0){var h=this.getBBox(),i=h.x+h.width/2,j=h.y+h.height/2;f=a/this._.sx;e=b/this._.sy;c=+c||c==0?c:i;d=+d||d==0?d:j;h=~~(a/w.abs(a));var l=~~(b/w.abs(b)),n=this.node.style,r=c+(i-c)*f;j=d+(j-d)*e;switch(this.type){case "rect":case "image":var q=g.width*h*f,k=g.height*l*e;this.attr({height:k,r:g.r*$(h*f,l*e),width:q,x:r-q/2,y:j-k/2});break;case "circle":case "ellipse":this.attr({rx:g.rx*h*f,ry:g.ry*l*e,r:g.r*$(h*f,l*e),cx:r,cy:j});break;case "text":this.attr({x:r,y:j}); +break;case "path":i=Oa(g.path);for(var t=true,L=0,B=i[o];L=i)return r;l=r}});function Ha(a,b){return function(c,d,f){c=ua(c); +for(var e,g,h,i,j="",l={},n=0,r=0,q=c.length;rd){if(b&&!l.start){e=jb(e,g,h[1],h[2],h[3],h[4],h[5],h[6],d-n);j+=["C",e.start.x,e.start.y,e.m.x,e.m.y,e.x,e.y];if(f)return j;l.start=j;j=["M",e.x,e.y+"C",e.n.x,e.n.y,e.end.x,e.end.y,h[5],h[6]][Q]();n+=i;e=+h[5];g=+h[6];continue}if(!a&&!b){e=jb(e,g,h[1],h[2],h[3],h[4],h[5],h[6],d-n);return{x:e.x,y:e.y,alpha:e.alpha}}}n+=i;e=+h[5];g=+h[6]}j+=h}l.end=j;e=a?n: +b?l:m.findDotsAtSegment(e,g,h[1],h[2],h[3],h[4],h[5],h[6],1);e.alpha&&(e={x:e.x,y:e.y,alpha:e.alpha});return e}}var Ib=T(function(a,b,c,d,f,e,g,h){for(var i={x:0,y:0},j=0,l=0;l<1.01;l+=0.01){var n=la(a,b,c,d,f,e,g,h,l);l&&(j+=D(D(i.x-n.x,2)+D(i.y-n.y,2),0.5));i=n}return j}),kb=Ha(1),za=Ha(),Ia=Ha(0,1);u[p].getTotalLength=function(){if(this.type=="path"){if(this.node.getTotalLength)return this.node.getTotalLength();return kb(this.attrs.path)}};u[p].getPointAtLength=function(a){if(this.type=="path")return za(this.attrs.path, +a)};u[p].getSubpath=function(a,b){if(this.type=="path"){if(w.abs(this.getTotalLength()-b)<1.0E-6)return Ia(this.attrs.path,a).end;b=Ia(this.attrs.path,b,1);return a?Ia(b,a).end:b}};m.easing_formulas={linear:function(a){return a},"<":function(a){return D(a,3)},">":function(a){return D(a-1,3)+1},"<>":function(a){a*=2;if(a<1)return D(a,3)/2;a-=2;return(D(a,3)+2)/2},backIn:function(a){var b=1.70158;return a*a*((b+1)*a-b)},backOut:function(a){a-=1;var b=1.70158;return a*a*((b+1)*a+b)+1},elastic:function(a){if(a== +0||a==1)return a;var b=0.3,c=b/4;return D(2,-10*a)*w.sin((a-c)*2*w.PI/b)+1},bounce:function(a){var b=7.5625,c=2.75;if(a<1/c)a=b*a*a;else if(a<2/c){a-=1.5/c;a=b*a*a+0.75}else if(a<2.5/c){a-=2.25/c;a=b*a*a+0.9375}else{a-=2.625/c;a=b*a*a+0.984375}return a}};var S={length:0};function lb(){var a=+new Date;for(var b in S)if(b!="length"&&S[z](b)){var c=S[b];if(c.stop||c.el.removed){delete S[b];S[o]--}else{var d=a-c.start,f=c.ms,e=c.easing,g=c.from,h=c.diff,i=c.to,j=c.t,l=c.prev||0,n=c.el,r=c.callback,q= +{},k;if(d + + + + +

          you shouldn't be here.. kicking you out!

          + + diff --git a/non-rack-legacy/public/js/irb.js b/non-rack-legacy/public/js/irb.js new file mode 100755 index 0000000..23d83df --- /dev/null +++ b/non-rack-legacy/public/js/irb.js @@ -0,0 +1,110 @@ +// +// Copyright (c) 2008 why the lucky stiff +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +var allStretch; +var helpPages; +var chapPages; +var defaultPage; +var toot = window.location.search.substr(1) + +//the main function, call to the effect object +function dumpAlert(obj) { + props = []; + for ( var i in obj ) { + props.push( "" + i + ": " + obj[i] ); + } + alert( props ); +} +window.onload = function() { + defaultPage = $('#helpstone .stretcher').html(); + + window.irb = new MouseApp.Irb('#irb', { + rows: 13, + name: 'IRB', + greeting: "%+r Interactive ruby ready. %-r", + ps: '\033[1;31m>>\033[m', + user: 'guest', + host: 'tryruby', + // original: irbUrl: '/irb', + irbUrl: '/irb.cgi', + init: function () { + helpPages = $(".stretcher"); + chapPages = new Array(); + for (var i = 0; i < helpPages.length; i++ ) { + var cls = helpPages[i].className.split(' '); + for (var j = 0; j < cls.length; j++) { + if (cls[j] == 'chapmark') { + chapPages.push([i, helpPages[i]]); + break; + } + } + } + }, + loadTutorial: function (id, instruct) { + $.ajax({ + url: '/tutorials/' + id + '.html', + type: 'GET', + complete: function (r) { + $('#helpstone').html("
          " + defaultPage + "
          " + r.responseText); + window.irb.init(); + window.irb.showHelp(0); + } + }); + }, + showChapter: function (n) { + if (n >= chapPages.length) return; + this.setHelpPage(chapPages[n][0], chapPages[n][1]); + }, + showHelp: function (n) { + if (n >= helpPages.length) return; + this.setHelpPage(n, helpPages[n]); + }, + popup_goto: function (u) { + $('#lilBrowser').show().css({left: '40px', top: '40px'}); + $('#lbIframe').attr('src', u); + }, + popup_make: function (s) { + $('#lilBrowser').show().css({left: '40px', top: '40px'}); + $('#lbIframe').get(0).onIframeLoad = function () { + alert($(this).html()); + alert("$(this).html()"); + return s; + }; + //$('#lbIframe').attr({src: '/blank.html'}); + src = s.replace(/\\/g, "\\\\").replace(/\"/g, "\\\""); + $('#lbIframe').attr({src: "javascript:\"" + src + "\""}); + // $('# + }, + popup_close: function () { + $('#lilBrowser').hide(); + } + }); + + if ( !toot ) { + toot = 'intro'; + } + try { + window.irb.options.loadTutorial( toot, true ); + } catch (e) {} +} diff --git a/non-rack-legacy/public/js/jquery-1.3.2.min.js b/non-rack-legacy/public/js/jquery-1.3.2.min.js new file mode 100644 index 0000000..b1ae21d --- /dev/null +++ b/non-rack-legacy/public/js/jquery-1.3.2.min.js @@ -0,0 +1,19 @@ +/* + * jQuery JavaScript Library v1.3.2 + * http://jquery.com/ + * + * Copyright (c) 2009 John Resig + * Dual licensed under the MIT and GPL licenses. + * http://docs.jquery.com/License + * + * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) + * Revision: 6246 + */ +(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("",""]||!O.indexOf("",""]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
          "]||!O.indexOf("",""]||(!O.indexOf("",""]||!O.indexOf("",""]||!o.support.htmlSerialize&&[1,"div
          ","
          "]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}}); +/* + * Sizzle CSS Selector Engine - v0.9.3 + * Copyright 2009, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return UT[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="

          ";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="
          ";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("
          ").append(M.responseText.replace(//g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='
          ';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})(); \ No newline at end of file diff --git a/non-rack-legacy/public/js/jquery.js b/non-rack-legacy/public/js/jquery.js new file mode 100755 index 0000000..3747929 --- /dev/null +++ b/non-rack-legacy/public/js/jquery.js @@ -0,0 +1,32 @@ +/* + * jQuery 1.2.3 - New Wave Javascript + * + * Copyright (c) 2008 John Resig (jquery.com) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * $Date: 2008-02-06 00:21:25 -0500 (Wed, 06 Feb 2008) $ + * $Rev: 4663 $ + */ +(function(){if(window.jQuery)var _jQuery=window.jQuery;var jQuery=window.jQuery=function(selector,context){return new jQuery.prototype.init(selector,context);};if(window.$)var _$=window.$;window.$=jQuery;var quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;var isSimple=/^.[^:#\[\.]*$/;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;return this;}else if(typeof selector=="string"){var match=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1])selector=jQuery.clean([match[1]],context);else{var elem=document.getElementById(match[3]);if(elem)if(elem.id!=match[3])return jQuery().find(selector);else{this[0]=elem;this.length=1;return this;}else +selector=[];}}else +return new jQuery(context).find(selector);}else if(jQuery.isFunction(selector))return new jQuery(document)[jQuery.fn.ready?"ready":"load"](selector);return this.setArray(selector.constructor==Array&&selector||(selector.jquery||selector.length&&selector!=window&&!selector.nodeType&&selector[0]!=undefined&&selector[0].nodeType)&&jQuery.makeArray(selector)||[selector]);},jquery:"1.2.3",size:function(){return this.length;},length:0,get:function(num){return num==undefined?jQuery.makeArray(this):this[num];},pushStack:function(elems){var ret=jQuery(elems);ret.prevObject=this;return ret;},setArray:function(elems){this.length=0;Array.prototype.push.apply(this,elems);return this;},each:function(callback,args){return jQuery.each(this,callback,args);},index:function(elem){var ret=-1;this.each(function(i){if(this==elem)ret=i;});return ret;},attr:function(name,value,type){var options=name;if(name.constructor==String)if(value==undefined)return this.length&&jQuery[type||"attr"](this[0],name)||undefined;else{options={};options[name]=value;}return this.each(function(i){for(name in options)jQuery.attr(type?this.style:this,name,jQuery.prop(this,options[name],type,i,name));});},css:function(key,value){if((key=='width'||key=='height')&&parseFloat(value)<0)value=undefined;return this.attr(key,value,"curCSS");},text:function(text){if(typeof text!="object"&&text!=null)return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(text));var ret="";jQuery.each(text||this,function(){jQuery.each(this.childNodes,function(){if(this.nodeType!=8)ret+=this.nodeType!=1?this.nodeValue:jQuery.fn.text([this]);});});return ret;},wrapAll:function(html){if(this[0])jQuery(html,this[0].ownerDocument).clone().insertBefore(this[0]).map(function(){var elem=this;while(elem.firstChild)elem=elem.firstChild;return elem;}).append(this);return this;},wrapInner:function(html){return this.each(function(){jQuery(this).contents().wrapAll(html);});},wrap:function(html){return this.each(function(){jQuery(this).wrapAll(html);});},append:function(){return this.domManip(arguments,true,false,function(elem){if(this.nodeType==1)this.appendChild(elem);});},prepend:function(){return this.domManip(arguments,true,true,function(elem){if(this.nodeType==1)this.insertBefore(elem,this.firstChild);});},before:function(){return this.domManip(arguments,false,false,function(elem){this.parentNode.insertBefore(elem,this);});},after:function(){return this.domManip(arguments,false,true,function(elem){this.parentNode.insertBefore(elem,this.nextSibling);});},end:function(){return this.prevObject||jQuery([]);},find:function(selector){var elems=jQuery.map(this,function(elem){return jQuery.find(selector,elem);});return this.pushStack(/[^+>] [^+>]/.test(selector)||selector.indexOf("..")>-1?jQuery.unique(elems):elems);},clone:function(events){var ret=this.map(function(){if(jQuery.browser.msie&&!jQuery.isXMLDoc(this)){var clone=this.cloneNode(true),container=document.createElement("div");container.appendChild(clone);return jQuery.clean([container.innerHTML])[0];}else +return this.cloneNode(true);});var clone=ret.find("*").andSelf().each(function(){if(this[expando]!=undefined)this[expando]=null;});if(events===true)this.find("*").andSelf().each(function(i){if(this.nodeType==3)return;var events=jQuery.data(this,"events");for(var type in events)for(var handler in events[type])jQuery.event.add(clone[i],type,events[type][handler],events[type][handler].data);});return ret;},filter:function(selector){return this.pushStack(jQuery.isFunction(selector)&&jQuery.grep(this,function(elem,i){return selector.call(elem,i);})||jQuery.multiFilter(selector,this));},not:function(selector){if(selector.constructor==String)if(isSimple.test(selector))return this.pushStack(jQuery.multiFilter(selector,this,true));else +selector=jQuery.multiFilter(selector,this);var isArrayLike=selector.length&&selector[selector.length-1]!==undefined&&!selector.nodeType;return this.filter(function(){return isArrayLike?jQuery.inArray(this,selector)<0:this!=selector;});},add:function(selector){return!selector?this:this.pushStack(jQuery.merge(this.get(),selector.constructor==String?jQuery(selector).get():selector.length!=undefined&&(!selector.nodeName||jQuery.nodeName(selector,"form"))?selector:[selector]));},is:function(selector){return selector?jQuery.multiFilter(selector,this).length>0:false;},hasClass:function(selector){return this.is("."+selector);},val:function(value){if(value==undefined){if(this.length){var elem=this[0];if(jQuery.nodeName(elem,"select")){var index=elem.selectedIndex,values=[],options=elem.options,one=elem.type=="select-one";if(index<0)return null;for(var i=one?index:0,max=one?index+1:options.length;i=0||jQuery.inArray(this.name,value)>=0);else if(jQuery.nodeName(this,"select")){var values=value.constructor==Array?value:[value];jQuery("option",this).each(function(){this.selected=(jQuery.inArray(this.value,values)>=0||jQuery.inArray(this.text,values)>=0);});if(!values.length)this.selectedIndex=-1;}else +this.value=value;});},html:function(value){return value==undefined?(this.length?this[0].innerHTML:null):this.empty().append(value);},replaceWith:function(value){return this.after(value).remove();},eq:function(i){return this.slice(i,i+1);},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments));},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem);}));},andSelf:function(){return this.add(this.prevObject);},data:function(key,value){var parts=key.split(".");parts[1]=parts[1]?"."+parts[1]:"";if(value==null){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data==undefined&&this.length)data=jQuery.data(this[0],key);return data==null&&parts[1]?this.data(parts[0]):data;}else +return this.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){jQuery.data(this,key,value);});},removeData:function(key){return this.each(function(){jQuery.removeData(this,key);});},domManip:function(args,table,reverse,callback){var clone=this.length>1,elems;return this.each(function(){if(!elems){elems=jQuery.clean(args,this.ownerDocument);if(reverse)elems.reverse();}var obj=this;if(table&&jQuery.nodeName(this,"table")&&jQuery.nodeName(elems[0],"tr"))obj=this.getElementsByTagName("tbody")[0]||this.appendChild(this.ownerDocument.createElement("tbody"));var scripts=jQuery([]);jQuery.each(elems,function(){var elem=clone?jQuery(this).clone(true)[0]:this;if(jQuery.nodeName(elem,"script")){scripts=scripts.add(elem);}else{if(elem.nodeType==1)scripts=scripts.add(jQuery("script",elem).remove());callback.call(obj,elem);}});scripts.each(evalScript);});}};jQuery.prototype.init.prototype=jQuery.prototype;function evalScript(i,elem){if(elem.src)jQuery.ajax({url:elem.src,async:false,dataType:"script"});else +jQuery.globalEval(elem.text||elem.textContent||elem.innerHTML||"");if(elem.parentNode)elem.parentNode.removeChild(elem);}jQuery.extend=jQuery.fn.extend=function(){var target=arguments[0]||{},i=1,length=arguments.length,deep=false,options;if(target.constructor==Boolean){deep=target;target=arguments[1]||{};i=2;}if(typeof target!="object"&&typeof target!="function")target={};if(length==1){target=this;i=0;}for(;i-1;}},swap:function(elem,options,callback){var old={};for(var name in options){old[name]=elem.style[name];elem.style[name]=options[name];}callback.call(elem);for(var name in options)elem.style[name]=old[name];},css:function(elem,name,force){if(name=="width"||name=="height"){var val,props={position:"absolute",visibility:"hidden",display:"block"},which=name=="width"?["Left","Right"]:["Top","Bottom"];function getWH(){val=name=="width"?elem.offsetWidth:elem.offsetHeight;var padding=0,border=0;jQuery.each(which,function(){padding+=parseFloat(jQuery.curCSS(elem,"padding"+this,true))||0;border+=parseFloat(jQuery.curCSS(elem,"border"+this+"Width",true))||0;});val-=Math.round(padding+border);}if(jQuery(elem).is(":visible"))getWH();else +jQuery.swap(elem,props,getWH);return Math.max(0,val);}return jQuery.curCSS(elem,name,force);},curCSS:function(elem,name,force){var ret;function color(elem){if(!jQuery.browser.safari)return false;var ret=document.defaultView.getComputedStyle(elem,null);return!ret||ret.getPropertyValue("color")=="";}if(name=="opacity"&&jQuery.browser.msie){ret=jQuery.attr(elem.style,"opacity");return ret==""?"1":ret;}if(jQuery.browser.opera&&name=="display"){var save=elem.style.outline;elem.style.outline="0 solid black";elem.style.outline=save;}if(name.match(/float/i))name=styleFloat;if(!force&&elem.style&&elem.style[name])ret=elem.style[name];else if(document.defaultView&&document.defaultView.getComputedStyle){if(name.match(/float/i))name="float";name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var getComputedStyle=document.defaultView.getComputedStyle(elem,null);if(getComputedStyle&&!color(elem))ret=getComputedStyle.getPropertyValue(name);else{var swap=[],stack=[];for(var a=elem;a&&color(a);a=a.parentNode)stack.unshift(a);for(var i=0;i]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+">";});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("",""]||!tags.indexOf("",""]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
          "]||!tags.indexOf("",""]||(!tags.indexOf("",""]||!tags.indexOf("",""]||jQuery.browser.msie&&[1,"div
          ","
          "]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--)div=div.lastChild;if(jQuery.browser.msie){var tbody=!tags.indexOf(""&&tags.indexOf("=0;--j)if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length)tbody[j].parentNode.removeChild(tbody[j]);if(/^\s/.test(elem))div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]),div.firstChild);}elem=jQuery.makeArray(div.childNodes);}if(elem.length===0&&(!jQuery.nodeName(elem,"form")&&!jQuery.nodeName(elem,"select")))return;if(elem[0]==undefined||jQuery.nodeName(elem,"form")||elem.options)ret.push(elem);else +ret=jQuery.merge(ret,elem);});return ret;},attr:function(elem,name,value){if(!elem||elem.nodeType==3||elem.nodeType==8)return undefined;var fix=jQuery.isXMLDoc(elem)?{}:jQuery.props;if(name=="selected"&&jQuery.browser.safari)elem.parentNode.selectedIndex;if(fix[name]){if(value!=undefined)elem[fix[name]]=value;return elem[fix[name]];}else if(jQuery.browser.msie&&name=="style")return jQuery.attr(elem.style,"cssText",value);else if(value==undefined&&jQuery.browser.msie&&jQuery.nodeName(elem,"form")&&(name=="action"||name=="method"))return elem.getAttributeNode(name).nodeValue;else if(elem.tagName){if(value!=undefined){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode)throw"type property can't be changed";elem.setAttribute(name,""+value);}if(jQuery.browser.msie&&/href|src/.test(name)&&!jQuery.isXMLDoc(elem))return elem.getAttribute(name,2);return elem.getAttribute(name);}else{if(name=="opacity"&&jQuery.browser.msie){if(value!=undefined){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+(parseFloat(value).toString()=="NaN"?"":"alpha(opacity="+value*100+")");}return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100).toString():"";}name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase();});if(value!=undefined)elem[name]=value;return elem[name];}},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"");},makeArray:function(array){var ret=[];if(typeof array!="array")for(var i=0,length=array.length;i*",this).remove();while(this.firstChild)this.removeChild(this.firstChild);}},function(name,fn){jQuery.fn[name]=function(){return this.each(fn,arguments);};});jQuery.each(["Height","Width"],function(i,name){var type=name.toLowerCase();jQuery.fn[type]=function(size){return this[0]==window?jQuery.browser.opera&&document.body["client"+name]||jQuery.browser.safari&&window["inner"+name]||document.compatMode=="CSS1Compat"&&document.documentElement["client"+name]||document.body["client"+name]:this[0]==document?Math.max(Math.max(document.body["scroll"+name],document.documentElement["scroll"+name]),Math.max(document.body["offset"+name],document.documentElement["offset"+name])):size==undefined?(this.length?jQuery.css(this[0],type):null):this.css(type,size.constructor==String?size:size+"px");};});var chars=jQuery.browser.safari&&parseInt(jQuery.browser.version)<417?"(?:[\\w*_-]|\\\\.)":"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",quickChild=new RegExp("^>\\s*("+chars+"+)"),quickID=new RegExp("^("+chars+"+)(#)("+chars+"+)"),quickClass=new RegExp("^([#.]?)("+chars+"*)");jQuery.extend({expr:{"":function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},"#":function(a,i,m){return a.getAttribute("id")==m[2];},":":{lt:function(a,i,m){return im[3]-0;},nth:function(a,i,m){return m[3]-0==i;},eq:function(a,i,m){return m[3]-0==i;},first:function(a,i){return i==0;},last:function(a,i,m,r){return i==r.length-1;},even:function(a,i){return i%2==0;},odd:function(a,i){return i%2;},"first-child":function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},"last-child":function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},"only-child":function(a){return!jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},parent:function(a){return a.firstChild;},empty:function(a){return!a.firstChild;},contains:function(a,i,m){return(a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},visible:function(a){return"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},hidden:function(a){return"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},enabled:function(a){return!a.disabled;},disabled:function(a){return a.disabled;},checked:function(a){return a.checked;},selected:function(a){return a.selected||jQuery.attr(a,"selected");},text:function(a){return"text"==a.type;},radio:function(a){return"radio"==a.type;},checkbox:function(a){return"checkbox"==a.type;},file:function(a){return"file"==a.type;},password:function(a){return"password"==a.type;},submit:function(a){return"submit"==a.type;},image:function(a){return"image"==a.type;},reset:function(a){return"reset"==a.type;},button:function(a){return"button"==a.type||jQuery.nodeName(a,"button");},input:function(a){return/input|select|textarea|button/i.test(a.nodeName);},has:function(a,i,m){return jQuery.find(m[3],a).length;},header:function(a){return/h\d/i.test(a.nodeName);},animated:function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}}},parse:[/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,new RegExp("^([:.#]*)("+chars+"+)")],multiFilter:function(expr,elems,not){var old,cur=[];while(expr&&expr!=old){old=expr;var f=jQuery.filter(expr,elems,not);expr=f.t.replace(/^\s*,\s*/,"");cur=not?elems=f.r:jQuery.merge(cur,f.r);}return cur;},find:function(t,context){if(typeof t!="string")return[t];if(context&&context.nodeType!=1&&context.nodeType!=9)return[];context=context||document;var ret=[context],done=[],last,nodeName;while(t&&last!=t){var r=[];last=t;t=jQuery.trim(t);var foundToken=false;var re=quickChild;var m=re.exec(t);if(m){nodeName=m[1].toUpperCase();for(var i=0;ret[i];i++)for(var c=ret[i].firstChild;c;c=c.nextSibling)if(c.nodeType==1&&(nodeName=="*"||c.nodeName.toUpperCase()==nodeName))r.push(c);ret=r;t=t.replace(re,"");if(t.indexOf(" ")==0)continue;foundToken=true;}else{re=/^([>+~])\s*(\w*)/i;if((m=re.exec(t))!=null){r=[];var merge={};nodeName=m[2].toUpperCase();m=m[1];for(var j=0,rl=ret.length;j=0;if(!not&&pass||not&&!pass)tmp.push(r[i]);}return tmp;},filter:function(t,r,not){var last;while(t&&t!=last){last=t;var p=jQuery.parse,m;for(var i=0;p[i];i++){m=p[i].exec(t);if(m){t=t.substring(m[0].length);m[2]=m[2].replace(/\\/g,"");break;}}if(!m)break;if(m[1]==":"&&m[2]=="not")r=isSimple.test(m[3])?jQuery.filter(m[3],r,true).r:jQuery(r).not(m[3]);else if(m[1]==".")r=jQuery.classFilter(r,m[2],not);else if(m[1]=="["){var tmp=[],type=m[3];for(var i=0,rl=r.length;i=0)^not)tmp.push(a);}r=tmp;}else if(m[1]==":"&&m[2]=="nth-child"){var merge={},tmp=[],test=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3]=="even"&&"2n"||m[3]=="odd"&&"2n+1"||!/\D/.test(m[3])&&"0n+"+m[3]||m[3]),first=(test[1]+(test[2]||1))-0,last=test[3]-0;for(var i=0,rl=r.length;i=0)add=true;if(add^not)tmp.push(node);}r=tmp;}else{var fn=jQuery.expr[m[1]];if(typeof fn=="object")fn=fn[m[2]];if(typeof fn=="string")fn=eval("false||function(a,i){return "+fn+";}");r=jQuery.grep(r,function(elem,i){return fn(elem,i,m,r);},not);}}return{r:r,t:t};},dir:function(elem,dir){var matched=[];var cur=elem[dir];while(cur&&cur!=document){if(cur.nodeType==1)matched.push(cur);cur=cur[dir];}return matched;},nth:function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir])if(cur.nodeType==1&&++num==result)break;return cur;},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType==1&&(!elem||n!=elem))r.push(n);}return r;}});jQuery.event={add:function(elem,types,handler,data){if(elem.nodeType==3||elem.nodeType==8)return;if(jQuery.browser.msie&&elem.setInterval!=undefined)elem=window;if(!handler.guid)handler.guid=this.guid++;if(data!=undefined){var fn=handler;handler=function(){return fn.apply(this,arguments);};handler.data=data;handler.guid=fn.guid;}var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){var val;if(typeof jQuery=="undefined"||jQuery.event.triggered)return val;val=jQuery.event.handle.apply(arguments.callee.elem,arguments);return val;});handle.elem=elem;jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];handler.type=parts[1];var handlers=events[type];if(!handlers){handlers=events[type]={};if(!jQuery.event.special[type]||jQuery.event.special[type].setup.call(elem)===false){if(elem.addEventListener)elem.addEventListener(type,handle,false);else if(elem.attachEvent)elem.attachEvent("on"+type,handle);}}handlers[handler.guid]=handler;jQuery.event.global[type]=true;});elem=null;},guid:1,global:{},remove:function(elem,types,handler){if(elem.nodeType==3||elem.nodeType==8)return;var events=jQuery.data(elem,"events"),ret,index;if(events){if(types==undefined||(typeof types=="string"&&types.charAt(0)=="."))for(var type in events)this.remove(elem,type+(types||""));else{if(types.type){handler=types.handler;types=types.type;}jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];if(events[type]){if(handler)delete events[type][handler.guid];else +for(handler in events[type])if(!parts[1]||events[type][handler].type==parts[1])delete events[type][handler];for(ret in events[type])break;if(!ret){if(!jQuery.event.special[type]||jQuery.event.special[type].teardown.call(elem)===false){if(elem.removeEventListener)elem.removeEventListener(type,jQuery.data(elem,"handle"),false);else if(elem.detachEvent)elem.detachEvent("on"+type,jQuery.data(elem,"handle"));}ret=null;delete events[type];}}});}for(ret in events)break;if(!ret){var handle=jQuery.data(elem,"handle");if(handle)handle.elem=null;jQuery.removeData(elem,"events");jQuery.removeData(elem,"handle");}}},trigger:function(type,data,elem,donative,extra){data=jQuery.makeArray(data||[]);if(type.indexOf("!")>=0){type=type.slice(0,-1);var exclusive=true;}if(!elem){if(this.global[type])jQuery("*").add([window,document]).trigger(type,data);}else{if(elem.nodeType==3||elem.nodeType==8)return undefined;var val,ret,fn=jQuery.isFunction(elem[type]||null),event=!data[0]||!data[0].preventDefault;if(event)data.unshift(this.fix({type:type,target:elem}));data[0].type=type;if(exclusive)data[0].exclusive=true;if(jQuery.isFunction(jQuery.data(elem,"handle")))val=jQuery.data(elem,"handle").apply(elem,data);if(!fn&&elem["on"+type]&&elem["on"+type].apply(elem,data)===false)val=false;if(event)data.shift();if(extra&&jQuery.isFunction(extra)){ret=extra.apply(elem,val==null?data:data.concat(val));if(ret!==undefined)val=ret;}if(fn&&donative!==false&&val!==false&&!(jQuery.nodeName(elem,'a')&&type=="click")){this.triggered=true;try{elem[type]();}catch(e){}}this.triggered=false;}return val;},handle:function(event){var val;event=jQuery.event.fix(event||window.event||{});var parts=event.type.split(".");event.type=parts[0];var handlers=jQuery.data(this,"events")&&jQuery.data(this,"events")[event.type],args=Array.prototype.slice.call(arguments,1);args.unshift(event);for(var j in handlers){var handler=handlers[j];args[0].handler=handler;args[0].data=handler.data;if(!parts[1]&&!event.exclusive||handler.type==parts[1]){var ret=handler.apply(this,args);if(val!==false)val=ret;if(ret===false){event.preventDefault();event.stopPropagation();}}}if(jQuery.browser.msie)event.target=event.preventDefault=event.stopPropagation=event.handler=event.data=null;return val;},fix:function(event){var originalEvent=event;event=jQuery.extend({},originalEvent);event.preventDefault=function(){if(originalEvent.preventDefault)originalEvent.preventDefault();originalEvent.returnValue=false;};event.stopPropagation=function(){if(originalEvent.stopPropagation)originalEvent.stopPropagation();originalEvent.cancelBubble=true;};if(!event.target)event.target=event.srcElement||document;if(event.target.nodeType==3)event.target=originalEvent.target.parentNode;if(!event.relatedTarget&&event.fromElement)event.relatedTarget=event.fromElement==event.target?event.toElement:event.fromElement;if(event.pageX==null&&event.clientX!=null){var doc=document.documentElement,body=document.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc.clientTop||0);}if(!event.which&&((event.charCode||event.charCode===0)?event.charCode:event.keyCode))event.which=event.charCode||event.keyCode;if(!event.metaKey&&event.ctrlKey)event.metaKey=event.ctrlKey;if(!event.which&&event.button)event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)));return event;},special:{ready:{setup:function(){bindReady();return;},teardown:function(){return;}},mouseenter:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseover",jQuery.event.special.mouseenter.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseover",jQuery.event.special.mouseenter.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseenter";return jQuery.event.handle.apply(this,arguments);}},mouseleave:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseout",jQuery.event.special.mouseleave.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseout",jQuery.event.special.mouseleave.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseleave";return jQuery.event.handle.apply(this,arguments);}}}};jQuery.fn.extend({bind:function(type,data,fn){return type=="unload"?this.one(type,data,fn):this.each(function(){jQuery.event.add(this,type,fn||data,fn&&data);});},one:function(type,data,fn){return this.each(function(){jQuery.event.add(this,type,function(event){jQuery(this).unbind(event);return(fn||data).apply(this,arguments);},fn&&data);});},unbind:function(type,fn){return this.each(function(){jQuery.event.remove(this,type,fn);});},trigger:function(type,data,fn){return this.each(function(){jQuery.event.trigger(type,data,this,true,fn);});},triggerHandler:function(type,data,fn){if(this[0])return jQuery.event.trigger(type,data,this[0],false,fn);return undefined;},toggle:function(){var args=arguments;return this.click(function(event){this.lastToggle=0==this.lastToggle?1:0;event.preventDefault();return args[this.lastToggle].apply(this,arguments)||false;});},hover:function(fnOver,fnOut){return this.bind('mouseenter',fnOver).bind('mouseleave',fnOut);},ready:function(fn){bindReady();if(jQuery.isReady)fn.call(document,jQuery);else +jQuery.readyList.push(function(){return fn.call(this,jQuery);});return this;}});jQuery.extend({isReady:false,readyList:[],ready:function(){if(!jQuery.isReady){jQuery.isReady=true;if(jQuery.readyList){jQuery.each(jQuery.readyList,function(){this.apply(document);});jQuery.readyList=null;}jQuery(document).triggerHandler("ready");}}});var readyBound=false;function bindReady(){if(readyBound)return;readyBound=true;if(document.addEventListener&&!jQuery.browser.opera)document.addEventListener("DOMContentLoaded",jQuery.ready,false);if(jQuery.browser.msie&&window==top)(function(){if(jQuery.isReady)return;try{document.documentElement.doScroll("left");}catch(error){setTimeout(arguments.callee,0);return;}jQuery.ready();})();if(jQuery.browser.opera)document.addEventListener("DOMContentLoaded",function(){if(jQuery.isReady)return;for(var i=0;i=0){var selector=url.slice(off,url.length);url=url.slice(0,off);}callback=callback||function(){};var type="GET";if(params)if(jQuery.isFunction(params)){callback=params;params=null;}else{params=jQuery.param(params);type="POST";}var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(res,status){if(status=="success"||status=="notmodified")self.html(selector?jQuery("
          ").append(res.responseText.replace(//g,"")).find(selector):res.responseText);self.each(callback,[res.responseText,status,res]);}});return this;},serialize:function(){return jQuery.param(this.serializeArray());},serializeArray:function(){return this.map(function(){return jQuery.nodeName(this,"form")?jQuery.makeArray(this.elements):this;}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type));}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:val.constructor==Array?jQuery.map(val,function(val,i){return{name:elem.name,value:val};}):{name:elem.name,value:val};}).get();}});jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(i,o){jQuery.fn[o]=function(f){return this.bind(o,f);};});var jsc=(new Date).getTime();jQuery.extend({get:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data=null;}return jQuery.ajax({type:"GET",url:url,data:data,success:callback,dataType:type});},getScript:function(url,callback){return jQuery.get(url,null,callback,"script");},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},post:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data={};}return jQuery.ajax({type:"POST",url:url,data:data,success:callback,dataType:type});},ajaxSetup:function(settings){jQuery.extend(jQuery.ajaxSettings,settings);},ajaxSettings:{global:true,type:"GET",timeout:0,contentType:"application/x-www-form-urlencoded",processData:true,async:true,data:null,username:null,password:null,accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(s){var jsonp,jsre=/=\?(&|$)/g,status,data;s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));if(s.data&&s.processData&&typeof s.data!="string")s.data=jQuery.param(s.data);if(s.dataType=="jsonp"){if(s.type.toLowerCase()=="get"){if(!s.url.match(jsre))s.url+=(s.url.match(/\?/)?"&":"?")+(s.jsonp||"callback")+"=?";}else if(!s.data||!s.data.match(jsre))s.data=(s.data?s.data+"&":"")+(s.jsonp||"callback")+"=?";s.dataType="json";}if(s.dataType=="json"&&(s.data&&s.data.match(jsre)||s.url.match(jsre))){jsonp="jsonp"+jsc++;if(s.data)s.data=(s.data+"").replace(jsre,"="+jsonp+"$1");s.url=s.url.replace(jsre,"="+jsonp+"$1");s.dataType="script";window[jsonp]=function(tmp){data=tmp;success();complete();window[jsonp]=undefined;try{delete window[jsonp];}catch(e){}if(head)head.removeChild(script);};}if(s.dataType=="script"&&s.cache==null)s.cache=false;if(s.cache===false&&s.type.toLowerCase()=="get"){var ts=(new Date()).getTime();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"");}if(s.data&&s.type.toLowerCase()=="get"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null;}if(s.global&&!jQuery.active++)jQuery.event.trigger("ajaxStart");if((!s.url.indexOf("http")||!s.url.indexOf("//"))&&s.dataType=="script"&&s.type.toLowerCase()=="get"){var head=document.getElementsByTagName("head")[0];var script=document.createElement("script");script.src=s.url;if(s.scriptCharset)script.charset=s.scriptCharset;if(!jsonp){var done=false;script.onload=script.onreadystatechange=function(){if(!done&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){done=true;success();complete();head.removeChild(script);}};}head.appendChild(script);return undefined;}var requestDone=false;var xml=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();xml.open(s.type,s.url,s.async,s.username,s.password);try{if(s.data)xml.setRequestHeader("Content-Type",s.contentType);if(s.ifModified)xml.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT");xml.setRequestHeader("X-Requested-With","XMLHttpRequest");xml.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default);}catch(e){}if(s.beforeSend)s.beforeSend(xml);if(s.global)jQuery.event.trigger("ajaxSend",[xml,s]);var onreadystatechange=function(isTimeout){if(!requestDone&&xml&&(xml.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null;}status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xml)&&"error"||s.ifModified&&jQuery.httpNotModified(xml,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xml,s.dataType);}catch(e){status="parsererror";}}if(status=="success"){var modRes;try{modRes=xml.getResponseHeader("Last-Modified");}catch(e){}if(s.ifModified&&modRes)jQuery.lastModified[s.url]=modRes;if(!jsonp)success();}else +jQuery.handleError(s,xml,status);complete();if(s.async)xml=null;}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0)setTimeout(function(){if(xml){xml.abort();if(!requestDone)onreadystatechange("timeout");}},s.timeout);}try{xml.send(s.data);}catch(e){jQuery.handleError(s,xml,null,e);}if(!s.async)onreadystatechange();function success(){if(s.success)s.success(data,status);if(s.global)jQuery.event.trigger("ajaxSuccess",[xml,s]);}function complete(){if(s.complete)s.complete(xml,status);if(s.global)jQuery.event.trigger("ajaxComplete",[xml,s]);if(s.global&&!--jQuery.active)jQuery.event.trigger("ajaxStop");}return xml;},handleError:function(s,xml,status,e){if(s.error)s.error(xml,status,e);if(s.global)jQuery.event.trigger("ajaxError",[xml,s,e]);},active:0,httpSuccess:function(r){try{return!r.status&&location.protocol=="file:"||(r.status>=200&&r.status<300)||r.status==304||r.status==1223||jQuery.browser.safari&&r.status==undefined;}catch(e){}return false;},httpNotModified:function(xml,url){try{var xmlRes=xml.getResponseHeader("Last-Modified");return xml.status==304||xmlRes==jQuery.lastModified[url]||jQuery.browser.safari&&xml.status==undefined;}catch(e){}return false;},httpData:function(r,type){var ct=r.getResponseHeader("content-type");var xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0;var data=xml?r.responseXML:r.responseText;if(xml&&data.documentElement.tagName=="parsererror")throw"parsererror";if(type=="script")jQuery.globalEval(data);if(type=="json")data=eval("("+data+")");return data;},param:function(a){var s=[];if(a.constructor==Array||a.jquery)jQuery.each(a,function(){s.push(encodeURIComponent(this.name)+"="+encodeURIComponent(this.value));});else +for(var j in a)if(a[j]&&a[j].constructor==Array)jQuery.each(a[j],function(){s.push(encodeURIComponent(j)+"="+encodeURIComponent(this));});else +s.push(encodeURIComponent(j)+"="+encodeURIComponent(a[j]));return s.join("&").replace(/%20/g,"+");}});jQuery.fn.extend({show:function(speed,callback){return speed?this.animate({height:"show",width:"show",opacity:"show"},speed,callback):this.filter(":hidden").each(function(){this.style.display=this.oldblock||"";if(jQuery.css(this,"display")=="none"){var elem=jQuery("<"+this.tagName+" />").appendTo("body");this.style.display=elem.css("display");if(this.style.display=="none")this.style.display="block";elem.remove();}}).end();},hide:function(speed,callback){return speed?this.animate({height:"hide",width:"hide",opacity:"hide"},speed,callback):this.filter(":visible").each(function(){this.oldblock=this.oldblock||jQuery.css(this,"display");this.style.display="none";}).end();},_toggle:jQuery.fn.toggle,toggle:function(fn,fn2){return jQuery.isFunction(fn)&&jQuery.isFunction(fn2)?this._toggle(fn,fn2):fn?this.animate({height:"toggle",width:"toggle",opacity:"toggle"},fn,fn2):this.each(function(){jQuery(this)[jQuery(this).is(":hidden")?"show":"hide"]();});},slideDown:function(speed,callback){return this.animate({height:"show"},speed,callback);},slideUp:function(speed,callback){return this.animate({height:"hide"},speed,callback);},slideToggle:function(speed,callback){return this.animate({height:"toggle"},speed,callback);},fadeIn:function(speed,callback){return this.animate({opacity:"show"},speed,callback);},fadeOut:function(speed,callback){return this.animate({opacity:"hide"},speed,callback);},fadeTo:function(speed,to,callback){return this.animate({opacity:to},speed,callback);},animate:function(prop,speed,easing,callback){var optall=jQuery.speed(speed,easing,callback);return this[optall.queue===false?"each":"queue"](function(){if(this.nodeType!=1)return false;var opt=jQuery.extend({},optall);var hidden=jQuery(this).is(":hidden"),self=this;for(var p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden)return jQuery.isFunction(opt.complete)&&opt.complete.apply(this);if(p=="height"||p=="width"){opt.display=jQuery.css(this,"display");opt.overflow=this.style.overflow;}}if(opt.overflow!=null)this.style.overflow="hidden";opt.curAnim=jQuery.extend({},prop);jQuery.each(prop,function(name,val){var e=new jQuery.fx(self,opt,name);if(/toggle|show|hide/.test(val))e[val=="toggle"?hidden?"show":"hide":val](prop);else{var parts=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),start=e.cur(true)||0;if(parts){var end=parseFloat(parts[2]),unit=parts[3]||"px";if(unit!="px"){self.style[name]=(end||1)+unit;start=((end||1)/e.cur(true))*start;self.style[name]=start+unit;}if(parts[1])end=((parts[1]=="-="?-1:1)*end)+start;e.custom(start,end,unit);}else +e.custom(start,val,"");}});return true;});},queue:function(type,fn){if(jQuery.isFunction(type)||(type&&type.constructor==Array)){fn=type;type="fx";}if(!type||(typeof type=="string"&&!fn))return queue(this[0],type);return this.each(function(){if(fn.constructor==Array)queue(this,type,fn);else{queue(this,type).push(fn);if(queue(this,type).length==1)fn.apply(this);}});},stop:function(clearQueue,gotoEnd){var timers=jQuery.timers;if(clearQueue)this.queue([]);this.each(function(){for(var i=timers.length-1;i>=0;i--)if(timers[i].elem==this){if(gotoEnd)timers[i](true);timers.splice(i,1);}});if(!gotoEnd)this.dequeue();return this;}});var queue=function(elem,type,array){if(!elem)return undefined;type=type||"fx";var q=jQuery.data(elem,type+"queue");if(!q||array)q=jQuery.data(elem,type+"queue",array?jQuery.makeArray(array):[]);return q;};jQuery.fn.dequeue=function(type){type=type||"fx";return this.each(function(){var q=queue(this,type);q.shift();if(q.length)q[0].apply(this);});};jQuery.extend({speed:function(speed,easing,fn){var opt=speed&&speed.constructor==Object?speed:{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&easing.constructor!=Function&&easing};opt.duration=(opt.duration&&opt.duration.constructor==Number?opt.duration:{slow:600,fast:200}[opt.duration])||400;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false)jQuery(this).dequeue();if(jQuery.isFunction(opt.old))opt.old.apply(this);};return opt;},easing:{linear:function(p,n,firstNum,diff){return firstNum+diff*p;},swing:function(p,n,firstNum,diff){return((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum;}},timers:[],timerId:null,fx:function(elem,options,prop){this.options=options;this.elem=elem;this.prop=prop;if(!options.orig)options.orig={};}});jQuery.fx.prototype={update:function(){if(this.options.step)this.options.step.apply(this.elem,[this.now,this]);(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);if(this.prop=="height"||this.prop=="width")this.elem.style.display="block";},cur:function(force){if(this.elem[this.prop]!=null&&this.elem.style[this.prop]==null)return this.elem[this.prop];var r=parseFloat(jQuery.css(this.elem,this.prop,force));return r&&r>-10000?r:parseFloat(jQuery.curCSS(this.elem,this.prop))||0;},custom:function(from,to,unit){this.startTime=(new Date()).getTime();this.start=from;this.end=to;this.unit=unit||this.unit||"px";this.now=this.start;this.pos=this.state=0;this.update();var self=this;function t(gotoEnd){return self.step(gotoEnd);}t.elem=this.elem;jQuery.timers.push(t);if(jQuery.timerId==null){jQuery.timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;ithis.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var done=true;for(var i in this.options.curAnim)if(this.options.curAnim[i]!==true)done=false;if(done){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(jQuery.css(this.elem,"display")=="none")this.elem.style.display="block";}if(this.options.hide)this.elem.style.display="none";if(this.options.hide||this.options.show)for(var p in this.options.curAnim)jQuery.attr(this.elem.style,p,this.options.orig[p]);}if(done&&jQuery.isFunction(this.options.complete))this.options.complete.apply(this.elem);return false;}else{var n=t-this.startTime;this.state=n/this.options.duration;this.pos=jQuery.easing[this.options.easing||(jQuery.easing.swing?"swing":"linear")](this.state,n,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update();}return true;}};jQuery.fx.step={scrollLeft:function(fx){fx.elem.scrollLeft=fx.now;},scrollTop:function(fx){fx.elem.scrollTop=fx.now;},opacity:function(fx){jQuery.attr(fx.elem.style,"opacity",fx.now);},_default:function(fx){fx.elem.style[fx.prop]=fx.now+fx.unit;}};jQuery.fn.offset=function(){var left=0,top=0,elem=this[0],results;if(elem)with(jQuery.browser){var parent=elem.parentNode,offsetChild=elem,offsetParent=elem.offsetParent,doc=elem.ownerDocument,safari2=safari&&parseInt(version)<522&&!/adobeair/i.test(userAgent),fixed=jQuery.css(elem,"position")=="fixed";if(elem.getBoundingClientRect){var box=elem.getBoundingClientRect();add(box.left+Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),box.top+Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));add(-doc.documentElement.clientLeft,-doc.documentElement.clientTop);}else{add(elem.offsetLeft,elem.offsetTop);while(offsetParent){add(offsetParent.offsetLeft,offsetParent.offsetTop);if(mozilla&&!/^t(able|d|h)$/i.test(offsetParent.tagName)||safari&&!safari2)border(offsetParent);if(!fixed&&jQuery.css(offsetParent,"position")=="fixed")fixed=true;offsetChild=/^body$/i.test(offsetParent.tagName)?offsetChild:offsetParent;offsetParent=offsetParent.offsetParent;}while(parent&&parent.tagName&&!/^body|html$/i.test(parent.tagName)){if(!/^inline|table.*$/i.test(jQuery.css(parent,"display")))add(-parent.scrollLeft,-parent.scrollTop);if(mozilla&&jQuery.css(parent,"overflow")!="visible")border(parent);parent=parent.parentNode;}if((safari2&&(fixed||jQuery.css(offsetChild,"position")=="absolute"))||(mozilla&&jQuery.css(offsetChild,"position")!="absolute"))add(-doc.body.offsetLeft,-doc.body.offsetTop);if(fixed)add(Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));}results={top:top,left:left};}function border(elem){add(jQuery.curCSS(elem,"borderLeftWidth",true),jQuery.curCSS(elem,"borderTopWidth",true));}function add(l,t){left+=parseInt(l)||0;top+=parseInt(t)||0;}return results;};})(); \ No newline at end of file diff --git a/non-rack-legacy/public/js/mouseapp_2.js b/non-rack-legacy/public/js/mouseapp_2.js new file mode 100755 index 0000000..6ea09a4 --- /dev/null +++ b/non-rack-legacy/public/js/mouseapp_2.js @@ -0,0 +1,913 @@ +// +// Copyright (c) 2008 why the lucky stiff +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +var MouseApp = { + Version: '0.12', + CharCodes: { + 0: ' ', 1: ' ', 9: ' ', + 32: ' ', 34: '"', 38: '&', + 60: '<', 62: '>', 127: '◊', + 0x20AC: '€' + }, + KeyCodes: { + Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 33, PageDown: 34, + End: 35, Home: 36, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 45, + Delete: 46, F1: 112, F2: 113, F3: 114, F4: 115, F5: 116, F6: 117, + F7: 118, F8: 119, F10: 121 + }, + CodeKeys: {}, + Modes: { 1: 'b', 2: 'u', 4: 'i', 8: 'strike' }, + ModeIds: { r: 1, u: 2, i: 4, s: 8 }, + Colors: ['black', 'blue', 'green', + 'cyan', 'red', 'purple', 'brown', + 'gray', 'dark_gray', 'lt_blue', + 'lt_green', 'lt_cyan', 'lt_red', + 'lt_purple', 'yellow', 'white'] +} +//some of these are patently false, because I need to get on a real keyboard-- not a macbook. +if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1){ + MouseApp.KeyCodes = { + Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, + End: 63275, Home: 63273, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 632325, + Delete: 8, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, + F7: 63242, F8: 63243, F10: 63244 + } + +} + +//even though I am tempted to combine chrome and opera into the same if statment, I will refrain for now +// i dont have proper access to a proper keyboard and there might be a single difference between the two +if (navigator.userAgent.indexOf("Opera") > -1){ + MouseApp.KeyCodes = { + Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, + End: 63275, Home: 63273, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 632325, + Delete: 8, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, + F7: 63242, F8: 63243, F10: 63244 + } + +} + +// i am going to comment this out, since this seems un needed. if it past december 15 2009 and this +// is still commented it, please del me +//if ( navigator.appVersion.indexOf('AppleWebKit') > 0 ) { +// MouseApp.KeyCodes = { +// Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, +// End: 63275, Home: 63273, Left: 63234, Up: 63232, Right: 63235, Down: 63233, Insert: 632325, +// Delete: 63272, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, +// F7: 63242, F8: 63243, F10: 63244 +// };// +//} +for ( var k in MouseApp.KeyCodes ) { + MouseApp.CodeKeys[MouseApp.KeyCodes[k]] = k; +} + +MouseApp.isPrintable = function(ch) { + return (ch >= 32); +}; + +MouseApp.Base = function(){}; +MouseApp.Base.prototype = { + setOptions: function(options) { + this.options = { + columns: 72, rows: 24, indent: 2, + title: 'MouseApp', + blinkRate: 500, + ps: '>', + greeting:'%+r Terminal ready. %-r' + } + $.extend(this.options, options || {}); + } +} + +MouseApp.Manager = new Object(); +$.extend(MouseApp.Manager, { + observeTerm: function(term) { + this.activeTerm = term; + if ( this.observingKeyboard ) return; + var mgr = this; + if ( term.input ) { + term.input.keypress(function(e) { mgr.onKeyPress(e) }); + if (!window.opera) term.input.keydown(function(e) { mgr.onKeyDown(e) }); + else window.setInterval(function(){term.input.focus()},1); + } else { + if (!window.opera) $(document).keydown(function(e) { mgr.onKeyDown(e) }); + $(document).keypress(function(e) { mgr.onKeyPress(e) }); + } + this.observingKeyboard = true; + }, + + onKeyDown: function(e) { + e = (e) ? e : ((event) ? event : null); + if ( e && MouseApp.CodeKeys[e.keyCode] ) { + if ( window.event ) { + this.sendKeyPress(e); + } + this.blockEvent(e); + return false; + } + return true; + }, + + onKeyPress: function(e) { + if ( !window.opera && window.event && e.keyCode != 13 && e.keyCode != 8 ) { + e.charCode = e.keyCode; e.keyCode = null; + } + if ( e.keyCode == 191 ) { /* FF 1.0.x sends this upsy quizy -- ignore */ + return; + } + return this.sendKeyPress(e); + }, + + sendKeyPress: function(e) { + var term = MouseApp.Manager.activeTerm; + term.cursorOff(); + b = term.onKeyPress(e); + term.cursorOn(); + return b; + }, + + blockEvent: function (e) { + e.cancelBubble=true; + if (window.event && !window.opera) e.keyCode=0; + if (e.stopPropagation) e.stopPropagation(); + if (e.preventDefault) e.preventDefault(); + } +}); + +/* Basic text window functionality */ +MouseApp.Window = function(element, options) { + this.element = $(element); + this.setOptions(options); + this.initWindow(); +}; + +$.extend(MouseApp.Window.prototype, (new MouseApp.Base()), { + initWindow: function() { + var html = ''; + for ( var i = 0; i < this.options.rows; i++ ) { + html += "
           
          \n"; + } + this.element.html(html); + this.typingOn(); + if (this.options.input) { + this.input = $(this.options.input); + this.input.focus(); + } + MouseApp.Manager.observeTerm(this); + this.clear(); + this.cursorOn(); + this.painting = true; + this.element.css({visibility: 'visible'}); + }, + + text: function() { + var str = ""; + for (var i = 0; i < this.screen.length; i++ ) { + for (var j = 0; j < this.options.columns; j++ ) { + var ch = this.screen[i][j]; + if ( ch[0] != 0 ) { + str += String.fromCharCode(ch[0]); + } + } + } + return str; + }, + + clear: function() { + this.rpos = 0; + this.cpos = 0; + this.screen = []; + this.element.html(''); + this.screen[0] = this.fillRow(this.options.columns, 0); + this.paint(0); + }, + + typingOn: function() { this.typing = true; }, + typingOff: function() { this.typing = false; }, + + cursorOn: function() { + if ( this.blinker ) { + clearInterval( this.blinker ); + } + this.underblink = this.screen[this.rpos][this.cpos][1]; + MouseApp.Manager.activeTerm.blink(); + this.blinker = setInterval(function(){MouseApp.Manager.activeTerm.blink();}, this.options.blinkRate); + this.cursor = true; + }, + + cursorOff: function() { + if ( this.blinker ) { + clearInterval( this.blinker ); + } + if ( this.cursor ) { + this.screen[this.rpos][this.cpos][1] = this.underblink; + this.paint(this.rpos); + this.cursor = false; + } + }, + + blink: function() { + if ( this == MouseApp.Manager.activeTerm ) { + var mode = this.screen[this.rpos][this.cpos][1]; + this.screen[this.rpos][this.cpos][1] = ( mode & 1 ) ? mode & 4094 : mode | 1; + this.paint(this.rpos); + } + }, + + fillRow: function(len, ch, mode) { + ary = [] + for (var i = 0; i < len; i++) { + ary[i] = [ch, mode]; + } + return ary; + }, + + paint: function(start, end) { + if (!this.painting) return; + + if (!end) end = start; + for (var row = start; row <= end && row < this.screen.length; row++) { + var html = ''; + var mode = 0; + var fcolor = 0; + var bcolor = 0; + var spans = 0; + for (var i = 0; i < this.options.columns; i++ ) { + var c = this.screen[row][i][0]; + var m = this.screen[row][i][1] & 15; // 4 mode bits + var f = (this.screen[row][i][1] & (15 << 4)) >> 4; // 4 foreground bits + var b = (this.screen[row][i][1] & (15 << 8)) >> 8; // 4 background bits + if ( m != mode ) { + if ( MouseApp.Modes[mode] ) html += ""; + if ( MouseApp.Modes[m] ) html += "<" + MouseApp.Modes[m] + ">"; + mode = m; + } + if ( ( f != fcolor && f == 0 ) || ( b != bcolor && b == 0 ) ) { + for ( var s = 0; s < spans; s++ ) html += ""; + fcolor = 0; bcolor = 0; + } + if ( f != fcolor ) { + if ( MouseApp.Colors[f] ) { + html += ""; + spans++; + } + fcolor = f; + } + if ( b != bcolor ) { + if ( MouseApp.Colors[b] ) html += ""; + spans++; bcolor = b; + } + html += MouseApp.CharCodes[c] ? MouseApp.CharCodes[c] : String.fromCharCode(c); + } + if ( MouseApp.Modes[mode] ) html += ""; + for ( var s = 0; s < spans; s++ ) html += ""; + var new_id = this.element.attr('id') + '_' + row; + if (!$('#' + new_id).get(0)) { + this.element.append("
           
          "); + this.scrollAllTheWayDown(); + } + $('#' + new_id).html(html); + } + }, + + onAfterKey: function() { + this.scrollAllTheWayDown(); + }, + + highlightLine: function(i) { + if (i >= 0 && i < this.screen.length) + { + $("#" + this.element.attr('id') + "_" + i); + } + }, + + scrollToLine: function(i) { + var p = this.element[0].parentNode; + if ( p.scrollHeight > p.clientHeight ) { + p.scrollTop = (p.scrollHeight - p.clientHeight); + } + }, + + scrollAllTheWayDown: function() { + var p = this.element[0].parentNode; + if ( p.scrollHeight > p.clientHeight ) { + p.scrollTop = (p.scrollHeight - p.clientHeight); + } + }, + + putc: function(ch, mode) { + if ( ch == 13 ) { + return; + } else if ( ch == 10 ) { + this.screen[this.rpos][this.cpos] = [ch, mode]; + this.advanceLine(); + } else { + this.screen[this.rpos][this.cpos] = [ch, mode]; + this.paint(this.rpos); + this.advance(); + } + }, + + zpad: function(n) { + if (n < 10) n = "0" + n; + return n; + }, + + puts: function(str, mode) { + if ( !str ) return; + var p = this.painting; + var r = this.rpos; + this.painting = false; + for ( var i = 0; i < str.length; i++ ) { + this.insertc(str.charCodeAt(i), mode); + } + this.painting = p; + this.paint(r, this.rpos); + }, + + advance: function() { + this.cpos++; + if ( this.cpos >= this.options.columns ) { + this.advanceLine(); + } + }, + + advanceLine: function() { + this.cpos = 0; + this.rpos++; + this.ensureRow(this.rpos); + this.paint(this.rpos, this.screen.length - 1); + }, + + fwdc: function() { + var r = this.rpos; + var c = this.cpos; + if ( c < this.options.columns - 1 ) { + c++; + } else if ( r < this.screen.length - 1 ) { + r++; + c = 0; + } + var ch = (c == 0 ? this.screen[r-1][this.options.columns-1] : this.screen[r][c-1]); + if ( MouseApp.isPrintable(ch[0]) ) { + this.rpos = r; + this.cpos = c; + } + }, + + fwdLine: function() { + if ( this.rpos >= this.screen.length - 1 ) return; + this.rpos++; + while ( this.cpos > 0 && !MouseApp.isPrintable(this.screen[this.rpos][this.cpos - 1][0]) ) { + this.cpos--; + } + }, + + backc: function() { + var r = this.rpos; + var c = this.cpos; + if ( c > 0 ) { + c--; + } else if ( r > 0 ) { + c = this.options.columns - 1; + r--; + } + if ( MouseApp.isPrintable(this.screen[r][c][0]) ) { + this.rpos = r; + this.cpos = c; + return true; + } + return false; + }, + + getTypingStart: function() { + var c = this.cpos; + if ( !MouseApp.isPrintable(this.screen[this.rpos][c][0]) ) { + c--; + } + var pos = null; + for ( var r = this.rpos; r >= 0; r-- ) { + while ( c >= 0 ) { + if ( !MouseApp.isPrintable(this.screen[r][c][0]) ) { + return pos; + } + pos = [r, c]; + c--; + } + c = this.options.columns - 1; + } + }, + + getTypingEnd: function(mod) { + var c = this.cpos; + if ( !MouseApp.isPrintable(this.screen[this.rpos][c][0]) ) { + c--; + } + var pos = null; + for ( var r = this.rpos; r < this.screen.length; r++ ) { + while ( c < this.options.columns ) { + if ( !this.screen[r] || !this.screen[r][c] || !MouseApp.isPrintable(this.screen[r][c][0]) ) { + if (!mod) return pos; + mod--; + } + pos = [r, c]; + c++; + } + c = 0; + } + }, + + getTypingAt: function(start, end) { + var r = start[0]; + var c = start[1]; + var str = ''; + while ( r < end[0] || c <= end[1] ) { + if ( c < this.options.columns ) { + str += String.fromCharCode(this.screen[r][c][0]); + c++; + } else { + c = 0; + r++; + } + } + return str; + }, + + ensureRow: function(r) { + if (!this.screen[r]) { + this.screen[r] = this.fillRow(this.options.columns, 0); + } + }, + + insertc: function(ch, mode) { + var r = this.rpos; var c = this.cpos; + var end = this.getTypingEnd(+1); + if (end) { + var thisc = null; + var lastc = this.screen[this.rpos][this.cpos]; + while ( r < end[0] || c <= end[1] ) { + if ( c < this.options.columns ) { + thisc = this.screen[r][c]; + this.screen[r][c] = lastc; + lastc = thisc; + c++; + } else { + c = 0; + r++; + this.ensureRow(r); + } + } + this.paint(this.rpos, end[0]); + } + this.putc(ch, mode); + }, + + delc: function() { + /* end of line */ + if ( MouseApp.isPrintable(this.screen[this.rpos][this.cpos][0]) ) { + var end = this.getTypingEnd(); + var thisc = null; + var lastc = [0, 0]; + while ( this.rpos < end[0] || this.cpos <= end[1] ) { + if ( end[1] >= 0 ) { + thisc = this.screen[end[0]][end[1]]; + this.screen[end[0]][end[1]] = lastc; + lastc = thisc; + end[1]--; + } else { + end[1] = this.options.columns - 1; + this.paint(end[0]); + end[0]--; + } + } + } + }, + + backspace: function() { + /* end of line */ + if ( !MouseApp.isPrintable(this.screen[this.rpos][this.cpos][0]) ) { + this.backc(); + this.screen[this.rpos][this.cpos] = [0, 0]; + } else { + if ( this.backc() ) this.delc(); + } + }, + + backLine: function() { + if ( this.rpos < 1 ) return; + this.rpos--; + while ( this.cpos > 0 && !MouseApp.isPrintable(this.screen[this.rpos][this.cpos - 1][0]) ) { + this.cpos--; + } + }, + + onKeyPress: function(e) { + var ch = e.keyCode; + var key_name = MouseApp.CodeKeys[ch]; + if (window.opera && !e.altKey && e.keyCode != 13 && e.keyCode != 8) key_name = null; + ch = (e.which || e.charCode || e.keyCode); + if (e.which) ch = e.which; + if (!key_name) { key_name = String.fromCharCode(ch); } + if (e.ctrlKey) { key_name = 'Ctrl' + key_name; } + + // alert([e.keyCode, e.which, key_name, this['onKey' + key_name]]); + if (this.typing && this.onAnyKey) this.onAnyKey(key_name); + if (key_name && this['onKey' + key_name]) { + if (this.typing) this['onKey' + key_name](); + MouseApp.Manager.blockEvent(e); + if (this.typing && this.onAfterKey) this.onAfterKey(key_name, true); + return false; + } + if (!e.ctrlKey) { + if (MouseApp.isPrintable(ch)) { + if (this.typing) this.insertc(ch, 0); + MouseApp.Manager.blockEvent(e); + if (this.typing && this.onAfterKey) this.onAfterKey(key_name, true); + return false; + } + } + if (this.typing && this.onAfterKey) this.onAfterKey(key_name, false); + return true; + }, + onKeyHome: function() { + var s = this.getTypingStart(); + this.rpos = s[0]; this.cpos = s[1]; + }, + onKeyEnd: function() { + var e = this.getTypingEnd(+1); + this.rpos = e[0]; this.cpos = e[1]; + }, + onKeyInsert: function() { }, + onKeyDelete: function() { this.delc(); }, + onKeyUp: function() { this.backLine(); }, + onKeyLeft: function() { this.backc(); }, + onKeyRight: function() { this.fwdc(); }, + onKeyDown: function() { this.fwdLine(); }, + onKeyBackspace: function() { this.backspace(); }, + onKeyEnter: function() { this.insertc(10, 0); }, + onKeyTab: function() { + this.insertc(32, 0); + while (this.cpos % this.options.indent != 0) this.insertc(32, 0); + } +}); + +/* Terminal running moush */ +MouseApp.Terminal = function(element, options) { + this.element = $(element); + this.setOptions(options); + this.initWindow(); + this.setup(); +}; + +$.extend(MouseApp.Terminal.prototype, MouseApp.Window.prototype, { + setup: function() { + this.history = []; + this.backupNum = this.historyNum = this.commandNum = 0; + if (this.onStart) { + this.onStart(); + } else { + this.write(this.options.greeting + "\n", true); + this.prompt(); + } + }, + + prompt: function(ps, pt) { + if (!ps) { + ps = this.options.ps; pt = true; + } + this.write(ps, pt); + this.putc(1, 0); + this.typingOn(); + }, + + getCommand: function() { + var s = this.getTypingStart(); + var e = this.getTypingEnd(); + if (!s || !e) return; + return this.getTypingAt(s, e); + }, + + clearCommand: function() { + var s = this.getTypingStart(); + var e = this.getTypingEnd(); + if (!s || !e) return; + var r = s[0]; + var c = s[1]; + this.rpos = r; this.cpos = c; + while ( r < e[0] || c <= e[1] ) { + if ( c < this.options.columns ) { + this.screen[r][c] = [0, 0]; + c++; + } else { + c = 0; + this.paint(r); + r++; + } + } + this.paint(r); + }, + + write: function(str, pcodes) { + var p = this.painting; + var r = this.rpos; + this.painting = false; + var mode = 0; + var today = new Date(); + for ( var i = 0; i < str.length; i++ ) { + if ( str.substr(i,1) == "\n" ) { + this.advanceLine(); + continue; + } else if ( str.substr(i,1) == "\033" ) { + if ( str.substr(i+1,2) == "[m" ) { + mode = 0; + i += 2; + continue; + } + if ( str.substr(i+1,5) == "[0;0m" ) { + mode = 0; + i += 5; + continue; + } + var colors = str.substr(i+1,7).match(/^\[(\d);(\d+)m/); + if ( colors ) { + var colCode = parseInt( colors[2] ); + var color = colCode % 10; + if ( colors[1] == '1' ) { + color += 8; + } + if ( colCode / 10 == 4 ) { + color = color << 4; + } + mode = (mode & 15) + color << 4; + i += colors[0].length; + continue; + } + } else if ( str.substr(i,1) == '%' && pcodes ) { + var s2 = str.substr(i,2); + switch ( s2 ) { + case '%h': + this.puts(this.options.host, mode); + i++; + continue; + case '%l': + this.puts(this.options.name, mode); + i++; + continue; + case '%n': + this.advanceLine(); + i++; + continue; + case '%s': + this.puts("moush", mode); + i++; + continue; + case '%t': + this.puts(this.zpad(today.getHours()) + ":" + this.zpad(today.getMinutes()) + ":" + + this.zpad(today.getSeconds()), mode); + i++; + continue; + case '%u': + this.puts(this.options.user, mode); + i++; + continue; + case '%v': + this.puts(MouseApp.Version, mode); + i++; + continue; + case '%!': + this.puts(this.historyNum.toString(), mode); + i++; + continue; + case '%#': + this.puts(this.commandNum.toString(), mode); + i++; + continue; + case '%+': + var kind = str.substr(i+2, 1); + if ( MouseApp.ModeIds[kind] ) { + mode = mode | MouseApp.ModeIds[kind]; + i += 2; + continue; + } + break; + case '%-': + var kind = str.substr(i+2, 1); + if ( MouseApp.ModeIds[kind] ) { + mode = mode & ( 4095 - MouseApp.ModeIds[kind] ); + i += 2; + continue; + } + break; + } + } + this.putc(str.charCodeAt(i), mode); + } + this.painting = p; + this.paint(r, this.rpos); + }, + + onKeyUp: function() { + if ( this.backupNum == 0 ) return; + if ( this.backupNum == this.historyNum ) { + this.history[this.historyNum] = this.getCommand(); + } + this.clearCommand(); + this.backupNum--; + this.puts(this.history[this.backupNum]); + }, + onKeyDown: function() { + if ( this.backupNum >= this.historyNum ) return; + this.clearCommand(); + this.backupNum++; + this.puts(this.history[this.backupNum]); + }, + onKeyEnter: function() { + var cmd = this.getCommand(); + if (cmd) { + this.history[this.historyNum] = cmd; + this.backupNum = ++this.historyNum; + } + this.commandNum++; + this.advanceLine(); + if (cmd) { + var str = this.onCommand(cmd); + if (str) { + if ( str.substr(str.length - 1, 1) != "\n" ) { + str += "\n"; + } + this.write(str); + } + } + this.prompt(); + }, + onCommand: function(line) { + // this.puts("Echoing: " + line + "\n"); + if ( line == "clear" ) { + this.clear(); + } else { + return "\033[1;37m\033[0;44mYou typed:\033[m " + line; + } + } +}); + +/* Notepad sort of editor */ +MouseApp.Notepad = function(element, options) { + this.element = $(element); + this.setOptions(options); + this.initWindow(); + this.history = []; + this.lineno = 0; +}; + +$.extend(MouseApp.Notepad.prototype, MouseApp.Window.prototype, { + csave: function() { + if ( this.cpos_save ) { + this.cpos = this.cpos_save; + } else { + this.cpos_save = this.cpos; + } + }, + onKeyUp: function() { if ( this.rpos < 1 ) { return; } this.csave(); this.backLine(); }, + onKeyDown: function() { if ( this.rpos < this.screen.length - 1 ) { this.csave(); this.fwdLine(); } }, + onAfterKey: function(key, st) { + if ( st && !(key == 'Up' || key == 'Down') ) { + this.cpos_save = null; + } + }, + insertc: function(ch, mode) { + if (ch == 10) { + this.element.append("
           
          "); + this.screen.splice(this.rpos + 1, 0, this.fillRow(this.options.columns, 0)); + var c = this.cpos; var c2 = 0; + while (c < this.options.columns) + { + if (this.screen[this.rpos][c] == 0) break; + this.screen[this.rpos + 1][c2] = this.screen[this.rpos][c]; + this.screen[this.rpos][c] = [0, 0]; + c++; c2++; + } + this.paint(this.rpos); + if (MouseApp.isPrintable(this.screen[this.rpos][c])) + { + var r = this.rpos; var c = this.cpos; + this.rpos += 1; this.cpos = c2; + this.delc(); + this.rpos = r; this.cpos = c; + } + this.putc(ch, mode); + if (this.rpos == this.screen.length - 1) + this.scrollAllTheWayDown(); + } else { + var c = this.cpos + 1; + var lastc = this.screen[this.rpos][this.cpos]; + this.putc(ch, mode); + for ( var r = this.rpos; r < this.screen.length; r++ ) { + while (c < this.options.columns) + { + var tmpc = this.screen[r][c]; + if (lastc[0] == 0) + break; + this.screen[r][c] = lastc; + lastc = tmpc; + c++; + } + if (c < this.options.columns) { + break; + } + c = 0; + } + } + }, + + backc: function() { + var r = this.rpos; + var c = this.cpos - 1; + for ( var r = this.rpos; r >= 0; r-- ) { + while ( c >= 0 ) { + this.rpos = r; + this.cpos = c; + if ( this.screen[r][c][0] != 0 ) { + this.paint(r); + return true; + } + this.screen[r][c] = [0, 0]; + c--; + } + c = this.options.columns - 1; + } + return false; + }, + delc: function() { + var c = this.cpos + 1; + for ( var r = this.rpos; r < this.screen.length; r++ ) { + while ( c < this.options.columns ) { + if ( this.screen[r][c][0] != 0 ) { + break; + } + c++; + } + if ( c < this.options.columns ) break; + c = 0; + } + + if (r >= this.screen.length) return; + + var r2 = this.rpos; + var c2 = this.cpos; + for ( var r2 = this.rpos; r2 < this.screen.length; r2++ ) { + while (c2 < this.options.columns) + { + if (this.screen[r][c][0] == 0) + break; + this.screen[r2][c2] = this.screen[r][c]; + c2++; + c++; + if (c >= this.options.columns) { + r++; + if (r >= this.options.rows) break; + c = 0; + } + } + if (c2 < this.options.columns) { + while (c2 < this.options.columns) { + this.screen[r2][c2] = [0, 0]; + c2++; + } + break; + } + c2 = 0; + } + + if (r != r2 && r < this.screen.length) + { + this.screen.splice(r, 1); + $("#" + this.element.attr('id') + "_" + this.screen.length).remove(); + } + this.paint(this.rpos, this.screen.length); + }, + onKeyBackspace: function() { + if (this.backc()) this.delc(); + } + +}); diff --git a/non-rack-legacy/public/js/mouseirb_2.js b/non-rack-legacy/public/js/mouseirb_2.js new file mode 100755 index 0000000..0fa5f12 --- /dev/null +++ b/non-rack-legacy/public/js/mouseirb_2.js @@ -0,0 +1,179 @@ +// +// Copyright (c) 2008 why the lucky stiff +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// + +/* Irb running moush */ +MouseApp.Irb = function(element, options) { + this.element = $(element); + this.setOptions(options); + this.showHelp = this.options.showHelp; + if ( this.options.showChapter ) { + this.showChapter = this.options.showChapter; + } + if ( this.options.init ) { + this.init = this.options.init; + } + this.initWindow(); + this.setup(); + this.helpPage = null; + this.irbInit = false; +}; + +$.extend(MouseApp.Irb.prototype, MouseApp.Terminal.prototype, { + cmdToQuery: function(cmd) { + return "cmd=" + escape(cmd.replace(/</g, '<').replace(/>/g, '>'). + replace(/&/g, '&').replace(/\r?\n/g, "\n")).replace(/\+/g, "%2B"); + }, + + fireOffCmd: function(cmd, func) { + var irb = this; + if (!this.irbInit) + { + $.ajax({url: this.options.irbUrl + "?" + this.cmdToQuery("!INIT!IRB!"), type: "GET", + complete: (function(r) { irb.irbInit = true; irb.fireOffCmd(cmd, func); })}); + } + else + { + $.ajax({url: this.options.irbUrl + "?" + this.cmdToQuery(cmd), type: "GET", + complete: func}); + } + }, + + reply: function(str) { + var raw = str.replace(/\033\[(\d);(\d+)m/g, ''); + this.checkAnswer(raw); + if (!str.match(/^(\.\.)+$/)) { + if ( str[str.length - 1] != "\n" ) { + str += "\n"; + } + js_payload = /\033\[1;JSm(.*)\033\[m/; + js_in = str.match(js_payload); + if (js_in) { + try { + js_in = eval(js_in[1]); + } catch (e) {} + str = str.replace(js_payload, ''); + } + var pr_re = new RegExp("(^|\\n)=>"); + if ( str.match( pr_re ) ) { + str = str.replace(new RegExp("(^|\\n)=>"), "$1\033[1;34m=>\033[m"); + } else { + str = str.replace(new RegExp("(^|\\n)= (.+?) ="), "$1\033[1;33m$2\033[m"); + } + this.write(str); + this.prompt(); + } else { + this.prompt("\033[1;32m" + ".." + "\033[m", true); + this.puts(str.replace(/\./g, ' '), 0); + } + }, + + setHelpPage: function(n, page) { + if (this.helpPage) + $(this.helpPage.ele).hide('fast'); + this.helpPage = {index: n, ele: page}; + match = this.scanHelpPageFor('load'); + if (match != -1) + { + this.fireOffCmd(match, (function(r) { + $(page).show('fast'); + })); + } + else + { + $(page).show('fast'); + } + }, + + scanHelpPageFor: function(eleClass) { + match = $("div." + eleClass, this.helpPage.ele); + if ( match[0] ) return match[0].innerHTML; + else return -1; + }, + + checkAnswer: function(str) { + if ( this.helpPage ) { + match = this.scanHelpPageFor('answer'); + if ( match != -1 ) { + if ( str.match( new RegExp('^\s*=> ' + match + '\s*$', 'm') ) ) { + this.showHelp(this.helpPage.index + 1); + } + } else { + match = this.scanHelpPageFor('stdout'); + if ( match != -1 ) { + if ( match == '' ) { + if ( str == '' || str == null ) this.showHelp(this.helpPage.index + 1); + } else if ( str.match( new RegExp('^\s*' + match + '$', 'm') ) ) { + this.showHelp(this.helpPage.index + 1); + } + } + } + } + }, + + onKeyCtrld: function() { + this.clearCommand(); + this.puts("reset"); + this.onKeyEnter(); + }, + + onKeyEnter: function() { + this.typingOff(); + var cmd = this.getCommand(); + if (cmd) { + this.history[this.historyNum] = cmd; + this.backupNum = ++this.historyNum; + } + this.commandNum++; + this.advanceLine(); + if (cmd) { + if ( cmd == "clear" ) { + this.clear(); + this.prompt(); + } else if ( cmd.match(/^(back)$/) ) { + if (this.helpPage && this.helpPage.index >= 1) { + this.showHelp(this.helpPage.index - 1); + } + this.prompt(); + } else if ( cmd.match(/^(next)$/) ) { + if (this.helpPage) { + this.showHelp(this.helpPage.index + 1); + } + this.prompt(); + } else if ( cmd.match(/^(help|wtf\?*)$/) ) { + this.showHelp(1); + this.prompt(); + } else if ( regs = cmd.match(/^(help|wtf\?*)\s+#?(\d+)\s*$/) ) { + this.showChapter(parseInt(regs[2])); + this.prompt(); + } else { + var term = this; + this.fireOffCmd(cmd, (function(r) { term.reply(r.responseText ? r.responseText : ''); })); + } + } else { + this.prompt(); + } + } +}); + diff --git a/non-rack-legacy/public/keypress_test.html b/non-rack-legacy/public/keypress_test.html new file mode 100644 index 0000000..7297c4d --- /dev/null +++ b/non-rack-legacy/public/keypress_test.html @@ -0,0 +1,37 @@ + + + + + + + + + +

          Press a key, the details will be displayed below

          +
          + + + diff --git a/non-rack-legacy/public/moods/index.html b/non-rack-legacy/public/moods/index.html new file mode 100755 index 0000000..e933af9 --- /dev/null +++ b/non-rack-legacy/public/moods/index.html @@ -0,0 +1,8 @@ + + + + + +

          you shouldn't be here.. kicking you out!

          + + diff --git a/non-rack-legacy/public/moods/sick.gif b/non-rack-legacy/public/moods/sick.gif new file mode 100755 index 0000000000000000000000000000000000000000..217a67cbae60740fdc90b92e06b977cf7fc56699 GIT binary patch literal 94 zcmZ?wbhEHb|6B#{self.text}" + end + + end + + class Link + attr_accessor :text, :target + def initialize(text, target) + self.text, self.target = text, target + end + def generate_html + "#{text}" + end + + + end + + class List + attr_accessor :elements + def initialize(elements) + self.elements = elements + end + + def generate_html + items = elements.map do |elem| + text = elem.instance_of?(Paragraph) ? elem.text : elem.generate_html + "
        2. #{text}
        3. " + end.join(" ") + + "
            #{items}
          " + end + end + + + class Paragraph + attr_accessor :text + def initialize(text) + self.text = text + end + + def generate_html + "

          #{self.text}

          " + end + end + + + class ComplexPopup + attr_reader :elements + def initialize + @elements = [] + end + + (1..6).each do |n| + define_method "h#{n}".to_sym do |text| + @elements << Header.new(n, text) + end + end + + + # def h1 text + # @elements << Header.new(1, text) + # end + + def link(text, target) + @elements << Link.new(text, target) + end + + def p(text) + @elements << Paragraph.new(text) + end + + def list(&block) + lst = ComplexPopup.new + lst.instance_eval(&block) + @elements << List.new(lst.elements) + end + + def generate_html() + @elements.map(&:generate_html).join(" ") + end + + + + end + + + def self.make(&block) + result = ComplexPopup.new + result.instance_eval(&block) + + html = result.generate_html.gsub('\\', '\\\\').gsub('"', '\"') + command = "window.irb.options.popup_make(\"#{html}\")" + TryRuby::Output.javascript command + end + +end diff --git a/non-rack-legacy/public/setup.rb b/non-rack-legacy/public/setup.rb new file mode 100644 index 0000000..10c1a39 --- /dev/null +++ b/non-rack-legacy/public/setup.rb @@ -0,0 +1,67 @@ +module TryRuby +SetupCode = < p:first-child{ + margin-top:0; +} +#facebox .content > p:last-child{ + margin-bottom:0; +} + +#facebox .close{ + position:absolute; + top:5px; + right:5px; + padding:2px; + background:#fff; +} +#facebox .close img{ + opacity:0.3; +} +#facebox .close:hover img{ + opacity:1.0; +} + +#facebox .loading { + text-align: center; +} + +#facebox .image { + text-align: center; +} + +#facebox img { + border: 0; + margin: 0; +} + +#facebox_overlay { + position: fixed; + top: 0px; + left: 0px; + height:100%; + width:100%; +} + +.facebox_hide { + z-index:-100; +} + +.facebox_overlayBG { + background-color: #000; + z-index: 99; +} +.facebox-footnote{ + margin-top:40px; +} \ No newline at end of file diff --git a/non-rack-legacy/public/stylesheets/reset.css b/non-rack-legacy/public/stylesheets/reset.css new file mode 100644 index 0000000..d709810 --- /dev/null +++ b/non-rack-legacy/public/stylesheets/reset.css @@ -0,0 +1,46 @@ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, font, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td { + margin: 0; + padding: 0; + border: 0; + outline: 0; + font-weight: inherit; + font-style: inherit; + font-size: 100%; + font-family: inherit; + vertical-align: baseline; +} +/* remember to define focus styles! */ +:focus { + outline: 0; +} +body { + line-height: 1; + color: black; + background: white; +} +ol, ul { + list-style: none; +} +/* tables still need 'cellspacing="0"' in the markup */ +table { + border-collapse: separate; + border-spacing: 0; +} +caption, th, td { + text-align: left; + font-weight: normal; +} +blockquote:before, blockquote:after, +q:before, q:after { + content: ""; +} +blockquote, q { + quotes: "" ""; +} diff --git a/non-rack-legacy/public/stylesheets/scaffold.css b/non-rack-legacy/public/stylesheets/scaffold.css new file mode 100644 index 0000000..1ae7000 --- /dev/null +++ b/non-rack-legacy/public/stylesheets/scaffold.css @@ -0,0 +1,56 @@ +body { background-color: #fff; color: #333; } + +body, p, ol, ul, td { + font-family: verdana, arial, helvetica, sans-serif; + font-size: 13px; + line-height: 18px; +} + +pre { + background-color: #eee; + padding: 10px; + font-size: 11px; +} + +a { color: #000; } +a:visited { color: #666; } +a:hover { color: #fff; background-color:#000; } + +div.field, div.actions { + margin-bottom: 10px; +} + +#notice { + color: green; +} + +.field_with_errors { + padding: 2px; + background-color: red; + display: table; +} + +#error_explanation { + width: 450px; + border: 2px solid red; + padding: 7px; + padding-bottom: 0; + margin-bottom: 20px; + background-color: #f0f0f0; +} + +#error_explanation h2 { + text-align: left; + font-weight: bold; + padding: 5px 5px 5px 15px; + font-size: 12px; + margin: -7px; + margin-bottom: 0px; + background-color: #c00; + color: #fff; +} + +#error_explanation ul li { + font-size: 12px; + list-style: square; +} diff --git a/non-rack-legacy/public/stylesheets/site.css b/non-rack-legacy/public/stylesheets/site.css new file mode 100755 index 0000000..62b1526 --- /dev/null +++ b/non-rack-legacy/public/stylesheets/site.css @@ -0,0 +1,378 @@ +body { + font-family: verdana, arial, sans-serif; + font-size: 14px; + text-align: center; +} +h1, h2, h3, h4 { + font-family: georgia, serif; + margin: 10px 45px; padding: 0; +} +h1 { + color: #333; + font-size: 48px; + font-weight: normal; + margin: 10px 0px; +} +h3 { + color: white; + font-size: 21px; + font-weight: normal; +} +a,a:link,a:visited { + text-decoration: none; + color: #57ad11; +} +a:hover { + text-decoration: underline; + color: #57ad11; +} +a:active { + text-decoration: underline; + color: #dddddd; +} +input.keyboard-selector-input { + position: fixed; + top: 0; + _position: absolute; + _top: expression(eval(document.body.scrollTop)); + left: -300px; +} +.container { + width: 678px; + margin: 0 auto; + text-align: left; +} +.content { + width: 712px; + background: url(/images/tile.png) repeat-y; +} +#lilBrowser { + position: absolute; + background-color: white; + top: -540px; + left: -440px; + width: 510px; + height: 430px; + padding: 5px; + border: solid 1px #444; + z-index: 100; +} +h3#lbTitle { + color: #444; + font-family: verdana, arial, sans-serif; + font-size: small; + float:left; + line-height: 90%; + margin: 0; padding: 3px; +} +p#lbClose { + font-size: small; + float: right; + margin: 0; padding: 3px; +} +p#lbClose a { + display: inline; +} +.shellwin { + width: 712px; + padding-left: 12px; + background: url(/images/background.png) no-repeat; +} + +/* tutorial panes */ +.stretcher { + color: #f1f1ff; + display: none; + margin: 0; + padding: 0; + padding-left: 12px; + background: url(/images/tile.png) repeat-y; +} +.stretcher a, .stretcher a:link, .stretcher a:visited, .stretcher a:active { + text-decoration: none; + color: #a7ed91; +} +.stretcher a:hover { + text-decoration: underline; + color: #b7fd91; +} +.stretcher p { + margin: 10px 16px; +} +.stretcher dl, .stretcher ul { + background-color: white; + color: #333; + padding: 4px 8px; + font-size: 12px; + margin-left: 16px; + list-style: none; +} +.stretcher li { + margin: 6px; +} +.stretcher p code { + background-color: #874a20; + color: #fedeec; + padding: 1px 4px; +} +.stretcher p code.cmd { + background-color: #eeeeec; + color: #204a87; +} +.stretcher dt { + font-weight: bold; +} + +.chapmark { + padding: 6px 0; + margin-left: 12px; + margin-right: 22px; + color: #553; + background: #efefe1; +} +.chapmark h3 { + color: #335; +} +.chapmark a, .chapmark a:link, .chapmark a:visited, .chapmark a:active { + text-decoration: none; + color: #372d61; +} +.chapmark a:hover { + text-decoration: underline; + color: #477d51; +} +.note { color: #ddc; text-align: center; font-size: xx-small; } +ul li strong { color: #286; border-bottom: solid 2px #cca; } +ul li code { background-color: #f1f1f1; padding: 1px 3px; border-bottom: solid 2px #ddd; } +ul li code.faded { color: #899; } +code strong { background-color: #dcffb9; padding: 1px 3px; } +ul.commands li strong { display: block; float: left; width: 60px; border: none; } + +/* irb terminal */ +.terminal { + background-color: #ffffff; + border: solid 1px #204a87; + width: 678px; + height: 240px; + overflow: auto; +} +.console { + padding: 4px; margin-left: -50px; + font-family: "Andale Mono", courier, fixed, monospace; + font-size: 14px; + line-height: 16px; + color: #204a87; + text-align: left; + width: 664px; + height:220px; +} + +.console div b { + background-color: #874a20; + color: #fedeac; +} +div.answer, div.stdout, div.no_answer, div.load { + display: none; +} + +/* terminal escape colors */ +span.fore_black { color: #2e3436; } +span.fore_dark_gray { color: #888a85; } +span.fore_gray { color: #babdb6; } +span.fore_white { color: #eeeeec; } +span.fore_blue { color: #204a87; } +span.fore_lt_blue { color: #729fcf; } +span.fore_green { color: #788600; font-weight: bold; } +span.fore_lt_green { color: #cbe134; } +span.fore_cyan { color: #c4a000; } /* using cyan for yellows */ +span.fore_lt_cyan { color: #fc994f; } +span.fore_red { color: #a40000; } +span.fore_lt_red { color: #ef2929; font-weight: bold; } +span.fore_purple { color: #5c3566; } +span.fore_lt_purple { color: #ad7fa8; } +span.fore_brown { color: #8f5972; } +span.fore_lt_brown { color: #b9b9de; } +span.back_black { background-color: #2e3436; } +span.back_dark_gray { background-color: #888a85; } +span.back_gray { background-color: #babdb6; } +span.back_white { background-color: #eeeeec; } +span.back_blue { background-color: #204a87; } +span.back_lt_blue { background-color: #729fcf; } +span.back_green { background-color: #788600; } +span.back_lt_green { background-color: #cbe134; } +span.back_cyan { background-color: #c4a000; } /* using cyan for yellows */ +span.back_lt_cyan { background-color: #fce94f; } +span.back_red { background-color: #a40000; } +span.back_lt_red { background-color: #ef2929; } +span.back_purple { background-color: #5c3566; } +span.back_lt_purple { background-color: #ad7fa8; } +span.back_brown { background-color: #8f5902; } +span.back_lt_brown { background-color: #b9b96e; } + +/** no ways***/ + +div.main-wrapper-bottom { + height:4px;background-position: 0px -80px; background-repeat: no-repeat; + font-size:0 /* IE6, go figure */ +} +div.main-wrapper-borders { + background-position: -1731px 0; padding:15px; + background-repeat:repeat-y; +} +div.console-wrapper { + margin:0px auto ;width:566px; + cursor:text; + font-family:monospace; +} +div.console-wrapper-top { + height:3px;background-position: -50px -48px; background-repeat: no-repeat; + font-size:0 /* IE6, go figure */ +} +div.console-wrapper-bottom { + height:3px;background-position: -50px -51px; background-repeat: no-repeat; + font-size:0 /* IE6, go figure */ +} +div.console-wrapper-borders { + background-position: 0px 0px; padding:1px; + background-repeat:repeat-y; +} +div.guide-wrapper { + color:#fff; width:566px;margin-left:2px +} +div.guide-wrapper-top { + height:4px;background-position: 0 -65px; + font-size:0 /* IE6, go figure */ +} +div.guide-wrapper-bottom { + height:4px;background-position: 0 -70px; + font-size:0 /* IE6, go figure */ +} +div.guide-wrapper-borders { + background-position: -1166px 0px;padding:15px; + background-repeat:repeat-y; +} + +div.footer-wrapper-borders { + background-position: -566px 0px; padding:10px; + background-repeat:repeat-y; + font-size:12px +} +h1.main-header { + text-indent:-9999px; background-position: -49px 0px; + background-repeat: no-repeat; + width:318px; height:48px; margin-bottom:20px; + float:left +} + +div.footer { + line-height: 1.3em; +} + div.console div.jquery-console-inner +{ height:100%; overflow:auto; background:white} +div.console div.jquery-console-prompt-box +{ color:#437375; font-family:monospace; margin-top:0.5em; } +div.console div.jquery-console-prompt-box .prompt-done +{ cursor: pointer } +div.console div.jquery-console-prompt-box .prompt-done:hover +{ background:#453D5B; color: white; } +div.console div.jquery-console-focus span.jquery-console-cursor +{ background:#666; color:#fff; } +div.console div.jquery-console-message-error { + color:#ef0505; font-family:sans-serif; font-weight:bold; + padding-top:0.25em +} +div.console div.jquery-console-message-value +{ color:#000; font-family:monospace;padding-top:0.25em; font-weight: bold; } +div.console div.jquery-console-message-type +{ color:#382567; font-family:monospace;padding-left:0em;padding-top:0.25em; font-size:.9em } +div.console span.jquery-console-prompt-label { font-weight:bold } +div.console div.jquery-console-welcome { font-family:"DejaVu Sans",sans-serif; } + +div.share-wrapper { font-size:12px;padding:10px 0em 0em 10px } +div.share-wrapper strong { font-weight: bold } + +.clearfix:after { content:"."; display:block; height:0; clear:both; visibility:hidden } +div.menu { + float:right; + margin-right:2px; + margin-top:40px; + margin-bottom:5px +} +a.reset-btn { + float:left; + display:block; + width:59px; + height:24px; + background-position: -427px -18px; background-repeat: no-repeat; +} +a.reset-btn span { display:none } + +div.clear { clear:both } + + +div.console-wrapper .notice { + position:absolute; + bottom:0;right:0; + margin:1px; + background:#eee; + color:black; + padding:10px; + font-size:12px; + font-family:sans-serif; + font-weight:bold; +} +p.ajax-loader { background:url(../images/ajax-loader.gif); width:16px; height:16px;text-indent:-9999px } + +.notice a { padding:3px;background:#333;color:white} +.notice .action { text-align: right } + +/* Support Try Ruby! */ + + +a.trigger{ +position: absolute; +text-decoration: none; +top: 80px; right: 0; +font-size: 14px; +letter-spacing:-1px; +font-family: verdana, helvetica, arial, sans-serif; +color:#fff; +padding: 10px 10px 10px 10px; +font-weight: 500; +background:#333333 url(images/plus.png) 15% 55% no-repeat; +border:1px solid #444444; +-moz-border-radius-topleft: 20px; +-webkit-border-top-left-radius: 20px; +-moz-border-radius-bottomleft: 20px; +-webkit-border-bottom-left-radius: 20px; +-moz-border-radius-bottomright: 0px; +-webkit-border-bottom-right-radius: 0px; +display: block; +} + +a.trigger:hover{ +position: absolute; +text-decoration: none; +top: 80px; right: 0; +font-size: 14px; +letter-spacing:-1px; +font-family: verdana, helvetica, arial, sans-serif; +color:#fff; +padding: 10px 10px 10px 10px; +font-weight: 500; +background: green; +border:1px solid #444444; +-moz-border-radius-topleft: 20px; +-webkit-border-top-left-radius: 20px; +-moz-border-radius-bottomleft: 20px; +-webkit-border-bottom-left-radius: 20px; +-moz-border-radius-bottomright: 0px; +-webkit-border-bottom-right-radius: 0px; +display: block; +} + +a.active.trigger { +background:#222222 url(images/minus.png) 15% 55% no-repeat; +} + + \ No newline at end of file diff --git a/non-rack-legacy/public/test.rb b/non-rack-legacy/public/test.rb new file mode 100755 index 0000000..8810c18 --- /dev/null +++ b/non-rack-legacy/public/test.rb @@ -0,0 +1,633 @@ +#!/usr/bin/env ruby +require 'test/unit' +require 'rexml/document' +require 'hpricot' +load 'tryruby_runner.rb' + +class Integer + def weeks + self * 7*24*60*60 + end +end + + +def run_script(session,line) + session << line +end + +class TryRubyTestSession < TryRubyBaseSession + def initialize + reset + @current_includes = [] + end + + attr_accessor :start_time, :current_statement + attr_accessor :nesting_level, :past_commands, :current_includes +end + +$session = nil + +# This tests the TryRubyBaseSession#calculate_nesting_level function +class NestingLevelTest < Test::Unit::TestCase + def test_finished_statement_should_return_0 + t = TryRubyBaseSession.new + assert_equal(0, t.calculate_nesting_level("42")) + end + + def test_missing_end_should_return_1 + t = TryRubyBaseSession.new + assert_equal(1, t.calculate_nesting_level("3.times do")) + end + + def test_missing_close_brace_should_return_1 + t = TryRubyBaseSession.new + assert_equal(1, t.calculate_nesting_level("3.times {")) + end + + def test_open_class_should_return_1 + t = TryRubyBaseSession.new + assert_equal(1, t.calculate_nesting_level("class BlogEntry")) + end + + def test_closed_class_should_return_0 + t = TryRubyBaseSession.new + assert_equal(0, t.calculate_nesting_level("class BlogEntry\nend")) + end + + def test_2_unclosed_dos_should_return_2 + t = TryRubyBaseSession.new + assert_equal(2, t.calculate_nesting_level("3.times do\n4.times do")) + end + + def test_mix_of_opened_statements + t = TryRubyBaseSession.new + test_str = <<-EOF + class MyClass + def mymethod + 3.times do + 8.times { + EOF + assert_equal(4, t.calculate_nesting_level(test_str)) + end + + def test_open_and_close_on_same_line_should_return_0 + t = TryRubyBaseSession.new + assert_equal(0, t.calculate_nesting_level("3.times { puts 'lol' }")) + assert_equal(0, t.calculate_nesting_level("3.times do |v| puts 'lol'; end")) + end + + def test_half_statement + t = TryRubyBaseSession.new + assert_equal(1, t.calculate_nesting_level('true and')) + assert_equal(1, t.calculate_nesting_level('amethod(')) + end + +end + + +class TryRubyTest < Test::Unit::TestCase + # a test helper that simplifies testing the tryruby interpretor. + # It takes one optional argument session, which is the session to use for + # the test. + # It then takes a block. In the block a method input is available which is used + # to send a line to the interpretor and test the output. + # + # input takes one mandatory argument, the line, and some optional args: + # - output: The output of line should match this (defaults to "") + # - javascript: The line generated a javascript function, and should match this + # - error: The line generated an error and should match this + # - result: The line didn't generate an error or javascript, and should match this + # (defaults to nil if not supplied) + # - line_continuation: The line didn't complete, the current indent level + # should be equal to this (use true if you aren't interested in testing this) + # output, error, javascript and result can take either a: + # - Class: Tests if is the given type + # - Proc: Proc should take one param (the ) and run assertions with that value + # - Regexp: Tests (a string) against the regexp + # - : should equal + def tryruby_session(session = TryRubyTestSession.new, &block) + input_o = TryRubySession_Input.new + input_o.session = session + input_o.test = self + input_o.instance_eval(&block) + + end + + + def test_lesson1 + tryruby_session do + input '2 + 6' , result: 8 + input '"Jimmy"' , result: "Jimmy" + input '"Jimmy".reverse' , result: "ymmiJ" + input '"Jimmy".length' , result: 5 + input '"Jimmy" * 5' , result: "JimmyJimmyJimmyJimmyJimmy" + end + end + + # tests statements that should end with a line continuation + def test_line_continuations + tryruby_session do + input '3.times do |v|' , line_continuation: 1 + input '3.times { |v|', line_continuation: 2 + input '}; end', result: Proc.new {true} + input 'class MyClass', line_continuation: 1 + input "def mymethod", line_continuation: 2 + input "end; end", result: Proc.new{true} + end + end + + def test_lines_with_semicolons + tryruby_session do + input '3; 4', result: 4 + input 'puts "hello"; a = 4; 5', output: "hello\n", result: 5 + input 'a', result: 4 + input '; 42', result: 42 + end + end + + + def test_errors + tryruby_session do + input 'asdf', error: NameError, output: "" + input 'print "hello"; asdf', error: NameError, output: "hello" + end + end + + # tests statements that shouldn't end with a line continuation + def test_shouldnt_have_line_continuation + tryruby_session do + input "'helloclassend'", result: "helloclassend" + input "3.class", result: Class + end + end + + def test_illegal_ops + $session = TryRubyTestSession.new + tryruby_session $session do + input '`cat /etc/passwd`', illegal: true + input 'require "popup"', result: Proc.new{} + input '%x(cat /etc/passwd)', illegal: true + end + end + + + def test_lesson2 + tryruby_session do + input '40.reverse', error: NoMethodError + input '40.to_s.reverse', result: "04" + input '[]', result: [] + input '[12,47,35]', result: [12,47,35] + input '[12,47,35].max', result: 47 + input 'ticket = [12,47,35]', result: [12,47,35] + input 'ticket', result: [12,47,35] + input 'ticket.sort!', result: [12,35,47] + end + end + + def test_lesson3 + poem = <<-EOF +My toast has flown from my hand +And my toast has gone to the +moon. +But when I saw it on television, +Planting our flag on Halley's +comet, +More still did I want to eat it. +EOF + + tryruby_session do + # the below line should be done automatically by the interpretor + # when help 3 is loaded + # input "poem = #{poem.inspect}", result: Proc.new{} + + input 'print poem', output: poem + input "poem['toast'] = 'honeydew'", result: "honeydew" + input 'print poem', output: (poem['toast'] = 'honeydew'; poem) + input 'poem.reverse', result: poem.reverse + input 'poem.lines.to_a.reverse', result: poem.lines.to_a.reverse + input 'print poem.lines.to_a.reverse.join', output: poem.lines.to_a.reverse.join + end + end + + def test_lesson4 + tryruby_session do + input 'books = {}', result: {} + + input 'books["Gravity\'s Rainbow"] = :splendid', + result: :splendid + + input 'books["a"] = :mediocre', result: :mediocre + input 'books["b"] = :mediocre', result: :mediocre + input 'books["c"] = :mediocre', result: :mediocre + input 'books.length', result: 4 + input 'books["Gravity\'s Rainbow"]', result: :splendid + input 'books.keys', result: ["Gravity's Rainbow", "a", "b", "c"] + input 'ratings = Hash.new {0}', result: {} + + input 'books.values.each { |rate| ratings[rate] += 1 }', + result: [:splendid, :mediocre, :mediocre, :mediocre] + + input '5.times {print "Odelay!" }', + result: 5, + output: 'Odelay!Odelay!Odelay!Odelay!Odelay!' + + end + end + + def test_lesson5 + tryruby_session do + input 'Dir.entries "/"', + result: [".", "..", "Home", "Libraries", "MouseHole", "Programs", "Tutorials", + "comics.txt"] + input 'Dir["/*.txt"]', result: ["/comics.txt"] + comics_txt_text = <", value.inspect + } + input 'File.mtime("/Home/comics.txt")', result: Time + input 'File.mtime("/Home/comics.txt").hour', result: Fixnum + end + + end + + def test_lesson6 + $session = TryRubyTestSession.new + tryruby_session $session do + input 'def load_comics( path )', line_continuation: 1 + input 'comics = {}', line_continuation: 1 + input 'File.foreach(path) do |line|', line_continuation: 2 + input "name, url = line.split(': ')", line_continuation: 2 + input 'comics[name] = url.strip', line_continuation: 2 + input 'end', line_continuation: 1 + input 'comics', line_continuation: 1 + input 'end', result: nil + + input "comics = load_comics('/comics.txt')", result: + {"Achewood"=>"http://achewood.com/", + "Dinosaur Comics"=>"http://qwantz.com/", + "Perry Bible Fellowship"=>"http://cheston.com/pbf/archive.html" , + "Get Your War On"=>"http://mnftiu.cc/"} + + input "require 'popup'", result: Proc.new {} + input 'Popup.goto "http://google.com/"', + javascript: "window.irb.options.popup_goto(\"http://google.com/\")" + + input 'Popup.make {', line_continuation: 1 + input 'h1 "My Links"', line_continuation: 1 + input 'link "Go to Google", "http://google.com/"', line_continuation: 1 + input '}', javascript: + "window.irb.options.popup_make" + + "(\"

          My Links

          " + + "Go to Google\")" + + input 'Popup.make do', line_continuation: 1 + input 'h1 "Things To Do"', line_continuation: 1 + input 'list do', line_continuation: 2 + input 'p "Try out Ruby"', line_continuation: 2 + input 'p "Ride a tiger"', line_continuation: 2 + input 'p "(down River Euphrates)"', line_continuation: 2 + input 'end', line_continuation: 1 + expected = <Things To Do +
          • Try out Ruby
          • +
          • Ride a tiger
          • +
          • (down River Euphrates) +
          ") +EOF + input 'end', javascript: expected.gsub("\n", "") + +input 'Popup.make do', line_continuation: 1 +input 'h1 "Comics on the Web"', line_continuation: 1 +input 'list do', line_continuation: 2 +input 'comics.each do |name, url|', line_continuation: 3 +input 'link name, url', line_continuation: 3 +input 'end', line_continuation: 2 +input 'end', line_continuation: 1 +input 'end', javascript: Proc.new { |v| + matches = v.match(/^window.irb.options.popup_make\("(.*)"\)/) + assert_not_nil(matches) + html = matches[1].gsub(/\\(.)/, '\1') + doc = Hpricot(html) + assert_equal("Comics on the Web", (doc/:h1).inner_html) + list_items = (doc/:li/:a).map do |elem| + {href: elem.attributes['href'], title: elem.inner_html} + end + assert_equal({href: "http://achewood.com/", title: "Achewood"}, + list_items[0]) + assert_equal({href: "http://qwantz.com/", title: "Dinosaur Comics"}, + list_items[1]) + assert_equal({href: "http://cheston.com/pbf/archive.html", + title: "Perry Bible Fellowship"}, + list_items[2]) + assert_equal({href: "http://mnftiu.cc/", title: "Get Your War On"}, + list_items[3]) + + #assert_equal("", html) + } + + + + + end + + end + + + + + def test_lesson7_and_8 + $session = TryRubyTestSession.new + tryruby_session $session do + input 'Hash.new', result: {} + input 'class BlogEntry', line_continuation: 1 + input 'attr_accessor :title, :time, :fulltext, :mood', line_continuation: 1 + input 'end', result: nil + + # can't test for BlogEntry directly, as it isn't defined in this scope + input 'entry = BlogEntry.new', result: Proc.new {|v| + assert_equal("BlogEntry", v.class.name, + "line should result in a BlogEntry") + } + + input 'entry.title = "Today Mt. Hood Was Stolen!"', result: "Today Mt. Hood Was Stolen!" + + input 'entry.time = Time.now', result: Time + + input 'entry.mood = :sick', result: :sick + + str = <

          My Blog

          +
            +
          • Today Mt. Hood Was Stolen!

          • +
          • I can't believe Mt. Hood was stolen! I am speechless! + It was stolen by a giraffe who drove away in his + Cadillac Seville very nonchalant!!
          • +
          • I Left my Hoodie on the Mountain!

          • +
          • I am never going back to that mountain and + I hope a giraffe steals it.
          • +
          + EOF + + expected_xml = REXML::Document.new(expected_str.strip) + assert_match(/^window.irb.options.popup_make\(".*"\)?/m, + v, + "testing that Popup calls the correct javascript function") + actual_str = v.match(/^window.irb.options.popup_make\("(.*)"\);?/m)[1] + actual_str = "#{actual_str}" + actual_xml = REXML::Document.new(actual_str.strip) + assert_equal(expected_xml.write(StringIO.new).to_s, + actual_xml.write(StringIO.new).to_s, + "testing that html used with the javascript popup " + + "function is correct") + } + + input 'Time.now - 2.weeks', result: Time + + input 'File.read("/MouseHole/flickrpedia.user.rb")', result: String + + end # tryruby_session + + end # lesson6_and_7 + + + + + # class that performs the tests with the input sections of the + # tryrubysession test helper + class TryRubySession_Input + attr_accessor :session, :test + + # performs an assertion + # actual is the value being tested + # expected should either be a + # - Class: the class of actual should be expected + # - Regexp: actual (a string) should match the expected Regexp + # - Proc: A proc that takes one argument, actual. Assertions can + # be used inside that proc, eg assert_equal, assert. + # - : actual should equal expected + # name is the name of the input (result, output, javascript, error), + # used in messages + # line is the line being tested + def do_assert(actual, expected, name, line) + case expected + when Class + @test.assert_kind_of(expected, actual, + "Testing line `#{line}': #{name} should be a #{expected}") + when Regexp + @test.assert_match(expected, actual, + "Testing line `#{line}': #{name} should match #{expected}") + when Proc + @backtrace_pos = 0 + @test.instance_exec(actual, &expected) + + # @test.assert(expected.call(actual), + # "Testing line `#{line}': #{message} \n[#{actual}]") + else + @test.assert_equal(expected,actual, + "Testing line `#{line}' for correct #{name}") + end + end + + # runs the line using this objects session. + def do_test(line) + o = Object.new + # store the initial constants of Object + initial_constants = Object.constants + session = @session + + thread = Thread.new do + o.instance_eval do + run_script(session, line) + end + end + + result = thread.value + # restores require to its old functionality + #def Object.require(str) + # old_require(str) + #end + + # next 4 lines will revert Object to the way it was before + # run_script + diff_constants = Object.constants - initial_constants + diff_constants.each do |constant| + Object.send(:remove_const, constant) + end + result + end + + + # The input function, used with the tryruby_session test helper + # see tryruby_session for more details + def input(line, params = {}) + @backtrace_pos = 2 + params[:output] ||= "" + params[:result] ||= nil + params[:error] ||= nil + + result = do_test(line) + begin + if params[:illegal] then + @test.assert_equal(:illegal, result.type, + "Testing if line `#{line}' resulted in an illegal operation") + elsif params[:error] then + @test.assert_equal(:error, result.type, + "Testing if line `#{line}` resulted in an error") + do_assert(result.error, params[:error], "error", line) + do_assert(result.output, params[:output], "output", line) + elsif params[:javascript] then + @test.assert_nil(result.error, + "Testing line `#{line}' to ensure there was no error") + do_assert(result.javascript, params[:javascript], "javascript", line) + do_assert(result.output, params[:output], "output", line) + elsif params[:line_continuation] + @test.assert_equal(:line_continuation, result.type, + "Testing if line `#{line}' resulted in a line continuation") + if params[:line_continuation] != true then + @test.assert_equal(result.indent_level, params[:line_continuation], + "Testing if line `#{line}' triggered enough autoindent") + end + else + @test.assert_nil(result.error, + "Testing line `#{line}' to ensure there was no error") + do_assert(result.result, params[:result], "result" , line) + do_assert(result.output, params[:output], "output", line) + end + + rescue Test::Unit::AssertionFailedError => e + p e + + new_bt = Test::Unit::Util::BacktraceFilter.filter_backtrace(e.backtrace) + new_bt = new_bt[@backtrace_pos..@backtrace_pos] + e.set_backtrace(new_bt) + raise e + + end + end + end +end + +# tests if the TryRubyOutput translation, for use with mouseapp_2.js and similar +# is working correctly +class TryRubyOutputTest < Test::Unit::TestCase + def test_simple_result + t = TryRubyOutput.standard(result: [12,24]) + assert_equal("=> \033[1;20m[12, 24]", t.format_output) + end + + def test_result_and_output + t = TryRubyOutput.standard(result: 333, output: "hello") + assert_equal("hello=> \033[1;20m333", t.format_output) + end + + def test_error + begin + 40.reverse + rescue Exception => e + t = TryRubyOutput.error(error: e) + end + assert_equal("\033[1;33mNoMethodError: undefined method `reverse' for 40:Fixnum", + t.format_output) + end + + def test_error_with_output + begin + 40.reverse + rescue Exception => e + t = TryRubyOutput.error(error: e, output: "hello\nworld") + end + assert_equal("hello\nworld\033[1;33mNoMethodError: undefined method `reverse' for 40:Fixnum", + t.format_output) + end + + def test_illegal + t = TryRubyOutput.illegal + assert_equal("\033[1;33mYou aren't allowed to run that command!", + t.format_output) + end + + + + def test_line_continuation + t = TryRubyOutput.line_continuation(3) + assert_equal(".." * 3, t.format_output) + end + + def test_javascript + t = TryRubyOutput.javascript(javascript: 'alert("hello")') + # expected ends in a space to stop a visual problem in mouseapp + assert_equal("\033[1;JSmalert(\"hello\")\033[m ", t.format_output) + end + +end diff --git a/non-rack-legacy/public/tryruby.rb b/non-rack-legacy/public/tryruby.rb new file mode 100644 index 0000000..4b9bbcb --- /dev/null +++ b/non-rack-legacy/public/tryruby.rb @@ -0,0 +1,174 @@ +#$LOAD_PATH.unshift File.join(File.dirname(__FILE__), 'submodules', 'fakefs', 'lib') +require './setup.rb' +require 'ruby_parser' +require './fakefs/safe' +require 'stringio' + +module TryRuby + extend self + + class Session + attr_accessor :past_commands, :current_statement, :start_time + def initialize + @past_commands = '' + @current_statement = '' + @start_time = Time.now + end + end + + class Output + attr_reader :type, :result, :output, :error, :indent_level, :javascript + + def self.standard(params = {}) + Output.new type: :standard, result: params[:result], + output: params[:output] || '' + end + + def self.illegal + Output.new type: :illegal + end + + def self.javascript(js) + Output.new type: :javascript, javascript: js + end + + def self.no_output + Output.standard result: nil + end + + def self.line_continuation(level) + Output.new type: :line_continuation, indent_level: level + end + + def self.error(params = {}) + params[:error] ||= StandardError.new('TryRuby Error') + params[:error].message.gsub! /\(eval\):\d*/, '(TryRuby):1' + Output.new type: :error, error: params[:error], + output: params[:output] || '' + end + + def format + case @type + when :line_continuation + ".." * @indent_level + when :error + @output + "\033[1;33m#{@error.class}: #{@error.message}" + when :illegal + "\033[1;33mYou aren't allowed to run that command!" + when :javascript + "\033[1;JSm#{@javascript}\033[m " + else + @output + "=> \033[1;20m#{@result.inspect}" + end + end + + protected + def initialize(values = {}) + values.each do |variable, value| + instance_variable_set("@#{variable}", value) + end + end + end + + + class << self + attr_accessor :session + TryRuby.session = TryRuby::Session.new + end + + def calculate_nesting_level(statement) + begin + RubyParser.new.parse(statement) + 0 + rescue Racc::ParseError => e + case e.message + when /parse error on value \"\$end\" \(\$end\)/ then + new_statement = statement + "\n end" + begin + RubyParser.new.parse(new_statement) + return 1 + rescue Racc::ParseError => e + if e.message =~ /parse error on value \"end\" \(kEND\)/ then + new_statement = statement + "\n }" + end + end + begin + 1 + calculate_nesting_level(new_statement) + rescue Racc::ParseError => e + return 1 + end + else + raise e + end + end + end + + def run_line(code) + case code.strip + when '!INIT!IRB!' + return Output.no_output + when 'reset' + TryRuby.session.current_statement = '' + return Output.no_output + when 'time' + seconds = (Time.now - session.start_time).ceil + return Output.standard result: + if seconds < 60; "#{seconds} seconds" + elsif seconds < 120; "1 minute" + else; "#{seconds / 60} minutes" + end + end + + # nesting level + level = begin + calculate_nesting_level(session.current_statement + "\n" + code) + rescue Racc::ParseError, SyntaxError + 0 + end + if level > 0 + session.current_statement += "\n" + code + return Output.line_continuation(level) + end + + # run something + FakeFS.activate! + stdout_id = $stdout.to_i + $stdout = StringIO.new + cmd = <<-EOF + #{SetupCode} + $SAFE = 3 + #{session.past_commands} + $stdout = StringIO.new + begin + #{session.current_statement} + #{code} + end + EOF + begin + result = Thread.new { eval cmd, TOPLEVEL_BINDING }.value + rescue SecurityError + return Output.illegal + rescue Exception => e + return Output.error :error => e, :output => get_stdout + ensure + output = get_stdout + $stdout = IO.new(stdout_id) + FakeFS.deactivate! + end + + session.current_statement += "\n" + code + session.past_commands += "\n" + session.current_statement.strip + session.current_statement = '' + + return result if result.is_a? Output and result.type == :javascript + Output.standard result: result, output: output + end + + private + def get_stdout + raise TypeError, "$stdout is a #{$stdout.class}" unless $stdout.is_a? StringIO + $stdout.rewind + $stdout.read + end + +end diff --git a/non-rack-legacy/public/tutorials/es_intro.html b/non-rack-legacy/public/tutorials/es_intro.html new file mode 100644 index 0000000..256de2f --- /dev/null +++ b/non-rack-legacy/public/tutorials/es_intro.html @@ -0,0 +1,666 @@ + +
          +

          Usando El Prompt

          +

          La ventana azul de arriba es el prompt de Ruby. ¡Escribe una línea de código Ruby, aprieta Enter + y velo correr!

          +

          Por ejemplo, trata de escribir algo matemático. Como: 2 + 6

          +
          \d+
          +
          +
          +

          Números & Matemática

          +

          ¡Bien! Hiciste algo de matemática. ¿Ves como la respuesta salta a la vista?

          +

          Ruby reconoce números y símbolos matemáticos. Puedes probar otras cosas como:

          +
          • 4 * 10
          • +
          • 5 - 12
          • +
          • 40 / 4
          +

          Seguro, las computadoras son habilidosas y rápidas con las matemáticas. Sigamos... ¿Quieres ver tu nombre al revés? + Escribe tu primer nombre entre comillas así: "Jimmy"

          +
          "(\w+)"
          +
          +
          +

          Decir Tu Nombre Al Revés

          +

          Perfecto, has formado un string de las letras de tu nombre. Un string + es un juego de caracteres que la computadora puede procesar.

          +

          Imagina que las letras están en una cuerda donde + se cuelga la ropa y las comillas son los broches que sostienen los bordes. Las comillas marcan el comienzo y el final.

          +

          Para invertir tu nombre, escribe: "Jimmy".reverse (¡No olvides el punto!)

          +
          "(\w+)"
          +
          +
          +

          Contando Las Letras

          +

          ¡Has usado el método reverse sobre tu nombre! Poniendo tu nombre entre comillas, + hiciste un string. Luego llamaste al método reverse, que funciona sobre un string cambiando + todas las letras de atrás para adelante.

          +

          Ahora, vamos a ver cuantas letras tiene tu nombre: "Jimmy".length

          +
          \d+
          +
          +
          +

          Repitiendo

          +

          Ahora, estoy seguro que te estarás preguntando para que sirve todo esto. Bueno, estoy seguro que habrás estado en alguna + pagina web donde te gritaron, ¡Hey, tu password es muy corto! Ves, algunos programas + usan este código tan simple.

          +

          Mira esto. Vamos a multiplicar tu nombre por 5. "Jimmy" * 5

          +
          "(\w+)"
          +
          +
          +

          Hey, Sumario #1 Listo

          +

          Vamos a ver que es lo que has aprendido en el primer minuto.

          +
            +
          • El prompt. Escribiendo código en el prompt verde obtienes + una respuesta del prompt rojo. Todo código te da una respuesta.
          • +
          • Números y strings son objetos matemáticos y de texto de Ruby.
          • +
          • Métodos Has usado métodos en Ingles como reverse + y métodos simbólicos como * (el método de multiplicación.) ¡Los métodos son acciones!
          • +
          +

          Esta es la esencia del aprendizaje. Tomar cosas simples, jugar con ellas + y trasformarlas en cosas nuevas. ¿Te sientes cómodo con todo? Te aseguro que lo estas.

          +

          Bien, vamos a hacer algo incomodo. Trata de invertir un número: 40.reverse

          +
          NoMethodError: undefined method `reverse' for (\d+):Fixnum
          +
          +
          +

          ¡Basta, Te Volviste Loco!

          +

          No puedes invertir el numero cuarenta. Supongo que puedes poner tu monitor en + frente de un espejo, pero invertir un numero no tiene sentido. Ruby lanza un + mensaje de error. Ruby te dice que no hay un método reverse para los números.

          +

          Tal vez si lo conviertes en un string: 40.to_s.reverse.

          +
          \"(\d+)\"
          +
          +
          +

          Los Chicos Son Diferentes De Las Chicas

          +

          Y los números son diferentes de los strings. Aunque puedes usar métodos en cualquier objeto + en Ruby, algunos métodos solo funcionan en cierto tipo de cosas. Pero siempre puedes + convertir entre diferentes tipos usando el método "to" de Ruby.

          +
          • to_s convierte cosas a strings.
          • +
          • to_i convierte cosas a integers (números.)
          • +
          • to_a convierte cosas a arrays.
          • +
          +

          ¿Que son los arrays?! Son listas. Escribe entre un par de corchetes: [].

          +
          \[\]
          +
          +
          +

          Mantenerse en Cola

          +

          Genial, eso es una lista vacía. Las listas guardan cosas en orden. + Como esperando en la cola para palomitas de maíz. Estas atrás de alguien y jamás + pensarías en empujarlo a un costado, ¿no es así? Y con respecto al tipo detrás de ti, + mantienes un ojo sobre el, ¿correcto?

          +

          Acá hay una lista para ti. Números de la lotería: [12, 47, 35].

          +
          \[(\d+(, )?){2,}\]
          +
          +
          +

          Uno Levanta La Mano

          +

          Una lista de números de la lotería. ¿Cual es el mayor?

          +

          Prueba: [12, 47, 35].max.

          +
          (\d+)
          +
          +
          +

          Manteniendo la Lista

          +

          Bien, bien. Pero es un fastidio el tener que reescribir esa lista, ¿no es así?

          +

          Guardemos nuestros números en un ticket de esta manera: ticket = [12, 47, 35]

          +
          \[(\d+(, )?){2,}\]
          +
          +
          +

          Ahora Escribe Ticket

          +

          Ahora, escribe: ticket

          +
          \[(\d+(, )?){2,}\]
          +
          +
          +

          Guardado, Escondido

          +

          ¡Fantástico! Te has aferrado a tus números de la lotería, escondiéndolos dentro de una + variable llamada ticket.

          +

          Vamos a poner tus números en orden, que te parece? Usa: ticket.sort!

          +
          \[(\d+(, )?){2,}\]
          +
          +
          +

          Sumario #2 Está Sobre Nosotros

          +

          Tenías una lista. Ordenaste la lista. La variable ticket ahora esta cambiada.

          +

          ¿Te diste cuenta que el método sort! tiene un claro y llamativo signo de exclamación al final? + Muchas veces los métodos de Ruby gritan así si es que alteran la variable para bien. No es nada + especial, solo una marca.

          +

          Ahora, mira como te fue en tu segundo minuto:

          +
            +
          • Errors. Si tratas de invertir un número o hacer algo sospechoso, + Ruby salteara el prompt para avisarte.
          • +
          • Arrays son listas para ordenar cosas en orden.
          • +
          • Variables guardan cosas y le dan un nombre. Usaste el + signo igual para hacerlo.
            Like: ticket = [14, 37, 18].
          • +
          +

          En total hay ocho lecciones. Estás a dos octavos de camino! + Esto es cosa simple, no te parece? Las cosas buenas están mas adelante.

          +

          Cambiemos de dirección por un momento. Rellené con un poco de poesía cierta + variable para ti. Hecha un vistazo. Escribe print poem

          +
          poem = "My toast has flown from my hand\nAnd my toast has gone to the +moon.\nBut when I saw it on television,\nPlanting our flag on Halley's +comet,\nMore still did I want to eat it.\n"
          +
          My toast (.+)
          +
          +
          +

          Desgraciadamente, Tú Odias la poesía de Tostadas

          +

          Mira, esta bien. No tiene que gustarte. Hackéalo, yo invito.

          +

          En vez de tostada, ve por un melón o algo. Prueba esto: poem['toast'] = 'honeydew'

          +

          Y luego escribe print poem para ver el nuevo poema.

          +
          My honey(.+)
          +
          +
          +

          Listo, Apuntado

          +

          Los corchetes que acabas de usar son muy comunes en Ruby. Recuerda, escribiste: poem['toast'] = 'honeydew'. Esa casilla con la palabra toast tiene corchetes a ambos lados, ¿ves?

          +

          Los +corchetes son como una mira para alinear un objetivo. Exacto. Estos +corchetes significan, "Estoy buscando ____." Listo, apuntado. Aquí estas buscando +una costada e intercambiándola por una fruta.

          +

          Aquí hay una pregunta: ¿Que pasa si volteamos el poema entero? poem.reverse +

          "\\n.ti tae ot (.+)"
          +
          +
          +

          Demasiado Invertido

          +

          Está bien, seguro. Entonces todo el poema fue puesto al revés. Letra por letra. Sin embargo, yo realmente solo quería + invertir las líneas. Mover la última línea a la primera y la primera hacia abajo a la ultima. Al revés, pero no + ése revés.

          +

          Aquí esta como lograrlo: poem.lines.to_a.reverse

          +
          \["More still did I(.+)"\]
          +
          +
          +

          Rizos de Metodos Concatenados

          +

          Dime, que es lo que ves? Que paso acá? Escribiste poem.lines.to_a.reverse y ¿que pasó?

          +

          Dos cosas pasaron. Convertiste poem en una lista usando +lines.to_a. lines decide la forma en que +el string se divide, luego to_a lo +convierte en un Array. (To array.) Diferentes métodos, como +bytes y chars pueden ser usadas en lugar de +lines. Usando lines, Ruby retornará cada línea de poem.

          +

          Luego, tu revertiste, reversed, esa lista. Tenías cada línea. Las revertiste. Eso es todo.

          +

          Vamos a hilar un método más al final de todo esto: print poem.lines.to_a.reverse.join +

          More still did I(.+)
          +
          +
          +

          De Todos los Sumarios, el #3 esta aquí

          +

          Buen espectáculo, mi amigo! El método join toma la lista de líneas revertidas y las pone juntas en un string. + (Seguro, también podrías haber usado to_s.)

          +

          Tiempo de Revisión.

          +
            +
          • Exclamaciones. Métodos pueden tener signos de exclamación (y también de interrogación) en + sus nombres. No es la gran cosa. Prueba: poem.include? "my hand"
          • +
          • Corchetes. Establece objetivos y busca cosas. Busca y reemplaza.
          • +
          • Concatenar métodos te permite hacer mas cosas juntas. Partir poem, revertirlo, + reensamblarlo: poem.lines.to_a.reverse.join
          • +
          +

          En este punto, querras manosear un poco más el poema. Una lista completa de métodos + String estan + + acá. + No temas y prueba algunos (como poem.downcase o poem.delete.)

          +

          Cuando estés listo para seguir adelante, escribe: books = {}

          +
          \{\}
          +
          +
          +

          Un Pequeñín Libro en Blanco

          +

          Has hecho un hash vacío. (también conocido como: un diccionario vacío.)

          +

          Vamos a rellenar con un libro de críticas en miniatura. Acá esta nuestro sistema de calificación:

          +
            +
          • :splendid → una obra maestra.
          • +
          • :quite_good → disfrutable, por supuesto que sí.
          • +
          • :mediocre → partes iguales de bueno y malo.
          • +
          • :quite_not_good → notablemente malo.
          • +
          • :abyssmal → una perdida de tiempo.
          • +
          +

          Para calificar un libro, pon el título entre corchetes y la calificación luego del signo igual.

          +

          Por ejemplo: books["Gravity's Rainbow"] = :splendid

          +
          :\w+
          +
          +
          +

          Mas Críticas Tamaño Bocadillo

          +

          Tú sigue, agrega mas críticas. Y, si quieres ver toda la lista, + implemente escribe: books

          +

          De nuevo, las calificaciones son: :splendid, :quite_good, :mediocre, + :quite_not_good, and :abyssmal.

          +

          Estas calificaciones no son strings. Cuando colocas dos puntos frente a una palabra simple, obtienes un + symbol. Los símbolos son más baratos que los strings (en términos de memoria de la computadora.) Si usas + una palabra una y otra vez en un programa, usa un símbolo. En vez de tener miles de + copias de una palabra en memoria, la computadora guardara el símbolo solamente una vez.

          +

          Una vez que tengas tres o cuatro libros allí + dentro, escribe: books.length.

          +
          [3-9]
          +
          +
          +

          Espera, ¿Me gustó Gravity's Rainbow?

          +

          Ves, el método length funciona sobre strings, list y hashes. Una gran cosa acerca de + Ruby es que los nombres usualmente se reutilizan, lo que significa menos nombres para recordar.

          +

          Si quisieras ver una de tus críticas hechas, vuelve a poner el título entre corchetes. Pero deja de lado el + signo igual.

          +

          Al igual que aquí: books["Gravity's Rainbow"]

          +
          :\w+
          +
          +
          +

          Hashes como Pares

          +

          Ten en mente que los hashes no mantienen las cosas en orden. Ese no es su trabajo. Solo emparejará dos + cosas: una key (llave) y un valor. En tus críticas, la key es el + titulo del libro y el valor es la calificación.

          +

          Si simplemente quieres ver los títulos de los libros que calificaste: books.keys

          +
          \[".*"\]
          +
          +
          +

          ¿Eres Duro?

          +

          ¿Estás dando duras injustas críticas? Sigamos puntuando con rigurosidad:
          ratings = Hash.new {0}

          +

          Entonces, bien, ahora vamos a contar tus críticas. Trata de seguirme. Escribe:
          + books.values.each { |rate| ratings[rate] += 1 }

          +

          (La línea vertical es el signo de tubería, probablemente lo logres con AltGr+1 con tu teclado.)

          +
          \[:.+\]
          +
          +
          +

          Un Recuento

          +

          Genial, wow! Has hecho un recuento de tus calificaciones. Escribe ratings para ver las cuenta. Este nuevo + hash muestra las calificaciones y luego el numero de veces que has dado esa calificación.

          +

          Una de las asombrosas cosas nuevas que acabamos de usar es un bloque, block. Vamos a explorar + explore these more in the next summary. más esto en el próximo sumario. Pero, básicamente, un bloque es un pedazo de código Ruby + rodeado por llaves.

          +

          Probemos otro bloque: 5.times { print "Odelay!" }

          +
          Odelay!Od.*
          +
          +
          +

          Ahora Arribamos al Sumario #4

          +

          Los bloques están siempre apegados a métodos. Como el método times, que toma el bloque y lo corre + repetidas veces. (En este caso: cinco veces.)

          +

          Esta última lección fue algo mas larga. Probablemente usaste unos tres minutos aprendiendo sobre:

          +
            +
          • Hashes. El pequeño diccionario con páginas arrugadas: {}.
          • +
          • Symbols. Pequeñas, eficientes palabras con dos puntos: :splendid.
          • +
          • Blocks. Pedazos de código que pueden ser clavados a muchos métodos de Ruby. Aquí + esta el código que usaste para crear el recuento:
            books.values.each { |rate| ratings[rate] += 1 }.
          • +
          +

          En tu computadora, probablemente tienes muchos archivos diferentes. Archivos con fotos en ellos, + archivos con programas dentro. Y los archivos usualmente se organizan en carpetas, también llamadas: + directorios.

          +

          He preparado algunos directorios para ti. Echa un vistazo: + Dir.entries "/"

          +
          \["\.", .+\]
          +
          +
          +

          La Privada Colección de Dr. Dir

          +

          Acabas de listar todo lo existente en el directorio superior. El directorio raíz, indicado + por la barra en diagonal. Conteniendo algunos programas y otros tutoriales y semejantes.

          +

          Entonces, ¿que es el método Dir.entries? Bueno, es solo un método ¿si?, + entries es el método llamado sobre la variable Dir. + Y Dir tiene una colección de métodos para chequear los archivos de los directorios.

          +

          Otra pequeña cosa de la que no hemos hablado abiertamente. Argumentos de los métodos, resaltados en verde.

          +
            +
          • Dir.entries "/": Cualquier cosa listada luego de un método + es considerado acoplamiento.
          • +
          • print poem: Ves, print es un método ordinario. + Y el poema esta acoplado. Para ser impreso.
          • +
          • print "pre", "event", "ual", "ism" posee varios argumentos, + con comas entre ellos.
          • +
          +

          Para listar solamente archivos de texto en el directorio: Dir["/*.txt"]

          +
          \["\/comics\.txt"\]
          +
          +
          +

          Ven, Lee Historietas Conmigo

          +

          El método Dir[] hace como entries pero tu buscas por archivos + archivos con carácteres de comodín. ¡Aquí, vemos esos corchetes otra vez! Te das + cuenta como todavía significan, "Estoy buscando _____.".

          +

          Mas específicamente: "Estoy buscando archivos que terminen con .txt."

          +

          Abramos este archivo con historietas de una vez. Aquí esta la manera:
          + print File.read("/comics.txt")

          +
          Achewood.+
          +
          +
          +

          Mi Comicas, Tu Comicas

          +

          ¡De acuerdo! Podemos comenzar a usar archivos para guardar cosas. Esto es excelente + porque normalmente cuando salimos de Ruby, todas nuestras variables desaparecerán. + Ruby, por si mismo, olvida estas cosas. Pero si salvamos cosas en archivos, + podemos leer esos archivos en futuras escapadas a Ruby.

          +

          Hey, y ¿adivina que? ¡El directorio /Home es tuyo! ¡Te lo entrego a ti! ¡Soy generoso! Hagamos una copia del archivo de la historieta.

          +

          Querrás hacer lo siguiente: FileUtils.copy('/comics.txt', '/Home/comics.txt') +

          Si ya has creado el archivo, usa File.delete('/Home/comics.txt') para arrojarlo a la basura.

          +
          nil
          +
          +
          +

          Tu Propio Territorio

          +

          Ok, tienes una copia. Chequéala: Dir["/Home/*.txt"]

          +

          Para agregar tu propia historieta a la lista, abramos el archivo en modo append.

          +

          Empieza asi: File.open("/Home/comics.txt", "a") do |f|.

          +
          ..
          +
          +
          +

          Y Ahora, para la Sorprendente Conclusión

          +

          Asi que tu prompt ha cambiado. ¿Lo notas? Tu prompt es doble punto ahora.

          +

          En este tutorial, este prompt significa que Ruby espera que escribas más. A + medida que vayas completando con líneas de código, los doble puntos se mantendrán + hasta que hallas finalizado.

          +

          Hot tip: si quieres parar de trabajar en el código y salirte de los doble puntos, usa el comando reset. + Si quieres volver a la pagina previa del tutorial, usa el comando back.

          +

          Aquí esta tu código. Ya has escrito la primera línea, asi que simplemente ingresa la segunda. (El \n + es el carácter de Enter.

          +
          • File.open("/Home/comics.txt", "a") do |f|
          • +
          •   f << "Cat and Girl: http://catandgirl.com/\n"
          • +
          • end
          • +
          +

          Y, como te has vuelto avanzado y capaz aquí, otro tip: puedes usar las flechas hacia + arriba y hacia abajo para editar tus viejos comandos o correrlos otra vez.

          +
          ..
          +
          +
          +

          Ruby se Sienta y Espera

          +

          Esa ultima línea agrega la historieta Cat and Girl a la lista, pero Ruby seguirá esperando + hasta que hallas terminado por completo para tomar acción.

          +

          Ahora, para finalizar el código que has empezado. Empezaste un nuevo bloque cuando escribiste do. + Hasta ahora los bloques que hemos visto usaban llaves. Esta vez usaremos do y end en lugar + de las llaves. Muchos Rubyistas usan do...end cuando el bloque ocupa varias líneas.

          +

          Terminemos ese bloque ahora mismo, con: end

          +
          • File.open("/Home/comics.txt", "a") do |f|
          • +
          •   f << "Cat and Girl: http://catandgirl.com/\n"
          • +
          • end
          • +
          +
          #.File:/Home/comics\.txt \(closed\).
          +
          +
          +

          El Reloj Clavado en el Archivo

          +

          ¡Bien, bien! Has añadido esa historieta al archivo. Puedes verlo por ti mismo: print File.read("/Home/comics.txt")

          +

          ¿Qué hora era cuando cambiaste el archivo? Veamos. Escribe: File.mtime("/Home/comics.txt")

          +
          \w+ \w+ \d+ \d{2}:\d{2}:\d{2} [+-]\d{4} \d{4}
          +
          +
          +

          Sólo la Manecilla de la Hora

          +

          Estupendo, allí esta la hora. La hora exacta en la que agregaste la historieta al archivo. El mtime te devuelve un objeto Time de Ruby.

          +

          Si sólo quieres ver la hora que era, aprieta la flecha para arriba y cambia la línea a: File.mtime("/Home/comics.txt").hour

          +
          \d+
          +
          +
          +

          Hola, ¿Quién Anda Ahí? Y el Sumario #5 Agita su Sombrero!

          +

          Bien hecho, bien hecho, bien hecho, ¡bien hecho! Realmente, realmente, realmente, realmente, ¡reaaaaaaaaalllmente!

          +

          Aquí esta tu último minuto de tu vida en retrospectiva:

          +
            +
          • Archivos. ¿Que más se puede decir? Muchos métodos para editar archivos y revisar directorios.
          • +
          • Argumentos. Los argumentos son listas de cosas mandadas en un método. Separadas con comas.
          • +
          • También hablamos sobre do y end que es otra manera de hacer un bloque.
          • +
          +

          Ahora ya sabes como usar Ruby por completo. Me refiero a que tienes lo esencial. Solo necesitas seguir + aprendiendo métodos y probar bloques más complejos.

          +

          Pero existe un lado de Ruby que no hemos hablado. Hacer tus propios métodos y clases.

          +

          Ahem! Acabemos con ello de una vez.

          +

          Empieza con: def load_comics( path )

          +
          ..
          +
          +
          +

          En Ruby, Def Leppard Significa ¡Define Leppard (un Método)!

          +

          Hey, bueno, lo hiciste. Estas haciendo tu propio método. Comenzaste con def, seguido por el nombre del método. + Y una lista de argumentos que va a necesitar el método. ¡Esto no da tanto miedo ni es peligroso!

          +

          Todo lo que debemos hacer es rellenar con Ruby y terminarlo con end.

          +

          Aquí esta el código:

          +
          • def load_comics( path )
          • +
          •   comics = {}
          • +
          •   File.foreach(path) do |line|
          • +
          •     url, name = line.split(': ')
          • +
          •     comics[url] = name.strip
          • +
          •   end
          • +
          •   comics
          • +
          • end
          • +
          +

          No necesitas indentar, si no quieres. Lo hice solo para que sea más legible.

          +
          nil
          +
          +
          +

          La Madura Fruta de tu Propia Creación

          +

          Un nuevo método ha nacido. Vamos a usarlo: comics = load_comics('/comics.txt')

          +

          Si tienes un problema, puedes haberlo escrito mal. Usa el comando back y prueba otra vez.

          +
          \{.*"Achewood"=."http://achewood.com/".*\}
          +
          +
          +

          Hey, Cool, Una Cosa de Historietas

          +

          En tu ventana de Ruby arriba, mira el código que has escrito para el método load_comics. ¿Qué esta pasando? Tu estas + pasando en la variable path y estas recibiendo la variable comics. Ruby permite filtrar el hash comics + que es devuelto al final del método.

          +

          Una cantidad de métodos se usaron para realizar el trabajo. Fíjate si puedes hallarlos.

          +
          • File.foreach es el método que abre un archivo y manda cada línea al bloque. La variable line + dentro del bloque do...end va turnando con cada línea del archivo.
          • +
          • split es un método para strings, que rompe los string en colocándolo en un array. Un hacha es arrojada sobre las comas + y las líneas se cortan en dos, dándonos la url y el nombre, name, de las historietas.
          • +
          • strip remueve los espacios extra alrededor de name. Por si acaso.
          • +
          +

          Justo allí. Bravo. Tienes las historietas en un hash de Ruby. ¿Pero ahora qué? ¿Qué tan bueno es en verdad?

          +

          Hagamos una página de links. ¿Qué te parece? Vamos a necesitar una pequeña librería que hice para ti.

          +

          Escribe: require 'popup'

          +
          true
          +
          +
          +

          El Navegador de Títere

          +

          Excelente, has cargado la librería popup. Está guardada en un archivo en el directorio Libraries. Mira: Dir["/Libraries/*"]

          +

          La librería popup contiene un puñado de métodos que he escrito y te dejaran controlar ventanas emergentes aquí en Try Ruby.

          +

          Mira, prueba esto: Popup.goto "http://google.com/"

          +
          \033\[1;JSm.*popup_goto\(.*\)\033\[m.*
          +
          +
          +

          Haciendo Links e Hilando Redes

          +

          Nuestro propio adorable, pequeño popup para manipular. también puedes rellenarlo con tus cositas. Empecemos por algo pequeño:

          +
          • Popup.make {
          • +
          •   h1 "My Links"
          • +
          •   link "Go to Google", "http://google.com/"
          • +
          • }
          • +
          +

          El termino h1 (h-uno) significa encabezado de nivel uno. En HTML, es el encabezado más grande.

          +
          \033\[1;JSm.*popup_make\(.*h1.*a href.*\)\033\[m.*
          +
          +
          +

          Los Popups son tan fáciles, es una Locura

          +

          Se ve bien, lo hiciste perfecto, tal como se te pidió. Hagamos una lista entonces.

          +

          Aquí esta como haces una lista con la librería de popup:

          +
          • Popup.make do
          • +
          •   h1 "Things To Do"
          • +
          •   list do
          • +
          •     p "Try out Ruby"
          • +
          •     p "Ride a tiger"
          • +
          •     p "(down River Euphrates)"
          • +
          •   end
          • +
          • end
          • +
          +

          El método p es la manera corta para "párrafo".

          +
          \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*li.*\)\033\[m.*
          +
          +
          +

          Expandiendo las Historietas en la Tabla

          +

          Bien, esto esta yendo maravilloso. Esto es algo simple, pero mantén en mente que no sabias nada sobre Ruby hace quince minutos atrás!<

          +

          Ultimo paso. Vamos a juntar todo, ¿sabes? ¡Juntémoslo como esos juegos de + campanillas hermosas que tintinean en los pórticos bajo la hermosa luz del sol + en la playa!

          +

          Asegúrate de que las historietas están cargadas: comics = load_comics( '/comics.txt' )

          +

          Ahora, hagamos una lista de links para cada historieta:

          +
          • Popup.make do
          • +
          •   h1 "Comics on the Web"
          • +
          •   list do
          • +
          •     comics.each do |name, url|
          • +
          •       link name, url
          • +
          •     end
          • +
          •   end
          • +
          • end
          • +
          +

          Puedes clickear en los links y leer las historietas ¡inclusive en la ventana principal! ¡Bárbaro!

          +
          \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*a href.*li.*a href.*\)\033\[m.*
          +
          +
          +

          Sumario #6 lo que Significa que has Llegado Muy Lejos

          +

          Eres un clérigo nivel 6 de Ruby. Quiero decir que buen trabajo has hecho. Vamos a revisar:

          +
            +
          • Agregaste tu propio método con def y usaste ese método load_comics varias veces.
          • +
          • Librerias. Tú usaste el método require para cargar la librería popup.
            Escribiendo: require 'popup'
          • +
          • Y como si no fuera suficiente, hiciste tu propia página web para listar los archivos de historietas. ¡Hiciste un programa real!
          • +
          +

          Entonces ¿Qué podrá venir luego? ¿Qué deberías aprender posiblemente ahora? + Ja, esta es la mejor parte. Has recorrido un largo camino y ahora descubrirás + las clases. En dos lecciones mas y ya estarás hecho.

          +

          Tempranamente, creamos un hash como este: Hash.new pruébalo.

          +
          \{\}
          +
          +
          +

          No una Clase de Escuela, Una Clase Trabajadora

          +

          Ves, las llaves vacías {} son abreviaciones para Hash.new. El método new + es usado para hacer objetos de cierta clase. (Piensa "clase" como en "clase + trabajadora" — un grupo especifico de objetos similares, tienen el + mismo trabajo, la misma camisa.)

          +

          Pregúntate esto: ¿Cómo haría mi blog en Ruby? ¿Dónde deberías + comenzar? Bien, deberías guardar tus entradas del blog en un archivo, ¿cierto? + Pero ¿cómo seguirías los títulos de las entradas y el momento en que fue creado? + Y cuando cargas el archivo, ¿cómo se vería en Ruby? ¿Sería un Hash? ¿O un Array? ¿O + un Array de Arrys? ¿O alguna otra cosa?

          Yo realmente creo que querrás usar una clase. Ya estas familiarizado con varias clases: Hash, Array, String.

          +

          Hagamos una clase nueva: class BlogEntry.

          +
          ..
          +
          +
          +

          El Relleno del Blog esta Hecho de

          +

          Has abierto una nueva clase BlogEntry. ¿De que están hechas las entradas de tu blog? Un titulo, seguro. también, + la fecha en la que fue creada. El texto entero de la entrada.

          +

          Vamos a poner el estado de ánimo, también, tal como LiveJournal. La internet ha traído de vuelta las personas de palitos y emoticones + fuera de la bancarrota.¡Que emoción!

          +

          Bueno, ya tienes la primera línea de la clase, aquí esta el resto:/p> +

          • class BlogEntry
          • +
          •   attr_accessor :title, :time, :fulltext, :mood
          • +
          • end
          • +
          +
          nil
          +
          +
          +

          Accessors Son las Extremidades Colgantes

          +

          Hey, buena clase, colega. Tienes una nueva clase BlogEntry. Para comenzar una entrada:
          entry = BlogEntry.new.

          +

          En la definición de la clase, usaste un método llamado attr_accessor. Existen varios métodos attribute + atributo, como este que agregan pequeñas configuraciones a la clase. Estos atributos son simplemente variables adosadas a la clase.

          +

          Piénsalo de este modo. Una clase es como una persona. Esa forma de estrella + del humano. Y los atributos son las extremidades, las diferentes partes que + hacen un cuerpo.

          +

          Para crear el titulo de tu entrada: entry.title = "Today Mt. Hood Was Stolen!"

          +
          ".+"
          +
          +
          +

          Un Objeto, Ese Estupendo Paquete Pequeño

          +

          Sigue adelante y pon la hora: entry.time = Time.now

          +

          Y el estado de animo: entry.mood = :sick

          +

          Y el anuncio en si: entry.fulltext = "I can't believe Mt. Hood was stolen! I am speechless! It was stolen by a giraffe who drove away + in his Cadillac Seville very nonchalant!!"

          +

          Para ver toda la configuración, simplemente escribe en el prompt: entry.

          +
          #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
          +
          +
          +

          Agilizando

          +

          Genial, tu blog es impresionante. Hey, hagamos las cosas algo mas fácil. No querrás + poner la hora asi todas las veces que postees. Solo quieres escribir el titulo, + el contenido y el emoticon rápido, ¿verdad?

          +

          Vamos a agregar un método initialize.

          +
          • class BlogEntry
          • +
          •   def initialize( title, mood, fulltext )
          • +
          •     @time = Time.now
          • +
          •     @title, @mood, @fulltext = title, mood, fulltext
          • +
          •   end
          • +
          • end
          • +
          +

          Una vez que lo hallas escrito, prueba hacer una nueva entrada: BlogEntry.new

          +
          ArgumentError: wrong number of arguments \(0 for 3\).*
          +
          +
          +

          Tu le Has Enseñado al Blog a Rechazar lo Malo

          +

          ¿Viste como usamos dentro de la clase el símbolo arroba? De este modo: @time = Time.now

          +

          Fuera de la clase, usamos accesos (accessors): entry.time = Time.now Pero dentro variables de instancia: @time = Time.now + Son exactamente lo mismo, pero expresado en dos partes diferentes de tu programa.

          +

          tu blog ahora necesita un titulo, estado de ánimo y el post para funcionar. Cuando un nuevo BlogEntry es creado, el método initialize + es usado para chequear cualquier argumento para new. ¡Uh, necesitamos tres argumentos!

          +

          Prueba de nuevo con los tres.

          +

          entry2 += BlogEntry.new( "I Left my Hoodie on the Mountain!", :confused, "I am +never going back to that mountain and I hope a giraffe steals it." )

          +
          #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
          +
          +
          +

          Una Jirafa No Ha Robado el Sumario #7

          +

          Aha, estas aquí. Y todo en una pieza. Todavía vamos a hacer tu blog realidad, pero hasta entonces, vamos a revisar, ¿bien?

          +
            +
          • Clases. Todo en Ruby es algún tipo de objeto. Las clases explican los objetos. Como ciertos objetos + trabajan. Por ejemplo, haces algunas entradas de blog y estos objetos están explicados en la clase BlogEntry. + En otras palabras: los llamas objetos del tipo BlogEntry.
          • +
          • Accessors son variables adosadas a un objeto que pueden ser usadas fuera del objeto. (entry.time = Time.now)
          • +
          • Variables de instancia son las mismas variables para accesos dentro del objeto. + Como en la definición de un método. (@time = Time.now)
          • +
          +

          Bueno, vamos a envolver las cosas, niño. Aquí esta el ultimo capitulo de la FASCINANTE épica + historia de Try Ruby! Ahora que ya has probado como todo funciona, ¿cómo vas a + usar eso alrededor de la casa y en tu tienda de comestibles? Eres una + gran persona (una de mis favoritas), pero necesitas dirección.

          +

          Vamos a terminar tu blog. Tienes entradas de blog, pero no un blog.

          +

          Pon las entradas en un array: blog = [entry, entry2]

          +
          \[#.BlogEntry:0x[0-9a-f]+.*, #.BlogEntry:0x[0-9a-f]+.*\]
          +
          +
          +

          Todo Se Trata de Combinar Cosas

          +

          Cosas hermosas pueden hacerse de partes simples de Ruby, especialmente + cuando las combinas entre ellas para formar algo nuevo. Aquí tenemos un blog + hecho de un array de clases. Y, en realidad, Ruby realmente hace buenas cosas + con este tipo de criaturas.

          +

          Aquí hay un puñado de cosas que puedes hacer con tu blog array:

          +
          • Querrás ordenar tus entradas de mas reciente a viejas. Puedes hacerlo con:
            + blog.sort_by { |entry| entry.time }.reverse
            Ve sort_by para más explicación.
          • +
          • Si quieres buscar en el blog por cualquier cosa relacionada con "cadillac":
            + blog.find_all { |entry| entry.fulltext.match(/cadillac/i) }
            + Lee mas en find_all + y match + para descubrir como funciona. También: /giraffe/i es un objeto Regexp, usado para concordar palabras.
          • +
          • Y agregar nuevas entradas con blog << new_entry
            + Y aquí la documentación del método <<.
          • +
          +

          Puedes buscar entre la lista de los métodos con los que viene Ruby en ruby-doc.org's core. + Otra buena lista hay en online pickaxe.

          +

          Un método realmente útil (probablemente yo uso esto mas que otra cosa) es map. Escribe: blog.map { |entry| entry.mood }

          +
          \[(:\w+, )+:\w+\]
          +
          +
          +

          Mira Su Cara — La Transformación Ha Comenzado

          +

          El método map recorre un array y reemplaza cada ítem con algo nuevo. ¿Dices que quieres reemplazar cada entrada de tu blog + con el nombre de Bruce Willis?. Hazlo entonces: blog.map { "Bruce Willis" }

          +

          Como el bloque siempre devuelve el string "Bruce Willis", eso es lo que obtienes. En el código que acabas de usar, la entrada entry wfue reemplazada + por solo el entry.mood.

          +

          Ahora, quiero que hagas un popup con las entradas de tu blog. Yo no te voy a + dar todo el código. Solo te voy a dar una parte.

          +
          • blog.each do |entry|
          • +
          •   h2 entry.title
          • +
          •   p entry.fulltext
          • +
          • end
          • +
          +

          Ahora, yo espero que pongas el código del popup alrededor y agregues un titulo con el nombre de tu blog usando h1. Como extra, tienes la hora de cada entrada para mostrar.

          +
          \033\[1;JSm.*popup_make\(.*h1.*h2.*li.*h2.*li.*\)\033\[m.*
          +
          +
          +

          Eres Una Especie de Gurú Web, Tengo Estrellas en Mis Ojos

          +

          Bien, ¡eso es! Este es exactamente el código que puedes usar para escribir tu + propio blog real en Ruby. Si te sientes aventurero, yo chequearía el video de + Rails videos donde muestran a un joven compañero creando un blog en 15 minutos. Solo sientete cómodo y mira.

          +

          Debo mencionar a Rails. Tú has estado aprendiendo el lenguaje Ruby, como + hablarlo. Pero Rails es grupo de librerías (algo asi como la librería de popup + que hemos estado usando.) Es un poderoso conjunto de herramientas para crear + sitios web. Si estas interesado en aprender sobre Rails, yo miraría head + por aquí directamente. ¡Empieza a usar tus habilidades en Ruby apropiadamente!

          +

          Algo que tiene Rails son métodos para manejar fechas fácilmente. Como, prueba: Time.now - 2.weeks

          +
          class Integer; def weeks; self * 7*24*60*60; end; end
          +
          \w+ \w+ \d+ \d{2}:\d{2}:\d{2} .*
          +
          +
          +

          Si Quieres Empezar Poco a Poco

          +

          Si quieres comenzar escribiendo pequeños programas en Ruby para practicar, tengo un proyecto llamado MouseHole + que es una pequeña caja de herramientas en la web para escribir programas cortos en Ruby. Puedes ver aquí algunos + scripts para ver que quiero decir.

          +

          MouseHole no es para escribir sitios web en realidad. Es para escribir + pequeños programas y correrlos dentro del navegador. Como hay un programa block + de notas para MouseHole y un programa que agrega una imagen de un ratón a los + links de la web que linkean a programas de MouseHole.

          +

          Tengo un script de MouseHole dentro de un archivo aquí mismo:
          + print File.read("/MouseHole/flickrpedia.user.rb")

          +
          .*Inserts Wikipedia links for Flickr tags.*
          +
          +
          +

          Sumario #8, El Sumario Hey-Relájate-Lo-Hiciste-Bien

          +

          Esta ultima sección se tomó un momento para relajarse, para darte algunos consejos de como + puedes usar Ruby. Si lo has disfrutado, descarga Ruby e instálalo.

          + +

          Una vez que tengas Ruby instalado, puedes usar Ruby Interactivo ejecutando el comando irb en el prompt de tu sistema. Para mas sobre Irb, esta + The Tiger's Vest para ayudarte.

          +

          Tú realmente mereces una torta doble-capa con doble-doble azúcar glaseado y + un tipo tocando una de esas guitarras que son doble-guitarra. Quiero decir + terminaste, ¡lo hiciste! No hay dudas de eso, ¡eres un gran ser certificado!

          +
          +
          + \ No newline at end of file diff --git a/non-rack-legacy/public/tutorials/intro.html b/non-rack-legacy/public/tutorials/intro.html new file mode 100644 index 0000000..56c1d1c --- /dev/null +++ b/non-rack-legacy/public/tutorials/intro.html @@ -0,0 +1,680 @@ + +
          +

          Using the Prompt

          +

          The blue window above is a Ruby prompt. Type a line of Ruby code, hit Enter + and watch it run!

          +

          For example, try typing some math. Like: 2 + 6

          +
          \d+
          +
          +
          +

          Numbers & Math

          +

          Good! You did a bit of math. See how the answer popped out?

          +

          Ruby recognizes numbers and mathematic symbols. You could try some other math like:

          +
          • 4 * 10
          • +
          • 5 - 12
          • +
          • 40 / 4
          +

          Sure, computers are handy and fast for math. Let's move on. Want to see your name reversed? + Type your first name in quotes like this: "Jimmy"

          +
          "(\w+)"
          +
          +
          +

          Say Your Name Backwards

          +

          Perfect, you've formed a string from the letters of your name. A string + is a set of characters the computer can process.

          +

          Imagine the letters are on a string of + laundry line and the quotes are clothespins holding the ends. The quotes mark the beginning and end.

          +

          To reverse your name, type: "Jimmy".reverse (Don't forget the dot!)

          +
          "(\w+)"
          +
          +
          +

          Counting the Letters

          +

          You have used the reverse method on your name! By enclosing your name in + quotes, you made a string. Then you called the reverse method, which works on strings to flip + all the letters backwards.

          +

          Now, let's see how many letters are in your name: "Jimmy".length

          +
          \d+
          +
          +
          +

          On Repeat

          +

          Now, I'm sure by now you're wondering what any of this is good for. Well, I'm sure you've been to + a website that screamed, Hey, your password is too short! See, some programs + use this simple code.

          +

          Watch this. Let's multiply your name by 5. "Jimmy" * 5

          +
          "(\w+)"
          +
          +
          +

          Hey, Summary #1 Already

          +

          Let's look at what you've learned in the first minute.

          +
            +
          • The prompt. Typing code into the green prompt gives you + an answer from a red prompt. All code gives an answer.
          • +
          • Numbers and strings are Ruby's math and text objects.
          • +
          • Methods. You've used English-language methods like reverse + and symbolic methods like * (the multiplication method.) Methods are action!
          • +
          +

          This is the essence of your learning. Taking simple things, toying with + them and turning them into new things. Feeling comfortable yet? I promise you are.

          +

          Okay, let's do something uncomfortable. Try reversing a number: 40.reverse

          +
          NoMethodError: undefined method `reverse' for (\d+):Fixnum
          +
          +
          +

          Stop, You're Barking Mad!

          +

          You can't reverse the number forty. I guess you can hold your monitor up to the + mirror, but reversing a number just doesn't make sense. Ruby has tossed an error + message. Ruby is telling you there is no method reverse for numbers.

          +

          Maybe if you turn it into a string: 40.to_s.reverse.

          +
          \"(\d+)\"
          +
          +
          +

          Boys are Different From Girls

          +

          And numbers are different from strings. While you can use methods on any object + in Ruby, some methods only work on certain types of things. But you can always + convert between different types using Ruby's "to" methods.

          +
          • to_s converts things to strings.
          • +
          • to_i converts things to integers (numbers.)
          • +
          • to_a converts things to arrays.
          • +
          +

          What are arrays?! They are lists. Type in a pair of brackets: [].

          +
          \[\]
          +
          +
          +

          Standing in Line

          +

          Great, that's an empty list. Lists store things in order. + Like standing in line for popcorn. You are behind someone and you wouldn't + dream of pushing them aside, right? And the guy behind you, you've got a + close eye on him, right?

          +

          Here's a list for you. Lottery numbers: [12, 47, 35].

          +
          \[(\d+(, )?){2,}\]
          +
          +
          +

          One Raises Its Hand

          +

          A list of lottery numbers. Which one is the highest?

          +

          Try: [12, 47, 35].max.

          +
          (\d+)
          +
          +
          +

          Tucking a List Away

          +

          Good, good. But it's annoying to have to retype that list, isn't it?

          +

          Let's save our numbers inside a ticket like so: ticket = [12, 47, 35]

          +
          \[(\d+(, )?){2,}\]
          +
          +
          +

          Now Type Ticket

          +

          Now, type: ticket

          +
          \[(\d+(, )?){2,}\]
          +
          +
          +

          Saved, Tucked Away

          +

          Fantastic! You've hung on to your lotto numbers, tucking them away inside a + variable called ticket.

          +

          Let's put your lotto numbers in order, how about? Use: ticket.sort!

          +
          \[(\d+(, )?){2,}\]
          +
          +
          +

          Summary #2 is Upon Us

          +

          You had a list. You sorted the list. The ticket variable is now changed.

          +

          Did you notice that the sort! method has a big, bright exclamation at the end? + A lot of times Ruby methods shout like that if they alter the variable for good. It's nothin + special, just a mark.

          +

          Now, look how your second minute went:

          +
            +
          • Errors. If you try to reverse a number or do anything fishy, + Ruby will skip the prompt and tell you so.
          • +
          • Arrays are lists for storing things in order.
          • +
          • Variables save a thing and give it a name. You used the + equals sign to do this.
            Like: ticket = [14, 37, 18].
          • +
          +

          In all there are eight lessons. You are two-eighths of the way there! + This is simple stuff, don't you think? Good stuff up ahead.

          +

          Let's change directions for a moment. I've stuffed a bit of poetry for you in + a certain variable. Take a look. Type print poem

          +
          poem = "My toast has flown from my hand\nAnd my toast has gone to the +moon.\nBut when I saw it on television,\nPlanting our flag on Halley's +comet,\nMore still did I want to eat it.\n"
          +
          My toast (.+)
          +
          +
          +

          Sadly, You Hate Toast Poetry

          +

          Look, it's okay. You don't have to like it. Hack it up, be my guest.

          +

          Instead of toast, go for a melon or something. Try this: poem['toast'] = 'honeydew'

          +

          And then type print poem by itself to see the new poem.

          +
          My honey(.+)
          +
          +
          +

          Ready, Aim

          +

          The square brackets you just used are very common in Ruby. Remember, you typed: poem['toast'] = 'honeydew'. That box with the word toast has a square bracket on each side, see?

          +

          The +two brackets are like sights used to line up a target. Exactly. These +brackets mean, "I am looking for ____." Ready, aim. Here you're looking +for toast and swapping it out with fruit.

          +

          Here's a question: what happens when we reverse this whole poem? poem.reverse +

          "\\n.ti tae ot (.+)"
          +
          +
          +

          Too Much Reversal

          +

          Okay, sure. So the whole poem's been turned backwards, letter-by-letter. I really want to just + reverse the lines, though. Move the last line up to first and the first line down to last. Backwards, but not + that backwards.

          +

          Here's how: poem.lines.to_a.reverse

          +
          \["More still did I(.+)"\]
          +
          +
          +

          Ringlets of Chained Methods

          +

          So what do you see? What happened there? You typed poem.lines.to_a.reverse and what happened?

          +

          Two things happened. You turned the poem into a +list using lines.to_a. lines decides the way +the string is split up, then to_a converted it into an +Array. (To array.) Different methods, such +as bytes and chars can be used in place +of lines. By using lines, ruby will return each line of the poem.

          +

          Then, you reversed that list. You had each line. You reversed them. That's it.

          +

          Let's tack one more method on the end there: print poem.lines.to_a.reverse.join +

          More still did I(.+)
          +
          +
          +

          Of All the Summaries, #3 is Here Now

          +

          Good show, my friend! The join method took that list of reversed lines and put them + together into a string. (Sure, you could have also just used to_s.)

          +

          Review time.

          +
            +
          • Exclamations. Methods may have exclamations (and also question marks) + in their name. No big deal. Try: poem.include? "my hand"
          • +
          • Square brackets. Target and find things. Search and replace.
          • +
          • Chaining methods lets you get a lot more done. Break up a poem, + reverse it, reassemble it: poem.lines.to_a.reverse.join
          • +
          +

          At this point, you may want to tinker with the poem a bit more. A complete list of all + the String methods is + + here. + Go ahead and try a few (such as poem.downcase or poem.delete.)

          +

          When you're ready to move on, type: books = {}

          +
          \{\}
          +
          +
          +

          A Wee Blank Book

          +

          You've made an empty hash. (Also known as: an empty dictionary.)

          +

          We're going to stuff some miniature book reviews in this hash. Here's our rating system:

          +
            +
          • :splendid → a masterpiece.
          • +
          • :quite_good → enjoyed, sure, yes.
          • +
          • :mediocre → equal parts great and terrible.
          • +
          • :quite_not_good → notably bad.
          • +
          • :abyssmal → steaming wreck.
          • +
          +

          To rate a book, put the title in square brackets and put the rating after the equals.

          +

          For example: books["Gravity's Rainbow"] = :splendid

          +
          :\w+
          +
          +
          +

          More Bite-Size Reviews

          +

          Keep going, fill it up with reviews. And, if you want to see the whole list, + just type: books

          +

          Again, the ratings are: :splendid, :quite_good, :mediocre, + :quite_not_good, and :abyssmal.

          +

          These ratings are not strings. When you place a colon in front of a simple word, you get a + symbol. Symbols are cheaper than strings (in terms of computer memory.) If + you use a word over and over in your program, use a symbol. Rather than having thousands of + copies of that word in memory, the computer will store the symbol only once.

          +

          Once you've got three or four books in + there, type: books.length.

          +
          [3-9]
          +
          +
          +

          Wait, Did I Like Gravity's Rainbow?

          +

          See, the length method works on strings, list and hashes. One great thing about + Ruby is that names are often reused, which means fewer names you need to remember.

          +

          If you'd like to look up one of your old reviews, again put the title in the square. But leave off + the equals.

          +

          Just like this: books["Gravity's Rainbow"]

          +
          :\w+
          +
          +
          +

          Hashes as Pairs

          +

          Keep in mind that hashes won't keep things in order. That's not their job. It'll just pair up two + things: a key and a value. In your reviews, the key is the book's + title and the value is the rating.

          +

          If you want to just see the titles of the books you've reviewed: books.keys

          +
          \[".*"\]
          +
          +
          +

          Are You Harsh?

          +

          So are you giving out harsh, unfair reviews? Let's keep score with this hash:
          ratings = Hash.new {0}

          +

          Then, okay, now let's count up your reviews. Just stay with me. Type:
          + books.values.each { |rate| ratings[rate] += 1 }

          +

          (The straight line in the code is the pipe character, probably located right above the + Enter key on your keyboard.)

          +
          \[:.+\]
          +
          +
          +

          A Tally

          +

          Great, wow! You've made a scorecard of your ratings. Type ratings to see the count. + This new hash shows a rating and then the number of times you've given that rating.

          +

          One of the amazing new things we've just used is a block. We're going to + explore these more in the next summary. But, basically, a block is a bit of Ruby code surrounded + by curly braces.

          +

          Let's try another block: 5.times { print "Odelay!" }

          +
          Odelay!Od.*
          +
          +
          +

          Now Arriving at Summary #4

          +

          Blocks are always attached to methods. Like the times method, which takes the + block and runs the code over and over. (In this case: five times.)

          +

          This last lesson was a bit longer. You've probably used up three minutes learning about:

          +
            +
          • Hashes. The little dictionary with the curly pages: {}.
          • +
          • Symbols. Tiny, efficient code words with a colon: :splendid.
          • +
          • Blocks. Chunks of code which can be tacked on to many of Ruby's methods. Here's the + code you used to build a scorecard:
            books.values.each { |rate| ratings[rate] += 1 }.
          • +
          +

          On your computer, you probably have a lot of different files. Files with pictures in them, + files with programs in them. And files are often organized into folders, also called: + directories.

          +

          I've prepared a few directories for you. Take a look: + Dir.entries "/"

          +
          \["\.", .+\]
          +
          +
          +

          The Private Collection of Dr. Dir

          +

          You've just listed out everything in the top directory. The root directory, indicated + by a single slash. Containing some programs and other tutorials and such.

          +

          So, what is the Dir.entries method? Well, it's just a method, right? + entries is a method called on the Dir variable. + And Dir has a collection of methods for checking out file directories.

          +

          One other little thing we haven't really talked about openly. Method arguments, highlighted in green.

          +
            +
          • Dir.entries "/": Anything listed after a method + is considered an attachment.
          • +
          • print poem: See, print is an ordinary method. And the + poem is attached. To be printed.
          • +
          • print "pre", "event", "ual", "ism" has several arguments, with commas + between them.
          • +
          +

          To list just the text files in that directory: Dir["/*.txt"]

          +
          \["\/comics\.txt"\]
          +
          +
          +

          Come, Read Comics With Me

          +

          The Dir[] method is like entries but you search for files + with wildcard characters. Here, we see those square brackets again! Notice how + they still mean, "I am looking for _____?"

          +

          More specifically: "I am looking for files which end with .txt."

          +

          Let's crack open this comics file, then. Here's the way:
          + print File.read("/comics.txt")

          +
          Achewood.+
          +
          +
          +

          Mi Comicas, Tu Comicas

          +

          All right! We can start to use files to store things. This is great because normally when + we exit Ruby, all our variables will be gone. Ruby, by itself, forgets these things. + But if we save things in files, we can read those files in future Ruby escapades.

          +

          Hey, and guess what? The /Home directory is yours! I gave it to you! I am generous! Let's make a copy of the comics file.

          +

          You'll want to: FileUtils.copy('/comics.txt', '/Home/comics.txt') +

          If you've already created the file, use File.delete('/Home/comics.txt') to trash it.

          +
          nil
          +
          +
          +

          Your Own Turf

          +

          Okay, you've got a copy. Check it: Dir["/Home/*.txt"]

          +

          To add your own comic to the list, let's open the file in append mode.

          +

          Start like this: File.open("/Home/comics.txt", "a") do |f|.

          +
          ..
          +
          +
          +

          And Now For the Startling Conclusion

          +

          So your prompt has changed. See that? Your prompt is a double dot now.

          +

          In this tutorial, this prompt means that Ruby is expecting you to type more. + As you type in the lines of Ruby code, the double dots will continue until you + are completely finished.

          +

          Hot tip: If you want to stop working on the code and break out of the double dots, use the reset + command. If you want to go the previous page of the tutorial, use the back command.

          +

          Here's your code. You've already typed the first line, so just enter the second line. (The \n + is an Enter character.

          +
          • File.open("/Home/comics.txt", "a") do |f|
          • +
          •   f << "Cat and Girl: http://catandgirl.com/\n"
          • +
          • end
          • +
          +

          And, since you're getting so advanced and capable here, one other tip: you can use the up and down arrow keys to + edit your old commands or run them again.

          +
          ..
          +
          +
          +

          Ruby Sits Still

          +

          That last line adds the Cat and Girl comic to the list, but Ruby's going to wait until you're totally finished to + take action.

          +

          Now, to finish the code you've started. You opened a new block when you typed do. + So far the blocks we've seen have used curly braces. This time we'll be using do and end instead + of curly braces. A lot of Rubyists will use do...end when the block goes on for many lines.

          +

          Let's get that block finished now, with: end

          +
          • File.open("/Home/comics.txt", "a") do |f|
          • +
          •   f << "Cat and Girl: http://catandgirl.com/\n"
          • +
          • end
          • +
          +
          #.File:/Home/comics\.txt \(closed\).
          +
          +
          +

          The Clock Nailed To the File

          +

          Good, good! You've added that new comic to the file. You can see for yourself: print File.read("/Home/comics.txt")

          +

          What time was it when you changed the file? Let's check. Type: File.mtime("/Home/comics.txt")

          +
          \d{4}-\d+-\d+ \d{2}:\d{2}:\d{2} [+-]\d{4}
          +
          +
          +

          Just the Hour Hand

          +

          Great, there's the time. The precise time exactly when you added to the file. The mtime gives you a Ruby Time object.

          +

          If you want to check just what hour it was, hit the up arrow key and change the line to: File.mtime("/Home/comics.txt").hour

          +
          \d+
          +
          +
          +

          Hallo, Who's There? And Summary #5 Waves Its Hat!

          +

          Well done, well done, well done, well done! Truly, truly, truly, truly, truuuuuuuuly!

          +

          Here's the last few minutes of your life in review:

          +
            +
          • Files. What more can be said? Lots of methods for editing files and lookin around in directories.
          • +
          • Arguments. Arguments are a list of things sent into a method. With commas between.
          • +
          • We also spoke about do and end which are another way to make a block.
          • +
          +

          You totally know how to use Ruby now. I mean you've got down the essentials. You just need to keep learning more methods and + try out more complex blocks.

          +

          But there's one side of Ruby we haven't settled. Making your own methods and classes.

          +

          Ahem! Let's get it over with then.

          +

          Start with: def load_comics( path )

          +
          ..
          +
          +
          +

          In Ruby, Def Leppard Means Define Leppard (a Method)!

          +

          Hey, okay, you done it. You're making your own method. You started with def, followed by the name of the method. + And a list of arguments which the method will need. This isn't too scary and dangerous!

          +

          All we have to do is fill it up with Ruby and finish it up with end.

          +

          Here's the code:

          +
          • def load_comics( path )
          • +
          •   comics = {}
          • +
          •   File.foreach(path) do |line|
          • +
          •     name, url = line.split(': ')
          • +
          •     comics[name] = url.strip
          • +
          •   end
          • +
          •   comics
          • +
          • end
          • +
          +

          No need to indent, if you don't want. I just do that to make it read easier.

          +
          nil
          +
          +
          +

          The Ripened Fruit of Your Own Creation

          +

          A new method is born. Let us use it: comics = load_comics('/comics.txt')

          +

          If you have a problem, you might have mistyped. Use the back command and try again.

          +
          \{.*"Achewood"=."http://achewood.com/".*\}
          +
          +
          +

          Hey, Cool, a Comics Thing

          +

          In your Ruby window above, look at the code you've typed for the load_comics method. What is happening? You're + passing in the path variable and you're getting back the comics variable. Ruby lets the comics + hash trickle out the end of the method.

          +

          A number of methods were used to get the job done. See if you can spot them.

          +
          • File.foreach is a method which opens a file and hands each line to the block. The line + variable inside the do...end block took turns with each line in the file.
          • +
          • split is a method for strings, which breaks the string up into an array. An axe is laid on the colon + and the line is chopped in half, giving us the url and name for each comic.
          • +
          • strip removes extra spaces around the name. Just in case.
          • +
          +

          Right on. Bravo. You've got the comics in a Ruby hash. But what now? What good is this really?

          +

          Let's make a page of links. How about that? I went ahead and loaded a little library I've made for you.

          +

          Type: next. This is temporary as I updates new lessons.

          +
          true
          +
          +
          +

          Browser Puppetry

          +

          Excellent, you've loaded the popup library. It's saved in a file in the Libraries folder. See: Dir["/Libraries/*"]

          +

          The popup library contains a bunch of methods I've written which let you control a popup here on the Try Ruby site.

          +

          Here, try this: Popup.goto "http://google.com/"

          +
          \033\[1;JSm.*popup_goto\(.*\)\033\[m.*
          +
          +
          +

          Making Links and Spinning Webs

          +

          Our own lovely, little popup to manipulate. You can also fill it with your own goodies. We'll start small:

          +
          • Popup.make {
          • +
          •   h1 "My Links"
          • +
          •   link "Go to Google", "http://google.com/"
          • +
          • }
          • +
          +

          The term h1 (h-one) means a level-one header. In HTML, this is the largest size of header.

          +
          \033\[1;JSm.*popup_make\(.*h1.*a href.*\)\033\[m.*
          +
          +
          +

          Popups Are So Easy, It's Crazy

          +

          Looks good, you did it perfectly, just as you were asked. Let's make a list then.

          +

          Here's how you make a list with the popup library:

          +
          • Popup.make do
          • +
          •   h1 "Things To Do"
          • +
          •   list do
          • +
          •     p "Try out Ruby"
          • +
          •     p "Ride a tiger"
          • +
          •     p "(down River Euphrates)"
          • +
          •   end
          • +
          • end
          • +
          +

          The p method is short for "paragraph".

          +
          \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*li.*\)\033\[m.*
          +
          +
          +

          Spread the Comics on the Table

          +

          Okay, this is coming along wonderfully. This is simple stuff, but keep in mind that you didn't know any Ruby whatsoever just fifteen minutes ago!

          +

          Last +step. Let's tie it all together, you know? Let's make it chime together +like a very nice set of glistening chimes on the beach in the +maginificent sunlight!

          +

          Make sure the comics are loaded: comics = load_comics( '/comics.txt' )

          +

          Now, let's make a list of the links to each comic:

          +
          • Popup.make do
          • +
          •   h1 "Comics on the Web"
          • +
          •   list do
          • +
          •     comics.each do |name, url|
          • +
          •       link name, url
          • +
          •     end
          • +
          •   end
          • +
          • end
          • +
          +

          You can click on the links and read the comics in the little window even! Smashing!

          +
          \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*a href.*li.*a href.*\)\033\[m.*
          +
          +
          +

          Summary #6 Which Means You've Come So Far

          +

          You're a level six Ruby cleric. I mean what a great job you've done. Let's review:

          +
            +
          • You added your own method with def and you used that load_comics method several times.
          • +
          • Libraries. You used the require method to load the popup library.
            By typing: require 'popup'
          • +
          • And if that wasn't enough, you made your own web page from a list of comics in a file. You made a real program!
          • +
          +

          So +what could possibly be next? What could you possibly have to learn now? +Ha, this is the best part. You've come such a long way that we're going +to uncover classes. For two more short lessons and you're done.

          +

          Earlier, we created a hash like this: Hash.new Try it.

          +
          \{\}
          +
          +
          +

          Not a School Class, a Working Class

          +

          You see, the empty curly braces {} is a shortcut for Hash.new. The new +method is used to make objects of a certain class. (Think "class" as in +"working class" — a specific group of objects which are similar, have +the same jobs, the same shirts.)

          +

          Ask yourself this: How would I make a blog in Ruby? +Where would you start? Well, you might store your blog entries in a +file, right? But how would you keep track of the title of the entry and +the time it was posted? And when you loaded the file, how would it look +in Ruby? Would it be a Hash? Or an Array? Or an Array of Arrays? Or +something else?

          I really think you'll want to use a class. You are already familiar with many classes: Hash, Array, String.

          +

          Let's make a new class: class BlogEntry.

          +
          ..
          +
          +
          +

          The Stuff Blogs are Made of

          +

          You've opened up a new BlogEntry class. What is your blog entry made of? A title, sure. Also, a time when the entry was posted. The + full text of the entry.

          +

          We'll do a mood setting, too, just like LiveJournal. The Internet has really brought back stick people and smileys + out of bankruptcy. Emote!

          +

          Okay, so you've got the first line of the class, here's the rest:

          +
          • class BlogEntry
          • +
          •   attr_accessor :title, :time, :fulltext, :mood
          • +
          • end
          • +
          +
          nil
          +
          +
          +

          Accessors Are the Dangling Limbs

          +

          Hey, good class, man. You've got a new BlogEntry class. To start an entry:
          entry = BlogEntry.new.

          +

          In the class definition, you used a method called attr_accessor. There are many attribute methods like + this which add little settings to classes. These attributes are just variables attached to a class.

          +

          Think +of it this way. A class is like a person. That star-shaped human thing +out there. And the attributes are the dangling limbs, the different +parts that make up a body.

          +

          To set the title of your entry: entry.title = "Today Mt. Hood Was Stolen!"

          +
          ".+"
          +
          +
          +

          An Object, That Neat Little Package

          +

          Go ahead and set the post time: entry.time = Time.now

          +

          And the mood: entry.mood = :sick

          +

          And the post itself: entry.fulltext = "I can't believe Mt. Hood was stolen! I am speechless! It was stolen by a giraffe who drove away + in his Cadillac Seville very nonchalant!!"

          +

          To see all your settings, just type at the prompt: entry.

          +
          #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
          +
          +
          +

          Quickening it Up

          +

          Cool, +you're blog is awesome. Hey, let's make things a bit easier on you. +You're not going to want to set the time like that every time you post. +You just want to type in the title and the entry and the mood quickly, +right?

          +

          Let's add an initialize method.

          +
          • class BlogEntry
          • +
          •   def initialize( title, mood, fulltext )
          • +
          •     @time = Time.now
          • +
          •     @title, @mood, @fulltext = title, mood, fulltext
          • +
          •   end
          • +
          • end
          • +
          +

          Once you've got that typed in, try making a new entry: BlogEntry.new

          +
          ArgumentError: wrong number of arguments \(0 for 3\).*
          +
          +
          +

          You've Taught Your Blog to Reject Worthless Things

          +

          Did you see how inside the class we used the at-symbols? Like this: @time = Time.now

          +

          Outside the class, we use accessors: entry.time = Time.now But inside we use instance variables: @time = Time.now + They're the exact same thing, but expressed in two different places of your program.

          +

          Your blog now needs a title, a mood and a post in order to work. When a new BlogEntry is created, the initialize method + is used to check for any arguments to new. Uh, we need three arguments!

          +

          Try it again with all three.

          +

          entry2 += BlogEntry.new( "I Left my Hoodie on the Mountain!", :confused, "I am +never going back to that mountain and I hope a giraffe steals it." )

          +
          #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
          +
          +
          +

          A Giraffe Has Not Stolen Summary #7

          +

          Aha, you're here. And all in one piece. We're still going to make your blog real, but until then, let's review, okay?

          +
            +
          • Classes. Everything in Ruby is some kind of object. Classes explain objects. How a certain object works. + For example, you made a few blog entry objects and these objects are explained in the BlogEntry class. + In other words: you call them BlogEntry objects.
          • +
          • Accessors are variables attached to an object which can be used outside the object. (entry.time = Time.now)
          • +
          • Instance variables are the same variables you're using for accessors when inside the object. + Like in a method definition. (@time = Time.now)
          • +
          +

          Okay, +let's wrap things up, kid. Here's the last chapter of the GRIPPING epic +story of Try Ruby! Now that you've got a taste of how it all works, how +are you going to use it around the house and in your grocer's freezer? +You're a great person (one of my favorites), but you need guidance.

          +

          Let's finish your blog. You have blog entries, but no actual blog.

          +

          Put the entries into an array: blog = [entry, entry2]

          +
          \[#.BlogEntry:0x[0-9a-f]+.*, #.BlogEntry:0x[0-9a-f]+.*\]
          +
          +
          +

          It's All About Combining Things

          +

          Some +beautiful things can be done with the simple parts of Ruby, especially +when you combine them together into new things. Here we've got a blog +made of an array of classes. And, actually, Ruby really does good with +this kind of creature.

          +

          Here's a few things you can do with your array blog:

          +
          • You'll want to sort your entries from newest to oldest. You can do this with:
            + blog.sort_by { |entry| entry.time }.reverse
            See the sort_by explanation for more.
          • +
          • If you want to search your blog for anything related to "cadillac":
            + blog.find_all { |entry| entry.fulltext.match(/cadillac/i) }
            + Read all about find_all + and match + to figure out how that works. Also: the slashy /giraffe/i is a Regexp object, used for matching words.
          • +
          • Add new entries with blog << new_entry
            + And check out the << method documentation.
          • +
          +

          You can browse a list of all Ruby's built-in methods at ruby-doc.org's core list. + Another good list is at the online pickaxe.

          +

          One really useful method (I probably use this more than anything else) is map. Type: blog.map { |entry| entry.mood }

          +
          \[(:\w+, )+:\w+\]
          +
          +
          +

          Look at His Face — The Transformation Has Begun

          +

          The map method cycles through an array and replaces each item with something new. Say you wanted to replace each of your blog entries + with the name Bruce Willis. Do it so: blog.map { "Bruce Willis" }

          +

          Since the block always returns the string "Bruce Willis", that's what you get. In the code you just used, the entry was swapped out + for only the entry.mood.

          +

          Now, +I want you to make a popup with your blog entries. I'm not going to +give you all of the code. I'm just going to give you part of it.

          +
          • blog.each do |entry|
          • +
          •   h2 entry.title
          • +
          •   p entry.fulltext
          • +
          • end
          • +
          +

          Now, I expect you to put the popup code around it and add an h1 title with the name of your blog. For extra haroompf, have the time of each entry display.

          +
          \033\[1;JSm.*popup_make\(.*h1.*h2.*li.*h2.*li.*\)\033\[m.*
          +
          +
          +

          You are Some Kind of Web Guru, I Have Stars in My Eyes

          +

          Good, +that's it! This is exactly the code you can use to write your own real +Ruby blog. If you're feeling adventurous, I'd check out the Rails videos which show a swift young fellow creating a blog in 15 minutes. You just sit back and watch.

          +

          I +should mention Rails. You have been learning the Ruby language, how to +speak it. But Rails is a bunch of libraries (sort of like the popup +library we've been using.) It's a very powerful toolkit for building +websites. If you're interested in learning about Rails, I would head + over there right away. Start using your Ruby skills proper!

          +

          One thing Rails has is easy methods for dates. Like, try: Time.now - 2.weeks

          +
          class Integer; def weeks; self * 7*24*60*60; end; end
          +
          \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-+]\d{4}
          +
          +
          +

          If You Want to Start Small

          +

          If you'd like to start writing little Ruby programs just to practice, I have a project called MouseHole + which is a little web toolkit for writing short Ruby programs. You can look over a few + scripts to see what I mean.

          +

          MouseHole +isn't for writing web sites really. It's just for writing little +programs you run inside your browser. Like there's a notepad program +for MouseHole and a program which adds a mouse picture next to links on +the web which link to MouseHole programs.

          +

          I've got a MouseHole script inside a file here:
          + print File.read("/MouseHole/flickrpedia.user.rb")

          +
          .*Inserts Wikipedia links for Flickr tags.*
          +
          +
          +

          Summary #8, The Hey-Relax-You-Did-Good Summary

          +

          This last section took a moment to wind down, to give you some pointers as to how you can use Ruby. If you enjoyed yourself, + download Ruby and install it.

          + +

          Once you have Ruby installed, you can use Interactive Ruby by running irb on your system's prompt. For more on Irb, + there's The Tiger's Vest to help you.

          +

          You +really deserve a double-layer cake with double-double frosting and a +guy playing one of those guitars that's a double guitar. I mean you +finished, you really did! No doubt about it, you're a certified +red-blooded smartiac!

          +
          +
          + + diff --git a/non-rack-legacy/public/tutorials/intro.html.broken b/non-rack-legacy/public/tutorials/intro.html.broken new file mode 100755 index 0000000..5a6c27c --- /dev/null +++ b/non-rack-legacy/public/tutorials/intro.html.broken @@ -0,0 +1,638 @@ + +
          +

          Using the Prompt

          +

          The blue window above is a Ruby prompt. Type a line of Ruby code, hit Enter + and watch it run!

          +

          For example, try typing some math. Like: 2 + 6

          +
          \d+
          +
          +
          +

          Numbers & Math

          +

          Good! You did a bit of math. See how the answer popped out?

          +

          Ruby recognizes numbers and mathematic symbols. You could try some other math like:

          +
          • 4 * 10
          • +
          • 5 - 12
          • +
          • 40 / 4
          +

          Sure, computers are handy and fast for math. Let's move on. Want to see your name reversed? + Type your first name in quotes like this: "Jimmy"

          +
          "(\w+)"
          +
          +
          +

          Say Your Name Backwards

          +

          Perfect, you've formed a string from the letters of your name. A string + is a set of characters the computer can process.

          +

          Imagine the letters are on a string of + laundry line and the quotes are clothespins holding the ends. The quotes mark the beginning and end.

          +

          To reverse your name, type: "Jimmy".reverse (Don't forget the dot!)

          +
          "(\w+)"
          +
          +
          +

          Counting the Letters

          +

          You have used the reverse method on your name! By enclosing your name in + quotes, you made a string. Then you called the reverse method, which works on strings to flip + all the letters backwards.

          +

          Now, let's see how many letters are in your name: "Jimmy".length

          +
          \d+
          +
          +
          +

          On Repeat

          +

          Now, I'm sure by now you're wondering what any of this is good for. Well, I'm sure you've been to + a website that screamed, Hey, your password is too short! See, some programs + use this simple code.

          +

          Watch this. Let's multiply your name by 5. "Jimmy" * 5

          +
          "(\w+)"
          +
          +
          +

          Hey, Summary #1 Already

          +

          Let's look at what you've learned in the first minute.

          +
            +
          • The prompt. Typing code into the green prompt gives you + an answer from a red prompt. All code gives an answer.
          • +
          • Numbers and strings are Ruby's math and text objects.
          • +
          • Methods. You've used English-language methods like reverse + and symbolic methods like * (the multiplication method.) Methods are action!
          • +
          +

          This is the essence of your learning. Taking simple things, toying with + them and turning them into new things. Feeling comfortable yet? I promise you are.

          +

          Okay, let's do something uncomfortable. Try reversing a number: 40.reverse

          +
          NoMethodError: undefined method `reverse' for (\d+):Fixnum
          +
          +
          +

          Stop, You're Barking Mad!

          +

          You can't reverse the number forty. I guess you can hold your monitor up to the + mirror, but reversing a number just doesn't make sense. Ruby has tossed an error + message. Ruby is telling you there is no method reverse for numbers.

          +

          Maybe if you turn it into a string: 40.to_s.reverse.

          +
          \"(\d+)\"
          +
          +
          +

          Boys are Different From Girls

          +

          And numbers are different from strings. While you can use methods on any object + in Ruby, some methods only work on certain types of things. But you can always + convert between different types using Ruby's "to" methods.

          +
          • to_s converts things to strings.
          • +
          • to_i converts things to integers (numbers.)
          • +
          • to_a converts things to arrays.
          • +
          +

          What are arrays?! They are lists. Type in a pair of brackets: [].

          +
          \[\]
          +
          +
          +

          Standing in Line

          +

          Great, that's an empty list. Lists store things in order. + Like standing in line for popcorn. You are behind someone and you wouldn't + dream of pushing them aside, right? And the guy behind you, you've got a + close eye on him, right?

          +

          Here's a list for you. Lottery numbers: [12, 47, 35].

          +
          \[(\d+(, )?){2,}\]
          +
          +
          +

          One Raises Its Hand

          +

          A list of lottery numbers. Which one is the highest?

          +

          Try: [12, 47, 35].max.

          +
          (\d+)
          +
          +
          +

          Tucking a List Away

          +

          Good, good. But it's annoying to have to retype that list, isn't it?

          +

          Let's save our numbers inside a ticket like so: ticket = [12, 47, 35]

          +
          \[(\d+(, )?){2,}\]
          +
          +
          +

          Now Type Ticket

          +

          Now, type: ticket

          +
          \[(\d+(, )?){2,}\]
          +
          +
          +

          Saved, Tucked Away

          +

          Fantastic! You've hung on to your lotto numbers, tucking them away inside a + variable called ticket.

          +

          Let's put your lotto numbers in order, how about? Use: ticket.sort!

          +
          \[(\d+(, )?){2,}\]
          +
          +
          +

          Summary #2 is Upon Us

          +

          You had a list. You sorted the list. The ticket variable is now changed.

          +

          Did you notice that the sort! method has a big, bright exclamation at the end? + A lot of times Ruby methods shout like that if they alter the variable for good. It's nothin + special, just a mark.

          +

          Now, look how your second minute went:

          +
            +
          • Errors. If you try to reverse a number or do anything fishy, + Ruby will skip the prompt and tell you so.
          • +
          • Arrays are lists for storing things in order.
          • +
          • Variables save a thing and give it a name. You used the + equals sign to do this.
            Like: ticket = [14, 37, 18].
          • +
          +

          In all there are eight lessons. You are two-eighths of the way there! + This is simple stuff, don't you think? Good stuff up ahead.

          +

          Let's change directions for a moment. I've stuffed a bit of poetry for you in + a certain variable. Take a look. Type print poem

          +
          poem = "My toast has flown from my hand\nAnd my toast has gone to the +moon.\nBut when I saw it on television,\nPlanting our flag on Halley's +comet,\nMore still did I want to eat it.\n"
          +
          My toast (.+)
          +
          +
          +

          Sadly, You Hate Toast Poetry

          +

          Look, it's okay. You don't have to like it. Hack it up, be my guest.

          +

          Instead of toast, go for a melon or something. Try this: poem['toast'] = 'honeydew'

          +

          And then type print poem by itself to see the new poem.

          +
          My honey(.+)
          +
          +
          +

          Ready, Aim

          +

          The square brackets you just used are very common in Ruby. Remember, you typed: poem['toast'] = 'honeydew'. That box with the word toast has a square bracket on each side, see?

          +

          The +two brackets are like sights used to line up a target. Exactly. These +brackets mean, "I am looking for ____." Ready, aim. Here you're looking +for toast and swapping it out with fruit.

          +

          Here's a question: what happens when we reverse this whole poem? poem.reverse +

          "\\n.ti tae ot (.+)"
          +
          +
          +

          Too Much Reversal

          +

          Okay, sure. So the whole poem's been turned backwards, letter-by-letter. I really want to just + reverse the lines, though. Move the last line up to first and the first line down to last. Backwards, but not + that backwards.

          +

          Here's how: poem.lines.to_a.reverse

          +
          \["More still did I(.+)"\]
          +
          +
          +

          Ringlets of Chained Methods

          +

          So what do you see? What happened there? You typed poem.lines.to_a.reverse and what happened?

          +

          Two things happened. You turned the poem into a +list using lines.to_a. lines decides the way +the string is split up, then to_a converted it into an +Array. (To array.) Different methods, such +as bytes and chars can be used in place +of lines. By using lines, ruby will return each line of the poem.

          +

          Then, you reversed that list. You had each line. You reversed them. That's it.

          +

          Let's tack one more method on the end there: print poem.lines.to_a.reverse.join +

          More still did I(.+)
          +
          +
          +

          Of All the Summaries, #3 is Here Now

          +

          Good show, my friend! The join method took that list of reversed lines and put them + together into a string. (Sure, you could have also just used to_s.)

          +

          Review time.

          +
            +
          • Exclamations. Methods may have exclamations (and also question marks) + in their name. No big deal. Try: poem.include? "my hand"
          • +
          • Square brackets. Target and find things. Search and replace.
          • +
          • Chaining methods lets you get a lot more done. Break up a poem, + reverse it, reassemble it: poem.lines.to_a.reverse.join
          • +
          +

          At this point, you may want to tinker with the poem a bit more. A complete list of all + the String methods is + + here. + Go ahead and try a few (such as poem.downcase or poem.delete.)

          +

          When you're ready to move on, type: books = {}

          +
          \{\}
          +
          +
          +

          A Wee Blank Book

          +

          You've made an empty hash. (Also known as: an empty dictionary.)

          +

          We're going to stuff some miniature book reviews in this hash. Here's our rating system:

          +
            +
          • :splendid → a masterpiece.
          • +
          • :quite_good → enjoyed, sure, yes.
          • +
          • :mediocre → equal parts great and terrible.
          • +
          • :quite_not_good → notably bad.
          • +
          • :abyssmal → steaming wreck.
          • +
          +

          To rate a book, put the title in square brackets and put the rating after the equals.

          +

          For example: books["Gravity's Rainbow"] = :splendid

          +
          :\w+
          +
          +
          +

          More Bite-Size Reviews

          +

          Keep going, fill it up with reviews. And, if you want to see the whole list, + just type: books

          +

          Again, the ratings are: :splendid, :quite_good, :mediocre, + :quite_not_good, and :abyssmal.

          +

          These ratings are not strings. When you place a colon in front of a simple word, you get a + symbol. Symbols are cheaper than strings (in terms of computer memory.) If + you use a word over and over in your program, use a symbol. Rather than having thousands of + copies of that word in memory, the computer will store the symbol only once.

          +

          Once you've got three or four books in + there, type: books.length.

          +
          [3-9]
          +
          +
          +

          Wait, Did I Like Gravity's Rainbow?

          +

          See, the length method works on strings, list and hashes. One great thing about + Ruby is that names are often reused, which means fewer names you need to remember.

          +

          If you'd like to look up one of your old reviews, again put the title in the square. But leave off + the equals.

          +

          Just like this: books["Gravity's Rainbow"]

          +
          :\w+
          +
          +
          +

          Hashes as Pairs

          +

          Keep in mind that hashes won't keep things in order. That's not their job. It'll just pair up two + things: a key and a value. In your reviews, the key is the book's + title and the value is the rating.

          +

          If you want to just see the titles of the books you've reviewed: books.keys

          +
          \[".*"\]
          +
          +
          +

          Are You Harsh?

          +

          So are you giving out harsh, unfair reviews? Let's keep score with this hash:
          ratings = Hash.new {0}

          +

          Then, okay, now let's count up your reviews. Just stay with me. Type:
          + books.values.each { |rate| ratings[rate] += 1 }

          +

          (The straight line in the code is the pipe character, probably located right above the + Enter key on your keyboard.)

          +
          \[:.+\]
          +
          +
          +

          A Tally

          +

          Great, wow! You've made a scorecard of your ratings. Type ratings to see the count. + This new hash shows a rating and then the number of times you've given that rating.

          +

          One of the amazing new things we've just used is a block. We're going to + explore these more in the next summary. But, basically, a block is a bit of Ruby code surrounded + by curly braces.

          +

          Let's try another block: 5.times { print "Odelay!" }

          +
          Odelay!Od.*
          +
          +
          +

          Now Arriving at Summary #4

          +

          Blocks are always attached to methods. Like the times method, which takes the + block and runs the code over and over. (In this case: five times.)

          +

          This last lesson was a bit longer. You've probably used up three minutes learning about:

          +
            +
          • Hashes. The little dictionary with the curly pages: {}.
          • +
          • Symbols. Tiny, efficient code words with a colon: :splendid.
          • +
          • Blocks. Chunks of code which can be tacked on to many of Ruby's methods. Here's the + code you used to build a scorecard:
            books.values.each { |rate| ratings[rate] += 1 }.
          • +
          +<<<<<<< HEAD + + +======= +

          On your computer, you probably have a lot of different files. Files with pictures in them, + files with programs in them. And files are often organized into folders, also called: + directories.

          +

          I've prepared a few directories for you. Take a look: + Dir.entries "/"

          +
          \["\.", .+\]
          +
          +
          +

          The Private Collection of Dr. Dir

          +

          You've just listed out everything in the top directory. The root directory, indicated + by a single slash. Containing some programs and other tutorials and such.

          +

          So, what is the Dir.entries method? Well, it's just a method, right? + entries is a method called on the Dir variable. + And Dir has a collection of methods for checking out file directories.

          +

          One other little thing we haven't really talked about openly. Method arguments, highlighted in green.

          +
            +
          • Dir.entries "/": Anything listed after a method + is considered an attachment.
          • +
          • print poem: See, print is an ordinary method. And the + poem is attached. To be printed.
          • +
          • print "pre", "event", "ual", "ism" has several arguments, with commas + between them.
          • +
          +

          To list just the text files in that directory: Dir["/*.txt"]

          +
          \["\/comics\.txt"\]
          +
          +
          +

          Come, Read Comics With Me

          +

          The Dir[] method is like entries but you search for files + with wildcard characters. Here, we see those square brackets again! Notice how + they still mean, "I am looking for _____?"

          +

          More specifically: "I am looking for files which end with .txt."

          +

          Let's crack open this comics file, then. Here's the way:
          + print File.read("/comics.txt")

          +
          Achewood.+
          +
          +
          +

          Mi Comicas, Tu Comicas

          +

          All right! We can start to use files to store things. This is great because normally when + we exit Ruby, all our variables will be gone. Ruby, by itself, forgets these things. + But if we save things in files, we can read those files in future Ruby escapades.

          +

          Hey, and guess what? The /Home directory is yours! I gave it to you! I am generous! Let's make a copy of the comics file.

          +

          You'll want to: FileUtils.copy('/comics.txt', '/Home/comics.txt') +

          If you've already created the file, use File.delete('/Home/comics.txt') to trash it.

          +
          nil
          +
          +
          +

          Your Own Turf

          +

          Okay, you've got a copy. Check it: Dir["/Home/*.txt"]

          +

          To add your own comic to the list, let's open the file in append mode.

          +

          Start like this: File.open("/Home/comics.txt", "a") do |f|.

          +
          ..
          +
          +
          +

          And Now For the Startling Conclusion

          +

          So your prompt has changed. See that? Your prompt is a double dot now.

          +

          In this tutorial, this prompt means that Ruby is expecting you to type more. + As you type in the lines of Ruby code, the double dots will continue until you + are completely finished.

          +

          Hot tip: If you want to stop working on the code and break out of the double dots, use the reset + command. If you want to go the previous page of the tutorial, use the back command.

          +

          Here's your code. You've already typed the first line, so just enter the second line. (The \n + is an Enter character.

          +
          • File.open("/Home/comics.txt", "a") do |f|
          • +
          •   f << "Cat and Girl: http://catandgirl.com/\n"
          • +
          • end
          • +
          +

          And, since you're getting so advanced and capable here, one other tip: you can use the up and down arrow keys to + edit your old commands or run them again.

          +
          ..
          +
          +
          +

          Ruby Sits Still

          +

          That last line adds the Cat and Girl comic to the list, but Ruby's going to wait until you're totally finished to + take action.

          +

          Now, to finish the code you've started. You opened a new block when you typed do. + So far the blocks we've seen have used curly braces. This time we'll be using do and end instead + of curly braces. A lot of Rubyists will use do...end when the block goes on for many lines.

          +

          Let's get that block finished now, with: end

          +
          • File.open("/Home/comics.txt", "a") do |f|
          • +
          •   f << "Cat and Girl: http://catandgirl.com/\n"
          • +
          • end
          • +
          +
          #.File:/Home/comics\.txt \(closed\).
          +
          +
          +

          The Clock Nailed To the File

          +

          Good, good! You've added that new comic to the file. You can see for yourself: print File.read("/Home/comics.txt")

          +

          What time was it when you changed the file? Let's check. Type: File.mtime("/Home/comics.txt")

          +
          \d{4}-\d+-\d+ \d{2}:\d{2}:\d{2} [+-]\d{4}
          +
          +
          +

          Just the Hour Hand

          +

          Great, there's the time. The precise time exactly when you added to the file. The mtime gives you a Ruby Time object.

          +

          If you want to check just what hour it was, hit the up arrow key and change the line to: File.mtime("/Home/comics.txt").hour

          +
          \d+
          +>>>>>>> nanothief/master +
          + +
          +

          Hallo, Who's There? And Summary #5 Waves Its Hat!

          +

          Well done, well done, well done, well done! Truly, truly, truly, truly, truuuuuuuuly!

          +

          Here's the last few minutes of your life in review:

          +
            +
          • Arguments. Arguments are a list of things sent into a method. With commas between.
          • +
          • We also spoke about do and end which are another way to make a block.
          • +
          +

          You totally know how to use Ruby now. I mean you've got down the essentials. You just need to keep learning more methods and + try out more complex blocks.

          +

          But there's one side of Ruby we haven't settled. Making your own methods and classes.

          +

          Ahem! Let's get it over with then.

          +
          +
          +

          In Ruby, Def Leppard Means Define Leppard (a Method)!

          +

          Hey, okay, you done it. You're making your own method. You started with def, followed by the name of the method. + And a list of arguments which the method will need. This isn't too scary and dangerous!

          +

          All we have to do is fill it up with Ruby and finish it up with end.

          +
          +
          +

          Hey, Cool, a Popup

          +

          Let's make a page of links. How about that? We'll need to load a little library I've made for you.

          +

          Type: require 'popup'

          +
          true
          +
          +
          +

          Browser Puppetry

          +

          Excellent, you've loaded the popup library.

          +

          The popup library contains a bunch of methods I've written which let you control a popup here on the Try Ruby site.

          +

          Here, try this: Popup.goto "http://google.com/"

          +
          \033\[1;JSm.*popup_goto\(.*\)\033\[m.*
          +
          +
          +

          Making Links and Spinning Webs

          +

          Our own lovely, little popup to manipulate. You can also fill it with your own goodies. We'll start small:

          +
          • Popup.make {
          • +
          •   h1 "My Links"
          • +
          •   link "Go to Google", "http://google.com/"
          • +
          • }
          • +
          +

          The term h1 (h-one) means a level-one header. In HTML, this is the largest size of header.

          +
          \033\[1;JSm.*popup_make\(.*h1.*a href.*\)\033\[m.*
          +
          +
          +

          Popups Are So Easy, It's Crazy

          +

          Looks good, you did it perfectly, just as you were asked. Let's make a list then.

          +

          Here's how you make a list with the popup library:

          +
          • Popup.make do
          • +
          •   h1 "Things To Do"
          • +
          •   list do
          • +
          •     p "Try out Ruby"
          • +
          •     p "Ride a tiger"
          • +
          •     p "(down River Euphrates)"
          • +
          •   end
          • +
          • end
          • +
          +

          The p method is short for "paragraph".

          +
          \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*li.*\)\033\[m.*
          +
          +
          +

          Spread the Comics on the Table

          +

          Okay, this is coming along wonderfully. This is simple stuff, but keep in mind that you didn't know any Ruby whatsoever just fifteen minutes ago!

          +

          Last +step. Let's tie it all together, you know? Let's make it chime together +like a very nice set of glistening chimes on the beach in the +maginificent sunlight!

          +

          Now, let's make a list of the links to each comic:

          +
          • Popup.make do
          • +
          •   h1 "Comics on the Web"
          • +
          •   list do
          • +
          •     comics.each do |name, url|
          • +
          •       link name, url
          • +
          •     end
          • +
          •   end
          • +
          • end
          • +
          +

          You can click on the links and read the comics in the little window even! Smashing!

          +
          \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*a href.*li.*a href.*\)\033\[m.*
          +
          +
          +

          Summary #6 Which Means You've Come So Far

          +

          You're a level six Ruby cleric. I mean what a great job you've done. Let's review:

          +
            +
          • You added your own method with def and you used that [coming soon]
          • +
          • You used the require method to load the popup library.
            By typing: require 'popup'
          • +
          • And if that wasn't enough, you made your own web page from a list of comics in a file no you havent. You made a real program!
          • +
          +

          So +what could possibly be next? What could you possibly have to learn now? +Ha, this is the best part. You've come such a long way that we're going +to uncover classes. For two more short lessons and you're done.

          +

          Earlier, we created a hash like this: Hash.new Try it.

          +
          \{\}
          +
          +
          +

          Not a School Class, a Working Class

          +

          You see, the empty curly braces {} is a shortcut for Hash.new. The new +method is used to make objects of a certain class. (Think "class" as in +"working class" — a specific group of objects which are similar, have +the same jobs, the same shirts.)

          +

          Ask yourself this: How would I make a blog in Ruby? +Where would you start? Well, you might store your blog entries in a +file, right? But how would you keep track of the title of the entry and +the time it was posted? And when you loaded the file, how would it look +in Ruby? Would it be a Hash? Or an Array? Or an Array of Arrays? Or +something else?

          I really think you'll want to use a class. You are already familiar with many classes: Hash, Array, String.

          +

          Let's make a new class: class BlogEntry.

          +
          ..
          +
          +
          +

          The Stuff Blogs are Made of

          +

          You've opened up a new BlogEntry class. What is your blog entry made of? A title, sure. Also, a time when the entry was posted. The + full text of the entry.

          +

          We'll do a mood setting, too, just like LiveJournal. The Internet has really brought back stick people and smileys + out of bankruptcy. Emote!

          +

          Okay, so you've got the first line of the class, here's the rest:

          +
          • class BlogEntry
          • +
          •   attr_accessor :title, :time, :fulltext, :mood
          • +
          • end
          • +
          +
          nil
          +
          +
          +

          Accessors Are the Dangling Limbs

          +

          Hey, good class, man. You've got a new BlogEntry class. To start an entry:
          entry = BlogEntry.new.

          +

          In the class definition, you used a method called attr_accessor. There are many attribute methods like + this which add little settings to classes. These attributes are just variables attached to a class.

          +

          Think +of it this way. A class is like a person. That star-shaped human thing +out there. And the attributes are the dangling limbs, the different +parts that make up a body.

          +

          To set the title of your entry: entry.title = "Today Mt. Hood Was Stolen!"

          +
          ".+"
          +
          +
          +

          An Object, That Neat Little Package

          +

          Go ahead and set the post time: entry.time = Time.now

          +

          And the mood: entry.mood = :sick

          +

          And the post itself: entry.fulltext = "I can't believe Mt. Hood was stolen! I am speechless! It was stolen by a giraffe who drove away + in his Cadillac Seville very nonchalant!!"

          +

          To see all your settings, just type at the prompt: entry.

          +
          #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
          +
          +
          +

          Quickening it Up

          +

          Cool, +you're blog is awesome. Hey, let's make things a bit easier on you. +You're not going to want to set the time like that every time you post. +You just want to type in the title and the entry and the mood quickly, +right?

          +

          Let's add an initialize method.

          +
          • class BlogEntry
          • +
          •   def initialize( title, mood, fulltext )
          • +
          •     @time = Time.now
          • +
          •     @title, @mood, @fulltext = title, mood, fulltext
          • +
          •   end
          • +
          • end
          • +
          +

          Once you've got that typed in, try making a new entry: BlogEntry.new

          +
          ArgumentError: wrong number of arguments \(0 for 3\).*
          +
          +
          +

          You've Taught Your Blog to Reject Worthless Things

          +

          Did you see how inside the class we used the at-symbols? Like this: @time = Time.now

          +

          Outside the class, we use accessors: entry.time = Time.now But inside we use instance variables: @time = Time.now + They're the exact same thing, but expressed in two different places of your program.

          +

          Your blog now needs a title, a mood and a post in order to work. When a new BlogEntry is created, the initialize method + is used to check for any arguments to new. Uh, we need three arguments!

          +

          Try it again with all three.

          +

          entry2 += BlogEntry.new( "I Left my Hoodie on the Mountain!", :confused, "I am +never going back to that mountain and I hope a giraffe steals it." )

          +
          #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
          +
          +
          +

          A Giraffe Has Not Stolen Summary #7

          +

          Aha, you're here. And all in one piece. We're still going to make your blog real, but until then, let's review, okay?

          +
            +
          • Classes. Everything in Ruby is some kind of object. Classes explain objects. How a certain object works. + For example, you made a few blog entry objects and these objects are explained in the BlogEntry class. + In other words: you call them BlogEntry objects.
          • +
          • Accessors are variables attached to an object which can be used outside the object. (entry.time = Time.now)
          • +
          • Instance variables are the same variables you're using for accessors when inside the object. + Like in a method definition. (@time = Time.now)
          • +
          +

          Okay, +let's wrap things up, kid. Here's the last chapter of the GRIPPING epic +story of Try Ruby! Now that you've got a taste of how it all works, how +are you going to use it around the house and in your grocer's freezer? +You're a great person (one of my favorites), but you need guidance.

          +

          Let's finish your blog. You have blog entries, but no actual blog.

          +

          Put the entries into an array: blog = [entry, entry2]

          +
          \[#.BlogEntry:0x[0-9a-f]+.*, #.BlogEntry:0x[0-9a-f]+.*\]
          +
          +
          +

          It's All About Combining Things

          +

          Some +beautiful things can be done with the simple parts of Ruby, especially +when you combine them together into new things. Here we've got a blog +made of an array of classes. And, actually, Ruby really does good with +this kind of creature.

          +

          Here's a few things you can do with your array blog:

          +
          • You'll want to sort your entries from newest to oldest. You can do this with:
            + blog.sort_by { |entry| entry.time }.reverse
            See the sort_by explanation for more.
          • +
          • If you want to search your blog for anything related to "cadillac":
            + blog.find_all { |entry| entry.fulltext.match(/cadillac/i) }
            + Read all about find_all + and match + to figure out how that works. Also: the slashy /giraffe/i is a Regexp object, used for matching words.
          • +
          • Add new entries with blog << new_entry
            + And check out the << method documentation.
          • +
          +

          You can browse a list of all Ruby's built-in methods at ruby-doc.org's core list. + Another good list is at the online pickaxe.

          +

          One really useful method (I probably use this more than anything else) is map. Type: blog.map { |entry| entry.mood }

          +
          \[(:\w+, )+:\w+\]
          +
          +
          +

          Look at His Face — The Transformation Has Begun

          +

          The map method cycles through an array and replaces each item with something new. Say you wanted to replace each of your blog entries + with the name Bruce Willis. Do it so: blog.map { "Bruce Willis" }

          +

          Since the block always returns the string "Bruce Willis", that's what you get. In the code you just used, the entry was swapped out + for only the entry.mood.

          +

          Now, +I want you to make a popup with your blog entries. I'm not going to +give you all of the code. I'm just going to give you part of it.

          +
          • blog.each do |entry|
          • +
          •   h2 entry.title
          • +
          •   p entry.fulltext
          • +
          • end
          • +
          +

          Now, I expect you to put the popup code around it and add an h1 title with the name of your blog. For extra haroompf, have the time of each entry display.

          +
          \033\[1;JSm.*popup_make\(.*h1.*h2.*li.*h2.*li.*\)\033\[m.*
          +
          +
          +

          You are Some Kind of Web Guru, I Have Stars in My Eyes

          +

          Good, +that's it! This is exactly the code you can use to write your own real +Ruby blog. If you're feeling adventurous, I'd check out the Rails videos which show a swift young fellow creating a blog in 15 minutes. You just sit back and watch.

          +

          I +should mention Rails. You have been learning the Ruby language, how to +speak it. But Rails is a bunch of libraries (sort of like the popup +library we've been using.) It's a very powerful toolkit for building +websites. If you're interested in learning about Rails, I would head + over there right away. Start using your Ruby skills proper!

          +

          One thing Rails has is easy methods for dates. Like, try: Time.now - 2.weeks

          +
          class Integer; def weeks; self * 7*24*60*60; end; end
          +
          \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-+]\d{4}
          +
          +
          +

          Summary #8, The Hey-Relax-You-Did-Good Summary

          +

          This last section took a moment to wind down, to give you some pointers as to how you can use Ruby. If you enjoyed yourself, + download Ruby and install it.

          + +

          Once you have Ruby installed, you can use Interactive Ruby by running irb on your system's prompt. For more on Irb, + there's The Tiger's Vest to help you.

          +

          You +really deserve a double-layer cake with double-double frosting and a +guy playing one of those guitars that's a double guitar. I mean you +finished, you really did! No doubt about it, you're a certified +red-blooded smartiac!

          +
          +
          + diff --git a/non-rack-legacy/public/tutorials/intro_files/sick.gif b/non-rack-legacy/public/tutorials/intro_files/sick.gif new file mode 100755 index 0000000000000000000000000000000000000000..217a67cbae60740fdc90b92e06b977cf7fc56699 GIT binary patch literal 94 zcmZ?wbhEHb|6B Date: Fri, 8 Jul 2011 17:23:44 -0500 Subject: [PATCH 07/16] trying to clean up --- TryRuby/.gitignore | 4 - TryRuby/.rspec | 1 - TryRuby/.rvmrc | 1 - TryRuby/app/controllers/classic_controller.rb | 2 - TryRuby/app/controllers/irb_controller.rb | 85 - TryRuby/app/controllers/public_controller.rb | 2 - TryRuby/app/helpers/classic_helper.rb | 2 - TryRuby/app/helpers/irb_helper.rb | 2 - TryRuby/app/helpers/public_helper.rb | 2 - TryRuby/app/views/irb/_form.html.erb | 17 - TryRuby/app/views/irb/edit.html.erb | 6 - TryRuby/app/views/irb/index.html.erb | 21 - TryRuby/app/views/irb/new.html.erb | 5 - TryRuby/app/views/irb/show.html.erb | 5 - TryRuby/app/views/layouts/tryruby_es.rhtml | 96 - TryRuby/app/views/tryruby/_donate.html.erb | 41 - TryRuby/config.ru | 4 - TryRuby/config/application.rb | 42 - TryRuby/config/cucumber.yml | 8 - TryRuby/config/initializers/secret_token.rb | 7 - .../db/migrate/20110314191710_create_irb.rb | 12 - TryRuby/db/schema.rb | 15 - TryRuby/features/lesson1.feature | 7 - TryRuby/features/lesson2.feature | 0 .../features/step_definitions/web_steps.rb | 219 - TryRuby/features/support/env.rb | 57 - TryRuby/features/support/paths.rb | 33 - TryRuby/lib/tasks/.gitkeep | 0 TryRuby/lib/tasks/cucumber.rake | 53 - TryRuby/public/images/ajax-loader.gif | Bin 673 -> 0 bytes TryRuby/public/images/closelabel.png | Bin 168 -> 0 bytes TryRuby/public/javascripts/facebox.js | 309 -- TryRuby/public/javascripts/jQuery.irb.js | 1641 ------- TryRuby/public/javascripts/raphael-min.js | 113 - TryRuby/public/stylesheets/facebox.css | 83 - TryRuby/public/stylesheets/reset.css | 46 - TryRuby/public/stylesheets/scaffold.css | 56 - TryRuby/public/tutorials/es_intro.html | 666 --- TryRuby/public/tutorials/intro.html | 680 --- TryRuby/public/tutorials/intro.html.broken | 638 --- TryRuby/public/tutorials/intro_files/sick.gif | Bin 94 -> 0 bytes TryRuby/script/cucumber | 10 - TryRuby/script/rails | 6 - .../controllers/classic_controller_spec.rb | 5 - .../spec/controllers/irb_controller_spec.rb | 125 - .../controllers/public_controller_spec.rb | 5 - TryRuby/spec/helpers/classic_helper_spec.rb | 15 - TryRuby/spec/helpers/irb_helper_spec.rb | 15 - TryRuby/spec/helpers/public_helper_spec.rb | 15 - TryRuby/spec/models/irb_spec.rb | 5 - TryRuby/spec/requests/irb_spec.rb | 11 - TryRuby/spec/routing/irb_routing_spec.rb | 35 - TryRuby/spec/spec_helper.rb | 27 - TryRuby/spec/views/irb/edit.html.erb_spec.rb | 15 - TryRuby/spec/views/irb/index.html.erb_spec.rb | 14 - TryRuby/spec/views/irb/new.html.erb_spec.rb | 15 - TryRuby/spec/views/irb/show.html.erb_spec.rb | 11 - TryRuby/vendor/plugins/.gitkeep | 0 tryruby/Gemfile | 46 - tryruby/README | 256 - tryruby/Rakefile | 7 - .../app/controllers/application_controller.rb | 24 - tryruby/app/controllers/tryruby_controller.rb | 26 - .../app/controllers/tutorials_controller.rb | 6 - tryruby/app/helpers/application_helper.rb | 18 - tryruby/app/views/layouts/tryruby.rhtml | 143 - tryruby/app/views/layouts/tryruby2.html.erb | 147 - tryruby/app/views/tryruby/index.rhtml | 11 - tryruby/app/views/tutorials/es_intro.html | 666 --- tryruby/app/views/tutorials/intro.rhtml | 680 --- tryruby/config/boot.rb | 6 - tryruby/config/database.yml | 32 - tryruby/config/environment.rb | 5 - tryruby/config/environments/development.rb | 26 - tryruby/config/environments/production.rb | 49 - tryruby/config/environments/test.rb | 35 - .../initializers/backtrace_silencers.rb | 7 - tryruby/config/initializers/inflections.rb | 10 - tryruby/config/initializers/mime_types.rb | 5 - .../config/initializers/new_rails_defaults.rb | 21 - tryruby/config/initializers/session_store.rb | 8 - tryruby/config/locales/en.yml | 5 - tryruby/config/preinitializer.rb | 20 - tryruby/config/routes.rb | 64 - tryruby/db/seeds.rb | 7 - tryruby/doc/README_FOR_APP | 2 - tryruby/doc/tryruby.rb | 174 - tryruby/lib/popup.rb | 115 - tryruby/lib/setup.rb | 68 - tryruby/lib/tryruby.rb | 281 -- tryruby/log/production.log | 0 tryruby/log/server.log | 0 tryruby/public/404.html | 30 - tryruby/public/422.html | 30 - tryruby/public/500.html | 30 - tryruby/public/blank.html | 4 - tryruby/public/favicon.ico | 0 tryruby/public/images/background.png | Bin 35315 -> 0 bytes tryruby/public/images/footer.png | Bin 6840 -> 0 bytes tryruby/public/images/header.png | Bin 51873 -> 0 bytes tryruby/public/images/rails.png | Bin 6646 -> 0 bytes tryruby/public/images/sick.gif | Bin 94 -> 0 bytes tryruby/public/images/tile.png | Bin 305 -> 0 bytes tryruby/public/javascripts/application.js | 2 - tryruby/public/javascripts/console.js | 288 -- tryruby/public/javascripts/controls.js | 963 ---- tryruby/public/javascripts/dragdrop.js | 973 ---- tryruby/public/javascripts/effects.js | 1128 ----- tryruby/public/javascripts/irb.js | 110 - .../public/javascripts/jquery-1.3.2.min.js | 19 - .../public/javascripts/jquery-1.4.2.min.js | 154 - tryruby/public/javascripts/jquery.console.js | 609 --- .../public/javascripts/jquery.console.min.js | 1 - tryruby/public/javascripts/jquery.js | 32 - tryruby/public/javascripts/json2.js | 1 - tryruby/public/javascripts/lib.min.js | 159 - tryruby/public/javascripts/mouseapp_2.js | 913 ---- tryruby/public/javascripts/mouseirb_2.js | 179 - tryruby/public/javascripts/prototype.js | 4320 ----------------- tryruby/public/keypress_test.html | 37 - tryruby/public/robots.txt | 5 - tryruby/public/stylesheets/site.css | 378 -- tryruby/script/about | 4 - tryruby/script/console | 3 - tryruby/script/dbconsole | 3 - tryruby/script/destroy | 3 - tryruby/script/generate | 3 - tryruby/script/performance/benchmarker | 3 - tryruby/script/performance/profiler | 3 - tryruby/script/plugin | 3 - tryruby/script/runner | 3 - tryruby/script/server | 3 - .../functional/tryruby_controller_test.rb | 9 - .../functional/tutorials_controller_test.rb | 8 - tryruby/test/performance/browsing_test.rb | 9 - tryruby/test/test_helper.rb | 13 - tryruby/test/unit/fake_f_s_test.rb | 94 - tryruby/test/unit/nesting_level_test.rb | 49 - tryruby/test/unit/output_test.rb | 55 - tryruby/test/unit/try_ruby_test.rb | 500 -- tryruby/tmp/pids/server.pid | 1 - 141 files changed, 19414 deletions(-) delete mode 100644 TryRuby/.gitignore delete mode 100644 TryRuby/.rspec delete mode 100644 TryRuby/.rvmrc delete mode 100644 TryRuby/app/controllers/classic_controller.rb delete mode 100644 TryRuby/app/controllers/irb_controller.rb delete mode 100644 TryRuby/app/controllers/public_controller.rb delete mode 100644 TryRuby/app/helpers/classic_helper.rb delete mode 100644 TryRuby/app/helpers/irb_helper.rb delete mode 100644 TryRuby/app/helpers/public_helper.rb delete mode 100644 TryRuby/app/views/irb/_form.html.erb delete mode 100644 TryRuby/app/views/irb/edit.html.erb delete mode 100644 TryRuby/app/views/irb/index.html.erb delete mode 100644 TryRuby/app/views/irb/new.html.erb delete mode 100644 TryRuby/app/views/irb/show.html.erb delete mode 100644 TryRuby/app/views/layouts/tryruby_es.rhtml delete mode 100644 TryRuby/app/views/tryruby/_donate.html.erb delete mode 100644 TryRuby/config.ru delete mode 100644 TryRuby/config/application.rb delete mode 100644 TryRuby/config/cucumber.yml delete mode 100644 TryRuby/config/initializers/secret_token.rb delete mode 100644 TryRuby/db/migrate/20110314191710_create_irb.rb delete mode 100644 TryRuby/db/schema.rb delete mode 100644 TryRuby/features/lesson1.feature delete mode 100644 TryRuby/features/lesson2.feature delete mode 100644 TryRuby/features/step_definitions/web_steps.rb delete mode 100644 TryRuby/features/support/env.rb delete mode 100644 TryRuby/features/support/paths.rb delete mode 100644 TryRuby/lib/tasks/.gitkeep delete mode 100644 TryRuby/lib/tasks/cucumber.rake delete mode 100644 TryRuby/public/images/ajax-loader.gif delete mode 100755 TryRuby/public/images/closelabel.png delete mode 100755 TryRuby/public/javascripts/facebox.js delete mode 100644 TryRuby/public/javascripts/jQuery.irb.js delete mode 100644 TryRuby/public/javascripts/raphael-min.js delete mode 100755 TryRuby/public/stylesheets/facebox.css delete mode 100644 TryRuby/public/stylesheets/reset.css delete mode 100644 TryRuby/public/stylesheets/scaffold.css delete mode 100644 TryRuby/public/tutorials/es_intro.html delete mode 100644 TryRuby/public/tutorials/intro.html delete mode 100755 TryRuby/public/tutorials/intro.html.broken delete mode 100755 TryRuby/public/tutorials/intro_files/sick.gif delete mode 100755 TryRuby/script/cucumber delete mode 100755 TryRuby/script/rails delete mode 100644 TryRuby/spec/controllers/classic_controller_spec.rb delete mode 100644 TryRuby/spec/controllers/irb_controller_spec.rb delete mode 100644 TryRuby/spec/controllers/public_controller_spec.rb delete mode 100644 TryRuby/spec/helpers/classic_helper_spec.rb delete mode 100644 TryRuby/spec/helpers/irb_helper_spec.rb delete mode 100644 TryRuby/spec/helpers/public_helper_spec.rb delete mode 100644 TryRuby/spec/models/irb_spec.rb delete mode 100644 TryRuby/spec/requests/irb_spec.rb delete mode 100644 TryRuby/spec/routing/irb_routing_spec.rb delete mode 100644 TryRuby/spec/spec_helper.rb delete mode 100644 TryRuby/spec/views/irb/edit.html.erb_spec.rb delete mode 100644 TryRuby/spec/views/irb/index.html.erb_spec.rb delete mode 100644 TryRuby/spec/views/irb/new.html.erb_spec.rb delete mode 100644 TryRuby/spec/views/irb/show.html.erb_spec.rb delete mode 100644 TryRuby/vendor/plugins/.gitkeep delete mode 100644 tryruby/Gemfile delete mode 100644 tryruby/README delete mode 100644 tryruby/Rakefile delete mode 100644 tryruby/app/controllers/application_controller.rb delete mode 100644 tryruby/app/controllers/tryruby_controller.rb delete mode 100644 tryruby/app/controllers/tutorials_controller.rb delete mode 100644 tryruby/app/helpers/application_helper.rb delete mode 100644 tryruby/app/views/layouts/tryruby.rhtml delete mode 100644 tryruby/app/views/layouts/tryruby2.html.erb delete mode 100644 tryruby/app/views/tryruby/index.rhtml delete mode 100644 tryruby/app/views/tutorials/es_intro.html delete mode 100644 tryruby/app/views/tutorials/intro.rhtml delete mode 100644 tryruby/config/boot.rb delete mode 100644 tryruby/config/database.yml delete mode 100644 tryruby/config/environment.rb delete mode 100644 tryruby/config/environments/development.rb delete mode 100644 tryruby/config/environments/production.rb delete mode 100644 tryruby/config/environments/test.rb delete mode 100644 tryruby/config/initializers/backtrace_silencers.rb delete mode 100644 tryruby/config/initializers/inflections.rb delete mode 100644 tryruby/config/initializers/mime_types.rb delete mode 100644 tryruby/config/initializers/new_rails_defaults.rb delete mode 100644 tryruby/config/initializers/session_store.rb delete mode 100644 tryruby/config/locales/en.yml delete mode 100644 tryruby/config/preinitializer.rb delete mode 100644 tryruby/config/routes.rb delete mode 100644 tryruby/db/seeds.rb delete mode 100644 tryruby/doc/README_FOR_APP delete mode 100644 tryruby/doc/tryruby.rb delete mode 100755 tryruby/lib/popup.rb delete mode 100644 tryruby/lib/setup.rb delete mode 100644 tryruby/lib/tryruby.rb delete mode 100644 tryruby/log/production.log delete mode 100644 tryruby/log/server.log delete mode 100644 tryruby/public/404.html delete mode 100644 tryruby/public/422.html delete mode 100644 tryruby/public/500.html delete mode 100755 tryruby/public/blank.html delete mode 100644 tryruby/public/favicon.ico delete mode 100755 tryruby/public/images/background.png delete mode 100755 tryruby/public/images/footer.png delete mode 100644 tryruby/public/images/header.png delete mode 100644 tryruby/public/images/rails.png delete mode 100755 tryruby/public/images/sick.gif delete mode 100755 tryruby/public/images/tile.png delete mode 100644 tryruby/public/javascripts/application.js delete mode 100644 tryruby/public/javascripts/console.js delete mode 100644 tryruby/public/javascripts/controls.js delete mode 100644 tryruby/public/javascripts/dragdrop.js delete mode 100644 tryruby/public/javascripts/effects.js delete mode 100755 tryruby/public/javascripts/irb.js delete mode 100644 tryruby/public/javascripts/jquery-1.3.2.min.js delete mode 100644 tryruby/public/javascripts/jquery-1.4.2.min.js delete mode 100644 tryruby/public/javascripts/jquery.console.js delete mode 100644 tryruby/public/javascripts/jquery.console.min.js delete mode 100755 tryruby/public/javascripts/jquery.js delete mode 100644 tryruby/public/javascripts/json2.js delete mode 100644 tryruby/public/javascripts/lib.min.js delete mode 100755 tryruby/public/javascripts/mouseapp_2.js delete mode 100755 tryruby/public/javascripts/mouseirb_2.js delete mode 100644 tryruby/public/javascripts/prototype.js delete mode 100644 tryruby/public/keypress_test.html delete mode 100644 tryruby/public/robots.txt delete mode 100755 tryruby/public/stylesheets/site.css delete mode 100755 tryruby/script/about delete mode 100755 tryruby/script/console delete mode 100755 tryruby/script/dbconsole delete mode 100755 tryruby/script/destroy delete mode 100755 tryruby/script/generate delete mode 100755 tryruby/script/performance/benchmarker delete mode 100755 tryruby/script/performance/profiler delete mode 100755 tryruby/script/plugin delete mode 100755 tryruby/script/runner delete mode 100755 tryruby/script/server delete mode 100644 tryruby/test/functional/tryruby_controller_test.rb delete mode 100644 tryruby/test/functional/tutorials_controller_test.rb delete mode 100644 tryruby/test/performance/browsing_test.rb delete mode 100644 tryruby/test/test_helper.rb delete mode 100644 tryruby/test/unit/fake_f_s_test.rb delete mode 100644 tryruby/test/unit/nesting_level_test.rb delete mode 100644 tryruby/test/unit/output_test.rb delete mode 100644 tryruby/test/unit/try_ruby_test.rb delete mode 100644 tryruby/tmp/pids/server.pid diff --git a/TryRuby/.gitignore b/TryRuby/.gitignore deleted file mode 100644 index f0fa30c..0000000 --- a/TryRuby/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -.bundle -db/*.sqlite3 -log/*.log -tmp/ diff --git a/TryRuby/.rspec b/TryRuby/.rspec deleted file mode 100644 index 53607ea..0000000 --- a/TryRuby/.rspec +++ /dev/null @@ -1 +0,0 @@ ---colour diff --git a/TryRuby/.rvmrc b/TryRuby/.rvmrc deleted file mode 100644 index 39b50dd..0000000 --- a/TryRuby/.rvmrc +++ /dev/null @@ -1 +0,0 @@ -rvm use 1.9.2@tryruby diff --git a/TryRuby/app/controllers/classic_controller.rb b/TryRuby/app/controllers/classic_controller.rb deleted file mode 100644 index 019e234..0000000 --- a/TryRuby/app/controllers/classic_controller.rb +++ /dev/null @@ -1,2 +0,0 @@ -class ClassicController < ApplicationController -end diff --git a/TryRuby/app/controllers/irb_controller.rb b/TryRuby/app/controllers/irb_controller.rb deleted file mode 100644 index f296b07..0000000 --- a/TryRuby/app/controllers/irb_controller.rb +++ /dev/null @@ -1,85 +0,0 @@ -class IrbController < ApplicationController - # GET /irb - # GET /irb.xml - def index - - @irb = [] - - respond_to do |format| - format.html # index.html.erb - format.to_json - format.xml { render :xml => @irb } - end - end - - # GET /irb/1 - # GET /irb/1.xml - def show - @irb = Irb.find(params[:id]) - - respond_to do |format| - format.html # show.html.erb - format.xml { render :xml => @irb } - end - end - - # GET /irb/new - # GET /irb/new.xml - def new - @irb = Irb.new - - respond_to do |format| - format.html # new.html.erb - format.xml { render :xml => @irb } - end - end - - # GET /irb/1/edit - def edit - @irb = Irb.find(params[:id]) - end - - # POST /irb - # POST /irb.xml - def create - @irb = Irb.new(params[:irb]) - - respond_to do |format| - if @irb.save - format.html { redirect_to(@irb, :notice => 'Irb was successfully created.') } - format.xml { render :xml => @irb, :status => :created, :location => @irb } - else - format.html { render :action => "new" } - format.xml { render :xml => @irb.errors, :status => :unprocessable_entity } - end - end - end - - # PUT /irb/1 - # PUT /irb/1.xml - def update - @irb = Irb.find(params[:id]) - - respond_to do |format| - if @irb.update_attributes(params[:irb]) - format.html { redirect_to(@irb, :notice => 'Irb was successfully updated.') } - format.xml { head :ok } - else - format.html { render :action => "edit" } - format.xml { render :xml => @irb.errors, :status => :unprocessable_entity } - end - end - end - - # DELETE /irb/1 - # DELETE /irb/1.xml - def destroy - @irb = Irb.find(params[:id]) - @irb.destroy - - respond_to do |format| - format.html { redirect_to(irb_url) } - format.xml { head :ok } - end - end -end diff --git a/TryRuby/app/controllers/public_controller.rb b/TryRuby/app/controllers/public_controller.rb deleted file mode 100644 index 2857026..0000000 --- a/TryRuby/app/controllers/public_controller.rb +++ /dev/null @@ -1,2 +0,0 @@ -class PublicController < ApplicationController -end diff --git a/TryRuby/app/helpers/classic_helper.rb b/TryRuby/app/helpers/classic_helper.rb deleted file mode 100644 index e85110a..0000000 --- a/TryRuby/app/helpers/classic_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module ClassicHelper -end diff --git a/TryRuby/app/helpers/irb_helper.rb b/TryRuby/app/helpers/irb_helper.rb deleted file mode 100644 index 6c9f3c9..0000000 --- a/TryRuby/app/helpers/irb_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module IrbHelper -end diff --git a/TryRuby/app/helpers/public_helper.rb b/TryRuby/app/helpers/public_helper.rb deleted file mode 100644 index 0d8e188..0000000 --- a/TryRuby/app/helpers/public_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module PublicHelper -end diff --git a/TryRuby/app/views/irb/_form.html.erb b/TryRuby/app/views/irb/_form.html.erb deleted file mode 100644 index 4e3cdae..0000000 --- a/TryRuby/app/views/irb/_form.html.erb +++ /dev/null @@ -1,17 +0,0 @@ -<%= form_for(@irb) do |f| %> - <% if @irb.errors.any? %> -
          -

          <%= pluralize(@irb.errors.count, "error") %> prohibited this irb from being saved:

          - -
            - <% @irb.errors.full_messages.each do |msg| %> -
          • <%= msg %>
          • - <% end %> -
          -
          - <% end %> - -
          - <%= f.submit %> -
          -<% end %> diff --git a/TryRuby/app/views/irb/edit.html.erb b/TryRuby/app/views/irb/edit.html.erb deleted file mode 100644 index 9e50dc3..0000000 --- a/TryRuby/app/views/irb/edit.html.erb +++ /dev/null @@ -1,6 +0,0 @@ -

          Editing irb

          - -<%= render 'form' %> - -<%= link_to 'Show', @irb %> | -<%= link_to 'Back', irb_path %> diff --git a/TryRuby/app/views/irb/index.html.erb b/TryRuby/app/views/irb/index.html.erb deleted file mode 100644 index 90b773b..0000000 --- a/TryRuby/app/views/irb/index.html.erb +++ /dev/null @@ -1,21 +0,0 @@ -

          Listing irb

          - - - - - - - - -<% @irb.each do |irb| %> - - - - - -<% end %> -
          <%= link_to 'Show', irb %><%= link_to 'Edit', edit_irb_path(irb) %><%= link_to 'Destroy', irb, :confirm => 'Are you sure?', :method => :delete %>
          - -
          - -<%= link_to 'New Irb', new_irb_path %> diff --git a/TryRuby/app/views/irb/new.html.erb b/TryRuby/app/views/irb/new.html.erb deleted file mode 100644 index 9a7b635..0000000 --- a/TryRuby/app/views/irb/new.html.erb +++ /dev/null @@ -1,5 +0,0 @@ -

          New irb

          - -<%= render 'form' %> - -<%= link_to 'Back', irb_path %> diff --git a/TryRuby/app/views/irb/show.html.erb b/TryRuby/app/views/irb/show.html.erb deleted file mode 100644 index c271c01..0000000 --- a/TryRuby/app/views/irb/show.html.erb +++ /dev/null @@ -1,5 +0,0 @@ -

          <%= notice %>

          - - -<%= link_to 'Edit', edit_irb_path(@irb) %> | -<%= link_to 'Back', irb_path %> diff --git a/TryRuby/app/views/layouts/tryruby_es.rhtml b/TryRuby/app/views/layouts/tryruby_es.rhtml deleted file mode 100644 index 9ab71c1..0000000 --- a/TryRuby/app/views/layouts/tryruby_es.rhtml +++ /dev/null @@ -1,96 +0,0 @@ - - - - - try ruby! (en tu navegador) - - - - - - - - - -
          - -
          -
          -
          - -

          A Popup Browser

          -

          [x]

          -
          - -
          -
          - -
          -
          -
          -
          -
          -
          -

          ¿Tienes 15 minutos? ¡Prueba Ruby ahora mismo!

          -

          Ruby es un lenguaje de programación de Japón - (disponible en ruby-lang.org) - que está revolucionando la web. - La belleza de Ruby se encuentra en su balance entre la simplicidad y el poder.

          - -

          Prueba código Ruby en el prompt de arriba. Además de los métodos - originales de Ruby, los siguientes comandos están disponibles:

          -
            -
          • help - Empieza el tutorial interactivo de 15 minutos. ¡Creeme, es muy básico!
          • -
          • help 2 - Salta al capítulo 2.
          • - -
          • clear - Limpia la pantalla. Útil si tu navegador empieza a alerdarce. - Tu historial de comandos será recordado. -
          • back - Retrocede una pantalla en el tutorial.
          • -
          • reset - Resetea el interprete. (o Ctrl-D!)
          • -
          • next - Te permite saltear la siguiente lección
          • - -
          • time - Detiene el reloj. Imprime cuanto tiempo tu sesión estuvo abierta.
          • -
          -

          Si te pasa de dejar o refrescar la página, tu sesión seguirá aquí a menos que - se deje inactiva por diez minutos.

          -
          -
          -
          - -
          -
          ¿Atrapado en los dos puntos? Unas comillas o algo fue dejado abierto. Escribe: reset o aprieta Ctrl-D.
          -
          - -

          This place was sired by why the lucky stiff. - Please contact me using the email address at that link.is maintained by Andrew McElroy and David Miani. For support issues, please post a ticket or contact Sophrinix on github.
          Por asuntos de traducción, mandar un ticket o contactarse con Cristian Re (leizzer) en Github.
          -

          - -
          - - - - - - - - - - diff --git a/TryRuby/app/views/tryruby/_donate.html.erb b/TryRuby/app/views/tryruby/_donate.html.erb deleted file mode 100644 index f7095b1..0000000 --- a/TryRuby/app/views/tryruby/_donate.html.erb +++ /dev/null @@ -1,41 +0,0 @@ - \ No newline at end of file diff --git a/TryRuby/config.ru b/TryRuby/config.ru deleted file mode 100644 index df742d3..0000000 --- a/TryRuby/config.ru +++ /dev/null @@ -1,4 +0,0 @@ -# This file is used by Rack-based servers to start the application. - -require ::File.expand_path('../config/environment', __FILE__) -run TryRuby::Application diff --git a/TryRuby/config/application.rb b/TryRuby/config/application.rb deleted file mode 100644 index a8f1bd9..0000000 --- a/TryRuby/config/application.rb +++ /dev/null @@ -1,42 +0,0 @@ -require File.expand_path('../boot', __FILE__) - -require 'rails/all' - -# If you have a Gemfile, require the gems listed there, including any gems -# you've limited to :test, :development, or :production. -Bundler.require(:default, Rails.env) if defined?(Bundler) - -module TryRuby - class Application < Rails::Application - # Settings in config/environments/* take precedence over those specified here. - # Application configuration should go into files in config/initializers - # -- all .rb files in that directory are automatically loaded. - - # Custom directories with classes and modules you want to be autoloadable. - # config.autoload_paths += %W(#{config.root}/extras) - - # Only load the plugins named here, in the order given (default is alphabetical). - # :all can be used as a placeholder for all plugins not explicitly named. - # config.plugins = [ :exception_notification, :ssl_requirement, :all ] - - # Activate observers that should always be running. - # config.active_record.observers = :cacher, :garbage_collector, :forum_observer - - # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. - # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. - # config.time_zone = 'Central Time (US & Canada)' - - # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. - # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] - # config.i18n.default_locale = :de - - # JavaScript files you want as :defaults (application.js is always included). - # config.action_view.javascript_expansions[:defaults] = %w(jquery rails) - - # Configure the default encoding used in templates for Ruby 1.9. - config.encoding = "utf-8" - - # Configure sensitive parameters which will be filtered from the log file. - config.filter_parameters += [:password] - end -end diff --git a/TryRuby/config/cucumber.yml b/TryRuby/config/cucumber.yml deleted file mode 100644 index 621a14c..0000000 --- a/TryRuby/config/cucumber.yml +++ /dev/null @@ -1,8 +0,0 @@ -<% -rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : "" -rerun_opts = rerun.to_s.strip.empty? ? "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}" -std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} --strict --tags ~@wip" -%> -default: <%= std_opts %> features -wip: --tags @wip:3 --wip features -rerun: <%= rerun_opts %> --format rerun --out rerun.txt --strict --tags ~@wip diff --git a/TryRuby/config/initializers/secret_token.rb b/TryRuby/config/initializers/secret_token.rb deleted file mode 100644 index 5e9b98f..0000000 --- a/TryRuby/config/initializers/secret_token.rb +++ /dev/null @@ -1,7 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# Your secret key for verifying the integrity of signed cookies. -# If you change this key, all old signed cookies will become invalid! -# Make sure the secret is at least 30 characters and all random, -# no regular words or you'll be exposed to dictionary attacks. -TryRuby::Application.config.secret_token = 'f256893c2715b8fab149294c7f3b79fbc7a725534be51332c220c2e19965e631cc72c360acfec77dcc0469f58b81b5023e7c93a800626520f9420816639948d5' diff --git a/TryRuby/db/migrate/20110314191710_create_irb.rb b/TryRuby/db/migrate/20110314191710_create_irb.rb deleted file mode 100644 index b628478..0000000 --- a/TryRuby/db/migrate/20110314191710_create_irb.rb +++ /dev/null @@ -1,12 +0,0 @@ -class CreateIrb < ActiveRecord::Migration - def self.up - create_table :irb do |t| - - t.timestamps - end - end - - def self.down - drop_table :irb - end -end diff --git a/TryRuby/db/schema.rb b/TryRuby/db/schema.rb deleted file mode 100644 index 671c0da..0000000 --- a/TryRuby/db/schema.rb +++ /dev/null @@ -1,15 +0,0 @@ -# This file is auto-generated from the current state of the database. Instead -# of editing this file, please use the migrations feature of Active Record to -# incrementally modify your database, and then regenerate this schema definition. -# -# Note that this schema.rb definition is the authoritative source for your -# database schema. If you need to create the application database on another -# system, you should be using db:schema:load, not running all the migrations -# from scratch. The latter is a flawed and unsustainable approach (the more migrations -# you'll amass, the slower it'll run and the greater likelihood for issues). -# -# It's strongly recommended to check this file into your version control system. - -ActiveRecord::Schema.define(:version => 0) do - -end diff --git a/TryRuby/features/lesson1.feature b/TryRuby/features/lesson1.feature deleted file mode 100644 index 409a21f..0000000 --- a/TryRuby/features/lesson1.feature +++ /dev/null @@ -1,7 +0,0 @@ -Feature: Successfully execute lesson 1 - Scenario: starting into try ruby - Given I am on index - When I type help - Then I should see Using The Prompt - - diff --git a/TryRuby/features/lesson2.feature b/TryRuby/features/lesson2.feature deleted file mode 100644 index e69de29..0000000 diff --git a/TryRuby/features/step_definitions/web_steps.rb b/TryRuby/features/step_definitions/web_steps.rb deleted file mode 100644 index 0f0af8a..0000000 --- a/TryRuby/features/step_definitions/web_steps.rb +++ /dev/null @@ -1,219 +0,0 @@ -# IMPORTANT: This file is generated by cucumber-rails - edit at your own peril. -# It is recommended to regenerate this file in the future when you upgrade to a -# newer version of cucumber-rails. Consider adding your own code to a new file -# instead of editing this one. Cucumber will automatically load all features/**/*.rb -# files. - - -require 'uri' -require 'cgi' -require File.expand_path(File.join(File.dirname(__FILE__), "..", "support", "paths")) - -module WithinHelpers - def with_scope(locator) - locator ? within(locator) { yield } : yield - end -end -World(WithinHelpers) - -Given /^(?:|I )am on (.+)$/ do |page_name| - visit path_to(page_name) -end - -When /^(?:|I )go to (.+)$/ do |page_name| - visit path_to(page_name) -end - -When /^(?:|I )press "([^"]*)"(?: within "([^"]*)")?$/ do |button, selector| - with_scope(selector) do - click_button(button) - end -end - -When /^(?:|I )follow "([^"]*)"(?: within "([^"]*)")?$/ do |link, selector| - with_scope(selector) do - click_link(link) - end -end - -When /^(?:|I )fill in "([^"]*)" with "([^"]*)"(?: within "([^"]*)")?$/ do |field, value, selector| - with_scope(selector) do - fill_in(field, :with => value) - end -end - -When /^(?:|I )fill in "([^"]*)" for "([^"]*)"(?: within "([^"]*)")?$/ do |value, field, selector| - with_scope(selector) do - fill_in(field, :with => value) - end -end - -# Use this to fill in an entire form with data from a table. Example: -# -# When I fill in the following: -# | Account Number | 5002 | -# | Expiry date | 2009-11-01 | -# | Note | Nice guy | -# | Wants Email? | | -# -# TODO: Add support for checkbox, select og option -# based on naming conventions. -# -When /^(?:|I )fill in the following(?: within "([^"]*)")?:$/ do |selector, fields| - with_scope(selector) do - fields.rows_hash.each do |name, value| - When %{I fill in "#{name}" with "#{value}"} - end - end -end - -When /^(?:|I )select "([^"]*)" from "([^"]*)"(?: within "([^"]*)")?$/ do |value, field, selector| - with_scope(selector) do - select(value, :from => field) - end -end - -When /^(?:|I )check "([^"]*)"(?: within "([^"]*)")?$/ do |field, selector| - with_scope(selector) do - check(field) - end -end - -When /^(?:|I )uncheck "([^"]*)"(?: within "([^"]*)")?$/ do |field, selector| - with_scope(selector) do - uncheck(field) - end -end - -When /^(?:|I )choose "([^"]*)"(?: within "([^"]*)")?$/ do |field, selector| - with_scope(selector) do - choose(field) - end -end - -When /^(?:|I )attach the file "([^"]*)" to "([^"]*)"(?: within "([^"]*)")?$/ do |path, field, selector| - with_scope(selector) do - attach_file(field, path) - end -end - -Then /^(?:|I )should see JSON:$/ do |expected_json| - require 'json' - expected = JSON.pretty_generate(JSON.parse(expected_json)) - actual = JSON.pretty_generate(JSON.parse(response.body)) - expected.should == actual -end - -Then /^(?:|I )should see "([^"]*)"(?: within "([^"]*)")?$/ do |text, selector| - with_scope(selector) do - if page.respond_to? :should - page.should have_content(text) - else - assert page.has_content?(text) - end - end -end - -Then /^(?:|I )should see \/([^\/]*)\/(?: within "([^"]*)")?$/ do |regexp, selector| - regexp = Regexp.new(regexp) - with_scope(selector) do - if page.respond_to? :should - page.should have_xpath('//*', :text => regexp) - else - assert page.has_xpath?('//*', :text => regexp) - end - end -end - -Then /^(?:|I )should not see "([^"]*)"(?: within "([^"]*)")?$/ do |text, selector| - with_scope(selector) do - if page.respond_to? :should - page.should have_no_content(text) - else - assert page.has_no_content?(text) - end - end -end - -Then /^(?:|I )should not see \/([^\/]*)\/(?: within "([^"]*)")?$/ do |regexp, selector| - regexp = Regexp.new(regexp) - with_scope(selector) do - if page.respond_to? :should - page.should have_no_xpath('//*', :text => regexp) - else - assert page.has_no_xpath?('//*', :text => regexp) - end - end -end - -Then /^the "([^"]*)" field(?: within "([^"]*)")? should contain "([^"]*)"$/ do |field, selector, value| - with_scope(selector) do - field = find_field(field) - field_value = (field.tag_name == 'textarea') ? field.text : field.value - if field_value.respond_to? :should - field_value.should =~ /#{value}/ - else - assert_match(/#{value}/, field_value) - end - end -end - -Then /^the "([^"]*)" field(?: within "([^"]*)")? should not contain "([^"]*)"$/ do |field, selector, value| - with_scope(selector) do - field = find_field(field) - field_value = (field.tag_name == 'textarea') ? field.text : field.value - if field_value.respond_to? :should_not - field_value.should_not =~ /#{value}/ - else - assert_no_match(/#{value}/, field_value) - end - end -end - -Then /^the "([^"]*)" checkbox(?: within "([^"]*)")? should be checked$/ do |label, selector| - with_scope(selector) do - field_checked = find_field(label)['checked'] - if field_checked.respond_to? :should - field_checked.should be_true - else - assert field_checked - end - end -end - -Then /^the "([^"]*)" checkbox(?: within "([^"]*)")? should not be checked$/ do |label, selector| - with_scope(selector) do - field_checked = find_field(label)['checked'] - if field_checked.respond_to? :should - field_checked.should be_false - else - assert !field_checked - end - end -end - -Then /^(?:|I )should be on (.+)$/ do |page_name| - current_path = URI.parse(current_url).path - if current_path.respond_to? :should - current_path.should == path_to(page_name) - else - assert_equal path_to(page_name), current_path - end -end - -Then /^(?:|I )should have the following query string:$/ do |expected_pairs| - query = URI.parse(current_url).query - actual_params = query ? CGI.parse(query) : {} - expected_params = {} - expected_pairs.rows_hash.each_pair{|k,v| expected_params[k] = v.split(',')} - - if actual_params.respond_to? :should - actual_params.should == expected_params - else - assert_equal expected_params, actual_params - end -end - -Then /^show me the page$/ do - save_and_open_page -end diff --git a/TryRuby/features/support/env.rb b/TryRuby/features/support/env.rb deleted file mode 100644 index 3333139..0000000 --- a/TryRuby/features/support/env.rb +++ /dev/null @@ -1,57 +0,0 @@ -# IMPORTANT: This file is generated by cucumber-rails - edit at your own peril. -# It is recommended to regenerate this file in the future when you upgrade to a -# newer version of cucumber-rails. Consider adding your own code to a new file -# instead of editing this one. Cucumber will automatically load all features/**/*.rb -# files. - -ENV["RAILS_ENV"] ||= "test" -require File.expand_path(File.dirname(__FILE__) + '/../../config/environment') - -require 'cucumber/formatter/unicode' # Remove this line if you don't want Cucumber Unicode support -require 'cucumber/rails/world' -require 'cucumber/rails/active_record' -require 'cucumber/web/tableish' - -require 'capybara/rails' -require 'capybara/cucumber' -require 'capybara/session' -require 'cucumber/rails/capybara_javascript_emulation' # Lets you click links with onclick javascript handlers without using @culerity or @javascript -# Capybara defaults to XPath selectors rather than Webrat's default of CSS3. In -# order to ease the transition to Capybara we set the default here. If you'd -# prefer to use XPath just remove this line and adjust any selectors in your -# steps to use the XPath syntax. -Capybara.default_selector = :css - -# If you set this to false, any error raised from within your app will bubble -# up to your step definition and out to cucumber unless you catch it somewhere -# on the way. You can make Rails rescue errors and render error pages on a -# per-scenario basis by tagging a scenario or feature with the @allow-rescue tag. -# -# If you set this to true, Rails will rescue all errors and render error -# pages, more or less in the same way your application would behave in the -# default production environment. It's not recommended to do this for all -# of your scenarios, as this makes it hard to discover errors in your application. -ActionController::Base.allow_rescue = false - -# If you set this to true, each scenario will run in a database transaction. -# You can still turn off transactions on a per-scenario basis, simply tagging -# a feature or scenario with the @no-txn tag. If you are using Capybara, -# tagging with @culerity or @javascript will also turn transactions off. -# -# If you set this to false, transactions will be off for all scenarios, -# regardless of whether you use @no-txn or not. -# -# Beware that turning transactions off will leave data in your database -# after each scenario, which can lead to hard-to-debug failures in -# subsequent scenarios. If you do this, we recommend you create a Before -# block that will explicitly put your database in a known state. -Cucumber::Rails::World.use_transactional_fixtures = true -# How to clean your database when transactions are turned off. See -# http://github.com/bmabey/database_cleaner for more info. -if defined?(ActiveRecord::Base) - begin - require 'database_cleaner' - DatabaseCleaner.strategy = :truncation - rescue LoadError => ignore_if_database_cleaner_not_present - end -end diff --git a/TryRuby/features/support/paths.rb b/TryRuby/features/support/paths.rb deleted file mode 100644 index 06b3efb..0000000 --- a/TryRuby/features/support/paths.rb +++ /dev/null @@ -1,33 +0,0 @@ -module NavigationHelpers - # Maps a name to a path. Used by the - # - # When /^I go to (.+)$/ do |page_name| - # - # step definition in web_steps.rb - # - def path_to(page_name) - case page_name - - when /the home\s?page/ - '/' - - # Add more mappings here. - # Here is an example that pulls values out of the Regexp: - # - # when /^(.*)'s profile page$/i - # user_profile_path(User.find_by_login($1)) - - else - begin - page_name =~ /the (.*) page/ - path_components = $1.split(/\s+/) - self.send(path_components.push('path').join('_').to_sym) - rescue Object => e - raise "Can't find mapping from \"#{page_name}\" to a path.\n" + - "Now, go and add a mapping in #{__FILE__}" - end - end - end -end - -World(NavigationHelpers) diff --git a/TryRuby/lib/tasks/.gitkeep b/TryRuby/lib/tasks/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/TryRuby/lib/tasks/cucumber.rake b/TryRuby/lib/tasks/cucumber.rake deleted file mode 100644 index 7db1a55..0000000 --- a/TryRuby/lib/tasks/cucumber.rake +++ /dev/null @@ -1,53 +0,0 @@ -# IMPORTANT: This file is generated by cucumber-rails - edit at your own peril. -# It is recommended to regenerate this file in the future when you upgrade to a -# newer version of cucumber-rails. Consider adding your own code to a new file -# instead of editing this one. Cucumber will automatically load all features/**/*.rb -# files. - - -unless ARGV.any? {|a| a =~ /^gems/} # Don't load anything when running the gems:* tasks - -vendored_cucumber_bin = Dir["#{Rails.root}/vendor/{gems,plugins}/cucumber*/bin/cucumber"].first -$LOAD_PATH.unshift(File.dirname(vendored_cucumber_bin) + '/../lib') unless vendored_cucumber_bin.nil? - -begin - require 'cucumber/rake/task' - - namespace :cucumber do - Cucumber::Rake::Task.new({:ok => 'db:test:prepare'}, 'Run features that should pass') do |t| - t.binary = vendored_cucumber_bin # If nil, the gem's binary is used. - t.fork = true # You may get faster startup if you set this to false - t.profile = 'default' - end - - Cucumber::Rake::Task.new({:wip => 'db:test:prepare'}, 'Run features that are being worked on') do |t| - t.binary = vendored_cucumber_bin - t.fork = true # You may get faster startup if you set this to false - t.profile = 'wip' - end - - Cucumber::Rake::Task.new({:rerun => 'db:test:prepare'}, 'Record failing features and run only them if any exist') do |t| - t.binary = vendored_cucumber_bin - t.fork = true # You may get faster startup if you set this to false - t.profile = 'rerun' - end - - desc 'Run all features' - task :all => [:ok, :wip] - end - desc 'Alias for cucumber:ok' - task :cucumber => 'cucumber:ok' - - task :default => :cucumber - - task :features => :cucumber do - STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***" - end -rescue LoadError - desc 'cucumber rake task not available (cucumber not installed)' - task :cucumber do - abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin' - end -end - -end diff --git a/TryRuby/public/images/ajax-loader.gif b/TryRuby/public/images/ajax-loader.gif deleted file mode 100644 index f2a1bc0c6f545e20e631a96e8e92f9822e75d046..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 673 zcmZ?wbhEHb6krfw_{6~Q|Nnmm28Kh24mmkF0U1e2Nli^nlO|14{3qpHl$uzQnxasi zS(2fUn3Y(Olb@KPmzkHA&!G5|g@FsGT=74*pKD04vtxj(k)8oFBTz^Oh=E26FfcG1 zbL_hF&)}42ws10s6^G;;cE1^EoUR)U5A70}d2pLv!jVIT7j&Z~EblI3x0K*v_sV|m z0W=b9G$XP(CLnYCdK49;TX=SFc-G}o=oA=|U?{1O;Nu!CwW3C5Yw7*Bi4yD$3fCnb zwK+>}QdQ9sf*QnxY>*kpE+b{_Q;sJloS71)&(@kO!}mqf@1v(v;*8Y=G9S3kY~Cw# zY=t&c z;3~JK4HxB^lY(MD+sYeQ=t%XSSW;x^1M?dTvN=W^yNcAcy`HCte31C;)5xP%b~qs> zDP&4(%TBqBNGHwnryK;BdMI$fEg xd0mc!C@j^ZpLxYv4HmnPfI0THYuv<%+6iSmMn&w3dPGDfL1|=LY008wP(boU~ diff --git a/TryRuby/public/images/closelabel.png b/TryRuby/public/images/closelabel.png deleted file mode 100755 index c339e59333e4c3b5bc5fd910796fda5469a2515f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 168 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5XygXeTLn>}1B_t#Wus+)Bu;yq3!!CzC+*<6@{_r1Jzd&eL zz_O}6Q6nrOf&;;F`V=YhW2-H5dcFFaTerms - * Loads the #terms div in the box - * - * Terms - * Loads the terms.html page in the box - * - * Terms - * Loads the terms.png image in the box - * - * - * You can also use it programmatically: - * - * jQuery.facebox('some html') - * jQuery.facebox('some html', 'my-groovy-style') - * - * The above will open a facebox with "some html" as the content. - * - * jQuery.facebox(function($) { - * $.get('blah.html', function(data) { $.facebox(data) }) - * }) - * - * The above will show a loading screen before the passed function is called, - * allowing for a better ajaxy experience. - * - * The facebox function can also display an ajax page, an image, or the contents of a div: - * - * jQuery.facebox({ ajax: 'remote.html' }) - * jQuery.facebox({ ajax: 'remote.html' }, 'my-groovy-style') - * jQuery.facebox({ image: 'stairs.jpg' }) - * jQuery.facebox({ image: 'stairs.jpg' }, 'my-groovy-style') - * jQuery.facebox({ div: '#box' }) - * jQuery.facebox({ div: '#box' }, 'my-groovy-style') - * - * Want to close the facebox? Trigger the 'close.facebox' document event: - * - * jQuery(document).trigger('close.facebox') - * - * Facebox also has a bunch of other hooks: - * - * loading.facebox - * beforeReveal.facebox - * reveal.facebox (aliased as 'afterReveal.facebox') - * init.facebox - * afterClose.facebox - * - * Simply bind a function to any of these hooks: - * - * $(document).bind('reveal.facebox', function() { ...stuff to do after the facebox and contents are revealed... }) - * - */ -(function($) { - $.facebox = function(data, klass) { - $.facebox.loading() - - if (data.ajax) fillFaceboxFromAjax(data.ajax, klass) - else if (data.image) fillFaceboxFromImage(data.image, klass) - else if (data.div) fillFaceboxFromHref(data.div, klass) - else if ($.isFunction(data)) data.call($) - else $.facebox.reveal(data, klass) - } - - /* - * Public, $.facebox methods - */ - - $.extend($.facebox, { - settings: { - opacity : 0.2, - overlay : true, - loadingImage : '/facebox/loading.gif', - closeImage : '/facebox/closelabel.png', - imageTypes : [ 'png', 'jpg', 'jpeg', 'gif' ], - faceboxHtml : '\ - ' - }, - - loading: function() { - init() - if ($('#facebox .loading').length == 1) return true - showOverlay() - - $('#facebox .content').empty() - $('#facebox .body').children().hide().end(). - append('
          ') - - $('#facebox').css({ - top: getPageScroll()[1] + (getPageHeight() / 10), - left: $(window).width() / 2 - 205 - }).show() - - $(document).bind('keydown.facebox', function(e) { - if (e.keyCode == 27) $.facebox.close() - return true - }) - $(document).trigger('loading.facebox') - }, - - reveal: function(data, klass) { - $(document).trigger('beforeReveal.facebox') - if (klass) $('#facebox .content').addClass(klass) - $('#facebox .content').append(data) - $('#facebox .loading').remove() - $('#facebox .body').children().fadeIn('normal') - $('#facebox').css('left', $(window).width() / 2 - ($('#facebox .popup').width() / 2)) - $(document).trigger('reveal.facebox').trigger('afterReveal.facebox') - }, - - close: function() { - $(document).trigger('close.facebox') - return false - } - }) - - /* - * Public, $.fn methods - */ - - $.fn.facebox = function(settings) { - if ($(this).length == 0) return - - init(settings) - - function clickHandler() { - $.facebox.loading(true) - - // support for rel="facebox.inline_popup" syntax, to add a class - // also supports deprecated "facebox[.inline_popup]" syntax - var klass = this.rel.match(/facebox\[?\.(\w+)\]?/) - if (klass) klass = klass[1] - - fillFaceboxFromHref(this.href, klass) - return false - } - - return this.bind('click.facebox', clickHandler) - } - - /* - * Private methods - */ - - // called one time to setup facebox on this page - function init(settings) { - if ($.facebox.settings.inited) return true - else $.facebox.settings.inited = true - - $(document).trigger('init.facebox') - makeCompatible() - - var imageTypes = $.facebox.settings.imageTypes.join('|') - $.facebox.settings.imageTypesRegexp = new RegExp('\.(' + imageTypes + ')$', 'i') - - if (settings) $.extend($.facebox.settings, settings) - $('body').append($.facebox.settings.faceboxHtml) - - var preload = [ new Image(), new Image() ] - preload[0].src = $.facebox.settings.closeImage - preload[1].src = $.facebox.settings.loadingImage - - $('#facebox').find('.b:first, .bl').each(function() { - preload.push(new Image()) - preload.slice(-1).src = $(this).css('background-image').replace(/url\((.+)\)/, '$1') - }) - - $('#facebox .close').click($.facebox.close) - $('#facebox .close_image').attr('src', $.facebox.settings.closeImage) - } - - // getPageScroll() by quirksmode.com - function getPageScroll() { - var xScroll, yScroll; - if (self.pageYOffset) { - yScroll = self.pageYOffset; - xScroll = self.pageXOffset; - } else if (document.documentElement && document.documentElement.scrollTop) { // Explorer 6 Strict - yScroll = document.documentElement.scrollTop; - xScroll = document.documentElement.scrollLeft; - } else if (document.body) {// all other Explorers - yScroll = document.body.scrollTop; - xScroll = document.body.scrollLeft; - } - return new Array(xScroll,yScroll) - } - - // Adapted from getPageSize() by quirksmode.com - function getPageHeight() { - var windowHeight - if (self.innerHeight) { // all except Explorer - windowHeight = self.innerHeight; - } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode - windowHeight = document.documentElement.clientHeight; - } else if (document.body) { // other Explorers - windowHeight = document.body.clientHeight; - } - return windowHeight - } - - // Backwards compatibility - function makeCompatible() { - var $s = $.facebox.settings - - $s.loadingImage = $s.loading_image || $s.loadingImage - $s.closeImage = $s.close_image || $s.closeImage - $s.imageTypes = $s.image_types || $s.imageTypes - $s.faceboxHtml = $s.facebox_html || $s.faceboxHtml - } - - // Figures out what you want to display and displays it - // formats are: - // div: #id - // image: blah.extension - // ajax: anything else - function fillFaceboxFromHref(href, klass) { - // div - if (href.match(/#/)) { - var url = window.location.href.split('#')[0] - var target = href.replace(url,'') - if (target == '#') return - $.facebox.reveal($(target).html(), klass) - - // image - } else if (href.match($.facebox.settings.imageTypesRegexp)) { - fillFaceboxFromImage(href, klass) - // ajax - } else { - fillFaceboxFromAjax(href, klass) - } - } - - function fillFaceboxFromImage(href, klass) { - var image = new Image() - image.onload = function() { - $.facebox.reveal('
          ', klass) - } - image.src = href - } - - function fillFaceboxFromAjax(href, klass) { - $.get(href, function(data) { $.facebox.reveal(data, klass) }) - } - - function skipOverlay() { - return $.facebox.settings.overlay == false || $.facebox.settings.opacity === null - } - - function showOverlay() { - if (skipOverlay()) return - - if ($('#facebox_overlay').length == 0) - $("body").append('
          ') - - $('#facebox_overlay').hide().addClass("facebox_overlayBG") - .css('opacity', $.facebox.settings.opacity) - .click(function() { $(document).trigger('close.facebox') }) - .fadeIn(200) - return false - } - - function hideOverlay() { - if (skipOverlay()) return - - $('#facebox_overlay').fadeOut(200, function(){ - $("#facebox_overlay").removeClass("facebox_overlayBG") - $("#facebox_overlay").addClass("facebox_hide") - $("#facebox_overlay").remove() - }) - - return false - } - - /* - * Bindings - */ - - $(document).bind('close.facebox', function() { - $(document).unbind('keydown.facebox') - $('#facebox').fadeOut(function() { - $('#facebox .content').removeClass().addClass('content') - $('#facebox .loading').remove() - $(document).trigger('afterClose.facebox') - }) - hideOverlay() - }) - -})(jQuery); diff --git a/TryRuby/public/javascripts/jQuery.irb.js b/TryRuby/public/javascripts/jQuery.irb.js deleted file mode 100644 index 765858d..0000000 --- a/TryRuby/public/javascripts/jQuery.irb.js +++ /dev/null @@ -1,1641 +0,0 @@ -//Try Ruby 1.5 (defacto version Number) -// March 14 2011 - -// large parts of this file are lifted from Try Haskell ( which lifted parts from try ruby without copyright notice >:-/ ) - -// Thus it is fair to include the following banner if/until there is no try haskell code left/ only code that originally existed in try ruby in the -//first place. - - // Try Haskell 1.0.1 - // Tue Feb 23 18:34:48 GMT 2010 - // - // Copyright 2010 Chris Done. All rights reserved. - // - // Redistribution and use in source and binary forms, with or without - // modification, are permitted provided that the following conditions - // are met: - // - // 1. Redistributions of source code must retain the above - // copyright notice, this list of conditions and the following - // disclaimer. - // 2. Redistributions in binary form must reproduce the above - // copyright notice, this list of conditions and the following - // disclaimer in the documentation and/or other materials - // provided with the distribution. - // - // THIS SOFTWARE IS PROVIDED BY CHRIS DONE ``AS IS'' AND ANY EXPRESS - // OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - // ARE DISCLAIMED. IN NO EVENT SHALL CHRIS DONE OR CONTRIBUTORS BE - // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - // OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - // DAMAGE. - // The views and conclusions contained in the software and - // documentation are those of the authors and should not be - // interpreted as representing official policies, either expressed or - // implied, of Chris Done. - // - // TESTED ON - // Internet Explorer 6 - // Opera 10.01 - // Chromium 4.0.237.0 (Ubuntu build 31094) - // Firefox 3.5.8 - - //IOS 4.3 (all devices) - -// Temporary fix -function opera() { - return navigator.userAgent.indexOf("Opera") == 0; -} - -function encodeHex(str) { - var result = ""; - for (var i = 0; i < str.length; i++) { - result += "%" + pad(toHex(str.charCodeAt(i) & 0xff), 2, '0'); - } - return result; -} - -//var handleJSON = function(a){ alert('Unassigned JSONP: ' + a); } -var hexv = { - "00": 0, - "01": 1, - "02": 2, - "03": 3, - "04": 4, - "05": 5, - "06": 6, - "07": 7, - "08": 8, - "09": 9, - "0A": 10, - "0B": 11, - "0C": 12, - "0D": 13, - "0E": 14, - "0F": 15, - "10": 16, - "11": 17, - "12": 18, - "13": 19, - "14": 20, - "15": 21, - "16": 22, - "17": 23, - "18": 24, - "19": 25, - "1A": 26, - "1B": 27, - "1C": 28, - "1D": 29, - "1E": 30, - "1F": 31, - "20": 32, - "21": 33, - "22": 34, - "23": 35, - "24": 36, - "25": 37, - "26": 38, - "27": 39, - "28": 40, - "29": 41, - "2A": 42, - "2B": 43, - "2C": 44, - "2D": 45, - "2E": 46, - "2F": 47, - "30": 48, - "31": 49, - "32": 50, - "33": 51, - "34": 52, - "35": 53, - "36": 54, - "37": 55, - "38": 56, - "39": 57, - "3A": 58, - "3B": 59, - "3C": 60, - "3D": 61, - "3E": 62, - "3F": 63, - "40": 64, - "41": 65, - "42": 66, - "43": 67, - "44": 68, - "45": 69, - "46": 70, - "47": 71, - "48": 72, - "49": 73, - "4A": 74, - "4B": 75, - "4C": 76, - "4D": 77, - "4E": 78, - "4F": 79, - "50": 80, - "51": 81, - "52": 82, - "53": 83, - "54": 84, - "55": 85, - "56": 86, - "57": 87, - "58": 88, - "59": 89, - "5A": 90, - "5B": 91, - "5C": 92, - "5D": 93, - "5E": 94, - "5F": 95, - "60": 96, - "61": 97, - "62": 98, - "63": 99, - "64": 100, - "65": 101, - "66": 102, - "67": 103, - "68": 104, - "69": 105, - "6A": 106, - "6B": 107, - "6C": 108, - "6D": 109, - "6E": 110, - "6F": 111, - "70": 112, - "71": 113, - "72": 114, - "73": 115, - "74": 116, - "75": 117, - "76": 118, - "77": 119, - "78": 120, - "79": 121, - "7A": 122, - "7B": 123, - "7C": 124, - "7D": 125, - "7E": 126, - "7F": 127, - "80": 128, - "81": 129, - "82": 130, - "83": 131, - "84": 132, - "85": 133, - "86": 134, - "87": 135, - "88": 136, - "89": 137, - "8A": 138, - "8B": 139, - "8C": 140, - "8D": 141, - "8E": 142, - "8F": 143, - "90": 144, - "91": 145, - "92": 146, - "93": 147, - "94": 148, - "95": 149, - "96": 150, - "97": 151, - "98": 152, - "99": 153, - "9A": 154, - "9B": 155, - "9C": 156, - "9D": 157, - "9E": 158, - "9F": 159, - "A0": 160, - "A1": 161, - "A2": 162, - "A3": 163, - "A4": 164, - "A5": 165, - "A6": 166, - "A7": 167, - "A8": 168, - "A9": 169, - "AA": 170, - "AB": 171, - "AC": 172, - "AD": 173, - "AE": 174, - "AF": 175, - "B0": 176, - "B1": 177, - "B2": 178, - "B3": 179, - "B4": 180, - "B5": 181, - "B6": 182, - "B7": 183, - "B8": 184, - "B9": 185, - "BA": 186, - "BB": 187, - "BC": 188, - "BD": 189, - "BE": 190, - "BF": 191, - "C0": 192, - "C1": 193, - "C2": 194, - "C3": 195, - "C4": 196, - "C5": 197, - "C6": 198, - "C7": 199, - "C8": 200, - "C9": 201, - "CA": 202, - "CB": 203, - "CC": 204, - "CD": 205, - "CE": 206, - "CF": 207, - "D0": 208, - "D1": 209, - "D2": 210, - "D3": 211, - "D4": 212, - "D5": 213, - "D6": 214, - "D7": 215, - "D8": 216, - "D9": 217, - "DA": 218, - "DB": 219, - "DC": 220, - "DD": 221, - "DE": 222, - "DF": 223, - "E0": 224, - "E1": 225, - "E2": 226, - "E3": 227, - "E4": 228, - "E5": 229, - "E6": 230, - "E7": 231, - "E8": 232, - "E9": 233, - "EA": 234, - "EB": 235, - "EC": 236, - "ED": 237, - "EE": 238, - "EF": 239, - "F0": 240, - "F1": 241, - "F2": 242, - "F3": 243, - "F4": 244, - "F5": 245, - "F6": 246, - "F7": 247, - "F8": 248, - "F9": 249, - "FA": 250, - "FB": 251, - "FC": 252, - "FD": 253, - "FE": 254, - "FF": 255 -}; - -function pad(str, len, pad) { - var result = str; - for (var i = str.length; i < len; i++) { - result = pad + result; - } - return result; -} - -var digitArray = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'); - -function toHex(n) { - var result = '' - var start = true; - for (var i = 32; i > 0;) { - i -= 4; - var digit = (n >> i) & 0xf; - if (!start || digit != 0) { - start = false; - result += digitArray[digit]; - } - } - return (result == '' ? '0': result); -} - - (function($) { - var raphaelPaper; - var raphaelObjs; - var tutorialGuide; - - // I don't like this at all... I intend to make this pull via ajax from a key value data store. - var pages = - [ - //////////////////////////////////////////////////////////////////////// - // Lesson 1 - // Simple addition - { - lesson: 1, - title: 'Basics; numbers, strings, etc.', - guide: - '

          ' + rmsg(['Learning By Numbers', 'Music is Math', 'Back to Basics']) - + '

          ' - + "

          To kick off let's try some maths out. Up there you can" - + " type in Haskell expressions. Try this out: 5 + 7

          " - }, - { - guide: function(result) { - if (!result) result = { - expr: '5+7', - result: 12 - }; - var complied = result.expr.replace(/ /g, '') == "5+7"; - var who = complied ? 'we': 'you'; - return '

          ' + rmsg(['Your first Haskell expression', - "First Time's a Charm"]) + '

          ' - + '

          Well done, you typed it perfect! You got back the number' + - ' ' + result.result + '. Just what ' + who + ' wanted. ' - + "

          Let's try something completely different." + - " Type in your name like this:" + - ' "chris"

          ' - }, - trigger: function(result) { - return result.type == "(Num t) => t" || - result.type == "Integer" || - result.type == "Int"; - } - }, - // Strings & types - { - guide: function(result) { - if (!result) result = { - expr: '"chris"', - result: "\"chris\"" - }; - var n = unString(result.result); - if (n) n = ", " + n; - n += "!"; - return '

          ' + rmsg(['Types of values', "What's in a name?"]) + - '

          ' - + '

          Hi there' + htmlEncode(n) - + (n != "!" ? " That's a pretty name. Honest.": "") - + " You're getting the hang of this!

          " + - "

          Note: You can chat to Haskell programmers while learning here, enter chat to start it." + - " You will join the official IRC channel of the Haskell community!

          " - + "

          Each time, you're getting back the value of the expression. So " + - "far, just a number and a list of characters.

          " + - "

          You can have lists of other stuff, too. Let's see your " + - " lottery numbers: [42,13,22]

          " - }, - trigger: function(result) { - return result.type == "[Char]" - || result.type == "String"; - } - }, - // Overview of lesson 1 - { - guide: function(result) { - if (!result) result = { - result: "[42,13,22]" - }; - return '

          ' + rmsg(["Lesson 1 done already!"]) + - '

          ' + - "

          Great, you made a list of numbers! If you win we'll split" + - " the winnings, right?

          " + - "

          Let's see what you've learned so far:

          " + - "
            " + - "
          1. How to write maths and lists of things.
          2. " + - "
          " + - "

          You can do stuff with lists. Maybe you want the lottery " + - "numbers sorted in the right order, try this: " + - "sort " + result.result + "

          " - }, - trigger: function(result) { - return result.expr.match(/^[ ]*\[[0-9, ]+\][ ]*$/) && - result.type == "(Num t) => [t]"; - } - }, - /////////////////////////////////////////////////////////////////////// - // Lesson 2 - Functions - // Functions on lists - { - lesson: 2, - title: 'Simple Functions', - guide: function(result) { - if (!result) result = { - result: "[13,23,30]" - }; - return '

          ' + rmsg(["We put the funk in function"]) + - '

          ' + - "

          Congratulations, you just used a function." + - " They're how you get things done in Haskell." + - "

          As you might've guessed, we got back " + - htmlEncode(result.result) - + ".

          Ever wanted an evil twin nemesis? Me too. " + - "Luckily, you can sort lists of characters, or " + - "strings" + - ", in the same way as numbers! sort \"chris\"

          " - }, - trigger: function(result) { - return result.expr.match(/sort/) && - result.type == "(Num t, Ord t) => [t]"; - } - }, - // Tuples - { - guide: function(result) { - if (!result) result = { - result: "\"chirs\"" - }; - nemesis = htmlEncode(unString(result.result)); - return '

          ' + - rmsg(["Tuples, because sometimes one value ain't enough!"]) + - '

          ' + - "

          Watch out for " + nemesis + "! You should keep their credentials for the police.

          " + - "

          My nemesis is 28 years of age: " + - "(28,\"chirs\")

          " - }, - trigger: function(result) { - return result.expr.match(/sort/) && - result.type == "[Char]"; - } - }, - // Functions on tuples - { - guide: function(result) { - if (!result) result = { - result: "(28,\"chirs\")" - }; - var age = result.result.match(/^\(([0-9]+)+/); - var villain = htmlEncode(result.result.replace(/\\"/g, '"')); - return '

          ' + - rmsg(["We'll keep them safe, don't worry about it."]) + - '

          ' + - "

          Is " + (age ? age[1] : "that") + " a normal age for a " + - "super-villain?

          " + - "

          You just wrote a tuple. It's a way to keep a bunch of values together in Haskell. " + - "You can put as many as you like in there:

          " + - "
          • (1,\"hats\",23/35)
          • (\"Shaggy\",\"Daphnie\",\"Velma\")
          " + - "

          Actually, let's say our villain is " + - "" + villain + "" + - ", how do you get their age?

          " + - "fst " + villain + "" - }, - trigger: function(result) { - return result.expr.match(/\([0-9]+,[ ]*"[^"]+"\)/) && - result.type == "(Num t) => (t, [Char])"; - } - }, - // Summary of lesson 2 - { - guide: function(result) { - return '

          ' + - rmsg(["Lesson 2 done! Wow, great job!", - "Lesson 2 completo!"]) + - '

          ' + - - "

          Good job! You got the age back from the tuple! Didn't " + - " even break a sweat, did you? The fst function " + - "just gets the first value. It's called \"fst\" because " + - "it's used a lot in Haskell so it really needs to be short!

          " + - - "

          Time to take a rest and see what you learned:

          " + - "
            " + - "
          1. Functions can be used on lists of any type.
          2. " + - "
          3. We can stuff values into tuples.
          4. " + - "
          5. Getting the values back from tuples is easy.
          6. " + - "
          " + - - "

          Now let's say you want " + - " to use a value more than once, how would you do it? " + - "To make our lives easier, we can say:

          " + - - "let x = 4 in x * x" - }, - trigger: function(result) { - return result.expr.match(/fst/) && - result.type == "(Num t) => t"; - } - }, - { - guide: function(result) { - return "

          Let them eat cake

          " + - - "

          You just bound a variable. " + - "That is, you bound x to the expression 4, " + - " and then you can write x in some code (the body) and " + - " it will mean the same as if you'd written 4.

          " + - - "

          It's like this: let var = expression in body

          " + - - "The in part just separates the expression from the body.

          " + - - "

          For example try: " + - "let x = 8 * 10 in x + x

          " + - - "

          So if we wanted to get the age of our villain, we could do:

          " + - - "let villain = (28,\"chirs\") in fst villain" - - }, - trigger: function(result) { - return result.expr.match(/^[ ]*let[ ]+x[ ]*=[ ]*[0-9]+[ ]*in[ ]*x[ ]*\*[ ]*x/) && - result.type == "(Num t) => t"; - } - }, - { - guide: function(result) { - return "

          Basics over, let's go!

          " + - "

          Next, let's take a short detour to learn about " + - "syntactic sugar. " + - "Try typing this out:

          " + - "

          'a' : []

          " + - "

          Or skip to lesson4 to learn about functions," + - " the meat of Haskell!"; - }, - trigger: function(result) { - return result.expr.match(/^[ ]*let[ ]+villain[ ]*=[ ]*\([0-9]+,[ ]*"[^"]+"\)[ ]*in[ ]+fst[ ]+villain[ ]*/) && - result.type == "(Num t) => t"; - } - }, - // Lesson 3: Syntactic sugar - { - lesson: 3, - title: 'Syntactic Sugar', - guide: function(result) { - return '

          ' + - rmsg(["You constructed a list!"]) + - '

          ' + - "

          Well done, that was tricky syntax. You used the (:) " + - "function. It takes two values, some value and a list, and " + - " constructs a new list" + - " out of them. We call it 'cons' for short.

          " + - "

          'a' is " + - "the character 'a', [] is an empty list. So " + - "tacking 'a' at the start of an empty list just " + - "makes a list ['a']!

          " + - "

          But thankfully we don't have to type out " + - "'a' : 'b' : [] every time to we want to make a " + - "list of characters; we can use " + - "syntactic sugar and just write" + - " ['a','b']. Don't believe me, check this!

          " + - "'a' : 'b' : [] == ['a','b']" - }, - trigger: function(result) { - return result.expr.match(/^[ ]*'a'[ ]*:[ ]*\[\][ ]*/) && - result.type == "[Char]"; - } - }, - // Booleans and string syntactic sugar - { - guide: function(result) { - return '

          ' + - rmsg(["You're on fire!"]) + - '

          ' + - "

          You're handling this syntax really well, nice!

          " + - "

          You just got a boolean value back, and it said " + - "True. That means they're equal!

          " + - "

          One final demonstration on syntactic sugar for now:

          " + - "['a','b','c'] == \"abc\"" - }, - trigger: function(result) { - return result.type == "Bool" && - result.expr.replace(/[^':\[\]\=,]/g, '') == "'':'':[]==['','']"; - } - }, - // Summary of syntactic sugar section - { - guide: function(result) { - return '

          ' + - rmsg(["Lesson 3 over! Syntactic sugar is sweet"]) + - '

          ' + - "

          Let's have a gander at what you learned:

          " + - "
            " + - "
          1. In 'a' : [], : is really just " + - " another function, just clever looking.
          2. " + - "
          3. Pretty functions like this are written like (:) when " + - " you talk about them.
          4. " + - "
          5. A list of characters ['a','b'] can just be written " + - "\"ab\". Much easier!
          6. " - + "
          " + - "

          Phew! You're getting pretty deep! Your arch nemesis, " + - nemesis + ", is gonna try to steal your " + rmsg(['mojo', - 'pizza']) + - "! Let's learn a bit more about functions and passing " + - "them around. Try this:

          map (+1) [1..5]

          "; - }, - trigger: function(result) { - return result.expr.replace(/[^\]\[',=\"]?/g, '') == "['','','']==\"\"" && - result.type == "Bool"; - } - }, - { - lesson: 4, - title: 'Functions, reloaded; passing, defining, etc.', - guide: function() { - var title = - rmsg(["Functions [of a Geisha]", - "Functions, functors, functoids, funky", - "Functions: Expanded fo' real"]); - return "

          " + title + "

          " + - - "

          Here's where the magic begins!

          " + - - "

          You just passed the (+1) " + - "function to the map function.

          " + - - "

          You can try other things like (remember: click to insert them):

          " + - - "
            " + - "
          • map (*99) [1..10]
          • " + - "
          • map (/5) [13,24,52,42]
          • " + - "
          • filter (>5) [62,3,25,7,1,9]
          • " + - "
          " + - - "

          Note that a tuple is different to a list because you can do this:

          " + - "(1,\"George\")" - }, - trigger: function(result) { - return result.expr.match(/^[ ]*map[ ]+\(\+1\)[ ]*\[1..5\][ ]*$/) && - result.type == "(Num a, Enum a) => [a]"; - } - }, - { - guide: function(result) { - return "

          Lists and Tuples

          " + - - "

          You can only " + - " have a list of numbers or a list of characters, whereas in a tuple you can throw anything in!

          " + - - "

          We've also seen that you can make a new list with (:) that joins two values together, like:

          " + - "

          1 : [2,3]

          " + - - "

          But we can't do this with tuples! You can only write a tuple and then look at what's inside. You can't make new ones on the fly like a list." + - - "

          Let's write our own functions! It's really easy. How about something simple:

          " + - "let square x = x * x in square " + rmsg([52, 10, 3]) + "" - - }, - trigger: function(result) { - return result.expr.match(/^[ ]*\(1,"[^"]+"\)[ ]*$/) && - result.type == "(Num t) => (t, [Char])"; - } - }, - { - guide: function(result) { - return "

          Let there be functions

          " + - "

          Nice one! I think you're getting used to the let syntax.

          " + - "

          You defined a function. You can read it as, as for a given " + - "parameter called x, square of " + - "x is x * x." + - "

          Some others you can try are:

          " + - "
          • let add1 x = x + 1 in add1 5
          • " + - "
          • let second x = snd x in second (3,4)
          • " + - "
          " + - "

          Let's go crazy and use our square function with map:

          " + - "let square x = x * x in map square [1..10]" - }, - trigger: function(result) { - return result.expr.match(/^[ ]*let[ ]*square[ ]+x[ ]*=[ ]*x[ ]*\*[ ]*x[ ]*in[ ]*square[ ]+[0-9]+/) && - result.type == "(Num t) => t"; - } - }, - { - guide: function(result) { - if (!result || !result.value) result = { - value: "[1,4,9,16,25,36,49,64,81,100]" - }; - return "

          Let there be functions

          " + - - "

          That's so cool! You described a simple function square and then " + - "you just passed it to another function (map) and got back " + - htmlEncode(result.value) + ", exactly what you expected!

          " + - - "

          Haskell is pretty good at composing things together like this. " + - "Some other things you can try are:

          " + - - "
            " + - "
          • let add1 x = x + 1 in map add1 [1,5,7]
          • " + - "
          • let take5s = filter (==5) in take5s [1,5,2,5,3,5]
          • " + - "
          • let take5s = filter (==5) in map take5s [[1,5],[5],[1,1]]
          • " + - "
          " + - - "

          Did you get back what you expected?

          " + - - "

          One more example for text; how do you upcase a letter?

          " + - - "

          toUpper 'a'

          " - }, - trigger: function(result) { - return result.expr.match(/^[ ]*let[ ]+square[ ]+x[ ]*=[ ]*x[ ]*\*[ ]*x[ ]*in[ ]+map[ ]+square[ ]*\[1..10\][ ]*$/) && - result.type == "(Num a, Enum a) => [a]"; - } - }, - { - guide: function(result) { - return "

          Exercise time!

          " + - - "

          Easy! Remember: characters are written like 'a' and " + - "strings (lists of characters) are written like \"a\"." + - - "

          I need you to use toUpper capitalise my whole name, " + - "\"Chris\". Give it a try." + - " You can do it, I believe in you!

          " + - - '

          Spoiler: map toUpper "Chris"

          ' - }, - trigger: function(result) { - return result.expr.match(/^toUpper 'a'$/) && - result.type == "Char"; - } - }, - { - guide: function(result) { - return "

          Lesson 4 complete!

          " + - - "

          Brilliant! You're making excellent progress! " + - "You just passed toUpper to map. No problem.

          " + - - "

          Let's go over what you've learned in this lesson:

          " + - - "
            " + - "
          1. Functions like map take other functions as parameters.
          2. " + - "
          3. Functions like (+1), (>5) and " + - "square can be passed to other functions.
          4. " + - "
          5. Defining functions is just a case of writing what " + - "to do with the parameters.
          6. " + "
          " + - - "

          Let's check out pattern matching; a way to " + - "get values from other values using patterns. Try this:

          " + - "

          let (a,b) = (10,12) in a * 2

          " + - - "

          Or you can skip this section and go to straight to lesson6; types!

          " - }, - trigger: function(result) { - return result.type == "[Char]" && - result.expr.match(/^map[ ]+toUpper/); - } - }, - { - lesson: 5, - title: 'Pattern Matching', - guide: function(result) { - var title = - rmsg(["And therefore, patterns emerge in nature.", - "And Then Patterns", - "Pattern matching!"]) - return "

          " + title + "

          " + - - "

          Jolly good show!

          " + - "

          So you had a value (10,12) and matched " + - "it against a pattern (a,b), then you were able" + - " to do stuff with the a and b!" + - - "

          Note: Pattern matching (a,b) against " + - "(1,2) to get the a is the same as" + - " doing fst (1,2), like you did in step7!

          " + - - "

          A pattern always matches the way the " + - "value was originally constructed. Remember that \"abc\" is " + - "syntactic sugar for 'a' : 'b' : 'c' : [].

          " + - - "

          So you can get the characters from a string with patterns:

          " + - - "let (a:b:c:[]) = \"xyz\" in a" - }, - trigger: function(result) { - return result.expr.match(/^[ ]*let[ ]+\(a,b\)[ ]+=[ ]+\(10,12\)[ ]+in[ ]+a[ ]*\*[ ]*2[ ]*$/) && - result.type == "(Num t) => t"; - } - }, - { - guide: function(result) { - return "

          " + rmsg(["Ignorance is bliss", "Ignoring values"]) + "

          " + - - "

          You're getting into tricky syntax, huh? I know you can handle it!

          " + - - "

          If you just want some of the values, you can ignore the others with _ (underscore) like this:

          " + - - "

          let (a:_:_:_) = \"xyz\" in a

          " + - - "

          In fact, (a:b:c:d) is short-hand for " + - "(a:(b:(c:d))), so you can just ignore the rest in one go:

          " + - - "let (a:_) = \"xyz\" in a" - }, - trigger: function(result) { - return result.expr.match(/^[ ]*let[ ]+\(a:b:c:\[\]\)[ ]*=[ ]*\"xyz\"[ ]*in[ ]+a[ ]*$/) && - result.type == "Char"; - } - }, - { - guide: function(result) { - return "

          " + rmsg(["Exercise!", "Show me the money!"]) + "

          " + - - "

          Try to get the 'a' value from this value using pattern matching:

          " + - "

          (10,\"abc\")

          " + - - "

          Spoiler: let (_,(a:_)) = (10,\"abc\") in a

          " - }, - trigger: function(result) { - return result.expr.match(/^[ ]*let[ ]*\(a:_\)[ ]*=[ ]*"xyz"[ ]*in[ ]*a[ ]*$/) && - result.type == "Char"; - } - }, - { - guide: function(result) { - return "

          " + rmsg(["Well done!", "Brilliant!", "Perfetto!"]) + "

          " + - - "

          Wizard! I think you've got pattern-matching down.

          " + - - "

          If you're still a bit unsure, here are some other things you can try:

          " + - - "
            " + - "
          • let _:_:c:_ = \"abcd\" in c
          • " + - "
          • let [a,b,c] = \"cat\" in (a,b,c)
          • " + - "
          " + - - "

          You can also grab a whole value and pattern match on it (have your cake and eat it too):

          " + - - "let abc@(a,b,c) = (10,20,30) in (abc,a,b,c)" - }, - trigger: function(result) { - return result.expr.match(/^[ ]*let[ ]*\(_,\(?a:_\)?\)[ ]*=[ ]*\(10,\"abc\"\)[ ]*in[ ]*a[ ]*$/) && - result.type == "Char"; - } - }, - { - guide: function(result) { - return "

          " + rmsg(["And that's the end of that chapter"]) + "

          " + - - "

          That was easy, right?

          " + - - "

          Let's go over what you've learned in this lesson:

          " + - - "
            " + - "
          1. Values are pattern matched, or deconstructed, by writing however they were constructed.
          2. " + - "
          3. Patterns let you use the values that you match.
          4. " + - "
          5. You can ignore whichever values you want.
          6. " + - "
          7. You can pattern match and keep hold of the original value too.
          8. " + - "
          " + - - "

          Now we get to the Deep Ones. Types!

          " + - - "

          Consider the following value: 'a'

          " - - }, - trigger: function(result) { - return result.type == "(Num t, Num t1, Num t2) => ((t, t1, t2), t, t1, t2)"; - } - }, - { - lesson: 6, - title: 'Types', - guide: function(result) { - showTypes = true; - return "

          " + rmsg(["Types", "What's in a Type?", "Types & Values"]) + "

          " + - "

          What's this? Something new!

          " + - - "

          In Haskell there are types of values. Every value belongs to a type. To demonstrate this fact, I've sneakily enabled types to be " + - "shown of every value in the console from now on.

          " + - - "

          The type of the value 'a' is Char (short for 'character', but you guessed that, right?).

          " + - - "

          You've seen the type of a character, now what about" + - " a list of characters?

          " + - "\"Spartacus\"" - }, - trigger: function(result) { - return result.type == 'Char'; - } - }, - { - guide: function(result) { - showTypes = true; - return "

          " + rmsg(["Lists of stuff, types"]) + "

          " + - - "

          I'm Spartacus!

          " + - - "

          Okay, so a list of characters has type [Char].

          " + - - "

          Notice that when we write a :: X it means the value a has type X. It's just a short-hand called a signature.

          " + - - "

          If you just want the type of a value, without actually evaluating it, you can just type:

          " + - ":t toUpper" - }, - trigger: function(result) { - return result.expr.match(/"[^"]+"/) && - result.type == '[Char]'; - } - }, - { - guide: function(result) { - showTypes = true; - return "

          " + rmsg(["Function types"]) + "

          " + - - "

          Woah! Hold your blinkin' 'orses! The type of toUpper reads: Char -> Char

          " + - - "

          It's pretty easy; a -> b means function from a to b. " + - "So

          toUpper :: Char -> Char means: for a" + - " given character (Char value) a, toUpper a has type Char.

          " + - - "

          Some other things you can try are:

          " + - - "
          • :t words
          • " + - "
          • :t unwords
          • " + - "
          • :t True
          • " + - "
          • :t not
          • " - + "
          " + - - "

          The words function is pretty handy. Want to get a list of words from a sentence?

          " + - "words \"There's jam in my pants.\"" - }, - trigger: function(result) { - return result.type == 'Char -> Char'; - } - }, - { - guide: function(result) { - showTypes = true; - return "

          " + rmsg(["Mid-way review"]) + "

          " + - - "

          The type of words was String -> [String]. You got a list of strings back! Just what you expected, right?

          " + - - "

          Let's take a rest in the middle of this lesson and go over what we've learned:

          " + - - "
            " + - "
          1. All values in Haskell have a type. We describe the types of values with signatures, like True :: Bool.
          2. " + - "
          3. Functions are values too, and they have types, notated a -> b.
          4. " + - "
          5. Functions can be defined for any type to any other type.
          6. " + - "
          7. Humble reader has a thing for jammy pants.
          8. " + - "
          " + - - "

          But what if you have a type that can contain values of any type, like a tuple?

          " + - ":t fst" - - }, - trigger: function(result) { - return result.expr.match(/^[ ]*words[ ]*\"[^"]+\"[ ]*$/) && - result.type == '[String]'; - } - }, - { - guide: function(result) { - showTypes = true; - return "

          " + rmsg(["Polymorphic functions"]) + "

          " + - - "

          Remember this one? I know you do! fst (1,2) is 1, right?

          " + - "

          We read its type

          " + - "

          fst :: (a, b) -> a

          " + - "

          as: for all types a and b, the fst has type (a,b) to a. So the fst " + - "function works on a pair of values of any types! We call such a function polymorphic." + - "

          " + - "

          Remember the drop function? Maybe you don't. I don't! Let's check out its type:

          " + - "

          :t drop

          " - }, - trigger: function(result) { - return result.type == '(a, b) -> a'; - } - }, - { - guide: function(result) { - showTypes = true; - return "

          " + rmsg(["Multi parameter functions"]) + "

          " + - - "

          So the drop function has type

          Int -> [a] -> [a].

          " + - - "

          This is something new. You've got two arrows! Relax. You can read

          " + - "

          a -> b -> c as a -> (b -> c)

          " + - - "

          In other words, drop is a function from integers (Int values) to functions of lists to lists ([a] -> [a] values). Drop is a function to another function.

          " + - - "

          Check for yourself! :t drop 3

          " - }, - trigger: function(result) { - return result.type == 'Int -> [a] -> [a]'; - } - }, - { - guide: function(result) { - showTypes = true; - return "

          " + rmsg(["Partial application"]) + "

          " + - - "

          You've got a function of type [a] -> [a]! The drop function is considered a multi-parameter function. Remember the map function? Its parameters were a function and a list. Just another multi-parameter function.

          " + - - "

          You can add another parameter and, hey presto, you get a list!

          " + - - "drop 3 \"hello!\"" - - }, - trigger: function(result) { - return result.type == '[a] -> [a]'; - } - }, - { - guide: function(result) { - showTypes = true; - return "

          " + rmsg(["Higher order functions"]) + "

          " + - - "

          'Lo bob! You've already used the map function loads. I wonder if you can guess its type?

          " + - - "

          map :: (a -> b) -> [a] -> [b] (spoiler)

          " + - - "

          It's okay to peek! Have a go at guessing these: filter, take

          " + - - "

          Tip: You can use parantheses to use more than one function. You want to double all the numbers over five? Psch!

          " + - "map (*2) (filter (>5) [10,2,16,9,4])" - }, - trigger: function(result) { - return result.expr.match(/^[ ]*drop[ ]*[0-9]+[ ]*"[^"]+"[ ]*$/) && - result.type == '[Char]'; - } - }, - { - guide: function(result) { - showTypes = true; - return "

          " + rmsg(["Phew! Rest time!"]) + "

          " + - - "

          Wow! You're doing so great! Have a look at what you know now!

          " + - - "
            " + - "
          1. Function parameters can be polymorphic; any type!
          2. " + - "
          3. Functions can have multiple parameters by returning more functions.
          4. " + - "
          5. You can wrap expressions in parentheses and apply functions to them as a whole value.
          6. " + - "
          " + - - "

          You're really making great progress. Don't hesitate to sit and play in the console between chapters to get a good feel of it!

          " + - - "

          Stay tuned for more chapters on type classes and the meaning of :t 1, :t (*), etc.

          " + - learnMore - }, - trigger: function(result) { - return result.type == '(Num a, Ord a) => [a]'; - } - } - ]; - // - // var webchat; - // - // function runWebchat() { - // if (!webchat) { - // // Create webchat frame - // var webchat = - // $(''); - // webchat.attr('width', 635); - // webchat.attr('height', 500); - // webchat.css('float', 'left'); - // webchat.css('webkit-border-radius', '3px'); - // webchat.css('moz-border-radius', '3px'); - // webchat.css('border-radius', '3px'); - // webchat.css('border', '5px solid #eeeeee'); - // - // // Extend page wrap to fit console and chat - // $('.page-wrap').css({ - // width: '1250px' - // }); - // $('.primary-content').css('margin-left', 0); - // $('.page-wrap').append(webchat.css('margin-left', '5px')); - // } - // } - - var pageTrigger = -1; - var notices = []; - var controller; - // Console controller - var learnMore; - - //////////////////////////////////////////////////////////////////////// - // Unshow a string - function unString(str) { - return str.replace(/^"(.*)"$/, "$1").replace(/\\"/, '"'); - } - - //////////////////////////////////////////////////////////////////////// - // Random message from a list of messages - function rmsg(choices) { - return choices[Math.floor((Math.random() * 100) % choices.length)]; - } - - // Simple HTML encoding - // Simply replace '<', '>' and '&' - // TODO: Use jQuery's .html() trick, or grab a proper, fast - // HTML encoder. - function htmlEncode(text, shy) { - return ( - ('' + text).replace(/&/g, '&') - .replace(/'); - handleJSON = function(r) { - script.remove(); - func(r); - }; - script.attr('src', url); - $('body').append(script); - } - - - var console = $('.console'); - controller = console.console({ - promptLabel: '> ', - continuedPromptLabel: ' .. ', /*not quiet right but good enough*/ - cancelHandle: function() { - controller.commandRef.ignore = true; - controller.finishCommand(); - controller.report(); - }, - - commandHandle: function(line, report) { - - controller.ajaxloader = $('

          Loading...

          '); - var commandRef = {}; - controller.currentLine = line; - controller.commandRef = commandRef; - controller.report = report; - if (tellAboutRet) tellAboutRet.fadeOut(function() { - $(this).remove(); - }); - - if (libTrigger(line, report)) return; - controller.inner.append(controller.ajaxloader); - controller.scrollToBottom(); - - jsonp("http://localhost:3030/tryruby/run/?cmd=" + encodeHex(line), - function(resp) { - if (commandRef.ignore) { - return; - } - controller.finishCommand(); - var result = resp; - if (pageTrigger > -1 && result.expr) { - triggerTutorialPage(pageTrigger, result); - } - if (result.type) { - if (pageTrigger == 24) showTypes = false; - handleSuccess(report, result); - } else if (result.error) { - report( - [{ - msg: result.error, - className: "jquery-console-message-error jquery-console-message-compile-error" - }] - ); - notice('compile-error', - "A compile-time error! " + - "It just means the expression wasn't quite right. " + - "Try again.", - 'prompt'); - } else if (result.exception) { - var err = limitsError(result.exception); - report( - [{ - msg: err, - className: "jquery-console-message-error jquery-console-message-exception" - }] - ); - if (err == result.exception) { - notice('compile-error', - "A run-time error! The expression was right but the" + - " result didn't make sense. Check your expression and try again.", - 'prompt'); - } - } else if (result.internal) { - report( - [{ - msg: limitsError(result.internal), - className: "jquery-console-message-error jquery-console-message-internal" - }] - ); - } else if (result.bind) { - report(); - } else if (result.result) { - if (result.expr.match(/^:modules/)) { - report( - [{ - msg: result.result.replace(/[\["\]]/g, '') - .replace(/,/g, ', '), - className: "jquery-console-message-type" - }]); - } - } - }); - - }, - - charInsertTrigger: function() { - var t = notice('tellaboutreturn', - "Hit Return when you're " + - "finished typing your expression."); - if (t) tellAboutRet = t; - return true; - }, - autofocus: true, - promptHistory: true, - historyPreserveColumn: true, - welcomeMessage: 'Interactive ruby ready' - }); - - controller.finishCommand = function() { - controller.ajaxloader.remove(); - $('.jquery-console-prompt :last').each(function() { - lastLine = controller.currentLine; - if (!$(this).hasClass('prompt-done')) { - $(this).addClass('prompt-done'); - $(this).click(function() { - controller.promptText(controller.currentLine); - }); - } - }); - } - - makeGuidSamplesClickable(); - - var match = window.location.href.match(/#([0-9]+)$/); - if (match) { - pageTrigger = match[1] - 1; - setTutorialPage(undefined, match[1] - 1); - } - - var match = window.location.href.match(/\?input=([^&]+)/); - if (match) { - controller.promptText(urlDecode(match[1])); - controller.inner.click(); - controller.typer.consoleControl(13); - } - }); - - function urlDecode(encodedString) { - var output = encodedString; - var binVal, - thisString; - var myregexp = /(%[^%]{2})/; - while ((match = myregexp.exec(output)) != null - && match.length > 1 - && match[1] != '') { - binVal = parseInt(match[1].substr(1), 16); - thisString = String.fromCharCode(binVal); - output = output.replace(match[1], thisString); - } - return output; - } - - function makeGuidSamplesClickable() { - $('.chapmark code').each(function() { - $(this).css('cursor', 'pointer'); - $(this).attr('title', 'Click me to insert "' + - $(this).text() + '" into the console.'); - $(this).click(function() { - controller.promptText($(this).text()); - controller.inner.click(); - }); - }); - } - - String.prototype.trim = function() { - return this.replace(/^[\t ]*(.*)[\t ]*$/, '$1'); - }; - - //////////////////////////////////////////////////////////////////////// - // Trigger console commands - function libTrigger(line, report) { - switch (line.trim()) { - case 'help': - { - setTutorialPage(undefined, 0); - report(); - pageTrigger = 0; - return true; - } - case 'back': - { - if (pageTrigger > 0) { - setTutorialPage(undefined, pageTrigger - 1); - pageTrigger--; - report(); - return true; - } - break; - } - case 'lessons': - { - var lessons = $('
            '); - for (var i = 0; i < pages.length; i++) { - if (pages[i].lesson) { - lessons.append($('
          1. '). - html('lesson' + pages[i].lesson + ' - ' + - pages[i].title)); - } - } - var lessonsList = '

            Lessons

            ' + lessons.html(); - tutorialGuide.animate({ - opacity: 0, - height: 0 - }, - 'fast', - function() { - tutorialGuide.html(lessonsList); - tutorialGuide.css({ - height: 'auto' - }); - tutorialGuide.animate({ - opacity: 1 - }, - 'fast'); - makeGuidSamplesClickable(); - }); - report(); - return true; - } - default: - { - if (line.trim() == 'chat') { - notice('irc', - 'Enter your nick on the right hand side and hit Connect!', - 'prompt'); - report(); - runWebchat(); - return true; - } - - var m = line.trim().match(/^link(.*)/); - if (m) { - var data; - if (m[1]) data = m[1].trim(); - else if (lastLine) data = lastLine; - if (data) { - var addr = '?input=' + encodeHex(data); - report([{ - msg: '', - className: 'latest-link' - }]); - var link = $(''). - text('link for ' + data).click(function() { - window.location.href = $(this).attr('href'); - return false; - }); - $('.latest-link').html(link).removeClass('latest-link'); - return true; - } - } - - var m = line.trim().match(/^step([0-9]+)/); - if (m) { - if ((m[1] * 1) <= pages.length) { - setTutorialPage(undefined, m[1] - 1); - report(); - pageTrigger = m[1] - 1; - return true; - } - } - var m = line.trim().match(/^help ([0-9]+)/); - if (m) { - for (var i = 0; i < pages.length; i++) { - if (pages[i].lesson == m[1] * 1) { - setTutorialPage(undefined, i); - report(); - pageTrigger = i; - return true; - } - } - } - } - }; - }; - - //////////////////////////////////////////////////////////////////////// - // Change the tutorial page - function setTutorialPage(result, n) { - if (pages[n]) { - window.location.href = '#' + (1 * n + 1); - tutorialGuide.find('#helpstone').remove(); - tutorialGuide.animate({ - opacity: 0, - height: 0 - }, - 'fast', - function() { - if (typeof(pages[n].guide) == 'function') - tutorialGuide.html(pages[n].guide(result)); - else - tutorialGuide.html(pages[n].guide); - var back = ''; - if (pageTrigger > 0) - back = 'You\'re at step' + (n + 1) - + '. Type back to go back.'; - else - back = 'You\'re at step' + (n + 1) + '. Type step' + (n + 1) - + ' to return here.'; - if (true) tutorialGuide - .append('
            ' + back + '
            ') - .append('
            Lesson: ' + - searchLessonBack(n) + - '
            '); - tutorialGuide.css({ - height: 'auto' - }); - tutorialGuide.animate({ - opacity: 1 - }, - 'fast'); - makeGuidSamplesClickable(); - }); - } - }; - - function searchLessonBack(page) { - for (var i = page; i >= 0; i--) { - if (pages[i].lesson) return pages[i].lesson; - } - return "1"; - } - - //////////////////////////////////////////////////////////////////////// - // Trigger a page according to a result - function triggerTutorialPage(n, result) { - n++; - if (pages[n] && (typeof(pages[n].trigger) == 'function') - && pages[n].trigger(result)) { - pageTrigger++; - setTutorialPage(result, n); - } - }; - - //////////////////////////////////////////////////////////////////////// - // Trigger various libraries after JSONRPC returned - function handleSuccess(report, result) { - if (result.type.match(/^Graphics\.Raphael\.Raphael[\r\n ]/)) { - runRaphael(result.result); - report(); - } - if (result.type.match(/standard/)) { - var hashrocket = ''; - var msg_value = ' => '; - if (result.result == null) { - hashrocket = ' => ' - msg_value = ''; - } - report( - [{ - msg: msg_value + result.output + hashrocket + result.result, - className: "jquery-console-message-value" - }]); - } - - if (result.type.match(/error/)) { - - report( - [{ - msg: result.error, - className: "jquery-console-message-value" - }]); - } - - if (result.type.match(/illegal/)) { - - report( - [{ - msg: 'You are not allowed to run that command!', - className: "jquery-console-message-value" - }]); - } - - - if (result.type.match(/line_continuation/)) { - report( - [{ - msg: '..', - className: "jquery-console-prompt-label" - }]); - } - - }; - - //////////////////////////////////////////////////////////////////////// - // Raphael support - function runRaphael(expr) { - raphaelPaper.clear(); - $('#raphael').parent().parent().slideDown(function() { - var exprs = expr.split(/\n/g); - for (var i = 0; i < exprs.length; i++) - raphaelRunExpr(exprs[i]); - }); - } - function raphaelRunExpr(expr) { - var expr = expr.split(/ /g); - switch (expr[0]) { - case 'new': - { - switch (expr[2]) { - case 'circle': - { - var x = expr[3], - y = expr[4], - radius = expr[5]; - var circle = raphaelPaper.circle(x * 1, y * 1, radius * 1); - circle.attr("fill", "#7360a4"); - break; - } - } - } - } - } - - function notice(name, msg, style) { - if (opera()) return; - if (!notices[name]) { - notices[name] = name; - return controller.notice(msg, style); - } - } - - function limitsError(str) { - if (str == "Terminated!") { - notice('terminated', - "This error means it took to long to work" + - " out on the server.", - 'fadeout'); - return "Terminated!"; - } else if (str == "Time limit exceeded.") { - notice('exceeded', - "This error means it took to long to work out on the server. " + - "Try again.", - 'fadeout'); - return "Terminated! Try again."; - } - return str; - } - -})(jQuery); diff --git a/TryRuby/public/javascripts/raphael-min.js b/TryRuby/public/javascripts/raphael-min.js deleted file mode 100644 index 4a99e3e..0000000 --- a/TryRuby/public/javascripts/raphael-min.js +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Raphael 1.4.3 - JavaScript Vector Library - * - * Copyright (c) 2010 Dmitry Baranovskiy (http://raphaeljs.com) - * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. - */ -Raphael=function(){function m(){if(m.is(arguments[0],U)){for(var a=arguments[0],b=Aa[K](m,a.splice(0,3+m.is(a[0],O))),c=b.set(),d=0,f=a[o];d

            ";if(ha.childNodes[o]!=2)return m.type=null;ha=null}m.svg=!(m.vml=m.type=="VML");G[p]=m[p];m._id=0;m._oid=0;m.fn={};m.is=function(a,b){b=ca.call(b);return b=="object"&&a===Object(a)||b=="undefined"&&typeof a==b||b=="null"&&a==null||ca.call(ob.call(a).slice(8,-1))==b};m.setWindow=function(a){X=a;C=X.document};function ra(a){if(m.vml){var b=/^\s+|\s+$/g;ra=T(function(d){var f;d=(d+s)[I](b, -s);try{var e=new X.ActiveXObject("htmlfile");e.write("");e.close();f=e.body}catch(g){f=X.createPopup().document.body}e=f.createTextRange();try{f.style.color=d;var h=e.queryCommandValue("ForeColor");h=(h&255)<<16|h&65280|(h&16711680)>>>16;return"#"+("000000"+h[N](16)).slice(-6)}catch(i){return"none"}})}else{var c=C.createElement("i");c.title="Rapha\u00ebl Colour Picker";c.style.display="none";C.body[y](c);ra=T(function(d){c.style.color=d;return C.defaultView.getComputedStyle(c,s).getPropertyValue("color")})}return ra(a)} -function qb(){return"hsb("+[this.h,this.s,this.b]+")"}function rb(){return this.hex}m.hsb2rgb=T(function(a,b,c){if(m.is(a,"object")&&"h"in a&&"s"in a&&"b"in a){c=a.b;b=a.s;a=a.h}var d;if(c==0)return{r:0,g:0,b:0,hex:"#000"};if(a>1||b>1||c>1){a/=255;b/=255;c/=255}d=~~(a*6);a=a*6-d;var f=c*(1-b),e=c*(1-b*a),g=c*(1-b*(1-a));a=[c,e,f,f,g,c,c][d];b=[g,c,c,e,f,f,g][d];d=[f,f,g,c,c,e,f][d];a*=255;b*=255;d*=255;c={r:a,g:b,b:d,toString:rb};a=(~~a)[N](16);b=(~~b)[N](16);d=(~~d)[N](16);a=a[I](ga,"0");b=b[I](ga, -"0");d=d[I](ga,"0");c.hex="#"+a+b+d;return c},m);m.rgb2hsb=T(function(a,b,c){if(m.is(a,"object")&&"r"in a&&"g"in a&&"b"in a){c=a.b;b=a.g;a=a.r}if(m.is(a,ea)){var d=m.getRGB(a);a=d.r;b=d.g;c=d.b}if(a>1||b>1||c>1){a/=255;b/=255;c/=255}var f=Y(a,b,c),e=$(a,b,c);d=f;if(e==f)return{h:0,s:0,b:f};else{var g=f-e;e=g/f;a=a==f?(b-c)/g:b==f?2+(c-a)/g:4+(a-b)/g;a/=6;a<0&&a++;a>1&&a--}return{h:a,s:e,b:d,toString:qb}},m);var sb=/,?([achlmqrstvxz]),?/gi,sa=/\s*,\s*/,tb={hs:1,rg:1};m._path2string=function(){return this.join(",")[I](sb, -"$1")};function T(a,b,c){function d(){var f=Array[p].slice.call(arguments,0),e=f[Q]("\u25ba"),g=d.cache=d.cache||{},h=d.count=d.count||[];if(g[z](e))return c?c(g[e]):g[e];h[o]>=1000&&delete g[h.shift()];h[E](e);g[e]=a[K](b,f);return c?c(g[e]):g[e]}return d}m.getRGB=T(function(a){if(!a||(a+=s).indexOf("-")+1)return{r:-1,g:-1,b:-1,hex:"none",error:1};if(a=="none")return{r:-1,g:-1,b:-1,hex:"none"};!(tb[z](a.substring(0,2))||a.charAt()=="#")&&(a=ra(a));var b,c,d,f,e;if(a=a.match(pb)){if(a[2]){d=da(a[2].substring(5), -16);c=da(a[2].substring(3,5),16);b=da(a[2].substring(1,3),16)}if(a[3]){d=da((e=a[3].charAt(3))+e,16);c=da((e=a[3].charAt(2))+e,16);b=da((e=a[3].charAt(1))+e,16)}if(a[4]){a=a[4][H](sa);b=A(a[0]);c=A(a[1]);d=A(a[2]);f=A(a[3])}if(a[5]){a=a[5][H](sa);b=A(a[0])*2.55;c=A(a[1])*2.55;d=A(a[2])*2.55;f=A(a[3])}if(a[6]){a=a[6][H](sa);b=A(a[0]);c=A(a[1]);d=A(a[2]);return m.hsb2rgb(b,c,d)}if(a[7]){a=a[7][H](sa);b=A(a[0])*2.55;c=A(a[1])*2.55;d=A(a[2])*2.55;return m.hsb2rgb(b,c,d)}a={r:b,g:c,b:d};b=(~~b)[N](16); -c=(~~c)[N](16);d=(~~d)[N](16);b=b[I](ga,"0");c=c[I](ga,"0");d=d[I](ga,"0");a.hex="#"+b+c+d;isFinite(A(f))&&(a.o=f);return a}return{r:-1,g:-1,b:-1,hex:"none",error:1}},m);m.getColor=function(a){a=this.getColor.start=this.getColor.start||{h:0,s:1,b:a||0.75};var b=this.hsb2rgb(a.h,a.s,a.b);a.h+=0.075;if(a.h>1){a.h=0;a.s-=0.2;a.s<=0&&(this.getColor.start={h:0,s:1,b:a.b})}return b.hex};m.getColor.reset=function(){delete this.start};var ub=/([achlmqstvz])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig, -vb=/(-?\d*\.?\d*(?:e[-+]?\d+)?)\s*,?\s*/ig;m.parsePathString=T(function(a){if(!a)return null;var b={a:7,c:6,h:1,l:2,m:2,q:4,s:4,t:2,v:1,z:0},c=[];if(m.is(a,U)&&m.is(a[0],U))c=ta(a);c[o]||(a+s)[I](ub,function(d,f,e){var g=[];d=ca.call(f);e[I](vb,function(h,i){i&&g[E](+i)});if(d=="m"&&g[o]>2){c[E]([f][M](g.splice(0,2)));d="l";f=f=="m"?"l":"L"}for(;g[o]>=b[d];){c[E]([f][M](g.splice(0,b[d])));if(!b[d])break}});c[N]=m._path2string;return c});m.findDotsAtSegment=function(a,b,c,d,f,e,g,h,i){var j=1-i,l= -D(j,3)*a+D(j,2)*3*i*c+j*3*i*i*f+D(i,3)*g;j=D(j,3)*b+D(j,2)*3*i*d+j*3*i*i*e+D(i,3)*h;var n=a+2*i*(c-a)+i*i*(f-2*c+a),r=b+2*i*(d-b)+i*i*(e-2*d+b),q=c+2*i*(f-c)+i*i*(g-2*f+c),k=d+2*i*(e-d)+i*i*(h-2*e+d);a=(1-i)*a+i*c;b=(1-i)*b+i*d;f=(1-i)*f+i*g;e=(1-i)*e+i*h;h=90-w.atan((n-q)/(r-k))*180/w.PI;(n>q||r1){B=w.sqrt(B);c=B*c;d=B*d}B=c*c;var L=d*d;B=(e==g?-1:1)*w.sqrt(w.abs((B*L-B*x*x-L*k*k)/(B*x*x+L*k*k)));e=B*c*x/d+(a+h)/2;var B= -B*-d*k/c+(b+i)/2,x=w.asin(((b-B)/d).toFixed(7));k=w.asin(((i-B)/d).toFixed(7));x=ak)x-=l*2;if(!g&&k>x)k-=l*2}l=k-x;if(w.abs(l)>n){q=k;l=h;L=i;k=x+n*(g&&k>x?1:-1);h=e+c*w.cos(k);i=B+d*w.sin(k);q=Qa(h,i,c,d,f,0,g,l,L,[k,q,e,B])}l=k-x;f=w.cos(x);e=w.sin(x);g=w.cos(k);k=w.sin(k);l=w.tan(l/4);c=4/3*c*l;l=4/3*d*l;d=[a,b];a=[a+c*e,b-l*f];b=[h+c*k,i-l*g];h=[h,i];a[0]=2*d[0]-a[0];a[1]=2*d[1]-a[1];if(j)return[a,b,h][M](q);else{q=[a,b,h][M](q)[Q]()[H](","); -j=[];h=0;for(i=q[o];h1000000000000&&(n=0.5);w.abs(i)>1000000000000&&(i=0.5);if(n>0&&n<1){n=la(a,b,c,d,f,e,g,h,n);q[E](n.x);r[E](n.y)}if(i> -0&&i<1){n=la(a,b,c,d,f,e,g,h,i);q[E](n.x);r[E](n.y)}i=e-2*d+b-(h-2*e+d);j=2*(d-b)-2*(e-d);l=b-d;n=(-j+w.sqrt(j*j-4*i*l))/2/i;i=(-j-w.sqrt(j*j-4*i*l))/2/i;w.abs(n)>1000000000000&&(n=0.5);w.abs(i)>1000000000000&&(i=0.5);if(n>0&&n<1){n=la(a,b,c,d,f,e,g,h,n);q[E](n.x);r[E](n.y)}if(i>0&&i<1){n=la(a,b,c,d,f,e,g,h,i);q[E](n.x);r[E](n.y)}return{min:{x:$[K](0,q),y:$[K](0,r)},max:{x:Y[K](0,q),y:Y[K](0,r)}}}),ua=T(function(a,b){var c=ka(a),d=b&&ka(b);a={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null};b={x:0,y:0, -bx:0,by:0,X:0,Y:0,qx:null,qy:null};function f(q,k){var t;if(!q)return["C",k.x,k.y,k.x,k.y,k.x,k.y];!(q[0]in{T:1,Q:1})&&(k.qx=k.qy=null);switch(q[0]){case "M":k.X=q[1];k.Y=q[2];break;case "A":q=["C"][M](Qa[K](0,[k.x,k.y][M](q.slice(1))));break;case "S":t=k.x+(k.x-(k.bx||k.x));k=k.y+(k.y-(k.by||k.y));q=["C",t,k][M](q.slice(1));break;case "T":k.qx=k.x+(k.x-(k.qx||k.x));k.qy=k.y+(k.y-(k.qy||k.y));q=["C"][M](Pa(k.x,k.y,k.qx,k.qy,q[1],q[2]));break;case "Q":k.qx=q[1];k.qy=q[2];q=["C"][M](Pa(k.x,k.y,q[1], -q[2],q[3],q[4]));break;case "L":q=["C"][M](wa(k.x,k.y,q[1],q[2]));break;case "H":q=["C"][M](wa(k.x,k.y,q[1],k.y));break;case "V":q=["C"][M](wa(k.x,k.y,k.x,q[1]));break;case "Z":q=["C"][M](wa(k.x,k.y,k.X,k.Y));break}return q}function e(q,k){if(q[k][o]>7){q[k].shift();for(var t=q[k];t[o];)q.splice(k++,0,["C"][M](t.splice(0,6)));q.splice(k,1);i=Y(c[o],d&&d[o]||0)}}function g(q,k,t,L,B){if(q&&k&&q[B][0]=="M"&&k[B][0]!="M"){k.splice(B,0,["M",L.x,L.y]);t.bx=0;t.by=0;t.x=q[B][1];t.y=q[B][2];i=Y(c[o],d&& -d[o]||0)}}for(var h=0,i=Y(c[o],d&&d[o]||0);h0.5)*2-1;D(f-0.5,2)+D(e-0.5,2)>0.25&&(e=w.sqrt(0.25-D(f-0.5,2))*l+0.5)&&e!=0.5&&(e=e.toFixed(5)-1.0E-5*l)}return s});b=b[H](/\s*\-\s*/);if(d=="linear"){var h=b.shift();h=-A(h);if(isNaN(h))return null;h=[0,0,w.cos(h*w.PI/180),w.sin(h*w.PI/180)];var i=1/(Y(w.abs(h[2]),w.abs(h[3]))||1);h[2]*=i;h[3]*=i;if(h[2]<0){h[0]=-h[2];h[2]=0}if(h[3]<0){h[1]=-h[3];h[3]=0}}b=Ra(b);if(!b)return null; -i=a.getAttribute(aa);(i=i.match(/^url\(#(.*)\)$/))&&c.defs.removeChild(C.getElementById(i[1]));i=v(d+"Gradient");i.id="r"+(m._id++)[N](36);v(i,d=="radial"?{fx:f,fy:e}:{x1:h[0],y1:h[1],x2:h[2],y2:h[3]});c.defs[y](i);c=0;for(h=b[o];cb.height&&(b.height=e.y+e.height-b.y);e.x+e.width-b.x>b.width&&(b.width=e.x+e.width-b.x)}}a&&this.hide();return b};u[p].attr=function(a,b){if(this.removed)return this;if(a==null){a={};for(var c in this.attrs)if(this.attrs[z](c))a[c]=this.attrs[c];this._.rt.deg&&(a.rotation=this.rotate());(this._.sx!=1||this._.sy!= -1)&&(a.scale=this.scale());a.gradient&&a.fill=="none"&&(a.fill=a.gradient)&&delete a.gradient;return a}if(b==null&&m.is(a,ea)){if(a=="translation")return ya.call(this);if(a=="rotation")return this.rotate();if(a=="scale")return this.scale();if(a==aa&&this.attrs.fill=="none"&&this.attrs.gradient)return this.attrs.gradient;return this.attrs[a]}if(b==null&&m.is(a,U)){b={};c=0;for(var d=a.length;c1&&(a=1);f.opacity=a}b.fill&&(f.on=true);if(f.on==null||b.fill=="none")f.on=false;if(f.on&&b.fill)if(a=b.fill.match(Na)){f.src=a[1];f.type="tile"}else{f.color=m.getRGB(b.fill).hex;f.src= -s;f.type="solid";if(m.getRGB(b.fill).error&&(g.type in{circle:1,ellipse:1}||(b.fill+s).charAt()!="r")&&ma(g,b.fill)){d.fill="none";d.gradient=b.fill}}e&&c[y](f);f=c.getElementsByTagName("stroke")&&c.getElementsByTagName("stroke")[0];e=false;!f&&(e=f=R("stroke"));if(b.stroke&&b.stroke!="none"||b["stroke-width"]||b["stroke-opacity"]!=null||b["stroke-dasharray"]||b["stroke-miterlimit"]||b["stroke-linejoin"]||b["stroke-linecap"])f.on=true;(b.stroke=="none"||f.on==null||b.stroke==0||b["stroke-width"]== -0)&&(f.on=false);a=m.getRGB(b.stroke);f.on&&b.stroke&&(f.color=a.hex);a=((+d["stroke-opacity"]+1||2)-1)*((+d.opacity+1||2)-1)*((+a.o+1||2)-1);h=(A(b["stroke-width"])||1)*0.75;a<0&&(a=0);a>1&&(a=1);b["stroke-width"]==null&&(h=d["stroke-width"]);b["stroke-width"]&&(f.weight=h);h&&h<1&&(a*=h)&&(f.weight=1);f.opacity=a;b["stroke-linejoin"]&&(f.joinstyle=b["stroke-linejoin"]||"miter");f.miterlimit=b["stroke-miterlimit"]||8;b["stroke-linecap"]&&(f.endcap=b["stroke-linecap"]=="butt"?"flat":b["stroke-linecap"]== -"square"?"square":"round");if(b["stroke-dasharray"]){a={"-":"shortdash",".":"shortdot","-.":"shortdashdot","-..":"shortdashdotdot",". ":"dot","- ":"dash","--":"longdash","- .":"dashdot","--.":"longdashdot","--..":"longdashdotdot"};f.dashstyle=a[z](b["stroke-dasharray"])?a[b["stroke-dasharray"]]:s}e&&c[y](f)}if(g.type=="text"){f=g.paper.span.style;d.font&&(f.font=d.font);d["font-family"]&&(f.fontFamily=d["font-family"]);d["font-size"]&&(f.fontSize=d["font-size"]);d["font-weight"]&&(f.fontWeight=d["font-weight"]); -d["font-style"]&&(f.fontStyle=d["font-style"]);g.node.string&&(g.paper.span.innerHTML=(g.node.string+s)[I](/"));g.W=d.w=g.paper.span.offsetWidth;g.H=d.h=g.paper.span.offsetHeight;g.X=d.x;g.Y=d.y+F(g.H/2);switch(d["text-anchor"]){case "start":g.node.style["v-text-align"]="left";g.bbx=F(g.W/2);break;case "end":g.node.style["v-text-align"]="right";g.bbx=-F(g.W/2);break;default:g.node.style["v-text-align"]="center";break}}};ma=function(a,b){a.attrs=a.attrs|| -{};var c="linear",d=".5 .5";a.attrs.gradient=b;b=(b+s)[I](Ya,function(i,j,l){c="radial";if(j&&l){j=A(j);l=A(l);D(j-0.5,2)+D(l-0.5,2)>0.25&&(l=w.sqrt(0.25-D(j-0.5,2))*((l>0.5)*2-1)+0.5);d=j+P+l}return s});b=b[H](/\s*\-\s*/);if(c=="linear"){var f=b.shift();f=-A(f);if(isNaN(f))return null}var e=Ra(b);if(!e)return null;a=a.shape||a.node;b=a.getElementsByTagName(aa)[0]||R(aa);!b.parentNode&&a.appendChild(b);if(e[o]){b.on=true;b.method="none";b.color=e[0].color;b.color2=e[e[o]-1].color;a=[];for(var g=0, -h=e[o];g')}}catch(Kb){R=function(a){return C.createElement("<"+a+' xmlns="urn:schemas-microsoft.com:vml" class="rvml">')}}Aa=function(){var a=Sa[K](0,arguments),b=a.container,c=a.height,d=a.width,f=a.x;a=a.y;if(!b)throw new Error("VML container not found.");var e=new G,g=e.canvas=C.createElement("div"),h=g.style;f=f||0;a=a||0;d=d||512; -c=c||342;d==+d&&(d+="px");c==+c&&(c+="px");e.width=1000;e.height=1000;e.coordsize=ja*1000+P+ja*1000;e.coordorigin="0 0";e.span=C.createElement("span");e.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";g[y](e.span);h.cssText=m.format("width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden",d,c);if(b==1){C.body[y](g);h.left=f+"px";h.top=a+"px";h.position="absolute"}else b.firstChild?b.insertBefore(g, -b.firstChild):b[y](g);Fa.call(e,e,m.fn);return e};G[p].clear=function(){this.canvas.innerHTML=s;this.span=C.createElement("span");this.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";this.canvas[y](this.span);this.bottom=this.top=null};G[p].remove=function(){this.canvas.parentNode.removeChild(this.canvas);for(var a in this)this[a]=Xa(a);return true}}G[p].safari=/^Apple|^Google/.test(X.navigator.vendor)&&(!(X.navigator.userAgent.indexOf("Version/4.0")+ -1)||X.navigator.platform.slice(0,2)=="iP")?function(){var a=this.rect(-99,-99,this.width+99,this.height+99);X.setTimeout(function(){a.remove()})}:function(){};function Db(){this.returnValue=false}function Eb(){return this.originalEvent.preventDefault()}function Fb(){this.cancelBubble=true}function Gb(){return this.originalEvent.stopPropagation()}var Hb=function(){if(C.addEventListener)return function(a,b,c,d){var f=Ba&&Ca[b]?Ca[b]:b;function e(g){if(Ba&&Ca[z](b))for(var h=0,i=g.targetTouches&&g.targetTouches.length;h< -i;h++)if(g.targetTouches[h].target==a){i=g;g=g.targetTouches[h];g.originalEvent=i;g.preventDefault=Eb;g.stopPropagation=Gb;break}return c.call(d,g)}a.addEventListener(f,e,false);return function(){a.removeEventListener(f,e,false);return true}};else if(C.attachEvent)return function(a,b,c,d){function f(g){g=g||X.event;g.preventDefault=g.preventDefault||Db;g.stopPropagation=g.stopPropagation||Fb;return c.call(d,g)}a.attachEvent("on"+b,f);function e(){a.detachEvent("on"+b,f);return true}return e}}();for(ha= -Ma[o];ha--;)(function(a){m[a]=u[p][a]=function(b){if(m.is(b,"function")){this.events=this.events||[];this.events.push({name:a,f:b,unbind:Hb(this.shape||this.node||C,a,b,this)})}return this};m["un"+a]=u[p]["un"+a]=function(b){for(var c=this.events,d=c[o];d--;)if(c[d].name==a&&c[d].f==b){c[d].unbind();c.splice(d,1);!c.length&&delete this.events;return this}return this}})(Ma[ha]);u[p].hover=function(a,b){return this.mouseover(a).mouseout(b)};u[p].unhover=function(a,b){return this.unmouseover(a).unmouseout(b)}; -u[p].drag=function(a,b,c){this._drag={};var d=this.mousedown(function(g){(g.originalEvent?g.originalEvent:g).preventDefault();this._drag.x=g.clientX;this._drag.y=g.clientY;this._drag.id=g.identifier;b&&b.call(this,g.clientX,g.clientY);Raphael.mousemove(f).mouseup(e)});function f(g){var h=g.clientX,i=g.clientY;if(Ba)for(var j=g.touches.length,l;j--;){l=g.touches[j];if(l.identifier==d._drag.id){h=l.clientX;i=l.clientY;(g.originalEvent?g.originalEvent:g).preventDefault();break}}else g.preventDefault(); -a&&a.call(d,h-d._drag.x,i-d._drag.y,h,i)}function e(){d._drag={};Raphael.unmousemove(f).unmouseup(e);c&&c.call(d)}return this};G[p].circle=function(a,b,c){return ab(this,a||0,b||0,c||0)};G[p].rect=function(a,b,c,d,f){return bb(this,a||0,b||0,c||0,d||0,f||0)};G[p].ellipse=function(a,b,c,d){return cb(this,a||0,b||0,c||0,d||0)};G[p].path=function(a){a&&!m.is(a,ea)&&!m.is(a[0],U)&&(a+=s);return Za(m.format[K](m,arguments),this)};G[p].image=function(a,b,c,d,f){return db(this,a||"about:blank",b||0,c||0, -d||0,f||0)};G[p].text=function(a,b,c){return eb(this,a||0,b||0,c||s)};G[p].set=function(a){arguments[o]>1&&(a=Array[p].splice.call(arguments,0,arguments[o]));return new Z(a)};G[p].setSize=fb;G[p].top=G[p].bottom=null;G[p].raphael=m;function ib(){return this.x+P+this.y}u[p].resetScale=function(){if(this.removed)return this;this._.sx=1;this._.sy=1;this.attrs.scale="1 1"};u[p].scale=function(a,b,c,d){if(this.removed)return this;if(a==null&&b==null)return{x:this._.sx,y:this._.sy,toString:ib};b=b||a;!+b&& -(b=a);var f,e,g=this.attrs;if(a!=0){var h=this.getBBox(),i=h.x+h.width/2,j=h.y+h.height/2;f=a/this._.sx;e=b/this._.sy;c=+c||c==0?c:i;d=+d||d==0?d:j;h=~~(a/w.abs(a));var l=~~(b/w.abs(b)),n=this.node.style,r=c+(i-c)*f;j=d+(j-d)*e;switch(this.type){case "rect":case "image":var q=g.width*h*f,k=g.height*l*e;this.attr({height:k,r:g.r*$(h*f,l*e),width:q,x:r-q/2,y:j-k/2});break;case "circle":case "ellipse":this.attr({rx:g.rx*h*f,ry:g.ry*l*e,r:g.r*$(h*f,l*e),cx:r,cy:j});break;case "text":this.attr({x:r,y:j}); -break;case "path":i=Oa(g.path);for(var t=true,L=0,B=i[o];L=i)return r;l=r}});function Ha(a,b){return function(c,d,f){c=ua(c); -for(var e,g,h,i,j="",l={},n=0,r=0,q=c.length;rd){if(b&&!l.start){e=jb(e,g,h[1],h[2],h[3],h[4],h[5],h[6],d-n);j+=["C",e.start.x,e.start.y,e.m.x,e.m.y,e.x,e.y];if(f)return j;l.start=j;j=["M",e.x,e.y+"C",e.n.x,e.n.y,e.end.x,e.end.y,h[5],h[6]][Q]();n+=i;e=+h[5];g=+h[6];continue}if(!a&&!b){e=jb(e,g,h[1],h[2],h[3],h[4],h[5],h[6],d-n);return{x:e.x,y:e.y,alpha:e.alpha}}}n+=i;e=+h[5];g=+h[6]}j+=h}l.end=j;e=a?n: -b?l:m.findDotsAtSegment(e,g,h[1],h[2],h[3],h[4],h[5],h[6],1);e.alpha&&(e={x:e.x,y:e.y,alpha:e.alpha});return e}}var Ib=T(function(a,b,c,d,f,e,g,h){for(var i={x:0,y:0},j=0,l=0;l<1.01;l+=0.01){var n=la(a,b,c,d,f,e,g,h,l);l&&(j+=D(D(i.x-n.x,2)+D(i.y-n.y,2),0.5));i=n}return j}),kb=Ha(1),za=Ha(),Ia=Ha(0,1);u[p].getTotalLength=function(){if(this.type=="path"){if(this.node.getTotalLength)return this.node.getTotalLength();return kb(this.attrs.path)}};u[p].getPointAtLength=function(a){if(this.type=="path")return za(this.attrs.path, -a)};u[p].getSubpath=function(a,b){if(this.type=="path"){if(w.abs(this.getTotalLength()-b)<1.0E-6)return Ia(this.attrs.path,a).end;b=Ia(this.attrs.path,b,1);return a?Ia(b,a).end:b}};m.easing_formulas={linear:function(a){return a},"<":function(a){return D(a,3)},">":function(a){return D(a-1,3)+1},"<>":function(a){a*=2;if(a<1)return D(a,3)/2;a-=2;return(D(a,3)+2)/2},backIn:function(a){var b=1.70158;return a*a*((b+1)*a-b)},backOut:function(a){a-=1;var b=1.70158;return a*a*((b+1)*a+b)+1},elastic:function(a){if(a== -0||a==1)return a;var b=0.3,c=b/4;return D(2,-10*a)*w.sin((a-c)*2*w.PI/b)+1},bounce:function(a){var b=7.5625,c=2.75;if(a<1/c)a=b*a*a;else if(a<2/c){a-=1.5/c;a=b*a*a+0.75}else if(a<2.5/c){a-=2.25/c;a=b*a*a+0.9375}else{a-=2.625/c;a=b*a*a+0.984375}return a}};var S={length:0};function lb(){var a=+new Date;for(var b in S)if(b!="length"&&S[z](b)){var c=S[b];if(c.stop||c.el.removed){delete S[b];S[o]--}else{var d=a-c.start,f=c.ms,e=c.easing,g=c.from,h=c.diff,i=c.to,j=c.t,l=c.prev||0,n=c.el,r=c.callback,q= -{},k;if(d p:first-child{ - margin-top:0; -} -#facebox .content > p:last-child{ - margin-bottom:0; -} - -#facebox .close{ - position:absolute; - top:5px; - right:5px; - padding:2px; - background:#fff; -} -#facebox .close img{ - opacity:0.3; -} -#facebox .close:hover img{ - opacity:1.0; -} - -#facebox .loading { - text-align: center; -} - -#facebox .image { - text-align: center; -} - -#facebox img { - border: 0; - margin: 0; -} - -#facebox_overlay { - position: fixed; - top: 0px; - left: 0px; - height:100%; - width:100%; -} - -.facebox_hide { - z-index:-100; -} - -.facebox_overlayBG { - background-color: #000; - z-index: 99; -} -.facebox-footnote{ - margin-top:40px; -} \ No newline at end of file diff --git a/TryRuby/public/stylesheets/reset.css b/TryRuby/public/stylesheets/reset.css deleted file mode 100644 index d709810..0000000 --- a/TryRuby/public/stylesheets/reset.css +++ /dev/null @@ -1,46 +0,0 @@ -html, body, div, span, applet, object, iframe, -h1, h2, h3, h4, h5, h6, p, blockquote, pre, -a, abbr, acronym, address, big, cite, code, -del, dfn, em, font, img, ins, kbd, q, s, samp, -small, strike, strong, sub, sup, tt, var, -dl, dt, dd, ol, ul, li, -fieldset, form, label, legend, -table, caption, tbody, tfoot, thead, tr, th, td { - margin: 0; - padding: 0; - border: 0; - outline: 0; - font-weight: inherit; - font-style: inherit; - font-size: 100%; - font-family: inherit; - vertical-align: baseline; -} -/* remember to define focus styles! */ -:focus { - outline: 0; -} -body { - line-height: 1; - color: black; - background: white; -} -ol, ul { - list-style: none; -} -/* tables still need 'cellspacing="0"' in the markup */ -table { - border-collapse: separate; - border-spacing: 0; -} -caption, th, td { - text-align: left; - font-weight: normal; -} -blockquote:before, blockquote:after, -q:before, q:after { - content: ""; -} -blockquote, q { - quotes: "" ""; -} diff --git a/TryRuby/public/stylesheets/scaffold.css b/TryRuby/public/stylesheets/scaffold.css deleted file mode 100644 index 1ae7000..0000000 --- a/TryRuby/public/stylesheets/scaffold.css +++ /dev/null @@ -1,56 +0,0 @@ -body { background-color: #fff; color: #333; } - -body, p, ol, ul, td { - font-family: verdana, arial, helvetica, sans-serif; - font-size: 13px; - line-height: 18px; -} - -pre { - background-color: #eee; - padding: 10px; - font-size: 11px; -} - -a { color: #000; } -a:visited { color: #666; } -a:hover { color: #fff; background-color:#000; } - -div.field, div.actions { - margin-bottom: 10px; -} - -#notice { - color: green; -} - -.field_with_errors { - padding: 2px; - background-color: red; - display: table; -} - -#error_explanation { - width: 450px; - border: 2px solid red; - padding: 7px; - padding-bottom: 0; - margin-bottom: 20px; - background-color: #f0f0f0; -} - -#error_explanation h2 { - text-align: left; - font-weight: bold; - padding: 5px 5px 5px 15px; - font-size: 12px; - margin: -7px; - margin-bottom: 0px; - background-color: #c00; - color: #fff; -} - -#error_explanation ul li { - font-size: 12px; - list-style: square; -} diff --git a/TryRuby/public/tutorials/es_intro.html b/TryRuby/public/tutorials/es_intro.html deleted file mode 100644 index 256de2f..0000000 --- a/TryRuby/public/tutorials/es_intro.html +++ /dev/null @@ -1,666 +0,0 @@ - -
            -

            Usando El Prompt

            -

            La ventana azul de arriba es el prompt de Ruby. ¡Escribe una línea de código Ruby, aprieta Enter - y velo correr!

            -

            Por ejemplo, trata de escribir algo matemático. Como: 2 + 6

            -
            \d+
            -
            -
            -

            Números & Matemática

            -

            ¡Bien! Hiciste algo de matemática. ¿Ves como la respuesta salta a la vista?

            -

            Ruby reconoce números y símbolos matemáticos. Puedes probar otras cosas como:

            -
            • 4 * 10
            • -
            • 5 - 12
            • -
            • 40 / 4
            -

            Seguro, las computadoras son habilidosas y rápidas con las matemáticas. Sigamos... ¿Quieres ver tu nombre al revés? - Escribe tu primer nombre entre comillas así: "Jimmy"

            -
            "(\w+)"
            -
            -
            -

            Decir Tu Nombre Al Revés

            -

            Perfecto, has formado un string de las letras de tu nombre. Un string - es un juego de caracteres que la computadora puede procesar.

            -

            Imagina que las letras están en una cuerda donde - se cuelga la ropa y las comillas son los broches que sostienen los bordes. Las comillas marcan el comienzo y el final.

            -

            Para invertir tu nombre, escribe: "Jimmy".reverse (¡No olvides el punto!)

            -
            "(\w+)"
            -
            -
            -

            Contando Las Letras

            -

            ¡Has usado el método reverse sobre tu nombre! Poniendo tu nombre entre comillas, - hiciste un string. Luego llamaste al método reverse, que funciona sobre un string cambiando - todas las letras de atrás para adelante.

            -

            Ahora, vamos a ver cuantas letras tiene tu nombre: "Jimmy".length

            -
            \d+
            -
            -
            -

            Repitiendo

            -

            Ahora, estoy seguro que te estarás preguntando para que sirve todo esto. Bueno, estoy seguro que habrás estado en alguna - pagina web donde te gritaron, ¡Hey, tu password es muy corto! Ves, algunos programas - usan este código tan simple.

            -

            Mira esto. Vamos a multiplicar tu nombre por 5. "Jimmy" * 5

            -
            "(\w+)"
            -
            -
            -

            Hey, Sumario #1 Listo

            -

            Vamos a ver que es lo que has aprendido en el primer minuto.

            -
              -
            • El prompt. Escribiendo código en el prompt verde obtienes - una respuesta del prompt rojo. Todo código te da una respuesta.
            • -
            • Números y strings son objetos matemáticos y de texto de Ruby.
            • -
            • Métodos Has usado métodos en Ingles como reverse - y métodos simbólicos como * (el método de multiplicación.) ¡Los métodos son acciones!
            • -
            -

            Esta es la esencia del aprendizaje. Tomar cosas simples, jugar con ellas - y trasformarlas en cosas nuevas. ¿Te sientes cómodo con todo? Te aseguro que lo estas.

            -

            Bien, vamos a hacer algo incomodo. Trata de invertir un número: 40.reverse

            -
            NoMethodError: undefined method `reverse' for (\d+):Fixnum
            -
            -
            -

            ¡Basta, Te Volviste Loco!

            -

            No puedes invertir el numero cuarenta. Supongo que puedes poner tu monitor en - frente de un espejo, pero invertir un numero no tiene sentido. Ruby lanza un - mensaje de error. Ruby te dice que no hay un método reverse para los números.

            -

            Tal vez si lo conviertes en un string: 40.to_s.reverse.

            -
            \"(\d+)\"
            -
            -
            -

            Los Chicos Son Diferentes De Las Chicas

            -

            Y los números son diferentes de los strings. Aunque puedes usar métodos en cualquier objeto - en Ruby, algunos métodos solo funcionan en cierto tipo de cosas. Pero siempre puedes - convertir entre diferentes tipos usando el método "to" de Ruby.

            -
            • to_s convierte cosas a strings.
            • -
            • to_i convierte cosas a integers (números.)
            • -
            • to_a convierte cosas a arrays.
            • -
            -

            ¿Que son los arrays?! Son listas. Escribe entre un par de corchetes: [].

            -
            \[\]
            -
            -
            -

            Mantenerse en Cola

            -

            Genial, eso es una lista vacía. Las listas guardan cosas en orden. - Como esperando en la cola para palomitas de maíz. Estas atrás de alguien y jamás - pensarías en empujarlo a un costado, ¿no es así? Y con respecto al tipo detrás de ti, - mantienes un ojo sobre el, ¿correcto?

            -

            Acá hay una lista para ti. Números de la lotería: [12, 47, 35].

            -
            \[(\d+(, )?){2,}\]
            -
            -
            -

            Uno Levanta La Mano

            -

            Una lista de números de la lotería. ¿Cual es el mayor?

            -

            Prueba: [12, 47, 35].max.

            -
            (\d+)
            -
            -
            -

            Manteniendo la Lista

            -

            Bien, bien. Pero es un fastidio el tener que reescribir esa lista, ¿no es así?

            -

            Guardemos nuestros números en un ticket de esta manera: ticket = [12, 47, 35]

            -
            \[(\d+(, )?){2,}\]
            -
            -
            -

            Ahora Escribe Ticket

            -

            Ahora, escribe: ticket

            -
            \[(\d+(, )?){2,}\]
            -
            -
            -

            Guardado, Escondido

            -

            ¡Fantástico! Te has aferrado a tus números de la lotería, escondiéndolos dentro de una - variable llamada ticket.

            -

            Vamos a poner tus números en orden, que te parece? Usa: ticket.sort!

            -
            \[(\d+(, )?){2,}\]
            -
            -
            -

            Sumario #2 Está Sobre Nosotros

            -

            Tenías una lista. Ordenaste la lista. La variable ticket ahora esta cambiada.

            -

            ¿Te diste cuenta que el método sort! tiene un claro y llamativo signo de exclamación al final? - Muchas veces los métodos de Ruby gritan así si es que alteran la variable para bien. No es nada - especial, solo una marca.

            -

            Ahora, mira como te fue en tu segundo minuto:

            -
              -
            • Errors. Si tratas de invertir un número o hacer algo sospechoso, - Ruby salteara el prompt para avisarte.
            • -
            • Arrays son listas para ordenar cosas en orden.
            • -
            • Variables guardan cosas y le dan un nombre. Usaste el - signo igual para hacerlo.
              Like: ticket = [14, 37, 18].
            • -
            -

            En total hay ocho lecciones. Estás a dos octavos de camino! - Esto es cosa simple, no te parece? Las cosas buenas están mas adelante.

            -

            Cambiemos de dirección por un momento. Rellené con un poco de poesía cierta - variable para ti. Hecha un vistazo. Escribe print poem

            -
            poem = "My toast has flown from my hand\nAnd my toast has gone to the -moon.\nBut when I saw it on television,\nPlanting our flag on Halley's -comet,\nMore still did I want to eat it.\n"
            -
            My toast (.+)
            -
            -
            -

            Desgraciadamente, Tú Odias la poesía de Tostadas

            -

            Mira, esta bien. No tiene que gustarte. Hackéalo, yo invito.

            -

            En vez de tostada, ve por un melón o algo. Prueba esto: poem['toast'] = 'honeydew'

            -

            Y luego escribe print poem para ver el nuevo poema.

            -
            My honey(.+)
            -
            -
            -

            Listo, Apuntado

            -

            Los corchetes que acabas de usar son muy comunes en Ruby. Recuerda, escribiste: poem['toast'] = 'honeydew'. Esa casilla con la palabra toast tiene corchetes a ambos lados, ¿ves?

            -

            Los -corchetes son como una mira para alinear un objetivo. Exacto. Estos -corchetes significan, "Estoy buscando ____." Listo, apuntado. Aquí estas buscando -una costada e intercambiándola por una fruta.

            -

            Aquí hay una pregunta: ¿Que pasa si volteamos el poema entero? poem.reverse -

            "\\n.ti tae ot (.+)"
            -
            -
            -

            Demasiado Invertido

            -

            Está bien, seguro. Entonces todo el poema fue puesto al revés. Letra por letra. Sin embargo, yo realmente solo quería - invertir las líneas. Mover la última línea a la primera y la primera hacia abajo a la ultima. Al revés, pero no - ése revés.

            -

            Aquí esta como lograrlo: poem.lines.to_a.reverse

            -
            \["More still did I(.+)"\]
            -
            -
            -

            Rizos de Metodos Concatenados

            -

            Dime, que es lo que ves? Que paso acá? Escribiste poem.lines.to_a.reverse y ¿que pasó?

            -

            Dos cosas pasaron. Convertiste poem en una lista usando -lines.to_a. lines decide la forma en que -el string se divide, luego to_a lo -convierte en un Array. (To array.) Diferentes métodos, como -bytes y chars pueden ser usadas en lugar de -lines. Usando lines, Ruby retornará cada línea de poem.

            -

            Luego, tu revertiste, reversed, esa lista. Tenías cada línea. Las revertiste. Eso es todo.

            -

            Vamos a hilar un método más al final de todo esto: print poem.lines.to_a.reverse.join -

            More still did I(.+)
            -
            -
            -

            De Todos los Sumarios, el #3 esta aquí

            -

            Buen espectáculo, mi amigo! El método join toma la lista de líneas revertidas y las pone juntas en un string. - (Seguro, también podrías haber usado to_s.)

            -

            Tiempo de Revisión.

            -
              -
            • Exclamaciones. Métodos pueden tener signos de exclamación (y también de interrogación) en - sus nombres. No es la gran cosa. Prueba: poem.include? "my hand"
            • -
            • Corchetes. Establece objetivos y busca cosas. Busca y reemplaza.
            • -
            • Concatenar métodos te permite hacer mas cosas juntas. Partir poem, revertirlo, - reensamblarlo: poem.lines.to_a.reverse.join
            • -
            -

            En este punto, querras manosear un poco más el poema. Una lista completa de métodos - String estan - - acá. - No temas y prueba algunos (como poem.downcase o poem.delete.)

            -

            Cuando estés listo para seguir adelante, escribe: books = {}

            -
            \{\}
            -
            -
            -

            Un Pequeñín Libro en Blanco

            -

            Has hecho un hash vacío. (también conocido como: un diccionario vacío.)

            -

            Vamos a rellenar con un libro de críticas en miniatura. Acá esta nuestro sistema de calificación:

            -
              -
            • :splendid → una obra maestra.
            • -
            • :quite_good → disfrutable, por supuesto que sí.
            • -
            • :mediocre → partes iguales de bueno y malo.
            • -
            • :quite_not_good → notablemente malo.
            • -
            • :abyssmal → una perdida de tiempo.
            • -
            -

            Para calificar un libro, pon el título entre corchetes y la calificación luego del signo igual.

            -

            Por ejemplo: books["Gravity's Rainbow"] = :splendid

            -
            :\w+
            -
            -
            -

            Mas Críticas Tamaño Bocadillo

            -

            Tú sigue, agrega mas críticas. Y, si quieres ver toda la lista, - implemente escribe: books

            -

            De nuevo, las calificaciones son: :splendid, :quite_good, :mediocre, - :quite_not_good, and :abyssmal.

            -

            Estas calificaciones no son strings. Cuando colocas dos puntos frente a una palabra simple, obtienes un - symbol. Los símbolos son más baratos que los strings (en términos de memoria de la computadora.) Si usas - una palabra una y otra vez en un programa, usa un símbolo. En vez de tener miles de - copias de una palabra en memoria, la computadora guardara el símbolo solamente una vez.

            -

            Una vez que tengas tres o cuatro libros allí - dentro, escribe: books.length.

            -
            [3-9]
            -
            -
            -

            Espera, ¿Me gustó Gravity's Rainbow?

            -

            Ves, el método length funciona sobre strings, list y hashes. Una gran cosa acerca de - Ruby es que los nombres usualmente se reutilizan, lo que significa menos nombres para recordar.

            -

            Si quisieras ver una de tus críticas hechas, vuelve a poner el título entre corchetes. Pero deja de lado el - signo igual.

            -

            Al igual que aquí: books["Gravity's Rainbow"]

            -
            :\w+
            -
            -
            -

            Hashes como Pares

            -

            Ten en mente que los hashes no mantienen las cosas en orden. Ese no es su trabajo. Solo emparejará dos - cosas: una key (llave) y un valor. En tus críticas, la key es el - titulo del libro y el valor es la calificación.

            -

            Si simplemente quieres ver los títulos de los libros que calificaste: books.keys

            -
            \[".*"\]
            -
            -
            -

            ¿Eres Duro?

            -

            ¿Estás dando duras injustas críticas? Sigamos puntuando con rigurosidad:
            ratings = Hash.new {0}

            -

            Entonces, bien, ahora vamos a contar tus críticas. Trata de seguirme. Escribe:
            - books.values.each { |rate| ratings[rate] += 1 }

            -

            (La línea vertical es el signo de tubería, probablemente lo logres con AltGr+1 con tu teclado.)

            -
            \[:.+\]
            -
            -
            -

            Un Recuento

            -

            Genial, wow! Has hecho un recuento de tus calificaciones. Escribe ratings para ver las cuenta. Este nuevo - hash muestra las calificaciones y luego el numero de veces que has dado esa calificación.

            -

            Una de las asombrosas cosas nuevas que acabamos de usar es un bloque, block. Vamos a explorar - explore these more in the next summary. más esto en el próximo sumario. Pero, básicamente, un bloque es un pedazo de código Ruby - rodeado por llaves.

            -

            Probemos otro bloque: 5.times { print "Odelay!" }

            -
            Odelay!Od.*
            -
            -
            -

            Ahora Arribamos al Sumario #4

            -

            Los bloques están siempre apegados a métodos. Como el método times, que toma el bloque y lo corre - repetidas veces. (En este caso: cinco veces.)

            -

            Esta última lección fue algo mas larga. Probablemente usaste unos tres minutos aprendiendo sobre:

            -
              -
            • Hashes. El pequeño diccionario con páginas arrugadas: {}.
            • -
            • Symbols. Pequeñas, eficientes palabras con dos puntos: :splendid.
            • -
            • Blocks. Pedazos de código que pueden ser clavados a muchos métodos de Ruby. Aquí - esta el código que usaste para crear el recuento:
              books.values.each { |rate| ratings[rate] += 1 }.
            • -
            -

            En tu computadora, probablemente tienes muchos archivos diferentes. Archivos con fotos en ellos, - archivos con programas dentro. Y los archivos usualmente se organizan en carpetas, también llamadas: - directorios.

            -

            He preparado algunos directorios para ti. Echa un vistazo: - Dir.entries "/"

            -
            \["\.", .+\]
            -
            -
            -

            La Privada Colección de Dr. Dir

            -

            Acabas de listar todo lo existente en el directorio superior. El directorio raíz, indicado - por la barra en diagonal. Conteniendo algunos programas y otros tutoriales y semejantes.

            -

            Entonces, ¿que es el método Dir.entries? Bueno, es solo un método ¿si?, - entries es el método llamado sobre la variable Dir. - Y Dir tiene una colección de métodos para chequear los archivos de los directorios.

            -

            Otra pequeña cosa de la que no hemos hablado abiertamente. Argumentos de los métodos, resaltados en verde.

            -
              -
            • Dir.entries "/": Cualquier cosa listada luego de un método - es considerado acoplamiento.
            • -
            • print poem: Ves, print es un método ordinario. - Y el poema esta acoplado. Para ser impreso.
            • -
            • print "pre", "event", "ual", "ism" posee varios argumentos, - con comas entre ellos.
            • -
            -

            Para listar solamente archivos de texto en el directorio: Dir["/*.txt"]

            -
            \["\/comics\.txt"\]
            -
            -
            -

            Ven, Lee Historietas Conmigo

            -

            El método Dir[] hace como entries pero tu buscas por archivos - archivos con carácteres de comodín. ¡Aquí, vemos esos corchetes otra vez! Te das - cuenta como todavía significan, "Estoy buscando _____.".

            -

            Mas específicamente: "Estoy buscando archivos que terminen con .txt."

            -

            Abramos este archivo con historietas de una vez. Aquí esta la manera:
            - print File.read("/comics.txt")

            -
            Achewood.+
            -
            -
            -

            Mi Comicas, Tu Comicas

            -

            ¡De acuerdo! Podemos comenzar a usar archivos para guardar cosas. Esto es excelente - porque normalmente cuando salimos de Ruby, todas nuestras variables desaparecerán. - Ruby, por si mismo, olvida estas cosas. Pero si salvamos cosas en archivos, - podemos leer esos archivos en futuras escapadas a Ruby.

            -

            Hey, y ¿adivina que? ¡El directorio /Home es tuyo! ¡Te lo entrego a ti! ¡Soy generoso! Hagamos una copia del archivo de la historieta.

            -

            Querrás hacer lo siguiente: FileUtils.copy('/comics.txt', '/Home/comics.txt') -

            Si ya has creado el archivo, usa File.delete('/Home/comics.txt') para arrojarlo a la basura.

            -
            nil
            -
            -
            -

            Tu Propio Territorio

            -

            Ok, tienes una copia. Chequéala: Dir["/Home/*.txt"]

            -

            Para agregar tu propia historieta a la lista, abramos el archivo en modo append.

            -

            Empieza asi: File.open("/Home/comics.txt", "a") do |f|.

            -
            ..
            -
            -
            -

            Y Ahora, para la Sorprendente Conclusión

            -

            Asi que tu prompt ha cambiado. ¿Lo notas? Tu prompt es doble punto ahora.

            -

            En este tutorial, este prompt significa que Ruby espera que escribas más. A - medida que vayas completando con líneas de código, los doble puntos se mantendrán - hasta que hallas finalizado.

            -

            Hot tip: si quieres parar de trabajar en el código y salirte de los doble puntos, usa el comando reset. - Si quieres volver a la pagina previa del tutorial, usa el comando back.

            -

            Aquí esta tu código. Ya has escrito la primera línea, asi que simplemente ingresa la segunda. (El \n - es el carácter de Enter.

            -
            • File.open("/Home/comics.txt", "a") do |f|
            • -
            •   f << "Cat and Girl: http://catandgirl.com/\n"
            • -
            • end
            • -
            -

            Y, como te has vuelto avanzado y capaz aquí, otro tip: puedes usar las flechas hacia - arriba y hacia abajo para editar tus viejos comandos o correrlos otra vez.

            -
            ..
            -
            -
            -

            Ruby se Sienta y Espera

            -

            Esa ultima línea agrega la historieta Cat and Girl a la lista, pero Ruby seguirá esperando - hasta que hallas terminado por completo para tomar acción.

            -

            Ahora, para finalizar el código que has empezado. Empezaste un nuevo bloque cuando escribiste do. - Hasta ahora los bloques que hemos visto usaban llaves. Esta vez usaremos do y end en lugar - de las llaves. Muchos Rubyistas usan do...end cuando el bloque ocupa varias líneas.

            -

            Terminemos ese bloque ahora mismo, con: end

            -
            • File.open("/Home/comics.txt", "a") do |f|
            • -
            •   f << "Cat and Girl: http://catandgirl.com/\n"
            • -
            • end
            • -
            -
            #.File:/Home/comics\.txt \(closed\).
            -
            -
            -

            El Reloj Clavado en el Archivo

            -

            ¡Bien, bien! Has añadido esa historieta al archivo. Puedes verlo por ti mismo: print File.read("/Home/comics.txt")

            -

            ¿Qué hora era cuando cambiaste el archivo? Veamos. Escribe: File.mtime("/Home/comics.txt")

            -
            \w+ \w+ \d+ \d{2}:\d{2}:\d{2} [+-]\d{4} \d{4}
            -
            -
            -

            Sólo la Manecilla de la Hora

            -

            Estupendo, allí esta la hora. La hora exacta en la que agregaste la historieta al archivo. El mtime te devuelve un objeto Time de Ruby.

            -

            Si sólo quieres ver la hora que era, aprieta la flecha para arriba y cambia la línea a: File.mtime("/Home/comics.txt").hour

            -
            \d+
            -
            -
            -

            Hola, ¿Quién Anda Ahí? Y el Sumario #5 Agita su Sombrero!

            -

            Bien hecho, bien hecho, bien hecho, ¡bien hecho! Realmente, realmente, realmente, realmente, ¡reaaaaaaaaalllmente!

            -

            Aquí esta tu último minuto de tu vida en retrospectiva:

            -
              -
            • Archivos. ¿Que más se puede decir? Muchos métodos para editar archivos y revisar directorios.
            • -
            • Argumentos. Los argumentos son listas de cosas mandadas en un método. Separadas con comas.
            • -
            • También hablamos sobre do y end que es otra manera de hacer un bloque.
            • -
            -

            Ahora ya sabes como usar Ruby por completo. Me refiero a que tienes lo esencial. Solo necesitas seguir - aprendiendo métodos y probar bloques más complejos.

            -

            Pero existe un lado de Ruby que no hemos hablado. Hacer tus propios métodos y clases.

            -

            Ahem! Acabemos con ello de una vez.

            -

            Empieza con: def load_comics( path )

            -
            ..
            -
            -
            -

            En Ruby, Def Leppard Significa ¡Define Leppard (un Método)!

            -

            Hey, bueno, lo hiciste. Estas haciendo tu propio método. Comenzaste con def, seguido por el nombre del método. - Y una lista de argumentos que va a necesitar el método. ¡Esto no da tanto miedo ni es peligroso!

            -

            Todo lo que debemos hacer es rellenar con Ruby y terminarlo con end.

            -

            Aquí esta el código:

            -
            • def load_comics( path )
            • -
            •   comics = {}
            • -
            •   File.foreach(path) do |line|
            • -
            •     url, name = line.split(': ')
            • -
            •     comics[url] = name.strip
            • -
            •   end
            • -
            •   comics
            • -
            • end
            • -
            -

            No necesitas indentar, si no quieres. Lo hice solo para que sea más legible.

            -
            nil
            -
            -
            -

            La Madura Fruta de tu Propia Creación

            -

            Un nuevo método ha nacido. Vamos a usarlo: comics = load_comics('/comics.txt')

            -

            Si tienes un problema, puedes haberlo escrito mal. Usa el comando back y prueba otra vez.

            -
            \{.*"Achewood"=."http://achewood.com/".*\}
            -
            -
            -

            Hey, Cool, Una Cosa de Historietas

            -

            En tu ventana de Ruby arriba, mira el código que has escrito para el método load_comics. ¿Qué esta pasando? Tu estas - pasando en la variable path y estas recibiendo la variable comics. Ruby permite filtrar el hash comics - que es devuelto al final del método.

            -

            Una cantidad de métodos se usaron para realizar el trabajo. Fíjate si puedes hallarlos.

            -
            • File.foreach es el método que abre un archivo y manda cada línea al bloque. La variable line - dentro del bloque do...end va turnando con cada línea del archivo.
            • -
            • split es un método para strings, que rompe los string en colocándolo en un array. Un hacha es arrojada sobre las comas - y las líneas se cortan en dos, dándonos la url y el nombre, name, de las historietas.
            • -
            • strip remueve los espacios extra alrededor de name. Por si acaso.
            • -
            -

            Justo allí. Bravo. Tienes las historietas en un hash de Ruby. ¿Pero ahora qué? ¿Qué tan bueno es en verdad?

            -

            Hagamos una página de links. ¿Qué te parece? Vamos a necesitar una pequeña librería que hice para ti.

            -

            Escribe: require 'popup'

            -
            true
            -
            -
            -

            El Navegador de Títere

            -

            Excelente, has cargado la librería popup. Está guardada en un archivo en el directorio Libraries. Mira: Dir["/Libraries/*"]

            -

            La librería popup contiene un puñado de métodos que he escrito y te dejaran controlar ventanas emergentes aquí en Try Ruby.

            -

            Mira, prueba esto: Popup.goto "http://google.com/"

            -
            \033\[1;JSm.*popup_goto\(.*\)\033\[m.*
            -
            -
            -

            Haciendo Links e Hilando Redes

            -

            Nuestro propio adorable, pequeño popup para manipular. también puedes rellenarlo con tus cositas. Empecemos por algo pequeño:

            -
            • Popup.make {
            • -
            •   h1 "My Links"
            • -
            •   link "Go to Google", "http://google.com/"
            • -
            • }
            • -
            -

            El termino h1 (h-uno) significa encabezado de nivel uno. En HTML, es el encabezado más grande.

            -
            \033\[1;JSm.*popup_make\(.*h1.*a href.*\)\033\[m.*
            -
            -
            -

            Los Popups son tan fáciles, es una Locura

            -

            Se ve bien, lo hiciste perfecto, tal como se te pidió. Hagamos una lista entonces.

            -

            Aquí esta como haces una lista con la librería de popup:

            -
            • Popup.make do
            • -
            •   h1 "Things To Do"
            • -
            •   list do
            • -
            •     p "Try out Ruby"
            • -
            •     p "Ride a tiger"
            • -
            •     p "(down River Euphrates)"
            • -
            •   end
            • -
            • end
            • -
            -

            El método p es la manera corta para "párrafo".

            -
            \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*li.*\)\033\[m.*
            -
            -
            -

            Expandiendo las Historietas en la Tabla

            -

            Bien, esto esta yendo maravilloso. Esto es algo simple, pero mantén en mente que no sabias nada sobre Ruby hace quince minutos atrás!<

            -

            Ultimo paso. Vamos a juntar todo, ¿sabes? ¡Juntémoslo como esos juegos de - campanillas hermosas que tintinean en los pórticos bajo la hermosa luz del sol - en la playa!

            -

            Asegúrate de que las historietas están cargadas: comics = load_comics( '/comics.txt' )

            -

            Ahora, hagamos una lista de links para cada historieta:

            -
            • Popup.make do
            • -
            •   h1 "Comics on the Web"
            • -
            •   list do
            • -
            •     comics.each do |name, url|
            • -
            •       link name, url
            • -
            •     end
            • -
            •   end
            • -
            • end
            • -
            -

            Puedes clickear en los links y leer las historietas ¡inclusive en la ventana principal! ¡Bárbaro!

            -
            \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*a href.*li.*a href.*\)\033\[m.*
            -
            -
            -

            Sumario #6 lo que Significa que has Llegado Muy Lejos

            -

            Eres un clérigo nivel 6 de Ruby. Quiero decir que buen trabajo has hecho. Vamos a revisar:

            -
              -
            • Agregaste tu propio método con def y usaste ese método load_comics varias veces.
            • -
            • Librerias. Tú usaste el método require para cargar la librería popup.
              Escribiendo: require 'popup'
            • -
            • Y como si no fuera suficiente, hiciste tu propia página web para listar los archivos de historietas. ¡Hiciste un programa real!
            • -
            -

            Entonces ¿Qué podrá venir luego? ¿Qué deberías aprender posiblemente ahora? - Ja, esta es la mejor parte. Has recorrido un largo camino y ahora descubrirás - las clases. En dos lecciones mas y ya estarás hecho.

            -

            Tempranamente, creamos un hash como este: Hash.new pruébalo.

            -
            \{\}
            -
            -
            -

            No una Clase de Escuela, Una Clase Trabajadora

            -

            Ves, las llaves vacías {} son abreviaciones para Hash.new. El método new - es usado para hacer objetos de cierta clase. (Piensa "clase" como en "clase - trabajadora" — un grupo especifico de objetos similares, tienen el - mismo trabajo, la misma camisa.)

            -

            Pregúntate esto: ¿Cómo haría mi blog en Ruby? ¿Dónde deberías - comenzar? Bien, deberías guardar tus entradas del blog en un archivo, ¿cierto? - Pero ¿cómo seguirías los títulos de las entradas y el momento en que fue creado? - Y cuando cargas el archivo, ¿cómo se vería en Ruby? ¿Sería un Hash? ¿O un Array? ¿O - un Array de Arrys? ¿O alguna otra cosa?

            Yo realmente creo que querrás usar una clase. Ya estas familiarizado con varias clases: Hash, Array, String.

            -

            Hagamos una clase nueva: class BlogEntry.

            -
            ..
            -
            -
            -

            El Relleno del Blog esta Hecho de

            -

            Has abierto una nueva clase BlogEntry. ¿De que están hechas las entradas de tu blog? Un titulo, seguro. también, - la fecha en la que fue creada. El texto entero de la entrada.

            -

            Vamos a poner el estado de ánimo, también, tal como LiveJournal. La internet ha traído de vuelta las personas de palitos y emoticones - fuera de la bancarrota.¡Que emoción!

            -

            Bueno, ya tienes la primera línea de la clase, aquí esta el resto:/p> -

            • class BlogEntry
            • -
            •   attr_accessor :title, :time, :fulltext, :mood
            • -
            • end
            • -
            -
            nil
            -
            -
            -

            Accessors Son las Extremidades Colgantes

            -

            Hey, buena clase, colega. Tienes una nueva clase BlogEntry. Para comenzar una entrada:
            entry = BlogEntry.new.

            -

            En la definición de la clase, usaste un método llamado attr_accessor. Existen varios métodos attribute - atributo, como este que agregan pequeñas configuraciones a la clase. Estos atributos son simplemente variables adosadas a la clase.

            -

            Piénsalo de este modo. Una clase es como una persona. Esa forma de estrella - del humano. Y los atributos son las extremidades, las diferentes partes que - hacen un cuerpo.

            -

            Para crear el titulo de tu entrada: entry.title = "Today Mt. Hood Was Stolen!"

            -
            ".+"
            -
            -
            -

            Un Objeto, Ese Estupendo Paquete Pequeño

            -

            Sigue adelante y pon la hora: entry.time = Time.now

            -

            Y el estado de animo: entry.mood = :sick

            -

            Y el anuncio en si: entry.fulltext = "I can't believe Mt. Hood was stolen! I am speechless! It was stolen by a giraffe who drove away - in his Cadillac Seville very nonchalant!!"

            -

            Para ver toda la configuración, simplemente escribe en el prompt: entry.

            -
            #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
            -
            -
            -

            Agilizando

            -

            Genial, tu blog es impresionante. Hey, hagamos las cosas algo mas fácil. No querrás - poner la hora asi todas las veces que postees. Solo quieres escribir el titulo, - el contenido y el emoticon rápido, ¿verdad?

            -

            Vamos a agregar un método initialize.

            -
            • class BlogEntry
            • -
            •   def initialize( title, mood, fulltext )
            • -
            •     @time = Time.now
            • -
            •     @title, @mood, @fulltext = title, mood, fulltext
            • -
            •   end
            • -
            • end
            • -
            -

            Una vez que lo hallas escrito, prueba hacer una nueva entrada: BlogEntry.new

            -
            ArgumentError: wrong number of arguments \(0 for 3\).*
            -
            -
            -

            Tu le Has Enseñado al Blog a Rechazar lo Malo

            -

            ¿Viste como usamos dentro de la clase el símbolo arroba? De este modo: @time = Time.now

            -

            Fuera de la clase, usamos accesos (accessors): entry.time = Time.now Pero dentro variables de instancia: @time = Time.now - Son exactamente lo mismo, pero expresado en dos partes diferentes de tu programa.

            -

            tu blog ahora necesita un titulo, estado de ánimo y el post para funcionar. Cuando un nuevo BlogEntry es creado, el método initialize - es usado para chequear cualquier argumento para new. ¡Uh, necesitamos tres argumentos!

            -

            Prueba de nuevo con los tres.

            -

            entry2 -= BlogEntry.new( "I Left my Hoodie on the Mountain!", :confused, "I am -never going back to that mountain and I hope a giraffe steals it." )

            -
            #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
            -
            -
            -

            Una Jirafa No Ha Robado el Sumario #7

            -

            Aha, estas aquí. Y todo en una pieza. Todavía vamos a hacer tu blog realidad, pero hasta entonces, vamos a revisar, ¿bien?

            -
              -
            • Clases. Todo en Ruby es algún tipo de objeto. Las clases explican los objetos. Como ciertos objetos - trabajan. Por ejemplo, haces algunas entradas de blog y estos objetos están explicados en la clase BlogEntry. - En otras palabras: los llamas objetos del tipo BlogEntry.
            • -
            • Accessors son variables adosadas a un objeto que pueden ser usadas fuera del objeto. (entry.time = Time.now)
            • -
            • Variables de instancia son las mismas variables para accesos dentro del objeto. - Como en la definición de un método. (@time = Time.now)
            • -
            -

            Bueno, vamos a envolver las cosas, niño. Aquí esta el ultimo capitulo de la FASCINANTE épica - historia de Try Ruby! Ahora que ya has probado como todo funciona, ¿cómo vas a - usar eso alrededor de la casa y en tu tienda de comestibles? Eres una - gran persona (una de mis favoritas), pero necesitas dirección.

            -

            Vamos a terminar tu blog. Tienes entradas de blog, pero no un blog.

            -

            Pon las entradas en un array: blog = [entry, entry2]

            -
            \[#.BlogEntry:0x[0-9a-f]+.*, #.BlogEntry:0x[0-9a-f]+.*\]
            -
            -
            -

            Todo Se Trata de Combinar Cosas

            -

            Cosas hermosas pueden hacerse de partes simples de Ruby, especialmente - cuando las combinas entre ellas para formar algo nuevo. Aquí tenemos un blog - hecho de un array de clases. Y, en realidad, Ruby realmente hace buenas cosas - con este tipo de criaturas.

            -

            Aquí hay un puñado de cosas que puedes hacer con tu blog array:

            -
            • Querrás ordenar tus entradas de mas reciente a viejas. Puedes hacerlo con:
              - blog.sort_by { |entry| entry.time }.reverse
              Ve sort_by para más explicación.
            • -
            • Si quieres buscar en el blog por cualquier cosa relacionada con "cadillac":
              - blog.find_all { |entry| entry.fulltext.match(/cadillac/i) }
              - Lee mas en find_all - y match - para descubrir como funciona. También: /giraffe/i es un objeto Regexp, usado para concordar palabras.
            • -
            • Y agregar nuevas entradas con blog << new_entry
              - Y aquí la documentación del método <<.
            • -
            -

            Puedes buscar entre la lista de los métodos con los que viene Ruby en ruby-doc.org's core. - Otra buena lista hay en online pickaxe.

            -

            Un método realmente útil (probablemente yo uso esto mas que otra cosa) es map. Escribe: blog.map { |entry| entry.mood }

            -
            \[(:\w+, )+:\w+\]
            -
            -
            -

            Mira Su Cara — La Transformación Ha Comenzado

            -

            El método map recorre un array y reemplaza cada ítem con algo nuevo. ¿Dices que quieres reemplazar cada entrada de tu blog - con el nombre de Bruce Willis?. Hazlo entonces: blog.map { "Bruce Willis" }

            -

            Como el bloque siempre devuelve el string "Bruce Willis", eso es lo que obtienes. En el código que acabas de usar, la entrada entry wfue reemplazada - por solo el entry.mood.

            -

            Ahora, quiero que hagas un popup con las entradas de tu blog. Yo no te voy a - dar todo el código. Solo te voy a dar una parte.

            -
            • blog.each do |entry|
            • -
            •   h2 entry.title
            • -
            •   p entry.fulltext
            • -
            • end
            • -
            -

            Ahora, yo espero que pongas el código del popup alrededor y agregues un titulo con el nombre de tu blog usando h1. Como extra, tienes la hora de cada entrada para mostrar.

            -
            \033\[1;JSm.*popup_make\(.*h1.*h2.*li.*h2.*li.*\)\033\[m.*
            -
            -
            -

            Eres Una Especie de Gurú Web, Tengo Estrellas en Mis Ojos

            -

            Bien, ¡eso es! Este es exactamente el código que puedes usar para escribir tu - propio blog real en Ruby. Si te sientes aventurero, yo chequearía el video de - Rails videos donde muestran a un joven compañero creando un blog en 15 minutos. Solo sientete cómodo y mira.

            -

            Debo mencionar a Rails. Tú has estado aprendiendo el lenguaje Ruby, como - hablarlo. Pero Rails es grupo de librerías (algo asi como la librería de popup - que hemos estado usando.) Es un poderoso conjunto de herramientas para crear - sitios web. Si estas interesado en aprender sobre Rails, yo miraría head - por aquí directamente. ¡Empieza a usar tus habilidades en Ruby apropiadamente!

            -

            Algo que tiene Rails son métodos para manejar fechas fácilmente. Como, prueba: Time.now - 2.weeks

            -
            class Integer; def weeks; self * 7*24*60*60; end; end
            -
            \w+ \w+ \d+ \d{2}:\d{2}:\d{2} .*
            -
            -
            -

            Si Quieres Empezar Poco a Poco

            -

            Si quieres comenzar escribiendo pequeños programas en Ruby para practicar, tengo un proyecto llamado MouseHole - que es una pequeña caja de herramientas en la web para escribir programas cortos en Ruby. Puedes ver aquí algunos - scripts para ver que quiero decir.

            -

            MouseHole no es para escribir sitios web en realidad. Es para escribir - pequeños programas y correrlos dentro del navegador. Como hay un programa block - de notas para MouseHole y un programa que agrega una imagen de un ratón a los - links de la web que linkean a programas de MouseHole.

            -

            Tengo un script de MouseHole dentro de un archivo aquí mismo:
            - print File.read("/MouseHole/flickrpedia.user.rb")

            -
            .*Inserts Wikipedia links for Flickr tags.*
            -
            -
            -

            Sumario #8, El Sumario Hey-Relájate-Lo-Hiciste-Bien

            -

            Esta ultima sección se tomó un momento para relajarse, para darte algunos consejos de como - puedes usar Ruby. Si lo has disfrutado, descarga Ruby e instálalo.

            - -

            Una vez que tengas Ruby instalado, puedes usar Ruby Interactivo ejecutando el comando irb en el prompt de tu sistema. Para mas sobre Irb, esta - The Tiger's Vest para ayudarte.

            -

            Tú realmente mereces una torta doble-capa con doble-doble azúcar glaseado y - un tipo tocando una de esas guitarras que son doble-guitarra. Quiero decir - terminaste, ¡lo hiciste! No hay dudas de eso, ¡eres un gran ser certificado!

            -
            -
            - \ No newline at end of file diff --git a/TryRuby/public/tutorials/intro.html b/TryRuby/public/tutorials/intro.html deleted file mode 100644 index 56c1d1c..0000000 --- a/TryRuby/public/tutorials/intro.html +++ /dev/null @@ -1,680 +0,0 @@ - -
            -

            Using the Prompt

            -

            The blue window above is a Ruby prompt. Type a line of Ruby code, hit Enter - and watch it run!

            -

            For example, try typing some math. Like: 2 + 6

            -
            \d+
            -
            -
            -

            Numbers & Math

            -

            Good! You did a bit of math. See how the answer popped out?

            -

            Ruby recognizes numbers and mathematic symbols. You could try some other math like:

            -
            • 4 * 10
            • -
            • 5 - 12
            • -
            • 40 / 4
            -

            Sure, computers are handy and fast for math. Let's move on. Want to see your name reversed? - Type your first name in quotes like this: "Jimmy"

            -
            "(\w+)"
            -
            -
            -

            Say Your Name Backwards

            -

            Perfect, you've formed a string from the letters of your name. A string - is a set of characters the computer can process.

            -

            Imagine the letters are on a string of - laundry line and the quotes are clothespins holding the ends. The quotes mark the beginning and end.

            -

            To reverse your name, type: "Jimmy".reverse (Don't forget the dot!)

            -
            "(\w+)"
            -
            -
            -

            Counting the Letters

            -

            You have used the reverse method on your name! By enclosing your name in - quotes, you made a string. Then you called the reverse method, which works on strings to flip - all the letters backwards.

            -

            Now, let's see how many letters are in your name: "Jimmy".length

            -
            \d+
            -
            -
            -

            On Repeat

            -

            Now, I'm sure by now you're wondering what any of this is good for. Well, I'm sure you've been to - a website that screamed, Hey, your password is too short! See, some programs - use this simple code.

            -

            Watch this. Let's multiply your name by 5. "Jimmy" * 5

            -
            "(\w+)"
            -
            -
            -

            Hey, Summary #1 Already

            -

            Let's look at what you've learned in the first minute.

            -
              -
            • The prompt. Typing code into the green prompt gives you - an answer from a red prompt. All code gives an answer.
            • -
            • Numbers and strings are Ruby's math and text objects.
            • -
            • Methods. You've used English-language methods like reverse - and symbolic methods like * (the multiplication method.) Methods are action!
            • -
            -

            This is the essence of your learning. Taking simple things, toying with - them and turning them into new things. Feeling comfortable yet? I promise you are.

            -

            Okay, let's do something uncomfortable. Try reversing a number: 40.reverse

            -
            NoMethodError: undefined method `reverse' for (\d+):Fixnum
            -
            -
            -

            Stop, You're Barking Mad!

            -

            You can't reverse the number forty. I guess you can hold your monitor up to the - mirror, but reversing a number just doesn't make sense. Ruby has tossed an error - message. Ruby is telling you there is no method reverse for numbers.

            -

            Maybe if you turn it into a string: 40.to_s.reverse.

            -
            \"(\d+)\"
            -
            -
            -

            Boys are Different From Girls

            -

            And numbers are different from strings. While you can use methods on any object - in Ruby, some methods only work on certain types of things. But you can always - convert between different types using Ruby's "to" methods.

            -
            • to_s converts things to strings.
            • -
            • to_i converts things to integers (numbers.)
            • -
            • to_a converts things to arrays.
            • -
            -

            What are arrays?! They are lists. Type in a pair of brackets: [].

            -
            \[\]
            -
            -
            -

            Standing in Line

            -

            Great, that's an empty list. Lists store things in order. - Like standing in line for popcorn. You are behind someone and you wouldn't - dream of pushing them aside, right? And the guy behind you, you've got a - close eye on him, right?

            -

            Here's a list for you. Lottery numbers: [12, 47, 35].

            -
            \[(\d+(, )?){2,}\]
            -
            -
            -

            One Raises Its Hand

            -

            A list of lottery numbers. Which one is the highest?

            -

            Try: [12, 47, 35].max.

            -
            (\d+)
            -
            -
            -

            Tucking a List Away

            -

            Good, good. But it's annoying to have to retype that list, isn't it?

            -

            Let's save our numbers inside a ticket like so: ticket = [12, 47, 35]

            -
            \[(\d+(, )?){2,}\]
            -
            -
            -

            Now Type Ticket

            -

            Now, type: ticket

            -
            \[(\d+(, )?){2,}\]
            -
            -
            -

            Saved, Tucked Away

            -

            Fantastic! You've hung on to your lotto numbers, tucking them away inside a - variable called ticket.

            -

            Let's put your lotto numbers in order, how about? Use: ticket.sort!

            -
            \[(\d+(, )?){2,}\]
            -
            -
            -

            Summary #2 is Upon Us

            -

            You had a list. You sorted the list. The ticket variable is now changed.

            -

            Did you notice that the sort! method has a big, bright exclamation at the end? - A lot of times Ruby methods shout like that if they alter the variable for good. It's nothin - special, just a mark.

            -

            Now, look how your second minute went:

            -
              -
            • Errors. If you try to reverse a number or do anything fishy, - Ruby will skip the prompt and tell you so.
            • -
            • Arrays are lists for storing things in order.
            • -
            • Variables save a thing and give it a name. You used the - equals sign to do this.
              Like: ticket = [14, 37, 18].
            • -
            -

            In all there are eight lessons. You are two-eighths of the way there! - This is simple stuff, don't you think? Good stuff up ahead.

            -

            Let's change directions for a moment. I've stuffed a bit of poetry for you in - a certain variable. Take a look. Type print poem

            -
            poem = "My toast has flown from my hand\nAnd my toast has gone to the -moon.\nBut when I saw it on television,\nPlanting our flag on Halley's -comet,\nMore still did I want to eat it.\n"
            -
            My toast (.+)
            -
            -
            -

            Sadly, You Hate Toast Poetry

            -

            Look, it's okay. You don't have to like it. Hack it up, be my guest.

            -

            Instead of toast, go for a melon or something. Try this: poem['toast'] = 'honeydew'

            -

            And then type print poem by itself to see the new poem.

            -
            My honey(.+)
            -
            -
            -

            Ready, Aim

            -

            The square brackets you just used are very common in Ruby. Remember, you typed: poem['toast'] = 'honeydew'. That box with the word toast has a square bracket on each side, see?

            -

            The -two brackets are like sights used to line up a target. Exactly. These -brackets mean, "I am looking for ____." Ready, aim. Here you're looking -for toast and swapping it out with fruit.

            -

            Here's a question: what happens when we reverse this whole poem? poem.reverse -

            "\\n.ti tae ot (.+)"
            -
            -
            -

            Too Much Reversal

            -

            Okay, sure. So the whole poem's been turned backwards, letter-by-letter. I really want to just - reverse the lines, though. Move the last line up to first and the first line down to last. Backwards, but not - that backwards.

            -

            Here's how: poem.lines.to_a.reverse

            -
            \["More still did I(.+)"\]
            -
            -
            -

            Ringlets of Chained Methods

            -

            So what do you see? What happened there? You typed poem.lines.to_a.reverse and what happened?

            -

            Two things happened. You turned the poem into a -list using lines.to_a. lines decides the way -the string is split up, then to_a converted it into an -Array. (To array.) Different methods, such -as bytes and chars can be used in place -of lines. By using lines, ruby will return each line of the poem.

            -

            Then, you reversed that list. You had each line. You reversed them. That's it.

            -

            Let's tack one more method on the end there: print poem.lines.to_a.reverse.join -

            More still did I(.+)
            -
            -
            -

            Of All the Summaries, #3 is Here Now

            -

            Good show, my friend! The join method took that list of reversed lines and put them - together into a string. (Sure, you could have also just used to_s.)

            -

            Review time.

            -
              -
            • Exclamations. Methods may have exclamations (and also question marks) - in their name. No big deal. Try: poem.include? "my hand"
            • -
            • Square brackets. Target and find things. Search and replace.
            • -
            • Chaining methods lets you get a lot more done. Break up a poem, - reverse it, reassemble it: poem.lines.to_a.reverse.join
            • -
            -

            At this point, you may want to tinker with the poem a bit more. A complete list of all - the String methods is - - here. - Go ahead and try a few (such as poem.downcase or poem.delete.)

            -

            When you're ready to move on, type: books = {}

            -
            \{\}
            -
            -
            -

            A Wee Blank Book

            -

            You've made an empty hash. (Also known as: an empty dictionary.)

            -

            We're going to stuff some miniature book reviews in this hash. Here's our rating system:

            -
              -
            • :splendid → a masterpiece.
            • -
            • :quite_good → enjoyed, sure, yes.
            • -
            • :mediocre → equal parts great and terrible.
            • -
            • :quite_not_good → notably bad.
            • -
            • :abyssmal → steaming wreck.
            • -
            -

            To rate a book, put the title in square brackets and put the rating after the equals.

            -

            For example: books["Gravity's Rainbow"] = :splendid

            -
            :\w+
            -
            -
            -

            More Bite-Size Reviews

            -

            Keep going, fill it up with reviews. And, if you want to see the whole list, - just type: books

            -

            Again, the ratings are: :splendid, :quite_good, :mediocre, - :quite_not_good, and :abyssmal.

            -

            These ratings are not strings. When you place a colon in front of a simple word, you get a - symbol. Symbols are cheaper than strings (in terms of computer memory.) If - you use a word over and over in your program, use a symbol. Rather than having thousands of - copies of that word in memory, the computer will store the symbol only once.

            -

            Once you've got three or four books in - there, type: books.length.

            -
            [3-9]
            -
            -
            -

            Wait, Did I Like Gravity's Rainbow?

            -

            See, the length method works on strings, list and hashes. One great thing about - Ruby is that names are often reused, which means fewer names you need to remember.

            -

            If you'd like to look up one of your old reviews, again put the title in the square. But leave off - the equals.

            -

            Just like this: books["Gravity's Rainbow"]

            -
            :\w+
            -
            -
            -

            Hashes as Pairs

            -

            Keep in mind that hashes won't keep things in order. That's not their job. It'll just pair up two - things: a key and a value. In your reviews, the key is the book's - title and the value is the rating.

            -

            If you want to just see the titles of the books you've reviewed: books.keys

            -
            \[".*"\]
            -
            -
            -

            Are You Harsh?

            -

            So are you giving out harsh, unfair reviews? Let's keep score with this hash:
            ratings = Hash.new {0}

            -

            Then, okay, now let's count up your reviews. Just stay with me. Type:
            - books.values.each { |rate| ratings[rate] += 1 }

            -

            (The straight line in the code is the pipe character, probably located right above the - Enter key on your keyboard.)

            -
            \[:.+\]
            -
            -
            -

            A Tally

            -

            Great, wow! You've made a scorecard of your ratings. Type ratings to see the count. - This new hash shows a rating and then the number of times you've given that rating.

            -

            One of the amazing new things we've just used is a block. We're going to - explore these more in the next summary. But, basically, a block is a bit of Ruby code surrounded - by curly braces.

            -

            Let's try another block: 5.times { print "Odelay!" }

            -
            Odelay!Od.*
            -
            -
            -

            Now Arriving at Summary #4

            -

            Blocks are always attached to methods. Like the times method, which takes the - block and runs the code over and over. (In this case: five times.)

            -

            This last lesson was a bit longer. You've probably used up three minutes learning about:

            -
              -
            • Hashes. The little dictionary with the curly pages: {}.
            • -
            • Symbols. Tiny, efficient code words with a colon: :splendid.
            • -
            • Blocks. Chunks of code which can be tacked on to many of Ruby's methods. Here's the - code you used to build a scorecard:
              books.values.each { |rate| ratings[rate] += 1 }.
            • -
            -

            On your computer, you probably have a lot of different files. Files with pictures in them, - files with programs in them. And files are often organized into folders, also called: - directories.

            -

            I've prepared a few directories for you. Take a look: - Dir.entries "/"

            -
            \["\.", .+\]
            -
            -
            -

            The Private Collection of Dr. Dir

            -

            You've just listed out everything in the top directory. The root directory, indicated - by a single slash. Containing some programs and other tutorials and such.

            -

            So, what is the Dir.entries method? Well, it's just a method, right? - entries is a method called on the Dir variable. - And Dir has a collection of methods for checking out file directories.

            -

            One other little thing we haven't really talked about openly. Method arguments, highlighted in green.

            -
              -
            • Dir.entries "/": Anything listed after a method - is considered an attachment.
            • -
            • print poem: See, print is an ordinary method. And the - poem is attached. To be printed.
            • -
            • print "pre", "event", "ual", "ism" has several arguments, with commas - between them.
            • -
            -

            To list just the text files in that directory: Dir["/*.txt"]

            -
            \["\/comics\.txt"\]
            -
            -
            -

            Come, Read Comics With Me

            -

            The Dir[] method is like entries but you search for files - with wildcard characters. Here, we see those square brackets again! Notice how - they still mean, "I am looking for _____?"

            -

            More specifically: "I am looking for files which end with .txt."

            -

            Let's crack open this comics file, then. Here's the way:
            - print File.read("/comics.txt")

            -
            Achewood.+
            -
            -
            -

            Mi Comicas, Tu Comicas

            -

            All right! We can start to use files to store things. This is great because normally when - we exit Ruby, all our variables will be gone. Ruby, by itself, forgets these things. - But if we save things in files, we can read those files in future Ruby escapades.

            -

            Hey, and guess what? The /Home directory is yours! I gave it to you! I am generous! Let's make a copy of the comics file.

            -

            You'll want to: FileUtils.copy('/comics.txt', '/Home/comics.txt') -

            If you've already created the file, use File.delete('/Home/comics.txt') to trash it.

            -
            nil
            -
            -
            -

            Your Own Turf

            -

            Okay, you've got a copy. Check it: Dir["/Home/*.txt"]

            -

            To add your own comic to the list, let's open the file in append mode.

            -

            Start like this: File.open("/Home/comics.txt", "a") do |f|.

            -
            ..
            -
            -
            -

            And Now For the Startling Conclusion

            -

            So your prompt has changed. See that? Your prompt is a double dot now.

            -

            In this tutorial, this prompt means that Ruby is expecting you to type more. - As you type in the lines of Ruby code, the double dots will continue until you - are completely finished.

            -

            Hot tip: If you want to stop working on the code and break out of the double dots, use the reset - command. If you want to go the previous page of the tutorial, use the back command.

            -

            Here's your code. You've already typed the first line, so just enter the second line. (The \n - is an Enter character.

            -
            • File.open("/Home/comics.txt", "a") do |f|
            • -
            •   f << "Cat and Girl: http://catandgirl.com/\n"
            • -
            • end
            • -
            -

            And, since you're getting so advanced and capable here, one other tip: you can use the up and down arrow keys to - edit your old commands or run them again.

            -
            ..
            -
            -
            -

            Ruby Sits Still

            -

            That last line adds the Cat and Girl comic to the list, but Ruby's going to wait until you're totally finished to - take action.

            -

            Now, to finish the code you've started. You opened a new block when you typed do. - So far the blocks we've seen have used curly braces. This time we'll be using do and end instead - of curly braces. A lot of Rubyists will use do...end when the block goes on for many lines.

            -

            Let's get that block finished now, with: end

            -
            • File.open("/Home/comics.txt", "a") do |f|
            • -
            •   f << "Cat and Girl: http://catandgirl.com/\n"
            • -
            • end
            • -
            -
            #.File:/Home/comics\.txt \(closed\).
            -
            -
            -

            The Clock Nailed To the File

            -

            Good, good! You've added that new comic to the file. You can see for yourself: print File.read("/Home/comics.txt")

            -

            What time was it when you changed the file? Let's check. Type: File.mtime("/Home/comics.txt")

            -
            \d{4}-\d+-\d+ \d{2}:\d{2}:\d{2} [+-]\d{4}
            -
            -
            -

            Just the Hour Hand

            -

            Great, there's the time. The precise time exactly when you added to the file. The mtime gives you a Ruby Time object.

            -

            If you want to check just what hour it was, hit the up arrow key and change the line to: File.mtime("/Home/comics.txt").hour

            -
            \d+
            -
            -
            -

            Hallo, Who's There? And Summary #5 Waves Its Hat!

            -

            Well done, well done, well done, well done! Truly, truly, truly, truly, truuuuuuuuly!

            -

            Here's the last few minutes of your life in review:

            -
              -
            • Files. What more can be said? Lots of methods for editing files and lookin around in directories.
            • -
            • Arguments. Arguments are a list of things sent into a method. With commas between.
            • -
            • We also spoke about do and end which are another way to make a block.
            • -
            -

            You totally know how to use Ruby now. I mean you've got down the essentials. You just need to keep learning more methods and - try out more complex blocks.

            -

            But there's one side of Ruby we haven't settled. Making your own methods and classes.

            -

            Ahem! Let's get it over with then.

            -

            Start with: def load_comics( path )

            -
            ..
            -
            -
            -

            In Ruby, Def Leppard Means Define Leppard (a Method)!

            -

            Hey, okay, you done it. You're making your own method. You started with def, followed by the name of the method. - And a list of arguments which the method will need. This isn't too scary and dangerous!

            -

            All we have to do is fill it up with Ruby and finish it up with end.

            -

            Here's the code:

            -
            • def load_comics( path )
            • -
            •   comics = {}
            • -
            •   File.foreach(path) do |line|
            • -
            •     name, url = line.split(': ')
            • -
            •     comics[name] = url.strip
            • -
            •   end
            • -
            •   comics
            • -
            • end
            • -
            -

            No need to indent, if you don't want. I just do that to make it read easier.

            -
            nil
            -
            -
            -

            The Ripened Fruit of Your Own Creation

            -

            A new method is born. Let us use it: comics = load_comics('/comics.txt')

            -

            If you have a problem, you might have mistyped. Use the back command and try again.

            -
            \{.*"Achewood"=."http://achewood.com/".*\}
            -
            -
            -

            Hey, Cool, a Comics Thing

            -

            In your Ruby window above, look at the code you've typed for the load_comics method. What is happening? You're - passing in the path variable and you're getting back the comics variable. Ruby lets the comics - hash trickle out the end of the method.

            -

            A number of methods were used to get the job done. See if you can spot them.

            -
            • File.foreach is a method which opens a file and hands each line to the block. The line - variable inside the do...end block took turns with each line in the file.
            • -
            • split is a method for strings, which breaks the string up into an array. An axe is laid on the colon - and the line is chopped in half, giving us the url and name for each comic.
            • -
            • strip removes extra spaces around the name. Just in case.
            • -
            -

            Right on. Bravo. You've got the comics in a Ruby hash. But what now? What good is this really?

            -

            Let's make a page of links. How about that? I went ahead and loaded a little library I've made for you.

            -

            Type: next. This is temporary as I updates new lessons.

            -
            true
            -
            -
            -

            Browser Puppetry

            -

            Excellent, you've loaded the popup library. It's saved in a file in the Libraries folder. See: Dir["/Libraries/*"]

            -

            The popup library contains a bunch of methods I've written which let you control a popup here on the Try Ruby site.

            -

            Here, try this: Popup.goto "http://google.com/"

            -
            \033\[1;JSm.*popup_goto\(.*\)\033\[m.*
            -
            -
            -

            Making Links and Spinning Webs

            -

            Our own lovely, little popup to manipulate. You can also fill it with your own goodies. We'll start small:

            -
            • Popup.make {
            • -
            •   h1 "My Links"
            • -
            •   link "Go to Google", "http://google.com/"
            • -
            • }
            • -
            -

            The term h1 (h-one) means a level-one header. In HTML, this is the largest size of header.

            -
            \033\[1;JSm.*popup_make\(.*h1.*a href.*\)\033\[m.*
            -
            -
            -

            Popups Are So Easy, It's Crazy

            -

            Looks good, you did it perfectly, just as you were asked. Let's make a list then.

            -

            Here's how you make a list with the popup library:

            -
            • Popup.make do
            • -
            •   h1 "Things To Do"
            • -
            •   list do
            • -
            •     p "Try out Ruby"
            • -
            •     p "Ride a tiger"
            • -
            •     p "(down River Euphrates)"
            • -
            •   end
            • -
            • end
            • -
            -

            The p method is short for "paragraph".

            -
            \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*li.*\)\033\[m.*
            -
            -
            -

            Spread the Comics on the Table

            -

            Okay, this is coming along wonderfully. This is simple stuff, but keep in mind that you didn't know any Ruby whatsoever just fifteen minutes ago!

            -

            Last -step. Let's tie it all together, you know? Let's make it chime together -like a very nice set of glistening chimes on the beach in the -maginificent sunlight!

            -

            Make sure the comics are loaded: comics = load_comics( '/comics.txt' )

            -

            Now, let's make a list of the links to each comic:

            -
            • Popup.make do
            • -
            •   h1 "Comics on the Web"
            • -
            •   list do
            • -
            •     comics.each do |name, url|
            • -
            •       link name, url
            • -
            •     end
            • -
            •   end
            • -
            • end
            • -
            -

            You can click on the links and read the comics in the little window even! Smashing!

            -
            \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*a href.*li.*a href.*\)\033\[m.*
            -
            -
            -

            Summary #6 Which Means You've Come So Far

            -

            You're a level six Ruby cleric. I mean what a great job you've done. Let's review:

            -
              -
            • You added your own method with def and you used that load_comics method several times.
            • -
            • Libraries. You used the require method to load the popup library.
              By typing: require 'popup'
            • -
            • And if that wasn't enough, you made your own web page from a list of comics in a file. You made a real program!
            • -
            -

            So -what could possibly be next? What could you possibly have to learn now? -Ha, this is the best part. You've come such a long way that we're going -to uncover classes. For two more short lessons and you're done.

            -

            Earlier, we created a hash like this: Hash.new Try it.

            -
            \{\}
            -
            -
            -

            Not a School Class, a Working Class

            -

            You see, the empty curly braces {} is a shortcut for Hash.new. The new -method is used to make objects of a certain class. (Think "class" as in -"working class" — a specific group of objects which are similar, have -the same jobs, the same shirts.)

            -

            Ask yourself this: How would I make a blog in Ruby? -Where would you start? Well, you might store your blog entries in a -file, right? But how would you keep track of the title of the entry and -the time it was posted? And when you loaded the file, how would it look -in Ruby? Would it be a Hash? Or an Array? Or an Array of Arrays? Or -something else?

            I really think you'll want to use a class. You are already familiar with many classes: Hash, Array, String.

            -

            Let's make a new class: class BlogEntry.

            -
            ..
            -
            -
            -

            The Stuff Blogs are Made of

            -

            You've opened up a new BlogEntry class. What is your blog entry made of? A title, sure. Also, a time when the entry was posted. The - full text of the entry.

            -

            We'll do a mood setting, too, just like LiveJournal. The Internet has really brought back stick people and smileys - out of bankruptcy. Emote!

            -

            Okay, so you've got the first line of the class, here's the rest:

            -
            • class BlogEntry
            • -
            •   attr_accessor :title, :time, :fulltext, :mood
            • -
            • end
            • -
            -
            nil
            -
            -
            -

            Accessors Are the Dangling Limbs

            -

            Hey, good class, man. You've got a new BlogEntry class. To start an entry:
            entry = BlogEntry.new.

            -

            In the class definition, you used a method called attr_accessor. There are many attribute methods like - this which add little settings to classes. These attributes are just variables attached to a class.

            -

            Think -of it this way. A class is like a person. That star-shaped human thing -out there. And the attributes are the dangling limbs, the different -parts that make up a body.

            -

            To set the title of your entry: entry.title = "Today Mt. Hood Was Stolen!"

            -
            ".+"
            -
            -
            -

            An Object, That Neat Little Package

            -

            Go ahead and set the post time: entry.time = Time.now

            -

            And the mood: entry.mood = :sick

            -

            And the post itself: entry.fulltext = "I can't believe Mt. Hood was stolen! I am speechless! It was stolen by a giraffe who drove away - in his Cadillac Seville very nonchalant!!"

            -

            To see all your settings, just type at the prompt: entry.

            -
            #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
            -
            -
            -

            Quickening it Up

            -

            Cool, -you're blog is awesome. Hey, let's make things a bit easier on you. -You're not going to want to set the time like that every time you post. -You just want to type in the title and the entry and the mood quickly, -right?

            -

            Let's add an initialize method.

            -
            • class BlogEntry
            • -
            •   def initialize( title, mood, fulltext )
            • -
            •     @time = Time.now
            • -
            •     @title, @mood, @fulltext = title, mood, fulltext
            • -
            •   end
            • -
            • end
            • -
            -

            Once you've got that typed in, try making a new entry: BlogEntry.new

            -
            ArgumentError: wrong number of arguments \(0 for 3\).*
            -
            -
            -

            You've Taught Your Blog to Reject Worthless Things

            -

            Did you see how inside the class we used the at-symbols? Like this: @time = Time.now

            -

            Outside the class, we use accessors: entry.time = Time.now But inside we use instance variables: @time = Time.now - They're the exact same thing, but expressed in two different places of your program.

            -

            Your blog now needs a title, a mood and a post in order to work. When a new BlogEntry is created, the initialize method - is used to check for any arguments to new. Uh, we need three arguments!

            -

            Try it again with all three.

            -

            entry2 -= BlogEntry.new( "I Left my Hoodie on the Mountain!", :confused, "I am -never going back to that mountain and I hope a giraffe steals it." )

            -
            #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
            -
            -
            -

            A Giraffe Has Not Stolen Summary #7

            -

            Aha, you're here. And all in one piece. We're still going to make your blog real, but until then, let's review, okay?

            -
              -
            • Classes. Everything in Ruby is some kind of object. Classes explain objects. How a certain object works. - For example, you made a few blog entry objects and these objects are explained in the BlogEntry class. - In other words: you call them BlogEntry objects.
            • -
            • Accessors are variables attached to an object which can be used outside the object. (entry.time = Time.now)
            • -
            • Instance variables are the same variables you're using for accessors when inside the object. - Like in a method definition. (@time = Time.now)
            • -
            -

            Okay, -let's wrap things up, kid. Here's the last chapter of the GRIPPING epic -story of Try Ruby! Now that you've got a taste of how it all works, how -are you going to use it around the house and in your grocer's freezer? -You're a great person (one of my favorites), but you need guidance.

            -

            Let's finish your blog. You have blog entries, but no actual blog.

            -

            Put the entries into an array: blog = [entry, entry2]

            -
            \[#.BlogEntry:0x[0-9a-f]+.*, #.BlogEntry:0x[0-9a-f]+.*\]
            -
            -
            -

            It's All About Combining Things

            -

            Some -beautiful things can be done with the simple parts of Ruby, especially -when you combine them together into new things. Here we've got a blog -made of an array of classes. And, actually, Ruby really does good with -this kind of creature.

            -

            Here's a few things you can do with your array blog:

            -
            • You'll want to sort your entries from newest to oldest. You can do this with:
              - blog.sort_by { |entry| entry.time }.reverse
              See the sort_by explanation for more.
            • -
            • If you want to search your blog for anything related to "cadillac":
              - blog.find_all { |entry| entry.fulltext.match(/cadillac/i) }
              - Read all about find_all - and match - to figure out how that works. Also: the slashy /giraffe/i is a Regexp object, used for matching words.
            • -
            • Add new entries with blog << new_entry
              - And check out the << method documentation.
            • -
            -

            You can browse a list of all Ruby's built-in methods at ruby-doc.org's core list. - Another good list is at the online pickaxe.

            -

            One really useful method (I probably use this more than anything else) is map. Type: blog.map { |entry| entry.mood }

            -
            \[(:\w+, )+:\w+\]
            -
            -
            -

            Look at His Face — The Transformation Has Begun

            -

            The map method cycles through an array and replaces each item with something new. Say you wanted to replace each of your blog entries - with the name Bruce Willis. Do it so: blog.map { "Bruce Willis" }

            -

            Since the block always returns the string "Bruce Willis", that's what you get. In the code you just used, the entry was swapped out - for only the entry.mood.

            -

            Now, -I want you to make a popup with your blog entries. I'm not going to -give you all of the code. I'm just going to give you part of it.

            -
            • blog.each do |entry|
            • -
            •   h2 entry.title
            • -
            •   p entry.fulltext
            • -
            • end
            • -
            -

            Now, I expect you to put the popup code around it and add an h1 title with the name of your blog. For extra haroompf, have the time of each entry display.

            -
            \033\[1;JSm.*popup_make\(.*h1.*h2.*li.*h2.*li.*\)\033\[m.*
            -
            -
            -

            You are Some Kind of Web Guru, I Have Stars in My Eyes

            -

            Good, -that's it! This is exactly the code you can use to write your own real -Ruby blog. If you're feeling adventurous, I'd check out the Rails videos which show a swift young fellow creating a blog in 15 minutes. You just sit back and watch.

            -

            I -should mention Rails. You have been learning the Ruby language, how to -speak it. But Rails is a bunch of libraries (sort of like the popup -library we've been using.) It's a very powerful toolkit for building -websites. If you're interested in learning about Rails, I would head - over there right away. Start using your Ruby skills proper!

            -

            One thing Rails has is easy methods for dates. Like, try: Time.now - 2.weeks

            -
            class Integer; def weeks; self * 7*24*60*60; end; end
            -
            \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-+]\d{4}
            -
            -
            -

            If You Want to Start Small

            -

            If you'd like to start writing little Ruby programs just to practice, I have a project called MouseHole - which is a little web toolkit for writing short Ruby programs. You can look over a few - scripts to see what I mean.

            -

            MouseHole -isn't for writing web sites really. It's just for writing little -programs you run inside your browser. Like there's a notepad program -for MouseHole and a program which adds a mouse picture next to links on -the web which link to MouseHole programs.

            -

            I've got a MouseHole script inside a file here:
            - print File.read("/MouseHole/flickrpedia.user.rb")

            -
            .*Inserts Wikipedia links for Flickr tags.*
            -
            -
            -

            Summary #8, The Hey-Relax-You-Did-Good Summary

            -

            This last section took a moment to wind down, to give you some pointers as to how you can use Ruby. If you enjoyed yourself, - download Ruby and install it.

            - -

            Once you have Ruby installed, you can use Interactive Ruby by running irb on your system's prompt. For more on Irb, - there's The Tiger's Vest to help you.

            -

            You -really deserve a double-layer cake with double-double frosting and a -guy playing one of those guitars that's a double guitar. I mean you -finished, you really did! No doubt about it, you're a certified -red-blooded smartiac!

            -
            -
            - - diff --git a/TryRuby/public/tutorials/intro.html.broken b/TryRuby/public/tutorials/intro.html.broken deleted file mode 100755 index 5a6c27c..0000000 --- a/TryRuby/public/tutorials/intro.html.broken +++ /dev/null @@ -1,638 +0,0 @@ - -
            -

            Using the Prompt

            -

            The blue window above is a Ruby prompt. Type a line of Ruby code, hit Enter - and watch it run!

            -

            For example, try typing some math. Like: 2 + 6

            -
            \d+
            -
            -
            -

            Numbers & Math

            -

            Good! You did a bit of math. See how the answer popped out?

            -

            Ruby recognizes numbers and mathematic symbols. You could try some other math like:

            -
            • 4 * 10
            • -
            • 5 - 12
            • -
            • 40 / 4
            -

            Sure, computers are handy and fast for math. Let's move on. Want to see your name reversed? - Type your first name in quotes like this: "Jimmy"

            -
            "(\w+)"
            -
            -
            -

            Say Your Name Backwards

            -

            Perfect, you've formed a string from the letters of your name. A string - is a set of characters the computer can process.

            -

            Imagine the letters are on a string of - laundry line and the quotes are clothespins holding the ends. The quotes mark the beginning and end.

            -

            To reverse your name, type: "Jimmy".reverse (Don't forget the dot!)

            -
            "(\w+)"
            -
            -
            -

            Counting the Letters

            -

            You have used the reverse method on your name! By enclosing your name in - quotes, you made a string. Then you called the reverse method, which works on strings to flip - all the letters backwards.

            -

            Now, let's see how many letters are in your name: "Jimmy".length

            -
            \d+
            -
            -
            -

            On Repeat

            -

            Now, I'm sure by now you're wondering what any of this is good for. Well, I'm sure you've been to - a website that screamed, Hey, your password is too short! See, some programs - use this simple code.

            -

            Watch this. Let's multiply your name by 5. "Jimmy" * 5

            -
            "(\w+)"
            -
            -
            -

            Hey, Summary #1 Already

            -

            Let's look at what you've learned in the first minute.

            -
              -
            • The prompt. Typing code into the green prompt gives you - an answer from a red prompt. All code gives an answer.
            • -
            • Numbers and strings are Ruby's math and text objects.
            • -
            • Methods. You've used English-language methods like reverse - and symbolic methods like * (the multiplication method.) Methods are action!
            • -
            -

            This is the essence of your learning. Taking simple things, toying with - them and turning them into new things. Feeling comfortable yet? I promise you are.

            -

            Okay, let's do something uncomfortable. Try reversing a number: 40.reverse

            -
            NoMethodError: undefined method `reverse' for (\d+):Fixnum
            -
            -
            -

            Stop, You're Barking Mad!

            -

            You can't reverse the number forty. I guess you can hold your monitor up to the - mirror, but reversing a number just doesn't make sense. Ruby has tossed an error - message. Ruby is telling you there is no method reverse for numbers.

            -

            Maybe if you turn it into a string: 40.to_s.reverse.

            -
            \"(\d+)\"
            -
            -
            -

            Boys are Different From Girls

            -

            And numbers are different from strings. While you can use methods on any object - in Ruby, some methods only work on certain types of things. But you can always - convert between different types using Ruby's "to" methods.

            -
            • to_s converts things to strings.
            • -
            • to_i converts things to integers (numbers.)
            • -
            • to_a converts things to arrays.
            • -
            -

            What are arrays?! They are lists. Type in a pair of brackets: [].

            -
            \[\]
            -
            -
            -

            Standing in Line

            -

            Great, that's an empty list. Lists store things in order. - Like standing in line for popcorn. You are behind someone and you wouldn't - dream of pushing them aside, right? And the guy behind you, you've got a - close eye on him, right?

            -

            Here's a list for you. Lottery numbers: [12, 47, 35].

            -
            \[(\d+(, )?){2,}\]
            -
            -
            -

            One Raises Its Hand

            -

            A list of lottery numbers. Which one is the highest?

            -

            Try: [12, 47, 35].max.

            -
            (\d+)
            -
            -
            -

            Tucking a List Away

            -

            Good, good. But it's annoying to have to retype that list, isn't it?

            -

            Let's save our numbers inside a ticket like so: ticket = [12, 47, 35]

            -
            \[(\d+(, )?){2,}\]
            -
            -
            -

            Now Type Ticket

            -

            Now, type: ticket

            -
            \[(\d+(, )?){2,}\]
            -
            -
            -

            Saved, Tucked Away

            -

            Fantastic! You've hung on to your lotto numbers, tucking them away inside a - variable called ticket.

            -

            Let's put your lotto numbers in order, how about? Use: ticket.sort!

            -
            \[(\d+(, )?){2,}\]
            -
            -
            -

            Summary #2 is Upon Us

            -

            You had a list. You sorted the list. The ticket variable is now changed.

            -

            Did you notice that the sort! method has a big, bright exclamation at the end? - A lot of times Ruby methods shout like that if they alter the variable for good. It's nothin - special, just a mark.

            -

            Now, look how your second minute went:

            -
              -
            • Errors. If you try to reverse a number or do anything fishy, - Ruby will skip the prompt and tell you so.
            • -
            • Arrays are lists for storing things in order.
            • -
            • Variables save a thing and give it a name. You used the - equals sign to do this.
              Like: ticket = [14, 37, 18].
            • -
            -

            In all there are eight lessons. You are two-eighths of the way there! - This is simple stuff, don't you think? Good stuff up ahead.

            -

            Let's change directions for a moment. I've stuffed a bit of poetry for you in - a certain variable. Take a look. Type print poem

            -
            poem = "My toast has flown from my hand\nAnd my toast has gone to the -moon.\nBut when I saw it on television,\nPlanting our flag on Halley's -comet,\nMore still did I want to eat it.\n"
            -
            My toast (.+)
            -
            -
            -

            Sadly, You Hate Toast Poetry

            -

            Look, it's okay. You don't have to like it. Hack it up, be my guest.

            -

            Instead of toast, go for a melon or something. Try this: poem['toast'] = 'honeydew'

            -

            And then type print poem by itself to see the new poem.

            -
            My honey(.+)
            -
            -
            -

            Ready, Aim

            -

            The square brackets you just used are very common in Ruby. Remember, you typed: poem['toast'] = 'honeydew'. That box with the word toast has a square bracket on each side, see?

            -

            The -two brackets are like sights used to line up a target. Exactly. These -brackets mean, "I am looking for ____." Ready, aim. Here you're looking -for toast and swapping it out with fruit.

            -

            Here's a question: what happens when we reverse this whole poem? poem.reverse -

            "\\n.ti tae ot (.+)"
            -
            -
            -

            Too Much Reversal

            -

            Okay, sure. So the whole poem's been turned backwards, letter-by-letter. I really want to just - reverse the lines, though. Move the last line up to first and the first line down to last. Backwards, but not - that backwards.

            -

            Here's how: poem.lines.to_a.reverse

            -
            \["More still did I(.+)"\]
            -
            -
            -

            Ringlets of Chained Methods

            -

            So what do you see? What happened there? You typed poem.lines.to_a.reverse and what happened?

            -

            Two things happened. You turned the poem into a -list using lines.to_a. lines decides the way -the string is split up, then to_a converted it into an -Array. (To array.) Different methods, such -as bytes and chars can be used in place -of lines. By using lines, ruby will return each line of the poem.

            -

            Then, you reversed that list. You had each line. You reversed them. That's it.

            -

            Let's tack one more method on the end there: print poem.lines.to_a.reverse.join -

            More still did I(.+)
            -
            -
            -

            Of All the Summaries, #3 is Here Now

            -

            Good show, my friend! The join method took that list of reversed lines and put them - together into a string. (Sure, you could have also just used to_s.)

            -

            Review time.

            -
              -
            • Exclamations. Methods may have exclamations (and also question marks) - in their name. No big deal. Try: poem.include? "my hand"
            • -
            • Square brackets. Target and find things. Search and replace.
            • -
            • Chaining methods lets you get a lot more done. Break up a poem, - reverse it, reassemble it: poem.lines.to_a.reverse.join
            • -
            -

            At this point, you may want to tinker with the poem a bit more. A complete list of all - the String methods is - - here. - Go ahead and try a few (such as poem.downcase or poem.delete.)

            -

            When you're ready to move on, type: books = {}

            -
            \{\}
            -
            -
            -

            A Wee Blank Book

            -

            You've made an empty hash. (Also known as: an empty dictionary.)

            -

            We're going to stuff some miniature book reviews in this hash. Here's our rating system:

            -
              -
            • :splendid → a masterpiece.
            • -
            • :quite_good → enjoyed, sure, yes.
            • -
            • :mediocre → equal parts great and terrible.
            • -
            • :quite_not_good → notably bad.
            • -
            • :abyssmal → steaming wreck.
            • -
            -

            To rate a book, put the title in square brackets and put the rating after the equals.

            -

            For example: books["Gravity's Rainbow"] = :splendid

            -
            :\w+
            -
            -
            -

            More Bite-Size Reviews

            -

            Keep going, fill it up with reviews. And, if you want to see the whole list, - just type: books

            -

            Again, the ratings are: :splendid, :quite_good, :mediocre, - :quite_not_good, and :abyssmal.

            -

            These ratings are not strings. When you place a colon in front of a simple word, you get a - symbol. Symbols are cheaper than strings (in terms of computer memory.) If - you use a word over and over in your program, use a symbol. Rather than having thousands of - copies of that word in memory, the computer will store the symbol only once.

            -

            Once you've got three or four books in - there, type: books.length.

            -
            [3-9]
            -
            -
            -

            Wait, Did I Like Gravity's Rainbow?

            -

            See, the length method works on strings, list and hashes. One great thing about - Ruby is that names are often reused, which means fewer names you need to remember.

            -

            If you'd like to look up one of your old reviews, again put the title in the square. But leave off - the equals.

            -

            Just like this: books["Gravity's Rainbow"]

            -
            :\w+
            -
            -
            -

            Hashes as Pairs

            -

            Keep in mind that hashes won't keep things in order. That's not their job. It'll just pair up two - things: a key and a value. In your reviews, the key is the book's - title and the value is the rating.

            -

            If you want to just see the titles of the books you've reviewed: books.keys

            -
            \[".*"\]
            -
            -
            -

            Are You Harsh?

            -

            So are you giving out harsh, unfair reviews? Let's keep score with this hash:
            ratings = Hash.new {0}

            -

            Then, okay, now let's count up your reviews. Just stay with me. Type:
            - books.values.each { |rate| ratings[rate] += 1 }

            -

            (The straight line in the code is the pipe character, probably located right above the - Enter key on your keyboard.)

            -
            \[:.+\]
            -
            -
            -

            A Tally

            -

            Great, wow! You've made a scorecard of your ratings. Type ratings to see the count. - This new hash shows a rating and then the number of times you've given that rating.

            -

            One of the amazing new things we've just used is a block. We're going to - explore these more in the next summary. But, basically, a block is a bit of Ruby code surrounded - by curly braces.

            -

            Let's try another block: 5.times { print "Odelay!" }

            -
            Odelay!Od.*
            -
            -
            -

            Now Arriving at Summary #4

            -

            Blocks are always attached to methods. Like the times method, which takes the - block and runs the code over and over. (In this case: five times.)

            -

            This last lesson was a bit longer. You've probably used up three minutes learning about:

            -
              -
            • Hashes. The little dictionary with the curly pages: {}.
            • -
            • Symbols. Tiny, efficient code words with a colon: :splendid.
            • -
            • Blocks. Chunks of code which can be tacked on to many of Ruby's methods. Here's the - code you used to build a scorecard:
              books.values.each { |rate| ratings[rate] += 1 }.
            • -
            -<<<<<<< HEAD - - -======= -

            On your computer, you probably have a lot of different files. Files with pictures in them, - files with programs in them. And files are often organized into folders, also called: - directories.

            -

            I've prepared a few directories for you. Take a look: - Dir.entries "/"

            -
            \["\.", .+\]
            -
            -
            -

            The Private Collection of Dr. Dir

            -

            You've just listed out everything in the top directory. The root directory, indicated - by a single slash. Containing some programs and other tutorials and such.

            -

            So, what is the Dir.entries method? Well, it's just a method, right? - entries is a method called on the Dir variable. - And Dir has a collection of methods for checking out file directories.

            -

            One other little thing we haven't really talked about openly. Method arguments, highlighted in green.

            -
              -
            • Dir.entries "/": Anything listed after a method - is considered an attachment.
            • -
            • print poem: See, print is an ordinary method. And the - poem is attached. To be printed.
            • -
            • print "pre", "event", "ual", "ism" has several arguments, with commas - between them.
            • -
            -

            To list just the text files in that directory: Dir["/*.txt"]

            -
            \["\/comics\.txt"\]
            -
            -
            -

            Come, Read Comics With Me

            -

            The Dir[] method is like entries but you search for files - with wildcard characters. Here, we see those square brackets again! Notice how - they still mean, "I am looking for _____?"

            -

            More specifically: "I am looking for files which end with .txt."

            -

            Let's crack open this comics file, then. Here's the way:
            - print File.read("/comics.txt")

            -
            Achewood.+
            -
            -
            -

            Mi Comicas, Tu Comicas

            -

            All right! We can start to use files to store things. This is great because normally when - we exit Ruby, all our variables will be gone. Ruby, by itself, forgets these things. - But if we save things in files, we can read those files in future Ruby escapades.

            -

            Hey, and guess what? The /Home directory is yours! I gave it to you! I am generous! Let's make a copy of the comics file.

            -

            You'll want to: FileUtils.copy('/comics.txt', '/Home/comics.txt') -

            If you've already created the file, use File.delete('/Home/comics.txt') to trash it.

            -
            nil
            -
            -
            -

            Your Own Turf

            -

            Okay, you've got a copy. Check it: Dir["/Home/*.txt"]

            -

            To add your own comic to the list, let's open the file in append mode.

            -

            Start like this: File.open("/Home/comics.txt", "a") do |f|.

            -
            ..
            -
            -
            -

            And Now For the Startling Conclusion

            -

            So your prompt has changed. See that? Your prompt is a double dot now.

            -

            In this tutorial, this prompt means that Ruby is expecting you to type more. - As you type in the lines of Ruby code, the double dots will continue until you - are completely finished.

            -

            Hot tip: If you want to stop working on the code and break out of the double dots, use the reset - command. If you want to go the previous page of the tutorial, use the back command.

            -

            Here's your code. You've already typed the first line, so just enter the second line. (The \n - is an Enter character.

            -
            • File.open("/Home/comics.txt", "a") do |f|
            • -
            •   f << "Cat and Girl: http://catandgirl.com/\n"
            • -
            • end
            • -
            -

            And, since you're getting so advanced and capable here, one other tip: you can use the up and down arrow keys to - edit your old commands or run them again.

            -
            ..
            -
            -
            -

            Ruby Sits Still

            -

            That last line adds the Cat and Girl comic to the list, but Ruby's going to wait until you're totally finished to - take action.

            -

            Now, to finish the code you've started. You opened a new block when you typed do. - So far the blocks we've seen have used curly braces. This time we'll be using do and end instead - of curly braces. A lot of Rubyists will use do...end when the block goes on for many lines.

            -

            Let's get that block finished now, with: end

            -
            • File.open("/Home/comics.txt", "a") do |f|
            • -
            •   f << "Cat and Girl: http://catandgirl.com/\n"
            • -
            • end
            • -
            -
            #.File:/Home/comics\.txt \(closed\).
            -
            -
            -

            The Clock Nailed To the File

            -

            Good, good! You've added that new comic to the file. You can see for yourself: print File.read("/Home/comics.txt")

            -

            What time was it when you changed the file? Let's check. Type: File.mtime("/Home/comics.txt")

            -
            \d{4}-\d+-\d+ \d{2}:\d{2}:\d{2} [+-]\d{4}
            -
            -
            -

            Just the Hour Hand

            -

            Great, there's the time. The precise time exactly when you added to the file. The mtime gives you a Ruby Time object.

            -

            If you want to check just what hour it was, hit the up arrow key and change the line to: File.mtime("/Home/comics.txt").hour

            -
            \d+
            ->>>>>>> nanothief/master -
            - -
            -

            Hallo, Who's There? And Summary #5 Waves Its Hat!

            -

            Well done, well done, well done, well done! Truly, truly, truly, truly, truuuuuuuuly!

            -

            Here's the last few minutes of your life in review:

            -
              -
            • Arguments. Arguments are a list of things sent into a method. With commas between.
            • -
            • We also spoke about do and end which are another way to make a block.
            • -
            -

            You totally know how to use Ruby now. I mean you've got down the essentials. You just need to keep learning more methods and - try out more complex blocks.

            -

            But there's one side of Ruby we haven't settled. Making your own methods and classes.

            -

            Ahem! Let's get it over with then.

            -
            -
            -

            In Ruby, Def Leppard Means Define Leppard (a Method)!

            -

            Hey, okay, you done it. You're making your own method. You started with def, followed by the name of the method. - And a list of arguments which the method will need. This isn't too scary and dangerous!

            -

            All we have to do is fill it up with Ruby and finish it up with end.

            -
            -
            -

            Hey, Cool, a Popup

            -

            Let's make a page of links. How about that? We'll need to load a little library I've made for you.

            -

            Type: require 'popup'

            -
            true
            -
            -
            -

            Browser Puppetry

            -

            Excellent, you've loaded the popup library.

            -

            The popup library contains a bunch of methods I've written which let you control a popup here on the Try Ruby site.

            -

            Here, try this: Popup.goto "http://google.com/"

            -
            \033\[1;JSm.*popup_goto\(.*\)\033\[m.*
            -
            -
            -

            Making Links and Spinning Webs

            -

            Our own lovely, little popup to manipulate. You can also fill it with your own goodies. We'll start small:

            -
            • Popup.make {
            • -
            •   h1 "My Links"
            • -
            •   link "Go to Google", "http://google.com/"
            • -
            • }
            • -
            -

            The term h1 (h-one) means a level-one header. In HTML, this is the largest size of header.

            -
            \033\[1;JSm.*popup_make\(.*h1.*a href.*\)\033\[m.*
            -
            -
            -

            Popups Are So Easy, It's Crazy

            -

            Looks good, you did it perfectly, just as you were asked. Let's make a list then.

            -

            Here's how you make a list with the popup library:

            -
            • Popup.make do
            • -
            •   h1 "Things To Do"
            • -
            •   list do
            • -
            •     p "Try out Ruby"
            • -
            •     p "Ride a tiger"
            • -
            •     p "(down River Euphrates)"
            • -
            •   end
            • -
            • end
            • -
            -

            The p method is short for "paragraph".

            -
            \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*li.*\)\033\[m.*
            -
            -
            -

            Spread the Comics on the Table

            -

            Okay, this is coming along wonderfully. This is simple stuff, but keep in mind that you didn't know any Ruby whatsoever just fifteen minutes ago!

            -

            Last -step. Let's tie it all together, you know? Let's make it chime together -like a very nice set of glistening chimes on the beach in the -maginificent sunlight!

            -

            Now, let's make a list of the links to each comic:

            -
            • Popup.make do
            • -
            •   h1 "Comics on the Web"
            • -
            •   list do
            • -
            •     comics.each do |name, url|
            • -
            •       link name, url
            • -
            •     end
            • -
            •   end
            • -
            • end
            • -
            -

            You can click on the links and read the comics in the little window even! Smashing!

            -
            \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*a href.*li.*a href.*\)\033\[m.*
            -
            -
            -

            Summary #6 Which Means You've Come So Far

            -

            You're a level six Ruby cleric. I mean what a great job you've done. Let's review:

            -
              -
            • You added your own method with def and you used that [coming soon]
            • -
            • You used the require method to load the popup library.
              By typing: require 'popup'
            • -
            • And if that wasn't enough, you made your own web page from a list of comics in a file no you havent. You made a real program!
            • -
            -

            So -what could possibly be next? What could you possibly have to learn now? -Ha, this is the best part. You've come such a long way that we're going -to uncover classes. For two more short lessons and you're done.

            -

            Earlier, we created a hash like this: Hash.new Try it.

            -
            \{\}
            -
            -
            -

            Not a School Class, a Working Class

            -

            You see, the empty curly braces {} is a shortcut for Hash.new. The new -method is used to make objects of a certain class. (Think "class" as in -"working class" — a specific group of objects which are similar, have -the same jobs, the same shirts.)

            -

            Ask yourself this: How would I make a blog in Ruby? -Where would you start? Well, you might store your blog entries in a -file, right? But how would you keep track of the title of the entry and -the time it was posted? And when you loaded the file, how would it look -in Ruby? Would it be a Hash? Or an Array? Or an Array of Arrays? Or -something else?

            I really think you'll want to use a class. You are already familiar with many classes: Hash, Array, String.

            -

            Let's make a new class: class BlogEntry.

            -
            ..
            -
            -
            -

            The Stuff Blogs are Made of

            -

            You've opened up a new BlogEntry class. What is your blog entry made of? A title, sure. Also, a time when the entry was posted. The - full text of the entry.

            -

            We'll do a mood setting, too, just like LiveJournal. The Internet has really brought back stick people and smileys - out of bankruptcy. Emote!

            -

            Okay, so you've got the first line of the class, here's the rest:

            -
            • class BlogEntry
            • -
            •   attr_accessor :title, :time, :fulltext, :mood
            • -
            • end
            • -
            -
            nil
            -
            -
            -

            Accessors Are the Dangling Limbs

            -

            Hey, good class, man. You've got a new BlogEntry class. To start an entry:
            entry = BlogEntry.new.

            -

            In the class definition, you used a method called attr_accessor. There are many attribute methods like - this which add little settings to classes. These attributes are just variables attached to a class.

            -

            Think -of it this way. A class is like a person. That star-shaped human thing -out there. And the attributes are the dangling limbs, the different -parts that make up a body.

            -

            To set the title of your entry: entry.title = "Today Mt. Hood Was Stolen!"

            -
            ".+"
            -
            -
            -

            An Object, That Neat Little Package

            -

            Go ahead and set the post time: entry.time = Time.now

            -

            And the mood: entry.mood = :sick

            -

            And the post itself: entry.fulltext = "I can't believe Mt. Hood was stolen! I am speechless! It was stolen by a giraffe who drove away - in his Cadillac Seville very nonchalant!!"

            -

            To see all your settings, just type at the prompt: entry.

            -
            #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
            -
            -
            -

            Quickening it Up

            -

            Cool, -you're blog is awesome. Hey, let's make things a bit easier on you. -You're not going to want to set the time like that every time you post. -You just want to type in the title and the entry and the mood quickly, -right?

            -

            Let's add an initialize method.

            -
            • class BlogEntry
            • -
            •   def initialize( title, mood, fulltext )
            • -
            •     @time = Time.now
            • -
            •     @title, @mood, @fulltext = title, mood, fulltext
            • -
            •   end
            • -
            • end
            • -
            -

            Once you've got that typed in, try making a new entry: BlogEntry.new

            -
            ArgumentError: wrong number of arguments \(0 for 3\).*
            -
            -
            -

            You've Taught Your Blog to Reject Worthless Things

            -

            Did you see how inside the class we used the at-symbols? Like this: @time = Time.now

            -

            Outside the class, we use accessors: entry.time = Time.now But inside we use instance variables: @time = Time.now - They're the exact same thing, but expressed in two different places of your program.

            -

            Your blog now needs a title, a mood and a post in order to work. When a new BlogEntry is created, the initialize method - is used to check for any arguments to new. Uh, we need three arguments!

            -

            Try it again with all three.

            -

            entry2 -= BlogEntry.new( "I Left my Hoodie on the Mountain!", :confused, "I am -never going back to that mountain and I hope a giraffe steals it." )

            -
            #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
            -
            -
            -

            A Giraffe Has Not Stolen Summary #7

            -

            Aha, you're here. And all in one piece. We're still going to make your blog real, but until then, let's review, okay?

            -
              -
            • Classes. Everything in Ruby is some kind of object. Classes explain objects. How a certain object works. - For example, you made a few blog entry objects and these objects are explained in the BlogEntry class. - In other words: you call them BlogEntry objects.
            • -
            • Accessors are variables attached to an object which can be used outside the object. (entry.time = Time.now)
            • -
            • Instance variables are the same variables you're using for accessors when inside the object. - Like in a method definition. (@time = Time.now)
            • -
            -

            Okay, -let's wrap things up, kid. Here's the last chapter of the GRIPPING epic -story of Try Ruby! Now that you've got a taste of how it all works, how -are you going to use it around the house and in your grocer's freezer? -You're a great person (one of my favorites), but you need guidance.

            -

            Let's finish your blog. You have blog entries, but no actual blog.

            -

            Put the entries into an array: blog = [entry, entry2]

            -
            \[#.BlogEntry:0x[0-9a-f]+.*, #.BlogEntry:0x[0-9a-f]+.*\]
            -
            -
            -

            It's All About Combining Things

            -

            Some -beautiful things can be done with the simple parts of Ruby, especially -when you combine them together into new things. Here we've got a blog -made of an array of classes. And, actually, Ruby really does good with -this kind of creature.

            -

            Here's a few things you can do with your array blog:

            -
            • You'll want to sort your entries from newest to oldest. You can do this with:
              - blog.sort_by { |entry| entry.time }.reverse
              See the sort_by explanation for more.
            • -
            • If you want to search your blog for anything related to "cadillac":
              - blog.find_all { |entry| entry.fulltext.match(/cadillac/i) }
              - Read all about find_all - and match - to figure out how that works. Also: the slashy /giraffe/i is a Regexp object, used for matching words.
            • -
            • Add new entries with blog << new_entry
              - And check out the << method documentation.
            • -
            -

            You can browse a list of all Ruby's built-in methods at ruby-doc.org's core list. - Another good list is at the online pickaxe.

            -

            One really useful method (I probably use this more than anything else) is map. Type: blog.map { |entry| entry.mood }

            -
            \[(:\w+, )+:\w+\]
            -
            -
            -

            Look at His Face — The Transformation Has Begun

            -

            The map method cycles through an array and replaces each item with something new. Say you wanted to replace each of your blog entries - with the name Bruce Willis. Do it so: blog.map { "Bruce Willis" }

            -

            Since the block always returns the string "Bruce Willis", that's what you get. In the code you just used, the entry was swapped out - for only the entry.mood.

            -

            Now, -I want you to make a popup with your blog entries. I'm not going to -give you all of the code. I'm just going to give you part of it.

            -
            • blog.each do |entry|
            • -
            •   h2 entry.title
            • -
            •   p entry.fulltext
            • -
            • end
            • -
            -

            Now, I expect you to put the popup code around it and add an h1 title with the name of your blog. For extra haroompf, have the time of each entry display.

            -
            \033\[1;JSm.*popup_make\(.*h1.*h2.*li.*h2.*li.*\)\033\[m.*
            -
            -
            -

            You are Some Kind of Web Guru, I Have Stars in My Eyes

            -

            Good, -that's it! This is exactly the code you can use to write your own real -Ruby blog. If you're feeling adventurous, I'd check out the Rails videos which show a swift young fellow creating a blog in 15 minutes. You just sit back and watch.

            -

            I -should mention Rails. You have been learning the Ruby language, how to -speak it. But Rails is a bunch of libraries (sort of like the popup -library we've been using.) It's a very powerful toolkit for building -websites. If you're interested in learning about Rails, I would head - over there right away. Start using your Ruby skills proper!

            -

            One thing Rails has is easy methods for dates. Like, try: Time.now - 2.weeks

            -
            class Integer; def weeks; self * 7*24*60*60; end; end
            -
            \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-+]\d{4}
            -
            -
            -

            Summary #8, The Hey-Relax-You-Did-Good Summary

            -

            This last section took a moment to wind down, to give you some pointers as to how you can use Ruby. If you enjoyed yourself, - download Ruby and install it.

            - -

            Once you have Ruby installed, you can use Interactive Ruby by running irb on your system's prompt. For more on Irb, - there's The Tiger's Vest to help you.

            -

            You -really deserve a double-layer cake with double-double frosting and a -guy playing one of those guitars that's a double guitar. I mean you -finished, you really did! No doubt about it, you're a certified -red-blooded smartiac!

            -
            -
            - diff --git a/TryRuby/public/tutorials/intro_files/sick.gif b/TryRuby/public/tutorials/intro_files/sick.gif deleted file mode 100755 index 217a67cbae60740fdc90b92e06b977cf7fc56699..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 94 zcmZ?wbhEHb|6B "37" - assigns(:irb).should be(mock_irb) - end - end - - describe "GET new" do - it "assigns a new irb as @irb" do - Irb.stub(:new) { mock_irb } - get :new - assigns(:irb).should be(mock_irb) - end - end - - describe "GET edit" do - it "assigns the requested irb as @irb" do - Irb.stub(:find).with("37") { mock_irb } - get :edit, :id => "37" - assigns(:irb).should be(mock_irb) - end - end - - describe "POST create" do - describe "with valid params" do - it "assigns a newly created irb as @irb" do - Irb.stub(:new).with({'these' => 'params'}) { mock_irb(:save => true) } - post :create, :irb => {'these' => 'params'} - assigns(:irb).should be(mock_irb) - end - - it "redirects to the created irb" do - Irb.stub(:new) { mock_irb(:save => true) } - post :create, :irb => {} - response.should redirect_to(irb_url(mock_irb)) - end - end - - describe "with invalid params" do - it "assigns a newly created but unsaved irb as @irb" do - Irb.stub(:new).with({'these' => 'params'}) { mock_irb(:save => false) } - post :create, :irb => {'these' => 'params'} - assigns(:irb).should be(mock_irb) - end - - it "re-renders the 'new' template" do - Irb.stub(:new) { mock_irb(:save => false) } - post :create, :irb => {} - response.should render_template("new") - end - end - end - - describe "PUT update" do - describe "with valid params" do - it "updates the requested irb" do - Irb.stub(:find).with("37") { mock_irb } - mock_irb.should_receive(:update_attributes).with({'these' => 'params'}) - put :update, :id => "37", :irb => {'these' => 'params'} - end - - it "assigns the requested irb as @irb" do - Irb.stub(:find) { mock_irb(:update_attributes => true) } - put :update, :id => "1" - assigns(:irb).should be(mock_irb) - end - - it "redirects to the irb" do - Irb.stub(:find) { mock_irb(:update_attributes => true) } - put :update, :id => "1" - response.should redirect_to(irb_url(mock_irb)) - end - end - - describe "with invalid params" do - it "assigns the irb as @irb" do - Irb.stub(:find) { mock_irb(:update_attributes => false) } - put :update, :id => "1" - assigns(:irb).should be(mock_irb) - end - - it "re-renders the 'edit' template" do - Irb.stub(:find) { mock_irb(:update_attributes => false) } - put :update, :id => "1" - response.should render_template("edit") - end - end - end - - describe "DELETE destroy" do - it "destroys the requested irb" do - Irb.stub(:find).with("37") { mock_irb } - mock_irb.should_receive(:destroy) - delete :destroy, :id => "37" - end - - it "redirects to the irb list" do - Irb.stub(:find) { mock_irb } - delete :destroy, :id => "1" - response.should redirect_to(irb_url) - end - end - -end diff --git a/TryRuby/spec/controllers/public_controller_spec.rb b/TryRuby/spec/controllers/public_controller_spec.rb deleted file mode 100644 index 61a96a3..0000000 --- a/TryRuby/spec/controllers/public_controller_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'spec_helper' - -describe PublicController do - -end diff --git a/TryRuby/spec/helpers/classic_helper_spec.rb b/TryRuby/spec/helpers/classic_helper_spec.rb deleted file mode 100644 index 2614b0f..0000000 --- a/TryRuby/spec/helpers/classic_helper_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'spec_helper' - -# Specs in this file have access to a helper object that includes -# the ClassicHelper. For example: -# -# describe ClassicHelper do -# describe "string concat" do -# it "concats two strings with spaces" do -# helper.concat_strings("this","that").should == "this that" -# end -# end -# end -describe ClassicHelper do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/TryRuby/spec/helpers/irb_helper_spec.rb b/TryRuby/spec/helpers/irb_helper_spec.rb deleted file mode 100644 index 325a0b0..0000000 --- a/TryRuby/spec/helpers/irb_helper_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'spec_helper' - -# Specs in this file have access to a helper object that includes -# the IrbHelper. For example: -# -# describe IrbHelper do -# describe "string concat" do -# it "concats two strings with spaces" do -# helper.concat_strings("this","that").should == "this that" -# end -# end -# end -describe IrbHelper do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/TryRuby/spec/helpers/public_helper_spec.rb b/TryRuby/spec/helpers/public_helper_spec.rb deleted file mode 100644 index 434276a..0000000 --- a/TryRuby/spec/helpers/public_helper_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'spec_helper' - -# Specs in this file have access to a helper object that includes -# the PublicHelper. For example: -# -# describe PublicHelper do -# describe "string concat" do -# it "concats two strings with spaces" do -# helper.concat_strings("this","that").should == "this that" -# end -# end -# end -describe PublicHelper do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/TryRuby/spec/models/irb_spec.rb b/TryRuby/spec/models/irb_spec.rb deleted file mode 100644 index 26e0fa0..0000000 --- a/TryRuby/spec/models/irb_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'spec_helper' - -describe Irb do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/TryRuby/spec/requests/irb_spec.rb b/TryRuby/spec/requests/irb_spec.rb deleted file mode 100644 index d0c7946..0000000 --- a/TryRuby/spec/requests/irb_spec.rb +++ /dev/null @@ -1,11 +0,0 @@ -require 'spec_helper' - -describe "Irb" do - describe "GET /irb" do - it "works! (now write some real specs)" do - # Run the generator again with the --webrat flag if you want to use webrat methods/matchers - get irb_path - response.status.should be(200) - end - end -end diff --git a/TryRuby/spec/routing/irb_routing_spec.rb b/TryRuby/spec/routing/irb_routing_spec.rb deleted file mode 100644 index 25ea295..0000000 --- a/TryRuby/spec/routing/irb_routing_spec.rb +++ /dev/null @@ -1,35 +0,0 @@ -require "spec_helper" - -describe IrbController do - describe "routing" do - - it "recognizes and generates #index" do - { :get => "/irb" }.should route_to(:controller => "irb", :action => "index") - end - - it "recognizes and generates #new" do - { :get => "/irb/new" }.should route_to(:controller => "irb", :action => "new") - end - - it "recognizes and generates #show" do - { :get => "/irb/1" }.should route_to(:controller => "irb", :action => "show", :id => "1") - end - - it "recognizes and generates #edit" do - { :get => "/irb/1/edit" }.should route_to(:controller => "irb", :action => "edit", :id => "1") - end - - it "recognizes and generates #create" do - { :post => "/irb" }.should route_to(:controller => "irb", :action => "create") - end - - it "recognizes and generates #update" do - { :put => "/irb/1" }.should route_to(:controller => "irb", :action => "update", :id => "1") - end - - it "recognizes and generates #destroy" do - { :delete => "/irb/1" }.should route_to(:controller => "irb", :action => "destroy", :id => "1") - end - - end -end diff --git a/TryRuby/spec/spec_helper.rb b/TryRuby/spec/spec_helper.rb deleted file mode 100644 index 9b8b02c..0000000 --- a/TryRuby/spec/spec_helper.rb +++ /dev/null @@ -1,27 +0,0 @@ -# This file is copied to spec/ when you run 'rails generate rspec:install' -ENV["RAILS_ENV"] ||= 'test' -require File.expand_path("../../config/environment", __FILE__) -require 'rspec/rails' - -# Requires supporting ruby files with custom matchers and macros, etc, -# in spec/support/ and its subdirectories. -Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} - -RSpec.configure do |config| - # == Mock Framework - # - # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line: - # - # config.mock_with :mocha - # config.mock_with :flexmock - # config.mock_with :rr - config.mock_with :rspec - - # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures - config.fixture_path = "#{::Rails.root}/spec/fixtures" - - # If you're not using ActiveRecord, or you'd prefer not to run each of your - # examples within a transaction, remove the following line or assign false - # instead of true. - config.use_transactional_fixtures = true -end diff --git a/TryRuby/spec/views/irb/edit.html.erb_spec.rb b/TryRuby/spec/views/irb/edit.html.erb_spec.rb deleted file mode 100644 index 5b63112..0000000 --- a/TryRuby/spec/views/irb/edit.html.erb_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'spec_helper' - -describe "irb/edit.html.erb" do - before(:each) do - @irb = assign(:irb, stub_model(Irb)) - end - - it "renders the edit irb form" do - render - - # Run the generator again with the --webrat flag if you want to use webrat matchers - assert_select "form", :action => irb_path(@irb), :method => "post" do - end - end -end diff --git a/TryRuby/spec/views/irb/index.html.erb_spec.rb b/TryRuby/spec/views/irb/index.html.erb_spec.rb deleted file mode 100644 index 193368a..0000000 --- a/TryRuby/spec/views/irb/index.html.erb_spec.rb +++ /dev/null @@ -1,14 +0,0 @@ -require 'spec_helper' - -describe "irb/index.html.erb" do - before(:each) do - assign(:irb, [ - stub_model(Irb), - stub_model(Irb) - ]) - end - - it "renders a list of irb" do - render - end -end diff --git a/TryRuby/spec/views/irb/new.html.erb_spec.rb b/TryRuby/spec/views/irb/new.html.erb_spec.rb deleted file mode 100644 index ca7c0ad..0000000 --- a/TryRuby/spec/views/irb/new.html.erb_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'spec_helper' - -describe "irb/new.html.erb" do - before(:each) do - assign(:irb, stub_model(Irb).as_new_record) - end - - it "renders new irb form" do - render - - # Run the generator again with the --webrat flag if you want to use webrat matchers - assert_select "form", :action => irb_path, :method => "post" do - end - end -end diff --git a/TryRuby/spec/views/irb/show.html.erb_spec.rb b/TryRuby/spec/views/irb/show.html.erb_spec.rb deleted file mode 100644 index 9a12d28..0000000 --- a/TryRuby/spec/views/irb/show.html.erb_spec.rb +++ /dev/null @@ -1,11 +0,0 @@ -require 'spec_helper' - -describe "irb/show.html.erb" do - before(:each) do - @irb = assign(:irb, stub_model(Irb)) - end - - it "renders attributes in

            " do - render - end -end diff --git a/TryRuby/vendor/plugins/.gitkeep b/TryRuby/vendor/plugins/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/tryruby/Gemfile b/tryruby/Gemfile deleted file mode 100644 index 668de60..0000000 --- a/tryruby/Gemfile +++ /dev/null @@ -1,46 +0,0 @@ -source 'http://rubygems.org' - -gem 'rails', '3.0.5' - -# Bundle edge Rails instead: -# gem 'rails', :git => 'git://github.com/rails/rails.git' - -gem 'mysql2' -gem 'fakefs', '0.2.1', :git => "http://github.com/defunkt/fakefs.git", :ref => "aa0cb96b8ebc81287a2e", :require => 'fakefs/safe' -# Use unicorn as the web server -# gem 'unicorn' -gem 'i18n' -# Deploy with Capistrano -# gem 'capistrano' - -gem 'devise' - -# To use debugger (ruby-debug for Ruby 1.8.7+, ruby-debug19 for Ruby 1.9.2+) -# gem 'ruby-debug' -# gem 'ruby-debug19', :require => 'ruby-debug' -gem 'jquery-rails' -gem 'ruby_parser' -gem 'racc' - -#gem 'ruby2ruby' -#gem 'newrelic_rpm' -#gem 'madmimi' -#gem 'delayed_job' -#gem 'dalli' -# Bundle the extra gems: -# gem 'bj' - -gem 'nokogiri' -# gem 'sqlite3-ruby', :require => 'sqlite3' -# gem 'aws-s3', :require => 'aws/s3' - -# Bundle gems for the local environment. Make sure to -# put test-only gems in this group so their generators -# and rake tasks are available in development mode: -# group :development, :test do - gem 'capybara' - gem 'rspec-rails' - gem 'cucumber-rails' - #gem 'factory-girl' - -# end diff --git a/tryruby/README b/tryruby/README deleted file mode 100644 index fe7013d..0000000 --- a/tryruby/README +++ /dev/null @@ -1,256 +0,0 @@ -== Welcome to Rails - -Rails is a web-application framework that includes everything needed to create -database-backed web applications according to the Model-View-Control pattern. - -This pattern splits the view (also called the presentation) into "dumb" -templates that are primarily responsible for inserting pre-built data in between -HTML tags. The model contains the "smart" domain objects (such as Account, -Product, Person, Post) that holds all the business logic and knows how to -persist themselves to a database. The controller handles the incoming requests -(such as Save New Account, Update Product, Show Post) by manipulating the model -and directing data to the view. - -In Rails, the model is handled by what's called an object-relational mapping -layer entitled Active Record. This layer allows you to present the data from -database rows as objects and embellish these data objects with business logic -methods. You can read more about Active Record in -link:files/vendor/rails/activerecord/README.html. - -The controller and view are handled by the Action Pack, which handles both -layers by its two parts: Action View and Action Controller. These two layers -are bundled in a single package due to their heavy interdependence. This is -unlike the relationship between the Active Record and Action Pack that is much -more separate. Each of these packages can be used independently outside of -Rails. You can read more about Action Pack in -link:files/vendor/rails/actionpack/README.html. - - -== Getting Started - -1. At the command prompt, create a new Rails application: - rails new myapp (where myapp is the application name) - -2. Change directory to myapp and start the web server: - cd myapp; rails server (run with --help for options) - -3. Go to http://localhost:3000/ and you'll see: - "Welcome aboard: You're riding Ruby on Rails!" - -4. Follow the guidelines to start developing your application. You can find -the following resources handy: - -* The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html -* Ruby on Rails Tutorial Book: http://www.railstutorial.org/ - - -== Debugging Rails - -Sometimes your application goes wrong. Fortunately there are a lot of tools that -will help you debug it and get it back on the rails. - -First area to check is the application log files. Have "tail -f" commands -running on the server.log and development.log. Rails will automatically display -debugging and runtime information to these files. Debugging info will also be -shown in the browser on requests from 127.0.0.1. - -You can also log your own messages directly into the log file from your code -using the Ruby logger class from inside your controllers. Example: - - class WeblogController < ActionController::Base - def destroy - @weblog = Weblog.find(params[:id]) - @weblog.destroy - logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!") - end - end - -The result will be a message in your log file along the lines of: - - Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1! - -More information on how to use the logger is at http://www.ruby-doc.org/core/ - -Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are -several books available online as well: - -* Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe) -* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide) - -These two books will bring you up to speed on the Ruby language and also on -programming in general. - - -== Debugger - -Debugger support is available through the debugger command when you start your -Mongrel or WEBrick server with --debugger. This means that you can break out of -execution at any point in the code, investigate and change the model, and then, -resume execution! You need to install ruby-debug to run the server in debugging -mode. With gems, use sudo gem install ruby-debug. Example: - - class WeblogController < ActionController::Base - def index - @posts = Post.find(:all) - debugger - end - end - -So the controller will accept the action, run the first line, then present you -with a IRB prompt in the server window. Here you can do things like: - - >> @posts.inspect - => "[#nil, "body"=>nil, "id"=>"1"}>, - #"Rails", "body"=>"Only ten..", "id"=>"2"}>]" - >> @posts.first.title = "hello from a debugger" - => "hello from a debugger" - -...and even better, you can examine how your runtime objects actually work: - - >> f = @posts.first - => #nil, "body"=>nil, "id"=>"1"}> - >> f. - Display all 152 possibilities? (y or n) - -Finally, when you're ready to resume execution, you can enter "cont". - - -== Console - -The console is a Ruby shell, which allows you to interact with your -application's domain model. Here you'll have all parts of the application -configured, just like it is when the application is running. You can inspect -domain models, change values, and save to the database. Starting the script -without arguments will launch it in the development environment. - -To start the console, run rails console from the application -directory. - -Options: - -* Passing the -s, --sandbox argument will rollback any modifications - made to the database. -* Passing an environment name as an argument will load the corresponding - environment. Example: rails console production. - -To reload your controllers and models after launching the console run -reload! - -More information about irb can be found at: -link:http://www.rubycentral.com/pickaxe/irb.html - - -== dbconsole - -You can go to the command line of your database directly through rails -dbconsole. You would be connected to the database with the credentials -defined in database.yml. Starting the script without arguments will connect you -to the development database. Passing an argument will connect you to a different -database, like rails dbconsole production. Currently works for MySQL, -PostgreSQL and SQLite 3. - -== Description of Contents - -The default directory structure of a generated Ruby on Rails application: - - |-- app - | |-- controllers - | |-- helpers - | |-- mailers - | |-- models - | `-- views - | `-- layouts - |-- config - | |-- environments - | |-- initializers - | `-- locales - |-- db - |-- doc - |-- lib - | `-- tasks - |-- log - |-- public - | |-- images - | |-- javascripts - | `-- stylesheets - |-- script - |-- test - | |-- fixtures - | |-- functional - | |-- integration - | |-- performance - | `-- unit - |-- tmp - | |-- cache - | |-- pids - | |-- sessions - | `-- sockets - `-- vendor - `-- plugins - -app - Holds all the code that's specific to this particular application. - -app/controllers - Holds controllers that should be named like weblogs_controller.rb for - automated URL mapping. All controllers should descend from - ApplicationController which itself descends from ActionController::Base. - -app/models - Holds models that should be named like post.rb. Models descend from - ActiveRecord::Base by default. - -app/views - Holds the template files for the view that should be named like - weblogs/index.html.erb for the WeblogsController#index action. All views use - eRuby syntax by default. - -app/views/layouts - Holds the template files for layouts to be used with views. This models the - common header/footer method of wrapping views. In your views, define a layout - using the layout :default and create a file named default.html.erb. - Inside default.html.erb, call <% yield %> to render the view using this - layout. - -app/helpers - Holds view helpers that should be named like weblogs_helper.rb. These are - generated for you automatically when using generators for controllers. - Helpers can be used to wrap functionality for your views into methods. - -config - Configuration files for the Rails environment, the routing map, the database, - and other dependencies. - -db - Contains the database schema in schema.rb. db/migrate contains all the - sequence of Migrations for your schema. - -doc - This directory is where your application documentation will be stored when - generated using rake doc:app - -lib - Application specific libraries. Basically, any kind of custom code that - doesn't belong under controllers, models, or helpers. This directory is in - the load path. - -public - The directory available for the web server. Contains subdirectories for - images, stylesheets, and javascripts. Also contains the dispatchers and the - default HTML files. This should be set as the DOCUMENT_ROOT of your web - server. - -script - Helper scripts for automation and generation. - -test - Unit and functional tests along with fixtures. When using the rails generate - command, template test files will be generated for you and placed in this - directory. - -vendor - External libraries that the application depends on. Also includes the plugins - subdirectory. If the app has frozen rails, those gems also go here, under - vendor/rails/. This directory is in the load path. diff --git a/tryruby/Rakefile b/tryruby/Rakefile deleted file mode 100644 index 79dd5f3..0000000 --- a/tryruby/Rakefile +++ /dev/null @@ -1,7 +0,0 @@ -# Add your own tasks in files placed in lib/tasks ending in .rake, -# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. - -require File.expand_path('../config/application', __FILE__) -require 'rake' - -TryRuby::Application.load_tasks diff --git a/tryruby/app/controllers/application_controller.rb b/tryruby/app/controllers/application_controller.rb deleted file mode 100644 index b0f4608..0000000 --- a/tryruby/app/controllers/application_controller.rb +++ /dev/null @@ -1,24 +0,0 @@ -# Filters added to this controller apply to all controllers in the application. -# Likewise, all the methods added will be available for all controllers. -require './lib/tryruby' - -class ApplicationController < ActionController::Base -# attr_accessor :past_commands, :current_statement, :start_time -=begin - #attr_accessor :session - TryRuby.session = session - - TryRuby.session['start_time'] ||= Time.now - TryRuby.session['current_statement'] ||= '' - TryRuby.session['past_commands'] ||= '' - - helper :all # include all helpers, all the time - protect_from_forgery # See ActionController::RequestForgeryProtection for details - - # Scrub sensitive parameters from your log - # filter_parameter_logging :password - #class << self -=end -# not needed - #end -end diff --git a/tryruby/app/controllers/tryruby_controller.rb b/tryruby/app/controllers/tryruby_controller.rb deleted file mode 100644 index 912866a..0000000 --- a/tryruby/app/controllers/tryruby_controller.rb +++ /dev/null @@ -1,26 +0,0 @@ -class TryrubyController < ApplicationController - layout 'tryruby' - - def run - @cmd=params[:cmd] - - @a= run_script(@cmd) -@b = "handleJSON({\"type\": #{@a.type.to_json}, \"output\":#{@a.output.to_json},\"result\":#{@a.result.inspect.to_json}, \"error\": #{@a.error.inspect.to_json}})" - - render :json => @b - end - - private - - def run_script(command) - # output = begin - # eval(command) - # rescue StandardError => e - # e.message + ". On the " - - TryRuby.run_line(command) - # end - - # return "=> #{output}" + ", says yoda" - end -end diff --git a/tryruby/app/controllers/tutorials_controller.rb b/tryruby/app/controllers/tutorials_controller.rb deleted file mode 100644 index 662aa01..0000000 --- a/tryruby/app/controllers/tutorials_controller.rb +++ /dev/null @@ -1,6 +0,0 @@ -class TutorialsController < ApplicationController - - def intro - - end -end diff --git a/tryruby/app/helpers/application_helper.rb b/tryruby/app/helpers/application_helper.rb deleted file mode 100644 index d995b05..0000000 --- a/tryruby/app/helpers/application_helper.rb +++ /dev/null @@ -1,18 +0,0 @@ -module ApplicationHelper - - def google_analytics_js - ua_code = "UA-2365371-3" - '' - - end - -end diff --git a/tryruby/app/views/layouts/tryruby.rhtml b/tryruby/app/views/layouts/tryruby.rhtml deleted file mode 100644 index 2600200..0000000 --- a/tryruby/app/views/layouts/tryruby.rhtml +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - try ruby! (in your browser) - - - - - - - - - - - - - - - - - - - - - -

            -
            -
            - - - <%= render :partial => 'tryruby/donate' %> - - -
            -
            - -

            A Popup Browser

            -

            [x]

            -
            - - - -
            - - - -
            - - -
            -
            -
            -
            -
            -
            -
            -
            -
            -
            -
            -

            Got 15 minutes? Give Ruby a shot right now!

            -

            Ruby is a programming language from Japan - (available at ruby-lang.org) - which is revolutionizing the web. - The beauty of Ruby is found in its balance between simplicity and power.

            - -

            Try out Ruby code in the prompt above. In addition - to Ruby's builtin methods, the following commands are available:

            -
              -
            • help - Start the 15 minute interactive tutorial. Trust me, it's very basic!
            • -
            • help 2 - Hop to chapter two.
            • - -
            • clear - Clear screen. Useful if your browser starts slowing down. - Your command history will be remembered. -
            • back - Go back one screen in the tutorial.
            • -
            • reset - Reset the interpreter if you get too deep. (or Ctrl-D!)
            • -
            • next -Allows you to skip to the next section of a lesson.
            • - -
            • time - A stopwatch. Prints the time your session has been open.
            • -
            -

            If you happen to leave or refresh the page, your session will still be here for - unless it is left inactive for ten minutes.

            -
            -
            -
            - -
            -
            Trapped in double dots? A quote or something was left open. Type: reset or hit Ctrl-D.
            -
            - -

            This place is maintained by Andrew McElroy and David Miani and Orangea. For support issues, please post a ticket or contact Sophrinix on github. -

            - -
            - - - - - - - - -Please Support
            Try Ruby!
            - - - diff --git a/tryruby/app/views/layouts/tryruby2.html.erb b/tryruby/app/views/layouts/tryruby2.html.erb deleted file mode 100644 index fbdd73e..0000000 --- a/tryruby/app/views/layouts/tryruby2.html.erb +++ /dev/null @@ -1,147 +0,0 @@ - - - - Try Haskell! An interactive tutorial in your browser - - - - - - - - - - - - -
            -
            -
            -
            -
            -

            Try Haskell! An interactive tutorial in your - browser

            - -
            - -
            -
            -
            - -

            A Popup Browser

            -

            [x]

            -
            - <%= yield %> - - -
            -
            - -
            -
            -
            -
            -
            -
            - -
            -
            -
            -
            -
            -
            -
            -
            -
            -
            -
            -
            -
            -
            -
            -
            -

            - Welcome to your first taste of Haskell! Let's try Haskell right now! -

            -

            Beginners

            -
            -

            Type help to start the - tutorial. Type lessons to see the - list of lessons.

            -

            Or try typing these out and see what happens - (click to insert):

            -
              -
            • - 23*36 -
            • -
            • - reverse "hello" -
            • -
            -
            -
            -

            Learn More

            -
            -

            - Real World Haskell! - Get stuck into a book with - Real - World Haskell - (readable online!), published by O'Reilly Media. - Checkout - Haskell.org - for more information about Haskell.

            -
            -
            -
            -
            -
            -
            -
            -
            -
            - -
            -
            - - diff --git a/tryruby/app/views/tryruby/index.rhtml b/tryruby/app/views/tryruby/index.rhtml deleted file mode 100644 index c95b8f7..0000000 --- a/tryruby/app/views/tryruby/index.rhtml +++ /dev/null @@ -1,11 +0,0 @@ - -
            -
            -
            -
            -
            -
            -
            -
            - - diff --git a/tryruby/app/views/tutorials/es_intro.html b/tryruby/app/views/tutorials/es_intro.html deleted file mode 100644 index 6a8e773..0000000 --- a/tryruby/app/views/tutorials/es_intro.html +++ /dev/null @@ -1,666 +0,0 @@ - -
            -

            Usando El Prompt

            -

            La ventana azul de arriba es el prompt de Ruby. ¡Escribe una línea de código Ruby, aprieta Enter - y velo correr!

            -

            Por ejemplo, trata de escribir algo matemático. Como: 2 + 6

            -
            \d+
            -
            -
            -

            Números & Matemática

            -

            ¡Bien! Hiciste algo de matemática. ¿Ves como la respuesta salta a la vista?

            -

            Ruby reconoce números y símbolos matemáticos. Puedes probar otras cosas como:

            -
            • 4 * 10
            • -
            • 5 - 12
            • -
            • 40 / 4
            -

            Seguro, las computadoras son habilidosas y rápidas con las matemáticas. Sigamos... ¿Quieres ver tu nombre al revés? - Escribe tu primer nombre entre comillas así: "Jimmy"

            -
            "(\w+)"
            -
            -
            -

            Decir Tu Nombre Al Revés

            -

            Perfecto, has formado un string de las letras de tu nombre. Un string - es un juego de caracteres que la computadora puede procesar.

            -

            Imagina que las letras están en una cuerda donde - se cuelga la ropa y las comillas son los broches que sostienen los bordes. Las comillas marcan el comienzo y el final.

            -

            Para invertir tu nombre, escribe: "Jimmy".reverse (¡No olvides el punto!)

            -
            "(\w+)"
            -
            -
            -

            Contando Las Letras

            -

            ¡Has usado el método reverse sobre tu nombre! Poniendo tu nombre entre comillas, - hiciste un string. Luego llamaste al método reverse, que funciona sobre un string cambiando - todas las letras de atrás para adelante.

            -

            Ahora, vamos a ver cuantas letras tiene tu nombre: "Jimmy".length

            -
            \d+
            -
            -
            -

            Repitiendo

            -

            Ahora, estoy seguro que te estarás preguntando para que sirve todo esto. Bueno, estoy seguro que habrás estado en alguna - pagina web donde te gritaron, ¡Hey, tu password es muy corto! Ves, algunos programas - usan este código tan simple.

            -

            Mira esto. Vamos a multiplicar tu nombre por 5. "Jimmy" * 5

            -
            "(\w+)"
            -
            -
            -

            Hey, Sumario #1 Listo

            -

            Vamos a ver que es lo que has aprendido en el primer minuto.

            -
              -
            • El prompt. Escribiendo código en el prompt verde obtienes - una respuesta del prompt rojo. Todo código te da una respuesta.
            • -
            • Números y strings son objetos matemáticos y de texto de Ruby.
            • -
            • Métodos Has usado métodos en Ingles como reverse - y métodos simbólicos como * (el método de multiplicación.) ¡Los métodos son acciones!
            • -
            -

            Esta es la esencia del aprendizaje. Tomar cosas simples, jugar con ellas - y trasformarlas en cosas nuevas. ¿Te sientes cómodo con todo? Te aseguro que lo estas.

            -

            Bien, vamos a hacer algo incomodo. Trata de invertir un número: 40.reverse

            -
            NoMethodError: undefined method `reverse' for (\d+):Fixnum
            -
            -
            -

            ¡Basta, Te Volviste Loco!

            -

            No puedes invertir el numero cuarenta. Supongo que puedes poner tu monitor en - frente de un espejo, pero invertir un numero no tiene sentido. Ruby lanza un - mensaje de error. Ruby te dice que no hay un método reverse para los números.

            -

            Tal vez si lo conviertes en un string: 40.to_s.reverse.

            -
            \"(\d+)\"
            -
            -
            -

            Los Chicos Son Diferentes De Las Chicas

            -

            Y los números son diferentes de los strings. Aunque puedes usar métodos en cualquier objeto - en Ruby, algunos métodos solo funcionan en cierto tipo de cosas. Pero siempre puedes - convertir entre diferentes tipos usando el método "to" de Ruby.

            -
            • to_s convierte cosas a strings.
            • -
            • to_i convierte cosas a integers (números.)
            • -
            • to_a convierte cosas a arrays.
            • -
            -

            ¿Que son los arrays?! Son listas. Escribe entre un par de corchetes: [].

            -
            \[\]
            -
            -
            -

            Mantenerse en Cola

            -

            Genial, eso es una lista vacía. Las listas guardan cosas en orden. - Como esperando en la cola para palomitas de maíz. Estas atrás de alguien y jamás - pensarías en empujarlo a un costado, ¿no es así? Y con respecto al tipo detrás de ti, - mantienes un ojo sobre el, ¿correcto?

            -

            Acá hay una lista para ti. Números de la lotería: [12, 47, 35].

            -
            \[(\d+(, )?){2,}\]
            -
            -
            -

            Uno Levanta La Mano

            -

            Una lista de números de la lotería. ¿Cual es el mayor?

            -

            Prueba: [12, 47, 35].max.

            -
            (\d+)
            -
            -
            -

            Manteniendo la Lista

            -

            Bien, bien. Pero es un fastidio el tener que reescribir esa lista, ¿no es así?

            -

            Guardemos nuestros números en un ticket de esta manera: ticket = [12, 47, 35]

            -
            \[(\d+(, )?){2,}\]
            -
            -
            -

            Ahora Escribe Ticket

            -

            Ahora, escribe: ticket

            -
            \[(\d+(, )?){2,}\]
            -
            -
            -

            Guardado, Escondido

            -

            ¡Fantástico! Te has aferrado a tus números de la lotería, escondiéndolos dentro de una - variable llamada ticket.

            -

            Vamos a poner tus números en orden, que te parece? Usa: ticket.sort!

            -
            \[(\d+(, )?){2,}\]
            -
            -
            -

            Sumario #2 Está Sobre Nosotros

            -

            Tenías una lista. Ordenaste la lista. La variable ticket ahora esta cambiada.

            -

            ¿Te diste cuenta que el método sort! tiene un claro y llamativo signo de exclamación al final? - Muchas veces los métodos de Ruby gritan así si es que alteran la variable para bien. No es nada - especial, solo una marca.

            -

            Ahora, mira como te fue en tu segundo minuto:

            -
              -
            • Errors. Si tratas de invertir un número o hacer algo sospechoso, - Ruby salteara el prompt para avisarte.
            • -
            • Arrays son listas para ordenar cosas en orden.
            • -
            • Variables guardan cosas y le dan un nombre. Usaste el - signo igual para hacerlo.
              Like: ticket = [14, 37, 18].
            • -
            -

            En total hay ocho lecciones. Estás a dos octavos de camino! - Esto es cosa simple, no te parece? Las cosas buenas están mas adelante.

            -

            Cambiemos de dirección por un momento. Rellené con un poco de poesía cierta - variable para ti. Hecha un vistazo. Escribe print poem

            -
            poem = "My toast has flown from my hand\nAnd my toast has gone to the -moon.\nBut when I saw it on television,\nPlanting our flag on Halley's -comet,\nMore still did I want to eat it.\n"
            -
            My toast (.+)
            -
            -
            -

            Desgraciadamente, Tú Odias la poesía de Tostadas

            -

            Mira, esta bien. No tiene que gustarte. Hackéalo, yo invito.

            -

            En vez de tostada, ve por un melón o algo. Prueba esto: poem['toast'] = 'honeydew'

            -

            Y luego escribe print poem para ver el nuevo poema.

            -
            My honey(.+)
            -
            -
            -

            Listo, Apuntado

            -

            Los corchetes que acabas de usar son muy comunes en Ruby. Recuerda, escribiste: poem['toast'] = 'honeydew'. Esa casilla con la palabra toast tiene corchetes a ambos lados, ¿ves?

            -

            Los -corchetes son como una mira para alinear un objetivo. Exacto. Estos -corchetes significan, "Estoy buscando ____." Listo, apuntado. Aquí estas buscando -una costada e intercambiándola por una fruta.

            -

            Aquí hay una pregunta: ¿Que pasa si volteamos el poema entero? poem.reverse -

            "\\n.ti tae ot (.+)"
            -
            -
            -

            Demasiado Invertido

            -

            Está bien, seguro. Entonces todo el poema fue puesto al revés. Letra por letra. Sin embargo, yo realmente solo quería - invertir las líneas. Mover la última línea a la primera y la primera hacia abajo a la ultima. Al revés, pero no - ése revés.

            -

            Aquí esta como lograrlo: poem.lines.to_a.reverse

            -
            \["More still did I(.+)"\]
            -
            -
            -

            Rizos de Metodos Concatenados

            -

            Dime, que es lo que ves? Que paso acá? Escribiste poem.lines.to_a.reverse y ¿que pasó?

            -

            Dos cosas pasaron. Convertiste poem en una lista usando -lines.to_a. lines decide la forma en que -el string se divide, luego to_a lo -convierte en un Array. (To array.) Diferentes métodos, como -bytes y chars pueden ser usadas en lugar de -lines. Usando lines, Ruby retornará cada línea de poem.

            -

            Luego, tu revertiste, reversed, esa lista. Tenías cada línea. Las revertiste. Eso es todo.

            -

            Vamos a hilar un método más al final de todo esto: print poem.lines.to_a.reverse.join -

            More still did I(.+)
            -
            -
            -

            De Todos los Sumarios, el #3 esta aquí

            -

            Buen espectáculo, mi amigo! El método join toma la lista de líneas revertidas y las pone juntas en un string. - (Seguro, también podrías haber usado to_s.)

            -

            Tiempo de Revisión.

            -
              -
            • Exclamaciones. Métodos pueden tener signos de exclamación (y también de interrogación) en - sus nombres. No es la gran cosa. Prueba: poem.include? "my hand"
            • -
            • Corchetes. Establece objetivos y busca cosas. Busca y reemplaza.
            • -
            • Concatenar métodos te permite hacer mas cosas juntas. Partir poem, revertirlo, - reensamblarlo: poem.lines.to_a.reverse.join
            • -
            -

            En este punto, querras manosear un poco más el poema. Una lista completa de métodos - String estan - - acá. - No temas y prueba algunos (como poem.downcase o poem.delete.)

            -

            Cuando estés listo para seguir adelante, escribe: books = {}

            -
            \{\}
            -
            -
            -

            Un Pequeñín Libro en Blanco

            -

            Has hecho un hash vacío. (también conocido como: un diccionario vacío.)

            -

            Vamos a rellenar con un libro de críticas en miniatura. Acá esta nuestro sistema de calificación:

            -
              -
            • :splendid → una obra maestra.
            • -
            • :quite_good → disfrutable, por supuesto que sí.
            • -
            • :mediocre → partes iguales de bueno y malo.
            • -
            • :quite_not_good → notablemente malo.
            • -
            • :abyssmal → una perdida de tiempo.
            • -
            -

            Para calificar un libro, pon el título entre corchetes y la calificación luego del signo igual.

            -

            Por ejemplo: books["Gravity's Rainbow"] = :splendid

            -
            :\w+
            -
            -
            -

            Mas Críticas Tamaño Bocadillo

            -

            Tú sigue, agrega mas críticas. Y, si quieres ver toda la lista, - implemente escribe: books

            -

            De nuevo, las calificaciones son: :splendid, :quite_good, :mediocre, - :quite_not_good, and :abyssmal.

            -

            Estas calificaciones no son strings. Cuando colocas dos puntos frente a una palabra simple, obtienes un - symbol. Los símbolos son más baratos que los strings (en términos de memoria de la computadora.) Si usas - una palabra una y otra vez en un programa, usa un símbolo. En vez de tener miles de - copias de una palabra en memoria, la computadora guardara el símbolo solamente una vez.

            -

            Una vez que tengas tres o cuatro libros allí - dentro, escribe: books.length.

            -
            [3-9]
            -
            -
            -

            Espera, ¿Me gustó Gravity's Rainbow?

            -

            Ves, el método length funciona sobre strings, list y hashes. Una gran cosa acerca de - Ruby es que los nombres usualmente se reutilizan, lo que significa menos nombres para recordar.

            -

            Si quisieras ver una de tus críticas hechas, vuelve a poner el título entre corchetes. Pero deja de lado el - signo igual.

            -

            Al igual que aquí: books["Gravity's Rainbow"]

            -
            :\w+
            -
            -
            -

            Hashes como Pares

            -

            Ten en mente que los hashes no mantienen las cosas en orden. Ese no es su trabajo. Solo emparejará dos - cosas: una key (llave) y un valor. En tus críticas, la key es el - titulo del libro y el valor es la calificación.

            -

            Si simplemente quieres ver los títulos de los libros que calificaste: books.keys

            -
            \[".*"\]
            -
            -
            -

            ¿Eres Duro?

            -

            ¿Estás dando duras injustas críticas? Sigamos puntuando con rigurosidad:
            ratings = Hash.new {0}

            -

            Entonces, bien, ahora vamos a contar tus críticas. Trata de seguirme. Escribe:
            - books.values.each { |rate| ratings[rate] += 1 }

            -

            (La línea vertical es el signo de tubería, probablemente lo logres con AltGr+1 con tu teclado.)

            -
            \[:.+\]
            -
            -
            -

            Un Recuento

            -

            Genial, wow! Has hecho un recuento de tus calificaciones. Escribe ratings para ver las cuenta. Este nuevo - hash muestra las calificaciones y luego el numero de veces que has dado esa calificación.

            -

            Una de las asombrosas cosas nuevas que acabamos de usar es un bloque, block. Vamos a explorar - explore these more in the next summary. más esto en el próximo sumario. Pero, básicamente, un bloque es un pedazo de código Ruby - rodeado por llaves.

            -

            Probemos otro bloque: 5.times { print "Odelay!" }

            -
            Odelay!Od.*
            -
            -
            -

            Ahora Arribamos al Sumario #4

            -

            Los bloques están siempre apegados a métodos. Como el método times, que toma el bloque y lo corre - repetidas veces. (En este caso: cinco veces.)

            -

            Esta última lección fue algo mas larga. Probablemente usaste unos tres minutos aprendiendo sobre:

            -
              -
            • Hashes. El pequeño diccionario con páginas arrugadas: {}.
            • -
            • Symbols. Pequeñas, eficientes palabras con dos puntos: :splendid.
            • -
            • Blocks. Pedazos de código que pueden ser clavados a muchos métodos de Ruby. Aquí - esta el código que usaste para crear el recuento:
              books.values.each { |rate| ratings[rate] += 1 }.
            • -
            -

            En tu computadora, probablemente tienes muchos archivos diferentes. Archivos con fotos en ellos, - archivos con programas dentro. Y los archivos usualmente se organizan en carpetas, también llamadas: - directorios.

            -

            He preparado algunos directorios para ti. Echa un vistazo: - Dir.entries "/"

            -
            \["\.", .+\]
            -
            -
            -

            La Privada Colección de Dr. Dir

            -

            Acabas de listar todo lo existente en el directorio superior. El directorio raíz, indicado - por la barra en diagonal. Conteniendo algunos programas y otros tutoriales y semejantes.

            -

            Entonces, ¿que es el método Dir.entries? Bueno, es solo un método ¿si?, - entries es el método llamado sobre la variable Dir. - Y Dir tiene una colección de métodos para chequear los archivos de los directorios.

            -

            Otra pequeña cosa de la que no hemos hablado abiertamente. Argumentos de los métodos, resaltados en verde.

            -
              -
            • Dir.entries "/": Cualquier cosa listada luego de un método - es considerado acoplamiento.
            • -
            • print poem: Ves, print es un método ordinario. - Y el poema esta acoplado. Para ser impreso.
            • -
            • print "pre", "event", "ual", "ism" posee varios argumentos, - con comas entre ellos.
            • -
            -

            Para listar solamente archivos de texto en el directorio: Dir["/*.txt"]

            -
            \["\/comics\.txt"\]
            -
            -
            -

            Ven, Lee Historietas Conmigo

            -

            El método Dir[] hace como entries pero tu buscas por archivos - archivos con carácteres de comodín. ¡Aquí, vemos esos corchetes otra vez! Te das - cuenta como todavía significan, "Estoy buscando _____.".

            -

            Mas específicamente: "Estoy buscando archivos que terminen con .txt."

            -

            Abramos este archivo con historietas de una vez. Aquí esta la manera:
            - print File.read("/comics.txt")

            -
            Achewood.+
            -
            -
            -

            Mi Comicas, Tu Comicas

            -

            ¡De acuerdo! Podemos comenzar a usar archivos para guardar cosas. Esto es excelente - porque normalmente cuando salimos de Ruby, todas nuestras variables desaparecerán. - Ruby, por si mismo, olvida estas cosas. Pero si salvamos cosas en archivos, - podemos leer esos archivos en futuras escapadas a Ruby.

            -

            Hey, y ¿adivina que? ¡El directorio /Home es tuyo! ¡Te lo entrego a ti! ¡Soy generoso! Hagamos una copia del archivo de la historieta.

            -

            Querrás hacer lo siguiente: FileUtils.copy('/comics.txt', '/Home/comics.txt') -

            Si ya has creado el archivo, usa File.delete('/Home/comics.txt') para arrojarlo a la basura.

            -
            nil
            -
            -
            -

            Tu Propio Territorio

            -

            Ok, tienes una copia. Chequéala: Dir["/Home/*.txt"]

            -

            Para agregar tu propia historieta a la lista, abramos el archivo en modo append.

            -

            Empieza asi: File.open("/Home/comics.txt", "a") do |f|.

            -
            ..
            -
            -
            -

            Y Ahora, para la Sorprendente Conclusión

            -

            Asi que tu prompt ha cambiado. ¿Lo notas? Tu prompt es doble punto ahora.

            -

            En este tutorial, este prompt significa que Ruby espera que escribas más. A - medida que vayas completando con líneas de código, los doble puntos se mantendrán - hasta que hallas finalizado.

            -

            Hot tip: si quieres parar de trabajar en el código y salirte de los doble puntos, usa el comando reset. - Si quieres volver a la pagina previa del tutorial, usa el comando back.

            -

            Aquí esta tu código. Ya has escrito la primera línea, asi que simplemente ingresa la segunda. (El \n - es el carácter de Enter.

            -
            • File.open("/Home/comics.txt", "a") do |f|
            • -
            •   f << "Cat and Girl: http://catandgirl.com/\n"
            • -
            • end
            • -
            -

            Y, como te has vuelto avanzado y capaz aquí, otro tip: puedes usar las flechas hacia - arriba y hacia abajo para editar tus viejos comandos o correrlos otra vez.

            -
            ..
            -
            -
            -

            Ruby se Sienta y Espera

            -

            Esa ultima línea agrega la historieta Cat and Girl a la lista, pero Ruby seguirá esperando - hasta que hallas terminado por completo para tomar acción.

            -

            Ahora, para finalizar el código que has empezado. Empezaste un nuevo bloque cuando escribiste do. - Hasta ahora los bloques que hemos visto usaban llaves. Esta vez usaremos do y end en lugar - de las llaves. Muchos Rubyistas usan do...end cuando el bloque ocupa varias líneas.

            -

            Terminemos ese bloque ahora mismo, con: end

            -
            • File.open("/Home/comics.txt", "a") do |f|
            • -
            •   f << "Cat and Girl: http://catandgirl.com/\n"
            • -
            • end
            • -
            -
            #.File:/Home/comics\.txt.
            -
            -
            -

            El Reloj Clavado en el Archivo

            -

            ¡Bien, bien! Has añadido esa historieta al archivo. Puedes verlo por ti mismo: print File.read("/Home/comics.txt")

            -

            ¿Qué hora era cuando cambiaste el archivo? Veamos. Escribe: File.mtime("/Home/comics.txt")

            -
            \w+ \w+ \d+ \d{2}:\d{2}:\d{2} [+-]\d{4} \d{4}
            -
            -
            -

            Sólo la Manecilla de la Hora

            -

            Estupendo, allí esta la hora. La hora exacta en la que agregaste la historieta al archivo. El mtime te devuelve un objeto Time de Ruby.

            -

            Si sólo quieres ver la hora que era, aprieta la flecha para arriba y cambia la línea a: File.mtime("/Home/comics.txt").hour

            -
            \d+
            -
            -
            -

            Hola, ¿Quién Anda Ahí? Y el Sumario #5 Agita su Sombrero!

            -

            Bien hecho, bien hecho, bien hecho, ¡bien hecho! Realmente, realmente, realmente, realmente, ¡reaaaaaaaaalllmente!

            -

            Aquí esta tu último minuto de tu vida en retrospectiva:

            -
              -
            • Archivos. ¿Que más se puede decir? Muchos métodos para editar archivos y revisar directorios.
            • -
            • Argumentos. Los argumentos son listas de cosas mandadas en un método. Separadas con comas.
            • -
            • También hablamos sobre do y end que es otra manera de hacer un bloque.
            • -
            -

            Ahora ya sabes como usar Ruby por completo. Me refiero a que tienes lo esencial. Solo necesitas seguir - aprendiendo métodos y probar bloques más complejos.

            -

            Pero existe un lado de Ruby que no hemos hablado. Hacer tus propios métodos y clases.

            -

            Ahem! Acabemos con ello de una vez.

            -

            Empieza con: def load_comics( path )

            -
            ..
            -
            -
            -

            En Ruby, Def Leppard Significa ¡Define Leppard (un Método)!

            -

            Hey, bueno, lo hiciste. Estas haciendo tu propio método. Comenzaste con def, seguido por el nombre del método. - Y una lista de argumentos que va a necesitar el método. ¡Esto no da tanto miedo ni es peligroso!

            -

            Todo lo que debemos hacer es rellenar con Ruby y terminarlo con end.

            -

            Aquí esta el código:

            -
            • def load_comics( path )
            • -
            •   comics = {}
            • -
            •   File.foreach(path) do |line|
            • -
            •     url, name = line.split(': ')
            • -
            •     comics[url] = name.strip
            • -
            •   end
            • -
            •   comics
            • -
            • end
            • -
            -

            No necesitas indentar, si no quieres. Lo hice solo para que sea más legible.

            -
            nil
            -
            -
            -

            La Madura Fruta de tu Propia Creación

            -

            Un nuevo método ha nacido. Vamos a usarlo: comics = load_comics('/comics.txt')

            -

            Si tienes un problema, puedes haberlo escrito mal. Usa el comando back y prueba otra vez.

            -
            \{.*"Achewood"=."http://achewood.com/".*\}
            -
            -
            -

            Hey, Cool, Una Cosa de Historietas

            -

            En tu ventana de Ruby arriba, mira el código que has escrito para el método load_comics. ¿Qué esta pasando? Tu estas - pasando en la variable path y estas recibiendo la variable comics. Ruby permite filtrar el hash comics - que es devuelto al final del método.

            -

            Una cantidad de métodos se usaron para realizar el trabajo. Fíjate si puedes hallarlos.

            -
            • File.foreach es el método que abre un archivo y manda cada línea al bloque. La variable line - dentro del bloque do...end va turnando con cada línea del archivo.
            • -
            • split es un método para strings, que rompe los string en colocándolo en un array. Un hacha es arrojada sobre las comas - y las líneas se cortan en dos, dándonos la url y el nombre, name, de las historietas.
            • -
            • strip remueve los espacios extra alrededor de name. Por si acaso.
            • -
            -

            Justo allí. Bravo. Tienes las historietas en un hash de Ruby. ¿Pero ahora qué? ¿Qué tan bueno es en verdad?

            -

            Hagamos una página de links. ¿Qué te parece? Vamos a necesitar una pequeña librería que hice para ti.

            -

            Escribe: require 'popup'

            -
            true
            -
            -
            -

            El Navegador de Títere

            -

            Excelente, has cargado la librería popup. Está guardada en un archivo en el directorio Libraries. Mira: Dir["/Libraries/*"]

            -

            La librería popup contiene un puñado de métodos que he escrito y te dejaran controlar ventanas emergentes aquí en Try Ruby.

            -

            Mira, prueba esto: Popup.goto "http://google.com/"

            -
            \033\[1;JSm.*popup_goto\(.*\)\033\[m.*
            -
            -
            -

            Haciendo Links e Hilando Redes

            -

            Nuestro propio adorable, pequeño popup para manipular. también puedes rellenarlo con tus cositas. Empecemos por algo pequeño:

            -
            • Popup.make {
            • -
            •   h1 "My Links"
            • -
            •   link "Go to Google", "http://google.com/"
            • -
            • }
            • -
            -

            El termino h1 (h-uno) significa encabezado de nivel uno. En HTML, es el encabezado más grande.

            -
            \033\[1;JSm.*popup_make\(.*h1.*a href.*\)\033\[m.*
            -
            -
            -

            Los Popups son tan fáciles, es una Locura

            -

            Se ve bien, lo hiciste perfecto, tal como se te pidió. Hagamos una lista entonces.

            -

            Aquí esta como haces una lista con la librería de popup:

            -
            • Popup.make do
            • -
            •   h1 "Things To Do"
            • -
            •   list do
            • -
            •     p "Try out Ruby"
            • -
            •     p "Ride a tiger"
            • -
            •     p "(down River Euphrates)"
            • -
            •   end
            • -
            • end
            • -
            -

            El método p es la manera corta para "párrafo".

            -
            \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*li.*\)\033\[m.*
            -
            -
            -

            Expandiendo las Historietas en la Tabla

            -

            Bien, esto esta yendo maravilloso. Esto es algo simple, pero mantén en mente que no sabias nada sobre Ruby hace quince minutos atrás!<

            -

            Ultimo paso. Vamos a juntar todo, ¿sabes? ¡Juntémoslo como esos juegos de - campanillas hermosas que tintinean en los pórticos bajo la hermosa luz del sol - en la playa!

            -

            Asegúrate de que las historietas están cargadas: comics = load_comics( '/comics.txt' )

            -

            Ahora, hagamos una lista de links para cada historieta:

            -
            • Popup.make do
            • -
            •   h1 "Comics on the Web"
            • -
            •   list do
            • -
            •     comics.each do |name, url|
            • -
            •       link name, url
            • -
            •     end
            • -
            •   end
            • -
            • end
            • -
            -

            Puedes clickear en los links y leer las historietas ¡inclusive en la ventana principal! ¡Bárbaro!

            -
            \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*a href.*li.*a href.*\)\033\[m.*
            -
            -
            -

            Sumario #6 lo que Significa que has Llegado Muy Lejos

            -

            Eres un clérigo nivel 6 de Ruby. Quiero decir que buen trabajo has hecho. Vamos a revisar:

            -
              -
            • Agregaste tu propio método con def y usaste ese método load_comics varias veces.
            • -
            • Librerias. Tú usaste el método require para cargar la librería popup.
              Escribiendo: require 'popup'
            • -
            • Y como si no fuera suficiente, hiciste tu propia página web para listar los archivos de historietas. ¡Hiciste un programa real!
            • -
            -

            Entonces ¿Qué podrá venir luego? ¿Qué deberías aprender posiblemente ahora? - Ja, esta es la mejor parte. Has recorrido un largo camino y ahora descubrirás - las clases. En dos lecciones mas y ya estarás hecho.

            -

            Tempranamente, creamos un hash como este: Hash.new pruébalo.

            -
            \{\}
            -
            -
            -

            No una Clase de Escuela, Una Clase Trabajadora

            -

            Ves, las llaves vacías {} son abreviaciones para Hash.new. El método new - es usado para hacer objetos de cierta clase. (Piensa "clase" como en "clase - trabajadora" — un grupo especifico de objetos similares, tienen el - mismo trabajo, la misma camisa.)

            -

            Pregúntate esto: ¿Cómo haría mi blog en Ruby? ¿Dónde deberías - comenzar? Bien, deberías guardar tus entradas del blog en un archivo, ¿cierto? - Pero ¿cómo seguirías los títulos de las entradas y el momento en que fue creado? - Y cuando cargas el archivo, ¿cómo se vería en Ruby? ¿Sería un Hash? ¿O un Array? ¿O - un Array de Arrys? ¿O alguna otra cosa?

            Yo realmente creo que querrás usar una clase. Ya estas familiarizado con varias clases: Hash, Array, String.

            -

            Hagamos una clase nueva: class BlogEntry.

            -
            ..
            -
            -
            -

            El Relleno del Blog esta Hecho de

            -

            Has abierto una nueva clase BlogEntry. ¿De que están hechas las entradas de tu blog? Un titulo, seguro. también, - la fecha en la que fue creada. El texto entero de la entrada.

            -

            Vamos a poner el estado de ánimo, también, tal como LiveJournal. La internet ha traído de vuelta las personas de palitos y emoticones - fuera de la bancarrota.¡Que emoción!

            -

            Bueno, ya tienes la primera línea de la clase, aquí esta el resto:/p> -

            • class BlogEntry
            • -
            •   attr_accessor :title, :time, :fulltext, :mood
            • -
            • end
            • -
            -
            nil
            -
            -
            -

            Accessors Son las Extremidades Colgantes

            -

            Hey, buena clase, colega. Tienes una nueva clase BlogEntry. Para comenzar una entrada:
            entry = BlogEntry.new.

            -

            En la definición de la clase, usaste un método llamado attr_accessor. Existen varios métodos attribute - atributo, como este que agregan pequeñas configuraciones a la clase. Estos atributos son simplemente variables adosadas a la clase.

            -

            Piénsalo de este modo. Una clase es como una persona. Esa forma de estrella - del humano. Y los atributos son las extremidades, las diferentes partes que - hacen un cuerpo.

            -

            Para crear el titulo de tu entrada: entry.title = "Today Mt. Hood Was Stolen!"

            -
            ".+"
            -
            -
            -

            Un Objeto, Ese Estupendo Paquete Pequeño

            -

            Sigue adelante y pon la hora: entry.time = Time.now

            -

            Y el estado de animo: entry.mood = :sick

            -

            Y el anuncio en si: entry.fulltext = "I can't believe Mt. Hood was stolen! I am speechless! It was stolen by a giraffe who drove away - in his Cadillac Seville very nonchalant!!"

            -

            Para ver toda la configuración, simplemente escribe en el prompt: entry.

            -
            #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
            -
            -
            -

            Agilizando

            -

            Genial, tu blog es impresionante. Hey, hagamos las cosas algo mas fácil. No querrás - poner la hora asi todas las veces que postees. Solo quieres escribir el titulo, - el contenido y el emoticon rápido, ¿verdad?

            -

            Vamos a agregar un método initialize.

            -
            • class BlogEntry
            • -
            •   def initialize( title, mood, fulltext )
            • -
            •     @time = Time.now
            • -
            •     @title, @mood, @fulltext = title, mood, fulltext
            • -
            •   end
            • -
            • end
            • -
            -

            Una vez que lo hallas escrito, prueba hacer una nueva entrada: BlogEntry.new

            -
            ArgumentError: wrong number of arguments \(0 for 3\).*
            -
            -
            -

            Tu le Has Enseñado al Blog a Rechazar lo Malo

            -

            ¿Viste como usamos dentro de la clase el símbolo arroba? De este modo: @time = Time.now

            -

            Fuera de la clase, usamos accesos (accessors): entry.time = Time.now Pero dentro variables de instancia: @time = Time.now - Son exactamente lo mismo, pero expresado en dos partes diferentes de tu programa.

            -

            tu blog ahora necesita un titulo, estado de ánimo y el post para funcionar. Cuando un nuevo BlogEntry es creado, el método initialize - es usado para chequear cualquier argumento para new. ¡Uh, necesitamos tres argumentos!

            -

            Prueba de nuevo con los tres.

            -

            entry2 -= BlogEntry.new( "I Left my Hoodie on the Mountain!", :confused, "I am -never going back to that mountain and I hope a giraffe steals it." )

            -
            #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
            -
            -
            -

            Una Jirafa No Ha Robado el Sumario #7

            -

            Aha, estas aquí. Y todo en una pieza. Todavía vamos a hacer tu blog realidad, pero hasta entonces, vamos a revisar, ¿bien?

            -
              -
            • Clases. Todo en Ruby es algún tipo de objeto. Las clases explican los objetos. Como ciertos objetos - trabajan. Por ejemplo, haces algunas entradas de blog y estos objetos están explicados en la clase BlogEntry. - En otras palabras: los llamas objetos del tipo BlogEntry.
            • -
            • Accessors son variables adosadas a un objeto que pueden ser usadas fuera del objeto. (entry.time = Time.now)
            • -
            • Variables de instancia son las mismas variables para accesos dentro del objeto. - Como en la definición de un método. (@time = Time.now)
            • -
            -

            Bueno, vamos a envolver las cosas, niño. Aquí esta el ultimo capitulo de la FASCINANTE épica - historia de Try Ruby! Ahora que ya has probado como todo funciona, ¿cómo vas a - usar eso alrededor de la casa y en tu tienda de comestibles? Eres una - gran persona (una de mis favoritas), pero necesitas dirección.

            -

            Vamos a terminar tu blog. Tienes entradas de blog, pero no un blog.

            -

            Pon las entradas en un array: blog = [entry, entry2]

            -
            \[#.BlogEntry:0x[0-9a-f]+.*, #.BlogEntry:0x[0-9a-f]+.*\]
            -
            -
            -

            Todo Se Trata de Combinar Cosas

            -

            Cosas hermosas pueden hacerse de partes simples de Ruby, especialmente - cuando las combinas entre ellas para formar algo nuevo. Aquí tenemos un blog - hecho de un array de clases. Y, en realidad, Ruby realmente hace buenas cosas - con este tipo de criaturas.

            -

            Aquí hay un puñado de cosas que puedes hacer con tu blog array:

            -
            • Querrás ordenar tus entradas de mas reciente a viejas. Puedes hacerlo con:
              - blog.sort_by { |entry| entry.time }.reverse
              Ve sort_by para más explicación.
            • -
            • Si quieres buscar en el blog por cualquier cosa relacionada con "cadillac":
              - blog.find_all { |entry| entry.fulltext.match(/cadillac/i) }
              - Lee mas en find_all - y match - para descubrir como funciona. También: /giraffe/i es un objeto Regexp, usado para concordar palabras.
            • -
            • Y agregar nuevas entradas con blog << new_entry
              - Y aquí la documentación del método <<.
            • -
            -

            Puedes buscar entre la lista de los métodos con los que viene Ruby en ruby-doc.org's core. - Otra buena lista hay en online pickaxe.

            -

            Un método realmente útil (probablemente yo uso esto mas que otra cosa) es map. Escribe: blog.map { |entry| entry.mood }

            -
            \[(:\w+, )+:\w+\]
            -
            -
            -

            Mira Su Cara — La Transformación Ha Comenzado

            -

            El método map recorre un array y reemplaza cada ítem con algo nuevo. ¿Dices que quieres reemplazar cada entrada de tu blog - con el nombre de Bruce Willis?. Hazlo entonces: blog.map { "Bruce Willis" }

            -

            Como el bloque siempre devuelve el string "Bruce Willis", eso es lo que obtienes. En el código que acabas de usar, la entrada entry wfue reemplazada - por solo el entry.mood.

            -

            Ahora, quiero que hagas un popup con las entradas de tu blog. Yo no te voy a - dar todo el código. Solo te voy a dar una parte.

            -
            • blog.each do |entry|
            • -
            •   h2 entry.title
            • -
            •   p entry.fulltext
            • -
            • end
            • -
            -

            Ahora, yo espero que pongas el código del popup alrededor y agregues un titulo con el nombre de tu blog usando h1. Como extra, tienes la hora de cada entrada para mostrar.

            -
            \033\[1;JSm.*popup_make\(.*h1.*h2.*li.*h2.*li.*\)\033\[m.*
            -
            -
            -

            Eres Una Especie de Gurú Web, Tengo Estrellas en Mis Ojos

            -

            Bien, ¡eso es! Este es exactamente el código que puedes usar para escribir tu - propio blog real en Ruby. Si te sientes aventurero, yo chequearía el video de - Rails videos donde muestran a un joven compañero creando un blog en 15 minutos. Solo sientete cómodo y mira.

            -

            Debo mencionar a Rails. Tú has estado aprendiendo el lenguaje Ruby, como - hablarlo. Pero Rails es grupo de librerías (algo asi como la librería de popup - que hemos estado usando.) Es un poderoso conjunto de herramientas para crear - sitios web. Si estas interesado en aprender sobre Rails, yo miraría head - por aquí directamente. ¡Empieza a usar tus habilidades en Ruby apropiadamente!

            -

            Algo que tiene Rails son métodos para manejar fechas fácilmente. Como, prueba: Time.now - 2.weeks

            -
            class Integer; def weeks; self * 7*24*60*60; end; end
            -
            \w+ \w+ \d+ \d{2}:\d{2}:\d{2} .*
            -
            -
            -

            Si Quieres Empezar Poco a Poco

            -

            Si quieres comenzar escribiendo pequeños programas en Ruby para practicar, tengo un proyecto llamado MouseHole - que es una pequeña caja de herramientas en la web para escribir programas cortos en Ruby. Puedes ver aquí algunos - scripts para ver que quiero decir.

            -

            MouseHole no es para escribir sitios web en realidad. Es para escribir - pequeños programas y correrlos dentro del navegador. Como hay un programa block - de notas para MouseHole y un programa que agrega una imagen de un ratón a los - links de la web que linkean a programas de MouseHole.

            -

            Tengo un script de MouseHole dentro de un archivo aquí mismo:
            - print File.read("/MouseHole/flickrpedia.user.rb")

            -
            .*Inserts Wikipedia links for Flickr tags.*
            -
            -
            -

            Sumario #8, El Sumario Hey-Relájate-Lo-Hiciste-Bien

            -

            Esta ultima sección se tomó un momento para relajarse, para darte algunos consejos de como - puedes usar Ruby. Si lo has disfrutado, descarga Ruby e instálalo.

            - -

            Una vez que tengas Ruby instalado, puedes usar Ruby Interactivo ejecutando el comando irb en el prompt de tu sistema. Para mas sobre Irb, esta - The Tiger's Vest para ayudarte.

            -

            Tú realmente mereces una torta doble-capa con doble-doble azúcar glaseado y - un tipo tocando una de esas guitarras que son doble-guitarra. Quiero decir - terminaste, ¡lo hiciste! No hay dudas de eso, ¡eres un gran ser certificado!

            -
            -
            - \ No newline at end of file diff --git a/tryruby/app/views/tutorials/intro.rhtml b/tryruby/app/views/tutorials/intro.rhtml deleted file mode 100644 index 7443c46..0000000 --- a/tryruby/app/views/tutorials/intro.rhtml +++ /dev/null @@ -1,680 +0,0 @@ - -
            -

            Using the Prompt

            -

            The blue window above is a Ruby prompt. Type a line of Ruby code, hit Enter - and watch it run!

            -

            For example, try typing some math. Like: 2 + 6

            -
            \d+
            -
            -
            -

            Numbers & Math

            -

            Good! You did a bit of math. See how the answer popped out?

            -

            Ruby recognizes numbers and mathematic symbols. You could try some other math like:

            -
            • 4 * 10
            • -
            • 5 - 12
            • -
            • 40 / 4
            -

            Sure, computers are handy and fast for math. Let's move on. Want to see your name reversed? - Type your first name in quotes like this: "Jimmy"

            -
            "(\w+)"
            -
            -
            -

            Say Your Name Backwards

            -

            Perfect, you've formed a string from the letters of your name. A string - is a set of characters the computer can process.

            -

            Imagine the letters are on a string of - laundry line and the quotes are clothespins holding the ends. The quotes mark the beginning and end.

            -

            To reverse your name, type: "Jimmy".reverse (Don't forget the dot!)

            -
            "(\w+)"
            -
            -
            -

            Counting the Letters

            -

            You have used the reverse method on your name! By enclosing your name in - quotes, you made a string. Then you called the reverse method, which works on strings to flip - all the letters backwards.

            -

            Now, let's see how many letters are in your name: "Jimmy".length

            -
            \d+
            -
            -
            -

            On Repeat

            -

            Now, I'm sure by now you're wondering what any of this is good for. Well, I'm sure you've been to - a website that screamed, Hey, your password is too short! See, some programs - use this simple code.

            -

            Watch this. Let's multiply your name by 5. "Jimmy" * 5

            -
            "(\w+)"
            -
            -
            -

            Hey, Summary #1 Already

            -

            Let's look at what you've learned in the first minute.

            -
              -
            • The prompt. Typing code into the green prompt gives you - an answer from a red prompt. All code gives an answer.
            • -
            • Numbers and strings are Ruby's math and text objects.
            • -
            • Methods. You've used English-language methods like reverse - and symbolic methods like * (the multiplication method.) Methods are action!
            • -
            -

            This is the essence of your learning. Taking simple things, toying with - them and turning them into new things. Feeling comfortable yet? I promise you are.

            -

            Okay, let's do something uncomfortable. Try reversing a number: 40.reverse

            -
            NoMethodError: undefined method `reverse' for (\d+):Fixnum
            -
            -
            -

            Stop, You're Barking Mad!

            -

            You can't reverse the number forty. I guess you can hold your monitor up to the - mirror, but reversing a number just doesn't make sense. Ruby has tossed an error - message. Ruby is telling you there is no method reverse for numbers.

            -

            Maybe if you turn it into a string: 40.to_s.reverse.

            -
            \"(\d+)\"
            -
            -
            -

            Boys are Different From Girls

            -

            And numbers are different from strings. While you can use methods on any object - in Ruby, some methods only work on certain types of things. But you can always - convert between different types using Ruby's "to" methods.

            -
            • to_s converts things to strings.
            • -
            • to_i converts things to integers (numbers.)
            • -
            • to_a converts things to arrays.
            • -
            -

            What are arrays?! They are lists. Type in a pair of brackets: [].

            -
            \[\]
            -
            -
            -

            Standing in Line

            -

            Great, that's an empty list. Lists store things in order. - Like standing in line for popcorn. You are behind someone and you wouldn't - dream of pushing them aside, right? And the guy behind you, you've got a - close eye on him, right?

            -

            Here's a list for you. Lottery numbers: [12, 47, 35].

            -
            \[(\d+(, )?){2,}\]
            -
            -
            -

            One Raises Its Hand

            -

            A list of lottery numbers. Which one is the highest?

            -

            Try: [12, 47, 35].max.

            -
            (\d+)
            -
            -
            -

            Tucking a List Away

            -

            Good, good. But it's annoying to have to retype that list, isn't it?

            -

            Let's save our numbers inside a ticket like so: ticket = [12, 47, 35]

            -
            \[(\d+(, )?){2,}\]
            -
            -
            -

            Now Type Ticket

            -

            Now, type: ticket

            -
            \[(\d+(, )?){2,}\]
            -
            -
            -

            Saved, Tucked Away

            -

            Fantastic! You've hung on to your lotto numbers, tucking them away inside a - variable called ticket.

            -

            Let's put your lotto numbers in order, how about? Use: ticket.sort!

            -
            \[(\d+(, )?){2,}\]
            -
            -
            -

            Summary #2 is Upon Us

            -

            You had a list. You sorted the list. The ticket variable is now changed.

            -

            Did you notice that the sort! method has a big, bright exclamation at the end? - A lot of times Ruby methods shout like that if they alter the variable for good. It's nothin - special, just a mark.

            -

            Now, look how your second minute went:

            -
              -
            • Errors. If you try to reverse a number or do anything fishy, - Ruby will skip the prompt and tell you so.
            • -
            • Arrays are lists for storing things in order.
            • -
            • Variables save a thing and give it a name. You used the - equals sign to do this.
              Like: ticket = [14, 37, 18].
            • -
            -

            In all there are eight lessons. You are two-eighths of the way there! - This is simple stuff, don't you think? Good stuff up ahead.

            -

            Let's change directions for a moment. I've stuffed a bit of poetry for you in - a certain variable. Take a look. Type print poem

            -
            poem = "My toast has flown from my hand\nAnd my toast has gone to the -moon.\nBut when I saw it on television,\nPlanting our flag on Halley's -comet,\nMore still did I want to eat it.\n"
            -
            My toast (.+)
            -
            -
            -

            Sadly, You Hate Toast Poetry

            -

            Look, it's okay. You don't have to like it. Hack it up, be my guest.

            -

            Instead of toast, go for a melon or something. Try this: poem['toast'] = 'honeydew'

            -

            And then type print poem by itself to see the new poem.

            -
            My honey(.+)
            -
            -
            -

            Ready, Aim

            -

            The square brackets you just used are very common in Ruby. Remember, you typed: poem['toast'] = 'honeydew'. That box with the word toast has a square bracket on each side, see?

            -

            The -two brackets are like sights used to line up a target. Exactly. These -brackets mean, "I am looking for ____." Ready, aim. Here you're looking -for toast and swapping it out with fruit.

            -

            Here's a question: what happens when we reverse this whole poem? poem.reverse -

            "\\n.ti tae ot (.+)"
            -
            -
            -

            Too Much Reversal

            -

            Okay, sure. So the whole poem's been turned backwards, letter-by-letter. I really want to just - reverse the lines, though. Move the last line up to first and the first line down to last. Backwards, but not - that backwards.

            -

            Here's how: poem.lines.to_a.reverse

            -
            \["More still did I(.+)"\]
            -
            -
            -

            Ringlets of Chained Methods

            -

            So what do you see? What happened there? You typed poem.lines.to_a.reverse and what happened?

            -

            Two things happened. You turned the poem into a -list using lines.to_a. lines decides the way -the string is split up, then to_a converted it into an -Array. (To array.) Different methods, such -as bytes and chars can be used in place -of lines. By using lines, ruby will return each line of the poem.

            -

            Then, you reversed that list. You had each line. You reversed them. That's it.

            -

            Let's tack one more method on the end there: print poem.lines.to_a.reverse.join -

            More still did I(.+)
            -
            -
            -

            Of All the Summaries, #3 is Here Now

            -

            Good show, my friend! The join method took that list of reversed lines and put them - together into a string. (Sure, you could have also just used to_s.)

            -

            Review time.

            -
              -
            • Exclamations. Methods may have exclamations (and also question marks) - in their name. No big deal. Try: poem.include? "my hand"
            • -
            • Square brackets. Target and find things. Search and replace.
            • -
            • Chaining methods lets you get a lot more done. Break up a poem, - reverse it, reassemble it: poem.lines.to_a.reverse.join
            • -
            -

            At this point, you may want to tinker with the poem a bit more. A complete list of all - the String methods is - - here. - Go ahead and try a few (such as poem.downcase or poem.delete.)

            -

            When you're ready to move on, type: books = {}

            -
            \{\}
            -
            -
            -

            A Wee Blank Book

            -

            You've made an empty hash. (Also known as: an empty dictionary.)

            -

            We're going to stuff some miniature book reviews in this hash. Here's our rating system:

            -
              -
            • :splendid → a masterpiece.
            • -
            • :quite_good → enjoyed, sure, yes.
            • -
            • :mediocre → equal parts great and terrible.
            • -
            • :quite_not_good → notably bad.
            • -
            • :abyssmal → steaming wreck.
            • -
            -

            To rate a book, put the title in square brackets and put the rating after the equals.

            -

            For example: books["Gravity's Rainbow"] = :splendid

            -
            :\w+
            -
            -
            -

            More Bite-Size Reviews

            -

            Keep going, fill it up with reviews. And, if you want to see the whole list, - just type: books

            -

            Again, the ratings are: :splendid, :quite_good, :mediocre, - :quite_not_good, and :abyssmal.

            -

            These ratings are not strings. When you place a colon in front of a simple word, you get a - symbol. Symbols are cheaper than strings (in terms of computer memory.) If - you use a word over and over in your program, use a symbol. Rather than having thousands of - copies of that word in memory, the computer will store the symbol only once.

            -

            Once you've got three or four books in - there, type: books.length.

            -
            [3-9]
            -
            -
            -

            Wait, Did I Like Gravity's Rainbow?

            -

            See, the length method works on strings, list and hashes. One great thing about - Ruby is that names are often reused, which means fewer names you need to remember.

            -

            If you'd like to look up one of your old reviews, again put the title in the square. But leave off - the equals.

            -

            Just like this: books["Gravity's Rainbow"]

            -
            :\w+
            -
            -
            -

            Hashes as Pairs

            -

            Keep in mind that hashes won't keep things in order. That's not their job. It'll just pair up two - things: a key and a value. In your reviews, the key is the book's - title and the value is the rating.

            -

            If you want to just see the titles of the books you've reviewed: books.keys

            -
            \[".*"\]
            -
            -
            -

            Are You Harsh?

            -

            So are you giving out harsh, unfair reviews? Let's keep score with this hash:
            ratings = Hash.new {0}

            -

            Then, okay, now let's count up your reviews. Just stay with me. Type:
            - books.values.each { |rate| ratings[rate] += 1 }

            -

            (The straight line in the code is the pipe character, probably located right above the - Enter key on your keyboard.)

            -
            \[:.+\]
            -
            -
            -

            A Tally

            -

            Great, wow! You've made a scorecard of your ratings. Type ratings to see the count. - This new hash shows a rating and then the number of times you've given that rating.

            -

            One of the amazing new things we've just used is a block. We're going to - explore these more in the next summary. But, basically, a block is a bit of Ruby code surrounded - by curly braces.

            -

            Let's try another block: 5.times { print "Odelay!" }

            -
            Odelay!Od.*
            -
            -
            -

            Now Arriving at Summary #4

            -

            Blocks are always attached to methods. Like the times method, which takes the - block and runs the code over and over. (In this case: five times.)

            -

            This last lesson was a bit longer. You've probably used up three minutes learning about:

            -
              -
            • Hashes. The little dictionary with the curly pages: {}.
            • -
            • Symbols. Tiny, efficient code words with a colon: :splendid.
            • -
            • Blocks. Chunks of code which can be tacked on to many of Ruby's methods. Here's the - code you used to build a scorecard:
              books.values.each { |rate| ratings[rate] += 1 }.
            • -
            -

            On your computer, you probably have a lot of different files. Files with pictures in them, - files with programs in them. And files are often organized into folders, also called: - directories.

            -

            I've prepared a few directories for you. Take a look: - Dir.entries "/"

            -
            \["\.", .+\]
            -
            -
            -

            The Private Collection of Dr. Dir

            -

            You've just listed out everything in the top directory. The root directory, indicated - by a single slash. Containing some programs and other tutorials and such.

            -

            So, what is the Dir.entries method? Well, it's just a method, right? - entries is a method called on the Dir variable. - And Dir has a collection of methods for checking out file directories.

            -

            One other little thing we haven't really talked about openly. Method arguments, highlighted in green.

            -
              -
            • Dir.entries "/": Anything listed after a method - is considered an attachment.
            • -
            • print poem: See, print is an ordinary method. And the - poem is attached. To be printed.
            • -
            • print "pre", "event", "ual", "ism" has several arguments, with commas - between them.
            • -
            -

            To list just the text files in that directory: Dir["/*.txt"]

            -
            \["\/comics\.txt"\]
            -
            -
            -

            Come, Read Comics With Me

            -

            The Dir[] method is like entries but you search for files - with wildcard characters. Here, we see those square brackets again! Notice how - they still mean, "I am looking for _____?"

            -

            More specifically: "I am looking for files which end with .txt."

            -

            Let's crack open this comics file, then. Here's the way:
            - print File.read("/comics.txt")

            -
            Achewood.+
            -
            -
            -

            Mi Comicas, Tu Comicas

            -

            All right! We can start to use files to store things. This is great because normally when - we exit Ruby, all our variables will be gone. Ruby, by itself, forgets these things. - But if we save things in files, we can read those files in future Ruby escapades.

            -

            Hey, and guess what? The /Home directory is yours! I gave it to you! I am generous! Let's make a copy of the comics file.

            -

            You'll want to: FileUtils.copy('/comics.txt', '/Home/comics.txt') -

            If you've already created the file, use File.delete('/Home/comics.txt') to trash it.

            -
            nil
            -
            -
            -

            Your Own Turf

            -

            Okay, you've got a copy. Check it: Dir["/Home/*.txt"]

            -

            To add your own comic to the list, let's open the file in append mode.

            -

            Start like this: File.open("/Home/comics.txt", "a") do |f|.

            -
            ..
            -
            -
            -

            And Now For the Startling Conclusion

            -

            So your prompt has changed. See that? Your prompt is a double dot now.

            -

            In this tutorial, this prompt means that Ruby is expecting you to type more. - As you type in the lines of Ruby code, the double dots will continue until you - are completely finished.

            -

            Hot tip: If you want to stop working on the code and break out of the double dots, use the reset - command. If you want to go the previous page of the tutorial, use the back command.

            -

            Here's your code. You've already typed the first line, so just enter the second line. (The \n - is an Enter character.

            -
            • File.open("/Home/comics.txt", "a") do |f|
            • -
            •   f << "Cat and Girl: http://catandgirl.com/\n"
            • -
            • end
            • -
            -

            And, since you're getting so advanced and capable here, one other tip: you can use the up and down arrow keys to - edit your old commands or run them again.

            -
            ..
            -
            -
            -

            Ruby Sits Still

            -

            That last line adds the Cat and Girl comic to the list, but Ruby's going to wait until you're totally finished to - take action.

            -

            Now, to finish the code you've started. You opened a new block when you typed do. - So far the blocks we've seen have used curly braces. This time we'll be using do and end instead - of curly braces. A lot of Rubyists will use do...end when the block goes on for many lines.

            -

            Let's get that block finished now, with: end

            -
            • File.open("/Home/comics.txt", "a") do |f|
            • -
            •   f << "Cat and Girl: http://catandgirl.com/\n"
            • -
            • end
            • -
            -
            #.File:/Home/comics\.txt.
            -
            -
            -

            The Clock Nailed To the File

            -

            Good, good! You've added that new comic to the file. You can see for yourself: print File.read("/Home/comics.txt")

            -

            What time was it when you changed the file? Let's check. Type: File.mtime("/Home/comics.txt")

            -
            \d{4}-\d+-\d+ \d{2}:\d{2}:\d{2} [+-]\d{4}
            -
            -
            -

            Just the Hour Hand

            -

            Great, there's the time. The precise time exactly when you added to the file. The mtime gives you a Ruby Time object.

            -

            If you want to check just what hour it was, hit the up arrow key and change the line to: File.mtime("/Home/comics.txt").hour

            -
            \d+
            -
            -
            -

            Hallo, Who's There? And Summary #5 Waves Its Hat!

            -

            Well done, well done, well done, well done! Truly, truly, truly, truly, truuuuuuuuly!

            -

            Here's the last few minutes of your life in review:

            -
              -
            • Files. What more can be said? Lots of methods for editing files and lookin around in directories.
            • -
            • Arguments. Arguments are a list of things sent into a method. With commas between.
            • -
            • We also spoke about do and end which are another way to make a block.
            • -
            -

            You totally know how to use Ruby now. I mean you've got down the essentials. You just need to keep learning more methods and - try out more complex blocks.

            -

            But there's one side of Ruby we haven't settled. Making your own methods and classes.

            -

            Ahem! Let's get it over with then.

            -

            Start with: def load_comics( path )

            -
            ..
            -
            -
            -

            In Ruby, Def Leppard Means Define Leppard (a Method)!

            -

            Hey, okay, you done it. You're making your own method. You started with def, followed by the name of the method. - And a list of arguments which the method will need. This isn't too scary and dangerous!

            -

            All we have to do is fill it up with Ruby and finish it up with end.

            -

            Here's the code:

            -
            • def load_comics( path )
            • -
            •   comics = {}
            • -
            •   File.foreach(path) do |line|
            • -
            •     name, url = line.split(': ')
            • -
            •     comics[name] = url.strip
            • -
            •   end
            • -
            •   comics
            • -
            • end
            • -
            -

            No need to indent, if you don't want. I just do that to make it read easier.

            -
            nil
            -
            -
            -

            The Ripened Fruit of Your Own Creation

            -

            A new method is born. Let us use it: comics = load_comics('/comics.txt')

            -

            If you have a problem, you might have mistyped. Use the back command and try again.

            -
            \{.*"Achewood"=."http://achewood.com/".*\}
            -
            -
            -

            Hey, Cool, a Comics Thing

            -

            In your Ruby window above, look at the code you've typed for the load_comics method. What is happening? You're - passing in the path variable and you're getting back the comics variable. Ruby lets the comics - hash trickle out the end of the method.

            -

            A number of methods were used to get the job done. See if you can spot them.

            -
            • File.foreach is a method which opens a file and hands each line to the block. The line - variable inside the do...end block took turns with each line in the file.
            • -
            • split is a method for strings, which breaks the string up into an array. An axe is laid on the colon - and the line is chopped in half, giving us the url and name for each comic.
            • -
            • strip removes extra spaces around the name. Just in case.
            • -
            -

            Right on. Bravo. You've got the comics in a Ruby hash. But what now? What good is this really?

            -

            Let's make a page of links. How about that? We'll need to load a little library I've made for you.

            -

            Type: require 'popup'

            -
            true
            -
            -
            -

            Browser Puppetry

            -

            Excellent, you've loaded the popup library. It's saved in a file in the Libraries folder. See: Dir["/Libraries/*"]

            -

            The popup library contains a bunch of methods I've written which let you control a popup here on the Try Ruby site.

            -

            Here, try this: Popup.goto "http://google.com/"

            -
            \033\[1;JSm.*popup_goto\(.*\)\033\[m.*
            -
            -
            -

            Making Links and Spinning Webs

            -

            Our own lovely, little popup to manipulate. You can also fill it with your own goodies. We'll start small:

            -
            • Popup.make {
            • -
            •   h1 "My Links"
            • -
            •   link "Go to Google", "http://google.com/"
            • -
            • }
            • -
            -

            The term h1 (h-one) means a level-one header. In HTML, this is the largest size of header.

            -
            \033\[1;JSm.*popup_make\(.*h1.*a href.*\)\033\[m.*
            -
            -
            -

            Popups Are So Easy, It's Crazy

            -

            Looks good, you did it perfectly, just as you were asked. Let's make a list then.

            -

            Here's how you make a list with the popup library:

            -
            • Popup.make do
            • -
            •   h1 "Things To Do"
            • -
            •   list do
            • -
            •     p "Try out Ruby"
            • -
            •     p "Ride a tiger"
            • -
            •     p "(down River Euphrates)"
            • -
            •   end
            • -
            • end
            • -
            -

            The p method is short for "paragraph".

            -
            \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*li.*\)\033\[m.*
            -
            -
            -

            Spread the Comics on the Table

            -

            Okay, this is coming along wonderfully. This is simple stuff, but keep in mind that you didn't know any Ruby whatsoever just fifteen minutes ago!

            -

            Last -step. Let's tie it all together, you know? Let's make it chime together -like a very nice set of glistening chimes on the beach in the -maginificent sunlight!

            -

            Make sure the comics are loaded: comics = load_comics( '/comics.txt' )

            -

            Now, let's make a list of the links to each comic:

            -
            • Popup.make do
            • -
            •   h1 "Comics on the Web"
            • -
            •   list do
            • -
            •     comics.each do |name, url|
            • -
            •       link name, url
            • -
            •     end
            • -
            •   end
            • -
            • end
            • -
            -

            You can click on the links and read the comics in the little window even! Smashing!

            -
            \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*a href.*li.*a href.*\)\033\[m.*
            -
            -
            -

            Summary #6 Which Means You've Come So Far

            -

            You're a level six Ruby cleric. I mean what a great job you've done. Let's review:

            -
              -
            • You added your own method with def and you used that load_comics method several times.
            • -
            • Libraries. You used the require method to load the popup library.
              By typing: require 'popup'
            • -
            • And if that wasn't enough, you made your own web page from a list of comics in a file. You made a real program!
            • -
            -

            So -what could possibly be next? What could you possibly have to learn now? -Ha, this is the best part. You've come such a long way that we're going -to uncover classes. For two more short lessons and you're done.

            -

            Earlier, we created a hash like this: Hash.new Try it.

            -
            \{\}
            -
            -
            -

            Not a School Class, a Working Class

            -

            You see, the empty curly braces {} is a shortcut for Hash.new. The new -method is used to make objects of a certain class. (Think "class" as in -"working class" — a specific group of objects which are similar, have -the same jobs, the same shirts.)

            -

            Ask yourself this: How would I make a blog in Ruby? -Where would you start? Well, you might store your blog entries in a -file, right? But how would you keep track of the title of the entry and -the time it was posted? And when you loaded the file, how would it look -in Ruby? Would it be a Hash? Or an Array? Or an Array of Arrays? Or -something else?

            I really think you'll want to use a class. You are already familiar with many classes: Hash, Array, String.

            -

            Let's make a new class: class BlogEntry.

            -
            ..
            -
            -
            -

            The Stuff Blogs are Made of

            -

            You've opened up a new BlogEntry class. What is your blog entry made of? A title, sure. Also, a time when the entry was posted. The - full text of the entry.

            -

            We'll do a mood setting, too, just like LiveJournal. The Internet has really brought back stick people and smileys - out of bankruptcy. Emote!

            -

            Okay, so you've got the first line of the class, here's the rest:

            -
            • class BlogEntry
            • -
            •   attr_accessor :title, :time, :fulltext, :mood
            • -
            • end
            • -
            -
            nil
            -
            -
            -

            Accessors Are the Dangling Limbs

            -

            Hey, good class, man. You've got a new BlogEntry class. To start an entry:
            entry = BlogEntry.new.

            -

            In the class definition, you used a method called attr_accessor. There are many attribute methods like - this which add little settings to classes. These attributes are just variables attached to a class.

            -

            Think -of it this way. A class is like a person. That star-shaped human thing -out there. And the attributes are the dangling limbs, the different -parts that make up a body.

            -

            To set the title of your entry: entry.title = "Today Mt. Hood Was Stolen!"

            -
            ".+"
            -
            -
            -

            An Object, That Neat Little Package

            -

            Go ahead and set the post time: entry.time = Time.now

            -

            And the mood: entry.mood = :sick

            -

            And the post itself: entry.fulltext = "I can't believe Mt. Hood was stolen! I am speechless! It was stolen by a giraffe who drove away - in his Cadillac Seville very nonchalant!!"

            -

            To see all your settings, just type at the prompt: entry.

            -
            #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
            -
            -
            -

            Quickening it Up

            -

            Cool, -your blog is awesome. Hey, let's make things a bit easier on you. -You're not going to want to set the time like that every time you post. -You just want to type in the title and the entry and the mood quickly, -right?

            -

            Let's add an initialize method.

            -
            • class BlogEntry
            • -
            •   def initialize( title, mood, fulltext )
            • -
            •     @time = Time.now
            • -
            •     @title, @mood, @fulltext = title, mood, fulltext
            • -
            •   end
            • -
            • end
            • -
            -

            Once you've got that typed in, try making a new entry: BlogEntry.new

            -
            ArgumentError: wrong number of arguments \(0 for 3\).*
            -
            -
            -

            You've Taught Your Blog to Reject Worthless Things

            -

            Did you see how inside the class we used the at-symbols? Like this: @time = Time.now

            -

            Outside the class, we use accessors: entry.time = Time.now But inside we use instance variables: @time = Time.now - They're the exact same thing, but expressed in two different places of your program.

            -

            Your blog now needs a title, a mood and a post in order to work. When a new BlogEntry is created, the initialize method - is used to check for any arguments to new. Uh, we need three arguments!

            -

            Try it again with all three.

            -

            entry2 -= BlogEntry.new( "I Left my Hoodie on the Mountain!", :confused, "I am -never going back to that mountain and I hope a giraffe steals it." )

            -
            #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
            -
            -
            -

            A Giraffe Has Not Stolen Summary #7

            -

            Aha, you're here. And all in one piece. We're still going to make your blog real, but until then, let's review, okay?

            -
              -
            • Classes. Everything in Ruby is some kind of object. Classes explain objects. How a certain object works. - For example, you made a few blog entry objects and these objects are explained in the BlogEntry class. - In other words: you call them BlogEntry objects.
            • -
            • Accessors are variables attached to an object which can be used outside the object. (entry.time = Time.now)
            • -
            • Instance variables are the same variables you're using for accessors when inside the object. - Like in a method definition. (@time = Time.now)
            • -
            -

            Okay, -let's wrap things up, kid. Here's the last chapter of the GRIPPING epic -story of Try Ruby! Now that you've got a taste of how it all works, how -are you going to use it around the house and in your grocer's freezer? -You're a great person (one of my favorites), but you need guidance.

            -

            Let's finish your blog. You have blog entries, but no actual blog.

            -

            Put the entries into an array: blog = [entry, entry2]

            -
            \[#.BlogEntry:0x[0-9a-f]+.*, #.BlogEntry:0x[0-9a-f]+.*\]
            -
            -
            -

            It's All About Combining Things

            -

            Some -beautiful things can be done with the simple parts of Ruby, especially -when you combine them together into new things. Here we've got a blog -made of an array of classes. And, actually, Ruby really does good with -this kind of creature.

            -

            Here's a few things you can do with your array blog:

            -
            • You'll want to sort your entries from newest to oldest. You can do this with:
              - blog.sort_by { |entry| entry.time }.reverse
              See the sort_by explanation for more.
            • -
            • If you want to search your blog for anything related to "cadillac":
              - blog.find_all { |entry| entry.fulltext.match(/cadillac/i) }
              - Read all about find_all - and match - to figure out how that works. Also: the slashy /giraffe/i is a Regexp object, used for matching words.
            • -
            • Add new entries with blog << new_entry
              - And check out the << method documentation.
            • -
            -

            You can browse a list of all Ruby's built-in methods at ruby-doc.org's core list. - Another good list is at the online pickaxe.

            -

            One really useful method (I probably use this more than anything else) is map. Type: blog.map { |entry| entry.mood }

            -
            \[(:\w+, )+:\w+\]
            -
            -
            -

            Look at His Face — The Transformation Has Begun

            -

            The map method cycles through an array and replaces each item with something new. Say you wanted to replace each of your blog entries - with the name Bruce Willis. Do it so: blog.map { "Bruce Willis" }

            -

            Since the block always returns the string "Bruce Willis", that's what you get. In the code you just used, the entry was swapped out - for only the entry.mood.

            -

            Now, -I want you to make a popup with your blog entries. I'm not going to -give you all of the code. I'm just going to give you part of it.

            -
            • blog.each do |entry|
            • -
            •   h2 entry.title
            • -
            •   p entry.fulltext
            • -
            • end
            • -
            -

            Now, I expect you to put the popup code around it and add an h1 title with the name of your blog. For extra haroompf, have the time of each entry display.

            -
            \033\[1;JSm.*popup_make\(.*h1.*h2.*li.*h2.*li.*\)\033\[m.*
            -
            -
            -

            You are Some Kind of Web Guru, I Have Stars in My Eyes

            -

            Good, -that's it! This is exactly the code you can use to write your own real -Ruby blog. If you're feeling adventurous, I'd check out the Rails videos which show a swift young fellow creating a blog in 15 minutes. You just sit back and watch.

            -

            I -should mention Rails. You have been learning the Ruby language, how to -speak it. But Rails is a bunch of libraries (sort of like the popup -library we've been using.) It's a very powerful toolkit for building -websites. If you're interested in learning about Rails, I would head - over there right away. Start using your Ruby skills proper!

            -

            One thing Rails has is easy methods for dates. Like, try: Time.now - 2.weeks

            -
            class Integer; def weeks; self * 7*24*60*60; end; end
            -
            \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-+]\d{4}
            -
            -
            -

            If You Want to Start Small

            -

            If you'd like to start writing little Ruby programs just to practice, I have a project called MouseHole - which is a little web toolkit for writing short Ruby programs. You can look over a few - scripts to see what I mean.

            -

            MouseHole -isn't for writing web sites really. It's just for writing little -programs you run inside your browser. Like there's a notepad program -for MouseHole and a program which adds a mouse picture next to links on -the web which link to MouseHole programs.

            -

            I've got a MouseHole script inside a file here:
            - print File.read("/MouseHole/flickrpedia.user.rb")

            -
            .*Inserts Wikipedia links for Flickr tags.*
            -
            -
            -

            Summary #8, The Hey-Relax-You-Did-Good Summary

            -

            This last section took a moment to wind down, to give you some pointers as to how you can use Ruby. If you enjoyed yourself, - download Ruby and install it.

            - -

            Once you have Ruby installed, you can use Interactive Ruby by running irb on your system's prompt. For more on Irb, - there's The Tiger's Vest to help you.

            -

            You -really deserve a double-layer cake with double-double frosting and a -guy playing one of those guitars that's a double guitar. I mean you -finished, you really did! No doubt about it, you're a certified -red-blooded smartiac!

            -
            -
            - - diff --git a/tryruby/config/boot.rb b/tryruby/config/boot.rb deleted file mode 100644 index 4489e58..0000000 --- a/tryruby/config/boot.rb +++ /dev/null @@ -1,6 +0,0 @@ -require 'rubygems' - -# Set up gems listed in the Gemfile. -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) - -require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) diff --git a/tryruby/config/database.yml b/tryruby/config/database.yml deleted file mode 100644 index 48e775d..0000000 --- a/tryruby/config/database.yml +++ /dev/null @@ -1,32 +0,0 @@ - -development: - adapter: mysql2 - database: tryruby_development - username: root - password: root - pool: 5 - timeout: 5000 - host: 127.0.0.1 - -# Warning: The database defined as "test" will be erased and -# re-generated from your development database when you run "rake". -# Do not set this db to the same as development or production. -test: - adapter: mysql2 - database: tryruby_test - username: root - password: root - pool: 5 - timeout: 5000 - host: 127.0.0.1 - -production: - adapter: mysql2 - database: tryruby_production - username: root - password: root - pool: 5 - timeout: 5000 - host: localhost -cucumber: - <<: *test \ No newline at end of file diff --git a/tryruby/config/environment.rb b/tryruby/config/environment.rb deleted file mode 100644 index 1c5d67b..0000000 --- a/tryruby/config/environment.rb +++ /dev/null @@ -1,5 +0,0 @@ -# Load the rails application -require File.expand_path('../application', __FILE__) - -# Initialize the rails application -TryRuby::Application.initialize! diff --git a/tryruby/config/environments/development.rb b/tryruby/config/environments/development.rb deleted file mode 100644 index 43463ef..0000000 --- a/tryruby/config/environments/development.rb +++ /dev/null @@ -1,26 +0,0 @@ -TryRuby::Application.configure do - # Settings specified here will take precedence over those in config/application.rb - - # In the development environment your application's code is reloaded on - # every request. This slows down response time but is perfect for development - # since you don't have to restart the webserver when you make code changes. - config.cache_classes = false - - # Log error messages when you accidentally call methods on nil. - config.whiny_nils = true - - # Show full error reports and disable caching - config.consider_all_requests_local = true - config.action_view.debug_rjs = true - config.action_controller.perform_caching = false - - # Don't care if the mailer can't send - config.action_mailer.raise_delivery_errors = false - - # Print deprecation notices to the Rails logger - config.active_support.deprecation = :log - - # Only use best-standards-support built into browsers - config.action_dispatch.best_standards_support = :builtin -end - diff --git a/tryruby/config/environments/production.rb b/tryruby/config/environments/production.rb deleted file mode 100644 index 3827776..0000000 --- a/tryruby/config/environments/production.rb +++ /dev/null @@ -1,49 +0,0 @@ -TryRuby::Application.configure do - # Settings specified here will take precedence over those in config/application.rb - - # The production environment is meant for finished, "live" apps. - # Code is not reloaded between requests - config.cache_classes = true - - # Full error reports are disabled and caching is turned on - config.consider_all_requests_local = false - config.action_controller.perform_caching = true - - # Specifies the header that your server uses for sending files - config.action_dispatch.x_sendfile_header = "X-Sendfile" - - # For nginx: - # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' - - # If you have no front-end server that supports something like X-Sendfile, - # just comment this out and Rails will serve the files - - # See everything in the log (default is :info) - # config.log_level = :debug - - # Use a different logger for distributed setups - # config.logger = SyslogLogger.new - - # Use a different cache store in production - # config.cache_store = :mem_cache_store - - # Disable Rails's static asset server - # In production, Apache or nginx will already do this - config.serve_static_assets = false - - # Enable serving of images, stylesheets, and javascripts from an asset server - # config.action_controller.asset_host = "http://assets.example.com" - - # Disable delivery errors, bad email addresses will be ignored - # config.action_mailer.raise_delivery_errors = false - - # Enable threaded mode - # config.threadsafe! - - # Enable locale fallbacks for I18n (makes lookups for any locale fall back to - # the I18n.default_locale when a translation can not be found) - config.i18n.fallbacks = true - - # Send deprecation notices to registered listeners - config.active_support.deprecation = :notify -end diff --git a/tryruby/config/environments/test.rb b/tryruby/config/environments/test.rb deleted file mode 100644 index 7127cbe..0000000 --- a/tryruby/config/environments/test.rb +++ /dev/null @@ -1,35 +0,0 @@ -TryRuby::Application.configure do - # Settings specified here will take precedence over those in config/application.rb - - # The test environment is used exclusively to run your application's - # test suite. You never need to work with it otherwise. Remember that - # your test database is "scratch space" for the test suite and is wiped - # and recreated between test runs. Don't rely on the data there! - config.cache_classes = true - - # Log error messages when you accidentally call methods on nil. - config.whiny_nils = true - - # Show full error reports and disable caching - config.consider_all_requests_local = true - config.action_controller.perform_caching = false - - # Raise exceptions instead of rendering exception templates - config.action_dispatch.show_exceptions = false - - # Disable request forgery protection in test environment - config.action_controller.allow_forgery_protection = false - - # Tell Action Mailer not to deliver emails to the real world. - # The :test delivery method accumulates sent emails in the - # ActionMailer::Base.deliveries array. - config.action_mailer.delivery_method = :test - - # Use SQL instead of Active Record's schema dumper when creating the test database. - # This is necessary if your schema can't be completely dumped by the schema dumper, - # like if you have constraints or database-specific column types - # config.active_record.schema_format = :sql - - # Print deprecation notices to the stderr - config.active_support.deprecation = :stderr -end diff --git a/tryruby/config/initializers/backtrace_silencers.rb b/tryruby/config/initializers/backtrace_silencers.rb deleted file mode 100644 index 59385cd..0000000 --- a/tryruby/config/initializers/backtrace_silencers.rb +++ /dev/null @@ -1,7 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. -# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } - -# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. -# Rails.backtrace_cleaner.remove_silencers! diff --git a/tryruby/config/initializers/inflections.rb b/tryruby/config/initializers/inflections.rb deleted file mode 100644 index d250860..0000000 --- a/tryruby/config/initializers/inflections.rb +++ /dev/null @@ -1,10 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# Add new inflection rules using the following format -# (all these examples are active by default): - ActiveSupport::Inflector.inflections do |inflect| -# inflect.plural /^(ox)$/i, '\1en' -# inflect.singular /^(ox)en/i, '\1' - inflect.irregular 'irb', 'irb' -# inflect.uncountable %w( fish sheep ) - end diff --git a/tryruby/config/initializers/mime_types.rb b/tryruby/config/initializers/mime_types.rb deleted file mode 100644 index 72aca7e..0000000 --- a/tryruby/config/initializers/mime_types.rb +++ /dev/null @@ -1,5 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# Add new mime types for use in respond_to blocks: -# Mime::Type.register "text/richtext", :rtf -# Mime::Type.register_alias "text/html", :iphone diff --git a/tryruby/config/initializers/new_rails_defaults.rb b/tryruby/config/initializers/new_rails_defaults.rb deleted file mode 100644 index c94db0a..0000000 --- a/tryruby/config/initializers/new_rails_defaults.rb +++ /dev/null @@ -1,21 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# These settings change the behavior of Rails 2 apps and will be defaults -# for Rails 3. You can remove this initializer when Rails 3 is released. - -if defined?(ActiveRecord) - # Include Active Record class name as root for JSON serialized output. - ActiveRecord::Base.include_root_in_json = true - - # Store the full class name (including module namespace) in STI type column. - ActiveRecord::Base.store_full_sti_class = true -end - -ActionController::Routing.generate_best_match = false - -# Use ISO 8601 format for JSON serialized times and dates. -ActiveSupport.use_standard_json_time_format = true - -# Don't escape HTML entities in JSON, leave that for the #json_escape helper. -# if you're including raw json in an HTML page. -ActiveSupport.escape_html_entities_in_json = false \ No newline at end of file diff --git a/tryruby/config/initializers/session_store.rb b/tryruby/config/initializers/session_store.rb deleted file mode 100644 index 5551e13..0000000 --- a/tryruby/config/initializers/session_store.rb +++ /dev/null @@ -1,8 +0,0 @@ -# Be sure to restart your server when you modify this file. - -TryRuby::Application.config.session_store :cookie_store, :key => '_TryRuby_session' - -# Use the database for sessions instead of the cookie-based default, -# which shouldn't be used to store highly confidential information -# (create the session table with "rails generate session_migration") -# TryRuby::Application.config.session_store :active_record_store diff --git a/tryruby/config/locales/en.yml b/tryruby/config/locales/en.yml deleted file mode 100644 index a747bfa..0000000 --- a/tryruby/config/locales/en.yml +++ /dev/null @@ -1,5 +0,0 @@ -# Sample localization file for English. Add more files in this directory for other locales. -# See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points. - -en: - hello: "Hello world" diff --git a/tryruby/config/preinitializer.rb b/tryruby/config/preinitializer.rb deleted file mode 100644 index be50356..0000000 --- a/tryruby/config/preinitializer.rb +++ /dev/null @@ -1,20 +0,0 @@ -begin - require "rubygems" - require "bundler" -rescue LoadError - raise "Could not load the bundler gem. Install it with `gem install bundler`." -end - -if Gem::Version.new(Bundler::VERSION) <= Gem::Version.new("0.9.24") - raise RuntimeError, "Your bundler version is too old." + - "Run `gem install bundler` to upgrade." -end - -begin - # Set up load paths for all bundled gems - ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile", __FILE__) - Bundler.setup -rescue Bundler::GemNotFound - raise RuntimeError, "Bundler couldn't find some gems." + - "Did you run `bundle install`?" -end diff --git a/tryruby/config/routes.rb b/tryruby/config/routes.rb deleted file mode 100644 index 3d5bd3f..0000000 --- a/tryruby/config/routes.rb +++ /dev/null @@ -1,64 +0,0 @@ -TryRuby::Application.routes.draw do - resources :irb - - # The priority is based upon order of creation: - # first created -> highest priority. - root :to => "tryruby#index" - match '/tryruby/run' => 'tryruby#run' - # connect ':controller/:action/:id' - # connect ':controller/:action/:id.:format' - - # Sample of regular route: - # match 'products/:id' => 'catalog#view' - # Keep in mind you can assign values other than :controller and :action - - # Sample of named route: - # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase - # This route can be invoked with purchase_url(:id => product.id) - - # Sample resource route (maps HTTP verbs to controller actions automatically): - # resources :products - - # Sample resource route with options: - # resources :products do - # member do - # get 'short' - # post 'toggle' - # end - # - # collection do - # get 'sold' - # end - # end - - # Sample resource route with sub-resources: - # resources :products do - # resources :comments, :sales - # resource :seller - # end - - # Sample resource route with more complex sub-resources - # resources :products do - # resources :comments - # resources :sales do - # get 'recent', :on => :collection - # end - # end - - # Sample resource route within a namespace: - # namespace :admin do - # # Directs /admin/products/* to Admin::ProductsController - # # (app/controllers/admin/products_controller.rb) - # resources :products - # end - - # You can have the root of your site routed with "root" - # just remember to delete public/index.html. - # root :to => "welcome#index" - - # See how all your routes lay out with "rake routes" - - # This is a legacy wild controller route that's not recommended for RESTful applications. - # Note: This route will make all actions in every controller accessible via GET requests. - # match ':controller(/:action(/:id(.:format)))' -end diff --git a/tryruby/db/seeds.rb b/tryruby/db/seeds.rb deleted file mode 100644 index 664d8c7..0000000 --- a/tryruby/db/seeds.rb +++ /dev/null @@ -1,7 +0,0 @@ -# This file should contain all the record creation needed to seed the database with its default values. -# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). -# -# Examples: -# -# cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }]) -# Mayor.create(:name => 'Daley', :city => cities.first) diff --git a/tryruby/doc/README_FOR_APP b/tryruby/doc/README_FOR_APP deleted file mode 100644 index fe41f5c..0000000 --- a/tryruby/doc/README_FOR_APP +++ /dev/null @@ -1,2 +0,0 @@ -Use this README file to introduce your application and point to useful places in the API for learning more. -Run "rake doc:app" to generate API documentation for your models, controllers, helpers, and libraries. diff --git a/tryruby/doc/tryruby.rb b/tryruby/doc/tryruby.rb deleted file mode 100644 index b1390aa..0000000 --- a/tryruby/doc/tryruby.rb +++ /dev/null @@ -1,174 +0,0 @@ -$LOAD_PATH.unshift File.join(File.dirname(__FILE__), 'submodules', 'fakefs', 'lib') -require 'setup.rb' -require 'ruby_parser' -require 'fakefs/safe' -require 'stringio' - -module TryRuby - extend self - - class Session - attr_accessor :past_commands, :current_statement, :start_time - def initialize - @past_commands = '' - @current_statement = '' - @start_time = Time.now - end - end - - class Output - attr_reader :type, :result, :output, :error, :indent_level, :javascript - - def self.standard(params = {}) - Output.new type: :standard, result: params[:result], - output: params[:output] || '' - end - - def self.illegal - Output.new type: :illegal - end - - def self.javascript(js) - Output.new type: :javascript, javascript: js - end - - def self.no_output - Output.standard result: nil - end - - def self.line_continuation(level) - Output.new type: :line_continuation, indent_level: level - end - - def self.error(params = {}) - params[:error] ||= StandardError.new('TryRuby Error') - params[:error].message.gsub! /\(eval\):\d*/, '(TryRuby):1' - Output.new type: :error, error: params[:error], - output: params[:output] || '' - end - - def format - case @type - when :line_continuation - ".." * @indent_level - when :error - @output + "\033[1;33m#{@error.class}: #{@error.message}" - when :illegal - "\033[1;33mYou aren't allowed to run that command!" - when :javascript - "\033[1;JSm#{@javascript}\033[m " - else - @output + "=> \033[1;20m#{@result.inspect}" - end - end - - protected - def initialize(values = {}) - values.each do |variable, value| - instance_variable_set("@#{variable}", value) - end - end - end - - - class << self - attr_accessor :session - TryRuby.session = TryRuby::Session.new - end - - def calculate_nesting_level(statement) - begin - RubyParser.new.parse(statement) - 0 - rescue Racc::ParseError => e - case e.message - when /parse error on value \"\$end\" \(\$end\)/ then - new_statement = statement + "\n end" - begin - RubyParser.new.parse(new_statement) - return 1 - rescue Racc::ParseError => e - if e.message =~ /parse error on value \"end\" \(kEND\)/ then - new_statement = statement + "\n }" - end - end - begin - 1 + calculate_nesting_level(new_statement) - rescue Racc::ParseError => e - return 1 - end - else - raise e - end - end - end - - def run_line(code) - case code.strip - when '!INIT!IRB!' - return Output.no_output - when 'reset' - TryRuby.session.current_statement = '' - return Output.no_output - when 'time' - seconds = (Time.now - session.start_time).ceil - return Output.standard result: - if seconds < 60; "#{seconds} seconds" - elsif seconds < 120; "1 minute" - else; "#{seconds / 60} minutes" - end - end - - # nesting level - level = begin - calculate_nesting_level(session.current_statement + "\n" + code) - rescue Racc::ParseError, SyntaxError - 0 - end - if level > 0 - session.current_statement += "\n" + code - return Output.line_continuation(level) - end - - # run something - FakeFS.activate! - stdout_id = $stdout.to_i - $stdout = StringIO.new - cmd = <<-EOF - #{SetupCode} - $SAFE = 3 - #{session.past_commands} - $stdout = StringIO.new - begin - #{session.current_statement} - #{code} - end - EOF - begin - result = Thread.new { eval cmd, TOPLEVEL_BINDING }.value - rescue SecurityError - return Output.illegal - rescue Exception => e - return Output.error :error => e, :output => get_stdout - ensure - output = get_stdout - $stdout = IO.new(stdout_id) - FakeFS.deactivate! - end - - session.current_statement += "\n" + code - session.past_commands += "\n" + session.current_statement.strip - session.current_statement = '' - - return result if result.is_a? Output and result.type == :javascript - Output.standard result: result, output: output - end - - private - def get_stdout - raise TypeError, "$stdout is a #{$stdout.class}" unless $stdout.is_a? StringIO - $stdout.rewind - $stdout.read - end - -end \ No newline at end of file diff --git a/tryruby/lib/popup.rb b/tryruby/lib/popup.rb deleted file mode 100755 index 481fee9..0000000 --- a/tryruby/lib/popup.rb +++ /dev/null @@ -1,115 +0,0 @@ -class Symbol - def to_proc - Proc.new { |obj, *args| obj.send(self, *args) } - end -end -module LoadPopup -module Popup - def self.goto(url) - url = url.gsub '"', '\"' - TryRuby::Output.javascript "window.irb.options.popup_goto(\"#{url}\")" - end - - class Header - attr_accessor :level, :text - def initialize(level, text) - self.level, self.text = level, text - end - def generate_html - "#{self.text}" - end - - end - - class Link - attr_accessor :text, :target - def initialize(text, target) - self.text, self.target = text, target - end - def generate_html - "#{text}" - end - - - end - - class List - attr_accessor :elements - def initialize(elements) - self.elements = elements - end - - def generate_html - items = elements.map do |elem| - text = elem.instance_of?(Paragraph) ? elem.text : elem.generate_html - "
          2. #{text}
          3. " - end.join(" ") - - "
              #{items}
            " - end - end - - - class Paragraph - attr_accessor :text - def initialize(text) - self.text = text - end - - def generate_html - "

            #{self.text}

            " - end - end - - - class ComplexPopup - attr_reader :elements - def initialize - @elements = [] - end - - (1..6).each do |n| - define_method "h#{n}".to_sym do |text| - @elements << Header.new(n, text) - end - end - - - # def h1 text - # @elements << Header.new(1, text) - # end - - def link(text, target) - @elements << Link.new(text, target) - end - - def p(text) - @elements << Paragraph.new(text) - end - - def list(&block) - lst = ComplexPopup.new - lst.instance_eval(&block) - @elements << List.new(lst.elements) - end - - def generate_html() - @elements.map(&:generate_html).join(" ") - end - - - - end - - - def self.make(&block) - result = ComplexPopup.new - result.instance_eval(&block) - - html = result.generate_html.gsub('\\', '\\\\').gsub('"', '\"') - command = "window.irb.options.popup_make(\"#{html}\")" - TryRuby::Output.javascript command - end - -end -end \ No newline at end of file diff --git a/tryruby/lib/setup.rb b/tryruby/lib/setup.rb deleted file mode 100644 index 6bae16a..0000000 --- a/tryruby/lib/setup.rb +++ /dev/null @@ -1,68 +0,0 @@ -module TryRuby -SetupCode = <" - end - - def self.foreach(path) - self.read(path).each_line {|line| yield(line) } - end - - def self.expand_path(*args) - file_name, dir_string = args - dir_string ||= FileSystem.current_dir.to_s - if file_name == "/" - return "/" - elsif (file_name.start_with?("/")) - abs_file_name = RealFile.join(file_name) - else - abs_file_name = RealFile.join(dir_string, file_name) - end - path_parts = abs_file_name.split(RealFile::Separator) - result_path_parts = [""] - path_parts.each do |part| - case part - when ".." then result_path_parts.pop - when "." then # ignore - else result_path_parts.push(part) - end - end - RealFile.join(*result_path_parts) - end - - end - - module FileUtils - def copy(src, dest) - cp(src, dest) - nil - end - end -end - -module TryRuby - extend self - - class Session - attr_accessor :past_commands, :current_statement, :start_time - def initialize - @past_commands = '' - @current_statement = '' - @start_time = Time.now - end - end - - class Output - attr_reader :type, :result, :output, :error, :indent_level, :javascript - - def self.standard(params = {}) - Output.new type: :standard, result: params[:result], - output: params[:output] || '' - end - - def self.illegal - Output.new type: :illegal - end - - def self.javascript(js) - Output.new type: :javascript, javascript: js - end - - def self.no_output - Output.standard result: nil - end - - def self.line_continuation(level) - Output.new type: :line_continuation, indent_level: level - end - - def self.error(params = {}) - params[:error] ||= StandardError.new('TryRuby Error') - params[:error].message.gsub! /\(eval\):\d*/, '(TryRuby):1' - Output.new type: :error, error: params[:error], - output: params[:output] || '' - end - - def format - case @type - when :line_continuation - ".." * @indent_level - when :error - @output + "\033[1;33m#{@error.class}: #{@error.message}" - when :illegal - "\033[1;33mYou aren't allowed to run that command!" - when :javascript - "\033[1;JSm#{@javascript}\033[m " - else - @output + "=> \033[1;20m#{@result.inspect}" - end - end - - protected - def initialize(values = {}) - values.each do |variable, value| - instance_variable_set("@#{variable}", value) - end - end - end - - - class << self - attr_accessor :session - TryRuby.session = TryRuby::Session.new - end - - def calculate_nesting_level(statement) - begin - RubyParser.new.parse(statement) - 0 - rescue Racc::ParseError => e - case e.message - when /parse error on value \"\$end\" \(\$end\)/ then - new_statement = statement + "\n end" - begin - RubyParser.new.parse(new_statement) - return 1 - rescue Racc::ParseError => e - if e.message =~ /parse error on value \"end\" \(kEND\)/ then - new_statement = statement + "\n }" - end - end - begin - 1 + calculate_nesting_level(new_statement) - rescue Racc::ParseError => e - return 1 - end - else - raise e - end - end - end - - def run_line(code) - case code.strip - when '!INIT!IRB!' - return Output.no_output - when 'reset' - TryRuby.session.current_statement = '' - return Output.no_output - when 'time' - seconds = (Time.now - session.start_time).ceil - return Output.standard result: - if seconds < 60; "#{seconds} seconds" - elsif seconds < 120; "1 minute" - else; "#{seconds / 60} minutes" - end - end - - # nesting level - level = begin - calculate_nesting_level(session.current_statement + "\n" + code) - rescue Racc::ParseError, SyntaxError - 0 - end - if level > 0 - session.current_statement += "\n" + code - return Output.line_continuation(level) - end - - # run something - FakeFS.activate! - stdout_id = $stdout.to_i - $stdout = StringIO.new - cmd = <<-EOF - #{SetupCode} - $SAFE = 3 - #{session.past_commands} - $stdout = StringIO.new - begin - #{session.current_statement} - #{code} - end - EOF - begin - result = Thread.new { eval cmd, TOPLEVEL_BINDING }.value - rescue SecurityError => e - puts e - return Output.illegal :illegal => e, :output => get_stdout - rescue Exception => e - return Output.error :error => e, :output => get_stdout - ensure - output = get_stdout - $stdout = IO.new(stdout_id) - FakeFS.deactivate! - end - - session.current_statement += "\n" + code - session.past_commands += "\n" + session.current_statement.strip - session.current_statement = '' - - return result if result.is_a? Output and result.type == :javascript - Output.standard result: result, output: output - end - - private - def get_stdout - raise TypeError, "$stdout is a #{$stdout.class}" unless $stdout.is_a? StringIO - $stdout.rewind - $stdout.read - end - -end \ No newline at end of file diff --git a/tryruby/log/production.log b/tryruby/log/production.log deleted file mode 100644 index e69de29..0000000 diff --git a/tryruby/log/server.log b/tryruby/log/server.log deleted file mode 100644 index e69de29..0000000 diff --git a/tryruby/public/404.html b/tryruby/public/404.html deleted file mode 100644 index eff660b..0000000 --- a/tryruby/public/404.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - The page you were looking for doesn't exist (404) - - - - - -
            -

            The page you were looking for doesn't exist.

            -

            You may have mistyped the address or the page may have moved.

            -
            - - \ No newline at end of file diff --git a/tryruby/public/422.html b/tryruby/public/422.html deleted file mode 100644 index b54e4a3..0000000 --- a/tryruby/public/422.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - The change you wanted was rejected (422) - - - - - -
            -

            The change you wanted was rejected.

            -

            Maybe you tried to change something you didn't have access to.

            -
            - - \ No newline at end of file diff --git a/tryruby/public/500.html b/tryruby/public/500.html deleted file mode 100644 index ec3bbf0..0000000 --- a/tryruby/public/500.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - We're sorry, but something went wrong (500) - - - - - -
            -

            We're sorry, but something went wrong.

            -

            We've been notified about this issue and we'll take a look at it shortly.

            -
            - - diff --git a/tryruby/public/blank.html b/tryruby/public/blank.html deleted file mode 100755 index 7879e1c..0000000 --- a/tryruby/public/blank.html +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/tryruby/public/favicon.ico b/tryruby/public/favicon.ico deleted file mode 100644 index e69de29..0000000 diff --git a/tryruby/public/images/background.png b/tryruby/public/images/background.png deleted file mode 100755 index 3a2dee031614731e46c00b5f8416d471908af982..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35315 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 b}X6WEoFQ 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 AQ~&?~ diff --git a/tryruby/public/images/sick.gif b/tryruby/public/images/sick.gif deleted file mode 100755 index 217a67cbae60740fdc90b92e06b977cf7fc56699..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 94 zcmZ?wbhEHb|6Be#ZdVeV@YYlo&$tx`(sO@ILaF1IwM9!1&Y00000NkvXXu0mjf DW=Vhn diff --git a/tryruby/public/javascripts/application.js b/tryruby/public/javascripts/application.js deleted file mode 100644 index fe45776..0000000 --- a/tryruby/public/javascripts/application.js +++ /dev/null @@ -1,2 +0,0 @@ -// Place your application-specific JavaScript functions and classes here -// This file is automatically included by javascript_include_tag :defaults diff --git a/tryruby/public/javascripts/console.js b/tryruby/public/javascripts/console.js deleted file mode 100644 index e7e8b79..0000000 --- a/tryruby/public/javascripts/console.js +++ /dev/null @@ -1,288 +0,0 @@ -jQuery.fn.debug = function() { - var msg = jqArray.args(arguments); - $("
            ").addClass("error").text(msg.join(", ")).prependTo(this); -} - -jQConsole = function(input, output) { - - var args = jqArray.args - - var input = input; - - // History - var command_history = []; - var command_selected = 0; - - var local_scope = safe_scope(); - - function hide_fn(fn) { return function() { return fn.apply(this, arguments); } } - hide_fn.desc = "A function that creates a wrapper that hides the implementation of another function"; - function queue_fn(fn, time) { if(!time) time = 0; return function() { setTimeout(fn, time); } } - queue_fn.desc = "Turns a function into a function that's called later"; - - var keys = function (o) { - var r = []; - if (typeof o != "object") return r; - for (var k in o) r.push(k); - return r; - } - var refocus = queue_fn(function() { input.blur().focus(); }); - var reset_input = queue_fn(function() { input.val("").blur().focus(); }); - function no_recurse(fn, max_depth) { - var count = 0; - if(!max_depth) max_depth = 1; - return function() { - count++; - if(count > max_depth) { - count--; return; - } else { - fn.apply(this, arguments); - } - } - } - - function hook_fn(fn, listener) { - fn.listener = function() { return listener; } - fn.apply = function(thisArg, argArray) { - if(fn == caller) return; - listener(); - return fn.apply(thisArg, argArray); - }; - } - - hook_fn(history, function() { print("Yo"); }); - - $(document).ready(page_onload); - - function page_onload() { - input = $(input); - output = $(output); - input.keypress(map_keyboard()); - $(document).click(refocus); - refocus(); - } - page_onload = hide_fn(page_onload); - - function clear() { output.html(""); } - - function history() { - return command_history.join("\n"); - } - - var keyLogging = false; - - function map_keyboard() { - var cmdKeys = keymap(); - with(cmdKeys) { - mapKeyCode(toggleKeyLogging, 120); - map(executeCommand, {keyCode:13, ctrlKey:true}); - //mapKeyCode(executeCommand, 13); - mapKeyCode(refocus, 9); - map(historyLast, {keyCode:38, ctrlKey:true}); - map(historyNext, {keyCode:40, ctrlKey:true}); - map(function() { return false; }, {keyCode:123}); - } - return function(e) { - if(keyLogging) - log("keyCode: " + e.keyCode, " shiftKey: " + e.shiftKey, " ctrlKey: " + e.ctrlKey); - resize_input(); - return cmdKeys.dispatch(e); - } - } - - function toggleKeyLogging() { keyLogging = !keyLogging; } - - function historyLast() { - command_selected = Math.max(0, command_selected - 1); - edit_command(command_history[command_selected]); - } - - function historyNext() { - command_selected = Math.min(command_history.length, command_selected + 1); - var cmd = (command_selected == command_history.length) ? "" : command_history[command_selected]; - edit_command(cmd); - } - - function tryComplete() { - - refocus(); - } - - function executeCommand(cmd) { - cmd = (!cmd) ? input.val() : cmd; - reset_input(); - var result = evalInScope(cmd, default_scope); - command_selected = command_history.length; - logCommand(cmd, result); - setTimeout(function() { input.attr("rows", 1); }, 2); - return false; - } - - function evalInScope(cmd, scope) { - try { - - //if(!scope) return eval.apply(our_scope, [cmd]); - with(scope) { - with(jQConsole.our_scope) { - return eval(cmd); - } - } - - //move_modified_scope(local_scope, global_scope); - } - catch(e) { - return e.message; - } - } - - function move_modified_scope(l, g) { - - for(var k in g) { - if(g[k] && typeof l[k] == 'undefined') { - l[k] = g[k]; - g[k] = null; - } - } - } - - function safe_scope() { - var s = {}, g = jQConsole.global_scope; - for(var k in g) { s[k] = null; } - s.global_scope = jQConsole.global_scope; - return s; - } - - var encoders = { - "object": function(o, l) { - if(o.constructor == Array) - return encode_array(o); - //return "[array]"; - return "{ " + encode_obj(o, l) + " }"; - }, - "function": function(v) { return v.toString(); }, - "string": function(v) { return "\"" + v + "\""; }, - "undefined": function() { return "undefined"; }, - _default: function(v) { return v.toString(); } - } - - function encode_array(a) { - var r = a.map(enc); - return "[" + r.join(",") + "]"; - } - - enc = function(v, l, root) { - root = root || true; - if(v == null) return (root) ? "" : "null" + l; - if(encoders[typeof v]) return encoders[typeof v](v); - //log("enc", v, l); - return encoders._default(v, l); - } - - function encode_obj(val, expand) { - if(expand <= 0) { return val.toString(); } - var r = []; - for(var i in val) { - r.push(i + ": " + enc(val[i], expand - 1, false)); - } - return r.join(",\n"); - } - - function encode_reg(s) { - return s.replace(/([\\/\t\n])/g, "\\$1"); - } - - function reg_lookup_fn(lookup) { - var re = new RegExp(encode_reg(keys(lookup).join("")), "ig"); - return re; - } - - function print(msg) { - var className = (typeof msg == "function") ? "cmd" : "print"; - msg = enc(msg, 3); - if(!msg) return; - var out = $($.PRE({"className":className}, msg)); - if(className == "cmd") { out.click(select_command); } - output.prepend(out); - } - - function logCommand(cmd, result) { - command_history.push(cmd); - if(result != undefined) { - output.prepend(jQuery.dump(result)); - } - $($.PRE({className:'cmd'}, cmd)).click(select_command).prependTo(output); - //print(result); - return cmd; - } - - function select_command() { - edit_command($(this).text()); - } - - function edit_command(cmd) { - input.val(cmd); - resize_input(); - input.get(0).select(); - } - - function log() { - var msg = args(arguments); - $("
            ").text(msg.join(", ")).prependTo(output); - } - - function resize_input() - { - setTimeout(do_resize, 0); - - function do_resize() { - var rows = input.val().split(/\n/).length - // + 1 // prevent scrollbar flickering in Mozilla - + (window.opera ? 1 : 0); // leave room for scrollbar in Opera - - // without this check, it is impossible to select text in Opera 7.60 or Opera 8.0. - if (input.attr("rows") != rows) - input.attr("rows", rows); - } - } - - var default_scope = { - "log": log, - "history": history, - alert: function(msg) { alert(msg); } - } - disable_functions(default_scope, "window,document,t1"); - - function disable_functions(obj, list) { - var list = list.split(","); - for(var i in list) { - obj[list[i]] = {}; - } - } - - return this; -}; - -jQuery.extend(jQuery.fn, { - "autoresize": function() - { - var thisp = this; - setTimeout(do_resize, 0); - - function do_resize() { - var s = thisp.val() || ""; - var rows = s.split(/\n/).length; - // + 1 // prevent scrollbar flickering in Mozilla - + (window.opera ? 1 : 0); // leave room for scrollbar in Opera - - // without this check, it is impossible to select text in Opera 7.60 or Opera 8.0. - if (thisp.attr("rows") != rows) - thisp.attr("rows", rows); - } - return this; - } -}) - - - -jQConsole.global_scope = this; -jQConsole.our_scope = {}; \ No newline at end of file diff --git a/tryruby/public/javascripts/controls.js b/tryruby/public/javascripts/controls.js deleted file mode 100644 index ca29aef..0000000 --- a/tryruby/public/javascripts/controls.js +++ /dev/null @@ -1,963 +0,0 @@ -// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// (c) 2005-2008 Ivan Krstic (http://blogs.law.harvard.edu/ivan) -// (c) 2005-2008 Jon Tirsen (http://www.tirsen.com) -// Contributors: -// Richard Livsey -// Rahul Bhargava -// Rob Wills -// -// script.aculo.us is freely distributable under the terms of an MIT-style license. -// For details, see the script.aculo.us web site: http://script.aculo.us/ - -// Autocompleter.Base handles all the autocompletion functionality -// that's independent of the data source for autocompletion. This -// includes drawing the autocompletion menu, observing keyboard -// and mouse events, and similar. -// -// Specific autocompleters need to provide, at the very least, -// a getUpdatedChoices function that will be invoked every time -// the text inside the monitored textbox changes. This method -// should get the text for which to provide autocompletion by -// invoking this.getToken(), NOT by directly accessing -// this.element.value. This is to allow incremental tokenized -// autocompletion. Specific auto-completion logic (AJAX, etc) -// belongs in getUpdatedChoices. -// -// Tokenized incremental autocompletion is enabled automatically -// when an autocompleter is instantiated with the 'tokens' option -// in the options parameter, e.g.: -// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' }); -// will incrementally autocomplete with a comma as the token. -// Additionally, ',' in the above example can be replaced with -// a token array, e.g. { tokens: [',', '\n'] } which -// enables autocompletion on multiple tokens. This is most -// useful when one of the tokens is \n (a newline), as it -// allows smart autocompletion after linebreaks. - -if(typeof Effect == 'undefined') - throw("controls.js requires including script.aculo.us' effects.js library"); - -var Autocompleter = { }; -Autocompleter.Base = Class.create({ - baseInitialize: function(element, update, options) { - element = $(element); - this.element = element; - this.update = $(update); - this.hasFocus = false; - this.changed = false; - this.active = false; - this.index = 0; - this.entryCount = 0; - this.oldElementValue = this.element.value; - - if(this.setOptions) - this.setOptions(options); - else - this.options = options || { }; - - this.options.paramName = this.options.paramName || this.element.name; - this.options.tokens = this.options.tokens || []; - this.options.frequency = this.options.frequency || 0.4; - this.options.minChars = this.options.minChars || 1; - this.options.onShow = this.options.onShow || - function(element, update){ - if(!update.style.position || update.style.position=='absolute') { - update.style.position = 'absolute'; - Position.clone(element, update, { - setHeight: false, - offsetTop: element.offsetHeight - }); - } - Effect.Appear(update,{duration:0.15}); - }; - this.options.onHide = this.options.onHide || - function(element, update){ new Effect.Fade(update,{duration:0.15}) }; - - if(typeof(this.options.tokens) == 'string') - this.options.tokens = new Array(this.options.tokens); - // Force carriage returns as token delimiters anyway - if (!this.options.tokens.include('\n')) - this.options.tokens.push('\n'); - - this.observer = null; - - this.element.setAttribute('autocomplete','off'); - - Element.hide(this.update); - - Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this)); - Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this)); - }, - - show: function() { - if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update); - if(!this.iefix && - (Prototype.Browser.IE) && - (Element.getStyle(this.update, 'position')=='absolute')) { - new Insertion.After(this.update, - ''); - this.iefix = $(this.update.id+'_iefix'); - } - if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50); - }, - - fixIEOverlapping: function() { - Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)}); - this.iefix.style.zIndex = 1; - this.update.style.zIndex = 2; - Element.show(this.iefix); - }, - - hide: function() { - this.stopIndicator(); - if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update); - if(this.iefix) Element.hide(this.iefix); - }, - - startIndicator: function() { - if(this.options.indicator) Element.show(this.options.indicator); - }, - - stopIndicator: function() { - if(this.options.indicator) Element.hide(this.options.indicator); - }, - - onKeyPress: function(event) { - if(this.active) - switch(event.keyCode) { - case Event.KEY_TAB: - case Event.KEY_RETURN: - this.selectEntry(); - Event.stop(event); - case Event.KEY_ESC: - this.hide(); - this.active = false; - Event.stop(event); - return; - case Event.KEY_LEFT: - case Event.KEY_RIGHT: - return; - case Event.KEY_UP: - this.markPrevious(); - this.render(); - Event.stop(event); - return; - case Event.KEY_DOWN: - this.markNext(); - this.render(); - Event.stop(event); - return; - } - else - if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || - (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return; - - this.changed = true; - this.hasFocus = true; - - if(this.observer) clearTimeout(this.observer); - this.observer = - setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); - }, - - activate: function() { - this.changed = false; - this.hasFocus = true; - this.getUpdatedChoices(); - }, - - onHover: function(event) { - var element = Event.findElement(event, 'LI'); - if(this.index != element.autocompleteIndex) - { - this.index = element.autocompleteIndex; - this.render(); - } - Event.stop(event); - }, - - onClick: function(event) { - var element = Event.findElement(event, 'LI'); - this.index = element.autocompleteIndex; - this.selectEntry(); - this.hide(); - }, - - onBlur: function(event) { - // needed to make click events working - setTimeout(this.hide.bind(this), 250); - this.hasFocus = false; - this.active = false; - }, - - render: function() { - if(this.entryCount > 0) { - for (var i = 0; i < this.entryCount; i++) - this.index==i ? - Element.addClassName(this.getEntry(i),"selected") : - Element.removeClassName(this.getEntry(i),"selected"); - if(this.hasFocus) { - this.show(); - this.active = true; - } - } else { - this.active = false; - this.hide(); - } - }, - - markPrevious: function() { - if(this.index > 0) this.index--; - else this.index = this.entryCount-1; - this.getEntry(this.index).scrollIntoView(true); - }, - - markNext: function() { - if(this.index < this.entryCount-1) this.index++; - else this.index = 0; - this.getEntry(this.index).scrollIntoView(false); - }, - - getEntry: function(index) { - return this.update.firstChild.childNodes[index]; - }, - - getCurrentEntry: function() { - return this.getEntry(this.index); - }, - - selectEntry: function() { - this.active = false; - this.updateElement(this.getCurrentEntry()); - }, - - updateElement: function(selectedElement) { - if (this.options.updateElement) { - this.options.updateElement(selectedElement); - return; - } - var value = ''; - if (this.options.select) { - var nodes = $(selectedElement).select('.' + this.options.select) || []; - if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); - } else - value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); - - var bounds = this.getTokenBounds(); - if (bounds[0] != -1) { - var newValue = this.element.value.substr(0, bounds[0]); - var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/); - if (whitespace) - newValue += whitespace[0]; - this.element.value = newValue + value + this.element.value.substr(bounds[1]); - } else { - this.element.value = value; - } - this.oldElementValue = this.element.value; - this.element.focus(); - - if (this.options.afterUpdateElement) - this.options.afterUpdateElement(this.element, selectedElement); - }, - - updateChoices: function(choices) { - if(!this.changed && this.hasFocus) { - this.update.innerHTML = choices; - Element.cleanWhitespace(this.update); - Element.cleanWhitespace(this.update.down()); - - if(this.update.firstChild && this.update.down().childNodes) { - this.entryCount = - this.update.down().childNodes.length; - for (var i = 0; i < this.entryCount; i++) { - var entry = this.getEntry(i); - entry.autocompleteIndex = i; - this.addObservers(entry); - } - } else { - this.entryCount = 0; - } - - this.stopIndicator(); - this.index = 0; - - if(this.entryCount==1 && this.options.autoSelect) { - this.selectEntry(); - this.hide(); - } else { - this.render(); - } - } - }, - - addObservers: function(element) { - Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this)); - Event.observe(element, "click", this.onClick.bindAsEventListener(this)); - }, - - onObserverEvent: function() { - this.changed = false; - this.tokenBounds = null; - if(this.getToken().length>=this.options.minChars) { - this.getUpdatedChoices(); - } else { - this.active = false; - this.hide(); - } - this.oldElementValue = this.element.value; - }, - - getToken: function() { - var bounds = this.getTokenBounds(); - return this.element.value.substring(bounds[0], bounds[1]).strip(); - }, - - getTokenBounds: function() { - if (null != this.tokenBounds) return this.tokenBounds; - var value = this.element.value; - if (value.strip().empty()) return [-1, 0]; - var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue); - var offset = (diff == this.oldElementValue.length ? 1 : 0); - var prevTokenPos = -1, nextTokenPos = value.length; - var tp; - for (var index = 0, l = this.options.tokens.length; index < l; ++index) { - tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1); - if (tp > prevTokenPos) prevTokenPos = tp; - tp = value.indexOf(this.options.tokens[index], diff + offset); - if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp; - } - return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]); - } -}); - -Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) { - var boundary = Math.min(newS.length, oldS.length); - for (var index = 0; index < boundary; ++index) - if (newS[index] != oldS[index]) - return index; - return boundary; -}; - -Ajax.Autocompleter = Class.create(Autocompleter.Base, { - initialize: function(element, update, url, options) { - this.baseInitialize(element, update, options); - this.options.asynchronous = true; - this.options.onComplete = this.onComplete.bind(this); - this.options.defaultParams = this.options.parameters || null; - this.url = url; - }, - - getUpdatedChoices: function() { - this.startIndicator(); - - var entry = encodeURIComponent(this.options.paramName) + '=' + - encodeURIComponent(this.getToken()); - - this.options.parameters = this.options.callback ? - this.options.callback(this.element, entry) : entry; - - if(this.options.defaultParams) - this.options.parameters += '&' + this.options.defaultParams; - - new Ajax.Request(this.url, this.options); - }, - - onComplete: function(request) { - this.updateChoices(request.responseText); - } -}); - -// The local array autocompleter. Used when you'd prefer to -// inject an array of autocompletion options into the page, rather -// than sending out Ajax queries, which can be quite slow sometimes. -// -// The constructor takes four parameters. The first two are, as usual, -// the id of the monitored textbox, and id of the autocompletion menu. -// The third is the array you want to autocomplete from, and the fourth -// is the options block. -// -// Extra local autocompletion options: -// - choices - How many autocompletion choices to offer -// -// - partialSearch - If false, the autocompleter will match entered -// text only at the beginning of strings in the -// autocomplete array. Defaults to true, which will -// match text at the beginning of any *word* in the -// strings in the autocomplete array. If you want to -// search anywhere in the string, additionally set -// the option fullSearch to true (default: off). -// -// - fullSsearch - Search anywhere in autocomplete array strings. -// -// - partialChars - How many characters to enter before triggering -// a partial match (unlike minChars, which defines -// how many characters are required to do any match -// at all). Defaults to 2. -// -// - ignoreCase - Whether to ignore case when autocompleting. -// Defaults to true. -// -// It's possible to pass in a custom function as the 'selector' -// option, if you prefer to write your own autocompletion logic. -// In that case, the other options above will not apply unless -// you support them. - -Autocompleter.Local = Class.create(Autocompleter.Base, { - initialize: function(element, update, array, options) { - this.baseInitialize(element, update, options); - this.options.array = array; - }, - - getUpdatedChoices: function() { - this.updateChoices(this.options.selector(this)); - }, - - setOptions: function(options) { - this.options = Object.extend({ - choices: 10, - partialSearch: true, - partialChars: 2, - ignoreCase: true, - fullSearch: false, - selector: function(instance) { - var ret = []; // Beginning matches - var partial = []; // Inside matches - var entry = instance.getToken(); - var count = 0; - - for (var i = 0; i < instance.options.array.length && - ret.length < instance.options.choices ; i++) { - - var elem = instance.options.array[i]; - var foundPos = instance.options.ignoreCase ? - elem.toLowerCase().indexOf(entry.toLowerCase()) : - elem.indexOf(entry); - - while (foundPos != -1) { - if (foundPos == 0 && elem.length != entry.length) { - ret.push("
          4. " + elem.substr(0, entry.length) + "" + - elem.substr(entry.length) + "
          5. "); - break; - } else if (entry.length >= instance.options.partialChars && - instance.options.partialSearch && foundPos != -1) { - if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) { - partial.push("
          6. " + elem.substr(0, foundPos) + "" + - elem.substr(foundPos, entry.length) + "" + elem.substr( - foundPos + entry.length) + "
          7. "); - break; - } - } - - foundPos = instance.options.ignoreCase ? - elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : - elem.indexOf(entry, foundPos + 1); - - } - } - if (partial.length) - ret = ret.concat(partial.slice(0, instance.options.choices - ret.length)); - return "
              " + ret.join('') + "
            "; - } - }, options || { }); - } -}); - -// AJAX in-place editor and collection editor -// Full rewrite by Christophe Porteneuve (April 2007). - -// Use this if you notice weird scrolling problems on some browsers, -// the DOM might be a bit confused when this gets called so do this -// waits 1 ms (with setTimeout) until it does the activation -Field.scrollFreeActivate = function(field) { - setTimeout(function() { - Field.activate(field); - }, 1); -}; - -Ajax.InPlaceEditor = Class.create({ - initialize: function(element, url, options) { - this.url = url; - this.element = element = $(element); - this.prepareOptions(); - this._controls = { }; - arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!! - Object.extend(this.options, options || { }); - if (!this.options.formId && this.element.id) { - this.options.formId = this.element.id + '-inplaceeditor'; - if ($(this.options.formId)) - this.options.formId = ''; - } - if (this.options.externalControl) - this.options.externalControl = $(this.options.externalControl); - if (!this.options.externalControl) - this.options.externalControlOnly = false; - this._originalBackground = this.element.getStyle('background-color') || 'transparent'; - this.element.title = this.options.clickToEditText; - this._boundCancelHandler = this.handleFormCancellation.bind(this); - this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this); - this._boundFailureHandler = this.handleAJAXFailure.bind(this); - this._boundSubmitHandler = this.handleFormSubmission.bind(this); - this._boundWrapperHandler = this.wrapUp.bind(this); - this.registerListeners(); - }, - checkForEscapeOrReturn: function(e) { - if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return; - if (Event.KEY_ESC == e.keyCode) - this.handleFormCancellation(e); - else if (Event.KEY_RETURN == e.keyCode) - this.handleFormSubmission(e); - }, - createControl: function(mode, handler, extraClasses) { - var control = this.options[mode + 'Control']; - var text = this.options[mode + 'Text']; - if ('button' == control) { - var btn = document.createElement('input'); - btn.type = 'submit'; - btn.value = text; - btn.className = 'editor_' + mode + '_button'; - if ('cancel' == mode) - btn.onclick = this._boundCancelHandler; - this._form.appendChild(btn); - this._controls[mode] = btn; - } else if ('link' == control) { - var link = document.createElement('a'); - link.href = '#'; - link.appendChild(document.createTextNode(text)); - link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler; - link.className = 'editor_' + mode + '_link'; - if (extraClasses) - link.className += ' ' + extraClasses; - this._form.appendChild(link); - this._controls[mode] = link; - } - }, - createEditField: function() { - var text = (this.options.loadTextURL ? this.options.loadingText : this.getText()); - var fld; - if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) { - fld = document.createElement('input'); - fld.type = 'text'; - var size = this.options.size || this.options.cols || 0; - if (0 < size) fld.size = size; - } else { - fld = document.createElement('textarea'); - fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows); - fld.cols = this.options.cols || 40; - } - fld.name = this.options.paramName; - fld.value = text; // No HTML breaks conversion anymore - fld.className = 'editor_field'; - if (this.options.submitOnBlur) - fld.onblur = this._boundSubmitHandler; - this._controls.editor = fld; - if (this.options.loadTextURL) - this.loadExternalText(); - this._form.appendChild(this._controls.editor); - }, - createForm: function() { - var ipe = this; - function addText(mode, condition) { - var text = ipe.options['text' + mode + 'Controls']; - if (!text || condition === false) return; - ipe._form.appendChild(document.createTextNode(text)); - }; - this._form = $(document.createElement('form')); - this._form.id = this.options.formId; - this._form.addClassName(this.options.formClassName); - this._form.onsubmit = this._boundSubmitHandler; - this.createEditField(); - if ('textarea' == this._controls.editor.tagName.toLowerCase()) - this._form.appendChild(document.createElement('br')); - if (this.options.onFormCustomization) - this.options.onFormCustomization(this, this._form); - addText('Before', this.options.okControl || this.options.cancelControl); - this.createControl('ok', this._boundSubmitHandler); - addText('Between', this.options.okControl && this.options.cancelControl); - this.createControl('cancel', this._boundCancelHandler, 'editor_cancel'); - addText('After', this.options.okControl || this.options.cancelControl); - }, - destroy: function() { - if (this._oldInnerHTML) - this.element.innerHTML = this._oldInnerHTML; - this.leaveEditMode(); - this.unregisterListeners(); - }, - enterEditMode: function(e) { - if (this._saving || this._editing) return; - this._editing = true; - this.triggerCallback('onEnterEditMode'); - if (this.options.externalControl) - this.options.externalControl.hide(); - this.element.hide(); - this.createForm(); - this.element.parentNode.insertBefore(this._form, this.element); - if (!this.options.loadTextURL) - this.postProcessEditField(); - if (e) Event.stop(e); - }, - enterHover: function(e) { - if (this.options.hoverClassName) - this.element.addClassName(this.options.hoverClassName); - if (this._saving) return; - this.triggerCallback('onEnterHover'); - }, - getText: function() { - return this.element.innerHTML.unescapeHTML(); - }, - handleAJAXFailure: function(transport) { - this.triggerCallback('onFailure', transport); - if (this._oldInnerHTML) { - this.element.innerHTML = this._oldInnerHTML; - this._oldInnerHTML = null; - } - }, - handleFormCancellation: function(e) { - this.wrapUp(); - if (e) Event.stop(e); - }, - handleFormSubmission: function(e) { - var form = this._form; - var value = $F(this._controls.editor); - this.prepareSubmission(); - var params = this.options.callback(form, value) || ''; - if (Object.isString(params)) - params = params.toQueryParams(); - params.editorId = this.element.id; - if (this.options.htmlResponse) { - var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions); - Object.extend(options, { - parameters: params, - onComplete: this._boundWrapperHandler, - onFailure: this._boundFailureHandler - }); - new Ajax.Updater({ success: this.element }, this.url, options); - } else { - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: params, - onComplete: this._boundWrapperHandler, - onFailure: this._boundFailureHandler - }); - new Ajax.Request(this.url, options); - } - if (e) Event.stop(e); - }, - leaveEditMode: function() { - this.element.removeClassName(this.options.savingClassName); - this.removeForm(); - this.leaveHover(); - this.element.style.backgroundColor = this._originalBackground; - this.element.show(); - if (this.options.externalControl) - this.options.externalControl.show(); - this._saving = false; - this._editing = false; - this._oldInnerHTML = null; - this.triggerCallback('onLeaveEditMode'); - }, - leaveHover: function(e) { - if (this.options.hoverClassName) - this.element.removeClassName(this.options.hoverClassName); - if (this._saving) return; - this.triggerCallback('onLeaveHover'); - }, - loadExternalText: function() { - this._form.addClassName(this.options.loadingClassName); - this._controls.editor.disabled = true; - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: 'editorId=' + encodeURIComponent(this.element.id), - onComplete: Prototype.emptyFunction, - onSuccess: function(transport) { - this._form.removeClassName(this.options.loadingClassName); - var text = transport.responseText; - if (this.options.stripLoadedTextTags) - text = text.stripTags(); - this._controls.editor.value = text; - this._controls.editor.disabled = false; - this.postProcessEditField(); - }.bind(this), - onFailure: this._boundFailureHandler - }); - new Ajax.Request(this.options.loadTextURL, options); - }, - postProcessEditField: function() { - var fpc = this.options.fieldPostCreation; - if (fpc) - $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate'](); - }, - prepareOptions: function() { - this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions); - Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks); - [this._extraDefaultOptions].flatten().compact().each(function(defs) { - Object.extend(this.options, defs); - }.bind(this)); - }, - prepareSubmission: function() { - this._saving = true; - this.removeForm(); - this.leaveHover(); - this.showSaving(); - }, - registerListeners: function() { - this._listeners = { }; - var listener; - $H(Ajax.InPlaceEditor.Listeners).each(function(pair) { - listener = this[pair.value].bind(this); - this._listeners[pair.key] = listener; - if (!this.options.externalControlOnly) - this.element.observe(pair.key, listener); - if (this.options.externalControl) - this.options.externalControl.observe(pair.key, listener); - }.bind(this)); - }, - removeForm: function() { - if (!this._form) return; - this._form.remove(); - this._form = null; - this._controls = { }; - }, - showSaving: function() { - this._oldInnerHTML = this.element.innerHTML; - this.element.innerHTML = this.options.savingText; - this.element.addClassName(this.options.savingClassName); - this.element.style.backgroundColor = this._originalBackground; - this.element.show(); - }, - triggerCallback: function(cbName, arg) { - if ('function' == typeof this.options[cbName]) { - this.options[cbName](this, arg); - } - }, - unregisterListeners: function() { - $H(this._listeners).each(function(pair) { - if (!this.options.externalControlOnly) - this.element.stopObserving(pair.key, pair.value); - if (this.options.externalControl) - this.options.externalControl.stopObserving(pair.key, pair.value); - }.bind(this)); - }, - wrapUp: function(transport) { - this.leaveEditMode(); - // Can't use triggerCallback due to backward compatibility: requires - // binding + direct element - this._boundComplete(transport, this.element); - } -}); - -Object.extend(Ajax.InPlaceEditor.prototype, { - dispose: Ajax.InPlaceEditor.prototype.destroy -}); - -Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, { - initialize: function($super, element, url, options) { - this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions; - $super(element, url, options); - }, - - createEditField: function() { - var list = document.createElement('select'); - list.name = this.options.paramName; - list.size = 1; - this._controls.editor = list; - this._collection = this.options.collection || []; - if (this.options.loadCollectionURL) - this.loadCollection(); - else - this.checkForExternalText(); - this._form.appendChild(this._controls.editor); - }, - - loadCollection: function() { - this._form.addClassName(this.options.loadingClassName); - this.showLoadingText(this.options.loadingCollectionText); - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: 'editorId=' + encodeURIComponent(this.element.id), - onComplete: Prototype.emptyFunction, - onSuccess: function(transport) { - var js = transport.responseText.strip(); - if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check - throw('Server returned an invalid collection representation.'); - this._collection = eval(js); - this.checkForExternalText(); - }.bind(this), - onFailure: this.onFailure - }); - new Ajax.Request(this.options.loadCollectionURL, options); - }, - - showLoadingText: function(text) { - this._controls.editor.disabled = true; - var tempOption = this._controls.editor.firstChild; - if (!tempOption) { - tempOption = document.createElement('option'); - tempOption.value = ''; - this._controls.editor.appendChild(tempOption); - tempOption.selected = true; - } - tempOption.update((text || '').stripScripts().stripTags()); - }, - - checkForExternalText: function() { - this._text = this.getText(); - if (this.options.loadTextURL) - this.loadExternalText(); - else - this.buildOptionList(); - }, - - loadExternalText: function() { - this.showLoadingText(this.options.loadingText); - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: 'editorId=' + encodeURIComponent(this.element.id), - onComplete: Prototype.emptyFunction, - onSuccess: function(transport) { - this._text = transport.responseText.strip(); - this.buildOptionList(); - }.bind(this), - onFailure: this.onFailure - }); - new Ajax.Request(this.options.loadTextURL, options); - }, - - buildOptionList: function() { - this._form.removeClassName(this.options.loadingClassName); - this._collection = this._collection.map(function(entry) { - return 2 === entry.length ? entry : [entry, entry].flatten(); - }); - var marker = ('value' in this.options) ? this.options.value : this._text; - var textFound = this._collection.any(function(entry) { - return entry[0] == marker; - }.bind(this)); - this._controls.editor.update(''); - var option; - this._collection.each(function(entry, index) { - option = document.createElement('option'); - option.value = entry[0]; - option.selected = textFound ? entry[0] == marker : 0 == index; - option.appendChild(document.createTextNode(entry[1])); - this._controls.editor.appendChild(option); - }.bind(this)); - this._controls.editor.disabled = false; - Field.scrollFreeActivate(this._controls.editor); - } -}); - -//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! **** -//**** This only exists for a while, in order to let **** -//**** users adapt to the new API. Read up on the new **** -//**** API and convert your code to it ASAP! **** - -Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) { - if (!options) return; - function fallback(name, expr) { - if (name in options || expr === undefined) return; - options[name] = expr; - }; - fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' : - options.cancelLink == options.cancelButton == false ? false : undefined))); - fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' : - options.okLink == options.okButton == false ? false : undefined))); - fallback('highlightColor', options.highlightcolor); - fallback('highlightEndColor', options.highlightendcolor); -}; - -Object.extend(Ajax.InPlaceEditor, { - DefaultOptions: { - ajaxOptions: { }, - autoRows: 3, // Use when multi-line w/ rows == 1 - cancelControl: 'link', // 'link'|'button'|false - cancelText: 'cancel', - clickToEditText: 'Click to edit', - externalControl: null, // id|elt - externalControlOnly: false, - fieldPostCreation: 'activate', // 'activate'|'focus'|false - formClassName: 'inplaceeditor-form', - formId: null, // id|elt - highlightColor: '#ffff99', - highlightEndColor: '#ffffff', - hoverClassName: '', - htmlResponse: true, - loadingClassName: 'inplaceeditor-loading', - loadingText: 'Loading...', - okControl: 'button', // 'link'|'button'|false - okText: 'ok', - paramName: 'value', - rows: 1, // If 1 and multi-line, uses autoRows - savingClassName: 'inplaceeditor-saving', - savingText: 'Saving...', - size: 0, - stripLoadedTextTags: false, - submitOnBlur: false, - textAfterControls: '', - textBeforeControls: '', - textBetweenControls: '' - }, - DefaultCallbacks: { - callback: function(form) { - return Form.serialize(form); - }, - onComplete: function(transport, element) { - // For backward compatibility, this one is bound to the IPE, and passes - // the element directly. It was too often customized, so we don't break it. - new Effect.Highlight(element, { - startcolor: this.options.highlightColor, keepBackgroundImage: true }); - }, - onEnterEditMode: null, - onEnterHover: function(ipe) { - ipe.element.style.backgroundColor = ipe.options.highlightColor; - if (ipe._effect) - ipe._effect.cancel(); - }, - onFailure: function(transport, ipe) { - alert('Error communication with the server: ' + transport.responseText.stripTags()); - }, - onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls. - onLeaveEditMode: null, - onLeaveHover: function(ipe) { - ipe._effect = new Effect.Highlight(ipe.element, { - startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor, - restorecolor: ipe._originalBackground, keepBackgroundImage: true - }); - } - }, - Listeners: { - click: 'enterEditMode', - keydown: 'checkForEscapeOrReturn', - mouseover: 'enterHover', - mouseout: 'leaveHover' - } -}); - -Ajax.InPlaceCollectionEditor.DefaultOptions = { - loadingCollectionText: 'Loading options...' -}; - -// Delayed observer, like Form.Element.Observer, -// but waits for delay after last key input -// Ideal for live-search fields - -Form.Element.DelayedObserver = Class.create({ - initialize: function(element, delay, callback) { - this.delay = delay || 0.5; - this.element = $(element); - this.callback = callback; - this.timer = null; - this.lastValue = $F(this.element); - Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this)); - }, - delayedListener: function(event) { - if(this.lastValue == $F(this.element)) return; - if(this.timer) clearTimeout(this.timer); - this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000); - this.lastValue = $F(this.element); - }, - onTimerEvent: function() { - this.timer = null; - this.callback(this.element, $F(this.element)); - } -}); \ No newline at end of file diff --git a/tryruby/public/javascripts/dragdrop.js b/tryruby/public/javascripts/dragdrop.js deleted file mode 100644 index 07229f9..0000000 --- a/tryruby/public/javascripts/dragdrop.js +++ /dev/null @@ -1,973 +0,0 @@ -// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// (c) 2005-2008 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz) -// -// script.aculo.us is freely distributable under the terms of an MIT-style license. -// For details, see the script.aculo.us web site: http://script.aculo.us/ - -if(Object.isUndefined(Effect)) - throw("dragdrop.js requires including script.aculo.us' effects.js library"); - -var Droppables = { - drops: [], - - remove: function(element) { - this.drops = this.drops.reject(function(d) { return d.element==$(element) }); - }, - - add: function(element) { - element = $(element); - var options = Object.extend({ - greedy: true, - hoverclass: null, - tree: false - }, arguments[1] || { }); - - // cache containers - if(options.containment) { - options._containers = []; - var containment = options.containment; - if(Object.isArray(containment)) { - containment.each( function(c) { options._containers.push($(c)) }); - } else { - options._containers.push($(containment)); - } - } - - if(options.accept) options.accept = [options.accept].flatten(); - - Element.makePositioned(element); // fix IE - options.element = element; - - this.drops.push(options); - }, - - findDeepestChild: function(drops) { - deepest = drops[0]; - - for (i = 1; i < drops.length; ++i) - if (Element.isParent(drops[i].element, deepest.element)) - deepest = drops[i]; - - return deepest; - }, - - isContained: function(element, drop) { - var containmentNode; - if(drop.tree) { - containmentNode = element.treeNode; - } else { - containmentNode = element.parentNode; - } - return drop._containers.detect(function(c) { return containmentNode == c }); - }, - - isAffected: function(point, element, drop) { - return ( - (drop.element!=element) && - ((!drop._containers) || - this.isContained(element, drop)) && - ((!drop.accept) || - (Element.classNames(element).detect( - function(v) { return drop.accept.include(v) } ) )) && - Position.within(drop.element, point[0], point[1]) ); - }, - - deactivate: function(drop) { - if(drop.hoverclass) - Element.removeClassName(drop.element, drop.hoverclass); - this.last_active = null; - }, - - activate: function(drop) { - if(drop.hoverclass) - Element.addClassName(drop.element, drop.hoverclass); - this.last_active = drop; - }, - - show: function(point, element) { - if(!this.drops.length) return; - var drop, affected = []; - - this.drops.each( function(drop) { - if(Droppables.isAffected(point, element, drop)) - affected.push(drop); - }); - - if(affected.length>0) - drop = Droppables.findDeepestChild(affected); - - if(this.last_active && this.last_active != drop) this.deactivate(this.last_active); - if (drop) { - Position.within(drop.element, point[0], point[1]); - if(drop.onHover) - drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); - - if (drop != this.last_active) Droppables.activate(drop); - } - }, - - fire: function(event, element) { - if(!this.last_active) return; - Position.prepare(); - - if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active)) - if (this.last_active.onDrop) { - this.last_active.onDrop(element, this.last_active.element, event); - return true; - } - }, - - reset: function() { - if(this.last_active) - this.deactivate(this.last_active); - } -}; - -var Draggables = { - drags: [], - observers: [], - - register: function(draggable) { - if(this.drags.length == 0) { - this.eventMouseUp = this.endDrag.bindAsEventListener(this); - this.eventMouseMove = this.updateDrag.bindAsEventListener(this); - this.eventKeypress = this.keyPress.bindAsEventListener(this); - - Event.observe(document, "mouseup", this.eventMouseUp); - Event.observe(document, "mousemove", this.eventMouseMove); - Event.observe(document, "keypress", this.eventKeypress); - } - this.drags.push(draggable); - }, - - unregister: function(draggable) { - this.drags = this.drags.reject(function(d) { return d==draggable }); - if(this.drags.length == 0) { - Event.stopObserving(document, "mouseup", this.eventMouseUp); - Event.stopObserving(document, "mousemove", this.eventMouseMove); - Event.stopObserving(document, "keypress", this.eventKeypress); - } - }, - - activate: function(draggable) { - if(draggable.options.delay) { - this._timeout = setTimeout(function() { - Draggables._timeout = null; - window.focus(); - Draggables.activeDraggable = draggable; - }.bind(this), draggable.options.delay); - } else { - window.focus(); // allows keypress events if window isn't currently focused, fails for Safari - this.activeDraggable = draggable; - } - }, - - deactivate: function() { - this.activeDraggable = null; - }, - - updateDrag: function(event) { - if(!this.activeDraggable) return; - var pointer = [Event.pointerX(event), Event.pointerY(event)]; - // Mozilla-based browsers fire successive mousemove events with - // the same coordinates, prevent needless redrawing (moz bug?) - if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return; - this._lastPointer = pointer; - - this.activeDraggable.updateDrag(event, pointer); - }, - - endDrag: function(event) { - if(this._timeout) { - clearTimeout(this._timeout); - this._timeout = null; - } - if(!this.activeDraggable) return; - this._lastPointer = null; - this.activeDraggable.endDrag(event); - this.activeDraggable = null; - }, - - keyPress: function(event) { - if(this.activeDraggable) - this.activeDraggable.keyPress(event); - }, - - addObserver: function(observer) { - this.observers.push(observer); - this._cacheObserverCallbacks(); - }, - - removeObserver: function(element) { // element instead of observer fixes mem leaks - this.observers = this.observers.reject( function(o) { return o.element==element }); - this._cacheObserverCallbacks(); - }, - - notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag' - if(this[eventName+'Count'] > 0) - this.observers.each( function(o) { - if(o[eventName]) o[eventName](eventName, draggable, event); - }); - if(draggable.options[eventName]) draggable.options[eventName](draggable, event); - }, - - _cacheObserverCallbacks: function() { - ['onStart','onEnd','onDrag'].each( function(eventName) { - Draggables[eventName+'Count'] = Draggables.observers.select( - function(o) { return o[eventName]; } - ).length; - }); - } -}; - -/*--------------------------------------------------------------------------*/ - -var Draggable = Class.create({ - initialize: function(element) { - var defaults = { - handle: false, - reverteffect: function(element, top_offset, left_offset) { - var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02; - new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur, - queue: {scope:'_draggable', position:'end'} - }); - }, - endeffect: function(element) { - var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0; - new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity, - queue: {scope:'_draggable', position:'end'}, - afterFinish: function(){ - Draggable._dragging[element] = false - } - }); - }, - zindex: 1000, - revert: false, - quiet: false, - scroll: false, - scrollSensitivity: 20, - scrollSpeed: 15, - snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] } - delay: 0 - }; - - if(!arguments[1] || Object.isUndefined(arguments[1].endeffect)) - Object.extend(defaults, { - starteffect: function(element) { - element._opacity = Element.getOpacity(element); - Draggable._dragging[element] = true; - new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7}); - } - }); - - var options = Object.extend(defaults, arguments[1] || { }); - - this.element = $(element); - - if(options.handle && Object.isString(options.handle)) - this.handle = this.element.down('.'+options.handle, 0); - - if(!this.handle) this.handle = $(options.handle); - if(!this.handle) this.handle = this.element; - - if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) { - options.scroll = $(options.scroll); - this._isScrollChild = Element.childOf(this.element, options.scroll); - } - - Element.makePositioned(this.element); // fix IE - - this.options = options; - this.dragging = false; - - this.eventMouseDown = this.initDrag.bindAsEventListener(this); - Event.observe(this.handle, "mousedown", this.eventMouseDown); - - Draggables.register(this); - }, - - destroy: function() { - Event.stopObserving(this.handle, "mousedown", this.eventMouseDown); - Draggables.unregister(this); - }, - - currentDelta: function() { - return([ - parseInt(Element.getStyle(this.element,'left') || '0'), - parseInt(Element.getStyle(this.element,'top') || '0')]); - }, - - initDrag: function(event) { - if(!Object.isUndefined(Draggable._dragging[this.element]) && - Draggable._dragging[this.element]) return; - if(Event.isLeftClick(event)) { - // abort on form elements, fixes a Firefox issue - var src = Event.element(event); - if((tag_name = src.tagName.toUpperCase()) && ( - tag_name=='INPUT' || - tag_name=='SELECT' || - tag_name=='OPTION' || - tag_name=='BUTTON' || - tag_name=='TEXTAREA')) return; - - var pointer = [Event.pointerX(event), Event.pointerY(event)]; - var pos = Position.cumulativeOffset(this.element); - this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) }); - - Draggables.activate(this); - Event.stop(event); - } - }, - - startDrag: function(event) { - this.dragging = true; - if(!this.delta) - this.delta = this.currentDelta(); - - if(this.options.zindex) { - this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0); - this.element.style.zIndex = this.options.zindex; - } - - if(this.options.ghosting) { - this._clone = this.element.cloneNode(true); - this._originallyAbsolute = (this.element.getStyle('position') == 'absolute'); - if (!this._originallyAbsolute) - Position.absolutize(this.element); - this.element.parentNode.insertBefore(this._clone, this.element); - } - - if(this.options.scroll) { - if (this.options.scroll == window) { - var where = this._getWindowScroll(this.options.scroll); - this.originalScrollLeft = where.left; - this.originalScrollTop = where.top; - } else { - this.originalScrollLeft = this.options.scroll.scrollLeft; - this.originalScrollTop = this.options.scroll.scrollTop; - } - } - - Draggables.notify('onStart', this, event); - - if(this.options.starteffect) this.options.starteffect(this.element); - }, - - updateDrag: function(event, pointer) { - if(!this.dragging) this.startDrag(event); - - if(!this.options.quiet){ - Position.prepare(); - Droppables.show(pointer, this.element); - } - - Draggables.notify('onDrag', this, event); - - this.draw(pointer); - if(this.options.change) this.options.change(this); - - if(this.options.scroll) { - this.stopScrolling(); - - var p; - if (this.options.scroll == window) { - with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; } - } else { - p = Position.page(this.options.scroll); - p[0] += this.options.scroll.scrollLeft + Position.deltaX; - p[1] += this.options.scroll.scrollTop + Position.deltaY; - p.push(p[0]+this.options.scroll.offsetWidth); - p.push(p[1]+this.options.scroll.offsetHeight); - } - var speed = [0,0]; - if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity); - if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity); - if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity); - if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity); - this.startScrolling(speed); - } - - // fix AppleWebKit rendering - if(Prototype.Browser.WebKit) window.scrollBy(0,0); - - Event.stop(event); - }, - - finishDrag: function(event, success) { - this.dragging = false; - - if(this.options.quiet){ - Position.prepare(); - var pointer = [Event.pointerX(event), Event.pointerY(event)]; - Droppables.show(pointer, this.element); - } - - if(this.options.ghosting) { - if (!this._originallyAbsolute) - Position.relativize(this.element); - delete this._originallyAbsolute; - Element.remove(this._clone); - this._clone = null; - } - - var dropped = false; - if(success) { - dropped = Droppables.fire(event, this.element); - if (!dropped) dropped = false; - } - if(dropped && this.options.onDropped) this.options.onDropped(this.element); - Draggables.notify('onEnd', this, event); - - var revert = this.options.revert; - if(revert && Object.isFunction(revert)) revert = revert(this.element); - - var d = this.currentDelta(); - if(revert && this.options.reverteffect) { - if (dropped == 0 || revert != 'failure') - this.options.reverteffect(this.element, - d[1]-this.delta[1], d[0]-this.delta[0]); - } else { - this.delta = d; - } - - if(this.options.zindex) - this.element.style.zIndex = this.originalZ; - - if(this.options.endeffect) - this.options.endeffect(this.element); - - Draggables.deactivate(this); - Droppables.reset(); - }, - - keyPress: function(event) { - if(event.keyCode!=Event.KEY_ESC) return; - this.finishDrag(event, false); - Event.stop(event); - }, - - endDrag: function(event) { - if(!this.dragging) return; - this.stopScrolling(); - this.finishDrag(event, true); - Event.stop(event); - }, - - draw: function(point) { - var pos = Position.cumulativeOffset(this.element); - if(this.options.ghosting) { - var r = Position.realOffset(this.element); - pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY; - } - - var d = this.currentDelta(); - pos[0] -= d[0]; pos[1] -= d[1]; - - if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) { - pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft; - pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop; - } - - var p = [0,1].map(function(i){ - return (point[i]-pos[i]-this.offset[i]) - }.bind(this)); - - if(this.options.snap) { - if(Object.isFunction(this.options.snap)) { - p = this.options.snap(p[0],p[1],this); - } else { - if(Object.isArray(this.options.snap)) { - p = p.map( function(v, i) { - return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this)); - } else { - p = p.map( function(v) { - return (v/this.options.snap).round()*this.options.snap }.bind(this)); - } - }} - - var style = this.element.style; - if((!this.options.constraint) || (this.options.constraint=='horizontal')) - style.left = p[0] + "px"; - if((!this.options.constraint) || (this.options.constraint=='vertical')) - style.top = p[1] + "px"; - - if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering - }, - - stopScrolling: function() { - if(this.scrollInterval) { - clearInterval(this.scrollInterval); - this.scrollInterval = null; - Draggables._lastScrollPointer = null; - } - }, - - startScrolling: function(speed) { - if(!(speed[0] || speed[1])) return; - this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed]; - this.lastScrolled = new Date(); - this.scrollInterval = setInterval(this.scroll.bind(this), 10); - }, - - scroll: function() { - var current = new Date(); - var delta = current - this.lastScrolled; - this.lastScrolled = current; - if(this.options.scroll == window) { - with (this._getWindowScroll(this.options.scroll)) { - if (this.scrollSpeed[0] || this.scrollSpeed[1]) { - var d = delta / 1000; - this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] ); - } - } - } else { - this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; - this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000; - } - - Position.prepare(); - Droppables.show(Draggables._lastPointer, this.element); - Draggables.notify('onDrag', this); - if (this._isScrollChild) { - Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer); - Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000; - Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000; - if (Draggables._lastScrollPointer[0] < 0) - Draggables._lastScrollPointer[0] = 0; - if (Draggables._lastScrollPointer[1] < 0) - Draggables._lastScrollPointer[1] = 0; - this.draw(Draggables._lastScrollPointer); - } - - if(this.options.change) this.options.change(this); - }, - - _getWindowScroll: function(w) { - var T, L, W, H; - with (w.document) { - if (w.document.documentElement && documentElement.scrollTop) { - T = documentElement.scrollTop; - L = documentElement.scrollLeft; - } else if (w.document.body) { - T = body.scrollTop; - L = body.scrollLeft; - } - if (w.innerWidth) { - W = w.innerWidth; - H = w.innerHeight; - } else if (w.document.documentElement && documentElement.clientWidth) { - W = documentElement.clientWidth; - H = documentElement.clientHeight; - } else { - W = body.offsetWidth; - H = body.offsetHeight; - } - } - return { top: T, left: L, width: W, height: H }; - } -}); - -Draggable._dragging = { }; - -/*--------------------------------------------------------------------------*/ - -var SortableObserver = Class.create({ - initialize: function(element, observer) { - this.element = $(element); - this.observer = observer; - this.lastValue = Sortable.serialize(this.element); - }, - - onStart: function() { - this.lastValue = Sortable.serialize(this.element); - }, - - onEnd: function() { - Sortable.unmark(); - if(this.lastValue != Sortable.serialize(this.element)) - this.observer(this.element) - } -}); - -var Sortable = { - SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/, - - sortables: { }, - - _findRootElement: function(element) { - while (element.tagName.toUpperCase() != "BODY") { - if(element.id && Sortable.sortables[element.id]) return element; - element = element.parentNode; - } - }, - - options: function(element) { - element = Sortable._findRootElement($(element)); - if(!element) return; - return Sortable.sortables[element.id]; - }, - - destroy: function(element){ - element = $(element); - var s = Sortable.sortables[element.id]; - - if(s) { - Draggables.removeObserver(s.element); - s.droppables.each(function(d){ Droppables.remove(d) }); - s.draggables.invoke('destroy'); - - delete Sortable.sortables[s.element.id]; - } - }, - - create: function(element) { - element = $(element); - var options = Object.extend({ - element: element, - tag: 'li', // assumes li children, override with tag: 'tagname' - dropOnEmpty: false, - tree: false, - treeTag: 'ul', - overlap: 'vertical', // one of 'vertical', 'horizontal' - constraint: 'vertical', // one of 'vertical', 'horizontal', false - containment: element, // also takes array of elements (or id's); or false - handle: false, // or a CSS class - only: false, - delay: 0, - hoverclass: null, - ghosting: false, - quiet: false, - scroll: false, - scrollSensitivity: 20, - scrollSpeed: 15, - format: this.SERIALIZE_RULE, - - // these take arrays of elements or ids and can be - // used for better initialization performance - elements: false, - handles: false, - - onChange: Prototype.emptyFunction, - onUpdate: Prototype.emptyFunction - }, arguments[1] || { }); - - // clear any old sortable with same element - this.destroy(element); - - // build options for the draggables - var options_for_draggable = { - revert: true, - quiet: options.quiet, - scroll: options.scroll, - scrollSpeed: options.scrollSpeed, - scrollSensitivity: options.scrollSensitivity, - delay: options.delay, - ghosting: options.ghosting, - constraint: options.constraint, - handle: options.handle }; - - if(options.starteffect) - options_for_draggable.starteffect = options.starteffect; - - if(options.reverteffect) - options_for_draggable.reverteffect = options.reverteffect; - else - if(options.ghosting) options_for_draggable.reverteffect = function(element) { - element.style.top = 0; - element.style.left = 0; - }; - - if(options.endeffect) - options_for_draggable.endeffect = options.endeffect; - - if(options.zindex) - options_for_draggable.zindex = options.zindex; - - // build options for the droppables - var options_for_droppable = { - overlap: options.overlap, - containment: options.containment, - tree: options.tree, - hoverclass: options.hoverclass, - onHover: Sortable.onHover - }; - - var options_for_tree = { - onHover: Sortable.onEmptyHover, - overlap: options.overlap, - containment: options.containment, - hoverclass: options.hoverclass - }; - - // fix for gecko engine - Element.cleanWhitespace(element); - - options.draggables = []; - options.droppables = []; - - // drop on empty handling - if(options.dropOnEmpty || options.tree) { - Droppables.add(element, options_for_tree); - options.droppables.push(element); - } - - (options.elements || this.findElements(element, options) || []).each( function(e,i) { - var handle = options.handles ? $(options.handles[i]) : - (options.handle ? $(e).select('.' + options.handle)[0] : e); - options.draggables.push( - new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); - Droppables.add(e, options_for_droppable); - if(options.tree) e.treeNode = element; - options.droppables.push(e); - }); - - if(options.tree) { - (Sortable.findTreeElements(element, options) || []).each( function(e) { - Droppables.add(e, options_for_tree); - e.treeNode = element; - options.droppables.push(e); - }); - } - - // keep reference - this.sortables[element.id] = options; - - // for onupdate - Draggables.addObserver(new SortableObserver(element, options.onUpdate)); - - }, - - // return all suitable-for-sortable elements in a guaranteed order - findElements: function(element, options) { - return Element.findChildren( - element, options.only, options.tree ? true : false, options.tag); - }, - - findTreeElements: function(element, options) { - return Element.findChildren( - element, options.only, options.tree ? true : false, options.treeTag); - }, - - onHover: function(element, dropon, overlap) { - if(Element.isParent(dropon, element)) return; - - if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) { - return; - } else if(overlap>0.5) { - Sortable.mark(dropon, 'before'); - if(dropon.previousSibling != element) { - var oldParentNode = element.parentNode; - element.style.visibility = "hidden"; // fix gecko rendering - dropon.parentNode.insertBefore(element, dropon); - if(dropon.parentNode!=oldParentNode) - Sortable.options(oldParentNode).onChange(element); - Sortable.options(dropon.parentNode).onChange(element); - } - } else { - Sortable.mark(dropon, 'after'); - var nextElement = dropon.nextSibling || null; - if(nextElement != element) { - var oldParentNode = element.parentNode; - element.style.visibility = "hidden"; // fix gecko rendering - dropon.parentNode.insertBefore(element, nextElement); - if(dropon.parentNode!=oldParentNode) - Sortable.options(oldParentNode).onChange(element); - Sortable.options(dropon.parentNode).onChange(element); - } - } - }, - - onEmptyHover: function(element, dropon, overlap) { - var oldParentNode = element.parentNode; - var droponOptions = Sortable.options(dropon); - - if(!Element.isParent(dropon, element)) { - var index; - - var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only}); - var child = null; - - if(children) { - var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap); - - for (index = 0; index < children.length; index += 1) { - if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) { - offset -= Element.offsetSize (children[index], droponOptions.overlap); - } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) { - child = index + 1 < children.length ? children[index + 1] : null; - break; - } else { - child = children[index]; - break; - } - } - } - - dropon.insertBefore(element, child); - - Sortable.options(oldParentNode).onChange(element); - droponOptions.onChange(element); - } - }, - - unmark: function() { - if(Sortable._marker) Sortable._marker.hide(); - }, - - mark: function(dropon, position) { - // mark on ghosting only - var sortable = Sortable.options(dropon.parentNode); - if(sortable && !sortable.ghosting) return; - - if(!Sortable._marker) { - Sortable._marker = - ($('dropmarker') || Element.extend(document.createElement('DIV'))). - hide().addClassName('dropmarker').setStyle({position:'absolute'}); - document.getElementsByTagName("body").item(0).appendChild(Sortable._marker); - } - var offsets = Position.cumulativeOffset(dropon); - Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'}); - - if(position=='after') - if(sortable.overlap == 'horizontal') - Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'}); - else - Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'}); - - Sortable._marker.show(); - }, - - _tree: function(element, options, parent) { - var children = Sortable.findElements(element, options) || []; - - for (var i = 0; i < children.length; ++i) { - var match = children[i].id.match(options.format); - - if (!match) continue; - - var child = { - id: encodeURIComponent(match ? match[1] : null), - element: element, - parent: parent, - children: [], - position: parent.children.length, - container: $(children[i]).down(options.treeTag) - }; - - /* Get the element containing the children and recurse over it */ - if (child.container) - this._tree(child.container, options, child); - - parent.children.push (child); - } - - return parent; - }, - - tree: function(element) { - element = $(element); - var sortableOptions = this.options(element); - var options = Object.extend({ - tag: sortableOptions.tag, - treeTag: sortableOptions.treeTag, - only: sortableOptions.only, - name: element.id, - format: sortableOptions.format - }, arguments[1] || { }); - - var root = { - id: null, - parent: null, - children: [], - container: element, - position: 0 - }; - - return Sortable._tree(element, options, root); - }, - - /* Construct a [i] index for a particular node */ - _constructIndex: function(node) { - var index = ''; - do { - if (node.id) index = '[' + node.position + ']' + index; - } while ((node = node.parent) != null); - return index; - }, - - sequence: function(element) { - element = $(element); - var options = Object.extend(this.options(element), arguments[1] || { }); - - return $(this.findElements(element, options) || []).map( function(item) { - return item.id.match(options.format) ? item.id.match(options.format)[1] : ''; - }); - }, - - setSequence: function(element, new_sequence) { - element = $(element); - var options = Object.extend(this.options(element), arguments[2] || { }); - - var nodeMap = { }; - this.findElements(element, options).each( function(n) { - if (n.id.match(options.format)) - nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode]; - n.parentNode.removeChild(n); - }); - - new_sequence.each(function(ident) { - var n = nodeMap[ident]; - if (n) { - n[1].appendChild(n[0]); - delete nodeMap[ident]; - } - }); - }, - - serialize: function(element) { - element = $(element); - var options = Object.extend(Sortable.options(element), arguments[1] || { }); - var name = encodeURIComponent( - (arguments[1] && arguments[1].name) ? arguments[1].name : element.id); - - if (options.tree) { - return Sortable.tree(element, arguments[1]).children.map( function (item) { - return [name + Sortable._constructIndex(item) + "[id]=" + - encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)); - }).flatten().join('&'); - } else { - return Sortable.sequence(element, arguments[1]).map( function(item) { - return name + "[]=" + encodeURIComponent(item); - }).join('&'); - } - } -}; - -// Returns true if child is contained within element -Element.isParent = function(child, element) { - if (!child.parentNode || child == element) return false; - if (child.parentNode == element) return true; - return Element.isParent(child.parentNode, element); -}; - -Element.findChildren = function(element, only, recursive, tagName) { - if(!element.hasChildNodes()) return null; - tagName = tagName.toUpperCase(); - if(only) only = [only].flatten(); - var elements = []; - $A(element.childNodes).each( function(e) { - if(e.tagName && e.tagName.toUpperCase()==tagName && - (!only || (Element.classNames(e).detect(function(v) { return only.include(v) })))) - elements.push(e); - if(recursive) { - var grandchildren = Element.findChildren(e, only, recursive, tagName); - if(grandchildren) elements.push(grandchildren); - } - }); - - return (elements.length>0 ? elements.flatten() : []); -}; - -Element.offsetSize = function (element, type) { - return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')]; -}; \ No newline at end of file diff --git a/tryruby/public/javascripts/effects.js b/tryruby/public/javascripts/effects.js deleted file mode 100644 index 5a639d2..0000000 --- a/tryruby/public/javascripts/effects.js +++ /dev/null @@ -1,1128 +0,0 @@ -// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// Contributors: -// Justin Palmer (http://encytemedia.com/) -// Mark Pilgrim (http://diveintomark.org/) -// Martin Bialasinki -// -// script.aculo.us is freely distributable under the terms of an MIT-style license. -// For details, see the script.aculo.us web site: http://script.aculo.us/ - -// converts rgb() and #xxx to #xxxxxx format, -// returns self (or first argument) if not convertable -String.prototype.parseColor = function() { - var color = '#'; - if (this.slice(0,4) == 'rgb(') { - var cols = this.slice(4,this.length-1).split(','); - var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); - } else { - if (this.slice(0,1) == '#') { - if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); - if (this.length==7) color = this.toLowerCase(); - } - } - return (color.length==7 ? color : (arguments[0] || this)); -}; - -/*--------------------------------------------------------------------------*/ - -Element.collectTextNodes = function(element) { - return $A($(element).childNodes).collect( function(node) { - return (node.nodeType==3 ? node.nodeValue : - (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); - }).flatten().join(''); -}; - -Element.collectTextNodesIgnoreClass = function(element, className) { - return $A($(element).childNodes).collect( function(node) { - return (node.nodeType==3 ? node.nodeValue : - ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? - Element.collectTextNodesIgnoreClass(node, className) : '')); - }).flatten().join(''); -}; - -Element.setContentZoom = function(element, percent) { - element = $(element); - element.setStyle({fontSize: (percent/100) + 'em'}); - if (Prototype.Browser.WebKit) window.scrollBy(0,0); - return element; -}; - -Element.getInlineOpacity = function(element){ - return $(element).style.opacity || ''; -}; - -Element.forceRerendering = function(element) { - try { - element = $(element); - var n = document.createTextNode(' '); - element.appendChild(n); - element.removeChild(n); - } catch(e) { } -}; - -/*--------------------------------------------------------------------------*/ - -var Effect = { - _elementDoesNotExistError: { - name: 'ElementDoesNotExistError', - message: 'The specified DOM element does not exist, but is required for this effect to operate' - }, - Transitions: { - linear: Prototype.K, - sinoidal: function(pos) { - return (-Math.cos(pos*Math.PI)/2) + .5; - }, - reverse: function(pos) { - return 1-pos; - }, - flicker: function(pos) { - var pos = ((-Math.cos(pos*Math.PI)/4) + .75) + Math.random()/4; - return pos > 1 ? 1 : pos; - }, - wobble: function(pos) { - return (-Math.cos(pos*Math.PI*(9*pos))/2) + .5; - }, - pulse: function(pos, pulses) { - return (-Math.cos((pos*((pulses||5)-.5)*2)*Math.PI)/2) + .5; - }, - spring: function(pos) { - return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6)); - }, - none: function(pos) { - return 0; - }, - full: function(pos) { - return 1; - } - }, - DefaultOptions: { - duration: 1.0, // seconds - fps: 100, // 100= assume 66fps max. - sync: false, // true for combining - from: 0.0, - to: 1.0, - delay: 0.0, - queue: 'parallel' - }, - tagifyText: function(element) { - var tagifyStyle = 'position:relative'; - if (Prototype.Browser.IE) tagifyStyle += ';zoom:1'; - - element = $(element); - $A(element.childNodes).each( function(child) { - if (child.nodeType==3) { - child.nodeValue.toArray().each( function(character) { - element.insertBefore( - new Element('span', {style: tagifyStyle}).update( - character == ' ' ? String.fromCharCode(160) : character), - child); - }); - Element.remove(child); - } - }); - }, - multiple: function(element, effect) { - var elements; - if (((typeof element == 'object') || - Object.isFunction(element)) && - (element.length)) - elements = element; - else - elements = $(element).childNodes; - - var options = Object.extend({ - speed: 0.1, - delay: 0.0 - }, arguments[2] || { }); - var masterDelay = options.delay; - - $A(elements).each( function(element, index) { - new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); - }); - }, - PAIRS: { - 'slide': ['SlideDown','SlideUp'], - 'blind': ['BlindDown','BlindUp'], - 'appear': ['Appear','Fade'] - }, - toggle: function(element, effect) { - element = $(element); - effect = (effect || 'appear').toLowerCase(); - var options = Object.extend({ - queue: { position:'end', scope:(element.id || 'global'), limit: 1 } - }, arguments[2] || { }); - Effect[element.visible() ? - Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); - } -}; - -Effect.DefaultOptions.transition = Effect.Transitions.sinoidal; - -/* ------------- core effects ------------- */ - -Effect.ScopedQueue = Class.create(Enumerable, { - initialize: function() { - this.effects = []; - this.interval = null; - }, - _each: function(iterator) { - this.effects._each(iterator); - }, - add: function(effect) { - var timestamp = new Date().getTime(); - - var position = Object.isString(effect.options.queue) ? - effect.options.queue : effect.options.queue.position; - - switch(position) { - case 'front': - // move unstarted effects after this effect - this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { - e.startOn += effect.finishOn; - e.finishOn += effect.finishOn; - }); - break; - case 'with-last': - timestamp = this.effects.pluck('startOn').max() || timestamp; - break; - case 'end': - // start effect after last queued effect has finished - timestamp = this.effects.pluck('finishOn').max() || timestamp; - break; - } - - effect.startOn += timestamp; - effect.finishOn += timestamp; - - if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) - this.effects.push(effect); - - if (!this.interval) - this.interval = setInterval(this.loop.bind(this), 15); - }, - remove: function(effect) { - this.effects = this.effects.reject(function(e) { return e==effect }); - if (this.effects.length == 0) { - clearInterval(this.interval); - this.interval = null; - } - }, - loop: function() { - var timePos = new Date().getTime(); - for(var i=0, len=this.effects.length;i= this.startOn) { - if (timePos >= this.finishOn) { - this.render(1.0); - this.cancel(); - this.event('beforeFinish'); - if (this.finish) this.finish(); - this.event('afterFinish'); - return; - } - var pos = (timePos - this.startOn) / this.totalTime, - frame = (pos * this.totalFrames).round(); - if (frame > this.currentFrame) { - this.render(pos); - this.currentFrame = frame; - } - } - }, - cancel: function() { - if (!this.options.sync) - Effect.Queues.get(Object.isString(this.options.queue) ? - 'global' : this.options.queue.scope).remove(this); - this.state = 'finished'; - }, - event: function(eventName) { - if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); - if (this.options[eventName]) this.options[eventName](this); - }, - inspect: function() { - var data = $H(); - for(property in this) - if (!Object.isFunction(this[property])) data.set(property, this[property]); - return '#'; - } -}); - -Effect.Parallel = Class.create(Effect.Base, { - initialize: function(effects) { - this.effects = effects || []; - this.start(arguments[1]); - }, - update: function(position) { - this.effects.invoke('render', position); - }, - finish: function(position) { - this.effects.each( function(effect) { - effect.render(1.0); - effect.cancel(); - effect.event('beforeFinish'); - if (effect.finish) effect.finish(position); - effect.event('afterFinish'); - }); - } -}); - -Effect.Tween = Class.create(Effect.Base, { - initialize: function(object, from, to) { - object = Object.isString(object) ? $(object) : object; - var args = $A(arguments), method = args.last(), - options = args.length == 5 ? args[3] : null; - this.method = Object.isFunction(method) ? method.bind(object) : - Object.isFunction(object[method]) ? object[method].bind(object) : - function(value) { object[method] = value }; - this.start(Object.extend({ from: from, to: to }, options || { })); - }, - update: function(position) { - this.method(position); - } -}); - -Effect.Event = Class.create(Effect.Base, { - initialize: function() { - this.start(Object.extend({ duration: 0 }, arguments[0] || { })); - }, - update: Prototype.emptyFunction -}); - -Effect.Opacity = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - // make this work on IE on elements without 'layout' - if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) - this.element.setStyle({zoom: 1}); - var options = Object.extend({ - from: this.element.getOpacity() || 0.0, - to: 1.0 - }, arguments[1] || { }); - this.start(options); - }, - update: function(position) { - this.element.setOpacity(position); - } -}); - -Effect.Move = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ - x: 0, - y: 0, - mode: 'relative' - }, arguments[1] || { }); - this.start(options); - }, - setup: function() { - this.element.makePositioned(); - this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); - this.originalTop = parseFloat(this.element.getStyle('top') || '0'); - if (this.options.mode == 'absolute') { - this.options.x = this.options.x - this.originalLeft; - this.options.y = this.options.y - this.originalTop; - } - }, - update: function(position) { - this.element.setStyle({ - left: (this.options.x * position + this.originalLeft).round() + 'px', - top: (this.options.y * position + this.originalTop).round() + 'px' - }); - } -}); - -// for backwards compatibility -Effect.MoveBy = function(element, toTop, toLeft) { - return new Effect.Move(element, - Object.extend({ x: toLeft, y: toTop }, arguments[3] || { })); -}; - -Effect.Scale = Class.create(Effect.Base, { - initialize: function(element, percent) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ - scaleX: true, - scaleY: true, - scaleContent: true, - scaleFromCenter: false, - scaleMode: 'box', // 'box' or 'contents' or { } with provided values - scaleFrom: 100.0, - scaleTo: percent - }, arguments[2] || { }); - this.start(options); - }, - setup: function() { - this.restoreAfterFinish = this.options.restoreAfterFinish || false; - this.elementPositioning = this.element.getStyle('position'); - - this.originalStyle = { }; - ['top','left','width','height','fontSize'].each( function(k) { - this.originalStyle[k] = this.element.style[k]; - }.bind(this)); - - this.originalTop = this.element.offsetTop; - this.originalLeft = this.element.offsetLeft; - - var fontSize = this.element.getStyle('font-size') || '100%'; - ['em','px','%','pt'].each( function(fontSizeType) { - if (fontSize.indexOf(fontSizeType)>0) { - this.fontSize = parseFloat(fontSize); - this.fontSizeType = fontSizeType; - } - }.bind(this)); - - this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; - - this.dims = null; - if (this.options.scaleMode=='box') - this.dims = [this.element.offsetHeight, this.element.offsetWidth]; - if (/^content/.test(this.options.scaleMode)) - this.dims = [this.element.scrollHeight, this.element.scrollWidth]; - if (!this.dims) - this.dims = [this.options.scaleMode.originalHeight, - this.options.scaleMode.originalWidth]; - }, - update: function(position) { - var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); - if (this.options.scaleContent && this.fontSize) - this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); - this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); - }, - finish: function(position) { - if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); - }, - setDimensions: function(height, width) { - var d = { }; - if (this.options.scaleX) d.width = width.round() + 'px'; - if (this.options.scaleY) d.height = height.round() + 'px'; - if (this.options.scaleFromCenter) { - var topd = (height - this.dims[0])/2; - var leftd = (width - this.dims[1])/2; - if (this.elementPositioning == 'absolute') { - if (this.options.scaleY) d.top = this.originalTop-topd + 'px'; - if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; - } else { - if (this.options.scaleY) d.top = -topd + 'px'; - if (this.options.scaleX) d.left = -leftd + 'px'; - } - } - this.element.setStyle(d); - } -}); - -Effect.Highlight = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { }); - this.start(options); - }, - setup: function() { - // Prevent executing on elements not in the layout flow - if (this.element.getStyle('display')=='none') { this.cancel(); return; } - // Disable background image during the effect - this.oldStyle = { }; - if (!this.options.keepBackgroundImage) { - this.oldStyle.backgroundImage = this.element.getStyle('background-image'); - this.element.setStyle({backgroundImage: 'none'}); - } - if (!this.options.endcolor) - this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); - if (!this.options.restorecolor) - this.options.restorecolor = this.element.getStyle('background-color'); - // init color calculations - this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); - this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this)); - }, - update: function(position) { - this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ - return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) }); - }, - finish: function() { - this.element.setStyle(Object.extend(this.oldStyle, { - backgroundColor: this.options.restorecolor - })); - } -}); - -Effect.ScrollTo = function(element) { - var options = arguments[1] || { }, - scrollOffsets = document.viewport.getScrollOffsets(), - elementOffsets = $(element).cumulativeOffset(); - - if (options.offset) elementOffsets[1] += options.offset; - - return new Effect.Tween(null, - scrollOffsets.top, - elementOffsets[1], - options, - function(p){ scrollTo(scrollOffsets.left, p.round()); } - ); -}; - -/* ------------- combination effects ------------- */ - -Effect.Fade = function(element) { - element = $(element); - var oldOpacity = element.getInlineOpacity(); - var options = Object.extend({ - from: element.getOpacity() || 1.0, - to: 0.0, - afterFinishInternal: function(effect) { - if (effect.options.to!=0) return; - effect.element.hide().setStyle({opacity: oldOpacity}); - } - }, arguments[1] || { }); - return new Effect.Opacity(element,options); -}; - -Effect.Appear = function(element) { - element = $(element); - var options = Object.extend({ - from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), - to: 1.0, - // force Safari to render floated elements properly - afterFinishInternal: function(effect) { - effect.element.forceRerendering(); - }, - beforeSetup: function(effect) { - effect.element.setOpacity(effect.options.from).show(); - }}, arguments[1] || { }); - return new Effect.Opacity(element,options); -}; - -Effect.Puff = function(element) { - element = $(element); - var oldStyle = { - opacity: element.getInlineOpacity(), - position: element.getStyle('position'), - top: element.style.top, - left: element.style.left, - width: element.style.width, - height: element.style.height - }; - return new Effect.Parallel( - [ new Effect.Scale(element, 200, - { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), - new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], - Object.extend({ duration: 1.0, - beforeSetupInternal: function(effect) { - Position.absolutize(effect.effects[0].element); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.hide().setStyle(oldStyle); } - }, arguments[1] || { }) - ); -}; - -Effect.BlindUp = function(element) { - element = $(element); - element.makeClipping(); - return new Effect.Scale(element, 0, - Object.extend({ scaleContent: false, - scaleX: false, - restoreAfterFinish: true, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping(); - } - }, arguments[1] || { }) - ); -}; - -Effect.BlindDown = function(element) { - element = $(element); - var elementDimensions = element.getDimensions(); - return new Effect.Scale(element, 100, Object.extend({ - scaleContent: false, - scaleX: false, - scaleFrom: 0, - scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, - restoreAfterFinish: true, - afterSetup: function(effect) { - effect.element.makeClipping().setStyle({height: '0px'}).show(); - }, - afterFinishInternal: function(effect) { - effect.element.undoClipping(); - } - }, arguments[1] || { })); -}; - -Effect.SwitchOff = function(element) { - element = $(element); - var oldOpacity = element.getInlineOpacity(); - return new Effect.Appear(element, Object.extend({ - duration: 0.4, - from: 0, - transition: Effect.Transitions.flicker, - afterFinishInternal: function(effect) { - new Effect.Scale(effect.element, 1, { - duration: 0.3, scaleFromCenter: true, - scaleX: false, scaleContent: false, restoreAfterFinish: true, - beforeSetup: function(effect) { - effect.element.makePositioned().makeClipping(); - }, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity}); - } - }); - } - }, arguments[1] || { })); -}; - -Effect.DropOut = function(element) { - element = $(element); - var oldStyle = { - top: element.getStyle('top'), - left: element.getStyle('left'), - opacity: element.getInlineOpacity() }; - return new Effect.Parallel( - [ new Effect.Move(element, {x: 0, y: 100, sync: true }), - new Effect.Opacity(element, { sync: true, to: 0.0 }) ], - Object.extend( - { duration: 0.5, - beforeSetup: function(effect) { - effect.effects[0].element.makePositioned(); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle); - } - }, arguments[1] || { })); -}; - -Effect.Shake = function(element) { - element = $(element); - var options = Object.extend({ - distance: 20, - duration: 0.5 - }, arguments[1] || {}); - var distance = parseFloat(options.distance); - var split = parseFloat(options.duration) / 10.0; - var oldStyle = { - top: element.getStyle('top'), - left: element.getStyle('left') }; - return new Effect.Move(element, - { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) { - effect.element.undoPositioned().setStyle(oldStyle); - }}); }}); }}); }}); }}); }}); -}; - -Effect.SlideDown = function(element) { - element = $(element).cleanWhitespace(); - // SlideDown need to have the content of the element wrapped in a container element with fixed height! - var oldInnerBottom = element.down().getStyle('bottom'); - var elementDimensions = element.getDimensions(); - return new Effect.Scale(element, 100, Object.extend({ - scaleContent: false, - scaleX: false, - scaleFrom: window.opera ? 0 : 1, - scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, - restoreAfterFinish: true, - afterSetup: function(effect) { - effect.element.makePositioned(); - effect.element.down().makePositioned(); - if (window.opera) effect.element.setStyle({top: ''}); - effect.element.makeClipping().setStyle({height: '0px'}).show(); - }, - afterUpdateInternal: function(effect) { - effect.element.down().setStyle({bottom: - (effect.dims[0] - effect.element.clientHeight) + 'px' }); - }, - afterFinishInternal: function(effect) { - effect.element.undoClipping().undoPositioned(); - effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); } - }, arguments[1] || { }) - ); -}; - -Effect.SlideUp = function(element) { - element = $(element).cleanWhitespace(); - var oldInnerBottom = element.down().getStyle('bottom'); - var elementDimensions = element.getDimensions(); - return new Effect.Scale(element, window.opera ? 0 : 1, - Object.extend({ scaleContent: false, - scaleX: false, - scaleMode: 'box', - scaleFrom: 100, - scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, - restoreAfterFinish: true, - afterSetup: function(effect) { - effect.element.makePositioned(); - effect.element.down().makePositioned(); - if (window.opera) effect.element.setStyle({top: ''}); - effect.element.makeClipping().show(); - }, - afterUpdateInternal: function(effect) { - effect.element.down().setStyle({bottom: - (effect.dims[0] - effect.element.clientHeight) + 'px' }); - }, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping().undoPositioned(); - effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); - } - }, arguments[1] || { }) - ); -}; - -// Bug in opera makes the TD containing this element expand for a instance after finish -Effect.Squish = function(element) { - return new Effect.Scale(element, window.opera ? 1 : 0, { - restoreAfterFinish: true, - beforeSetup: function(effect) { - effect.element.makeClipping(); - }, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping(); - } - }); -}; - -Effect.Grow = function(element) { - element = $(element); - var options = Object.extend({ - direction: 'center', - moveTransition: Effect.Transitions.sinoidal, - scaleTransition: Effect.Transitions.sinoidal, - opacityTransition: Effect.Transitions.full - }, arguments[1] || { }); - var oldStyle = { - top: element.style.top, - left: element.style.left, - height: element.style.height, - width: element.style.width, - opacity: element.getInlineOpacity() }; - - var dims = element.getDimensions(); - var initialMoveX, initialMoveY; - var moveX, moveY; - - switch (options.direction) { - case 'top-left': - initialMoveX = initialMoveY = moveX = moveY = 0; - break; - case 'top-right': - initialMoveX = dims.width; - initialMoveY = moveY = 0; - moveX = -dims.width; - break; - case 'bottom-left': - initialMoveX = moveX = 0; - initialMoveY = dims.height; - moveY = -dims.height; - break; - case 'bottom-right': - initialMoveX = dims.width; - initialMoveY = dims.height; - moveX = -dims.width; - moveY = -dims.height; - break; - case 'center': - initialMoveX = dims.width / 2; - initialMoveY = dims.height / 2; - moveX = -dims.width / 2; - moveY = -dims.height / 2; - break; - } - - return new Effect.Move(element, { - x: initialMoveX, - y: initialMoveY, - duration: 0.01, - beforeSetup: function(effect) { - effect.element.hide().makeClipping().makePositioned(); - }, - afterFinishInternal: function(effect) { - new Effect.Parallel( - [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), - new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), - new Effect.Scale(effect.element, 100, { - scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, - sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) - ], Object.extend({ - beforeSetup: function(effect) { - effect.effects[0].element.setStyle({height: '0px'}).show(); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle); - } - }, options) - ); - } - }); -}; - -Effect.Shrink = function(element) { - element = $(element); - var options = Object.extend({ - direction: 'center', - moveTransition: Effect.Transitions.sinoidal, - scaleTransition: Effect.Transitions.sinoidal, - opacityTransition: Effect.Transitions.none - }, arguments[1] || { }); - var oldStyle = { - top: element.style.top, - left: element.style.left, - height: element.style.height, - width: element.style.width, - opacity: element.getInlineOpacity() }; - - var dims = element.getDimensions(); - var moveX, moveY; - - switch (options.direction) { - case 'top-left': - moveX = moveY = 0; - break; - case 'top-right': - moveX = dims.width; - moveY = 0; - break; - case 'bottom-left': - moveX = 0; - moveY = dims.height; - break; - case 'bottom-right': - moveX = dims.width; - moveY = dims.height; - break; - case 'center': - moveX = dims.width / 2; - moveY = dims.height / 2; - break; - } - - return new Effect.Parallel( - [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), - new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), - new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) - ], Object.extend({ - beforeStartInternal: function(effect) { - effect.effects[0].element.makePositioned().makeClipping(); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); } - }, options) - ); -}; - -Effect.Pulsate = function(element) { - element = $(element); - var options = arguments[1] || { }, - oldOpacity = element.getInlineOpacity(), - transition = options.transition || Effect.Transitions.linear, - reverser = function(pos){ - return 1 - transition((-Math.cos((pos*(options.pulses||5)*2)*Math.PI)/2) + .5); - }; - - return new Effect.Opacity(element, - Object.extend(Object.extend({ duration: 2.0, from: 0, - afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } - }, options), {transition: reverser})); -}; - -Effect.Fold = function(element) { - element = $(element); - var oldStyle = { - top: element.style.top, - left: element.style.left, - width: element.style.width, - height: element.style.height }; - element.makeClipping(); - return new Effect.Scale(element, 5, Object.extend({ - scaleContent: false, - scaleX: false, - afterFinishInternal: function(effect) { - new Effect.Scale(element, 1, { - scaleContent: false, - scaleY: false, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping().setStyle(oldStyle); - } }); - }}, arguments[1] || { })); -}; - -Effect.Morph = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ - style: { } - }, arguments[1] || { }); - - if (!Object.isString(options.style)) this.style = $H(options.style); - else { - if (options.style.include(':')) - this.style = options.style.parseStyle(); - else { - this.element.addClassName(options.style); - this.style = $H(this.element.getStyles()); - this.element.removeClassName(options.style); - var css = this.element.getStyles(); - this.style = this.style.reject(function(style) { - return style.value == css[style.key]; - }); - options.afterFinishInternal = function(effect) { - effect.element.addClassName(effect.options.style); - effect.transforms.each(function(transform) { - effect.element.style[transform.style] = ''; - }); - }; - } - } - this.start(options); - }, - - setup: function(){ - function parseColor(color){ - if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff'; - color = color.parseColor(); - return $R(0,2).map(function(i){ - return parseInt( color.slice(i*2+1,i*2+3), 16 ); - }); - } - this.transforms = this.style.map(function(pair){ - var property = pair[0], value = pair[1], unit = null; - - if (value.parseColor('#zzzzzz') != '#zzzzzz') { - value = value.parseColor(); - unit = 'color'; - } else if (property == 'opacity') { - value = parseFloat(value); - if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) - this.element.setStyle({zoom: 1}); - } else if (Element.CSS_LENGTH.test(value)) { - var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); - value = parseFloat(components[1]); - unit = (components.length == 3) ? components[2] : null; - } - - var originalValue = this.element.getStyle(property); - return { - style: property.camelize(), - originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), - targetValue: unit=='color' ? parseColor(value) : value, - unit: unit - }; - }.bind(this)).reject(function(transform){ - return ( - (transform.originalValue == transform.targetValue) || - ( - transform.unit != 'color' && - (isNaN(transform.originalValue) || isNaN(transform.targetValue)) - ) - ); - }); - }, - update: function(position) { - var style = { }, transform, i = this.transforms.length; - while(i--) - style[(transform = this.transforms[i]).style] = - transform.unit=='color' ? '#'+ - (Math.round(transform.originalValue[0]+ - (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() + - (Math.round(transform.originalValue[1]+ - (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() + - (Math.round(transform.originalValue[2]+ - (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() : - (transform.originalValue + - (transform.targetValue - transform.originalValue) * position).toFixed(3) + - (transform.unit === null ? '' : transform.unit); - this.element.setStyle(style, true); - } -}); - -Effect.Transform = Class.create({ - initialize: function(tracks){ - this.tracks = []; - this.options = arguments[1] || { }; - this.addTracks(tracks); - }, - addTracks: function(tracks){ - tracks.each(function(track){ - track = $H(track); - var data = track.values().first(); - this.tracks.push($H({ - ids: track.keys().first(), - effect: Effect.Morph, - options: { style: data } - })); - }.bind(this)); - return this; - }, - play: function(){ - return new Effect.Parallel( - this.tracks.map(function(track){ - var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options'); - var elements = [$(ids) || $$(ids)].flatten(); - return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) }); - }).flatten(), - this.options - ); - } -}); - -Element.CSS_PROPERTIES = $w( - 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + - 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' + - 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' + - 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' + - 'fontSize fontWeight height left letterSpacing lineHeight ' + - 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+ - 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' + - 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' + - 'right textIndent top width wordSpacing zIndex'); - -Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; - -String.__parseStyleElement = document.createElement('div'); -String.prototype.parseStyle = function(){ - var style, styleRules = $H(); - if (Prototype.Browser.WebKit) - style = new Element('div',{style:this}).style; - else { - String.__parseStyleElement.innerHTML = '
            '; - style = String.__parseStyleElement.childNodes[0].style; - } - - Element.CSS_PROPERTIES.each(function(property){ - if (style[property]) styleRules.set(property, style[property]); - }); - - if (Prototype.Browser.IE && this.include('opacity')) - styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]); - - return styleRules; -}; - -if (document.defaultView && document.defaultView.getComputedStyle) { - Element.getStyles = function(element) { - var css = document.defaultView.getComputedStyle($(element), null); - return Element.CSS_PROPERTIES.inject({ }, function(styles, property) { - styles[property] = css[property]; - return styles; - }); - }; -} else { - Element.getStyles = function(element) { - element = $(element); - var css = element.currentStyle, styles; - styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) { - results[property] = css[property]; - return results; - }); - if (!styles.opacity) styles.opacity = element.getOpacity(); - return styles; - }; -} - -Effect.Methods = { - morph: function(element, style) { - element = $(element); - new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { })); - return element; - }, - visualEffect: function(element, effect, options) { - element = $(element); - var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1); - new Effect[klass](element, options); - return element; - }, - highlight: function(element, options) { - element = $(element); - new Effect.Highlight(element, options); - return element; - } -}; - -$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+ - 'pulsate shake puff squish switchOff dropOut').each( - function(effect) { - Effect.Methods[effect] = function(element, options){ - element = $(element); - Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options); - return element; - }; - } -); - -$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each( - function(f) { Effect.Methods[f] = Element[f]; } -); - -Element.addMethods(Effect.Methods); \ No newline at end of file diff --git a/tryruby/public/javascripts/irb.js b/tryruby/public/javascripts/irb.js deleted file mode 100755 index b4cb354..0000000 --- a/tryruby/public/javascripts/irb.js +++ /dev/null @@ -1,110 +0,0 @@ -// -// Copyright (c) 2008 why the lucky stiff -// Copyright (c) 2010 Andrew McElroy -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, -// and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT -// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -var allStretch; -var helpPages; -var chapPages; -var defaultPage; -var toot = window.location.search.substr(1) - -//the main function, call to the effect object -function dumpAlert(obj) { - props = []; - for ( var i in obj ) { - props.push( "" + i + ": " + obj[i] ); - } - alert( props ); -} -window.onload = function() { - defaultPage = $('#helpstone .stretcher').html(); - - window.irb = new MouseApp.Irb('#irb', { - rows: 13, - name: 'IRB', - greeting: "%+r Interactive ruby ready. %-r", - ps: '\033[1;31m>>\033[m', - user: 'guest', - host: 'tryruby', - // original: irbUrl: '/irb', - irbUrl: '/tryruby/run', - init: function () { - helpPages = $(".stretcher"); - chapPages = new Array(); - for (var i = 0; i < helpPages.length; i++ ) { - var cls = helpPages[i].className.split(' '); - for (var j = 0; j < cls.length; j++) { - if (cls[j] == 'chapmark') { - chapPages.push([i, helpPages[i]]); - break; - } - } - } - }, - loadTutorial: function (id, instruct) { - $.ajax({ - url: '/tutorials/' + id , - type: 'GET', - complete: function (r) { - $('#helpstone').html("
            " + defaultPage + "
            " + r.responseText); - window.irb.init(); - window.irb.showHelp(0); - } - }); - }, - showChapter: function (n) { - if (n >= chapPages.length) return; - this.setHelpPage(chapPages[n][0], chapPages[n][1]); - }, - showHelp: function (n) { - if (n >= helpPages.length) return; - this.setHelpPage(n, helpPages[n]); - }, - popup_goto: function (u) { - $('#lilBrowser').show().css({left: '40px', top: '40px'}); - $('#lbIframe').attr('src', u); - }, - popup_make: function (s) { - $('#lilBrowser').show().css({left: '40px', top: '40px'}); - $('#lbIframe').get(0).onIframeLoad = function () { - alert($(this).html()); - alert("$(this).html()"); - return s; - }; - //$('#lbIframe').attr({src: '/blank.html'}); - src = s.replace(/\\/g, "\\\\").replace(/\"/g, "\\\""); - $('#lbIframe').attr({src: "javascript:\"" + src + "\""}); - // $('# - }, - popup_close: function () { - $('#lilBrowser').hide(); - } - }); - - if ( !toot ) { - toot = 'intro'; - } - try { - window.irb.options.loadTutorial( toot, true ); - } catch (e) {} -} diff --git a/tryruby/public/javascripts/jquery-1.3.2.min.js b/tryruby/public/javascripts/jquery-1.3.2.min.js deleted file mode 100644 index b1ae21d..0000000 --- a/tryruby/public/javascripts/jquery-1.3.2.min.js +++ /dev/null @@ -1,19 +0,0 @@ -/* - * jQuery JavaScript Library v1.3.2 - * http://jquery.com/ - * - * Copyright (c) 2009 John Resig - * Dual licensed under the MIT and GPL licenses. - * http://docs.jquery.com/License - * - * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) - * Revision: 6246 - */ -(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("",""]||!O.indexOf("",""]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
            "]||!O.indexOf("",""]||(!O.indexOf("",""]||!O.indexOf("",""]||!o.support.htmlSerialize&&[1,"div
            ","
            "]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}}); -/* - * Sizzle CSS Selector Engine - v0.9.3 - * Copyright 2009, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * More information: http://sizzlejs.com/ - */ -(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return UT[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="

            ";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="
            ";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("
            ").append(M.responseText.replace(//g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='
            ';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})(); \ No newline at end of file diff --git a/tryruby/public/javascripts/jquery-1.4.2.min.js b/tryruby/public/javascripts/jquery-1.4.2.min.js deleted file mode 100644 index 7c24308..0000000 --- a/tryruby/public/javascripts/jquery-1.4.2.min.js +++ /dev/null @@ -1,154 +0,0 @@ -/*! - * jQuery JavaScript Library v1.4.2 - * http://jquery.com/ - * - * Copyright 2010, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2010, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Sat Feb 13 22:33:48 2010 -0500 - */ -(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, -Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& -(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, -a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== -"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, -function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
            a"; -var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, -parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= -false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= -s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, -applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; -else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, -a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== -w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, -cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= -c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); -a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, -function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); -k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), -C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B=0){a.type= -e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& -f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; -if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", -e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, -"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, -d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, -e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); -t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| -g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, -CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, -g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, -text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, -setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= -h[3];l=0;for(m=h.length;l=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== -"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, -h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& -q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; -if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="

            ";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); -(function(){var g=s.createElement("div");g.innerHTML="
            ";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: -function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var j=d;j0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= -{},i;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== -"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", -d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? -a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== -1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"},F={option:[1,""],legend:[1,"
            ","
            "],thead:[1,"","
            "],tr:[2,"","
            "],td:[3,"","
            "],col:[2,"","
            "],area:[1,"",""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
            ","
            "];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= -c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, -wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, -prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, -this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); -return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, -""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); -return this}else{e=0;for(var j=d.length;e0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", -""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===""&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= -c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? -c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= -function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= -Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, -"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= -a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= -a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=//gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!== -"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("
            ").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this}, -serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), -function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href, -global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&& -e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)? -"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache=== -false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B= -false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since", -c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E|| -d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x); -g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status=== -1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b=== -"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional; -if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration=== -"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]|| -c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start; -this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now= -this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem, -e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b
            "; -a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b); -c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a, -d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top- -f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset": -"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in -e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window); diff --git a/tryruby/public/javascripts/jquery.console.js b/tryruby/public/javascripts/jquery.console.js deleted file mode 100644 index d45390d..0000000 --- a/tryruby/public/javascripts/jquery.console.js +++ /dev/null @@ -1,609 +0,0 @@ -// JQuery Console 1.0 -// Sun Feb 21 20:28:47 GMT 2010 -// -// Copyright 2010 Chris Done, Simon David Pratt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// 1. Redistributions of source code must retain the above -// copyright notice, this list of conditions and the following -// disclaimer. -// -// 2. Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// TESTED ON -// Internet Explorer 6 -// Opera 10.01 -// Chromium 4.0.237.0 (Ubuntu build 31094) -// Firefox 3.5.8, 3.6.2 (Mac) -// Safari 4.0.5 (6531.22.7) (Mac) -// Google Chrome 5.0.375.55 (Mac) - -(function($){ - $.fn.console = function(config){ - //////////////////////////////////////////////////////////////////////// - // Constants - // Some are enums, data types, others just for optimisation - var keyCodes = { - // left - 37: moveBackward, - // right - 39: moveForward, - // up - 38: previousHistory, - // down - 40: nextHistory, - // backspace - 8: backDelete, - // delete - 46: forwardDelete, - // end - 35: moveToEnd, - // start - 36: moveToStart, - // return - 13: commandTrigger, - // tab - 18: doNothing - }; - var ctrlCodes = { - // C-a - 65: moveToStart, - // C-e - 69: moveToEnd, - // C-d - 68: forwardDelete, - // C-n - 78: nextHistory, - // C-p - 80: previousHistory, - // C-b - 66: moveBackward, - // C-f - 70: moveForward, - // C-k - 75: deleteUntilEnd - }; - var altCodes = { - // M-f - 70: moveToNextWord, - // M-b - 66: moveToPreviousWord, - // M-d - 68: deleteNextWord - }; - var cursor = ' '; - // Opera only works with this character, not or ­, - // but IE6 displays this character, which is bad, so just use - // it on Opera. - var wbr = $.browser.opera? '​' : ''; - - //////////////////////////////////////////////////////////////////////// - // Globals - var container = $(this); - var inner = $('
            '); - var typer = $(''); - // Prompt - var promptBox; - var prompt; - var promptLabel = config && config.promptLabel? config.promptLabel : "> "; - var column = 0; - var promptText = ''; - var restoreText = ''; - // Prompt history stack - var history = []; - var ringn = 0; - // For reasons unknown to The Sword of Michael himself, Opera - // triggers and sends a key character when you hit various - // keys like PgUp, End, etc. So there is no way of knowing - // when a user has typed '#' or End. My solution is in the - // typer.keydown and typer.keypress functions; I use the - // variable below to ignore the keypress event if the keydown - // event succeeds. - var cancelKeyPress = 0; - // When this value is false, the prompt will not respond to input - var acceptInput = true; - // When this value is true, the command has been canceled - var cancelCommand = false; - - // External exports object - var extern = {}; - - //////////////////////////////////////////////////////////////////////// - // Main entry point - (function(){ - container.append(inner); - inner.append(typer); - typer.css({position:'absolute',top:0,left:'-9999px'}); - if (config.welcomeMessage) - message(config.welcomeMessage,'jquery-console-welcome'); - newPromptBox(); - if (config.autofocus) { - inner.addClass('jquery-console-focus'); - typer.focus(); - setTimeout(function(){ - inner.addClass('jquery-console-focus'); - typer.focus(); - },100); - } - extern.inner = inner; - extern.typer = typer; - extern.scrollToBottom = scrollToBottom; - })(); - - //////////////////////////////////////////////////////////////////////// - // Reset terminal - extern.reset = function(){ - var welcome = true; - inner.parent().fadeOut(function(){ - inner.find('div').each(function(){ - if (!welcome) - $(this).remove(); - welcome = false; - }); - newPromptBox(); - inner.parent().fadeIn(function(){ - inner.addClass('jquery-console-focus'); - typer.focus(); - }); - }); - }; - - //////////////////////////////////////////////////////////////////////// - // Reset terminal - extern.notice = function(msg,style){ - var n = $('
            ').append($('
            ').text(msg)) - .css({visibility:'hidden'}); - container.append(n); - var focused = true; - if (style=='fadeout') - setTimeout(function(){ - n.fadeOut(function(){ - n.remove(); - }); - },4000); - else if (style=='prompt') { - var a = $('
            '); - n.append(a); - focused = false; - a.click(function(){ n.fadeOut(function(){ n.remove();inner.css({opacity:1}) }); }); - } - var h = n.height(); - n.css({height:'0px',visibility:'visible'}) - .animate({height:h+'px'},function(){ - if (!focused) inner.css({opacity:0.5}); - }); - n.css('cursor','default'); - return n; - }; - - //////////////////////////////////////////////////////////////////////// - // Make a new prompt box - function newPromptBox() { - column = 0; - promptText = ''; - ringn = 0; // Reset the position of the history ring - enableInput(); - promptBox = $('
            '); - var label = $(''); - promptBox.append(label.text(promptLabel).show()); - prompt = $(''); - promptBox.append(prompt); - inner.append(promptBox); - updatePromptDisplay(); - }; - - //////////////////////////////////////////////////////////////////////// - // Handle setting focus - container.click(function(){ - inner.addClass('jquery-console-focus'); - inner.removeClass('jquery-console-nofocus'); - typer.focus(); - scrollToBottom(); - return false; - }); - - //////////////////////////////////////////////////////////////////////// - // Handle losing focus - typer.blur(function(){ - inner.removeClass('jquery-console-focus'); - inner.addClass('jquery-console-nofocus'); - }); - - //////////////////////////////////////////////////////////////////////// - // Handle key hit before translation - // For picking up control characters like up/left/down/right - - typer.keydown(function(e){ - cancelKeyPress = 0; - var keyCode = e.keyCode; - // C-c: cancel the execution - if(e.ctrlKey && keyCode == 67) { - cancelKeyPress = keyCode; - cancelExecution(); - return false; - } - if (acceptInput) { - if (keyCode in keyCodes) { - cancelKeyPress = keyCode; - (keyCodes[keyCode])(); - return false; - } else if (e.ctrlKey && keyCode in ctrlCodes) { - cancelKeyPress = keyCode; - (ctrlCodes[keyCode])(); - return false; - } else if (e.altKey && keyCode in altCodes) { - cancelKeyPress = keyCode; - (altCodes[keyCode])(); - return false; - } - } - }); - - //////////////////////////////////////////////////////////////////////// - // Handle key press - typer.keypress(function(e){ - var keyCode = e.keyCode || e.which; - if (isIgnorableKey(e)) { - return false; - } - if (acceptInput && cancelKeyPress != keyCode && keyCode >= 32){ - if (cancelKeyPress) return false; - if (typeof config.charInsertTrigger == 'undefined' || - (typeof config.charInsertTrigger == 'function' && - config.charInsertTrigger(keyCode,promptText))) - typer.consoleInsert(keyCode); - } - if ($.browser.webkit) return false; - }); - - function isIgnorableKey(e) { - // for now just filter alt+tab that we receive on some platforms when - // user switches windows (goes away from the browser) - return ((e.keyCode == keyCodes.tab || e.keyCode == 192) && e.altKey); - }; - - //////////////////////////////////////////////////////////////////////// - // Rotate through the command history - function rotateHistory(n){ - if (history.length == 0) return; - ringn += n; - if (ringn < 0) ringn = history.length; - else if (ringn > history.length) ringn = 0; - var prevText = promptText; - if (ringn == 0) { - promptText = restoreText; - } else { - promptText = history[ringn - 1]; - } - if (config.historyPreserveColumn) { - if (promptText.length < column + 1) { - column = promptText.length; - } else if (column == 0) { - column = promptText.length; - } - } else if (config.historyColumnAtEnd) { - column = promptText.length; - } else { - column = 0; - } - updatePromptDisplay(); - }; - - function previousHistory() { - rotateHistory(-1); - }; - - function nextHistory() { - rotateHistory(1); - }; - - // Add something to the history ring - function addToHistory(line){ - history.push(line); - restoreText = ''; - }; - - // Delete the character at the current position - function deleteCharAtPos(){ - if (column < promptText.length){ - promptText = - promptText.substring(0,column) + - promptText.substring(column+1); - restoreText = promptText; - return true; - } else return false; - }; - - function backDelete() { - if (moveColumn(-1)){ - deleteCharAtPos(); - updatePromptDisplay(); - } - }; - - function forwardDelete() { - if (deleteCharAtPos()) - updatePromptDisplay(); - }; - - function deleteUntilEnd() { - while(deleteCharAtPos()) { - updatePromptDisplay(); - } - }; - - function deleteNextWord() { - // A word is defined within this context as a series of alphanumeric - // characters. - // Delete up to the next alphanumeric character - while(column < promptText.length && - !isCharAlphanumeric(promptText[column])) { - deleteCharAtPos(); - updatePromptDisplay(); - } - // Then, delete until the next non-alphanumeric character - while(column < promptText.length && - isCharAlphanumeric(promptText[column])) { - deleteCharAtPos(); - updatePromptDisplay(); - } - }; - - //////////////////////////////////////////////////////////////////////// - // Validate command and trigger it if valid, or show a validation error - function commandTrigger() { - var line = promptText; - if (typeof config.commandValidate == 'function') { - var ret = config.commandValidate(line); - if (ret == true || ret == false) { - if (ret) { - handleCommand(); - } - } else { - commandResult(ret,"jquery-console-message-error"); - } - } else { - handleCommand(); - } - }; - - // Scroll to the bottom of the view - function scrollToBottom() { - inner.attr({ scrollTop: inner.attr("scrollHeight") });; - }; - - function cancelExecution() { - if(typeof config.cancelHandle == 'function') { - config.cancelHandle(); - } - } - - //////////////////////////////////////////////////////////////////////// - // Handle a command - function handleCommand() { - if (typeof config.commandHandle == 'function') { - disableInput(); - addToHistory(promptText); - var ret = config.commandHandle(promptText,function(msgs){ - commandResult(msgs); - }); - if (typeof ret == 'boolean') { - if (ret) { - // Command succeeded without a result. - commandResult(); - } else { - commandResult('Command failed.', - "jquery-console-message-error"); - } - } else if (typeof ret == "string") { - commandResult(ret,"jquery-console-message-success"); - } else if (typeof ret == 'object' && ret.length) { - commandResult(ret); - } - } - }; - - //////////////////////////////////////////////////////////////////////// - // Disable input - function disableInput() { - acceptInput = false; - }; - - // Enable input - function enableInput() { - acceptInput = true; - } - - //////////////////////////////////////////////////////////////////////// - // Reset the prompt in invalid command - function commandResult(msg,className) { - column = -1; - updatePromptDisplay(); - if (typeof msg == 'string') { - message(msg,className); - } else { - for (var x in msg) { - var ret = msg[x]; - message(ret.msg,ret.className); - } - } - newPromptBox(); - }; - - //////////////////////////////////////////////////////////////////////// - // Display a message - function message(msg,className) { - var mesg = $('
            '); - if (className) mesg.addClass(className); - mesg.filledText(msg).hide(); - inner.append(mesg); - mesg.show(); - }; - - //////////////////////////////////////////////////////////////////////// - // Handle normal character insertion - typer.consoleInsert = function(keyCode){ - // TODO: remove redundant indirection - var char = String.fromCharCode(keyCode); - var before = promptText.substring(0,column); - var after = promptText.substring(column); - promptText = before + char + after; - moveColumn(1); - restoreText = promptText; - updatePromptDisplay(); - }; - - //////////////////////////////////////////////////////////////////////// - // Move to another column relative to this one - // Negative means go back, positive means go forward. - function moveColumn(n){ - if (column + n >= 0 && column + n <= promptText.length){ - column += n; - return true; - } else return false; - }; - - function moveForward() { - if(moveColumn(1)) { - updatePromptDisplay(); - return true; - } - return false; - }; - - function moveBackward() { - if(moveColumn(-1)) { - updatePromptDisplay(); - return true; - } - return false; - }; - - function moveToStart() { - if (moveColumn(-column)) - updatePromptDisplay(); - }; - - function moveToEnd() { - if (moveColumn(promptText.length-column)) - updatePromptDisplay(); - }; - - function moveToNextWord() { - while(column < promptText.length && - !isCharAlphanumeric(promptText[column]) && - moveForward()) { - } - while(column < promptText.length && - isCharAlphanumeric(promptText[column]) && - moveForward()) { - } - }; - - function moveToPreviousWord() { - // Move backward until we find the first alphanumeric - while(column -1 >= 0 && - !isCharAlphanumeric(promptText[column-1]) && - moveBackward()) { - } - // Move until we find the first non-alphanumeric - while(column -1 >= 0 && - isCharAlphanumeric(promptText[column-1]) && - moveBackward()) { - } - }; - - function isCharAlphanumeric(charToTest) { - if(typeof charToTest == 'string') { - var code = charToTest.charCodeAt(); - return (code >= 'A'.charCodeAt() && code <= 'Z'.charCodeAt()) || - (code >= 'a'.charCodeAt() && code <= 'z'.charCodeAt()) || - (code >= '0'.charCodeAt() && code <= '9'.charCodeAt()); - } - return false; - }; - - function doNothing() {}; - - extern.promptText = function(text){ - if (text) { - promptText = text; - if (column > promptText.length) - column = promptText.length; - updatePromptDisplay(); - } - return promptText; - }; - - //////////////////////////////////////////////////////////////////////// - // Update the prompt display - function updatePromptDisplay(){ - var line = promptText; - var html = ''; - if (column > 0 && line == ''){ - // When we have an empty line just display a cursor. - html = cursor; - } else if (column == promptText.length){ - // We're at the end of the line, so we need to display - // the text *and* cursor. - html = htmlEncode(line) + cursor; - } else { - // Grab the current character, if there is one, and - // make it the current cursor. - var before = line.substring(0, column); - var current = line.substring(column,column+1); - if (current){ - current = - '' + - htmlEncode(current) + - ''; - } - var after = line.substring(column+1); - html = htmlEncode(before) + current + htmlEncode(after); - } - prompt.html(html); - scrollToBottom(); - }; - - // Simple HTML encoding - // Simply replace '<', '>' and '&' - // TODO: Use jQuery's .html() trick, or grab a proper, fast - // HTML encoder. - function htmlEncode(text){ - return ( - text.replace(/&/g,'&') - .replace(/&]{10})/g,'$1­' + wbr) - ); - }; - - return extern; - }; - // Simple utility for printing messages - $.fn.filledText = function(txt){ - $(this).text(txt); - $(this).html($(this).html().replace(/\n/g,'
            ')); - return this; - }; -})(jQuery); diff --git a/tryruby/public/javascripts/jquery.console.min.js b/tryruby/public/javascripts/jquery.console.min.js deleted file mode 100644 index 7ae1e6b..0000000 --- a/tryruby/public/javascripts/jquery.console.min.js +++ /dev/null @@ -1 +0,0 @@ -(function($){$.fn.console=function(config){var keyCodes={left:37,right:39,up:38,down:40,back:8,del:46,end:35,start:36,ret:13};var cursor=' ';var wbr=$.browser.opera?'​':'';var container=$(this);var inner=$('
            ');var typer=$('');var promptBox;var prompt;var promptLabel=config&&config.promptLabel?config.promptLabel:"> ";var column=0;var promptText='';var restoreText='';var history=[];var ringn=0;var cancelKeyPress=0;var extern={};(function(){container.append(inner);inner.append(typer);typer.css({position:'absolute',top:0,left:'-999px'});if(config.welcomeMessage)message(config.welcomeMessage,'jquery-console-welcome');newPromptBox();if(config.autofocus){inner.addClass('jquery-console-focus');typer.focus();setTimeout(function(){inner.addClass('jquery-console-focus');typer.focus()},100)}})();extern.reset=function(){var welcome=true;inner.parent().fadeOut(function(){inner.find('div').each(function(){if(!welcome)$(this).remove();welcome=false});newPromptBox();inner.parent().fadeIn(function(){inner.addClass('jquery-console-focus');typer.focus()})})};function newPromptBox(){column=0;promptText='';promptBox=$('
            ');var label=$('');promptBox.append(label.text(promptLabel).show());prompt=$('');promptBox.append(prompt);inner.append(promptBox);updatePromptDisplay()};container.click(function(){inner.addClass('jquery-console-focus');inner.removeClass('jquery-console-nofocus');typer.focus();scrollToBottom();return false});typer.blur(function(){inner.removeClass('jquery-console-focus');inner.addClass('jquery-console-nofocus')});typer.keydown(function(e){cancelKeyPress=0;var keyCode=e.keyCode;if(isControlCharacter(keyCode)){cancelKeyPress=keyCode;if(!typer.consoleControl(keyCode)){return false}}});typer.keypress(function(e){var keyCode=e.keyCode||e.which;if(cancelKeyPress!=keyCode&&keyCode>=32){if(cancelKeyPress)return false;typer.consoleInsert(keyCode)}if($.browser.webkit)return false});function isControlCharacter(keyCode){return((keyCode>=keyCodes.left&&keyCode<=keyCodes.down)||keyCode==keyCodes.back||keyCode==keyCodes.del||keyCode==keyCodes.end||keyCode==keyCodes.start||keyCode==keyCodes.ret)};typer.consoleControl=function(keyCode){switch(keyCode){case keyCodes.left:{moveColumn(-1);updatePromptDisplay();return false;break}case keyCodes.right:{moveColumn(1);updatePromptDisplay();return false;break}case keyCodes.back:{if(moveColumn(-1)){deleteCharAtPos();updatePromptDisplay()}return false;break}case keyCodes.del:{if(deleteCharAtPos())updatePromptDisplay();return false;break}case keyCodes.end:{if(moveColumn(promptText.length-column))updatePromptDisplay();return false;break}case keyCodes.start:{if(moveColumn(-column))updatePromptDisplay();return false;break}case keyCodes.ret:{commandTrigger();return false}case keyCodes.up:{rotateHistory(-1);return false}case keyCodes.down:{rotateHistory(1);return false}default:}};function rotateHistory(n){if(history.length==0)return;ringn+=n;if(ringn<0)ringn=history.length;else if(ringn>history.length)ringn=0;var prevText=promptText;if(ringn==0){promptText=restoreText}else{promptText=history[ringn-1]}if(config.historyPreserveColumn){if(promptText.length
            ');if(className)mesg.addClass(className);mesg.filledText(msg).hide();inner.append(mesg);mesg.show()};typer.consoleInsert=function(keyCode){var char=String.fromCharCode(keyCode);var before=promptText.substring(0,column);var after=promptText.substring(column);promptText=before+char+after;moveColumn(1);restoreText=promptText;updatePromptDisplay()};function moveColumn(n){if(column+n>=0&&column+n<=promptText.length){column+=n;return true}else return false};function updatePromptDisplay(){var line=promptText;var html='';if(column>0&&line==''){html=cursor}else if(column==promptText.length){html=htmlEncode(line)+cursor}else{var before=line.substring(0,column);var current=line.substring(column,column+1);if(current){current=''+htmlEncode(current)+''}var after=line.substring(column+1);html=htmlEncode(before)+current+htmlEncode(after)}prompt.html(html);scrollToBottom()};function htmlEncode(text){return(text.replace(/&/g,'&').replace(/&]{10})/g,'$1­'+wbr))};return extern};$.fn.filledText=function(txt){$(this).text(txt);$(this).html($(this).html().replace(/\n/g,'
            '));return this}})(jQuery); \ No newline at end of file diff --git a/tryruby/public/javascripts/jquery.js b/tryruby/public/javascripts/jquery.js deleted file mode 100755 index 3747929..0000000 --- a/tryruby/public/javascripts/jquery.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * jQuery 1.2.3 - New Wave Javascript - * - * Copyright (c) 2008 John Resig (jquery.com) - * Dual licensed under the MIT (MIT-LICENSE.txt) - * and GPL (GPL-LICENSE.txt) licenses. - * - * $Date: 2008-02-06 00:21:25 -0500 (Wed, 06 Feb 2008) $ - * $Rev: 4663 $ - */ -(function(){if(window.jQuery)var _jQuery=window.jQuery;var jQuery=window.jQuery=function(selector,context){return new jQuery.prototype.init(selector,context);};if(window.$)var _$=window.$;window.$=jQuery;var quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;var isSimple=/^.[^:#\[\.]*$/;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;return this;}else if(typeof selector=="string"){var match=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1])selector=jQuery.clean([match[1]],context);else{var elem=document.getElementById(match[3]);if(elem)if(elem.id!=match[3])return jQuery().find(selector);else{this[0]=elem;this.length=1;return this;}else -selector=[];}}else -return new jQuery(context).find(selector);}else if(jQuery.isFunction(selector))return new jQuery(document)[jQuery.fn.ready?"ready":"load"](selector);return this.setArray(selector.constructor==Array&&selector||(selector.jquery||selector.length&&selector!=window&&!selector.nodeType&&selector[0]!=undefined&&selector[0].nodeType)&&jQuery.makeArray(selector)||[selector]);},jquery:"1.2.3",size:function(){return this.length;},length:0,get:function(num){return num==undefined?jQuery.makeArray(this):this[num];},pushStack:function(elems){var ret=jQuery(elems);ret.prevObject=this;return ret;},setArray:function(elems){this.length=0;Array.prototype.push.apply(this,elems);return this;},each:function(callback,args){return jQuery.each(this,callback,args);},index:function(elem){var ret=-1;this.each(function(i){if(this==elem)ret=i;});return ret;},attr:function(name,value,type){var options=name;if(name.constructor==String)if(value==undefined)return this.length&&jQuery[type||"attr"](this[0],name)||undefined;else{options={};options[name]=value;}return this.each(function(i){for(name in options)jQuery.attr(type?this.style:this,name,jQuery.prop(this,options[name],type,i,name));});},css:function(key,value){if((key=='width'||key=='height')&&parseFloat(value)<0)value=undefined;return this.attr(key,value,"curCSS");},text:function(text){if(typeof text!="object"&&text!=null)return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(text));var ret="";jQuery.each(text||this,function(){jQuery.each(this.childNodes,function(){if(this.nodeType!=8)ret+=this.nodeType!=1?this.nodeValue:jQuery.fn.text([this]);});});return ret;},wrapAll:function(html){if(this[0])jQuery(html,this[0].ownerDocument).clone().insertBefore(this[0]).map(function(){var elem=this;while(elem.firstChild)elem=elem.firstChild;return elem;}).append(this);return this;},wrapInner:function(html){return this.each(function(){jQuery(this).contents().wrapAll(html);});},wrap:function(html){return this.each(function(){jQuery(this).wrapAll(html);});},append:function(){return this.domManip(arguments,true,false,function(elem){if(this.nodeType==1)this.appendChild(elem);});},prepend:function(){return this.domManip(arguments,true,true,function(elem){if(this.nodeType==1)this.insertBefore(elem,this.firstChild);});},before:function(){return this.domManip(arguments,false,false,function(elem){this.parentNode.insertBefore(elem,this);});},after:function(){return this.domManip(arguments,false,true,function(elem){this.parentNode.insertBefore(elem,this.nextSibling);});},end:function(){return this.prevObject||jQuery([]);},find:function(selector){var elems=jQuery.map(this,function(elem){return jQuery.find(selector,elem);});return this.pushStack(/[^+>] [^+>]/.test(selector)||selector.indexOf("..")>-1?jQuery.unique(elems):elems);},clone:function(events){var ret=this.map(function(){if(jQuery.browser.msie&&!jQuery.isXMLDoc(this)){var clone=this.cloneNode(true),container=document.createElement("div");container.appendChild(clone);return jQuery.clean([container.innerHTML])[0];}else -return this.cloneNode(true);});var clone=ret.find("*").andSelf().each(function(){if(this[expando]!=undefined)this[expando]=null;});if(events===true)this.find("*").andSelf().each(function(i){if(this.nodeType==3)return;var events=jQuery.data(this,"events");for(var type in events)for(var handler in events[type])jQuery.event.add(clone[i],type,events[type][handler],events[type][handler].data);});return ret;},filter:function(selector){return this.pushStack(jQuery.isFunction(selector)&&jQuery.grep(this,function(elem,i){return selector.call(elem,i);})||jQuery.multiFilter(selector,this));},not:function(selector){if(selector.constructor==String)if(isSimple.test(selector))return this.pushStack(jQuery.multiFilter(selector,this,true));else -selector=jQuery.multiFilter(selector,this);var isArrayLike=selector.length&&selector[selector.length-1]!==undefined&&!selector.nodeType;return this.filter(function(){return isArrayLike?jQuery.inArray(this,selector)<0:this!=selector;});},add:function(selector){return!selector?this:this.pushStack(jQuery.merge(this.get(),selector.constructor==String?jQuery(selector).get():selector.length!=undefined&&(!selector.nodeName||jQuery.nodeName(selector,"form"))?selector:[selector]));},is:function(selector){return selector?jQuery.multiFilter(selector,this).length>0:false;},hasClass:function(selector){return this.is("."+selector);},val:function(value){if(value==undefined){if(this.length){var elem=this[0];if(jQuery.nodeName(elem,"select")){var index=elem.selectedIndex,values=[],options=elem.options,one=elem.type=="select-one";if(index<0)return null;for(var i=one?index:0,max=one?index+1:options.length;i=0||jQuery.inArray(this.name,value)>=0);else if(jQuery.nodeName(this,"select")){var values=value.constructor==Array?value:[value];jQuery("option",this).each(function(){this.selected=(jQuery.inArray(this.value,values)>=0||jQuery.inArray(this.text,values)>=0);});if(!values.length)this.selectedIndex=-1;}else -this.value=value;});},html:function(value){return value==undefined?(this.length?this[0].innerHTML:null):this.empty().append(value);},replaceWith:function(value){return this.after(value).remove();},eq:function(i){return this.slice(i,i+1);},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments));},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem);}));},andSelf:function(){return this.add(this.prevObject);},data:function(key,value){var parts=key.split(".");parts[1]=parts[1]?"."+parts[1]:"";if(value==null){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data==undefined&&this.length)data=jQuery.data(this[0],key);return data==null&&parts[1]?this.data(parts[0]):data;}else -return this.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){jQuery.data(this,key,value);});},removeData:function(key){return this.each(function(){jQuery.removeData(this,key);});},domManip:function(args,table,reverse,callback){var clone=this.length>1,elems;return this.each(function(){if(!elems){elems=jQuery.clean(args,this.ownerDocument);if(reverse)elems.reverse();}var obj=this;if(table&&jQuery.nodeName(this,"table")&&jQuery.nodeName(elems[0],"tr"))obj=this.getElementsByTagName("tbody")[0]||this.appendChild(this.ownerDocument.createElement("tbody"));var scripts=jQuery([]);jQuery.each(elems,function(){var elem=clone?jQuery(this).clone(true)[0]:this;if(jQuery.nodeName(elem,"script")){scripts=scripts.add(elem);}else{if(elem.nodeType==1)scripts=scripts.add(jQuery("script",elem).remove());callback.call(obj,elem);}});scripts.each(evalScript);});}};jQuery.prototype.init.prototype=jQuery.prototype;function evalScript(i,elem){if(elem.src)jQuery.ajax({url:elem.src,async:false,dataType:"script"});else -jQuery.globalEval(elem.text||elem.textContent||elem.innerHTML||"");if(elem.parentNode)elem.parentNode.removeChild(elem);}jQuery.extend=jQuery.fn.extend=function(){var target=arguments[0]||{},i=1,length=arguments.length,deep=false,options;if(target.constructor==Boolean){deep=target;target=arguments[1]||{};i=2;}if(typeof target!="object"&&typeof target!="function")target={};if(length==1){target=this;i=0;}for(;i-1;}},swap:function(elem,options,callback){var old={};for(var name in options){old[name]=elem.style[name];elem.style[name]=options[name];}callback.call(elem);for(var name in options)elem.style[name]=old[name];},css:function(elem,name,force){if(name=="width"||name=="height"){var val,props={position:"absolute",visibility:"hidden",display:"block"},which=name=="width"?["Left","Right"]:["Top","Bottom"];function getWH(){val=name=="width"?elem.offsetWidth:elem.offsetHeight;var padding=0,border=0;jQuery.each(which,function(){padding+=parseFloat(jQuery.curCSS(elem,"padding"+this,true))||0;border+=parseFloat(jQuery.curCSS(elem,"border"+this+"Width",true))||0;});val-=Math.round(padding+border);}if(jQuery(elem).is(":visible"))getWH();else -jQuery.swap(elem,props,getWH);return Math.max(0,val);}return jQuery.curCSS(elem,name,force);},curCSS:function(elem,name,force){var ret;function color(elem){if(!jQuery.browser.safari)return false;var ret=document.defaultView.getComputedStyle(elem,null);return!ret||ret.getPropertyValue("color")=="";}if(name=="opacity"&&jQuery.browser.msie){ret=jQuery.attr(elem.style,"opacity");return ret==""?"1":ret;}if(jQuery.browser.opera&&name=="display"){var save=elem.style.outline;elem.style.outline="0 solid black";elem.style.outline=save;}if(name.match(/float/i))name=styleFloat;if(!force&&elem.style&&elem.style[name])ret=elem.style[name];else if(document.defaultView&&document.defaultView.getComputedStyle){if(name.match(/float/i))name="float";name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var getComputedStyle=document.defaultView.getComputedStyle(elem,null);if(getComputedStyle&&!color(elem))ret=getComputedStyle.getPropertyValue(name);else{var swap=[],stack=[];for(var a=elem;a&&color(a);a=a.parentNode)stack.unshift(a);for(var i=0;i]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+">";});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("",""]||!tags.indexOf("",""]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
            "]||!tags.indexOf("",""]||(!tags.indexOf("",""]||!tags.indexOf("",""]||jQuery.browser.msie&&[1,"div
            ","
            "]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--)div=div.lastChild;if(jQuery.browser.msie){var tbody=!tags.indexOf(""&&tags.indexOf("=0;--j)if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length)tbody[j].parentNode.removeChild(tbody[j]);if(/^\s/.test(elem))div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]),div.firstChild);}elem=jQuery.makeArray(div.childNodes);}if(elem.length===0&&(!jQuery.nodeName(elem,"form")&&!jQuery.nodeName(elem,"select")))return;if(elem[0]==undefined||jQuery.nodeName(elem,"form")||elem.options)ret.push(elem);else -ret=jQuery.merge(ret,elem);});return ret;},attr:function(elem,name,value){if(!elem||elem.nodeType==3||elem.nodeType==8)return undefined;var fix=jQuery.isXMLDoc(elem)?{}:jQuery.props;if(name=="selected"&&jQuery.browser.safari)elem.parentNode.selectedIndex;if(fix[name]){if(value!=undefined)elem[fix[name]]=value;return elem[fix[name]];}else if(jQuery.browser.msie&&name=="style")return jQuery.attr(elem.style,"cssText",value);else if(value==undefined&&jQuery.browser.msie&&jQuery.nodeName(elem,"form")&&(name=="action"||name=="method"))return elem.getAttributeNode(name).nodeValue;else if(elem.tagName){if(value!=undefined){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode)throw"type property can't be changed";elem.setAttribute(name,""+value);}if(jQuery.browser.msie&&/href|src/.test(name)&&!jQuery.isXMLDoc(elem))return elem.getAttribute(name,2);return elem.getAttribute(name);}else{if(name=="opacity"&&jQuery.browser.msie){if(value!=undefined){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+(parseFloat(value).toString()=="NaN"?"":"alpha(opacity="+value*100+")");}return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100).toString():"";}name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase();});if(value!=undefined)elem[name]=value;return elem[name];}},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"");},makeArray:function(array){var ret=[];if(typeof array!="array")for(var i=0,length=array.length;i*",this).remove();while(this.firstChild)this.removeChild(this.firstChild);}},function(name,fn){jQuery.fn[name]=function(){return this.each(fn,arguments);};});jQuery.each(["Height","Width"],function(i,name){var type=name.toLowerCase();jQuery.fn[type]=function(size){return this[0]==window?jQuery.browser.opera&&document.body["client"+name]||jQuery.browser.safari&&window["inner"+name]||document.compatMode=="CSS1Compat"&&document.documentElement["client"+name]||document.body["client"+name]:this[0]==document?Math.max(Math.max(document.body["scroll"+name],document.documentElement["scroll"+name]),Math.max(document.body["offset"+name],document.documentElement["offset"+name])):size==undefined?(this.length?jQuery.css(this[0],type):null):this.css(type,size.constructor==String?size:size+"px");};});var chars=jQuery.browser.safari&&parseInt(jQuery.browser.version)<417?"(?:[\\w*_-]|\\\\.)":"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",quickChild=new RegExp("^>\\s*("+chars+"+)"),quickID=new RegExp("^("+chars+"+)(#)("+chars+"+)"),quickClass=new RegExp("^([#.]?)("+chars+"*)");jQuery.extend({expr:{"":function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},"#":function(a,i,m){return a.getAttribute("id")==m[2];},":":{lt:function(a,i,m){return im[3]-0;},nth:function(a,i,m){return m[3]-0==i;},eq:function(a,i,m){return m[3]-0==i;},first:function(a,i){return i==0;},last:function(a,i,m,r){return i==r.length-1;},even:function(a,i){return i%2==0;},odd:function(a,i){return i%2;},"first-child":function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},"last-child":function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},"only-child":function(a){return!jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},parent:function(a){return a.firstChild;},empty:function(a){return!a.firstChild;},contains:function(a,i,m){return(a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},visible:function(a){return"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},hidden:function(a){return"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},enabled:function(a){return!a.disabled;},disabled:function(a){return a.disabled;},checked:function(a){return a.checked;},selected:function(a){return a.selected||jQuery.attr(a,"selected");},text:function(a){return"text"==a.type;},radio:function(a){return"radio"==a.type;},checkbox:function(a){return"checkbox"==a.type;},file:function(a){return"file"==a.type;},password:function(a){return"password"==a.type;},submit:function(a){return"submit"==a.type;},image:function(a){return"image"==a.type;},reset:function(a){return"reset"==a.type;},button:function(a){return"button"==a.type||jQuery.nodeName(a,"button");},input:function(a){return/input|select|textarea|button/i.test(a.nodeName);},has:function(a,i,m){return jQuery.find(m[3],a).length;},header:function(a){return/h\d/i.test(a.nodeName);},animated:function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}}},parse:[/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,new RegExp("^([:.#]*)("+chars+"+)")],multiFilter:function(expr,elems,not){var old,cur=[];while(expr&&expr!=old){old=expr;var f=jQuery.filter(expr,elems,not);expr=f.t.replace(/^\s*,\s*/,"");cur=not?elems=f.r:jQuery.merge(cur,f.r);}return cur;},find:function(t,context){if(typeof t!="string")return[t];if(context&&context.nodeType!=1&&context.nodeType!=9)return[];context=context||document;var ret=[context],done=[],last,nodeName;while(t&&last!=t){var r=[];last=t;t=jQuery.trim(t);var foundToken=false;var re=quickChild;var m=re.exec(t);if(m){nodeName=m[1].toUpperCase();for(var i=0;ret[i];i++)for(var c=ret[i].firstChild;c;c=c.nextSibling)if(c.nodeType==1&&(nodeName=="*"||c.nodeName.toUpperCase()==nodeName))r.push(c);ret=r;t=t.replace(re,"");if(t.indexOf(" ")==0)continue;foundToken=true;}else{re=/^([>+~])\s*(\w*)/i;if((m=re.exec(t))!=null){r=[];var merge={};nodeName=m[2].toUpperCase();m=m[1];for(var j=0,rl=ret.length;j=0;if(!not&&pass||not&&!pass)tmp.push(r[i]);}return tmp;},filter:function(t,r,not){var last;while(t&&t!=last){last=t;var p=jQuery.parse,m;for(var i=0;p[i];i++){m=p[i].exec(t);if(m){t=t.substring(m[0].length);m[2]=m[2].replace(/\\/g,"");break;}}if(!m)break;if(m[1]==":"&&m[2]=="not")r=isSimple.test(m[3])?jQuery.filter(m[3],r,true).r:jQuery(r).not(m[3]);else if(m[1]==".")r=jQuery.classFilter(r,m[2],not);else if(m[1]=="["){var tmp=[],type=m[3];for(var i=0,rl=r.length;i=0)^not)tmp.push(a);}r=tmp;}else if(m[1]==":"&&m[2]=="nth-child"){var merge={},tmp=[],test=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3]=="even"&&"2n"||m[3]=="odd"&&"2n+1"||!/\D/.test(m[3])&&"0n+"+m[3]||m[3]),first=(test[1]+(test[2]||1))-0,last=test[3]-0;for(var i=0,rl=r.length;i=0)add=true;if(add^not)tmp.push(node);}r=tmp;}else{var fn=jQuery.expr[m[1]];if(typeof fn=="object")fn=fn[m[2]];if(typeof fn=="string")fn=eval("false||function(a,i){return "+fn+";}");r=jQuery.grep(r,function(elem,i){return fn(elem,i,m,r);},not);}}return{r:r,t:t};},dir:function(elem,dir){var matched=[];var cur=elem[dir];while(cur&&cur!=document){if(cur.nodeType==1)matched.push(cur);cur=cur[dir];}return matched;},nth:function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir])if(cur.nodeType==1&&++num==result)break;return cur;},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType==1&&(!elem||n!=elem))r.push(n);}return r;}});jQuery.event={add:function(elem,types,handler,data){if(elem.nodeType==3||elem.nodeType==8)return;if(jQuery.browser.msie&&elem.setInterval!=undefined)elem=window;if(!handler.guid)handler.guid=this.guid++;if(data!=undefined){var fn=handler;handler=function(){return fn.apply(this,arguments);};handler.data=data;handler.guid=fn.guid;}var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){var val;if(typeof jQuery=="undefined"||jQuery.event.triggered)return val;val=jQuery.event.handle.apply(arguments.callee.elem,arguments);return val;});handle.elem=elem;jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];handler.type=parts[1];var handlers=events[type];if(!handlers){handlers=events[type]={};if(!jQuery.event.special[type]||jQuery.event.special[type].setup.call(elem)===false){if(elem.addEventListener)elem.addEventListener(type,handle,false);else if(elem.attachEvent)elem.attachEvent("on"+type,handle);}}handlers[handler.guid]=handler;jQuery.event.global[type]=true;});elem=null;},guid:1,global:{},remove:function(elem,types,handler){if(elem.nodeType==3||elem.nodeType==8)return;var events=jQuery.data(elem,"events"),ret,index;if(events){if(types==undefined||(typeof types=="string"&&types.charAt(0)=="."))for(var type in events)this.remove(elem,type+(types||""));else{if(types.type){handler=types.handler;types=types.type;}jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];if(events[type]){if(handler)delete events[type][handler.guid];else -for(handler in events[type])if(!parts[1]||events[type][handler].type==parts[1])delete events[type][handler];for(ret in events[type])break;if(!ret){if(!jQuery.event.special[type]||jQuery.event.special[type].teardown.call(elem)===false){if(elem.removeEventListener)elem.removeEventListener(type,jQuery.data(elem,"handle"),false);else if(elem.detachEvent)elem.detachEvent("on"+type,jQuery.data(elem,"handle"));}ret=null;delete events[type];}}});}for(ret in events)break;if(!ret){var handle=jQuery.data(elem,"handle");if(handle)handle.elem=null;jQuery.removeData(elem,"events");jQuery.removeData(elem,"handle");}}},trigger:function(type,data,elem,donative,extra){data=jQuery.makeArray(data||[]);if(type.indexOf("!")>=0){type=type.slice(0,-1);var exclusive=true;}if(!elem){if(this.global[type])jQuery("*").add([window,document]).trigger(type,data);}else{if(elem.nodeType==3||elem.nodeType==8)return undefined;var val,ret,fn=jQuery.isFunction(elem[type]||null),event=!data[0]||!data[0].preventDefault;if(event)data.unshift(this.fix({type:type,target:elem}));data[0].type=type;if(exclusive)data[0].exclusive=true;if(jQuery.isFunction(jQuery.data(elem,"handle")))val=jQuery.data(elem,"handle").apply(elem,data);if(!fn&&elem["on"+type]&&elem["on"+type].apply(elem,data)===false)val=false;if(event)data.shift();if(extra&&jQuery.isFunction(extra)){ret=extra.apply(elem,val==null?data:data.concat(val));if(ret!==undefined)val=ret;}if(fn&&donative!==false&&val!==false&&!(jQuery.nodeName(elem,'a')&&type=="click")){this.triggered=true;try{elem[type]();}catch(e){}}this.triggered=false;}return val;},handle:function(event){var val;event=jQuery.event.fix(event||window.event||{});var parts=event.type.split(".");event.type=parts[0];var handlers=jQuery.data(this,"events")&&jQuery.data(this,"events")[event.type],args=Array.prototype.slice.call(arguments,1);args.unshift(event);for(var j in handlers){var handler=handlers[j];args[0].handler=handler;args[0].data=handler.data;if(!parts[1]&&!event.exclusive||handler.type==parts[1]){var ret=handler.apply(this,args);if(val!==false)val=ret;if(ret===false){event.preventDefault();event.stopPropagation();}}}if(jQuery.browser.msie)event.target=event.preventDefault=event.stopPropagation=event.handler=event.data=null;return val;},fix:function(event){var originalEvent=event;event=jQuery.extend({},originalEvent);event.preventDefault=function(){if(originalEvent.preventDefault)originalEvent.preventDefault();originalEvent.returnValue=false;};event.stopPropagation=function(){if(originalEvent.stopPropagation)originalEvent.stopPropagation();originalEvent.cancelBubble=true;};if(!event.target)event.target=event.srcElement||document;if(event.target.nodeType==3)event.target=originalEvent.target.parentNode;if(!event.relatedTarget&&event.fromElement)event.relatedTarget=event.fromElement==event.target?event.toElement:event.fromElement;if(event.pageX==null&&event.clientX!=null){var doc=document.documentElement,body=document.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc.clientTop||0);}if(!event.which&&((event.charCode||event.charCode===0)?event.charCode:event.keyCode))event.which=event.charCode||event.keyCode;if(!event.metaKey&&event.ctrlKey)event.metaKey=event.ctrlKey;if(!event.which&&event.button)event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)));return event;},special:{ready:{setup:function(){bindReady();return;},teardown:function(){return;}},mouseenter:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseover",jQuery.event.special.mouseenter.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseover",jQuery.event.special.mouseenter.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseenter";return jQuery.event.handle.apply(this,arguments);}},mouseleave:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseout",jQuery.event.special.mouseleave.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseout",jQuery.event.special.mouseleave.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseleave";return jQuery.event.handle.apply(this,arguments);}}}};jQuery.fn.extend({bind:function(type,data,fn){return type=="unload"?this.one(type,data,fn):this.each(function(){jQuery.event.add(this,type,fn||data,fn&&data);});},one:function(type,data,fn){return this.each(function(){jQuery.event.add(this,type,function(event){jQuery(this).unbind(event);return(fn||data).apply(this,arguments);},fn&&data);});},unbind:function(type,fn){return this.each(function(){jQuery.event.remove(this,type,fn);});},trigger:function(type,data,fn){return this.each(function(){jQuery.event.trigger(type,data,this,true,fn);});},triggerHandler:function(type,data,fn){if(this[0])return jQuery.event.trigger(type,data,this[0],false,fn);return undefined;},toggle:function(){var args=arguments;return this.click(function(event){this.lastToggle=0==this.lastToggle?1:0;event.preventDefault();return args[this.lastToggle].apply(this,arguments)||false;});},hover:function(fnOver,fnOut){return this.bind('mouseenter',fnOver).bind('mouseleave',fnOut);},ready:function(fn){bindReady();if(jQuery.isReady)fn.call(document,jQuery);else -jQuery.readyList.push(function(){return fn.call(this,jQuery);});return this;}});jQuery.extend({isReady:false,readyList:[],ready:function(){if(!jQuery.isReady){jQuery.isReady=true;if(jQuery.readyList){jQuery.each(jQuery.readyList,function(){this.apply(document);});jQuery.readyList=null;}jQuery(document).triggerHandler("ready");}}});var readyBound=false;function bindReady(){if(readyBound)return;readyBound=true;if(document.addEventListener&&!jQuery.browser.opera)document.addEventListener("DOMContentLoaded",jQuery.ready,false);if(jQuery.browser.msie&&window==top)(function(){if(jQuery.isReady)return;try{document.documentElement.doScroll("left");}catch(error){setTimeout(arguments.callee,0);return;}jQuery.ready();})();if(jQuery.browser.opera)document.addEventListener("DOMContentLoaded",function(){if(jQuery.isReady)return;for(var i=0;i=0){var selector=url.slice(off,url.length);url=url.slice(0,off);}callback=callback||function(){};var type="GET";if(params)if(jQuery.isFunction(params)){callback=params;params=null;}else{params=jQuery.param(params);type="POST";}var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(res,status){if(status=="success"||status=="notmodified")self.html(selector?jQuery("
            ").append(res.responseText.replace(//g,"")).find(selector):res.responseText);self.each(callback,[res.responseText,status,res]);}});return this;},serialize:function(){return jQuery.param(this.serializeArray());},serializeArray:function(){return this.map(function(){return jQuery.nodeName(this,"form")?jQuery.makeArray(this.elements):this;}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type));}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:val.constructor==Array?jQuery.map(val,function(val,i){return{name:elem.name,value:val};}):{name:elem.name,value:val};}).get();}});jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(i,o){jQuery.fn[o]=function(f){return this.bind(o,f);};});var jsc=(new Date).getTime();jQuery.extend({get:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data=null;}return jQuery.ajax({type:"GET",url:url,data:data,success:callback,dataType:type});},getScript:function(url,callback){return jQuery.get(url,null,callback,"script");},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},post:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data={};}return jQuery.ajax({type:"POST",url:url,data:data,success:callback,dataType:type});},ajaxSetup:function(settings){jQuery.extend(jQuery.ajaxSettings,settings);},ajaxSettings:{global:true,type:"GET",timeout:0,contentType:"application/x-www-form-urlencoded",processData:true,async:true,data:null,username:null,password:null,accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(s){var jsonp,jsre=/=\?(&|$)/g,status,data;s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));if(s.data&&s.processData&&typeof s.data!="string")s.data=jQuery.param(s.data);if(s.dataType=="jsonp"){if(s.type.toLowerCase()=="get"){if(!s.url.match(jsre))s.url+=(s.url.match(/\?/)?"&":"?")+(s.jsonp||"callback")+"=?";}else if(!s.data||!s.data.match(jsre))s.data=(s.data?s.data+"&":"")+(s.jsonp||"callback")+"=?";s.dataType="json";}if(s.dataType=="json"&&(s.data&&s.data.match(jsre)||s.url.match(jsre))){jsonp="jsonp"+jsc++;if(s.data)s.data=(s.data+"").replace(jsre,"="+jsonp+"$1");s.url=s.url.replace(jsre,"="+jsonp+"$1");s.dataType="script";window[jsonp]=function(tmp){data=tmp;success();complete();window[jsonp]=undefined;try{delete window[jsonp];}catch(e){}if(head)head.removeChild(script);};}if(s.dataType=="script"&&s.cache==null)s.cache=false;if(s.cache===false&&s.type.toLowerCase()=="get"){var ts=(new Date()).getTime();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"");}if(s.data&&s.type.toLowerCase()=="get"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null;}if(s.global&&!jQuery.active++)jQuery.event.trigger("ajaxStart");if((!s.url.indexOf("http")||!s.url.indexOf("//"))&&s.dataType=="script"&&s.type.toLowerCase()=="get"){var head=document.getElementsByTagName("head")[0];var script=document.createElement("script");script.src=s.url;if(s.scriptCharset)script.charset=s.scriptCharset;if(!jsonp){var done=false;script.onload=script.onreadystatechange=function(){if(!done&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){done=true;success();complete();head.removeChild(script);}};}head.appendChild(script);return undefined;}var requestDone=false;var xml=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();xml.open(s.type,s.url,s.async,s.username,s.password);try{if(s.data)xml.setRequestHeader("Content-Type",s.contentType);if(s.ifModified)xml.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT");xml.setRequestHeader("X-Requested-With","XMLHttpRequest");xml.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default);}catch(e){}if(s.beforeSend)s.beforeSend(xml);if(s.global)jQuery.event.trigger("ajaxSend",[xml,s]);var onreadystatechange=function(isTimeout){if(!requestDone&&xml&&(xml.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null;}status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xml)&&"error"||s.ifModified&&jQuery.httpNotModified(xml,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xml,s.dataType);}catch(e){status="parsererror";}}if(status=="success"){var modRes;try{modRes=xml.getResponseHeader("Last-Modified");}catch(e){}if(s.ifModified&&modRes)jQuery.lastModified[s.url]=modRes;if(!jsonp)success();}else -jQuery.handleError(s,xml,status);complete();if(s.async)xml=null;}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0)setTimeout(function(){if(xml){xml.abort();if(!requestDone)onreadystatechange("timeout");}},s.timeout);}try{xml.send(s.data);}catch(e){jQuery.handleError(s,xml,null,e);}if(!s.async)onreadystatechange();function success(){if(s.success)s.success(data,status);if(s.global)jQuery.event.trigger("ajaxSuccess",[xml,s]);}function complete(){if(s.complete)s.complete(xml,status);if(s.global)jQuery.event.trigger("ajaxComplete",[xml,s]);if(s.global&&!--jQuery.active)jQuery.event.trigger("ajaxStop");}return xml;},handleError:function(s,xml,status,e){if(s.error)s.error(xml,status,e);if(s.global)jQuery.event.trigger("ajaxError",[xml,s,e]);},active:0,httpSuccess:function(r){try{return!r.status&&location.protocol=="file:"||(r.status>=200&&r.status<300)||r.status==304||r.status==1223||jQuery.browser.safari&&r.status==undefined;}catch(e){}return false;},httpNotModified:function(xml,url){try{var xmlRes=xml.getResponseHeader("Last-Modified");return xml.status==304||xmlRes==jQuery.lastModified[url]||jQuery.browser.safari&&xml.status==undefined;}catch(e){}return false;},httpData:function(r,type){var ct=r.getResponseHeader("content-type");var xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0;var data=xml?r.responseXML:r.responseText;if(xml&&data.documentElement.tagName=="parsererror")throw"parsererror";if(type=="script")jQuery.globalEval(data);if(type=="json")data=eval("("+data+")");return data;},param:function(a){var s=[];if(a.constructor==Array||a.jquery)jQuery.each(a,function(){s.push(encodeURIComponent(this.name)+"="+encodeURIComponent(this.value));});else -for(var j in a)if(a[j]&&a[j].constructor==Array)jQuery.each(a[j],function(){s.push(encodeURIComponent(j)+"="+encodeURIComponent(this));});else -s.push(encodeURIComponent(j)+"="+encodeURIComponent(a[j]));return s.join("&").replace(/%20/g,"+");}});jQuery.fn.extend({show:function(speed,callback){return speed?this.animate({height:"show",width:"show",opacity:"show"},speed,callback):this.filter(":hidden").each(function(){this.style.display=this.oldblock||"";if(jQuery.css(this,"display")=="none"){var elem=jQuery("<"+this.tagName+" />").appendTo("body");this.style.display=elem.css("display");if(this.style.display=="none")this.style.display="block";elem.remove();}}).end();},hide:function(speed,callback){return speed?this.animate({height:"hide",width:"hide",opacity:"hide"},speed,callback):this.filter(":visible").each(function(){this.oldblock=this.oldblock||jQuery.css(this,"display");this.style.display="none";}).end();},_toggle:jQuery.fn.toggle,toggle:function(fn,fn2){return jQuery.isFunction(fn)&&jQuery.isFunction(fn2)?this._toggle(fn,fn2):fn?this.animate({height:"toggle",width:"toggle",opacity:"toggle"},fn,fn2):this.each(function(){jQuery(this)[jQuery(this).is(":hidden")?"show":"hide"]();});},slideDown:function(speed,callback){return this.animate({height:"show"},speed,callback);},slideUp:function(speed,callback){return this.animate({height:"hide"},speed,callback);},slideToggle:function(speed,callback){return this.animate({height:"toggle"},speed,callback);},fadeIn:function(speed,callback){return this.animate({opacity:"show"},speed,callback);},fadeOut:function(speed,callback){return this.animate({opacity:"hide"},speed,callback);},fadeTo:function(speed,to,callback){return this.animate({opacity:to},speed,callback);},animate:function(prop,speed,easing,callback){var optall=jQuery.speed(speed,easing,callback);return this[optall.queue===false?"each":"queue"](function(){if(this.nodeType!=1)return false;var opt=jQuery.extend({},optall);var hidden=jQuery(this).is(":hidden"),self=this;for(var p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden)return jQuery.isFunction(opt.complete)&&opt.complete.apply(this);if(p=="height"||p=="width"){opt.display=jQuery.css(this,"display");opt.overflow=this.style.overflow;}}if(opt.overflow!=null)this.style.overflow="hidden";opt.curAnim=jQuery.extend({},prop);jQuery.each(prop,function(name,val){var e=new jQuery.fx(self,opt,name);if(/toggle|show|hide/.test(val))e[val=="toggle"?hidden?"show":"hide":val](prop);else{var parts=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),start=e.cur(true)||0;if(parts){var end=parseFloat(parts[2]),unit=parts[3]||"px";if(unit!="px"){self.style[name]=(end||1)+unit;start=((end||1)/e.cur(true))*start;self.style[name]=start+unit;}if(parts[1])end=((parts[1]=="-="?-1:1)*end)+start;e.custom(start,end,unit);}else -e.custom(start,val,"");}});return true;});},queue:function(type,fn){if(jQuery.isFunction(type)||(type&&type.constructor==Array)){fn=type;type="fx";}if(!type||(typeof type=="string"&&!fn))return queue(this[0],type);return this.each(function(){if(fn.constructor==Array)queue(this,type,fn);else{queue(this,type).push(fn);if(queue(this,type).length==1)fn.apply(this);}});},stop:function(clearQueue,gotoEnd){var timers=jQuery.timers;if(clearQueue)this.queue([]);this.each(function(){for(var i=timers.length-1;i>=0;i--)if(timers[i].elem==this){if(gotoEnd)timers[i](true);timers.splice(i,1);}});if(!gotoEnd)this.dequeue();return this;}});var queue=function(elem,type,array){if(!elem)return undefined;type=type||"fx";var q=jQuery.data(elem,type+"queue");if(!q||array)q=jQuery.data(elem,type+"queue",array?jQuery.makeArray(array):[]);return q;};jQuery.fn.dequeue=function(type){type=type||"fx";return this.each(function(){var q=queue(this,type);q.shift();if(q.length)q[0].apply(this);});};jQuery.extend({speed:function(speed,easing,fn){var opt=speed&&speed.constructor==Object?speed:{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&easing.constructor!=Function&&easing};opt.duration=(opt.duration&&opt.duration.constructor==Number?opt.duration:{slow:600,fast:200}[opt.duration])||400;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false)jQuery(this).dequeue();if(jQuery.isFunction(opt.old))opt.old.apply(this);};return opt;},easing:{linear:function(p,n,firstNum,diff){return firstNum+diff*p;},swing:function(p,n,firstNum,diff){return((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum;}},timers:[],timerId:null,fx:function(elem,options,prop){this.options=options;this.elem=elem;this.prop=prop;if(!options.orig)options.orig={};}});jQuery.fx.prototype={update:function(){if(this.options.step)this.options.step.apply(this.elem,[this.now,this]);(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);if(this.prop=="height"||this.prop=="width")this.elem.style.display="block";},cur:function(force){if(this.elem[this.prop]!=null&&this.elem.style[this.prop]==null)return this.elem[this.prop];var r=parseFloat(jQuery.css(this.elem,this.prop,force));return r&&r>-10000?r:parseFloat(jQuery.curCSS(this.elem,this.prop))||0;},custom:function(from,to,unit){this.startTime=(new Date()).getTime();this.start=from;this.end=to;this.unit=unit||this.unit||"px";this.now=this.start;this.pos=this.state=0;this.update();var self=this;function t(gotoEnd){return self.step(gotoEnd);}t.elem=this.elem;jQuery.timers.push(t);if(jQuery.timerId==null){jQuery.timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;ithis.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var done=true;for(var i in this.options.curAnim)if(this.options.curAnim[i]!==true)done=false;if(done){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(jQuery.css(this.elem,"display")=="none")this.elem.style.display="block";}if(this.options.hide)this.elem.style.display="none";if(this.options.hide||this.options.show)for(var p in this.options.curAnim)jQuery.attr(this.elem.style,p,this.options.orig[p]);}if(done&&jQuery.isFunction(this.options.complete))this.options.complete.apply(this.elem);return false;}else{var n=t-this.startTime;this.state=n/this.options.duration;this.pos=jQuery.easing[this.options.easing||(jQuery.easing.swing?"swing":"linear")](this.state,n,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update();}return true;}};jQuery.fx.step={scrollLeft:function(fx){fx.elem.scrollLeft=fx.now;},scrollTop:function(fx){fx.elem.scrollTop=fx.now;},opacity:function(fx){jQuery.attr(fx.elem.style,"opacity",fx.now);},_default:function(fx){fx.elem.style[fx.prop]=fx.now+fx.unit;}};jQuery.fn.offset=function(){var left=0,top=0,elem=this[0],results;if(elem)with(jQuery.browser){var parent=elem.parentNode,offsetChild=elem,offsetParent=elem.offsetParent,doc=elem.ownerDocument,safari2=safari&&parseInt(version)<522&&!/adobeair/i.test(userAgent),fixed=jQuery.css(elem,"position")=="fixed";if(elem.getBoundingClientRect){var box=elem.getBoundingClientRect();add(box.left+Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),box.top+Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));add(-doc.documentElement.clientLeft,-doc.documentElement.clientTop);}else{add(elem.offsetLeft,elem.offsetTop);while(offsetParent){add(offsetParent.offsetLeft,offsetParent.offsetTop);if(mozilla&&!/^t(able|d|h)$/i.test(offsetParent.tagName)||safari&&!safari2)border(offsetParent);if(!fixed&&jQuery.css(offsetParent,"position")=="fixed")fixed=true;offsetChild=/^body$/i.test(offsetParent.tagName)?offsetChild:offsetParent;offsetParent=offsetParent.offsetParent;}while(parent&&parent.tagName&&!/^body|html$/i.test(parent.tagName)){if(!/^inline|table.*$/i.test(jQuery.css(parent,"display")))add(-parent.scrollLeft,-parent.scrollTop);if(mozilla&&jQuery.css(parent,"overflow")!="visible")border(parent);parent=parent.parentNode;}if((safari2&&(fixed||jQuery.css(offsetChild,"position")=="absolute"))||(mozilla&&jQuery.css(offsetChild,"position")!="absolute"))add(-doc.body.offsetLeft,-doc.body.offsetTop);if(fixed)add(Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));}results={top:top,left:left};}function border(elem){add(jQuery.curCSS(elem,"borderLeftWidth",true),jQuery.curCSS(elem,"borderTopWidth",true));}function add(l,t){left+=parseInt(l)||0;top+=parseInt(t)||0;}return results;};})(); \ No newline at end of file diff --git a/tryruby/public/javascripts/json2.js b/tryruby/public/javascripts/json2.js deleted file mode 100644 index d4f4541..0000000 --- a/tryruby/public/javascripts/json2.js +++ /dev/null @@ -1 +0,0 @@ -if(!this.JSON){this.JSON={}}(function(){function f(n){return n<10?'0'+n:n}if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+'-'+f(this.getUTCMonth()+1)+'-'+f(this.getUTCDate())+'T'+f(this.getUTCHours())+':'+f(this.getUTCMinutes())+':'+f(this.getUTCSeconds())+'Z':null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key)}if(typeof rep==='function'){value=rep.call(holder,key,value)}switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null'}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object Array]'){length=value.length;for(i=0;i)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, -Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& -(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, -a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== -"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, -function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
            a"; -var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, -parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= -false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= -s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, -applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; -else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, -a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== -w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, -cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= -c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); -a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, -function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); -k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), -C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B=0){a.type= -e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& -f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; -if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", -e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, -"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, -d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, -e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); -t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| -g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, -CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, -g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, -text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, -setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= -h[3];l=0;for(m=h.length;l=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== -"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, -h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& -q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; -if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="

            ";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); -(function(){var g=s.createElement("div");g.innerHTML="
            ";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: -function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var j=d;j0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= -{},i;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== -"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", -d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? -a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== -1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"},F={option:[1,""],legend:[1,"
            ","
            "],thead:[1,"","
            "],tr:[2,"","
            "],td:[3,"","
            "],col:[2,"","
            "],area:[1,"",""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
            ","
            "];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= -c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, -wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, -prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, -this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); -return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, -""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); -return this}else{e=0;for(var j=d.length;e0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", -""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===""&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= -c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? -c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= -function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= -Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, -"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= -a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= -a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=//gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!== -"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("
            ").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this}, -serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), -function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href, -global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&& -e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)? -"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache=== -false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B= -false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since", -c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E|| -d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x); -g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status=== -1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b=== -"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional; -if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration=== -"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]|| -c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start; -this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now= -this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem, -e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b
            "; -a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b); -c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a, -d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top- -f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset": -"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in -e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window); -/*json2.js*/ -if(!this.JSON){this.JSON={}}(function(){function f(n){return n<10?'0'+n:n}if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+'-'+f(this.getUTCMonth()+1)+'-'+f(this.getUTCDate())+'T'+f(this.getUTCHours())+':'+f(this.getUTCMinutes())+':'+f(this.getUTCSeconds())+'Z':null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key)}if(typeof rep==='function'){value=rep.call(holder,key,value)}switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null'}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object Array]'){length=value.length;for(i=0;i
            ');var typer=$('');var promptBox;var prompt;var promptLabel=config&&config.promptLabel?config.promptLabel:"> ";var column=0;var promptText='';var restoreText='';var history=[];var ringn=0;var cancelKeyPress=0;var extern={};(function(){container.append(inner);inner.append(typer);typer.css({position:'absolute',top:0,left:'-999px'});if(config.welcomeMessage)message(config.welcomeMessage,'jquery-console-welcome');newPromptBox();if(config.autofocus){inner.addClass('jquery-console-focus');typer.focus();setTimeout(function(){inner.addClass('jquery-console-focus');typer.focus()},100)}})();extern.reset=function(){var welcome=true;inner.parent().fadeOut(function(){inner.find('div').each(function(){if(!welcome)$(this).remove();welcome=false});newPromptBox();inner.parent().fadeIn(function(){inner.addClass('jquery-console-focus');typer.focus()})})};function newPromptBox(){column=0;promptText='';promptBox=$('
            ');var label=$('');promptBox.append(label.text(promptLabel).show());prompt=$('');promptBox.append(prompt);inner.append(promptBox);updatePromptDisplay()};container.click(function(){inner.addClass('jquery-console-focus');inner.removeClass('jquery-console-nofocus');typer.focus();scrollToBottom();return false});typer.blur(function(){inner.removeClass('jquery-console-focus');inner.addClass('jquery-console-nofocus')});typer.keydown(function(e){cancelKeyPress=0;var keyCode=e.keyCode;if(isControlCharacter(keyCode)){cancelKeyPress=keyCode;if(!typer.consoleControl(keyCode)){return false}}});typer.keypress(function(e){var keyCode=e.keyCode||e.which;if(cancelKeyPress!=keyCode&&keyCode>=32){if(cancelKeyPress)return false;typer.consoleInsert(keyCode)}if($.browser.webkit)return false});function isControlCharacter(keyCode){return((keyCode>=keyCodes.left&&keyCode<=keyCodes.down)||keyCode==keyCodes.back||keyCode==keyCodes.del||keyCode==keyCodes.end||keyCode==keyCodes.start||keyCode==keyCodes.ret)};typer.consoleControl=function(keyCode){switch(keyCode){case keyCodes.left:{moveColumn(-1);updatePromptDisplay();return false;break}case keyCodes.right:{moveColumn(1);updatePromptDisplay();return false;break}case keyCodes.back:{if(moveColumn(-1)){deleteCharAtPos();updatePromptDisplay()}return false;break}case keyCodes.del:{if(deleteCharAtPos())updatePromptDisplay();return false;break}case keyCodes.end:{if(moveColumn(promptText.length-column))updatePromptDisplay();return false;break}case keyCodes.start:{if(moveColumn(-column))updatePromptDisplay();return false;break}case keyCodes.ret:{commandTrigger();return false}case keyCodes.up:{rotateHistory(-1);return false}case keyCodes.down:{rotateHistory(1);return false}default:}};function rotateHistory(n){if(history.length==0)return;ringn+=n;if(ringn<0)ringn=history.length;else if(ringn>history.length)ringn=0;var prevText=promptText;if(ringn==0){promptText=restoreText}else{promptText=history[ringn-1]}if(config.historyPreserveColumn){if(promptText.length
            ');if(className)mesg.addClass(className);mesg.filledText(msg).hide();inner.append(mesg);mesg.show()};typer.consoleInsert=function(keyCode){var char=String.fromCharCode(keyCode);var before=promptText.substring(0,column);var after=promptText.substring(column);promptText=before+char+after;moveColumn(1);restoreText=promptText;updatePromptDisplay()};function moveColumn(n){if(column+n>=0&&column+n<=promptText.length){column+=n;return true}else return false};function updatePromptDisplay(){var line=promptText;var html='';if(column>0&&line==''){html=cursor}else if(column==promptText.length){html=htmlEncode(line)+cursor}else{var before=line.substring(0,column);var current=line.substring(column,column+1);if(current){current=''+htmlEncode(current)+''}var after=line.substring(column+1);html=htmlEncode(before)+current+htmlEncode(after)}prompt.html(html);scrollToBottom()};function htmlEncode(text){return(text.replace(/&/g,'&').replace(/&]{10})/g,'$1­'+wbr))};return extern};$.fn.filledText=function(txt){$(this).text(txt);$(this).html($(this).html().replace(/\n/g,'
            '));return this}})(jQuery); diff --git a/tryruby/public/javascripts/mouseapp_2.js b/tryruby/public/javascripts/mouseapp_2.js deleted file mode 100755 index de5c777..0000000 --- a/tryruby/public/javascripts/mouseapp_2.js +++ /dev/null @@ -1,913 +0,0 @@ -// -// Copyright (c) 2008 why the lucky stiff -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, -// and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT -// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -var MouseApp = { - Version: '0.12', - CharCodes: { - 0: ' ', 1: ' ', 9: ' ', - 32: ' ', 34: '"', 38: '&', - 60: '<', 62: '>', 127: '◊', - 0x20AC: '€' - }, - KeyCodes: { - Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 33, PageDown: 34, - End: 35, Home: 36, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 45, - Delete: 46, F1: 112, F2: 113, F3: 114, F4: 115, F5: 116, F6: 117, - F7: 118, F8: 119, F10: 121 - }, - CodeKeys: {}, - Modes: { 1: 'b', 2: 'u', 4: 'i', 8: 'strike' }, - ModeIds: { r: 1, u: 2, i: 4, s: 8 }, - Colors: ['black', 'blue', 'green', - 'cyan', 'red', 'purple', 'brown', - 'gray', 'dark_gray', 'lt_blue', - 'lt_green', 'lt_cyan', 'lt_red', - 'lt_purple', 'yellow', 'white'] -} -//some of these are patently false, because I need to get on a real keyboard-- not a macbook. -if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1){ - MouseApp.KeyCodes = { - Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, - End: 63275, Home: 63273, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 632325, - Delete: 46, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, - F7: 63242, F8: 63243, F10: 63244 - } - -} - -//even though I am tempted to combine chrome and opera into the same if statment, I will refrain for now -// i dont have proper access to a proper keyboard and there might be a single difference between the two -if (navigator.userAgent.indexOf("Opera") > -1){ - MouseApp.KeyCodes = { - Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, - End: 63275, Home: 63273, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 632325, - Delete: 46, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, - F7: 63242, F8: 63243, F10: 63244 - } - -} - -// i am going to comment this out, since this seems un needed. if it past december 15 2009 and this -// is still commented it, please del me -//if ( navigator.appVersion.indexOf('AppleWebKit') > 0 ) { -// MouseApp.KeyCodes = { -// Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, -// End: 63275, Home: 63273, Left: 63234, Up: 63232, Right: 63235, Down: 63233, Insert: 632325, -// Delete: 63272, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, -// F7: 63242, F8: 63243, F10: 63244 -// };// -//} -for ( var k in MouseApp.KeyCodes ) { - MouseApp.CodeKeys[MouseApp.KeyCodes[k]] = k; -} - -MouseApp.isPrintable = function(ch) { - return (ch >= 32); -}; - -MouseApp.Base = function(){}; -MouseApp.Base.prototype = { - setOptions: function(options) { - this.options = { - columns: 72, rows: 24, indent: 2, - title: 'MouseApp', - blinkRate: 500, - ps: '>', - greeting:'%+r Terminal ready. %-r' - } - $.extend(this.options, options || {}); - } -} - -MouseApp.Manager = new Object(); -$.extend(MouseApp.Manager, { - observeTerm: function(term) { - this.activeTerm = term; - if ( this.observingKeyboard ) return; - var mgr = this; - if ( term.input ) { - term.input.keypress(function(e) { mgr.onKeyPress(e) }); - if (!window.opera) term.input.keydown(function(e) { mgr.onKeyDown(e) }); - else window.setInterval(function(){term.input.focus()},1); - } else { - if (!window.opera) $(document).keydown(function(e) { mgr.onKeyDown(e) }); - $(document).keypress(function(e) { mgr.onKeyPress(e) }); - } - this.observingKeyboard = true; - }, - - onKeyDown: function(e) { - e = (e) ? e : ((event) ? event : null); - if ( e && MouseApp.CodeKeys[e.keyCode] ) { - if ( window.event ) { - this.sendKeyPress(e); - } - this.blockEvent(e); - return false; - } - return true; - }, - - onKeyPress: function(e) { - if ( !window.opera && window.event && e.keyCode != 13 && e.keyCode != 8 ) { - e.charCode = e.keyCode; e.keyCode = null; - } - if ( e.keyCode == 191 ) { /* FF 1.0.x sends this upsy quizy -- ignore */ - return; - } - return this.sendKeyPress(e); - }, - - sendKeyPress: function(e) { - var term = MouseApp.Manager.activeTerm; - term.cursorOff(); - b = term.onKeyPress(e); - term.cursorOn(); - return b; - }, - - blockEvent: function (e) { - e.cancelBubble=true; - if (window.event && !window.opera) e.keyCode=0; - if (e.stopPropagation) e.stopPropagation(); - if (e.preventDefault) e.preventDefault(); - } -}); - -/* Basic text window functionality */ -MouseApp.Window = function(element, options) { - this.element = $(element); - this.setOptions(options); - this.initWindow(); -}; - -$.extend(MouseApp.Window.prototype, (new MouseApp.Base()), { - initWindow: function() { - var html = ''; - for ( var i = 0; i < this.options.rows; i++ ) { - html += "
             
            \n"; - } - this.element.html(html); - this.typingOn(); - if (this.options.input) { - this.input = $(this.options.input); - this.input.focus(); - } - MouseApp.Manager.observeTerm(this); - this.clear(); - this.cursorOn(); - this.painting = true; - this.element.css({visibility: 'visible'}); - }, - - text: function() { - var str = ""; - for (var i = 0; i < this.screen.length; i++ ) { - for (var j = 0; j < this.options.columns; j++ ) { - var ch = this.screen[i][j]; - if ( ch[0] != 0 ) { - str += String.fromCharCode(ch[0]); - } - } - } - return str; - }, - - clear: function() { - this.rpos = 0; - this.cpos = 0; - this.screen = []; - this.element.html(''); - this.screen[0] = this.fillRow(this.options.columns, 0); - this.paint(0); - }, - - typingOn: function() { this.typing = true; }, - typingOff: function() { this.typing = false; }, - - cursorOn: function() { - if ( this.blinker ) { - clearInterval( this.blinker ); - } - this.underblink = this.screen[this.rpos][this.cpos][1]; - MouseApp.Manager.activeTerm.blink(); - this.blinker = setInterval(function(){MouseApp.Manager.activeTerm.blink();}, this.options.blinkRate); - this.cursor = true; - }, - - cursorOff: function() { - if ( this.blinker ) { - clearInterval( this.blinker ); - } - if ( this.cursor ) { - this.screen[this.rpos][this.cpos][1] = this.underblink; - this.paint(this.rpos); - this.cursor = false; - } - }, - - blink: function() { - if ( this == MouseApp.Manager.activeTerm ) { - var mode = this.screen[this.rpos][this.cpos][1]; - this.screen[this.rpos][this.cpos][1] = ( mode & 1 ) ? mode & 4094 : mode | 1; - this.paint(this.rpos); - } - }, - - fillRow: function(len, ch, mode) { - ary = [] - for (var i = 0; i < len; i++) { - ary[i] = [ch, mode]; - } - return ary; - }, - - paint: function(start, end) { - if (!this.painting) return; - - if (!end) end = start; - for (var row = start; row <= end && row < this.screen.length; row++) { - var html = ''; - var mode = 0; - var fcolor = 0; - var bcolor = 0; - var spans = 0; - for (var i = 0; i < this.options.columns; i++ ) { - var c = this.screen[row][i][0]; - var m = this.screen[row][i][1] & 15; // 4 mode bits - var f = (this.screen[row][i][1] & (15 << 4)) >> 4; // 4 foreground bits - var b = (this.screen[row][i][1] & (15 << 8)) >> 8; // 4 background bits - if ( m != mode ) { - if ( MouseApp.Modes[mode] ) html += ""; - if ( MouseApp.Modes[m] ) html += "<" + MouseApp.Modes[m] + ">"; - mode = m; - } - if ( ( f != fcolor && f == 0 ) || ( b != bcolor && b == 0 ) ) { - for ( var s = 0; s < spans; s++ ) html += ""; - fcolor = 0; bcolor = 0; - } - if ( f != fcolor ) { - if ( MouseApp.Colors[f] ) { - html += ""; - spans++; - } - fcolor = f; - } - if ( b != bcolor ) { - if ( MouseApp.Colors[b] ) html += ""; - spans++; bcolor = b; - } - html += MouseApp.CharCodes[c] ? MouseApp.CharCodes[c] : String.fromCharCode(c); - } - if ( MouseApp.Modes[mode] ) html += ""; - for ( var s = 0; s < spans; s++ ) html += ""; - var new_id = this.element.attr('id') + '_' + row; - if (!$('#' + new_id).get(0)) { - this.element.append("
             
            "); - this.scrollAllTheWayDown(); - } - $('#' + new_id).html(html); - } - }, - - onAfterKey: function() { - this.scrollAllTheWayDown(); - }, - - highlightLine: function(i) { - if (i >= 0 && i < this.screen.length) - { - $("#" + this.element.attr('id') + "_" + i); - } - }, - - scrollToLine: function(i) { - var p = this.element[0].parentNode; - if ( p.scrollHeight > p.clientHeight ) { - p.scrollTop = (p.scrollHeight - p.clientHeight); - } - }, - - scrollAllTheWayDown: function() { - var p = this.element[0].parentNode; - if ( p.scrollHeight > p.clientHeight ) { - p.scrollTop = (p.scrollHeight - p.clientHeight); - } - }, - - putc: function(ch, mode) { - if ( ch == 13 ) { - return; - } else if ( ch == 10 ) { - this.screen[this.rpos][this.cpos] = [ch, mode]; - this.advanceLine(); - } else { - this.screen[this.rpos][this.cpos] = [ch, mode]; - this.paint(this.rpos); - this.advance(); - } - }, - - zpad: function(n) { - if (n < 10) n = "0" + n; - return n; - }, - - puts: function(str, mode) { - if ( !str ) return; - var p = this.painting; - var r = this.rpos; - this.painting = false; - for ( var i = 0; i < str.length; i++ ) { - this.insertc(str.charCodeAt(i), mode); - } - this.painting = p; - this.paint(r, this.rpos); - }, - - advance: function() { - this.cpos++; - if ( this.cpos >= this.options.columns ) { - this.advanceLine(); - } - }, - - advanceLine: function() { - this.cpos = 0; - this.rpos++; - this.ensureRow(this.rpos); - this.paint(this.rpos, this.screen.length - 1); - }, - - fwdc: function() { - var r = this.rpos; - var c = this.cpos; - if ( c < this.options.columns - 1 ) { - c++; - } else if ( r < this.screen.length - 1 ) { - r++; - c = 0; - } - var ch = (c == 0 ? this.screen[r-1][this.options.columns-1] : this.screen[r][c-1]); - if ( MouseApp.isPrintable(ch[0]) ) { - this.rpos = r; - this.cpos = c; - } - }, - - fwdLine: function() { - if ( this.rpos >= this.screen.length - 1 ) return; - this.rpos++; - while ( this.cpos > 0 && !MouseApp.isPrintable(this.screen[this.rpos][this.cpos - 1][0]) ) { - this.cpos--; - } - }, - - backc: function() { - var r = this.rpos; - var c = this.cpos; - if ( c > 0 ) { - c--; - } else if ( r > 0 ) { - c = this.options.columns - 1; - r--; - } - if ( MouseApp.isPrintable(this.screen[r][c][0]) ) { - this.rpos = r; - this.cpos = c; - return true; - } - return false; - }, - - getTypingStart: function() { - var c = this.cpos; - if ( !MouseApp.isPrintable(this.screen[this.rpos][c][0]) ) { - c--; - } - var pos = null; - for ( var r = this.rpos; r >= 0; r-- ) { - while ( c >= 0 ) { - if ( !MouseApp.isPrintable(this.screen[r][c][0]) ) { - return pos; - } - pos = [r, c]; - c--; - } - c = this.options.columns - 1; - } - }, - - getTypingEnd: function(mod) { - var c = this.cpos; - if ( !MouseApp.isPrintable(this.screen[this.rpos][c][0]) ) { - c--; - } - var pos = null; - for ( var r = this.rpos; r < this.screen.length; r++ ) { - while ( c < this.options.columns ) { - if ( !this.screen[r] || !this.screen[r][c] || !MouseApp.isPrintable(this.screen[r][c][0]) ) { - if (!mod) return pos; - mod--; - } - pos = [r, c]; - c++; - } - c = 0; - } - }, - - getTypingAt: function(start, end) { - var r = start[0]; - var c = start[1]; - var str = ''; - while ( r < end[0] || c <= end[1] ) { - if ( c < this.options.columns ) { - str += String.fromCharCode(this.screen[r][c][0]); - c++; - } else { - c = 0; - r++; - } - } - return str; - }, - - ensureRow: function(r) { - if (!this.screen[r]) { - this.screen[r] = this.fillRow(this.options.columns, 0); - } - }, - - insertc: function(ch, mode) { - var r = this.rpos; var c = this.cpos; - var end = this.getTypingEnd(+1); - if (end) { - var thisc = null; - var lastc = this.screen[this.rpos][this.cpos]; - while ( r < end[0] || c <= end[1] ) { - if ( c < this.options.columns ) { - thisc = this.screen[r][c]; - this.screen[r][c] = lastc; - lastc = thisc; - c++; - } else { - c = 0; - r++; - this.ensureRow(r); - } - } - this.paint(this.rpos, end[0]); - } - this.putc(ch, mode); - }, - - delc: function() { - /* end of line */ - if ( MouseApp.isPrintable(this.screen[this.rpos][this.cpos][0]) ) { - var end = this.getTypingEnd(); - var thisc = null; - var lastc = [0, 0]; - while ( this.rpos < end[0] || this.cpos <= end[1] ) { - if ( end[1] >= 0 ) { - thisc = this.screen[end[0]][end[1]]; - this.screen[end[0]][end[1]] = lastc; - lastc = thisc; - end[1]--; - } else { - end[1] = this.options.columns - 1; - this.paint(end[0]); - end[0]--; - } - } - } - }, - - backspace: function() { - /* end of line */ - if ( !MouseApp.isPrintable(this.screen[this.rpos][this.cpos][0]) ) { - this.backc(); - this.screen[this.rpos][this.cpos] = [0, 0]; - } else { - if ( this.backc() ) this.delc(); - } - }, - - backLine: function() { - if ( this.rpos < 1 ) return; - this.rpos--; - while ( this.cpos > 0 && !MouseApp.isPrintable(this.screen[this.rpos][this.cpos - 1][0]) ) { - this.cpos--; - } - }, - - onKeyPress: function(e) { - var ch = e.keyCode; - var key_name = MouseApp.CodeKeys[ch]; - if (window.opera && !e.altKey && e.keyCode != 13 && e.keyCode != 8) key_name = null; - ch = (e.which || e.charCode || e.keyCode); - if (e.which) ch = e.which; - if (!key_name) { key_name = String.fromCharCode(ch); } - if (e.ctrlKey) { key_name = 'Ctrl' + key_name; } - - // alert([e.keyCode, e.which, key_name, this['onKey' + key_name]]); - if (this.typing && this.onAnyKey) this.onAnyKey(key_name); - if (key_name && this['onKey' + key_name]) { - if (this.typing) this['onKey' + key_name](); - MouseApp.Manager.blockEvent(e); - if (this.typing && this.onAfterKey) this.onAfterKey(key_name, true); - return false; - } - if (!e.ctrlKey) { - if (MouseApp.isPrintable(ch)) { - if (this.typing) this.insertc(ch, 0); - MouseApp.Manager.blockEvent(e); - if (this.typing && this.onAfterKey) this.onAfterKey(key_name, true); - return false; - } - } - if (this.typing && this.onAfterKey) this.onAfterKey(key_name, false); - return true; - }, - onKeyHome: function() { - var s = this.getTypingStart(); - this.rpos = s[0]; this.cpos = s[1]; - }, - onKeyEnd: function() { - var e = this.getTypingEnd(+1); - this.rpos = e[0]; this.cpos = e[1]; - }, - onKeyInsert: function() { }, - onKeyDelete: function() { this.delc(); }, - onKeyUp: function() { this.backLine(); }, - onKeyLeft: function() { this.backc(); }, - onKeyRight: function() { this.fwdc(); }, - onKeyDown: function() { this.fwdLine(); }, - onKeyBackspace: function() { this.backspace(); }, - onKeyEnter: function() { this.insertc(10, 0); }, - onKeyTab: function() { - this.insertc(32, 0); - while (this.cpos % this.options.indent != 0) this.insertc(32, 0); - } -}); - -/* Terminal running moush */ -MouseApp.Terminal = function(element, options) { - this.element = $(element); - this.setOptions(options); - this.initWindow(); - this.setup(); -}; - -$.extend(MouseApp.Terminal.prototype, MouseApp.Window.prototype, { - setup: function() { - this.history = []; - this.backupNum = this.historyNum = this.commandNum = 0; - if (this.onStart) { - this.onStart(); - } else { - this.write(this.options.greeting + "\n", true); - this.prompt(); - } - }, - - prompt: function(ps, pt) { - if (!ps) { - ps = this.options.ps; pt = true; - } - this.write(ps, pt); - this.putc(1, 0); - this.typingOn(); - }, - - getCommand: function() { - var s = this.getTypingStart(); - var e = this.getTypingEnd(); - if (!s || !e) return; - return this.getTypingAt(s, e); - }, - - clearCommand: function() { - var s = this.getTypingStart(); - var e = this.getTypingEnd(); - if (!s || !e) return; - var r = s[0]; - var c = s[1]; - this.rpos = r; this.cpos = c; - while ( r < e[0] || c <= e[1] ) { - if ( c < this.options.columns ) { - this.screen[r][c] = [0, 0]; - c++; - } else { - c = 0; - this.paint(r); - r++; - } - } - this.paint(r); - }, - - write: function(str, pcodes) { - var p = this.painting; - var r = this.rpos; - this.painting = false; - var mode = 0; - var today = new Date(); - for ( var i = 0; i < str.length; i++ ) { - if ( str.substr(i,1) == "\n" ) { - this.advanceLine(); - continue; - } else if ( str.substr(i,1) == "\033" ) { - if ( str.substr(i+1,2) == "[m" ) { - mode = 0; - i += 2; - continue; - } - if ( str.substr(i+1,5) == "[0;0m" ) { - mode = 0; - i += 5; - continue; - } - var colors = str.substr(i+1,7).match(/^\[(\d);(\d+)m/); - if ( colors ) { - var colCode = parseInt( colors[2] ); - var color = colCode % 10; - if ( colors[1] == '1' ) { - color += 8; - } - if ( colCode / 10 == 4 ) { - color = color << 4; - } - mode = (mode & 15) + color << 4; - i += colors[0].length; - continue; - } - } else if ( str.substr(i,1) == '%' && pcodes ) { - var s2 = str.substr(i,2); - switch ( s2 ) { - case '%h': - this.puts(this.options.host, mode); - i++; - continue; - case '%l': - this.puts(this.options.name, mode); - i++; - continue; - case '%n': - this.advanceLine(); - i++; - continue; - case '%s': - this.puts("moush", mode); - i++; - continue; - case '%t': - this.puts(this.zpad(today.getHours()) + ":" + this.zpad(today.getMinutes()) + ":" + - this.zpad(today.getSeconds()), mode); - i++; - continue; - case '%u': - this.puts(this.options.user, mode); - i++; - continue; - case '%v': - this.puts(MouseApp.Version, mode); - i++; - continue; - case '%!': - this.puts(this.historyNum.toString(), mode); - i++; - continue; - case '%#': - this.puts(this.commandNum.toString(), mode); - i++; - continue; - case '%+': - var kind = str.substr(i+2, 1); - if ( MouseApp.ModeIds[kind] ) { - mode = mode | MouseApp.ModeIds[kind]; - i += 2; - continue; - } - break; - case '%-': - var kind = str.substr(i+2, 1); - if ( MouseApp.ModeIds[kind] ) { - mode = mode & ( 4095 - MouseApp.ModeIds[kind] ); - i += 2; - continue; - } - break; - } - } - this.putc(str.charCodeAt(i), mode); - } - this.painting = p; - this.paint(r, this.rpos); - }, - - onKeyUp: function() { - if ( this.backupNum == 0 ) return; - if ( this.backupNum == this.historyNum ) { - this.history[this.historyNum] = this.getCommand(); - } - this.clearCommand(); - this.backupNum--; - this.puts(this.history[this.backupNum]); - }, - onKeyDown: function() { - if ( this.backupNum >= this.historyNum ) return; - this.clearCommand(); - this.backupNum++; - this.puts(this.history[this.backupNum]); - }, - onKeyEnter: function() { - var cmd = this.getCommand(); - if (cmd) { - this.history[this.historyNum] = cmd; - this.backupNum = ++this.historyNum; - } - this.commandNum++; - this.advanceLine(); - if (cmd) { - var str = this.onCommand(cmd); - if (str) { - if ( str.substr(str.length - 1, 1) != "\n" ) { - str += "\n"; - } - this.write(str); - } - } - this.prompt(); - }, - onCommand: function(line) { - // this.puts("Echoing: " + line + "\n"); - if ( line == "clear" ) { - this.clear(); - } else { - return "\033[1;37m\033[0;44mYou typed:\033[m " + line; - } - } -}); - -/* Notepad sort of editor */ -MouseApp.Notepad = function(element, options) { - this.element = $(element); - this.setOptions(options); - this.initWindow(); - this.history = []; - this.lineno = 0; -}; - -$.extend(MouseApp.Notepad.prototype, MouseApp.Window.prototype, { - csave: function() { - if ( this.cpos_save ) { - this.cpos = this.cpos_save; - } else { - this.cpos_save = this.cpos; - } - }, - onKeyUp: function() { if ( this.rpos < 1 ) { return; } this.csave(); this.backLine(); }, - onKeyDown: function() { if ( this.rpos < this.screen.length - 1 ) { this.csave(); this.fwdLine(); } }, - onAfterKey: function(key, st) { - if ( st && !(key == 'Up' || key == 'Down') ) { - this.cpos_save = null; - } - }, - insertc: function(ch, mode) { - if (ch == 10) { - this.element.append("
             
            "); - this.screen.splice(this.rpos + 1, 0, this.fillRow(this.options.columns, 0)); - var c = this.cpos; var c2 = 0; - while (c < this.options.columns) - { - if (this.screen[this.rpos][c] == 0) break; - this.screen[this.rpos + 1][c2] = this.screen[this.rpos][c]; - this.screen[this.rpos][c] = [0, 0]; - c++; c2++; - } - this.paint(this.rpos); - if (MouseApp.isPrintable(this.screen[this.rpos][c])) - { - var r = this.rpos; var c = this.cpos; - this.rpos += 1; this.cpos = c2; - this.delc(); - this.rpos = r; this.cpos = c; - } - this.putc(ch, mode); - if (this.rpos == this.screen.length - 1) - this.scrollAllTheWayDown(); - } else { - var c = this.cpos + 1; - var lastc = this.screen[this.rpos][this.cpos]; - this.putc(ch, mode); - for ( var r = this.rpos; r < this.screen.length; r++ ) { - while (c < this.options.columns) - { - var tmpc = this.screen[r][c]; - if (lastc[0] == 0) - break; - this.screen[r][c] = lastc; - lastc = tmpc; - c++; - } - if (c < this.options.columns) { - break; - } - c = 0; - } - } - }, - - backc: function() { - var r = this.rpos; - var c = this.cpos - 1; - for ( var r = this.rpos; r >= 0; r-- ) { - while ( c >= 0 ) { - this.rpos = r; - this.cpos = c; - if ( this.screen[r][c][0] != 0 ) { - this.paint(r); - return true; - } - this.screen[r][c] = [0, 0]; - c--; - } - c = this.options.columns - 1; - } - return false; - }, - delc: function() { - var c = this.cpos + 1; - for ( var r = this.rpos; r < this.screen.length; r++ ) { - while ( c < this.options.columns ) { - if ( this.screen[r][c][0] != 0 ) { - break; - } - c++; - } - if ( c < this.options.columns ) break; - c = 0; - } - - if (r >= this.screen.length) return; - - var r2 = this.rpos; - var c2 = this.cpos; - for ( var r2 = this.rpos; r2 < this.screen.length; r2++ ) { - while (c2 < this.options.columns) - { - if (this.screen[r][c][0] == 0) - break; - this.screen[r2][c2] = this.screen[r][c]; - c2++; - c++; - if (c >= this.options.columns) { - r++; - if (r >= this.options.rows) break; - c = 0; - } - } - if (c2 < this.options.columns) { - while (c2 < this.options.columns) { - this.screen[r2][c2] = [0, 0]; - c2++; - } - break; - } - c2 = 0; - } - - if (r != r2 && r < this.screen.length) - { - this.screen.splice(r, 1); - $("#" + this.element.attr('id') + "_" + this.screen.length).remove(); - } - this.paint(this.rpos, this.screen.length); - }, - onKeyBackspace: function() { - if (this.backc()) this.delc(); - } - -}); diff --git a/tryruby/public/javascripts/mouseirb_2.js b/tryruby/public/javascripts/mouseirb_2.js deleted file mode 100755 index 0fa5f12..0000000 --- a/tryruby/public/javascripts/mouseirb_2.js +++ /dev/null @@ -1,179 +0,0 @@ -// -// Copyright (c) 2008 why the lucky stiff -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, -// and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT -// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -/* Irb running moush */ -MouseApp.Irb = function(element, options) { - this.element = $(element); - this.setOptions(options); - this.showHelp = this.options.showHelp; - if ( this.options.showChapter ) { - this.showChapter = this.options.showChapter; - } - if ( this.options.init ) { - this.init = this.options.init; - } - this.initWindow(); - this.setup(); - this.helpPage = null; - this.irbInit = false; -}; - -$.extend(MouseApp.Irb.prototype, MouseApp.Terminal.prototype, { - cmdToQuery: function(cmd) { - return "cmd=" + escape(cmd.replace(/</g, '<').replace(/>/g, '>'). - replace(/&/g, '&').replace(/\r?\n/g, "\n")).replace(/\+/g, "%2B"); - }, - - fireOffCmd: function(cmd, func) { - var irb = this; - if (!this.irbInit) - { - $.ajax({url: this.options.irbUrl + "?" + this.cmdToQuery("!INIT!IRB!"), type: "GET", - complete: (function(r) { irb.irbInit = true; irb.fireOffCmd(cmd, func); })}); - } - else - { - $.ajax({url: this.options.irbUrl + "?" + this.cmdToQuery(cmd), type: "GET", - complete: func}); - } - }, - - reply: function(str) { - var raw = str.replace(/\033\[(\d);(\d+)m/g, ''); - this.checkAnswer(raw); - if (!str.match(/^(\.\.)+$/)) { - if ( str[str.length - 1] != "\n" ) { - str += "\n"; - } - js_payload = /\033\[1;JSm(.*)\033\[m/; - js_in = str.match(js_payload); - if (js_in) { - try { - js_in = eval(js_in[1]); - } catch (e) {} - str = str.replace(js_payload, ''); - } - var pr_re = new RegExp("(^|\\n)=>"); - if ( str.match( pr_re ) ) { - str = str.replace(new RegExp("(^|\\n)=>"), "$1\033[1;34m=>\033[m"); - } else { - str = str.replace(new RegExp("(^|\\n)= (.+?) ="), "$1\033[1;33m$2\033[m"); - } - this.write(str); - this.prompt(); - } else { - this.prompt("\033[1;32m" + ".." + "\033[m", true); - this.puts(str.replace(/\./g, ' '), 0); - } - }, - - setHelpPage: function(n, page) { - if (this.helpPage) - $(this.helpPage.ele).hide('fast'); - this.helpPage = {index: n, ele: page}; - match = this.scanHelpPageFor('load'); - if (match != -1) - { - this.fireOffCmd(match, (function(r) { - $(page).show('fast'); - })); - } - else - { - $(page).show('fast'); - } - }, - - scanHelpPageFor: function(eleClass) { - match = $("div." + eleClass, this.helpPage.ele); - if ( match[0] ) return match[0].innerHTML; - else return -1; - }, - - checkAnswer: function(str) { - if ( this.helpPage ) { - match = this.scanHelpPageFor('answer'); - if ( match != -1 ) { - if ( str.match( new RegExp('^\s*=> ' + match + '\s*$', 'm') ) ) { - this.showHelp(this.helpPage.index + 1); - } - } else { - match = this.scanHelpPageFor('stdout'); - if ( match != -1 ) { - if ( match == '' ) { - if ( str == '' || str == null ) this.showHelp(this.helpPage.index + 1); - } else if ( str.match( new RegExp('^\s*' + match + '$', 'm') ) ) { - this.showHelp(this.helpPage.index + 1); - } - } - } - } - }, - - onKeyCtrld: function() { - this.clearCommand(); - this.puts("reset"); - this.onKeyEnter(); - }, - - onKeyEnter: function() { - this.typingOff(); - var cmd = this.getCommand(); - if (cmd) { - this.history[this.historyNum] = cmd; - this.backupNum = ++this.historyNum; - } - this.commandNum++; - this.advanceLine(); - if (cmd) { - if ( cmd == "clear" ) { - this.clear(); - this.prompt(); - } else if ( cmd.match(/^(back)$/) ) { - if (this.helpPage && this.helpPage.index >= 1) { - this.showHelp(this.helpPage.index - 1); - } - this.prompt(); - } else if ( cmd.match(/^(next)$/) ) { - if (this.helpPage) { - this.showHelp(this.helpPage.index + 1); - } - this.prompt(); - } else if ( cmd.match(/^(help|wtf\?*)$/) ) { - this.showHelp(1); - this.prompt(); - } else if ( regs = cmd.match(/^(help|wtf\?*)\s+#?(\d+)\s*$/) ) { - this.showChapter(parseInt(regs[2])); - this.prompt(); - } else { - var term = this; - this.fireOffCmd(cmd, (function(r) { term.reply(r.responseText ? r.responseText : ''); })); - } - } else { - this.prompt(); - } - } -}); - diff --git a/tryruby/public/javascripts/prototype.js b/tryruby/public/javascripts/prototype.js deleted file mode 100644 index dfe8ab4..0000000 --- a/tryruby/public/javascripts/prototype.js +++ /dev/null @@ -1,4320 +0,0 @@ -/* Prototype JavaScript framework, version 1.6.0.3 - * (c) 2005-2008 Sam Stephenson - * - * Prototype is freely distributable under the terms of an MIT-style license. - * For details, see the Prototype web site: http://www.prototypejs.org/ - * - *--------------------------------------------------------------------------*/ - -var Prototype = { - Version: '1.6.0.3', - - Browser: { - IE: !!(window.attachEvent && - navigator.userAgent.indexOf('Opera') === -1), - Opera: navigator.userAgent.indexOf('Opera') > -1, - WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, - Gecko: navigator.userAgent.indexOf('Gecko') > -1 && - navigator.userAgent.indexOf('KHTML') === -1, - MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/) - }, - - BrowserFeatures: { - XPath: !!document.evaluate, - SelectorsAPI: !!document.querySelector, - ElementExtensions: !!window.HTMLElement, - SpecificElementExtensions: - document.createElement('div')['__proto__'] && - document.createElement('div')['__proto__'] !== - document.createElement('form')['__proto__'] - }, - - ScriptFragment: ']*>([\\S\\s]*?)<\/script>', - JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, - - emptyFunction: function() { }, - K: function(x) { return x } -}; - -if (Prototype.Browser.MobileSafari) - Prototype.BrowserFeatures.SpecificElementExtensions = false; - - -/* Based on Alex Arnell's inheritance implementation. */ -var Class = { - create: function() { - var parent = null, properties = $A(arguments); - if (Object.isFunction(properties[0])) - parent = properties.shift(); - - function klass() { - this.initialize.apply(this, arguments); - } - - Object.extend(klass, Class.Methods); - klass.superclass = parent; - klass.subclasses = []; - - if (parent) { - var subclass = function() { }; - subclass.prototype = parent.prototype; - klass.prototype = new subclass; - parent.subclasses.push(klass); - } - - for (var i = 0; i < properties.length; i++) - klass.addMethods(properties[i]); - - if (!klass.prototype.initialize) - klass.prototype.initialize = Prototype.emptyFunction; - - klass.prototype.constructor = klass; - - return klass; - } -}; - -Class.Methods = { - addMethods: function(source) { - var ancestor = this.superclass && this.superclass.prototype; - var properties = Object.keys(source); - - if (!Object.keys({ toString: true }).length) - properties.push("toString", "valueOf"); - - for (var i = 0, length = properties.length; i < length; i++) { - var property = properties[i], value = source[property]; - if (ancestor && Object.isFunction(value) && - value.argumentNames().first() == "$super") { - var method = value; - value = (function(m) { - return function() { return ancestor[m].apply(this, arguments) }; - })(property).wrap(method); - - value.valueOf = method.valueOf.bind(method); - value.toString = method.toString.bind(method); - } - this.prototype[property] = value; - } - - return this; - } -}; - -var Abstract = { }; - -Object.extend = function(destination, source) { - for (var property in source) - destination[property] = source[property]; - return destination; -}; - -Object.extend(Object, { - inspect: function(object) { - try { - if (Object.isUndefined(object)) return 'undefined'; - if (object === null) return 'null'; - return object.inspect ? object.inspect() : String(object); - } catch (e) { - if (e instanceof RangeError) return '...'; - throw e; - } - }, - - toJSON: function(object) { - var type = typeof object; - switch (type) { - case 'undefined': - case 'function': - case 'unknown': return; - case 'boolean': return object.toString(); - } - - if (object === null) return 'null'; - if (object.toJSON) return object.toJSON(); - if (Object.isElement(object)) return; - - var results = []; - for (var property in object) { - var value = Object.toJSON(object[property]); - if (!Object.isUndefined(value)) - results.push(property.toJSON() + ': ' + value); - } - - return '{' + results.join(', ') + '}'; - }, - - toQueryString: function(object) { - return $H(object).toQueryString(); - }, - - toHTML: function(object) { - return object && object.toHTML ? object.toHTML() : String.interpret(object); - }, - - keys: function(object) { - var keys = []; - for (var property in object) - keys.push(property); - return keys; - }, - - values: function(object) { - var values = []; - for (var property in object) - values.push(object[property]); - return values; - }, - - clone: function(object) { - return Object.extend({ }, object); - }, - - isElement: function(object) { - return !!(object && object.nodeType == 1); - }, - - isArray: function(object) { - return object != null && typeof object == "object" && - 'splice' in object && 'join' in object; - }, - - isHash: function(object) { - return object instanceof Hash; - }, - - isFunction: function(object) { - return typeof object == "function"; - }, - - isString: function(object) { - return typeof object == "string"; - }, - - isNumber: function(object) { - return typeof object == "number"; - }, - - isUndefined: function(object) { - return typeof object == "undefined"; - } -}); - -Object.extend(Function.prototype, { - argumentNames: function() { - var names = this.toString().match(/^[\s\(]*function[^(]*\(([^\)]*)\)/)[1] - .replace(/\s+/g, '').split(','); - return names.length == 1 && !names[0] ? [] : names; - }, - - bind: function() { - if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; - var __method = this, args = $A(arguments), object = args.shift(); - return function() { - return __method.apply(object, args.concat($A(arguments))); - } - }, - - bindAsEventListener: function() { - var __method = this, args = $A(arguments), object = args.shift(); - return function(event) { - return __method.apply(object, [event || window.event].concat(args)); - } - }, - - curry: function() { - if (!arguments.length) return this; - var __method = this, args = $A(arguments); - return function() { - return __method.apply(this, args.concat($A(arguments))); - } - }, - - delay: function() { - var __method = this, args = $A(arguments), timeout = args.shift() * 1000; - return window.setTimeout(function() { - return __method.apply(__method, args); - }, timeout); - }, - - defer: function() { - var args = [0.01].concat($A(arguments)); - return this.delay.apply(this, args); - }, - - wrap: function(wrapper) { - var __method = this; - return function() { - return wrapper.apply(this, [__method.bind(this)].concat($A(arguments))); - } - }, - - methodize: function() { - if (this._methodized) return this._methodized; - var __method = this; - return this._methodized = function() { - return __method.apply(null, [this].concat($A(arguments))); - }; - } -}); - -Date.prototype.toJSON = function() { - return '"' + this.getUTCFullYear() + '-' + - (this.getUTCMonth() + 1).toPaddedString(2) + '-' + - this.getUTCDate().toPaddedString(2) + 'T' + - this.getUTCHours().toPaddedString(2) + ':' + - this.getUTCMinutes().toPaddedString(2) + ':' + - this.getUTCSeconds().toPaddedString(2) + 'Z"'; -}; - -var Try = { - these: function() { - var returnValue; - - for (var i = 0, length = arguments.length; i < length; i++) { - var lambda = arguments[i]; - try { - returnValue = lambda(); - break; - } catch (e) { } - } - - return returnValue; - } -}; - -RegExp.prototype.match = RegExp.prototype.test; - -RegExp.escape = function(str) { - return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); -}; - -/*--------------------------------------------------------------------------*/ - -var PeriodicalExecuter = Class.create({ - initialize: function(callback, frequency) { - this.callback = callback; - this.frequency = frequency; - this.currentlyExecuting = false; - - this.registerCallback(); - }, - - registerCallback: function() { - this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); - }, - - execute: function() { - this.callback(this); - }, - - stop: function() { - if (!this.timer) return; - clearInterval(this.timer); - this.timer = null; - }, - - onTimerEvent: function() { - if (!this.currentlyExecuting) { - try { - this.currentlyExecuting = true; - this.execute(); - } finally { - this.currentlyExecuting = false; - } - } - } -}); -Object.extend(String, { - interpret: function(value) { - return value == null ? '' : String(value); - }, - specialChar: { - '\b': '\\b', - '\t': '\\t', - '\n': '\\n', - '\f': '\\f', - '\r': '\\r', - '\\': '\\\\' - } -}); - -Object.extend(String.prototype, { - gsub: function(pattern, replacement) { - var result = '', source = this, match; - replacement = arguments.callee.prepareReplacement(replacement); - - while (source.length > 0) { - if (match = source.match(pattern)) { - result += source.slice(0, match.index); - result += String.interpret(replacement(match)); - source = source.slice(match.index + match[0].length); - } else { - result += source, source = ''; - } - } - return result; - }, - - sub: function(pattern, replacement, count) { - replacement = this.gsub.prepareReplacement(replacement); - count = Object.isUndefined(count) ? 1 : count; - - return this.gsub(pattern, function(match) { - if (--count < 0) return match[0]; - return replacement(match); - }); - }, - - scan: function(pattern, iterator) { - this.gsub(pattern, iterator); - return String(this); - }, - - truncate: function(length, truncation) { - length = length || 30; - truncation = Object.isUndefined(truncation) ? '...' : truncation; - return this.length > length ? - this.slice(0, length - truncation.length) + truncation : String(this); - }, - - strip: function() { - return this.replace(/^\s+/, '').replace(/\s+$/, ''); - }, - - stripTags: function() { - return this.replace(/<\/?[^>]+>/gi, ''); - }, - - stripScripts: function() { - return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); - }, - - extractScripts: function() { - var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); - var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); - return (this.match(matchAll) || []).map(function(scriptTag) { - return (scriptTag.match(matchOne) || ['', ''])[1]; - }); - }, - - evalScripts: function() { - return this.extractScripts().map(function(script) { return eval(script) }); - }, - - escapeHTML: function() { - var self = arguments.callee; - self.text.data = this; - return self.div.innerHTML; - }, - - unescapeHTML: function() { - var div = new Element('div'); - div.innerHTML = this.stripTags(); - return div.childNodes[0] ? (div.childNodes.length > 1 ? - $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : - div.childNodes[0].nodeValue) : ''; - }, - - toQueryParams: function(separator) { - var match = this.strip().match(/([^?#]*)(#.*)?$/); - if (!match) return { }; - - return match[1].split(separator || '&').inject({ }, function(hash, pair) { - if ((pair = pair.split('='))[0]) { - var key = decodeURIComponent(pair.shift()); - var value = pair.length > 1 ? pair.join('=') : pair[0]; - if (value != undefined) value = decodeURIComponent(value); - - if (key in hash) { - if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; - hash[key].push(value); - } - else hash[key] = value; - } - return hash; - }); - }, - - toArray: function() { - return this.split(''); - }, - - succ: function() { - return this.slice(0, this.length - 1) + - String.fromCharCode(this.charCodeAt(this.length - 1) + 1); - }, - - times: function(count) { - return count < 1 ? '' : new Array(count + 1).join(this); - }, - - camelize: function() { - var parts = this.split('-'), len = parts.length; - if (len == 1) return parts[0]; - - var camelized = this.charAt(0) == '-' - ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) - : parts[0]; - - for (var i = 1; i < len; i++) - camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); - - return camelized; - }, - - capitalize: function() { - return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); - }, - - underscore: function() { - return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); - }, - - dasherize: function() { - return this.gsub(/_/,'-'); - }, - - inspect: function(useDoubleQuotes) { - var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { - var character = String.specialChar[match[0]]; - return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); - }); - if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; - return "'" + escapedString.replace(/'/g, '\\\'') + "'"; - }, - - toJSON: function() { - return this.inspect(true); - }, - - unfilterJSON: function(filter) { - return this.sub(filter || Prototype.JSONFilter, '#{1}'); - }, - - isJSON: function() { - var str = this; - if (str.blank()) return false; - str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); - return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); - }, - - evalJSON: function(sanitize) { - var json = this.unfilterJSON(); - try { - if (!sanitize || json.isJSON()) return eval('(' + json + ')'); - } catch (e) { } - throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); - }, - - include: function(pattern) { - return this.indexOf(pattern) > -1; - }, - - startsWith: function(pattern) { - return this.indexOf(pattern) === 0; - }, - - endsWith: function(pattern) { - var d = this.length - pattern.length; - return d >= 0 && this.lastIndexOf(pattern) === d; - }, - - empty: function() { - return this == ''; - }, - - blank: function() { - return /^\s*$/.test(this); - }, - - interpolate: function(object, pattern) { - return new Template(this, pattern).evaluate(object); - } -}); - -if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { - escapeHTML: function() { - return this.replace(/&/g,'&').replace(//g,'>'); - }, - unescapeHTML: function() { - return this.stripTags().replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); - } -}); - -String.prototype.gsub.prepareReplacement = function(replacement) { - if (Object.isFunction(replacement)) return replacement; - var template = new Template(replacement); - return function(match) { return template.evaluate(match) }; -}; - -String.prototype.parseQuery = String.prototype.toQueryParams; - -Object.extend(String.prototype.escapeHTML, { - div: document.createElement('div'), - text: document.createTextNode('') -}); - -String.prototype.escapeHTML.div.appendChild(String.prototype.escapeHTML.text); - -var Template = Class.create({ - initialize: function(template, pattern) { - this.template = template.toString(); - this.pattern = pattern || Template.Pattern; - }, - - evaluate: function(object) { - if (Object.isFunction(object.toTemplateReplacements)) - object = object.toTemplateReplacements(); - - return this.template.gsub(this.pattern, function(match) { - if (object == null) return ''; - - var before = match[1] || ''; - if (before == '\\') return match[2]; - - var ctx = object, expr = match[3]; - var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; - match = pattern.exec(expr); - if (match == null) return before; - - while (match != null) { - var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1]; - ctx = ctx[comp]; - if (null == ctx || '' == match[3]) break; - expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); - match = pattern.exec(expr); - } - - return before + String.interpret(ctx); - }); - } -}); -Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; - -var $break = { }; - -var Enumerable = { - each: function(iterator, context) { - var index = 0; - try { - this._each(function(value) { - iterator.call(context, value, index++); - }); - } catch (e) { - if (e != $break) throw e; - } - return this; - }, - - eachSlice: function(number, iterator, context) { - var index = -number, slices = [], array = this.toArray(); - if (number < 1) return array; - while ((index += number) < array.length) - slices.push(array.slice(index, index+number)); - return slices.collect(iterator, context); - }, - - all: function(iterator, context) { - iterator = iterator || Prototype.K; - var result = true; - this.each(function(value, index) { - result = result && !!iterator.call(context, value, index); - if (!result) throw $break; - }); - return result; - }, - - any: function(iterator, context) { - iterator = iterator || Prototype.K; - var result = false; - this.each(function(value, index) { - if (result = !!iterator.call(context, value, index)) - throw $break; - }); - return result; - }, - - collect: function(iterator, context) { - iterator = iterator || Prototype.K; - var results = []; - this.each(function(value, index) { - results.push(iterator.call(context, value, index)); - }); - return results; - }, - - detect: function(iterator, context) { - var result; - this.each(function(value, index) { - if (iterator.call(context, value, index)) { - result = value; - throw $break; - } - }); - return result; - }, - - findAll: function(iterator, context) { - var results = []; - this.each(function(value, index) { - if (iterator.call(context, value, index)) - results.push(value); - }); - return results; - }, - - grep: function(filter, iterator, context) { - iterator = iterator || Prototype.K; - var results = []; - - if (Object.isString(filter)) - filter = new RegExp(filter); - - this.each(function(value, index) { - if (filter.match(value)) - results.push(iterator.call(context, value, index)); - }); - return results; - }, - - include: function(object) { - if (Object.isFunction(this.indexOf)) - if (this.indexOf(object) != -1) return true; - - var found = false; - this.each(function(value) { - if (value == object) { - found = true; - throw $break; - } - }); - return found; - }, - - inGroupsOf: function(number, fillWith) { - fillWith = Object.isUndefined(fillWith) ? null : fillWith; - return this.eachSlice(number, function(slice) { - while(slice.length < number) slice.push(fillWith); - return slice; - }); - }, - - inject: function(memo, iterator, context) { - this.each(function(value, index) { - memo = iterator.call(context, memo, value, index); - }); - return memo; - }, - - invoke: function(method) { - var args = $A(arguments).slice(1); - return this.map(function(value) { - return value[method].apply(value, args); - }); - }, - - max: function(iterator, context) { - iterator = iterator || Prototype.K; - var result; - this.each(function(value, index) { - value = iterator.call(context, value, index); - if (result == null || value >= result) - result = value; - }); - return result; - }, - - min: function(iterator, context) { - iterator = iterator || Prototype.K; - var result; - this.each(function(value, index) { - value = iterator.call(context, value, index); - if (result == null || value < result) - result = value; - }); - return result; - }, - - partition: function(iterator, context) { - iterator = iterator || Prototype.K; - var trues = [], falses = []; - this.each(function(value, index) { - (iterator.call(context, value, index) ? - trues : falses).push(value); - }); - return [trues, falses]; - }, - - pluck: function(property) { - var results = []; - this.each(function(value) { - results.push(value[property]); - }); - return results; - }, - - reject: function(iterator, context) { - var results = []; - this.each(function(value, index) { - if (!iterator.call(context, value, index)) - results.push(value); - }); - return results; - }, - - sortBy: function(iterator, context) { - return this.map(function(value, index) { - return { - value: value, - criteria: iterator.call(context, value, index) - }; - }).sort(function(left, right) { - var a = left.criteria, b = right.criteria; - return a < b ? -1 : a > b ? 1 : 0; - }).pluck('value'); - }, - - toArray: function() { - return this.map(); - }, - - zip: function() { - var iterator = Prototype.K, args = $A(arguments); - if (Object.isFunction(args.last())) - iterator = args.pop(); - - var collections = [this].concat(args).map($A); - return this.map(function(value, index) { - return iterator(collections.pluck(index)); - }); - }, - - size: function() { - return this.toArray().length; - }, - - inspect: function() { - return '#'; - } -}; - -Object.extend(Enumerable, { - map: Enumerable.collect, - find: Enumerable.detect, - select: Enumerable.findAll, - filter: Enumerable.findAll, - member: Enumerable.include, - entries: Enumerable.toArray, - every: Enumerable.all, - some: Enumerable.any -}); -function $A(iterable) { - if (!iterable) return []; - if (iterable.toArray) return iterable.toArray(); - var length = iterable.length || 0, results = new Array(length); - while (length--) results[length] = iterable[length]; - return results; -} - -if (Prototype.Browser.WebKit) { - $A = function(iterable) { - if (!iterable) return []; - // In Safari, only use the `toArray` method if it's not a NodeList. - // A NodeList is a function, has an function `item` property, and a numeric - // `length` property. Adapted from Google Doctype. - if (!(typeof iterable === 'function' && typeof iterable.length === - 'number' && typeof iterable.item === 'function') && iterable.toArray) - return iterable.toArray(); - var length = iterable.length || 0, results = new Array(length); - while (length--) results[length] = iterable[length]; - return results; - }; -} - -Array.from = $A; - -Object.extend(Array.prototype, Enumerable); - -if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse; - -Object.extend(Array.prototype, { - _each: function(iterator) { - for (var i = 0, length = this.length; i < length; i++) - iterator(this[i]); - }, - - clear: function() { - this.length = 0; - return this; - }, - - first: function() { - return this[0]; - }, - - last: function() { - return this[this.length - 1]; - }, - - compact: function() { - return this.select(function(value) { - return value != null; - }); - }, - - flatten: function() { - return this.inject([], function(array, value) { - return array.concat(Object.isArray(value) ? - value.flatten() : [value]); - }); - }, - - without: function() { - var values = $A(arguments); - return this.select(function(value) { - return !values.include(value); - }); - }, - - reverse: function(inline) { - return (inline !== false ? this : this.toArray())._reverse(); - }, - - reduce: function() { - return this.length > 1 ? this : this[0]; - }, - - uniq: function(sorted) { - return this.inject([], function(array, value, index) { - if (0 == index || (sorted ? array.last() != value : !array.include(value))) - array.push(value); - return array; - }); - }, - - intersect: function(array) { - return this.uniq().findAll(function(item) { - return array.detect(function(value) { return item === value }); - }); - }, - - clone: function() { - return [].concat(this); - }, - - size: function() { - return this.length; - }, - - inspect: function() { - return '[' + this.map(Object.inspect).join(', ') + ']'; - }, - - toJSON: function() { - var results = []; - this.each(function(object) { - var value = Object.toJSON(object); - if (!Object.isUndefined(value)) results.push(value); - }); - return '[' + results.join(', ') + ']'; - } -}); - -// use native browser JS 1.6 implementation if available -if (Object.isFunction(Array.prototype.forEach)) - Array.prototype._each = Array.prototype.forEach; - -if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) { - i || (i = 0); - var length = this.length; - if (i < 0) i = length + i; - for (; i < length; i++) - if (this[i] === item) return i; - return -1; -}; - -if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) { - i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; - var n = this.slice(0, i).reverse().indexOf(item); - return (n < 0) ? n : i - n - 1; -}; - -Array.prototype.toArray = Array.prototype.clone; - -function $w(string) { - if (!Object.isString(string)) return []; - string = string.strip(); - return string ? string.split(/\s+/) : []; -} - -if (Prototype.Browser.Opera){ - Array.prototype.concat = function() { - var array = []; - for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); - for (var i = 0, length = arguments.length; i < length; i++) { - if (Object.isArray(arguments[i])) { - for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) - array.push(arguments[i][j]); - } else { - array.push(arguments[i]); - } - } - return array; - }; -} -Object.extend(Number.prototype, { - toColorPart: function() { - return this.toPaddedString(2, 16); - }, - - succ: function() { - return this + 1; - }, - - times: function(iterator, context) { - $R(0, this, true).each(iterator, context); - return this; - }, - - toPaddedString: function(length, radix) { - var string = this.toString(radix || 10); - return '0'.times(length - string.length) + string; - }, - - toJSON: function() { - return isFinite(this) ? this.toString() : 'null'; - } -}); - -$w('abs round ceil floor').each(function(method){ - Number.prototype[method] = Math[method].methodize(); -}); -function $H(object) { - return new Hash(object); -}; - -var Hash = Class.create(Enumerable, (function() { - - function toQueryPair(key, value) { - if (Object.isUndefined(value)) return key; - return key + '=' + encodeURIComponent(String.interpret(value)); - } - - return { - initialize: function(object) { - this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); - }, - - _each: function(iterator) { - for (var key in this._object) { - var value = this._object[key], pair = [key, value]; - pair.key = key; - pair.value = value; - iterator(pair); - } - }, - - set: function(key, value) { - return this._object[key] = value; - }, - - get: function(key) { - // simulating poorly supported hasOwnProperty - if (this._object[key] !== Object.prototype[key]) - return this._object[key]; - }, - - unset: function(key) { - var value = this._object[key]; - delete this._object[key]; - return value; - }, - - toObject: function() { - return Object.clone(this._object); - }, - - keys: function() { - return this.pluck('key'); - }, - - values: function() { - return this.pluck('value'); - }, - - index: function(value) { - var match = this.detect(function(pair) { - return pair.value === value; - }); - return match && match.key; - }, - - merge: function(object) { - return this.clone().update(object); - }, - - update: function(object) { - return new Hash(object).inject(this, function(result, pair) { - result.set(pair.key, pair.value); - return result; - }); - }, - - toQueryString: function() { - return this.inject([], function(results, pair) { - var key = encodeURIComponent(pair.key), values = pair.value; - - if (values && typeof values == 'object') { - if (Object.isArray(values)) - return results.concat(values.map(toQueryPair.curry(key))); - } else results.push(toQueryPair(key, values)); - return results; - }).join('&'); - }, - - inspect: function() { - return '#'; - }, - - toJSON: function() { - return Object.toJSON(this.toObject()); - }, - - clone: function() { - return new Hash(this); - } - } -})()); - -Hash.prototype.toTemplateReplacements = Hash.prototype.toObject; -Hash.from = $H; -var ObjectRange = Class.create(Enumerable, { - initialize: function(start, end, exclusive) { - this.start = start; - this.end = end; - this.exclusive = exclusive; - }, - - _each: function(iterator) { - var value = this.start; - while (this.include(value)) { - iterator(value); - value = value.succ(); - } - }, - - include: function(value) { - if (value < this.start) - return false; - if (this.exclusive) - return value < this.end; - return value <= this.end; - } -}); - -var $R = function(start, end, exclusive) { - return new ObjectRange(start, end, exclusive); -}; - -var Ajax = { - getTransport: function() { - return Try.these( - function() {return new XMLHttpRequest()}, - function() {return new ActiveXObject('Msxml2.XMLHTTP')}, - function() {return new ActiveXObject('Microsoft.XMLHTTP')} - ) || false; - }, - - activeRequestCount: 0 -}; - -Ajax.Responders = { - responders: [], - - _each: function(iterator) { - this.responders._each(iterator); - }, - - register: function(responder) { - if (!this.include(responder)) - this.responders.push(responder); - }, - - unregister: function(responder) { - this.responders = this.responders.without(responder); - }, - - dispatch: function(callback, request, transport, json) { - this.each(function(responder) { - if (Object.isFunction(responder[callback])) { - try { - responder[callback].apply(responder, [request, transport, json]); - } catch (e) { } - } - }); - } -}; - -Object.extend(Ajax.Responders, Enumerable); - -Ajax.Responders.register({ - onCreate: function() { Ajax.activeRequestCount++ }, - onComplete: function() { Ajax.activeRequestCount-- } -}); - -Ajax.Base = Class.create({ - initialize: function(options) { - this.options = { - method: 'post', - asynchronous: true, - contentType: 'application/x-www-form-urlencoded', - encoding: 'UTF-8', - parameters: '', - evalJSON: true, - evalJS: true - }; - Object.extend(this.options, options || { }); - - this.options.method = this.options.method.toLowerCase(); - - if (Object.isString(this.options.parameters)) - this.options.parameters = this.options.parameters.toQueryParams(); - else if (Object.isHash(this.options.parameters)) - this.options.parameters = this.options.parameters.toObject(); - } -}); - -Ajax.Request = Class.create(Ajax.Base, { - _complete: false, - - initialize: function($super, url, options) { - $super(options); - this.transport = Ajax.getTransport(); - this.request(url); - }, - - request: function(url) { - this.url = url; - this.method = this.options.method; - var params = Object.clone(this.options.parameters); - - if (!['get', 'post'].include(this.method)) { - // simulate other verbs over post - params['_method'] = this.method; - this.method = 'post'; - } - - this.parameters = params; - - if (params = Object.toQueryString(params)) { - // when GET, append parameters to URL - if (this.method == 'get') - this.url += (this.url.include('?') ? '&' : '?') + params; - else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) - params += '&_='; - } - - try { - var response = new Ajax.Response(this); - if (this.options.onCreate) this.options.onCreate(response); - Ajax.Responders.dispatch('onCreate', this, response); - - this.transport.open(this.method.toUpperCase(), this.url, - this.options.asynchronous); - - if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); - - this.transport.onreadystatechange = this.onStateChange.bind(this); - this.setRequestHeaders(); - - this.body = this.method == 'post' ? (this.options.postBody || params) : null; - this.transport.send(this.body); - - /* Force Firefox to handle ready state 4 for synchronous requests */ - if (!this.options.asynchronous && this.transport.overrideMimeType) - this.onStateChange(); - - } - catch (e) { - this.dispatchException(e); - } - }, - - onStateChange: function() { - var readyState = this.transport.readyState; - if (readyState > 1 && !((readyState == 4) && this._complete)) - this.respondToReadyState(this.transport.readyState); - }, - - setRequestHeaders: function() { - var headers = { - 'X-Requested-With': 'XMLHttpRequest', - 'X-Prototype-Version': Prototype.Version, - 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' - }; - - if (this.method == 'post') { - headers['Content-type'] = this.options.contentType + - (this.options.encoding ? '; charset=' + this.options.encoding : ''); - - /* Force "Connection: close" for older Mozilla browsers to work - * around a bug where XMLHttpRequest sends an incorrect - * Content-length header. See Mozilla Bugzilla #246651. - */ - if (this.transport.overrideMimeType && - (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) - headers['Connection'] = 'close'; - } - - // user-defined headers - if (typeof this.options.requestHeaders == 'object') { - var extras = this.options.requestHeaders; - - if (Object.isFunction(extras.push)) - for (var i = 0, length = extras.length; i < length; i += 2) - headers[extras[i]] = extras[i+1]; - else - $H(extras).each(function(pair) { headers[pair.key] = pair.value }); - } - - for (var name in headers) - this.transport.setRequestHeader(name, headers[name]); - }, - - success: function() { - var status = this.getStatus(); - return !status || (status >= 200 && status < 300); - }, - - getStatus: function() { - try { - return this.transport.status || 0; - } catch (e) { return 0 } - }, - - respondToReadyState: function(readyState) { - var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); - - if (state == 'Complete') { - try { - this._complete = true; - (this.options['on' + response.status] - || this.options['on' + (this.success() ? 'Success' : 'Failure')] - || Prototype.emptyFunction)(response, response.headerJSON); - } catch (e) { - this.dispatchException(e); - } - - var contentType = response.getHeader('Content-type'); - if (this.options.evalJS == 'force' - || (this.options.evalJS && this.isSameOrigin() && contentType - && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) - this.evalResponse(); - } - - try { - (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); - Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); - } catch (e) { - this.dispatchException(e); - } - - if (state == 'Complete') { - // avoid memory leak in MSIE: clean up - this.transport.onreadystatechange = Prototype.emptyFunction; - } - }, - - isSameOrigin: function() { - var m = this.url.match(/^\s*https?:\/\/[^\/]*/); - return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({ - protocol: location.protocol, - domain: document.domain, - port: location.port ? ':' + location.port : '' - })); - }, - - getHeader: function(name) { - try { - return this.transport.getResponseHeader(name) || null; - } catch (e) { return null } - }, - - evalResponse: function() { - try { - return eval((this.transport.responseText || '').unfilterJSON()); - } catch (e) { - this.dispatchException(e); - } - }, - - dispatchException: function(exception) { - (this.options.onException || Prototype.emptyFunction)(this, exception); - Ajax.Responders.dispatch('onException', this, exception); - } -}); - -Ajax.Request.Events = - ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; - -Ajax.Response = Class.create({ - initialize: function(request){ - this.request = request; - var transport = this.transport = request.transport, - readyState = this.readyState = transport.readyState; - - if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { - this.status = this.getStatus(); - this.statusText = this.getStatusText(); - this.responseText = String.interpret(transport.responseText); - this.headerJSON = this._getHeaderJSON(); - } - - if(readyState == 4) { - var xml = transport.responseXML; - this.responseXML = Object.isUndefined(xml) ? null : xml; - this.responseJSON = this._getResponseJSON(); - } - }, - - status: 0, - statusText: '', - - getStatus: Ajax.Request.prototype.getStatus, - - getStatusText: function() { - try { - return this.transport.statusText || ''; - } catch (e) { return '' } - }, - - getHeader: Ajax.Request.prototype.getHeader, - - getAllHeaders: function() { - try { - return this.getAllResponseHeaders(); - } catch (e) { return null } - }, - - getResponseHeader: function(name) { - return this.transport.getResponseHeader(name); - }, - - getAllResponseHeaders: function() { - return this.transport.getAllResponseHeaders(); - }, - - _getHeaderJSON: function() { - var json = this.getHeader('X-JSON'); - if (!json) return null; - json = decodeURIComponent(escape(json)); - try { - return json.evalJSON(this.request.options.sanitizeJSON || - !this.request.isSameOrigin()); - } catch (e) { - this.request.dispatchException(e); - } - }, - - _getResponseJSON: function() { - var options = this.request.options; - if (!options.evalJSON || (options.evalJSON != 'force' && - !(this.getHeader('Content-type') || '').include('application/json')) || - this.responseText.blank()) - return null; - try { - return this.responseText.evalJSON(options.sanitizeJSON || - !this.request.isSameOrigin()); - } catch (e) { - this.request.dispatchException(e); - } - } -}); - -Ajax.Updater = Class.create(Ajax.Request, { - initialize: function($super, container, url, options) { - this.container = { - success: (container.success || container), - failure: (container.failure || (container.success ? null : container)) - }; - - options = Object.clone(options); - var onComplete = options.onComplete; - options.onComplete = (function(response, json) { - this.updateContent(response.responseText); - if (Object.isFunction(onComplete)) onComplete(response, json); - }).bind(this); - - $super(url, options); - }, - - updateContent: function(responseText) { - var receiver = this.container[this.success() ? 'success' : 'failure'], - options = this.options; - - if (!options.evalScripts) responseText = responseText.stripScripts(); - - if (receiver = $(receiver)) { - if (options.insertion) { - if (Object.isString(options.insertion)) { - var insertion = { }; insertion[options.insertion] = responseText; - receiver.insert(insertion); - } - else options.insertion(receiver, responseText); - } - else receiver.update(responseText); - } - } -}); - -Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { - initialize: function($super, container, url, options) { - $super(options); - this.onComplete = this.options.onComplete; - - this.frequency = (this.options.frequency || 2); - this.decay = (this.options.decay || 1); - - this.updater = { }; - this.container = container; - this.url = url; - - this.start(); - }, - - start: function() { - this.options.onComplete = this.updateComplete.bind(this); - this.onTimerEvent(); - }, - - stop: function() { - this.updater.options.onComplete = undefined; - clearTimeout(this.timer); - (this.onComplete || Prototype.emptyFunction).apply(this, arguments); - }, - - updateComplete: function(response) { - if (this.options.decay) { - this.decay = (response.responseText == this.lastText ? - this.decay * this.options.decay : 1); - - this.lastText = response.responseText; - } - this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); - }, - - onTimerEvent: function() { - this.updater = new Ajax.Updater(this.container, this.url, this.options); - } -}); -function $(element) { - if (arguments.length > 1) { - for (var i = 0, elements = [], length = arguments.length; i < length; i++) - elements.push($(arguments[i])); - return elements; - } - if (Object.isString(element)) - element = document.getElementById(element); - return Element.extend(element); -} - -if (Prototype.BrowserFeatures.XPath) { - document._getElementsByXPath = function(expression, parentElement) { - var results = []; - var query = document.evaluate(expression, $(parentElement) || document, - null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); - for (var i = 0, length = query.snapshotLength; i < length; i++) - results.push(Element.extend(query.snapshotItem(i))); - return results; - }; -} - -/*--------------------------------------------------------------------------*/ - -if (!window.Node) var Node = { }; - -if (!Node.ELEMENT_NODE) { - // DOM level 2 ECMAScript Language Binding - Object.extend(Node, { - ELEMENT_NODE: 1, - ATTRIBUTE_NODE: 2, - TEXT_NODE: 3, - CDATA_SECTION_NODE: 4, - ENTITY_REFERENCE_NODE: 5, - ENTITY_NODE: 6, - PROCESSING_INSTRUCTION_NODE: 7, - COMMENT_NODE: 8, - DOCUMENT_NODE: 9, - DOCUMENT_TYPE_NODE: 10, - DOCUMENT_FRAGMENT_NODE: 11, - NOTATION_NODE: 12 - }); -} - -(function() { - var element = this.Element; - this.Element = function(tagName, attributes) { - attributes = attributes || { }; - tagName = tagName.toLowerCase(); - var cache = Element.cache; - if (Prototype.Browser.IE && attributes.name) { - tagName = '<' + tagName + ' name="' + attributes.name + '">'; - delete attributes.name; - return Element.writeAttribute(document.createElement(tagName), attributes); - } - if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); - return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); - }; - Object.extend(this.Element, element || { }); - if (element) this.Element.prototype = element.prototype; -}).call(window); - -Element.cache = { }; - -Element.Methods = { - visible: function(element) { - return $(element).style.display != 'none'; - }, - - toggle: function(element) { - element = $(element); - Element[Element.visible(element) ? 'hide' : 'show'](element); - return element; - }, - - hide: function(element) { - element = $(element); - element.style.display = 'none'; - return element; - }, - - show: function(element) { - element = $(element); - element.style.display = ''; - return element; - }, - - remove: function(element) { - element = $(element); - element.parentNode.removeChild(element); - return element; - }, - - update: function(element, content) { - element = $(element); - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) return element.update().insert(content); - content = Object.toHTML(content); - element.innerHTML = content.stripScripts(); - content.evalScripts.bind(content).defer(); - return element; - }, - - replace: function(element, content) { - element = $(element); - if (content && content.toElement) content = content.toElement(); - else if (!Object.isElement(content)) { - content = Object.toHTML(content); - var range = element.ownerDocument.createRange(); - range.selectNode(element); - content.evalScripts.bind(content).defer(); - content = range.createContextualFragment(content.stripScripts()); - } - element.parentNode.replaceChild(content, element); - return element; - }, - - insert: function(element, insertions) { - element = $(element); - - if (Object.isString(insertions) || Object.isNumber(insertions) || - Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) - insertions = {bottom:insertions}; - - var content, insert, tagName, childNodes; - - for (var position in insertions) { - content = insertions[position]; - position = position.toLowerCase(); - insert = Element._insertionTranslations[position]; - - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) { - insert(element, content); - continue; - } - - content = Object.toHTML(content); - - tagName = ((position == 'before' || position == 'after') - ? element.parentNode : element).tagName.toUpperCase(); - - childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); - - if (position == 'top' || position == 'after') childNodes.reverse(); - childNodes.each(insert.curry(element)); - - content.evalScripts.bind(content).defer(); - } - - return element; - }, - - wrap: function(element, wrapper, attributes) { - element = $(element); - if (Object.isElement(wrapper)) - $(wrapper).writeAttribute(attributes || { }); - else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); - else wrapper = new Element('div', wrapper); - if (element.parentNode) - element.parentNode.replaceChild(wrapper, element); - wrapper.appendChild(element); - return wrapper; - }, - - inspect: function(element) { - element = $(element); - var result = '<' + element.tagName.toLowerCase(); - $H({'id': 'id', 'className': 'class'}).each(function(pair) { - var property = pair.first(), attribute = pair.last(); - var value = (element[property] || '').toString(); - if (value) result += ' ' + attribute + '=' + value.inspect(true); - }); - return result + '>'; - }, - - recursivelyCollect: function(element, property) { - element = $(element); - var elements = []; - while (element = element[property]) - if (element.nodeType == 1) - elements.push(Element.extend(element)); - return elements; - }, - - ancestors: function(element) { - return $(element).recursivelyCollect('parentNode'); - }, - - descendants: function(element) { - return $(element).select("*"); - }, - - firstDescendant: function(element) { - element = $(element).firstChild; - while (element && element.nodeType != 1) element = element.nextSibling; - return $(element); - }, - - immediateDescendants: function(element) { - if (!(element = $(element).firstChild)) return []; - while (element && element.nodeType != 1) element = element.nextSibling; - if (element) return [element].concat($(element).nextSiblings()); - return []; - }, - - previousSiblings: function(element) { - return $(element).recursivelyCollect('previousSibling'); - }, - - nextSiblings: function(element) { - return $(element).recursivelyCollect('nextSibling'); - }, - - siblings: function(element) { - element = $(element); - return element.previousSiblings().reverse().concat(element.nextSiblings()); - }, - - match: function(element, selector) { - if (Object.isString(selector)) - selector = new Selector(selector); - return selector.match($(element)); - }, - - up: function(element, expression, index) { - element = $(element); - if (arguments.length == 1) return $(element.parentNode); - var ancestors = element.ancestors(); - return Object.isNumber(expression) ? ancestors[expression] : - Selector.findElement(ancestors, expression, index); - }, - - down: function(element, expression, index) { - element = $(element); - if (arguments.length == 1) return element.firstDescendant(); - return Object.isNumber(expression) ? element.descendants()[expression] : - Element.select(element, expression)[index || 0]; - }, - - previous: function(element, expression, index) { - element = $(element); - if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); - var previousSiblings = element.previousSiblings(); - return Object.isNumber(expression) ? previousSiblings[expression] : - Selector.findElement(previousSiblings, expression, index); - }, - - next: function(element, expression, index) { - element = $(element); - if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); - var nextSiblings = element.nextSiblings(); - return Object.isNumber(expression) ? nextSiblings[expression] : - Selector.findElement(nextSiblings, expression, index); - }, - - select: function() { - var args = $A(arguments), element = $(args.shift()); - return Selector.findChildElements(element, args); - }, - - adjacent: function() { - var args = $A(arguments), element = $(args.shift()); - return Selector.findChildElements(element.parentNode, args).without(element); - }, - - identify: function(element) { - element = $(element); - var id = element.readAttribute('id'), self = arguments.callee; - if (id) return id; - do { id = 'anonymous_element_' + self.counter++ } while ($(id)); - element.writeAttribute('id', id); - return id; - }, - - readAttribute: function(element, name) { - element = $(element); - if (Prototype.Browser.IE) { - var t = Element._attributeTranslations.read; - if (t.values[name]) return t.values[name](element, name); - if (t.names[name]) name = t.names[name]; - if (name.include(':')) { - return (!element.attributes || !element.attributes[name]) ? null : - element.attributes[name].value; - } - } - return element.getAttribute(name); - }, - - writeAttribute: function(element, name, value) { - element = $(element); - var attributes = { }, t = Element._attributeTranslations.write; - - if (typeof name == 'object') attributes = name; - else attributes[name] = Object.isUndefined(value) ? true : value; - - for (var attr in attributes) { - name = t.names[attr] || attr; - value = attributes[attr]; - if (t.values[attr]) name = t.values[attr](element, value); - if (value === false || value === null) - element.removeAttribute(name); - else if (value === true) - element.setAttribute(name, name); - else element.setAttribute(name, value); - } - return element; - }, - - getHeight: function(element) { - return $(element).getDimensions().height; - }, - - getWidth: function(element) { - return $(element).getDimensions().width; - }, - - classNames: function(element) { - return new Element.ClassNames(element); - }, - - hasClassName: function(element, className) { - if (!(element = $(element))) return; - var elementClassName = element.className; - return (elementClassName.length > 0 && (elementClassName == className || - new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName))); - }, - - addClassName: function(element, className) { - if (!(element = $(element))) return; - if (!element.hasClassName(className)) - element.className += (element.className ? ' ' : '') + className; - return element; - }, - - removeClassName: function(element, className) { - if (!(element = $(element))) return; - element.className = element.className.replace( - new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip(); - return element; - }, - - toggleClassName: function(element, className) { - if (!(element = $(element))) return; - return element[element.hasClassName(className) ? - 'removeClassName' : 'addClassName'](className); - }, - - // removes whitespace-only text node children - cleanWhitespace: function(element) { - element = $(element); - var node = element.firstChild; - while (node) { - var nextNode = node.nextSibling; - if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) - element.removeChild(node); - node = nextNode; - } - return element; - }, - - empty: function(element) { - return $(element).innerHTML.blank(); - }, - - descendantOf: function(element, ancestor) { - element = $(element), ancestor = $(ancestor); - - if (element.compareDocumentPosition) - return (element.compareDocumentPosition(ancestor) & 8) === 8; - - if (ancestor.contains) - return ancestor.contains(element) && ancestor !== element; - - while (element = element.parentNode) - if (element == ancestor) return true; - - return false; - }, - - scrollTo: function(element) { - element = $(element); - var pos = element.cumulativeOffset(); - window.scrollTo(pos[0], pos[1]); - return element; - }, - - getStyle: function(element, style) { - element = $(element); - style = style == 'float' ? 'cssFloat' : style.camelize(); - var value = element.style[style]; - if (!value || value == 'auto') { - var css = document.defaultView.getComputedStyle(element, null); - value = css ? css[style] : null; - } - if (style == 'opacity') return value ? parseFloat(value) : 1.0; - return value == 'auto' ? null : value; - }, - - getOpacity: function(element) { - return $(element).getStyle('opacity'); - }, - - setStyle: function(element, styles) { - element = $(element); - var elementStyle = element.style, match; - if (Object.isString(styles)) { - element.style.cssText += ';' + styles; - return styles.include('opacity') ? - element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; - } - for (var property in styles) - if (property == 'opacity') element.setOpacity(styles[property]); - else - elementStyle[(property == 'float' || property == 'cssFloat') ? - (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') : - property] = styles[property]; - - return element; - }, - - setOpacity: function(element, value) { - element = $(element); - element.style.opacity = (value == 1 || value === '') ? '' : - (value < 0.00001) ? 0 : value; - return element; - }, - - getDimensions: function(element) { - element = $(element); - var display = element.getStyle('display'); - if (display != 'none' && display != null) // Safari bug - return {width: element.offsetWidth, height: element.offsetHeight}; - - // All *Width and *Height properties give 0 on elements with display none, - // so enable the element temporarily - var els = element.style; - var originalVisibility = els.visibility; - var originalPosition = els.position; - var originalDisplay = els.display; - els.visibility = 'hidden'; - els.position = 'absolute'; - els.display = 'block'; - var originalWidth = element.clientWidth; - var originalHeight = element.clientHeight; - els.display = originalDisplay; - els.position = originalPosition; - els.visibility = originalVisibility; - return {width: originalWidth, height: originalHeight}; - }, - - makePositioned: function(element) { - element = $(element); - var pos = Element.getStyle(element, 'position'); - if (pos == 'static' || !pos) { - element._madePositioned = true; - element.style.position = 'relative'; - // Opera returns the offset relative to the positioning context, when an - // element is position relative but top and left have not been defined - if (Prototype.Browser.Opera) { - element.style.top = 0; - element.style.left = 0; - } - } - return element; - }, - - undoPositioned: function(element) { - element = $(element); - if (element._madePositioned) { - element._madePositioned = undefined; - element.style.position = - element.style.top = - element.style.left = - element.style.bottom = - element.style.right = ''; - } - return element; - }, - - makeClipping: function(element) { - element = $(element); - if (element._overflow) return element; - element._overflow = Element.getStyle(element, 'overflow') || 'auto'; - if (element._overflow !== 'hidden') - element.style.overflow = 'hidden'; - return element; - }, - - undoClipping: function(element) { - element = $(element); - if (!element._overflow) return element; - element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; - element._overflow = null; - return element; - }, - - cumulativeOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - } while (element); - return Element._returnOffset(valueL, valueT); - }, - - positionedOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - if (element) { - if (element.tagName.toUpperCase() == 'BODY') break; - var p = Element.getStyle(element, 'position'); - if (p !== 'static') break; - } - } while (element); - return Element._returnOffset(valueL, valueT); - }, - - absolutize: function(element) { - element = $(element); - if (element.getStyle('position') == 'absolute') return element; - // Position.prepare(); // To be done manually by Scripty when it needs it. - - var offsets = element.positionedOffset(); - var top = offsets[1]; - var left = offsets[0]; - var width = element.clientWidth; - var height = element.clientHeight; - - element._originalLeft = left - parseFloat(element.style.left || 0); - element._originalTop = top - parseFloat(element.style.top || 0); - element._originalWidth = element.style.width; - element._originalHeight = element.style.height; - - element.style.position = 'absolute'; - element.style.top = top + 'px'; - element.style.left = left + 'px'; - element.style.width = width + 'px'; - element.style.height = height + 'px'; - return element; - }, - - relativize: function(element) { - element = $(element); - if (element.getStyle('position') == 'relative') return element; - // Position.prepare(); // To be done manually by Scripty when it needs it. - - element.style.position = 'relative'; - var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); - var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); - - element.style.top = top + 'px'; - element.style.left = left + 'px'; - element.style.height = element._originalHeight; - element.style.width = element._originalWidth; - return element; - }, - - cumulativeScrollOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.scrollTop || 0; - valueL += element.scrollLeft || 0; - element = element.parentNode; - } while (element); - return Element._returnOffset(valueL, valueT); - }, - - getOffsetParent: function(element) { - if (element.offsetParent) return $(element.offsetParent); - if (element == document.body) return $(element); - - while ((element = element.parentNode) && element != document.body) - if (Element.getStyle(element, 'position') != 'static') - return $(element); - - return $(document.body); - }, - - viewportOffset: function(forElement) { - var valueT = 0, valueL = 0; - - var element = forElement; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - - // Safari fix - if (element.offsetParent == document.body && - Element.getStyle(element, 'position') == 'absolute') break; - - } while (element = element.offsetParent); - - element = forElement; - do { - if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) { - valueT -= element.scrollTop || 0; - valueL -= element.scrollLeft || 0; - } - } while (element = element.parentNode); - - return Element._returnOffset(valueL, valueT); - }, - - clonePosition: function(element, source) { - var options = Object.extend({ - setLeft: true, - setTop: true, - setWidth: true, - setHeight: true, - offsetTop: 0, - offsetLeft: 0 - }, arguments[2] || { }); - - // find page position of source - source = $(source); - var p = source.viewportOffset(); - - // find coordinate system to use - element = $(element); - var delta = [0, 0]; - var parent = null; - // delta [0,0] will do fine with position: fixed elements, - // position:absolute needs offsetParent deltas - if (Element.getStyle(element, 'position') == 'absolute') { - parent = element.getOffsetParent(); - delta = parent.viewportOffset(); - } - - // correct by body offsets (fixes Safari) - if (parent == document.body) { - delta[0] -= document.body.offsetLeft; - delta[1] -= document.body.offsetTop; - } - - // set position - if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; - if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; - if (options.setWidth) element.style.width = source.offsetWidth + 'px'; - if (options.setHeight) element.style.height = source.offsetHeight + 'px'; - return element; - } -}; - -Element.Methods.identify.counter = 1; - -Object.extend(Element.Methods, { - getElementsBySelector: Element.Methods.select, - childElements: Element.Methods.immediateDescendants -}); - -Element._attributeTranslations = { - write: { - names: { - className: 'class', - htmlFor: 'for' - }, - values: { } - } -}; - -if (Prototype.Browser.Opera) { - Element.Methods.getStyle = Element.Methods.getStyle.wrap( - function(proceed, element, style) { - switch (style) { - case 'left': case 'top': case 'right': case 'bottom': - if (proceed(element, 'position') === 'static') return null; - case 'height': case 'width': - // returns '0px' for hidden elements; we want it to return null - if (!Element.visible(element)) return null; - - // returns the border-box dimensions rather than the content-box - // dimensions, so we subtract padding and borders from the value - var dim = parseInt(proceed(element, style), 10); - - if (dim !== element['offset' + style.capitalize()]) - return dim + 'px'; - - var properties; - if (style === 'height') { - properties = ['border-top-width', 'padding-top', - 'padding-bottom', 'border-bottom-width']; - } - else { - properties = ['border-left-width', 'padding-left', - 'padding-right', 'border-right-width']; - } - return properties.inject(dim, function(memo, property) { - var val = proceed(element, property); - return val === null ? memo : memo - parseInt(val, 10); - }) + 'px'; - default: return proceed(element, style); - } - } - ); - - Element.Methods.readAttribute = Element.Methods.readAttribute.wrap( - function(proceed, element, attribute) { - if (attribute === 'title') return element.title; - return proceed(element, attribute); - } - ); -} - -else if (Prototype.Browser.IE) { - // IE doesn't report offsets correctly for static elements, so we change them - // to "relative" to get the values, then change them back. - Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap( - function(proceed, element) { - element = $(element); - // IE throws an error if element is not in document - try { element.offsetParent } - catch(e) { return $(document.body) } - var position = element.getStyle('position'); - if (position !== 'static') return proceed(element); - element.setStyle({ position: 'relative' }); - var value = proceed(element); - element.setStyle({ position: position }); - return value; - } - ); - - $w('positionedOffset viewportOffset').each(function(method) { - Element.Methods[method] = Element.Methods[method].wrap( - function(proceed, element) { - element = $(element); - try { element.offsetParent } - catch(e) { return Element._returnOffset(0,0) } - var position = element.getStyle('position'); - if (position !== 'static') return proceed(element); - // Trigger hasLayout on the offset parent so that IE6 reports - // accurate offsetTop and offsetLeft values for position: fixed. - var offsetParent = element.getOffsetParent(); - if (offsetParent && offsetParent.getStyle('position') === 'fixed') - offsetParent.setStyle({ zoom: 1 }); - element.setStyle({ position: 'relative' }); - var value = proceed(element); - element.setStyle({ position: position }); - return value; - } - ); - }); - - Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap( - function(proceed, element) { - try { element.offsetParent } - catch(e) { return Element._returnOffset(0,0) } - return proceed(element); - } - ); - - Element.Methods.getStyle = function(element, style) { - element = $(element); - style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); - var value = element.style[style]; - if (!value && element.currentStyle) value = element.currentStyle[style]; - - if (style == 'opacity') { - if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) - if (value[1]) return parseFloat(value[1]) / 100; - return 1.0; - } - - if (value == 'auto') { - if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) - return element['offset' + style.capitalize()] + 'px'; - return null; - } - return value; - }; - - Element.Methods.setOpacity = function(element, value) { - function stripAlpha(filter){ - return filter.replace(/alpha\([^\)]*\)/gi,''); - } - element = $(element); - var currentStyle = element.currentStyle; - if ((currentStyle && !currentStyle.hasLayout) || - (!currentStyle && element.style.zoom == 'normal')) - element.style.zoom = 1; - - var filter = element.getStyle('filter'), style = element.style; - if (value == 1 || value === '') { - (filter = stripAlpha(filter)) ? - style.filter = filter : style.removeAttribute('filter'); - return element; - } else if (value < 0.00001) value = 0; - style.filter = stripAlpha(filter) + - 'alpha(opacity=' + (value * 100) + ')'; - return element; - }; - - Element._attributeTranslations = { - read: { - names: { - 'class': 'className', - 'for': 'htmlFor' - }, - values: { - _getAttr: function(element, attribute) { - return element.getAttribute(attribute, 2); - }, - _getAttrNode: function(element, attribute) { - var node = element.getAttributeNode(attribute); - return node ? node.value : ""; - }, - _getEv: function(element, attribute) { - attribute = element.getAttribute(attribute); - return attribute ? attribute.toString().slice(23, -2) : null; - }, - _flag: function(element, attribute) { - return $(element).hasAttribute(attribute) ? attribute : null; - }, - style: function(element) { - return element.style.cssText.toLowerCase(); - }, - title: function(element) { - return element.title; - } - } - } - }; - - Element._attributeTranslations.write = { - names: Object.extend({ - cellpadding: 'cellPadding', - cellspacing: 'cellSpacing' - }, Element._attributeTranslations.read.names), - values: { - checked: function(element, value) { - element.checked = !!value; - }, - - style: function(element, value) { - element.style.cssText = value ? value : ''; - } - } - }; - - Element._attributeTranslations.has = {}; - - $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + - 'encType maxLength readOnly longDesc frameBorder').each(function(attr) { - Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; - Element._attributeTranslations.has[attr.toLowerCase()] = attr; - }); - - (function(v) { - Object.extend(v, { - href: v._getAttr, - src: v._getAttr, - type: v._getAttr, - action: v._getAttrNode, - disabled: v._flag, - checked: v._flag, - readonly: v._flag, - multiple: v._flag, - onload: v._getEv, - onunload: v._getEv, - onclick: v._getEv, - ondblclick: v._getEv, - onmousedown: v._getEv, - onmouseup: v._getEv, - onmouseover: v._getEv, - onmousemove: v._getEv, - onmouseout: v._getEv, - onfocus: v._getEv, - onblur: v._getEv, - onkeypress: v._getEv, - onkeydown: v._getEv, - onkeyup: v._getEv, - onsubmit: v._getEv, - onreset: v._getEv, - onselect: v._getEv, - onchange: v._getEv - }); - })(Element._attributeTranslations.read.values); -} - -else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { - Element.Methods.setOpacity = function(element, value) { - element = $(element); - element.style.opacity = (value == 1) ? 0.999999 : - (value === '') ? '' : (value < 0.00001) ? 0 : value; - return element; - }; -} - -else if (Prototype.Browser.WebKit) { - Element.Methods.setOpacity = function(element, value) { - element = $(element); - element.style.opacity = (value == 1 || value === '') ? '' : - (value < 0.00001) ? 0 : value; - - if (value == 1) - if(element.tagName.toUpperCase() == 'IMG' && element.width) { - element.width++; element.width--; - } else try { - var n = document.createTextNode(' '); - element.appendChild(n); - element.removeChild(n); - } catch (e) { } - - return element; - }; - - // Safari returns margins on body which is incorrect if the child is absolutely - // positioned. For performance reasons, redefine Element#cumulativeOffset for - // KHTML/WebKit only. - Element.Methods.cumulativeOffset = function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - if (element.offsetParent == document.body) - if (Element.getStyle(element, 'position') == 'absolute') break; - - element = element.offsetParent; - } while (element); - - return Element._returnOffset(valueL, valueT); - }; -} - -if (Prototype.Browser.IE || Prototype.Browser.Opera) { - // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements - Element.Methods.update = function(element, content) { - element = $(element); - - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) return element.update().insert(content); - - content = Object.toHTML(content); - var tagName = element.tagName.toUpperCase(); - - if (tagName in Element._insertionTranslations.tags) { - $A(element.childNodes).each(function(node) { element.removeChild(node) }); - Element._getContentFromAnonymousElement(tagName, content.stripScripts()) - .each(function(node) { element.appendChild(node) }); - } - else element.innerHTML = content.stripScripts(); - - content.evalScripts.bind(content).defer(); - return element; - }; -} - -if ('outerHTML' in document.createElement('div')) { - Element.Methods.replace = function(element, content) { - element = $(element); - - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) { - element.parentNode.replaceChild(content, element); - return element; - } - - content = Object.toHTML(content); - var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); - - if (Element._insertionTranslations.tags[tagName]) { - var nextSibling = element.next(); - var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); - parent.removeChild(element); - if (nextSibling) - fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); - else - fragments.each(function(node) { parent.appendChild(node) }); - } - else element.outerHTML = content.stripScripts(); - - content.evalScripts.bind(content).defer(); - return element; - }; -} - -Element._returnOffset = function(l, t) { - var result = [l, t]; - result.left = l; - result.top = t; - return result; -}; - -Element._getContentFromAnonymousElement = function(tagName, html) { - var div = new Element('div'), t = Element._insertionTranslations.tags[tagName]; - if (t) { - div.innerHTML = t[0] + html + t[1]; - t[2].times(function() { div = div.firstChild }); - } else div.innerHTML = html; - return $A(div.childNodes); -}; - -Element._insertionTranslations = { - before: function(element, node) { - element.parentNode.insertBefore(node, element); - }, - top: function(element, node) { - element.insertBefore(node, element.firstChild); - }, - bottom: function(element, node) { - element.appendChild(node); - }, - after: function(element, node) { - element.parentNode.insertBefore(node, element.nextSibling); - }, - tags: { - TABLE: ['', '
            ', 1], - TBODY: ['', '
            ', 2], - TR: ['', '
            ', 3], - TD: ['
            ', '
            ', 4], - SELECT: ['', 1] - } -}; - -(function() { - Object.extend(this.tags, { - THEAD: this.tags.TBODY, - TFOOT: this.tags.TBODY, - TH: this.tags.TD - }); -}).call(Element._insertionTranslations); - -Element.Methods.Simulated = { - hasAttribute: function(element, attribute) { - attribute = Element._attributeTranslations.has[attribute] || attribute; - var node = $(element).getAttributeNode(attribute); - return !!(node && node.specified); - } -}; - -Element.Methods.ByTag = { }; - -Object.extend(Element, Element.Methods); - -if (!Prototype.BrowserFeatures.ElementExtensions && - document.createElement('div')['__proto__']) { - window.HTMLElement = { }; - window.HTMLElement.prototype = document.createElement('div')['__proto__']; - Prototype.BrowserFeatures.ElementExtensions = true; -} - -Element.extend = (function() { - if (Prototype.BrowserFeatures.SpecificElementExtensions) - return Prototype.K; - - var Methods = { }, ByTag = Element.Methods.ByTag; - - var extend = Object.extend(function(element) { - if (!element || element._extendedByPrototype || - element.nodeType != 1 || element == window) return element; - - var methods = Object.clone(Methods), - tagName = element.tagName.toUpperCase(), property, value; - - // extend methods for specific tags - if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); - - for (property in methods) { - value = methods[property]; - if (Object.isFunction(value) && !(property in element)) - element[property] = value.methodize(); - } - - element._extendedByPrototype = Prototype.emptyFunction; - return element; - - }, { - refresh: function() { - // extend methods for all tags (Safari doesn't need this) - if (!Prototype.BrowserFeatures.ElementExtensions) { - Object.extend(Methods, Element.Methods); - Object.extend(Methods, Element.Methods.Simulated); - } - } - }); - - extend.refresh(); - return extend; -})(); - -Element.hasAttribute = function(element, attribute) { - if (element.hasAttribute) return element.hasAttribute(attribute); - return Element.Methods.Simulated.hasAttribute(element, attribute); -}; - -Element.addMethods = function(methods) { - var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; - - if (!methods) { - Object.extend(Form, Form.Methods); - Object.extend(Form.Element, Form.Element.Methods); - Object.extend(Element.Methods.ByTag, { - "FORM": Object.clone(Form.Methods), - "INPUT": Object.clone(Form.Element.Methods), - "SELECT": Object.clone(Form.Element.Methods), - "TEXTAREA": Object.clone(Form.Element.Methods) - }); - } - - if (arguments.length == 2) { - var tagName = methods; - methods = arguments[1]; - } - - if (!tagName) Object.extend(Element.Methods, methods || { }); - else { - if (Object.isArray(tagName)) tagName.each(extend); - else extend(tagName); - } - - function extend(tagName) { - tagName = tagName.toUpperCase(); - if (!Element.Methods.ByTag[tagName]) - Element.Methods.ByTag[tagName] = { }; - Object.extend(Element.Methods.ByTag[tagName], methods); - } - - function copy(methods, destination, onlyIfAbsent) { - onlyIfAbsent = onlyIfAbsent || false; - for (var property in methods) { - var value = methods[property]; - if (!Object.isFunction(value)) continue; - if (!onlyIfAbsent || !(property in destination)) - destination[property] = value.methodize(); - } - } - - function findDOMClass(tagName) { - var klass; - var trans = { - "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", - "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", - "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", - "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", - "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": - "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": - "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": - "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": - "FrameSet", "IFRAME": "IFrame" - }; - if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; - if (window[klass]) return window[klass]; - klass = 'HTML' + tagName + 'Element'; - if (window[klass]) return window[klass]; - klass = 'HTML' + tagName.capitalize() + 'Element'; - if (window[klass]) return window[klass]; - - window[klass] = { }; - window[klass].prototype = document.createElement(tagName)['__proto__']; - return window[klass]; - } - - if (F.ElementExtensions) { - copy(Element.Methods, HTMLElement.prototype); - copy(Element.Methods.Simulated, HTMLElement.prototype, true); - } - - if (F.SpecificElementExtensions) { - for (var tag in Element.Methods.ByTag) { - var klass = findDOMClass(tag); - if (Object.isUndefined(klass)) continue; - copy(T[tag], klass.prototype); - } - } - - Object.extend(Element, Element.Methods); - delete Element.ByTag; - - if (Element.extend.refresh) Element.extend.refresh(); - Element.cache = { }; -}; - -document.viewport = { - getDimensions: function() { - var dimensions = { }, B = Prototype.Browser; - $w('width height').each(function(d) { - var D = d.capitalize(); - if (B.WebKit && !document.evaluate) { - // Safari <3.0 needs self.innerWidth/Height - dimensions[d] = self['inner' + D]; - } else if (B.Opera && parseFloat(window.opera.version()) < 9.5) { - // Opera <9.5 needs document.body.clientWidth/Height - dimensions[d] = document.body['client' + D] - } else { - dimensions[d] = document.documentElement['client' + D]; - } - }); - return dimensions; - }, - - getWidth: function() { - return this.getDimensions().width; - }, - - getHeight: function() { - return this.getDimensions().height; - }, - - getScrollOffsets: function() { - return Element._returnOffset( - window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, - window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); - } -}; -/* Portions of the Selector class are derived from Jack Slocum's DomQuery, - * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style - * license. Please see http://www.yui-ext.com/ for more information. */ - -var Selector = Class.create({ - initialize: function(expression) { - this.expression = expression.strip(); - - if (this.shouldUseSelectorsAPI()) { - this.mode = 'selectorsAPI'; - } else if (this.shouldUseXPath()) { - this.mode = 'xpath'; - this.compileXPathMatcher(); - } else { - this.mode = "normal"; - this.compileMatcher(); - } - - }, - - shouldUseXPath: function() { - if (!Prototype.BrowserFeatures.XPath) return false; - - var e = this.expression; - - // Safari 3 chokes on :*-of-type and :empty - if (Prototype.Browser.WebKit && - (e.include("-of-type") || e.include(":empty"))) - return false; - - // XPath can't do namespaced attributes, nor can it read - // the "checked" property from DOM nodes - if ((/(\[[\w-]*?:|:checked)/).test(e)) - return false; - - return true; - }, - - shouldUseSelectorsAPI: function() { - if (!Prototype.BrowserFeatures.SelectorsAPI) return false; - - if (!Selector._div) Selector._div = new Element('div'); - - // Make sure the browser treats the selector as valid. Test on an - // isolated element to minimize cost of this check. - try { - Selector._div.querySelector(this.expression); - } catch(e) { - return false; - } - - return true; - }, - - compileMatcher: function() { - var e = this.expression, ps = Selector.patterns, h = Selector.handlers, - c = Selector.criteria, le, p, m; - - if (Selector._cache[e]) { - this.matcher = Selector._cache[e]; - return; - } - - this.matcher = ["this.matcher = function(root) {", - "var r = root, h = Selector.handlers, c = false, n;"]; - - while (e && le != e && (/\S/).test(e)) { - le = e; - for (var i in ps) { - p = ps[i]; - if (m = e.match(p)) { - this.matcher.push(Object.isFunction(c[i]) ? c[i](m) : - new Template(c[i]).evaluate(m)); - e = e.replace(m[0], ''); - break; - } - } - } - - this.matcher.push("return h.unique(n);\n}"); - eval(this.matcher.join('\n')); - Selector._cache[this.expression] = this.matcher; - }, - - compileXPathMatcher: function() { - var e = this.expression, ps = Selector.patterns, - x = Selector.xpath, le, m; - - if (Selector._cache[e]) { - this.xpath = Selector._cache[e]; return; - } - - this.matcher = ['.//*']; - while (e && le != e && (/\S/).test(e)) { - le = e; - for (var i in ps) { - if (m = e.match(ps[i])) { - this.matcher.push(Object.isFunction(x[i]) ? x[i](m) : - new Template(x[i]).evaluate(m)); - e = e.replace(m[0], ''); - break; - } - } - } - - this.xpath = this.matcher.join(''); - Selector._cache[this.expression] = this.xpath; - }, - - findElements: function(root) { - root = root || document; - var e = this.expression, results; - - switch (this.mode) { - case 'selectorsAPI': - // querySelectorAll queries document-wide, then filters to descendants - // of the context element. That's not what we want. - // Add an explicit context to the selector if necessary. - if (root !== document) { - var oldId = root.id, id = $(root).identify(); - e = "#" + id + " " + e; - } - - results = $A(root.querySelectorAll(e)).map(Element.extend); - root.id = oldId; - - return results; - case 'xpath': - return document._getElementsByXPath(this.xpath, root); - default: - return this.matcher(root); - } - }, - - match: function(element) { - this.tokens = []; - - var e = this.expression, ps = Selector.patterns, as = Selector.assertions; - var le, p, m; - - while (e && le !== e && (/\S/).test(e)) { - le = e; - for (var i in ps) { - p = ps[i]; - if (m = e.match(p)) { - // use the Selector.assertions methods unless the selector - // is too complex. - if (as[i]) { - this.tokens.push([i, Object.clone(m)]); - e = e.replace(m[0], ''); - } else { - // reluctantly do a document-wide search - // and look for a match in the array - return this.findElements(document).include(element); - } - } - } - } - - var match = true, name, matches; - for (var i = 0, token; token = this.tokens[i]; i++) { - name = token[0], matches = token[1]; - if (!Selector.assertions[name](element, matches)) { - match = false; break; - } - } - - return match; - }, - - toString: function() { - return this.expression; - }, - - inspect: function() { - return "#"; - } -}); - -Object.extend(Selector, { - _cache: { }, - - xpath: { - descendant: "//*", - child: "/*", - adjacent: "/following-sibling::*[1]", - laterSibling: '/following-sibling::*', - tagName: function(m) { - if (m[1] == '*') return ''; - return "[local-name()='" + m[1].toLowerCase() + - "' or local-name()='" + m[1].toUpperCase() + "']"; - }, - className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", - id: "[@id='#{1}']", - attrPresence: function(m) { - m[1] = m[1].toLowerCase(); - return new Template("[@#{1}]").evaluate(m); - }, - attr: function(m) { - m[1] = m[1].toLowerCase(); - m[3] = m[5] || m[6]; - return new Template(Selector.xpath.operators[m[2]]).evaluate(m); - }, - pseudo: function(m) { - var h = Selector.xpath.pseudos[m[1]]; - if (!h) return ''; - if (Object.isFunction(h)) return h(m); - return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); - }, - operators: { - '=': "[@#{1}='#{3}']", - '!=': "[@#{1}!='#{3}']", - '^=': "[starts-with(@#{1}, '#{3}')]", - '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", - '*=': "[contains(@#{1}, '#{3}')]", - '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", - '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" - }, - pseudos: { - 'first-child': '[not(preceding-sibling::*)]', - 'last-child': '[not(following-sibling::*)]', - 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', - 'empty': "[count(*) = 0 and (count(text()) = 0)]", - 'checked': "[@checked]", - 'disabled': "[(@disabled) and (@type!='hidden')]", - 'enabled': "[not(@disabled) and (@type!='hidden')]", - 'not': function(m) { - var e = m[6], p = Selector.patterns, - x = Selector.xpath, le, v; - - var exclusion = []; - while (e && le != e && (/\S/).test(e)) { - le = e; - for (var i in p) { - if (m = e.match(p[i])) { - v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m); - exclusion.push("(" + v.substring(1, v.length - 1) + ")"); - e = e.replace(m[0], ''); - break; - } - } - } - return "[not(" + exclusion.join(" and ") + ")]"; - }, - 'nth-child': function(m) { - return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); - }, - 'nth-last-child': function(m) { - return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); - }, - 'nth-of-type': function(m) { - return Selector.xpath.pseudos.nth("position() ", m); - }, - 'nth-last-of-type': function(m) { - return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); - }, - 'first-of-type': function(m) { - m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); - }, - 'last-of-type': function(m) { - m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); - }, - 'only-of-type': function(m) { - var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); - }, - nth: function(fragment, m) { - var mm, formula = m[6], predicate; - if (formula == 'even') formula = '2n+0'; - if (formula == 'odd') formula = '2n+1'; - if (mm = formula.match(/^(\d+)$/)) // digit only - return '[' + fragment + "= " + mm[1] + ']'; - if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b - if (mm[1] == "-") mm[1] = -1; - var a = mm[1] ? Number(mm[1]) : 1; - var b = mm[2] ? Number(mm[2]) : 0; - predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + - "((#{fragment} - #{b}) div #{a} >= 0)]"; - return new Template(predicate).evaluate({ - fragment: fragment, a: a, b: b }); - } - } - } - }, - - criteria: { - tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', - className: 'n = h.className(n, r, "#{1}", c); c = false;', - id: 'n = h.id(n, r, "#{1}", c); c = false;', - attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;', - attr: function(m) { - m[3] = (m[5] || m[6]); - return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m); - }, - pseudo: function(m) { - if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); - return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); - }, - descendant: 'c = "descendant";', - child: 'c = "child";', - adjacent: 'c = "adjacent";', - laterSibling: 'c = "laterSibling";' - }, - - patterns: { - // combinators must be listed first - // (and descendant needs to be last combinator) - laterSibling: /^\s*~\s*/, - child: /^\s*>\s*/, - adjacent: /^\s*\+\s*/, - descendant: /^\s/, - - // selectors follow - tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, - id: /^#([\w\-\*]+)(\b|$)/, - className: /^\.([\w\-\*]+)(\b|$)/, - pseudo: -/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/, - attrPresence: /^\[((?:[\w]+:)?[\w]+)\]/, - attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ - }, - - // for Selector.match and Element#match - assertions: { - tagName: function(element, matches) { - return matches[1].toUpperCase() == element.tagName.toUpperCase(); - }, - - className: function(element, matches) { - return Element.hasClassName(element, matches[1]); - }, - - id: function(element, matches) { - return element.id === matches[1]; - }, - - attrPresence: function(element, matches) { - return Element.hasAttribute(element, matches[1]); - }, - - attr: function(element, matches) { - var nodeValue = Element.readAttribute(element, matches[1]); - return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]); - } - }, - - handlers: { - // UTILITY FUNCTIONS - // joins two collections - concat: function(a, b) { - for (var i = 0, node; node = b[i]; i++) - a.push(node); - return a; - }, - - // marks an array of nodes for counting - mark: function(nodes) { - var _true = Prototype.emptyFunction; - for (var i = 0, node; node = nodes[i]; i++) - node._countedByPrototype = _true; - return nodes; - }, - - unmark: function(nodes) { - for (var i = 0, node; node = nodes[i]; i++) - node._countedByPrototype = undefined; - return nodes; - }, - - // mark each child node with its position (for nth calls) - // "ofType" flag indicates whether we're indexing for nth-of-type - // rather than nth-child - index: function(parentNode, reverse, ofType) { - parentNode._countedByPrototype = Prototype.emptyFunction; - if (reverse) { - for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { - var node = nodes[i]; - if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; - } - } else { - for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) - if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; - } - }, - - // filters out duplicates and extends all nodes - unique: function(nodes) { - if (nodes.length == 0) return nodes; - var results = [], n; - for (var i = 0, l = nodes.length; i < l; i++) - if (!(n = nodes[i])._countedByPrototype) { - n._countedByPrototype = Prototype.emptyFunction; - results.push(Element.extend(n)); - } - return Selector.handlers.unmark(results); - }, - - // COMBINATOR FUNCTIONS - descendant: function(nodes) { - var h = Selector.handlers; - for (var i = 0, results = [], node; node = nodes[i]; i++) - h.concat(results, node.getElementsByTagName('*')); - return results; - }, - - child: function(nodes) { - var h = Selector.handlers; - for (var i = 0, results = [], node; node = nodes[i]; i++) { - for (var j = 0, child; child = node.childNodes[j]; j++) - if (child.nodeType == 1 && child.tagName != '!') results.push(child); - } - return results; - }, - - adjacent: function(nodes) { - for (var i = 0, results = [], node; node = nodes[i]; i++) { - var next = this.nextElementSibling(node); - if (next) results.push(next); - } - return results; - }, - - laterSibling: function(nodes) { - var h = Selector.handlers; - for (var i = 0, results = [], node; node = nodes[i]; i++) - h.concat(results, Element.nextSiblings(node)); - return results; - }, - - nextElementSibling: function(node) { - while (node = node.nextSibling) - if (node.nodeType == 1) return node; - return null; - }, - - previousElementSibling: function(node) { - while (node = node.previousSibling) - if (node.nodeType == 1) return node; - return null; - }, - - // TOKEN FUNCTIONS - tagName: function(nodes, root, tagName, combinator) { - var uTagName = tagName.toUpperCase(); - var results = [], h = Selector.handlers; - if (nodes) { - if (combinator) { - // fastlane for ordinary descendant combinators - if (combinator == "descendant") { - for (var i = 0, node; node = nodes[i]; i++) - h.concat(results, node.getElementsByTagName(tagName)); - return results; - } else nodes = this[combinator](nodes); - if (tagName == "*") return nodes; - } - for (var i = 0, node; node = nodes[i]; i++) - if (node.tagName.toUpperCase() === uTagName) results.push(node); - return results; - } else return root.getElementsByTagName(tagName); - }, - - id: function(nodes, root, id, combinator) { - var targetNode = $(id), h = Selector.handlers; - if (!targetNode) return []; - if (!nodes && root == document) return [targetNode]; - if (nodes) { - if (combinator) { - if (combinator == 'child') { - for (var i = 0, node; node = nodes[i]; i++) - if (targetNode.parentNode == node) return [targetNode]; - } else if (combinator == 'descendant') { - for (var i = 0, node; node = nodes[i]; i++) - if (Element.descendantOf(targetNode, node)) return [targetNode]; - } else if (combinator == 'adjacent') { - for (var i = 0, node; node = nodes[i]; i++) - if (Selector.handlers.previousElementSibling(targetNode) == node) - return [targetNode]; - } else nodes = h[combinator](nodes); - } - for (var i = 0, node; node = nodes[i]; i++) - if (node == targetNode) return [targetNode]; - return []; - } - return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; - }, - - className: function(nodes, root, className, combinator) { - if (nodes && combinator) nodes = this[combinator](nodes); - return Selector.handlers.byClassName(nodes, root, className); - }, - - byClassName: function(nodes, root, className) { - if (!nodes) nodes = Selector.handlers.descendant([root]); - var needle = ' ' + className + ' '; - for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { - nodeClassName = node.className; - if (nodeClassName.length == 0) continue; - if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) - results.push(node); - } - return results; - }, - - attrPresence: function(nodes, root, attr, combinator) { - if (!nodes) nodes = root.getElementsByTagName("*"); - if (nodes && combinator) nodes = this[combinator](nodes); - var results = []; - for (var i = 0, node; node = nodes[i]; i++) - if (Element.hasAttribute(node, attr)) results.push(node); - return results; - }, - - attr: function(nodes, root, attr, value, operator, combinator) { - if (!nodes) nodes = root.getElementsByTagName("*"); - if (nodes && combinator) nodes = this[combinator](nodes); - var handler = Selector.operators[operator], results = []; - for (var i = 0, node; node = nodes[i]; i++) { - var nodeValue = Element.readAttribute(node, attr); - if (nodeValue === null) continue; - if (handler(nodeValue, value)) results.push(node); - } - return results; - }, - - pseudo: function(nodes, name, value, root, combinator) { - if (nodes && combinator) nodes = this[combinator](nodes); - if (!nodes) nodes = root.getElementsByTagName("*"); - return Selector.pseudos[name](nodes, value, root); - } - }, - - pseudos: { - 'first-child': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) { - if (Selector.handlers.previousElementSibling(node)) continue; - results.push(node); - } - return results; - }, - 'last-child': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) { - if (Selector.handlers.nextElementSibling(node)) continue; - results.push(node); - } - return results; - }, - 'only-child': function(nodes, value, root) { - var h = Selector.handlers; - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) - results.push(node); - return results; - }, - 'nth-child': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, formula, root); - }, - 'nth-last-child': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, formula, root, true); - }, - 'nth-of-type': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, formula, root, false, true); - }, - 'nth-last-of-type': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, formula, root, true, true); - }, - 'first-of-type': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, "1", root, false, true); - }, - 'last-of-type': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, "1", root, true, true); - }, - 'only-of-type': function(nodes, formula, root) { - var p = Selector.pseudos; - return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); - }, - - // handles the an+b logic - getIndices: function(a, b, total) { - if (a == 0) return b > 0 ? [b] : []; - return $R(1, total).inject([], function(memo, i) { - if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); - return memo; - }); - }, - - // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type - nth: function(nodes, formula, root, reverse, ofType) { - if (nodes.length == 0) return []; - if (formula == 'even') formula = '2n+0'; - if (formula == 'odd') formula = '2n+1'; - var h = Selector.handlers, results = [], indexed = [], m; - h.mark(nodes); - for (var i = 0, node; node = nodes[i]; i++) { - if (!node.parentNode._countedByPrototype) { - h.index(node.parentNode, reverse, ofType); - indexed.push(node.parentNode); - } - } - if (formula.match(/^\d+$/)) { // just a number - formula = Number(formula); - for (var i = 0, node; node = nodes[i]; i++) - if (node.nodeIndex == formula) results.push(node); - } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b - if (m[1] == "-") m[1] = -1; - var a = m[1] ? Number(m[1]) : 1; - var b = m[2] ? Number(m[2]) : 0; - var indices = Selector.pseudos.getIndices(a, b, nodes.length); - for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { - for (var j = 0; j < l; j++) - if (node.nodeIndex == indices[j]) results.push(node); - } - } - h.unmark(nodes); - h.unmark(indexed); - return results; - }, - - 'empty': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) { - // IE treats comments as element nodes - if (node.tagName == '!' || node.firstChild) continue; - results.push(node); - } - return results; - }, - - 'not': function(nodes, selector, root) { - var h = Selector.handlers, selectorType, m; - var exclusions = new Selector(selector).findElements(root); - h.mark(exclusions); - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (!node._countedByPrototype) results.push(node); - h.unmark(exclusions); - return results; - }, - - 'enabled': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (!node.disabled && (!node.type || node.type !== 'hidden')) - results.push(node); - return results; - }, - - 'disabled': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (node.disabled) results.push(node); - return results; - }, - - 'checked': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (node.checked) results.push(node); - return results; - } - }, - - operators: { - '=': function(nv, v) { return nv == v; }, - '!=': function(nv, v) { return nv != v; }, - '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); }, - '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); }, - '*=': function(nv, v) { return nv == v || nv && nv.include(v); }, - '$=': function(nv, v) { return nv.endsWith(v); }, - '*=': function(nv, v) { return nv.include(v); }, - '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, - '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() + - '-').include('-' + (v || "").toUpperCase() + '-'); } - }, - - split: function(expression) { - var expressions = []; - expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { - expressions.push(m[1].strip()); - }); - return expressions; - }, - - matchElements: function(elements, expression) { - var matches = $$(expression), h = Selector.handlers; - h.mark(matches); - for (var i = 0, results = [], element; element = elements[i]; i++) - if (element._countedByPrototype) results.push(element); - h.unmark(matches); - return results; - }, - - findElement: function(elements, expression, index) { - if (Object.isNumber(expression)) { - index = expression; expression = false; - } - return Selector.matchElements(elements, expression || '*')[index || 0]; - }, - - findChildElements: function(element, expressions) { - expressions = Selector.split(expressions.join(',')); - var results = [], h = Selector.handlers; - for (var i = 0, l = expressions.length, selector; i < l; i++) { - selector = new Selector(expressions[i].strip()); - h.concat(results, selector.findElements(element)); - } - return (l > 1) ? h.unique(results) : results; - } -}); - -if (Prototype.Browser.IE) { - Object.extend(Selector.handlers, { - // IE returns comment nodes on getElementsByTagName("*"). - // Filter them out. - concat: function(a, b) { - for (var i = 0, node; node = b[i]; i++) - if (node.tagName !== "!") a.push(node); - return a; - }, - - // IE improperly serializes _countedByPrototype in (inner|outer)HTML. - unmark: function(nodes) { - for (var i = 0, node; node = nodes[i]; i++) - node.removeAttribute('_countedByPrototype'); - return nodes; - } - }); -} - -function $$() { - return Selector.findChildElements(document, $A(arguments)); -} -var Form = { - reset: function(form) { - $(form).reset(); - return form; - }, - - serializeElements: function(elements, options) { - if (typeof options != 'object') options = { hash: !!options }; - else if (Object.isUndefined(options.hash)) options.hash = true; - var key, value, submitted = false, submit = options.submit; - - var data = elements.inject({ }, function(result, element) { - if (!element.disabled && element.name) { - key = element.name; value = $(element).getValue(); - if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted && - submit !== false && (!submit || key == submit) && (submitted = true)))) { - if (key in result) { - // a key is already present; construct an array of values - if (!Object.isArray(result[key])) result[key] = [result[key]]; - result[key].push(value); - } - else result[key] = value; - } - } - return result; - }); - - return options.hash ? data : Object.toQueryString(data); - } -}; - -Form.Methods = { - serialize: function(form, options) { - return Form.serializeElements(Form.getElements(form), options); - }, - - getElements: function(form) { - return $A($(form).getElementsByTagName('*')).inject([], - function(elements, child) { - if (Form.Element.Serializers[child.tagName.toLowerCase()]) - elements.push(Element.extend(child)); - return elements; - } - ); - }, - - getInputs: function(form, typeName, name) { - form = $(form); - var inputs = form.getElementsByTagName('input'); - - if (!typeName && !name) return $A(inputs).map(Element.extend); - - for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { - var input = inputs[i]; - if ((typeName && input.type != typeName) || (name && input.name != name)) - continue; - matchingInputs.push(Element.extend(input)); - } - - return matchingInputs; - }, - - disable: function(form) { - form = $(form); - Form.getElements(form).invoke('disable'); - return form; - }, - - enable: function(form) { - form = $(form); - Form.getElements(form).invoke('enable'); - return form; - }, - - findFirstElement: function(form) { - var elements = $(form).getElements().findAll(function(element) { - return 'hidden' != element.type && !element.disabled; - }); - var firstByIndex = elements.findAll(function(element) { - return element.hasAttribute('tabIndex') && element.tabIndex >= 0; - }).sortBy(function(element) { return element.tabIndex }).first(); - - return firstByIndex ? firstByIndex : elements.find(function(element) { - return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); - }); - }, - - focusFirstElement: function(form) { - form = $(form); - form.findFirstElement().activate(); - return form; - }, - - request: function(form, options) { - form = $(form), options = Object.clone(options || { }); - - var params = options.parameters, action = form.readAttribute('action') || ''; - if (action.blank()) action = window.location.href; - options.parameters = form.serialize(true); - - if (params) { - if (Object.isString(params)) params = params.toQueryParams(); - Object.extend(options.parameters, params); - } - - if (form.hasAttribute('method') && !options.method) - options.method = form.method; - - return new Ajax.Request(action, options); - } -}; - -/*--------------------------------------------------------------------------*/ - -Form.Element = { - focus: function(element) { - $(element).focus(); - return element; - }, - - select: function(element) { - $(element).select(); - return element; - } -}; - -Form.Element.Methods = { - serialize: function(element) { - element = $(element); - if (!element.disabled && element.name) { - var value = element.getValue(); - if (value != undefined) { - var pair = { }; - pair[element.name] = value; - return Object.toQueryString(pair); - } - } - return ''; - }, - - getValue: function(element) { - element = $(element); - var method = element.tagName.toLowerCase(); - return Form.Element.Serializers[method](element); - }, - - setValue: function(element, value) { - element = $(element); - var method = element.tagName.toLowerCase(); - Form.Element.Serializers[method](element, value); - return element; - }, - - clear: function(element) { - $(element).value = ''; - return element; - }, - - present: function(element) { - return $(element).value != ''; - }, - - activate: function(element) { - element = $(element); - try { - element.focus(); - if (element.select && (element.tagName.toLowerCase() != 'input' || - !['button', 'reset', 'submit'].include(element.type))) - element.select(); - } catch (e) { } - return element; - }, - - disable: function(element) { - element = $(element); - element.disabled = true; - return element; - }, - - enable: function(element) { - element = $(element); - element.disabled = false; - return element; - } -}; - -/*--------------------------------------------------------------------------*/ - -var Field = Form.Element; -var $F = Form.Element.Methods.getValue; - -/*--------------------------------------------------------------------------*/ - -Form.Element.Serializers = { - input: function(element, value) { - switch (element.type.toLowerCase()) { - case 'checkbox': - case 'radio': - return Form.Element.Serializers.inputSelector(element, value); - default: - return Form.Element.Serializers.textarea(element, value); - } - }, - - inputSelector: function(element, value) { - if (Object.isUndefined(value)) return element.checked ? element.value : null; - else element.checked = !!value; - }, - - textarea: function(element, value) { - if (Object.isUndefined(value)) return element.value; - else element.value = value; - }, - - select: function(element, value) { - if (Object.isUndefined(value)) - return this[element.type == 'select-one' ? - 'selectOne' : 'selectMany'](element); - else { - var opt, currentValue, single = !Object.isArray(value); - for (var i = 0, length = element.length; i < length; i++) { - opt = element.options[i]; - currentValue = this.optionValue(opt); - if (single) { - if (currentValue == value) { - opt.selected = true; - return; - } - } - else opt.selected = value.include(currentValue); - } - } - }, - - selectOne: function(element) { - var index = element.selectedIndex; - return index >= 0 ? this.optionValue(element.options[index]) : null; - }, - - selectMany: function(element) { - var values, length = element.length; - if (!length) return null; - - for (var i = 0, values = []; i < length; i++) { - var opt = element.options[i]; - if (opt.selected) values.push(this.optionValue(opt)); - } - return values; - }, - - optionValue: function(opt) { - // extend element because hasAttribute may not be native - return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; - } -}; - -/*--------------------------------------------------------------------------*/ - -Abstract.TimedObserver = Class.create(PeriodicalExecuter, { - initialize: function($super, element, frequency, callback) { - $super(callback, frequency); - this.element = $(element); - this.lastValue = this.getValue(); - }, - - execute: function() { - var value = this.getValue(); - if (Object.isString(this.lastValue) && Object.isString(value) ? - this.lastValue != value : String(this.lastValue) != String(value)) { - this.callback(this.element, value); - this.lastValue = value; - } - } -}); - -Form.Element.Observer = Class.create(Abstract.TimedObserver, { - getValue: function() { - return Form.Element.getValue(this.element); - } -}); - -Form.Observer = Class.create(Abstract.TimedObserver, { - getValue: function() { - return Form.serialize(this.element); - } -}); - -/*--------------------------------------------------------------------------*/ - -Abstract.EventObserver = Class.create({ - initialize: function(element, callback) { - this.element = $(element); - this.callback = callback; - - this.lastValue = this.getValue(); - if (this.element.tagName.toLowerCase() == 'form') - this.registerFormCallbacks(); - else - this.registerCallback(this.element); - }, - - onElementEvent: function() { - var value = this.getValue(); - if (this.lastValue != value) { - this.callback(this.element, value); - this.lastValue = value; - } - }, - - registerFormCallbacks: function() { - Form.getElements(this.element).each(this.registerCallback, this); - }, - - registerCallback: function(element) { - if (element.type) { - switch (element.type.toLowerCase()) { - case 'checkbox': - case 'radio': - Event.observe(element, 'click', this.onElementEvent.bind(this)); - break; - default: - Event.observe(element, 'change', this.onElementEvent.bind(this)); - break; - } - } - } -}); - -Form.Element.EventObserver = Class.create(Abstract.EventObserver, { - getValue: function() { - return Form.Element.getValue(this.element); - } -}); - -Form.EventObserver = Class.create(Abstract.EventObserver, { - getValue: function() { - return Form.serialize(this.element); - } -}); -if (!window.Event) var Event = { }; - -Object.extend(Event, { - KEY_BACKSPACE: 8, - KEY_TAB: 9, - KEY_RETURN: 13, - KEY_ESC: 27, - KEY_LEFT: 37, - KEY_UP: 38, - KEY_RIGHT: 39, - KEY_DOWN: 40, - KEY_DELETE: 46, - KEY_HOME: 36, - KEY_END: 35, - KEY_PAGEUP: 33, - KEY_PAGEDOWN: 34, - KEY_INSERT: 45, - - cache: { }, - - relatedTarget: function(event) { - var element; - switch(event.type) { - case 'mouseover': element = event.fromElement; break; - case 'mouseout': element = event.toElement; break; - default: return null; - } - return Element.extend(element); - } -}); - -Event.Methods = (function() { - var isButton; - - if (Prototype.Browser.IE) { - var buttonMap = { 0: 1, 1: 4, 2: 2 }; - isButton = function(event, code) { - return event.button == buttonMap[code]; - }; - - } else if (Prototype.Browser.WebKit) { - isButton = function(event, code) { - switch (code) { - case 0: return event.which == 1 && !event.metaKey; - case 1: return event.which == 1 && event.metaKey; - default: return false; - } - }; - - } else { - isButton = function(event, code) { - return event.which ? (event.which === code + 1) : (event.button === code); - }; - } - - return { - isLeftClick: function(event) { return isButton(event, 0) }, - isMiddleClick: function(event) { return isButton(event, 1) }, - isRightClick: function(event) { return isButton(event, 2) }, - - element: function(event) { - event = Event.extend(event); - - var node = event.target, - type = event.type, - currentTarget = event.currentTarget; - - if (currentTarget && currentTarget.tagName) { - // Firefox screws up the "click" event when moving between radio buttons - // via arrow keys. It also screws up the "load" and "error" events on images, - // reporting the document as the target instead of the original image. - if (type === 'load' || type === 'error' || - (type === 'click' && currentTarget.tagName.toLowerCase() === 'input' - && currentTarget.type === 'radio')) - node = currentTarget; - } - if (node.nodeType == Node.TEXT_NODE) node = node.parentNode; - return Element.extend(node); - }, - - findElement: function(event, expression) { - var element = Event.element(event); - if (!expression) return element; - var elements = [element].concat(element.ancestors()); - return Selector.findElement(elements, expression, 0); - }, - - pointer: function(event) { - var docElement = document.documentElement, - body = document.body || { scrollLeft: 0, scrollTop: 0 }; - return { - x: event.pageX || (event.clientX + - (docElement.scrollLeft || body.scrollLeft) - - (docElement.clientLeft || 0)), - y: event.pageY || (event.clientY + - (docElement.scrollTop || body.scrollTop) - - (docElement.clientTop || 0)) - }; - }, - - pointerX: function(event) { return Event.pointer(event).x }, - pointerY: function(event) { return Event.pointer(event).y }, - - stop: function(event) { - Event.extend(event); - event.preventDefault(); - event.stopPropagation(); - event.stopped = true; - } - }; -})(); - -Event.extend = (function() { - var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { - m[name] = Event.Methods[name].methodize(); - return m; - }); - - if (Prototype.Browser.IE) { - Object.extend(methods, { - stopPropagation: function() { this.cancelBubble = true }, - preventDefault: function() { this.returnValue = false }, - inspect: function() { return "[object Event]" } - }); - - return function(event) { - if (!event) return false; - if (event._extendedByPrototype) return event; - - event._extendedByPrototype = Prototype.emptyFunction; - var pointer = Event.pointer(event); - Object.extend(event, { - target: event.srcElement, - relatedTarget: Event.relatedTarget(event), - pageX: pointer.x, - pageY: pointer.y - }); - return Object.extend(event, methods); - }; - - } else { - Event.prototype = Event.prototype || document.createEvent("HTMLEvents")['__proto__']; - Object.extend(Event.prototype, methods); - return Prototype.K; - } -})(); - -Object.extend(Event, (function() { - var cache = Event.cache; - - function getEventID(element) { - if (element._prototypeEventID) return element._prototypeEventID[0]; - arguments.callee.id = arguments.callee.id || 1; - return element._prototypeEventID = [++arguments.callee.id]; - } - - function getDOMEventName(eventName) { - if (eventName && eventName.include(':')) return "dataavailable"; - return eventName; - } - - function getCacheForID(id) { - return cache[id] = cache[id] || { }; - } - - function getWrappersForEventName(id, eventName) { - var c = getCacheForID(id); - return c[eventName] = c[eventName] || []; - } - - function createWrapper(element, eventName, handler) { - var id = getEventID(element); - var c = getWrappersForEventName(id, eventName); - if (c.pluck("handler").include(handler)) return false; - - var wrapper = function(event) { - if (!Event || !Event.extend || - (event.eventName && event.eventName != eventName)) - return false; - - Event.extend(event); - handler.call(element, event); - }; - - wrapper.handler = handler; - c.push(wrapper); - return wrapper; - } - - function findWrapper(id, eventName, handler) { - var c = getWrappersForEventName(id, eventName); - return c.find(function(wrapper) { return wrapper.handler == handler }); - } - - function destroyWrapper(id, eventName, handler) { - var c = getCacheForID(id); - if (!c[eventName]) return false; - c[eventName] = c[eventName].without(findWrapper(id, eventName, handler)); - } - - function destroyCache() { - for (var id in cache) - for (var eventName in cache[id]) - cache[id][eventName] = null; - } - - - // Internet Explorer needs to remove event handlers on page unload - // in order to avoid memory leaks. - if (window.attachEvent) { - window.attachEvent("onunload", destroyCache); - } - - // Safari has a dummy event handler on page unload so that it won't - // use its bfcache. Safari <= 3.1 has an issue with restoring the "document" - // object when page is returned to via the back button using its bfcache. - if (Prototype.Browser.WebKit) { - window.addEventListener('unload', Prototype.emptyFunction, false); - } - - return { - observe: function(element, eventName, handler) { - element = $(element); - var name = getDOMEventName(eventName); - - var wrapper = createWrapper(element, eventName, handler); - if (!wrapper) return element; - - if (element.addEventListener) { - element.addEventListener(name, wrapper, false); - } else { - element.attachEvent("on" + name, wrapper); - } - - return element; - }, - - stopObserving: function(element, eventName, handler) { - element = $(element); - var id = getEventID(element), name = getDOMEventName(eventName); - - if (!handler && eventName) { - getWrappersForEventName(id, eventName).each(function(wrapper) { - element.stopObserving(eventName, wrapper.handler); - }); - return element; - - } else if (!eventName) { - Object.keys(getCacheForID(id)).each(function(eventName) { - element.stopObserving(eventName); - }); - return element; - } - - var wrapper = findWrapper(id, eventName, handler); - if (!wrapper) return element; - - if (element.removeEventListener) { - element.removeEventListener(name, wrapper, false); - } else { - element.detachEvent("on" + name, wrapper); - } - - destroyWrapper(id, eventName, handler); - - return element; - }, - - fire: function(element, eventName, memo) { - element = $(element); - if (element == document && document.createEvent && !element.dispatchEvent) - element = document.documentElement; - - var event; - if (document.createEvent) { - event = document.createEvent("HTMLEvents"); - event.initEvent("dataavailable", true, true); - } else { - event = document.createEventObject(); - event.eventType = "ondataavailable"; - } - - event.eventName = eventName; - event.memo = memo || { }; - - if (document.createEvent) { - element.dispatchEvent(event); - } else { - element.fireEvent(event.eventType, event); - } - - return Event.extend(event); - } - }; -})()); - -Object.extend(Event, Event.Methods); - -Element.addMethods({ - fire: Event.fire, - observe: Event.observe, - stopObserving: Event.stopObserving -}); - -Object.extend(document, { - fire: Element.Methods.fire.methodize(), - observe: Element.Methods.observe.methodize(), - stopObserving: Element.Methods.stopObserving.methodize(), - loaded: false -}); - -(function() { - /* Support for the DOMContentLoaded event is based on work by Dan Webb, - Matthias Miller, Dean Edwards and John Resig. */ - - var timer; - - function fireContentLoadedEvent() { - if (document.loaded) return; - if (timer) window.clearInterval(timer); - document.fire("dom:loaded"); - document.loaded = true; - } - - if (document.addEventListener) { - if (Prototype.Browser.WebKit) { - timer = window.setInterval(function() { - if (/loaded|complete/.test(document.readyState)) - fireContentLoadedEvent(); - }, 0); - - Event.observe(window, "load", fireContentLoadedEvent); - - } else { - document.addEventListener("DOMContentLoaded", - fireContentLoadedEvent, false); - } - - } else { - document.write(" - - - - -

            Press a key, the details will be displayed below

            -
            - - - diff --git a/tryruby/public/robots.txt b/tryruby/public/robots.txt deleted file mode 100644 index 085187f..0000000 --- a/tryruby/public/robots.txt +++ /dev/null @@ -1,5 +0,0 @@ -# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file -# -# To ban all spiders from the entire site uncomment the next two lines: -# User-Agent: * -# Disallow: / diff --git a/tryruby/public/stylesheets/site.css b/tryruby/public/stylesheets/site.css deleted file mode 100755 index 62b1526..0000000 --- a/tryruby/public/stylesheets/site.css +++ /dev/null @@ -1,378 +0,0 @@ -body { - font-family: verdana, arial, sans-serif; - font-size: 14px; - text-align: center; -} -h1, h2, h3, h4 { - font-family: georgia, serif; - margin: 10px 45px; padding: 0; -} -h1 { - color: #333; - font-size: 48px; - font-weight: normal; - margin: 10px 0px; -} -h3 { - color: white; - font-size: 21px; - font-weight: normal; -} -a,a:link,a:visited { - text-decoration: none; - color: #57ad11; -} -a:hover { - text-decoration: underline; - color: #57ad11; -} -a:active { - text-decoration: underline; - color: #dddddd; -} -input.keyboard-selector-input { - position: fixed; - top: 0; - _position: absolute; - _top: expression(eval(document.body.scrollTop)); - left: -300px; -} -.container { - width: 678px; - margin: 0 auto; - text-align: left; -} -.content { - width: 712px; - background: url(/images/tile.png) repeat-y; -} -#lilBrowser { - position: absolute; - background-color: white; - top: -540px; - left: -440px; - width: 510px; - height: 430px; - padding: 5px; - border: solid 1px #444; - z-index: 100; -} -h3#lbTitle { - color: #444; - font-family: verdana, arial, sans-serif; - font-size: small; - float:left; - line-height: 90%; - margin: 0; padding: 3px; -} -p#lbClose { - font-size: small; - float: right; - margin: 0; padding: 3px; -} -p#lbClose a { - display: inline; -} -.shellwin { - width: 712px; - padding-left: 12px; - background: url(/images/background.png) no-repeat; -} - -/* tutorial panes */ -.stretcher { - color: #f1f1ff; - display: none; - margin: 0; - padding: 0; - padding-left: 12px; - background: url(/images/tile.png) repeat-y; -} -.stretcher a, .stretcher a:link, .stretcher a:visited, .stretcher a:active { - text-decoration: none; - color: #a7ed91; -} -.stretcher a:hover { - text-decoration: underline; - color: #b7fd91; -} -.stretcher p { - margin: 10px 16px; -} -.stretcher dl, .stretcher ul { - background-color: white; - color: #333; - padding: 4px 8px; - font-size: 12px; - margin-left: 16px; - list-style: none; -} -.stretcher li { - margin: 6px; -} -.stretcher p code { - background-color: #874a20; - color: #fedeec; - padding: 1px 4px; -} -.stretcher p code.cmd { - background-color: #eeeeec; - color: #204a87; -} -.stretcher dt { - font-weight: bold; -} - -.chapmark { - padding: 6px 0; - margin-left: 12px; - margin-right: 22px; - color: #553; - background: #efefe1; -} -.chapmark h3 { - color: #335; -} -.chapmark a, .chapmark a:link, .chapmark a:visited, .chapmark a:active { - text-decoration: none; - color: #372d61; -} -.chapmark a:hover { - text-decoration: underline; - color: #477d51; -} -.note { color: #ddc; text-align: center; font-size: xx-small; } -ul li strong { color: #286; border-bottom: solid 2px #cca; } -ul li code { background-color: #f1f1f1; padding: 1px 3px; border-bottom: solid 2px #ddd; } -ul li code.faded { color: #899; } -code strong { background-color: #dcffb9; padding: 1px 3px; } -ul.commands li strong { display: block; float: left; width: 60px; border: none; } - -/* irb terminal */ -.terminal { - background-color: #ffffff; - border: solid 1px #204a87; - width: 678px; - height: 240px; - overflow: auto; -} -.console { - padding: 4px; margin-left: -50px; - font-family: "Andale Mono", courier, fixed, monospace; - font-size: 14px; - line-height: 16px; - color: #204a87; - text-align: left; - width: 664px; - height:220px; -} - -.console div b { - background-color: #874a20; - color: #fedeac; -} -div.answer, div.stdout, div.no_answer, div.load { - display: none; -} - -/* terminal escape colors */ -span.fore_black { color: #2e3436; } -span.fore_dark_gray { color: #888a85; } -span.fore_gray { color: #babdb6; } -span.fore_white { color: #eeeeec; } -span.fore_blue { color: #204a87; } -span.fore_lt_blue { color: #729fcf; } -span.fore_green { color: #788600; font-weight: bold; } -span.fore_lt_green { color: #cbe134; } -span.fore_cyan { color: #c4a000; } /* using cyan for yellows */ -span.fore_lt_cyan { color: #fc994f; } -span.fore_red { color: #a40000; } -span.fore_lt_red { color: #ef2929; font-weight: bold; } -span.fore_purple { color: #5c3566; } -span.fore_lt_purple { color: #ad7fa8; } -span.fore_brown { color: #8f5972; } -span.fore_lt_brown { color: #b9b9de; } -span.back_black { background-color: #2e3436; } -span.back_dark_gray { background-color: #888a85; } -span.back_gray { background-color: #babdb6; } -span.back_white { background-color: #eeeeec; } -span.back_blue { background-color: #204a87; } -span.back_lt_blue { background-color: #729fcf; } -span.back_green { background-color: #788600; } -span.back_lt_green { background-color: #cbe134; } -span.back_cyan { background-color: #c4a000; } /* using cyan for yellows */ -span.back_lt_cyan { background-color: #fce94f; } -span.back_red { background-color: #a40000; } -span.back_lt_red { background-color: #ef2929; } -span.back_purple { background-color: #5c3566; } -span.back_lt_purple { background-color: #ad7fa8; } -span.back_brown { background-color: #8f5902; } -span.back_lt_brown { background-color: #b9b96e; } - -/** no ways***/ - -div.main-wrapper-bottom { - height:4px;background-position: 0px -80px; background-repeat: no-repeat; - font-size:0 /* IE6, go figure */ -} -div.main-wrapper-borders { - background-position: -1731px 0; padding:15px; - background-repeat:repeat-y; -} -div.console-wrapper { - margin:0px auto ;width:566px; - cursor:text; - font-family:monospace; -} -div.console-wrapper-top { - height:3px;background-position: -50px -48px; background-repeat: no-repeat; - font-size:0 /* IE6, go figure */ -} -div.console-wrapper-bottom { - height:3px;background-position: -50px -51px; background-repeat: no-repeat; - font-size:0 /* IE6, go figure */ -} -div.console-wrapper-borders { - background-position: 0px 0px; padding:1px; - background-repeat:repeat-y; -} -div.guide-wrapper { - color:#fff; width:566px;margin-left:2px -} -div.guide-wrapper-top { - height:4px;background-position: 0 -65px; - font-size:0 /* IE6, go figure */ -} -div.guide-wrapper-bottom { - height:4px;background-position: 0 -70px; - font-size:0 /* IE6, go figure */ -} -div.guide-wrapper-borders { - background-position: -1166px 0px;padding:15px; - background-repeat:repeat-y; -} - -div.footer-wrapper-borders { - background-position: -566px 0px; padding:10px; - background-repeat:repeat-y; - font-size:12px -} -h1.main-header { - text-indent:-9999px; background-position: -49px 0px; - background-repeat: no-repeat; - width:318px; height:48px; margin-bottom:20px; - float:left -} - -div.footer { - line-height: 1.3em; -} - div.console div.jquery-console-inner -{ height:100%; overflow:auto; background:white} -div.console div.jquery-console-prompt-box -{ color:#437375; font-family:monospace; margin-top:0.5em; } -div.console div.jquery-console-prompt-box .prompt-done -{ cursor: pointer } -div.console div.jquery-console-prompt-box .prompt-done:hover -{ background:#453D5B; color: white; } -div.console div.jquery-console-focus span.jquery-console-cursor -{ background:#666; color:#fff; } -div.console div.jquery-console-message-error { - color:#ef0505; font-family:sans-serif; font-weight:bold; - padding-top:0.25em -} -div.console div.jquery-console-message-value -{ color:#000; font-family:monospace;padding-top:0.25em; font-weight: bold; } -div.console div.jquery-console-message-type -{ color:#382567; font-family:monospace;padding-left:0em;padding-top:0.25em; font-size:.9em } -div.console span.jquery-console-prompt-label { font-weight:bold } -div.console div.jquery-console-welcome { font-family:"DejaVu Sans",sans-serif; } - -div.share-wrapper { font-size:12px;padding:10px 0em 0em 10px } -div.share-wrapper strong { font-weight: bold } - -.clearfix:after { content:"."; display:block; height:0; clear:both; visibility:hidden } -div.menu { - float:right; - margin-right:2px; - margin-top:40px; - margin-bottom:5px -} -a.reset-btn { - float:left; - display:block; - width:59px; - height:24px; - background-position: -427px -18px; background-repeat: no-repeat; -} -a.reset-btn span { display:none } - -div.clear { clear:both } - - -div.console-wrapper .notice { - position:absolute; - bottom:0;right:0; - margin:1px; - background:#eee; - color:black; - padding:10px; - font-size:12px; - font-family:sans-serif; - font-weight:bold; -} -p.ajax-loader { background:url(../images/ajax-loader.gif); width:16px; height:16px;text-indent:-9999px } - -.notice a { padding:3px;background:#333;color:white} -.notice .action { text-align: right } - -/* Support Try Ruby! */ - - -a.trigger{ -position: absolute; -text-decoration: none; -top: 80px; right: 0; -font-size: 14px; -letter-spacing:-1px; -font-family: verdana, helvetica, arial, sans-serif; -color:#fff; -padding: 10px 10px 10px 10px; -font-weight: 500; -background:#333333 url(images/plus.png) 15% 55% no-repeat; -border:1px solid #444444; --moz-border-radius-topleft: 20px; --webkit-border-top-left-radius: 20px; --moz-border-radius-bottomleft: 20px; --webkit-border-bottom-left-radius: 20px; --moz-border-radius-bottomright: 0px; --webkit-border-bottom-right-radius: 0px; -display: block; -} - -a.trigger:hover{ -position: absolute; -text-decoration: none; -top: 80px; right: 0; -font-size: 14px; -letter-spacing:-1px; -font-family: verdana, helvetica, arial, sans-serif; -color:#fff; -padding: 10px 10px 10px 10px; -font-weight: 500; -background: green; -border:1px solid #444444; --moz-border-radius-topleft: 20px; --webkit-border-top-left-radius: 20px; --moz-border-radius-bottomleft: 20px; --webkit-border-bottom-left-radius: 20px; --moz-border-radius-bottomright: 0px; --webkit-border-bottom-right-radius: 0px; -display: block; -} - -a.active.trigger { -background:#222222 url(images/minus.png) 15% 55% no-repeat; -} - - \ No newline at end of file diff --git a/tryruby/script/about b/tryruby/script/about deleted file mode 100755 index 1eeb6eb..0000000 --- a/tryruby/script/about +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env ruby -require File.expand_path('../../config/boot', __FILE__) -$LOAD_PATH.unshift "#{RAILTIES_PATH}/builtin/rails_info" -require 'commands/about' diff --git a/tryruby/script/console b/tryruby/script/console deleted file mode 100755 index 235a1f2..0000000 --- a/tryruby/script/console +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.expand_path('../../config/boot', __FILE__) -require 'commands/console' diff --git a/tryruby/script/dbconsole b/tryruby/script/dbconsole deleted file mode 100755 index 83c8436..0000000 --- a/tryruby/script/dbconsole +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.expand_path('../../config/boot', __FILE__) -require 'commands/dbconsole' diff --git a/tryruby/script/destroy b/tryruby/script/destroy deleted file mode 100755 index 88d295f..0000000 --- a/tryruby/script/destroy +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.expand_path('../../config/boot', __FILE__) -require 'commands/destroy' diff --git a/tryruby/script/generate b/tryruby/script/generate deleted file mode 100755 index 62a8a4c..0000000 --- a/tryruby/script/generate +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.expand_path('../../config/boot', __FILE__) -require 'commands/generate' diff --git a/tryruby/script/performance/benchmarker b/tryruby/script/performance/benchmarker deleted file mode 100755 index 3bff809..0000000 --- a/tryruby/script/performance/benchmarker +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.expand_path('../../../config/boot', __FILE__) -require 'commands/performance/benchmarker' diff --git a/tryruby/script/performance/profiler b/tryruby/script/performance/profiler deleted file mode 100755 index 0764057..0000000 --- a/tryruby/script/performance/profiler +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.expand_path('../../../config/boot', __FILE__) -require 'commands/performance/profiler' diff --git a/tryruby/script/plugin b/tryruby/script/plugin deleted file mode 100755 index b82201f..0000000 --- a/tryruby/script/plugin +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.expand_path('../../config/boot', __FILE__) -require 'commands/plugin' diff --git a/tryruby/script/runner b/tryruby/script/runner deleted file mode 100755 index be4c5d4..0000000 --- a/tryruby/script/runner +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.expand_path('../../config/boot', __FILE__) -require 'commands/runner' diff --git a/tryruby/script/server b/tryruby/script/server deleted file mode 100755 index b9fcb71..0000000 --- a/tryruby/script/server +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.expand_path('../../config/boot', __FILE__) -require 'commands/server' diff --git a/tryruby/test/functional/tryruby_controller_test.rb b/tryruby/test/functional/tryruby_controller_test.rb deleted file mode 100644 index 0b2649e..0000000 --- a/tryruby/test/functional/tryruby_controller_test.rb +++ /dev/null @@ -1,9 +0,0 @@ -require 'test_helper' - -class TryrubyControllerTest < ActionController::TestCase - test "run" do - get :run, :cmd => "2 + 6" - assert_response :success - assert_equal "=> \e[1;20m8", @response.body - end -end diff --git a/tryruby/test/functional/tutorials_controller_test.rb b/tryruby/test/functional/tutorials_controller_test.rb deleted file mode 100644 index a2e7246..0000000 --- a/tryruby/test/functional/tutorials_controller_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -require 'test_helper' - -class TutorialsControllerTest < ActionController::TestCase - # Replace this with your real tests. - test "the truth" do - assert true - end -end diff --git a/tryruby/test/performance/browsing_test.rb b/tryruby/test/performance/browsing_test.rb deleted file mode 100644 index 867fc8c..0000000 --- a/tryruby/test/performance/browsing_test.rb +++ /dev/null @@ -1,9 +0,0 @@ -require 'test_helper' -require 'rails/performance_test_help' - -# Profiling results for each test method are written to tmp/performance. -class BrowsingTest < ActionDispatch::PerformanceTest - def test_homepage - get '/' - end -end diff --git a/tryruby/test/test_helper.rb b/tryruby/test/test_helper.rb deleted file mode 100644 index 8bf1192..0000000 --- a/tryruby/test/test_helper.rb +++ /dev/null @@ -1,13 +0,0 @@ -ENV["RAILS_ENV"] = "test" -require File.expand_path('../../config/environment', __FILE__) -require 'rails/test_help' - -class ActiveSupport::TestCase - # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order. - # - # Note: You'll currently still have to declare fixtures explicitly in integration tests - # -- they do not yet inherit this setting - fixtures :all - - # Add more helper methods to be used by all tests here... -end diff --git a/tryruby/test/unit/fake_f_s_test.rb b/tryruby/test/unit/fake_f_s_test.rb deleted file mode 100644 index deaa7b9..0000000 --- a/tryruby/test/unit/fake_f_s_test.rb +++ /dev/null @@ -1,94 +0,0 @@ -require 'test/test_helper' - -class FakeFSTest < Test::Unit::TestCase - def setup - FakeFS.activate! - FakeFS::FileSystem.clear - end - - def teardown - FakeFS.deactivate! - end - - def test_file_system_current_dir - assert_equal({}, FakeFS::FileSystem.current_dir) - Dir.mkdir "Home" - assert_equal({"Home"=>{}}, FakeFS::FileSystem.current_dir) - FakeFS::FileSystem.chdir "Home" do - Dir.mkdir "Sub" - assert_equal({"Sub" => {}}, FakeFS::FileSystem.current_dir) - end - assert_equal({"Home" => {"Sub" => {}}}, FakeFS::FileSystem.current_dir) - end - - def test_dir_entries_for_current_dir - assert_equal [".", ".."], Dir.entries(".") - end - - def test_dir_entries_for_root - assert_equal [".", ".."], Dir.entries("/") - end - - def test_dir_entries2 - Dir.mkdir "Home" - assert_equal [".", "..", "Home"], Dir.entries(".") - end - - def test_dir_entries3 - ["Home", "Libraries", "MouseHole", "Programs", "Tutorials"].each {|dir| Dir.mkdir dir } - assert_equal [".", "..", "Home", "Libraries", "MouseHole", "Programs", "Tutorials"], Dir.entries("/") - end - - def test_fake_dir_to_s_for_root_dir - assert_equal("/", FakeFS::FileSystem.current_dir.to_s) - end - - def test_fake_dir_to_s_for_sub_dir - Dir.mkdir "Home" - FakeFS::FileSystem.chdir "Home" do - assert_equal("/Home", FakeFS::FileSystem.current_dir.to_s) - end - end - - def test_fake_dir_to_s_for_sub_sub_dir - Dir.mkdir "Home" - FakeFS::FileSystem.chdir "Home" do - Dir.mkdir "Sub" - FakeFS::FileSystem.chdir "Sub" do - assert_equal("/Home/Sub", FakeFS::FileSystem.current_dir.to_s) - end - end - end - - def test_file_inspect - assert_equal("#", File.open("/comics.txt", "a") { |f| f << "a"}.inspect) - end - - def test_file_foreach - File.open("/comics.txt", "a") { |f| f << "a"} - lines = [] - File.foreach("/comics.txt") do |l| lines << l - end - assert_equal(["a"], lines) - end - - def test_file_expand_path_for_current_dir - assert_equal "/", File.expand_path(".") - Dir.mkdir "Home" - FakeFS::FileSystem.chdir "Home" do - assert_equal "/Home", File.expand_path(".") - end - end - - def test_file_expand_path_for_root_dir - assert_equal RealFile.expand_path("/"), File.expand_path("/") - end - - def test_file_expand_path_for_user_dir - assert_equal "/~", File.expand_path("~") - end - - def test_file_expand_path_for_user_dir_with_sub_dir - assert_equal "/~/test", File.expand_path("~/test") - end -end \ No newline at end of file diff --git a/tryruby/test/unit/nesting_level_test.rb b/tryruby/test/unit/nesting_level_test.rb deleted file mode 100644 index ea45dda..0000000 --- a/tryruby/test/unit/nesting_level_test.rb +++ /dev/null @@ -1,49 +0,0 @@ -require 'test_helper' - -# This tests the TryRubyBaseSession#calculate_nesting_level function -class NestingLevelTest < Test::Unit::TestCase - def test_finished_statement_should_return_0 - assert_equal(0, TryRuby.calculate_nesting_level("42")) - end - - def test_missing_end_should_return_1 - assert_equal(1, TryRuby.calculate_nesting_level("3.times do")) - end - - def test_missing_close_brace_should_return_1 - assert_equal(1, TryRuby.calculate_nesting_level("3.times {")) - end - - def test_open_class_should_return_1 - assert_equal(1, TryRuby.calculate_nesting_level("class BlogEntry")) - end - - def test_closed_class_should_return_0 - assert_equal(0, TryRuby.calculate_nesting_level("class BlogEntry\nend")) - end - - def test_2_unclosed_dos_should_return_2 - assert_equal(2, TryRuby.calculate_nesting_level("3.times do\n4.times do")) - end - - def test_mix_of_opened_statements - test_str = <<-EOF - class MyClass - def mymethod - 3.times do - 8.times { - EOF - assert_equal(4, TryRuby.calculate_nesting_level(test_str)) - end - - def test_open_and_close_on_same_line_should_return_0 - assert_equal(0, TryRuby.calculate_nesting_level("3.times { puts 'lol' }")) - assert_equal(0, TryRuby.calculate_nesting_level("3.times do |v| puts 'lol'; end")) - end - - def test_half_statement - assert_equal(1, TryRuby.calculate_nesting_level('true and')) - assert_equal(1, TryRuby.calculate_nesting_level('amethod(')) - end - -end diff --git a/tryruby/test/unit/output_test.rb b/tryruby/test/unit/output_test.rb deleted file mode 100644 index 3c5ef55..0000000 --- a/tryruby/test/unit/output_test.rb +++ /dev/null @@ -1,55 +0,0 @@ -require 'test_helper' - -# tests if the TryRubyOutput translation, for use with mouseapp_2.js and similar -# is working correctly -class OutputTest < Test::Unit::TestCase - def test_simple_result - t = TryRuby::Output.standard(result: [12,24]) - assert_equal("=> \033[1;20m[12, 24]", t.format) - end - - def test_result_and_output - t = TryRuby::Output.standard(result: 333, output: "hello") - assert_equal("hello=> \033[1;20m333", t.format) - end - - def test_error - begin - 40.reverse - rescue Exception => e - t = TryRuby::Output.error(error: e) - end - assert_equal("\033[1;33mNoMethodError: undefined method `reverse' for 40:Fixnum", - t.format) - end - - def test_error_with_output - begin - 40.reverse - rescue Exception => e - t = TryRuby::Output.error(error: e, output: "hello\nworld") - end - assert_equal("hello\nworld\033[1;33mNoMethodError: undefined method `reverse' for 40:Fixnum", - t.format) - end - - def test_illegal - t = TryRuby::Output.illegal - assert_equal("\033[1;33mYou aren't allowed to run that command!", - t.format) - end - - - - def test_line_continuation - t = TryRuby::Output.line_continuation(3) - assert_equal(".." * 3, t.format) - end - - def xtest_javascript - t = TryRuby::Output.javascript(javascript: 'alert("hello")') - # expected ends in a space to stop a visual problem in mouseapp - assert_equal("\033[1;JSmalert(\"hello\")\033[m ", t.format) - end - -end \ No newline at end of file diff --git a/tryruby/test/unit/try_ruby_test.rb b/tryruby/test/unit/try_ruby_test.rb deleted file mode 100644 index 35da8e6..0000000 --- a/tryruby/test/unit/try_ruby_test.rb +++ /dev/null @@ -1,500 +0,0 @@ -require 'test_helper' - -class FakeFS::File - def self.foreach(path) - self.read(path).each_line {|line| yield(line) } - end -end -$session = nil - -class TryRubyTest < Test::Unit::TestCase - # a test helper that simplifies testing the tryruby interpretor. - # It takes one optional argument session, which is the session to use for - # the test. - # It then takes a block. In the block a method input is available which is used - # to send a line to the interpretor and test the output. - # - # input takes one mandatory argument, the line, and some optional args: - # - output: The output of line should match this (defaults to "") - # - javascript: The line generated a javascript function, and should match this - # - error: The line generated an error and should match this - # - result: The line didn't generate an error or javascript, and should match this - # (defaults to nil if not supplied) - # - line_continuation: The line didn't complete, the current indent level - # should be equal to this (use true if you aren't interested in testing this) - # output, error, javascript and result can take either a: - # - Class: Tests if is the given type - # - Proc: Proc should take one param (the ) and run assertions with that value - # - Regexp: Tests (a string) against the regexp - # - : should equal - def tryruby_session(session = TryRubyTestSession.new, &block) - input_o = TryRubySession_Input.new - input_o.session = session - input_o.test = self - input_o.instance_eval(&block) - - end - - - def test_lesson1 - tryruby_session do - input '2 + 6' , result: 8 - input '"Jimmy"' , result: "Jimmy" - input '"Jimmy".reverse' , result: "ymmiJ" - input '"Jimmy".length' , result: 5 - input '"Jimmy" * 5' , result: "JimmyJimmyJimmyJimmyJimmy" - end - end - - # tests statements that should end with a line continuation - def test_line_continuations - tryruby_session do - input '3.times do |v|' , line_continuation: 1 - input '3.times { |v|', line_continuation: 2 - input '}; end', result: Proc.new {true} - input 'class MyClass', line_continuation: 1 - input "def mymethod", line_continuation: 2 - input "end; end", result: Proc.new{true} - end - end - - def test_lines_with_semicolons - tryruby_session do - input '3; 4', result: 4 - input 'puts "hello"; a = 4; 5', output: "hello\n", result: 5 - input 'a', result: 4 - input '; 42', result: 42 - end - end - - - def test_errors - tryruby_session do - input 'asdf', error: NameError, output: "" - input 'print "hello"; asdf', error: NameError, output: "hello" - end - end - - # tests statements that shouldn't end with a line continuation - def test_shouldnt_have_line_continuation - tryruby_session do - input "'helloclassend'", result: "helloclassend" - input "3.class", result: Class - end - end - - def test_illegal_ops - $session = TryRubyTestSession.new - tryruby_session $session do - input '`cat /etc/passwd`', illegal: true - input 'require "popup"', result: Proc.new{} - input '%x(cat /etc/passwd)', illegal: true - end - end - - - def test_lesson2 - tryruby_session do - input '40.reverse', error: NoMethodError - input '40.to_s.reverse', result: "04" - input '[]', result: [] - input '[12,47,35]', result: [12,47,35] - input '[12,47,35].max', result: 47 - input 'ticket = [12,47,35]', result: [12,47,35] - input 'ticket', result: [12,47,35] - input 'ticket.sort!', result: [12,35,47] - end - end - - def test_lesson3 - poem = <<-EOF -My toast has flown from my hand -And my toast has gone to the -moon. -But when I saw it on television, -Planting our flag on Halley's -comet, -More still did I want to eat it. -EOF - - tryruby_session do - # the below line should be done automatically by the interpretor - # when help 3 is loaded - input "poem = #{poem.inspect}", result: Proc.new{} - input 'print poem', output: poem - input "poem['toast'] = 'honeydew'", result: "honeydew" - input 'print poem', output: (poem['toast'] = 'honeydew'; poem) - input 'poem.reverse', result: poem.reverse - input 'poem.lines.to_a.reverse', result: poem.lines.to_a.reverse - input 'print poem.lines.to_a.reverse.join', output: poem.lines.to_a.reverse.join - end - end - - def test_lesson4 - tryruby_session do - input 'books = {}', result: {} - - input 'books["Gravity\'s Rainbow"] = :splendid', - result: :splendid - - input 'books["a"] = :mediocre', result: :mediocre - input 'books["b"] = :mediocre', result: :mediocre - input 'books["c"] = :mediocre', result: :mediocre - input 'books.length', result: 4 - input 'books["Gravity\'s Rainbow"]', result: :splendid - input 'books.keys', result: ["Gravity's Rainbow", "a", "b", "c"] - input 'ratings = Hash.new {0}', result: {} - - input 'books.values.each { |rate| ratings[rate] += 1 }', - result: [:splendid, :mediocre, :mediocre, :mediocre] - - input '5.times {print "Odelay!" }', - result: 5, - output: 'Odelay!Odelay!Odelay!Odelay!Odelay!' - - end - end - - def test_lesson5 - tryruby_session do - input 'Dir.entries "/"', - result: [".", "..", "Home", "Libraries", "MouseHole", "Programs", "Tutorials", - "comics.txt"] - input 'Dir["/*.txt"]', result: ["/comics.txt"] - comics_txt_text = <", value.inspect - } - input 'File.mtime("/Home/comics.txt")', result: Time - input 'File.mtime("/Home/comics.txt").hour', result: Fixnum - end - - end - - def test_lesson6 - $session = TryRubyTestSession.new - tryruby_session $session do - input 'def load_comics( path )', line_continuation: 1 - input 'comics = {}', line_continuation: 1 - input 'File.foreach(path) do |line|', line_continuation: 2 - input "name, url = line.split(': ')", line_continuation: 2 - input 'comics[name] = url.strip', line_continuation: 2 - input 'end', line_continuation: 1 - input 'comics', line_continuation: 1 - input 'end', result: nil - - input "comics = load_comics('/comics.txt')", result: - {"Achewood"=>"http://achewood.com/", - "Dinosaur Comics"=>"http://qwantz.com/", - "Perry Bible Fellowship"=>"http://cheston.com/pbf/archive.html" , - "Get Your War On"=>"http://mnftiu.cc/"} - - input "require 'popup'", result: Proc.new {} - input 'Popup.goto "http://google.com/"', :output => nil, - javascript: "window.irb.options.popup_goto(\"http://google.com/\")" - - input 'Popup.make {', line_continuation: 1 - input 'h1 "My Links"', line_continuation: 1 - input 'link "Go to Google", "http://google.com/"', line_continuation: 1 - input '}', :output => nil, javascript: - "window.irb.options.popup_make" + - "(\"

            My Links

            " + - "Go to Google\")" - - input 'Popup.make do', line_continuation: 1 - input 'h1 "Things To Do"', line_continuation: 1 - input 'list do', line_continuation: 2 - input 'p "Try out Ruby"', line_continuation: 2 - input 'p "Ride a tiger"', line_continuation: 2 - input 'p "(down River Euphrates)"', line_continuation: 2 - input 'end', line_continuation: 1 - expected = <Things To Do -
            • Try out Ruby
            • -
            • Ride a tiger
            • -
            • (down River Euphrates) -
            ") -EOF - input 'end', :output => nil, javascript: expected.gsub("\n", "") - -input 'Popup.make do', line_continuation: 1 -input 'h1 "Comics on the Web"', line_continuation: 1 -input 'list do', line_continuation: 2 -input 'comics.each do |name, url|', line_continuation: 3 -input 'link name, url', line_continuation: 3 -input 'end', line_continuation: 2 -input 'end', line_continuation: 1 -input 'end', :output => nil, javascript: Proc.new { |v| - matches = v.match(/^window.irb.options.popup_make\("(.*)"\)/) - assert_not_nil(matches) - html = matches[1].gsub(/\\(.)/, '\1') - doc = Hpricot(html) - assert_equal("Comics on the Web", (doc/:h1).inner_html) - list_items = (doc/:li/:a).map do |elem| - {href: elem.attributes['href'], title: elem.inner_html} - end - assert_equal({href: "http://achewood.com/", title: "Achewood"}, - list_items[0]) - assert_equal({href: "http://qwantz.com/", title: "Dinosaur Comics"}, - list_items[1]) - assert_equal({href: "http://cheston.com/pbf/archive.html", - title: "Perry Bible Fellowship"}, - list_items[2]) - assert_equal({href: "http://mnftiu.cc/", title: "Get Your War On"}, - list_items[3]) - - #assert_equal("", html) - } - - - - - end - - end - - - - - def test_lesson7_and_8 - $session = TryRubyTestSession.new - tryruby_session $session do - input 'Hash.new', result: {} - input 'class BlogEntry', line_continuation: 1 - input 'attr_accessor :title, :time, :fulltext, :mood', line_continuation: 1 - input 'end', result: nil - - # can't test for BlogEntry directly, as it isn't defined in this scope - input 'entry = BlogEntry.new', result: Proc.new {|v| - assert_equal("BlogEntry", v.class.name, - "line should result in a BlogEntry") - } - - input 'entry.title = "Today Mt. Hood Was Stolen!"', result: "Today Mt. Hood Was Stolen!" - - input 'entry.time = Time.now', result: Time - - input 'entry.mood = :sick', result: :sick - - str = <

            My Blog

            -
              -
            • Today Mt. Hood Was Stolen!

            • -
            • I can't believe Mt. Hood was stolen! I am speechless! - It was stolen by a giraffe who drove away in his - Cadillac Seville very nonchalant!!
            • -
            • I Left my Hoodie on the Mountain!

            • -
            • I am never going back to that mountain and - I hope a giraffe steals it.
            • -
            - EOF - - expected_xml = REXML::Document.new(expected_str.strip) - assert_match(/^window.irb.options.popup_make\(".*"\)?/m, - v, - "testing that Popup calls the correct javascript function") - actual_str = v.match(/^window.irb.options.popup_make\("(.*)"\);?/m)[1] - actual_str = "#{actual_str}" - actual_xml = REXML::Document.new(actual_str.strip) - assert_equal(expected_xml.write(StringIO.new).to_s, - actual_xml.write(StringIO.new).to_s, - "testing that html used with the javascript popup " + - "function is correct") - } - - input 'Time.now - 2.weeks', result: Time - - input 'File.read("/MouseHole/flickrpedia.user.rb")', result: String - - end # tryruby_session - - end # lesson6_and_7 - - - - - # class that performs the tests with the input sections of the - # tryrubysession test helper - class TryRubySession_Input - attr_accessor :session, :test - - # performs an assertion - # actual is the value being tested - # expected should either be a - # - Class: the class of actual should be expected - # - Regexp: actual (a string) should match the expected Regexp - # - Proc: A proc that takes one argument, actual. Assertions can - # be used inside that proc, eg assert_equal, assert. - # - : actual should equal expected - # name is the name of the input (result, output, javascript, error), - # used in messages - # line is the line being tested - def do_assert(actual, expected, name, line) - case expected - when Class - @test.assert_kind_of(expected, actual, - "Testing line `#{line}': #{name} should be a #{expected}") - when Regexp - @test.assert_match(expected, actual, - "Testing line `#{line}': #{name} should match #{expected}") - when Proc - @backtrace_pos = 0 - @test.instance_exec(actual, &expected) - - # @test.assert(expected.call(actual), - # "Testing line `#{line}': #{message} \n[#{actual}]") - else - @test.assert_equal(expected,actual, - "Testing line `#{line}' for correct #{name}") - end - end - - # runs the line using this objects session. - def do_test(line) - o = Object.new - # store the initial constants of Object - initial_constants = Object.constants - session = @session - - thread = Thread.new do - o.instance_eval do - result = run_script(session, line) - end - end - - result = thread.value - # restores require to its old functionality - #def Object.require(str) - # old_require(str) - #end - - # next 4 lines will revert Object to the way it was before - # run_script - diff_constants = Object.constants - initial_constants - diff_constants.each do |constant| - Object.send(:remove_const, constant) rescue nil - end - result - end - - - # The input function, used with the tryruby_session test helper - # see tryruby_session for more details - def input(line, params = {}) - @backtrace_pos = 2 - params[:output] = "" unless params.has_key?(:output) - params[:result] ||= nil - params[:error] ||= nil - result = do_test(line) - begin - if params[:illegal] then - @test.assert_equal(:illegal, result.type, - "Testing if line `#{line}' resulted in an illegal operation") - elsif params[:error] then - @test.assert_equal(:error, result.type, - "Testing if line `#{line}` resulted in an error") - do_assert(result.error, params[:error], "error", line) - do_assert(result.output, params[:output], "output", line) - elsif params[:javascript] then - @test.assert_nil(result.error, - "Testing line `#{line}' to ensure there was no error") - do_assert(result.javascript, params[:javascript], "javascript", line) - do_assert(result.output, params[:output], "output", line) - elsif params[:line_continuation] - @test.assert_equal(:line_continuation, result.type, - "Testing if line `#{line}' resulted in a line continuation") - if params[:line_continuation] != true then - @test.assert_equal(result.indent_level, params[:line_continuation], - "Testing if line `#{line}' triggered enough autoindent") - end - else - @test.assert_nil(result.error, - "Testing line `#{line}' to ensure there was no error") - do_assert(result.result, params[:result], "result" , line) - do_assert(result.output, params[:output], "output", line) - end - - rescue Test::Unit::AssertionFailedError => e - p e - - new_bt = Test::Unit::Util::BacktraceFilter.filter_backtrace(e.backtrace) - new_bt = new_bt[@backtrace_pos..@backtrace_pos] - e.set_backtrace(new_bt) - raise e - - end - end - end -end - diff --git a/tryruby/tmp/pids/server.pid b/tryruby/tmp/pids/server.pid deleted file mode 100644 index 3acadad..0000000 --- a/tryruby/tmp/pids/server.pid +++ /dev/null @@ -1 +0,0 @@ -48625 \ No newline at end of file From e7517c61d860bfb0b949a16e4f2369593e9afc40 Mon Sep 17 00:00:00 2001 From: Andrew McElroy Date: Fri, 8 Jul 2011 17:25:32 -0500 Subject: [PATCH 08/16] figured out how to clean up case sensitive names in git on a non case sensitive filesystem --- public/.gitignore | 2 - public/blank.html | 4 - public/comics.txt | 4 - public/es_index.html | 96 -- public/fakefs | 1 - public/images/background.png | Bin 35315 -> 0 bytes public/images/footer.png | Bin 6840 -> 0 bytes public/images/header.png | Bin 51873 -> 0 bytes public/images/index.html | 8 - public/images/tile.png | Bin 305 -> 0 bytes public/index.html | 166 --- public/irb.cgi | 38 - public/javascripts/application.js | 2 - public/javascripts/console.js | 288 ---- public/javascripts/controls.js | 963 ------------- public/javascripts/dragdrop.js | 973 ------------- public/javascripts/effects.js | 1128 --------------- public/javascripts/facebox.js | 309 ---- public/javascripts/index.html | 8 - public/javascripts/irb.js | 110 -- public/javascripts/jQuery.irb.js | 1641 ---------------------- public/javascripts/jquery-1.3.2.min.js | 19 - public/javascripts/jquery-1.4.2.min.js | 154 -- public/javascripts/jquery.console.js | 609 -------- public/javascripts/jquery.console.min.js | 1 - public/javascripts/jquery.js | 32 - public/javascripts/json2.js | 1 - public/javascripts/lib.min.js | 159 --- public/javascripts/mouseapp_2.js | 913 ------------ public/javascripts/mouseirb_2.js | 179 --- public/javascripts/raphael-min.js | 113 -- public/js/index.html | 8 - public/js/irb.js | 110 -- public/js/jquery-1.3.2.min.js | 19 - public/js/jquery.js | 32 - public/js/mouseapp_2.js | 913 ------------ public/js/mouseirb_2.js | 179 --- public/keypress_test.html | 37 - public/moods/index.html | 8 - public/moods/sick.gif | Bin 94 -> 0 bytes public/popup.rb | 114 -- public/setup.rb | 67 - public/site.css | 211 --- public/stylesheets/facebox.css | 83 -- public/stylesheets/reset.css | 46 - public/stylesheets/scaffold.css | 56 - public/stylesheets/site.css | 378 ----- public/submodules/fakefs | 1 - public/test.rb | 633 --------- public/tmp/index.html | 8 - public/tryruby.rb | 174 --- public/tutorials/es_intro.html | 666 --------- public/tutorials/intro.html | 680 --------- public/tutorials/intro.html.broken | 638 --------- public/tutorials/intro_files/sick.gif | Bin 94 -> 0 bytes 55 files changed, 12982 deletions(-) delete mode 100644 public/.gitignore delete mode 100755 public/blank.html delete mode 100755 public/comics.txt delete mode 100644 public/es_index.html delete mode 160000 public/fakefs delete mode 100755 public/images/background.png delete mode 100755 public/images/footer.png delete mode 100644 public/images/header.png delete mode 100755 public/images/index.html delete mode 100755 public/images/tile.png delete mode 100644 public/index.html delete mode 100755 public/irb.cgi delete mode 100644 public/javascripts/application.js delete mode 100644 public/javascripts/console.js delete mode 100644 public/javascripts/controls.js delete mode 100644 public/javascripts/dragdrop.js delete mode 100644 public/javascripts/effects.js delete mode 100755 public/javascripts/facebox.js delete mode 100755 public/javascripts/index.html delete mode 100755 public/javascripts/irb.js delete mode 100644 public/javascripts/jQuery.irb.js delete mode 100644 public/javascripts/jquery-1.3.2.min.js delete mode 100644 public/javascripts/jquery-1.4.2.min.js delete mode 100644 public/javascripts/jquery.console.js delete mode 100644 public/javascripts/jquery.console.min.js delete mode 100755 public/javascripts/jquery.js delete mode 100644 public/javascripts/json2.js delete mode 100644 public/javascripts/lib.min.js delete mode 100755 public/javascripts/mouseapp_2.js delete mode 100755 public/javascripts/mouseirb_2.js delete mode 100644 public/javascripts/raphael-min.js delete mode 100755 public/js/index.html delete mode 100755 public/js/irb.js delete mode 100644 public/js/jquery-1.3.2.min.js delete mode 100755 public/js/jquery.js delete mode 100755 public/js/mouseapp_2.js delete mode 100755 public/js/mouseirb_2.js delete mode 100644 public/keypress_test.html delete mode 100755 public/moods/index.html delete mode 100755 public/moods/sick.gif delete mode 100755 public/popup.rb delete mode 100644 public/setup.rb delete mode 100755 public/site.css delete mode 100755 public/stylesheets/facebox.css delete mode 100644 public/stylesheets/reset.css delete mode 100644 public/stylesheets/scaffold.css delete mode 100755 public/stylesheets/site.css delete mode 160000 public/submodules/fakefs delete mode 100755 public/test.rb delete mode 100755 public/tmp/index.html delete mode 100644 public/tryruby.rb delete mode 100644 public/tutorials/es_intro.html delete mode 100644 public/tutorials/intro.html delete mode 100755 public/tutorials/intro.html.broken delete mode 100755 public/tutorials/intro_files/sick.gif diff --git a/public/.gitignore b/public/.gitignore deleted file mode 100644 index a1632ab..0000000 --- a/public/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -tmp/ - diff --git a/public/blank.html b/public/blank.html deleted file mode 100755 index 7879e1c..0000000 --- a/public/blank.html +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/public/comics.txt b/public/comics.txt deleted file mode 100755 index 7dfc8e6..0000000 --- a/public/comics.txt +++ /dev/null @@ -1,4 +0,0 @@ -Achewood: http://achewood.com/ -Dinosaur Comics: http://qwantz.com/ -Perry Bible Fellowship: http://cheston.com/pbf/archive.html -Get Your War On: http://mnftiu.cc/ diff --git a/public/es_index.html b/public/es_index.html deleted file mode 100644 index 7519e36..0000000 --- a/public/es_index.html +++ /dev/null @@ -1,96 +0,0 @@ - - - - - try ruby! (en tu navegador) - - - - - - - - - -
            - -
            -
            -
            - -

            A Popup Browser

            -

            [x]

            -
            - -
            -
            - -
            -
            -
            -
            -
            -
            -

            ¿Tienes 15 minutos? ¡Prueba Ruby ahora mismo!

            -

            Ruby es un lenguaje de programación de Japón - (disponible en ruby-lang.org) - que está revolucionando la web. - La belleza de Ruby se encuentra en su balance entre la simplicidad y el poder.

            - -

            Prueba código Ruby en el prompt de arriba. Además de los métodos - originales de Ruby, los siguientes comandos están disponibles:

            -
              -
            • help - Empieza el tutorial interactivo de 15 minutos. ¡Creeme, es muy básico!
            • -
            • help 2 - Salta al capítulo 2.
            • - -
            • clear - Limpia la pantalla. Útil si tu navegador empieza a alerdarce. - Tu historial de comandos será recordado. -
            • back - Retrocede una pantalla en el tutorial.
            • -
            • reset - Resetea el interprete. (o Ctrl-D!)
            • -
            • next - Te permite saltear la siguiente lección
            • - -
            • time - Detiene el reloj. Imprime cuanto tiempo tu sesión estuvo abierta.
            • -
            -

            Si te pasa de dejar o refrescar la página, tu sesión seguirá aquí a menos que - se deje inactiva por diez minutos.

            -
            -
            -
            - -
            -
            ¿Atrapado en los dos puntos? Unas comillas o algo fue dejado abierto. Escribe: reset o aprieta Ctrl-D.
            -
            - -

            This place was sired by why the lucky stiff. - Please contact me using the email address at that link.is maintained by Andrew McElroy and David Miani. For support issues, please post a ticket or contact Sophrinix on github.
            Por asuntos de traducción, mandar un ticket o contactarse con Cristian Re (leizzer) en Github.
            -

            - -
            - - - - - - - - - - diff --git a/public/fakefs b/public/fakefs deleted file mode 160000 index c6168d4..0000000 --- a/public/fakefs +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c6168d41363e4c60ddf9d4cb784e6acf79ea581d diff --git a/public/images/background.png b/public/images/background.png deleted file mode 100755 index 3a2dee031614731e46c00b5f8416d471908af982..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35315 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 b}X6WEoFQ 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 - - - - -

            you shouldn't be here.. kicking you out!

            - - diff --git a/public/images/tile.png b/public/images/tile.png deleted file mode 100755 index 399139f26d14e29a407d8b4bb8473ad2279edc41..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 305 zcmV-10nYx3P)e#ZdVeV@YYlo&$tx`(sO@ILaF1IwM9!1&Y00000NkvXXu0mjf DW=Vhn diff --git a/public/index.html b/public/index.html deleted file mode 100644 index 566f947..0000000 --- a/public/index.html +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - try ruby! (in your browser) - - - - - - - - - - - - - - - - - - -
            - -
            - -
            -
            - -

            A Popup Browser

            -

            [x]

            -
            - -
            -
            - -
            -
            -
            -
            -
            -
            -

            Got 15 minutes? Give Ruby a shot right now!

            -

            Ruby is a programming language from Japan - (available at ruby-lang.org) - which is revolutionizing the web. - The beauty of Ruby is found in its balance between simplicity and power.

            - -

            Try out Ruby code in the prompt above. In addition - to Ruby's builtin methods, the following commands are available:

            -
              -
            • help - Start the 15 minute interactive tutorial. Trust me, it's very basic!
            • -
            • help 2 - Hop to chapter two.
            • - -
            • clear - Clear screen. Useful if your browser starts slowing down. - Your command history will be remembered. -
            • back - Go back one screen in the tutorial.
            • -
            • reset - Reset the interpreter if you get too deep. (or Ctrl-D!)
            • -
            • next -Allows you to skip to the next section of a lesson.
            • - -
            • time - A stopwatch. Prints the time your session has been open.
            • -
            -

            If you happen to leave or refresh the page, your session will still be here for - unless it is left inactive for ten minutes.

            -
            -
            -
            - -
            -
            Trapped in double dots? A quote or something was left open. Type: reset or hit Ctrl-D.
            -
            - -

            This place was sired by why the lucky stiff. - Please contact me using the email address at that link.is maintained by Andrew McElroy and David Miani. For support issues, please post a ticket or contact Sophrinix on github. -

            - -
            - - - - - - - - -Please Support
            Try Ruby!
            - - - diff --git a/public/irb.cgi b/public/irb.cgi deleted file mode 100755 index 9bf2d06..0000000 --- a/public/irb.cgi +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/local/bin/ruby - -require './tryruby.rb' -require 'cgi' -require 'cgi/session' -require 'cgi/session/pstore' -require './popup.rb' - -class TryRubyCGISession# < TryRuby::Session - attr_accessor :cgi, :session - - def initialize - @session = CGI::Session.new @cgi = CGI.new, - 'database_manager' => CGI::Session::PStore, # use PStore - 'session_key' => 'trb_sess_id', # custom $session key - 'session_expires' => Time.now + 60 * 60, # 60 minute timeout - 'prefix' => 'pstore_sid_', #Pstore option - 'tmpdir' => 'tmp' # Temp Directory for sessions - - - @session['start_time'] ||= Time.now - @session['current_statement'] ||= '' - @session['past_commands'] ||= '' - end - - def header - @cgi.header 'text/plain' - end - - [:current_statement, :past_commands, :start_time].each do |accessor| - define_method(accessor) { @session[accessor.to_s] } - define_method(:"#{accessor.to_s}=") { |new_val| @session[accessor.to_s] = new_val } - end -end - -TryRuby.session = TryRubyCGISession.new - -print TryRuby.session.header + TryRuby.run_line(TryRuby.session.cgi['cmd']).format diff --git a/public/javascripts/application.js b/public/javascripts/application.js deleted file mode 100644 index fe45776..0000000 --- a/public/javascripts/application.js +++ /dev/null @@ -1,2 +0,0 @@ -// Place your application-specific JavaScript functions and classes here -// This file is automatically included by javascript_include_tag :defaults diff --git a/public/javascripts/console.js b/public/javascripts/console.js deleted file mode 100644 index e7e8b79..0000000 --- a/public/javascripts/console.js +++ /dev/null @@ -1,288 +0,0 @@ -jQuery.fn.debug = function() { - var msg = jqArray.args(arguments); - $("
            ").addClass("error").text(msg.join(", ")).prependTo(this); -} - -jQConsole = function(input, output) { - - var args = jqArray.args - - var input = input; - - // History - var command_history = []; - var command_selected = 0; - - var local_scope = safe_scope(); - - function hide_fn(fn) { return function() { return fn.apply(this, arguments); } } - hide_fn.desc = "A function that creates a wrapper that hides the implementation of another function"; - function queue_fn(fn, time) { if(!time) time = 0; return function() { setTimeout(fn, time); } } - queue_fn.desc = "Turns a function into a function that's called later"; - - var keys = function (o) { - var r = []; - if (typeof o != "object") return r; - for (var k in o) r.push(k); - return r; - } - var refocus = queue_fn(function() { input.blur().focus(); }); - var reset_input = queue_fn(function() { input.val("").blur().focus(); }); - function no_recurse(fn, max_depth) { - var count = 0; - if(!max_depth) max_depth = 1; - return function() { - count++; - if(count > max_depth) { - count--; return; - } else { - fn.apply(this, arguments); - } - } - } - - function hook_fn(fn, listener) { - fn.listener = function() { return listener; } - fn.apply = function(thisArg, argArray) { - if(fn == caller) return; - listener(); - return fn.apply(thisArg, argArray); - }; - } - - hook_fn(history, function() { print("Yo"); }); - - $(document).ready(page_onload); - - function page_onload() { - input = $(input); - output = $(output); - input.keypress(map_keyboard()); - $(document).click(refocus); - refocus(); - } - page_onload = hide_fn(page_onload); - - function clear() { output.html(""); } - - function history() { - return command_history.join("\n"); - } - - var keyLogging = false; - - function map_keyboard() { - var cmdKeys = keymap(); - with(cmdKeys) { - mapKeyCode(toggleKeyLogging, 120); - map(executeCommand, {keyCode:13, ctrlKey:true}); - //mapKeyCode(executeCommand, 13); - mapKeyCode(refocus, 9); - map(historyLast, {keyCode:38, ctrlKey:true}); - map(historyNext, {keyCode:40, ctrlKey:true}); - map(function() { return false; }, {keyCode:123}); - } - return function(e) { - if(keyLogging) - log("keyCode: " + e.keyCode, " shiftKey: " + e.shiftKey, " ctrlKey: " + e.ctrlKey); - resize_input(); - return cmdKeys.dispatch(e); - } - } - - function toggleKeyLogging() { keyLogging = !keyLogging; } - - function historyLast() { - command_selected = Math.max(0, command_selected - 1); - edit_command(command_history[command_selected]); - } - - function historyNext() { - command_selected = Math.min(command_history.length, command_selected + 1); - var cmd = (command_selected == command_history.length) ? "" : command_history[command_selected]; - edit_command(cmd); - } - - function tryComplete() { - - refocus(); - } - - function executeCommand(cmd) { - cmd = (!cmd) ? input.val() : cmd; - reset_input(); - var result = evalInScope(cmd, default_scope); - command_selected = command_history.length; - logCommand(cmd, result); - setTimeout(function() { input.attr("rows", 1); }, 2); - return false; - } - - function evalInScope(cmd, scope) { - try { - - //if(!scope) return eval.apply(our_scope, [cmd]); - with(scope) { - with(jQConsole.our_scope) { - return eval(cmd); - } - } - - //move_modified_scope(local_scope, global_scope); - } - catch(e) { - return e.message; - } - } - - function move_modified_scope(l, g) { - - for(var k in g) { - if(g[k] && typeof l[k] == 'undefined') { - l[k] = g[k]; - g[k] = null; - } - } - } - - function safe_scope() { - var s = {}, g = jQConsole.global_scope; - for(var k in g) { s[k] = null; } - s.global_scope = jQConsole.global_scope; - return s; - } - - var encoders = { - "object": function(o, l) { - if(o.constructor == Array) - return encode_array(o); - //return "[array]"; - return "{ " + encode_obj(o, l) + " }"; - }, - "function": function(v) { return v.toString(); }, - "string": function(v) { return "\"" + v + "\""; }, - "undefined": function() { return "undefined"; }, - _default: function(v) { return v.toString(); } - } - - function encode_array(a) { - var r = a.map(enc); - return "[" + r.join(",") + "]"; - } - - enc = function(v, l, root) { - root = root || true; - if(v == null) return (root) ? "" : "null" + l; - if(encoders[typeof v]) return encoders[typeof v](v); - //log("enc", v, l); - return encoders._default(v, l); - } - - function encode_obj(val, expand) { - if(expand <= 0) { return val.toString(); } - var r = []; - for(var i in val) { - r.push(i + ": " + enc(val[i], expand - 1, false)); - } - return r.join(",\n"); - } - - function encode_reg(s) { - return s.replace(/([\\/\t\n])/g, "\\$1"); - } - - function reg_lookup_fn(lookup) { - var re = new RegExp(encode_reg(keys(lookup).join("")), "ig"); - return re; - } - - function print(msg) { - var className = (typeof msg == "function") ? "cmd" : "print"; - msg = enc(msg, 3); - if(!msg) return; - var out = $($.PRE({"className":className}, msg)); - if(className == "cmd") { out.click(select_command); } - output.prepend(out); - } - - function logCommand(cmd, result) { - command_history.push(cmd); - if(result != undefined) { - output.prepend(jQuery.dump(result)); - } - $($.PRE({className:'cmd'}, cmd)).click(select_command).prependTo(output); - //print(result); - return cmd; - } - - function select_command() { - edit_command($(this).text()); - } - - function edit_command(cmd) { - input.val(cmd); - resize_input(); - input.get(0).select(); - } - - function log() { - var msg = args(arguments); - $("
            ").text(msg.join(", ")).prependTo(output); - } - - function resize_input() - { - setTimeout(do_resize, 0); - - function do_resize() { - var rows = input.val().split(/\n/).length - // + 1 // prevent scrollbar flickering in Mozilla - + (window.opera ? 1 : 0); // leave room for scrollbar in Opera - - // without this check, it is impossible to select text in Opera 7.60 or Opera 8.0. - if (input.attr("rows") != rows) - input.attr("rows", rows); - } - } - - var default_scope = { - "log": log, - "history": history, - alert: function(msg) { alert(msg); } - } - disable_functions(default_scope, "window,document,t1"); - - function disable_functions(obj, list) { - var list = list.split(","); - for(var i in list) { - obj[list[i]] = {}; - } - } - - return this; -}; - -jQuery.extend(jQuery.fn, { - "autoresize": function() - { - var thisp = this; - setTimeout(do_resize, 0); - - function do_resize() { - var s = thisp.val() || ""; - var rows = s.split(/\n/).length; - // + 1 // prevent scrollbar flickering in Mozilla - + (window.opera ? 1 : 0); // leave room for scrollbar in Opera - - // without this check, it is impossible to select text in Opera 7.60 or Opera 8.0. - if (thisp.attr("rows") != rows) - thisp.attr("rows", rows); - } - return this; - } -}) - - - -jQConsole.global_scope = this; -jQConsole.our_scope = {}; \ No newline at end of file diff --git a/public/javascripts/controls.js b/public/javascripts/controls.js deleted file mode 100644 index ca29aef..0000000 --- a/public/javascripts/controls.js +++ /dev/null @@ -1,963 +0,0 @@ -// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// (c) 2005-2008 Ivan Krstic (http://blogs.law.harvard.edu/ivan) -// (c) 2005-2008 Jon Tirsen (http://www.tirsen.com) -// Contributors: -// Richard Livsey -// Rahul Bhargava -// Rob Wills -// -// script.aculo.us is freely distributable under the terms of an MIT-style license. -// For details, see the script.aculo.us web site: http://script.aculo.us/ - -// Autocompleter.Base handles all the autocompletion functionality -// that's independent of the data source for autocompletion. This -// includes drawing the autocompletion menu, observing keyboard -// and mouse events, and similar. -// -// Specific autocompleters need to provide, at the very least, -// a getUpdatedChoices function that will be invoked every time -// the text inside the monitored textbox changes. This method -// should get the text for which to provide autocompletion by -// invoking this.getToken(), NOT by directly accessing -// this.element.value. This is to allow incremental tokenized -// autocompletion. Specific auto-completion logic (AJAX, etc) -// belongs in getUpdatedChoices. -// -// Tokenized incremental autocompletion is enabled automatically -// when an autocompleter is instantiated with the 'tokens' option -// in the options parameter, e.g.: -// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' }); -// will incrementally autocomplete with a comma as the token. -// Additionally, ',' in the above example can be replaced with -// a token array, e.g. { tokens: [',', '\n'] } which -// enables autocompletion on multiple tokens. This is most -// useful when one of the tokens is \n (a newline), as it -// allows smart autocompletion after linebreaks. - -if(typeof Effect == 'undefined') - throw("controls.js requires including script.aculo.us' effects.js library"); - -var Autocompleter = { }; -Autocompleter.Base = Class.create({ - baseInitialize: function(element, update, options) { - element = $(element); - this.element = element; - this.update = $(update); - this.hasFocus = false; - this.changed = false; - this.active = false; - this.index = 0; - this.entryCount = 0; - this.oldElementValue = this.element.value; - - if(this.setOptions) - this.setOptions(options); - else - this.options = options || { }; - - this.options.paramName = this.options.paramName || this.element.name; - this.options.tokens = this.options.tokens || []; - this.options.frequency = this.options.frequency || 0.4; - this.options.minChars = this.options.minChars || 1; - this.options.onShow = this.options.onShow || - function(element, update){ - if(!update.style.position || update.style.position=='absolute') { - update.style.position = 'absolute'; - Position.clone(element, update, { - setHeight: false, - offsetTop: element.offsetHeight - }); - } - Effect.Appear(update,{duration:0.15}); - }; - this.options.onHide = this.options.onHide || - function(element, update){ new Effect.Fade(update,{duration:0.15}) }; - - if(typeof(this.options.tokens) == 'string') - this.options.tokens = new Array(this.options.tokens); - // Force carriage returns as token delimiters anyway - if (!this.options.tokens.include('\n')) - this.options.tokens.push('\n'); - - this.observer = null; - - this.element.setAttribute('autocomplete','off'); - - Element.hide(this.update); - - Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this)); - Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this)); - }, - - show: function() { - if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update); - if(!this.iefix && - (Prototype.Browser.IE) && - (Element.getStyle(this.update, 'position')=='absolute')) { - new Insertion.After(this.update, - ''); - this.iefix = $(this.update.id+'_iefix'); - } - if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50); - }, - - fixIEOverlapping: function() { - Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)}); - this.iefix.style.zIndex = 1; - this.update.style.zIndex = 2; - Element.show(this.iefix); - }, - - hide: function() { - this.stopIndicator(); - if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update); - if(this.iefix) Element.hide(this.iefix); - }, - - startIndicator: function() { - if(this.options.indicator) Element.show(this.options.indicator); - }, - - stopIndicator: function() { - if(this.options.indicator) Element.hide(this.options.indicator); - }, - - onKeyPress: function(event) { - if(this.active) - switch(event.keyCode) { - case Event.KEY_TAB: - case Event.KEY_RETURN: - this.selectEntry(); - Event.stop(event); - case Event.KEY_ESC: - this.hide(); - this.active = false; - Event.stop(event); - return; - case Event.KEY_LEFT: - case Event.KEY_RIGHT: - return; - case Event.KEY_UP: - this.markPrevious(); - this.render(); - Event.stop(event); - return; - case Event.KEY_DOWN: - this.markNext(); - this.render(); - Event.stop(event); - return; - } - else - if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || - (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return; - - this.changed = true; - this.hasFocus = true; - - if(this.observer) clearTimeout(this.observer); - this.observer = - setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); - }, - - activate: function() { - this.changed = false; - this.hasFocus = true; - this.getUpdatedChoices(); - }, - - onHover: function(event) { - var element = Event.findElement(event, 'LI'); - if(this.index != element.autocompleteIndex) - { - this.index = element.autocompleteIndex; - this.render(); - } - Event.stop(event); - }, - - onClick: function(event) { - var element = Event.findElement(event, 'LI'); - this.index = element.autocompleteIndex; - this.selectEntry(); - this.hide(); - }, - - onBlur: function(event) { - // needed to make click events working - setTimeout(this.hide.bind(this), 250); - this.hasFocus = false; - this.active = false; - }, - - render: function() { - if(this.entryCount > 0) { - for (var i = 0; i < this.entryCount; i++) - this.index==i ? - Element.addClassName(this.getEntry(i),"selected") : - Element.removeClassName(this.getEntry(i),"selected"); - if(this.hasFocus) { - this.show(); - this.active = true; - } - } else { - this.active = false; - this.hide(); - } - }, - - markPrevious: function() { - if(this.index > 0) this.index--; - else this.index = this.entryCount-1; - this.getEntry(this.index).scrollIntoView(true); - }, - - markNext: function() { - if(this.index < this.entryCount-1) this.index++; - else this.index = 0; - this.getEntry(this.index).scrollIntoView(false); - }, - - getEntry: function(index) { - return this.update.firstChild.childNodes[index]; - }, - - getCurrentEntry: function() { - return this.getEntry(this.index); - }, - - selectEntry: function() { - this.active = false; - this.updateElement(this.getCurrentEntry()); - }, - - updateElement: function(selectedElement) { - if (this.options.updateElement) { - this.options.updateElement(selectedElement); - return; - } - var value = ''; - if (this.options.select) { - var nodes = $(selectedElement).select('.' + this.options.select) || []; - if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); - } else - value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); - - var bounds = this.getTokenBounds(); - if (bounds[0] != -1) { - var newValue = this.element.value.substr(0, bounds[0]); - var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/); - if (whitespace) - newValue += whitespace[0]; - this.element.value = newValue + value + this.element.value.substr(bounds[1]); - } else { - this.element.value = value; - } - this.oldElementValue = this.element.value; - this.element.focus(); - - if (this.options.afterUpdateElement) - this.options.afterUpdateElement(this.element, selectedElement); - }, - - updateChoices: function(choices) { - if(!this.changed && this.hasFocus) { - this.update.innerHTML = choices; - Element.cleanWhitespace(this.update); - Element.cleanWhitespace(this.update.down()); - - if(this.update.firstChild && this.update.down().childNodes) { - this.entryCount = - this.update.down().childNodes.length; - for (var i = 0; i < this.entryCount; i++) { - var entry = this.getEntry(i); - entry.autocompleteIndex = i; - this.addObservers(entry); - } - } else { - this.entryCount = 0; - } - - this.stopIndicator(); - this.index = 0; - - if(this.entryCount==1 && this.options.autoSelect) { - this.selectEntry(); - this.hide(); - } else { - this.render(); - } - } - }, - - addObservers: function(element) { - Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this)); - Event.observe(element, "click", this.onClick.bindAsEventListener(this)); - }, - - onObserverEvent: function() { - this.changed = false; - this.tokenBounds = null; - if(this.getToken().length>=this.options.minChars) { - this.getUpdatedChoices(); - } else { - this.active = false; - this.hide(); - } - this.oldElementValue = this.element.value; - }, - - getToken: function() { - var bounds = this.getTokenBounds(); - return this.element.value.substring(bounds[0], bounds[1]).strip(); - }, - - getTokenBounds: function() { - if (null != this.tokenBounds) return this.tokenBounds; - var value = this.element.value; - if (value.strip().empty()) return [-1, 0]; - var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue); - var offset = (diff == this.oldElementValue.length ? 1 : 0); - var prevTokenPos = -1, nextTokenPos = value.length; - var tp; - for (var index = 0, l = this.options.tokens.length; index < l; ++index) { - tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1); - if (tp > prevTokenPos) prevTokenPos = tp; - tp = value.indexOf(this.options.tokens[index], diff + offset); - if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp; - } - return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]); - } -}); - -Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) { - var boundary = Math.min(newS.length, oldS.length); - for (var index = 0; index < boundary; ++index) - if (newS[index] != oldS[index]) - return index; - return boundary; -}; - -Ajax.Autocompleter = Class.create(Autocompleter.Base, { - initialize: function(element, update, url, options) { - this.baseInitialize(element, update, options); - this.options.asynchronous = true; - this.options.onComplete = this.onComplete.bind(this); - this.options.defaultParams = this.options.parameters || null; - this.url = url; - }, - - getUpdatedChoices: function() { - this.startIndicator(); - - var entry = encodeURIComponent(this.options.paramName) + '=' + - encodeURIComponent(this.getToken()); - - this.options.parameters = this.options.callback ? - this.options.callback(this.element, entry) : entry; - - if(this.options.defaultParams) - this.options.parameters += '&' + this.options.defaultParams; - - new Ajax.Request(this.url, this.options); - }, - - onComplete: function(request) { - this.updateChoices(request.responseText); - } -}); - -// The local array autocompleter. Used when you'd prefer to -// inject an array of autocompletion options into the page, rather -// than sending out Ajax queries, which can be quite slow sometimes. -// -// The constructor takes four parameters. The first two are, as usual, -// the id of the monitored textbox, and id of the autocompletion menu. -// The third is the array you want to autocomplete from, and the fourth -// is the options block. -// -// Extra local autocompletion options: -// - choices - How many autocompletion choices to offer -// -// - partialSearch - If false, the autocompleter will match entered -// text only at the beginning of strings in the -// autocomplete array. Defaults to true, which will -// match text at the beginning of any *word* in the -// strings in the autocomplete array. If you want to -// search anywhere in the string, additionally set -// the option fullSearch to true (default: off). -// -// - fullSsearch - Search anywhere in autocomplete array strings. -// -// - partialChars - How many characters to enter before triggering -// a partial match (unlike minChars, which defines -// how many characters are required to do any match -// at all). Defaults to 2. -// -// - ignoreCase - Whether to ignore case when autocompleting. -// Defaults to true. -// -// It's possible to pass in a custom function as the 'selector' -// option, if you prefer to write your own autocompletion logic. -// In that case, the other options above will not apply unless -// you support them. - -Autocompleter.Local = Class.create(Autocompleter.Base, { - initialize: function(element, update, array, options) { - this.baseInitialize(element, update, options); - this.options.array = array; - }, - - getUpdatedChoices: function() { - this.updateChoices(this.options.selector(this)); - }, - - setOptions: function(options) { - this.options = Object.extend({ - choices: 10, - partialSearch: true, - partialChars: 2, - ignoreCase: true, - fullSearch: false, - selector: function(instance) { - var ret = []; // Beginning matches - var partial = []; // Inside matches - var entry = instance.getToken(); - var count = 0; - - for (var i = 0; i < instance.options.array.length && - ret.length < instance.options.choices ; i++) { - - var elem = instance.options.array[i]; - var foundPos = instance.options.ignoreCase ? - elem.toLowerCase().indexOf(entry.toLowerCase()) : - elem.indexOf(entry); - - while (foundPos != -1) { - if (foundPos == 0 && elem.length != entry.length) { - ret.push("
          8. " + elem.substr(0, entry.length) + "" + - elem.substr(entry.length) + "
          9. "); - break; - } else if (entry.length >= instance.options.partialChars && - instance.options.partialSearch && foundPos != -1) { - if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) { - partial.push("
          10. " + elem.substr(0, foundPos) + "" + - elem.substr(foundPos, entry.length) + "" + elem.substr( - foundPos + entry.length) + "
          11. "); - break; - } - } - - foundPos = instance.options.ignoreCase ? - elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : - elem.indexOf(entry, foundPos + 1); - - } - } - if (partial.length) - ret = ret.concat(partial.slice(0, instance.options.choices - ret.length)); - return "
              " + ret.join('') + "
            "; - } - }, options || { }); - } -}); - -// AJAX in-place editor and collection editor -// Full rewrite by Christophe Porteneuve (April 2007). - -// Use this if you notice weird scrolling problems on some browsers, -// the DOM might be a bit confused when this gets called so do this -// waits 1 ms (with setTimeout) until it does the activation -Field.scrollFreeActivate = function(field) { - setTimeout(function() { - Field.activate(field); - }, 1); -}; - -Ajax.InPlaceEditor = Class.create({ - initialize: function(element, url, options) { - this.url = url; - this.element = element = $(element); - this.prepareOptions(); - this._controls = { }; - arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!! - Object.extend(this.options, options || { }); - if (!this.options.formId && this.element.id) { - this.options.formId = this.element.id + '-inplaceeditor'; - if ($(this.options.formId)) - this.options.formId = ''; - } - if (this.options.externalControl) - this.options.externalControl = $(this.options.externalControl); - if (!this.options.externalControl) - this.options.externalControlOnly = false; - this._originalBackground = this.element.getStyle('background-color') || 'transparent'; - this.element.title = this.options.clickToEditText; - this._boundCancelHandler = this.handleFormCancellation.bind(this); - this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this); - this._boundFailureHandler = this.handleAJAXFailure.bind(this); - this._boundSubmitHandler = this.handleFormSubmission.bind(this); - this._boundWrapperHandler = this.wrapUp.bind(this); - this.registerListeners(); - }, - checkForEscapeOrReturn: function(e) { - if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return; - if (Event.KEY_ESC == e.keyCode) - this.handleFormCancellation(e); - else if (Event.KEY_RETURN == e.keyCode) - this.handleFormSubmission(e); - }, - createControl: function(mode, handler, extraClasses) { - var control = this.options[mode + 'Control']; - var text = this.options[mode + 'Text']; - if ('button' == control) { - var btn = document.createElement('input'); - btn.type = 'submit'; - btn.value = text; - btn.className = 'editor_' + mode + '_button'; - if ('cancel' == mode) - btn.onclick = this._boundCancelHandler; - this._form.appendChild(btn); - this._controls[mode] = btn; - } else if ('link' == control) { - var link = document.createElement('a'); - link.href = '#'; - link.appendChild(document.createTextNode(text)); - link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler; - link.className = 'editor_' + mode + '_link'; - if (extraClasses) - link.className += ' ' + extraClasses; - this._form.appendChild(link); - this._controls[mode] = link; - } - }, - createEditField: function() { - var text = (this.options.loadTextURL ? this.options.loadingText : this.getText()); - var fld; - if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) { - fld = document.createElement('input'); - fld.type = 'text'; - var size = this.options.size || this.options.cols || 0; - if (0 < size) fld.size = size; - } else { - fld = document.createElement('textarea'); - fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows); - fld.cols = this.options.cols || 40; - } - fld.name = this.options.paramName; - fld.value = text; // No HTML breaks conversion anymore - fld.className = 'editor_field'; - if (this.options.submitOnBlur) - fld.onblur = this._boundSubmitHandler; - this._controls.editor = fld; - if (this.options.loadTextURL) - this.loadExternalText(); - this._form.appendChild(this._controls.editor); - }, - createForm: function() { - var ipe = this; - function addText(mode, condition) { - var text = ipe.options['text' + mode + 'Controls']; - if (!text || condition === false) return; - ipe._form.appendChild(document.createTextNode(text)); - }; - this._form = $(document.createElement('form')); - this._form.id = this.options.formId; - this._form.addClassName(this.options.formClassName); - this._form.onsubmit = this._boundSubmitHandler; - this.createEditField(); - if ('textarea' == this._controls.editor.tagName.toLowerCase()) - this._form.appendChild(document.createElement('br')); - if (this.options.onFormCustomization) - this.options.onFormCustomization(this, this._form); - addText('Before', this.options.okControl || this.options.cancelControl); - this.createControl('ok', this._boundSubmitHandler); - addText('Between', this.options.okControl && this.options.cancelControl); - this.createControl('cancel', this._boundCancelHandler, 'editor_cancel'); - addText('After', this.options.okControl || this.options.cancelControl); - }, - destroy: function() { - if (this._oldInnerHTML) - this.element.innerHTML = this._oldInnerHTML; - this.leaveEditMode(); - this.unregisterListeners(); - }, - enterEditMode: function(e) { - if (this._saving || this._editing) return; - this._editing = true; - this.triggerCallback('onEnterEditMode'); - if (this.options.externalControl) - this.options.externalControl.hide(); - this.element.hide(); - this.createForm(); - this.element.parentNode.insertBefore(this._form, this.element); - if (!this.options.loadTextURL) - this.postProcessEditField(); - if (e) Event.stop(e); - }, - enterHover: function(e) { - if (this.options.hoverClassName) - this.element.addClassName(this.options.hoverClassName); - if (this._saving) return; - this.triggerCallback('onEnterHover'); - }, - getText: function() { - return this.element.innerHTML.unescapeHTML(); - }, - handleAJAXFailure: function(transport) { - this.triggerCallback('onFailure', transport); - if (this._oldInnerHTML) { - this.element.innerHTML = this._oldInnerHTML; - this._oldInnerHTML = null; - } - }, - handleFormCancellation: function(e) { - this.wrapUp(); - if (e) Event.stop(e); - }, - handleFormSubmission: function(e) { - var form = this._form; - var value = $F(this._controls.editor); - this.prepareSubmission(); - var params = this.options.callback(form, value) || ''; - if (Object.isString(params)) - params = params.toQueryParams(); - params.editorId = this.element.id; - if (this.options.htmlResponse) { - var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions); - Object.extend(options, { - parameters: params, - onComplete: this._boundWrapperHandler, - onFailure: this._boundFailureHandler - }); - new Ajax.Updater({ success: this.element }, this.url, options); - } else { - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: params, - onComplete: this._boundWrapperHandler, - onFailure: this._boundFailureHandler - }); - new Ajax.Request(this.url, options); - } - if (e) Event.stop(e); - }, - leaveEditMode: function() { - this.element.removeClassName(this.options.savingClassName); - this.removeForm(); - this.leaveHover(); - this.element.style.backgroundColor = this._originalBackground; - this.element.show(); - if (this.options.externalControl) - this.options.externalControl.show(); - this._saving = false; - this._editing = false; - this._oldInnerHTML = null; - this.triggerCallback('onLeaveEditMode'); - }, - leaveHover: function(e) { - if (this.options.hoverClassName) - this.element.removeClassName(this.options.hoverClassName); - if (this._saving) return; - this.triggerCallback('onLeaveHover'); - }, - loadExternalText: function() { - this._form.addClassName(this.options.loadingClassName); - this._controls.editor.disabled = true; - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: 'editorId=' + encodeURIComponent(this.element.id), - onComplete: Prototype.emptyFunction, - onSuccess: function(transport) { - this._form.removeClassName(this.options.loadingClassName); - var text = transport.responseText; - if (this.options.stripLoadedTextTags) - text = text.stripTags(); - this._controls.editor.value = text; - this._controls.editor.disabled = false; - this.postProcessEditField(); - }.bind(this), - onFailure: this._boundFailureHandler - }); - new Ajax.Request(this.options.loadTextURL, options); - }, - postProcessEditField: function() { - var fpc = this.options.fieldPostCreation; - if (fpc) - $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate'](); - }, - prepareOptions: function() { - this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions); - Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks); - [this._extraDefaultOptions].flatten().compact().each(function(defs) { - Object.extend(this.options, defs); - }.bind(this)); - }, - prepareSubmission: function() { - this._saving = true; - this.removeForm(); - this.leaveHover(); - this.showSaving(); - }, - registerListeners: function() { - this._listeners = { }; - var listener; - $H(Ajax.InPlaceEditor.Listeners).each(function(pair) { - listener = this[pair.value].bind(this); - this._listeners[pair.key] = listener; - if (!this.options.externalControlOnly) - this.element.observe(pair.key, listener); - if (this.options.externalControl) - this.options.externalControl.observe(pair.key, listener); - }.bind(this)); - }, - removeForm: function() { - if (!this._form) return; - this._form.remove(); - this._form = null; - this._controls = { }; - }, - showSaving: function() { - this._oldInnerHTML = this.element.innerHTML; - this.element.innerHTML = this.options.savingText; - this.element.addClassName(this.options.savingClassName); - this.element.style.backgroundColor = this._originalBackground; - this.element.show(); - }, - triggerCallback: function(cbName, arg) { - if ('function' == typeof this.options[cbName]) { - this.options[cbName](this, arg); - } - }, - unregisterListeners: function() { - $H(this._listeners).each(function(pair) { - if (!this.options.externalControlOnly) - this.element.stopObserving(pair.key, pair.value); - if (this.options.externalControl) - this.options.externalControl.stopObserving(pair.key, pair.value); - }.bind(this)); - }, - wrapUp: function(transport) { - this.leaveEditMode(); - // Can't use triggerCallback due to backward compatibility: requires - // binding + direct element - this._boundComplete(transport, this.element); - } -}); - -Object.extend(Ajax.InPlaceEditor.prototype, { - dispose: Ajax.InPlaceEditor.prototype.destroy -}); - -Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, { - initialize: function($super, element, url, options) { - this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions; - $super(element, url, options); - }, - - createEditField: function() { - var list = document.createElement('select'); - list.name = this.options.paramName; - list.size = 1; - this._controls.editor = list; - this._collection = this.options.collection || []; - if (this.options.loadCollectionURL) - this.loadCollection(); - else - this.checkForExternalText(); - this._form.appendChild(this._controls.editor); - }, - - loadCollection: function() { - this._form.addClassName(this.options.loadingClassName); - this.showLoadingText(this.options.loadingCollectionText); - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: 'editorId=' + encodeURIComponent(this.element.id), - onComplete: Prototype.emptyFunction, - onSuccess: function(transport) { - var js = transport.responseText.strip(); - if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check - throw('Server returned an invalid collection representation.'); - this._collection = eval(js); - this.checkForExternalText(); - }.bind(this), - onFailure: this.onFailure - }); - new Ajax.Request(this.options.loadCollectionURL, options); - }, - - showLoadingText: function(text) { - this._controls.editor.disabled = true; - var tempOption = this._controls.editor.firstChild; - if (!tempOption) { - tempOption = document.createElement('option'); - tempOption.value = ''; - this._controls.editor.appendChild(tempOption); - tempOption.selected = true; - } - tempOption.update((text || '').stripScripts().stripTags()); - }, - - checkForExternalText: function() { - this._text = this.getText(); - if (this.options.loadTextURL) - this.loadExternalText(); - else - this.buildOptionList(); - }, - - loadExternalText: function() { - this.showLoadingText(this.options.loadingText); - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: 'editorId=' + encodeURIComponent(this.element.id), - onComplete: Prototype.emptyFunction, - onSuccess: function(transport) { - this._text = transport.responseText.strip(); - this.buildOptionList(); - }.bind(this), - onFailure: this.onFailure - }); - new Ajax.Request(this.options.loadTextURL, options); - }, - - buildOptionList: function() { - this._form.removeClassName(this.options.loadingClassName); - this._collection = this._collection.map(function(entry) { - return 2 === entry.length ? entry : [entry, entry].flatten(); - }); - var marker = ('value' in this.options) ? this.options.value : this._text; - var textFound = this._collection.any(function(entry) { - return entry[0] == marker; - }.bind(this)); - this._controls.editor.update(''); - var option; - this._collection.each(function(entry, index) { - option = document.createElement('option'); - option.value = entry[0]; - option.selected = textFound ? entry[0] == marker : 0 == index; - option.appendChild(document.createTextNode(entry[1])); - this._controls.editor.appendChild(option); - }.bind(this)); - this._controls.editor.disabled = false; - Field.scrollFreeActivate(this._controls.editor); - } -}); - -//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! **** -//**** This only exists for a while, in order to let **** -//**** users adapt to the new API. Read up on the new **** -//**** API and convert your code to it ASAP! **** - -Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) { - if (!options) return; - function fallback(name, expr) { - if (name in options || expr === undefined) return; - options[name] = expr; - }; - fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' : - options.cancelLink == options.cancelButton == false ? false : undefined))); - fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' : - options.okLink == options.okButton == false ? false : undefined))); - fallback('highlightColor', options.highlightcolor); - fallback('highlightEndColor', options.highlightendcolor); -}; - -Object.extend(Ajax.InPlaceEditor, { - DefaultOptions: { - ajaxOptions: { }, - autoRows: 3, // Use when multi-line w/ rows == 1 - cancelControl: 'link', // 'link'|'button'|false - cancelText: 'cancel', - clickToEditText: 'Click to edit', - externalControl: null, // id|elt - externalControlOnly: false, - fieldPostCreation: 'activate', // 'activate'|'focus'|false - formClassName: 'inplaceeditor-form', - formId: null, // id|elt - highlightColor: '#ffff99', - highlightEndColor: '#ffffff', - hoverClassName: '', - htmlResponse: true, - loadingClassName: 'inplaceeditor-loading', - loadingText: 'Loading...', - okControl: 'button', // 'link'|'button'|false - okText: 'ok', - paramName: 'value', - rows: 1, // If 1 and multi-line, uses autoRows - savingClassName: 'inplaceeditor-saving', - savingText: 'Saving...', - size: 0, - stripLoadedTextTags: false, - submitOnBlur: false, - textAfterControls: '', - textBeforeControls: '', - textBetweenControls: '' - }, - DefaultCallbacks: { - callback: function(form) { - return Form.serialize(form); - }, - onComplete: function(transport, element) { - // For backward compatibility, this one is bound to the IPE, and passes - // the element directly. It was too often customized, so we don't break it. - new Effect.Highlight(element, { - startcolor: this.options.highlightColor, keepBackgroundImage: true }); - }, - onEnterEditMode: null, - onEnterHover: function(ipe) { - ipe.element.style.backgroundColor = ipe.options.highlightColor; - if (ipe._effect) - ipe._effect.cancel(); - }, - onFailure: function(transport, ipe) { - alert('Error communication with the server: ' + transport.responseText.stripTags()); - }, - onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls. - onLeaveEditMode: null, - onLeaveHover: function(ipe) { - ipe._effect = new Effect.Highlight(ipe.element, { - startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor, - restorecolor: ipe._originalBackground, keepBackgroundImage: true - }); - } - }, - Listeners: { - click: 'enterEditMode', - keydown: 'checkForEscapeOrReturn', - mouseover: 'enterHover', - mouseout: 'leaveHover' - } -}); - -Ajax.InPlaceCollectionEditor.DefaultOptions = { - loadingCollectionText: 'Loading options...' -}; - -// Delayed observer, like Form.Element.Observer, -// but waits for delay after last key input -// Ideal for live-search fields - -Form.Element.DelayedObserver = Class.create({ - initialize: function(element, delay, callback) { - this.delay = delay || 0.5; - this.element = $(element); - this.callback = callback; - this.timer = null; - this.lastValue = $F(this.element); - Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this)); - }, - delayedListener: function(event) { - if(this.lastValue == $F(this.element)) return; - if(this.timer) clearTimeout(this.timer); - this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000); - this.lastValue = $F(this.element); - }, - onTimerEvent: function() { - this.timer = null; - this.callback(this.element, $F(this.element)); - } -}); \ No newline at end of file diff --git a/public/javascripts/dragdrop.js b/public/javascripts/dragdrop.js deleted file mode 100644 index 07229f9..0000000 --- a/public/javascripts/dragdrop.js +++ /dev/null @@ -1,973 +0,0 @@ -// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// (c) 2005-2008 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz) -// -// script.aculo.us is freely distributable under the terms of an MIT-style license. -// For details, see the script.aculo.us web site: http://script.aculo.us/ - -if(Object.isUndefined(Effect)) - throw("dragdrop.js requires including script.aculo.us' effects.js library"); - -var Droppables = { - drops: [], - - remove: function(element) { - this.drops = this.drops.reject(function(d) { return d.element==$(element) }); - }, - - add: function(element) { - element = $(element); - var options = Object.extend({ - greedy: true, - hoverclass: null, - tree: false - }, arguments[1] || { }); - - // cache containers - if(options.containment) { - options._containers = []; - var containment = options.containment; - if(Object.isArray(containment)) { - containment.each( function(c) { options._containers.push($(c)) }); - } else { - options._containers.push($(containment)); - } - } - - if(options.accept) options.accept = [options.accept].flatten(); - - Element.makePositioned(element); // fix IE - options.element = element; - - this.drops.push(options); - }, - - findDeepestChild: function(drops) { - deepest = drops[0]; - - for (i = 1; i < drops.length; ++i) - if (Element.isParent(drops[i].element, deepest.element)) - deepest = drops[i]; - - return deepest; - }, - - isContained: function(element, drop) { - var containmentNode; - if(drop.tree) { - containmentNode = element.treeNode; - } else { - containmentNode = element.parentNode; - } - return drop._containers.detect(function(c) { return containmentNode == c }); - }, - - isAffected: function(point, element, drop) { - return ( - (drop.element!=element) && - ((!drop._containers) || - this.isContained(element, drop)) && - ((!drop.accept) || - (Element.classNames(element).detect( - function(v) { return drop.accept.include(v) } ) )) && - Position.within(drop.element, point[0], point[1]) ); - }, - - deactivate: function(drop) { - if(drop.hoverclass) - Element.removeClassName(drop.element, drop.hoverclass); - this.last_active = null; - }, - - activate: function(drop) { - if(drop.hoverclass) - Element.addClassName(drop.element, drop.hoverclass); - this.last_active = drop; - }, - - show: function(point, element) { - if(!this.drops.length) return; - var drop, affected = []; - - this.drops.each( function(drop) { - if(Droppables.isAffected(point, element, drop)) - affected.push(drop); - }); - - if(affected.length>0) - drop = Droppables.findDeepestChild(affected); - - if(this.last_active && this.last_active != drop) this.deactivate(this.last_active); - if (drop) { - Position.within(drop.element, point[0], point[1]); - if(drop.onHover) - drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); - - if (drop != this.last_active) Droppables.activate(drop); - } - }, - - fire: function(event, element) { - if(!this.last_active) return; - Position.prepare(); - - if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active)) - if (this.last_active.onDrop) { - this.last_active.onDrop(element, this.last_active.element, event); - return true; - } - }, - - reset: function() { - if(this.last_active) - this.deactivate(this.last_active); - } -}; - -var Draggables = { - drags: [], - observers: [], - - register: function(draggable) { - if(this.drags.length == 0) { - this.eventMouseUp = this.endDrag.bindAsEventListener(this); - this.eventMouseMove = this.updateDrag.bindAsEventListener(this); - this.eventKeypress = this.keyPress.bindAsEventListener(this); - - Event.observe(document, "mouseup", this.eventMouseUp); - Event.observe(document, "mousemove", this.eventMouseMove); - Event.observe(document, "keypress", this.eventKeypress); - } - this.drags.push(draggable); - }, - - unregister: function(draggable) { - this.drags = this.drags.reject(function(d) { return d==draggable }); - if(this.drags.length == 0) { - Event.stopObserving(document, "mouseup", this.eventMouseUp); - Event.stopObserving(document, "mousemove", this.eventMouseMove); - Event.stopObserving(document, "keypress", this.eventKeypress); - } - }, - - activate: function(draggable) { - if(draggable.options.delay) { - this._timeout = setTimeout(function() { - Draggables._timeout = null; - window.focus(); - Draggables.activeDraggable = draggable; - }.bind(this), draggable.options.delay); - } else { - window.focus(); // allows keypress events if window isn't currently focused, fails for Safari - this.activeDraggable = draggable; - } - }, - - deactivate: function() { - this.activeDraggable = null; - }, - - updateDrag: function(event) { - if(!this.activeDraggable) return; - var pointer = [Event.pointerX(event), Event.pointerY(event)]; - // Mozilla-based browsers fire successive mousemove events with - // the same coordinates, prevent needless redrawing (moz bug?) - if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return; - this._lastPointer = pointer; - - this.activeDraggable.updateDrag(event, pointer); - }, - - endDrag: function(event) { - if(this._timeout) { - clearTimeout(this._timeout); - this._timeout = null; - } - if(!this.activeDraggable) return; - this._lastPointer = null; - this.activeDraggable.endDrag(event); - this.activeDraggable = null; - }, - - keyPress: function(event) { - if(this.activeDraggable) - this.activeDraggable.keyPress(event); - }, - - addObserver: function(observer) { - this.observers.push(observer); - this._cacheObserverCallbacks(); - }, - - removeObserver: function(element) { // element instead of observer fixes mem leaks - this.observers = this.observers.reject( function(o) { return o.element==element }); - this._cacheObserverCallbacks(); - }, - - notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag' - if(this[eventName+'Count'] > 0) - this.observers.each( function(o) { - if(o[eventName]) o[eventName](eventName, draggable, event); - }); - if(draggable.options[eventName]) draggable.options[eventName](draggable, event); - }, - - _cacheObserverCallbacks: function() { - ['onStart','onEnd','onDrag'].each( function(eventName) { - Draggables[eventName+'Count'] = Draggables.observers.select( - function(o) { return o[eventName]; } - ).length; - }); - } -}; - -/*--------------------------------------------------------------------------*/ - -var Draggable = Class.create({ - initialize: function(element) { - var defaults = { - handle: false, - reverteffect: function(element, top_offset, left_offset) { - var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02; - new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur, - queue: {scope:'_draggable', position:'end'} - }); - }, - endeffect: function(element) { - var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0; - new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity, - queue: {scope:'_draggable', position:'end'}, - afterFinish: function(){ - Draggable._dragging[element] = false - } - }); - }, - zindex: 1000, - revert: false, - quiet: false, - scroll: false, - scrollSensitivity: 20, - scrollSpeed: 15, - snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] } - delay: 0 - }; - - if(!arguments[1] || Object.isUndefined(arguments[1].endeffect)) - Object.extend(defaults, { - starteffect: function(element) { - element._opacity = Element.getOpacity(element); - Draggable._dragging[element] = true; - new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7}); - } - }); - - var options = Object.extend(defaults, arguments[1] || { }); - - this.element = $(element); - - if(options.handle && Object.isString(options.handle)) - this.handle = this.element.down('.'+options.handle, 0); - - if(!this.handle) this.handle = $(options.handle); - if(!this.handle) this.handle = this.element; - - if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) { - options.scroll = $(options.scroll); - this._isScrollChild = Element.childOf(this.element, options.scroll); - } - - Element.makePositioned(this.element); // fix IE - - this.options = options; - this.dragging = false; - - this.eventMouseDown = this.initDrag.bindAsEventListener(this); - Event.observe(this.handle, "mousedown", this.eventMouseDown); - - Draggables.register(this); - }, - - destroy: function() { - Event.stopObserving(this.handle, "mousedown", this.eventMouseDown); - Draggables.unregister(this); - }, - - currentDelta: function() { - return([ - parseInt(Element.getStyle(this.element,'left') || '0'), - parseInt(Element.getStyle(this.element,'top') || '0')]); - }, - - initDrag: function(event) { - if(!Object.isUndefined(Draggable._dragging[this.element]) && - Draggable._dragging[this.element]) return; - if(Event.isLeftClick(event)) { - // abort on form elements, fixes a Firefox issue - var src = Event.element(event); - if((tag_name = src.tagName.toUpperCase()) && ( - tag_name=='INPUT' || - tag_name=='SELECT' || - tag_name=='OPTION' || - tag_name=='BUTTON' || - tag_name=='TEXTAREA')) return; - - var pointer = [Event.pointerX(event), Event.pointerY(event)]; - var pos = Position.cumulativeOffset(this.element); - this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) }); - - Draggables.activate(this); - Event.stop(event); - } - }, - - startDrag: function(event) { - this.dragging = true; - if(!this.delta) - this.delta = this.currentDelta(); - - if(this.options.zindex) { - this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0); - this.element.style.zIndex = this.options.zindex; - } - - if(this.options.ghosting) { - this._clone = this.element.cloneNode(true); - this._originallyAbsolute = (this.element.getStyle('position') == 'absolute'); - if (!this._originallyAbsolute) - Position.absolutize(this.element); - this.element.parentNode.insertBefore(this._clone, this.element); - } - - if(this.options.scroll) { - if (this.options.scroll == window) { - var where = this._getWindowScroll(this.options.scroll); - this.originalScrollLeft = where.left; - this.originalScrollTop = where.top; - } else { - this.originalScrollLeft = this.options.scroll.scrollLeft; - this.originalScrollTop = this.options.scroll.scrollTop; - } - } - - Draggables.notify('onStart', this, event); - - if(this.options.starteffect) this.options.starteffect(this.element); - }, - - updateDrag: function(event, pointer) { - if(!this.dragging) this.startDrag(event); - - if(!this.options.quiet){ - Position.prepare(); - Droppables.show(pointer, this.element); - } - - Draggables.notify('onDrag', this, event); - - this.draw(pointer); - if(this.options.change) this.options.change(this); - - if(this.options.scroll) { - this.stopScrolling(); - - var p; - if (this.options.scroll == window) { - with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; } - } else { - p = Position.page(this.options.scroll); - p[0] += this.options.scroll.scrollLeft + Position.deltaX; - p[1] += this.options.scroll.scrollTop + Position.deltaY; - p.push(p[0]+this.options.scroll.offsetWidth); - p.push(p[1]+this.options.scroll.offsetHeight); - } - var speed = [0,0]; - if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity); - if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity); - if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity); - if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity); - this.startScrolling(speed); - } - - // fix AppleWebKit rendering - if(Prototype.Browser.WebKit) window.scrollBy(0,0); - - Event.stop(event); - }, - - finishDrag: function(event, success) { - this.dragging = false; - - if(this.options.quiet){ - Position.prepare(); - var pointer = [Event.pointerX(event), Event.pointerY(event)]; - Droppables.show(pointer, this.element); - } - - if(this.options.ghosting) { - if (!this._originallyAbsolute) - Position.relativize(this.element); - delete this._originallyAbsolute; - Element.remove(this._clone); - this._clone = null; - } - - var dropped = false; - if(success) { - dropped = Droppables.fire(event, this.element); - if (!dropped) dropped = false; - } - if(dropped && this.options.onDropped) this.options.onDropped(this.element); - Draggables.notify('onEnd', this, event); - - var revert = this.options.revert; - if(revert && Object.isFunction(revert)) revert = revert(this.element); - - var d = this.currentDelta(); - if(revert && this.options.reverteffect) { - if (dropped == 0 || revert != 'failure') - this.options.reverteffect(this.element, - d[1]-this.delta[1], d[0]-this.delta[0]); - } else { - this.delta = d; - } - - if(this.options.zindex) - this.element.style.zIndex = this.originalZ; - - if(this.options.endeffect) - this.options.endeffect(this.element); - - Draggables.deactivate(this); - Droppables.reset(); - }, - - keyPress: function(event) { - if(event.keyCode!=Event.KEY_ESC) return; - this.finishDrag(event, false); - Event.stop(event); - }, - - endDrag: function(event) { - if(!this.dragging) return; - this.stopScrolling(); - this.finishDrag(event, true); - Event.stop(event); - }, - - draw: function(point) { - var pos = Position.cumulativeOffset(this.element); - if(this.options.ghosting) { - var r = Position.realOffset(this.element); - pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY; - } - - var d = this.currentDelta(); - pos[0] -= d[0]; pos[1] -= d[1]; - - if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) { - pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft; - pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop; - } - - var p = [0,1].map(function(i){ - return (point[i]-pos[i]-this.offset[i]) - }.bind(this)); - - if(this.options.snap) { - if(Object.isFunction(this.options.snap)) { - p = this.options.snap(p[0],p[1],this); - } else { - if(Object.isArray(this.options.snap)) { - p = p.map( function(v, i) { - return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this)); - } else { - p = p.map( function(v) { - return (v/this.options.snap).round()*this.options.snap }.bind(this)); - } - }} - - var style = this.element.style; - if((!this.options.constraint) || (this.options.constraint=='horizontal')) - style.left = p[0] + "px"; - if((!this.options.constraint) || (this.options.constraint=='vertical')) - style.top = p[1] + "px"; - - if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering - }, - - stopScrolling: function() { - if(this.scrollInterval) { - clearInterval(this.scrollInterval); - this.scrollInterval = null; - Draggables._lastScrollPointer = null; - } - }, - - startScrolling: function(speed) { - if(!(speed[0] || speed[1])) return; - this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed]; - this.lastScrolled = new Date(); - this.scrollInterval = setInterval(this.scroll.bind(this), 10); - }, - - scroll: function() { - var current = new Date(); - var delta = current - this.lastScrolled; - this.lastScrolled = current; - if(this.options.scroll == window) { - with (this._getWindowScroll(this.options.scroll)) { - if (this.scrollSpeed[0] || this.scrollSpeed[1]) { - var d = delta / 1000; - this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] ); - } - } - } else { - this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; - this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000; - } - - Position.prepare(); - Droppables.show(Draggables._lastPointer, this.element); - Draggables.notify('onDrag', this); - if (this._isScrollChild) { - Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer); - Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000; - Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000; - if (Draggables._lastScrollPointer[0] < 0) - Draggables._lastScrollPointer[0] = 0; - if (Draggables._lastScrollPointer[1] < 0) - Draggables._lastScrollPointer[1] = 0; - this.draw(Draggables._lastScrollPointer); - } - - if(this.options.change) this.options.change(this); - }, - - _getWindowScroll: function(w) { - var T, L, W, H; - with (w.document) { - if (w.document.documentElement && documentElement.scrollTop) { - T = documentElement.scrollTop; - L = documentElement.scrollLeft; - } else if (w.document.body) { - T = body.scrollTop; - L = body.scrollLeft; - } - if (w.innerWidth) { - W = w.innerWidth; - H = w.innerHeight; - } else if (w.document.documentElement && documentElement.clientWidth) { - W = documentElement.clientWidth; - H = documentElement.clientHeight; - } else { - W = body.offsetWidth; - H = body.offsetHeight; - } - } - return { top: T, left: L, width: W, height: H }; - } -}); - -Draggable._dragging = { }; - -/*--------------------------------------------------------------------------*/ - -var SortableObserver = Class.create({ - initialize: function(element, observer) { - this.element = $(element); - this.observer = observer; - this.lastValue = Sortable.serialize(this.element); - }, - - onStart: function() { - this.lastValue = Sortable.serialize(this.element); - }, - - onEnd: function() { - Sortable.unmark(); - if(this.lastValue != Sortable.serialize(this.element)) - this.observer(this.element) - } -}); - -var Sortable = { - SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/, - - sortables: { }, - - _findRootElement: function(element) { - while (element.tagName.toUpperCase() != "BODY") { - if(element.id && Sortable.sortables[element.id]) return element; - element = element.parentNode; - } - }, - - options: function(element) { - element = Sortable._findRootElement($(element)); - if(!element) return; - return Sortable.sortables[element.id]; - }, - - destroy: function(element){ - element = $(element); - var s = Sortable.sortables[element.id]; - - if(s) { - Draggables.removeObserver(s.element); - s.droppables.each(function(d){ Droppables.remove(d) }); - s.draggables.invoke('destroy'); - - delete Sortable.sortables[s.element.id]; - } - }, - - create: function(element) { - element = $(element); - var options = Object.extend({ - element: element, - tag: 'li', // assumes li children, override with tag: 'tagname' - dropOnEmpty: false, - tree: false, - treeTag: 'ul', - overlap: 'vertical', // one of 'vertical', 'horizontal' - constraint: 'vertical', // one of 'vertical', 'horizontal', false - containment: element, // also takes array of elements (or id's); or false - handle: false, // or a CSS class - only: false, - delay: 0, - hoverclass: null, - ghosting: false, - quiet: false, - scroll: false, - scrollSensitivity: 20, - scrollSpeed: 15, - format: this.SERIALIZE_RULE, - - // these take arrays of elements or ids and can be - // used for better initialization performance - elements: false, - handles: false, - - onChange: Prototype.emptyFunction, - onUpdate: Prototype.emptyFunction - }, arguments[1] || { }); - - // clear any old sortable with same element - this.destroy(element); - - // build options for the draggables - var options_for_draggable = { - revert: true, - quiet: options.quiet, - scroll: options.scroll, - scrollSpeed: options.scrollSpeed, - scrollSensitivity: options.scrollSensitivity, - delay: options.delay, - ghosting: options.ghosting, - constraint: options.constraint, - handle: options.handle }; - - if(options.starteffect) - options_for_draggable.starteffect = options.starteffect; - - if(options.reverteffect) - options_for_draggable.reverteffect = options.reverteffect; - else - if(options.ghosting) options_for_draggable.reverteffect = function(element) { - element.style.top = 0; - element.style.left = 0; - }; - - if(options.endeffect) - options_for_draggable.endeffect = options.endeffect; - - if(options.zindex) - options_for_draggable.zindex = options.zindex; - - // build options for the droppables - var options_for_droppable = { - overlap: options.overlap, - containment: options.containment, - tree: options.tree, - hoverclass: options.hoverclass, - onHover: Sortable.onHover - }; - - var options_for_tree = { - onHover: Sortable.onEmptyHover, - overlap: options.overlap, - containment: options.containment, - hoverclass: options.hoverclass - }; - - // fix for gecko engine - Element.cleanWhitespace(element); - - options.draggables = []; - options.droppables = []; - - // drop on empty handling - if(options.dropOnEmpty || options.tree) { - Droppables.add(element, options_for_tree); - options.droppables.push(element); - } - - (options.elements || this.findElements(element, options) || []).each( function(e,i) { - var handle = options.handles ? $(options.handles[i]) : - (options.handle ? $(e).select('.' + options.handle)[0] : e); - options.draggables.push( - new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); - Droppables.add(e, options_for_droppable); - if(options.tree) e.treeNode = element; - options.droppables.push(e); - }); - - if(options.tree) { - (Sortable.findTreeElements(element, options) || []).each( function(e) { - Droppables.add(e, options_for_tree); - e.treeNode = element; - options.droppables.push(e); - }); - } - - // keep reference - this.sortables[element.id] = options; - - // for onupdate - Draggables.addObserver(new SortableObserver(element, options.onUpdate)); - - }, - - // return all suitable-for-sortable elements in a guaranteed order - findElements: function(element, options) { - return Element.findChildren( - element, options.only, options.tree ? true : false, options.tag); - }, - - findTreeElements: function(element, options) { - return Element.findChildren( - element, options.only, options.tree ? true : false, options.treeTag); - }, - - onHover: function(element, dropon, overlap) { - if(Element.isParent(dropon, element)) return; - - if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) { - return; - } else if(overlap>0.5) { - Sortable.mark(dropon, 'before'); - if(dropon.previousSibling != element) { - var oldParentNode = element.parentNode; - element.style.visibility = "hidden"; // fix gecko rendering - dropon.parentNode.insertBefore(element, dropon); - if(dropon.parentNode!=oldParentNode) - Sortable.options(oldParentNode).onChange(element); - Sortable.options(dropon.parentNode).onChange(element); - } - } else { - Sortable.mark(dropon, 'after'); - var nextElement = dropon.nextSibling || null; - if(nextElement != element) { - var oldParentNode = element.parentNode; - element.style.visibility = "hidden"; // fix gecko rendering - dropon.parentNode.insertBefore(element, nextElement); - if(dropon.parentNode!=oldParentNode) - Sortable.options(oldParentNode).onChange(element); - Sortable.options(dropon.parentNode).onChange(element); - } - } - }, - - onEmptyHover: function(element, dropon, overlap) { - var oldParentNode = element.parentNode; - var droponOptions = Sortable.options(dropon); - - if(!Element.isParent(dropon, element)) { - var index; - - var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only}); - var child = null; - - if(children) { - var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap); - - for (index = 0; index < children.length; index += 1) { - if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) { - offset -= Element.offsetSize (children[index], droponOptions.overlap); - } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) { - child = index + 1 < children.length ? children[index + 1] : null; - break; - } else { - child = children[index]; - break; - } - } - } - - dropon.insertBefore(element, child); - - Sortable.options(oldParentNode).onChange(element); - droponOptions.onChange(element); - } - }, - - unmark: function() { - if(Sortable._marker) Sortable._marker.hide(); - }, - - mark: function(dropon, position) { - // mark on ghosting only - var sortable = Sortable.options(dropon.parentNode); - if(sortable && !sortable.ghosting) return; - - if(!Sortable._marker) { - Sortable._marker = - ($('dropmarker') || Element.extend(document.createElement('DIV'))). - hide().addClassName('dropmarker').setStyle({position:'absolute'}); - document.getElementsByTagName("body").item(0).appendChild(Sortable._marker); - } - var offsets = Position.cumulativeOffset(dropon); - Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'}); - - if(position=='after') - if(sortable.overlap == 'horizontal') - Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'}); - else - Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'}); - - Sortable._marker.show(); - }, - - _tree: function(element, options, parent) { - var children = Sortable.findElements(element, options) || []; - - for (var i = 0; i < children.length; ++i) { - var match = children[i].id.match(options.format); - - if (!match) continue; - - var child = { - id: encodeURIComponent(match ? match[1] : null), - element: element, - parent: parent, - children: [], - position: parent.children.length, - container: $(children[i]).down(options.treeTag) - }; - - /* Get the element containing the children and recurse over it */ - if (child.container) - this._tree(child.container, options, child); - - parent.children.push (child); - } - - return parent; - }, - - tree: function(element) { - element = $(element); - var sortableOptions = this.options(element); - var options = Object.extend({ - tag: sortableOptions.tag, - treeTag: sortableOptions.treeTag, - only: sortableOptions.only, - name: element.id, - format: sortableOptions.format - }, arguments[1] || { }); - - var root = { - id: null, - parent: null, - children: [], - container: element, - position: 0 - }; - - return Sortable._tree(element, options, root); - }, - - /* Construct a [i] index for a particular node */ - _constructIndex: function(node) { - var index = ''; - do { - if (node.id) index = '[' + node.position + ']' + index; - } while ((node = node.parent) != null); - return index; - }, - - sequence: function(element) { - element = $(element); - var options = Object.extend(this.options(element), arguments[1] || { }); - - return $(this.findElements(element, options) || []).map( function(item) { - return item.id.match(options.format) ? item.id.match(options.format)[1] : ''; - }); - }, - - setSequence: function(element, new_sequence) { - element = $(element); - var options = Object.extend(this.options(element), arguments[2] || { }); - - var nodeMap = { }; - this.findElements(element, options).each( function(n) { - if (n.id.match(options.format)) - nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode]; - n.parentNode.removeChild(n); - }); - - new_sequence.each(function(ident) { - var n = nodeMap[ident]; - if (n) { - n[1].appendChild(n[0]); - delete nodeMap[ident]; - } - }); - }, - - serialize: function(element) { - element = $(element); - var options = Object.extend(Sortable.options(element), arguments[1] || { }); - var name = encodeURIComponent( - (arguments[1] && arguments[1].name) ? arguments[1].name : element.id); - - if (options.tree) { - return Sortable.tree(element, arguments[1]).children.map( function (item) { - return [name + Sortable._constructIndex(item) + "[id]=" + - encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)); - }).flatten().join('&'); - } else { - return Sortable.sequence(element, arguments[1]).map( function(item) { - return name + "[]=" + encodeURIComponent(item); - }).join('&'); - } - } -}; - -// Returns true if child is contained within element -Element.isParent = function(child, element) { - if (!child.parentNode || child == element) return false; - if (child.parentNode == element) return true; - return Element.isParent(child.parentNode, element); -}; - -Element.findChildren = function(element, only, recursive, tagName) { - if(!element.hasChildNodes()) return null; - tagName = tagName.toUpperCase(); - if(only) only = [only].flatten(); - var elements = []; - $A(element.childNodes).each( function(e) { - if(e.tagName && e.tagName.toUpperCase()==tagName && - (!only || (Element.classNames(e).detect(function(v) { return only.include(v) })))) - elements.push(e); - if(recursive) { - var grandchildren = Element.findChildren(e, only, recursive, tagName); - if(grandchildren) elements.push(grandchildren); - } - }); - - return (elements.length>0 ? elements.flatten() : []); -}; - -Element.offsetSize = function (element, type) { - return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')]; -}; \ No newline at end of file diff --git a/public/javascripts/effects.js b/public/javascripts/effects.js deleted file mode 100644 index 5a639d2..0000000 --- a/public/javascripts/effects.js +++ /dev/null @@ -1,1128 +0,0 @@ -// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// Contributors: -// Justin Palmer (http://encytemedia.com/) -// Mark Pilgrim (http://diveintomark.org/) -// Martin Bialasinki -// -// script.aculo.us is freely distributable under the terms of an MIT-style license. -// For details, see the script.aculo.us web site: http://script.aculo.us/ - -// converts rgb() and #xxx to #xxxxxx format, -// returns self (or first argument) if not convertable -String.prototype.parseColor = function() { - var color = '#'; - if (this.slice(0,4) == 'rgb(') { - var cols = this.slice(4,this.length-1).split(','); - var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); - } else { - if (this.slice(0,1) == '#') { - if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); - if (this.length==7) color = this.toLowerCase(); - } - } - return (color.length==7 ? color : (arguments[0] || this)); -}; - -/*--------------------------------------------------------------------------*/ - -Element.collectTextNodes = function(element) { - return $A($(element).childNodes).collect( function(node) { - return (node.nodeType==3 ? node.nodeValue : - (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); - }).flatten().join(''); -}; - -Element.collectTextNodesIgnoreClass = function(element, className) { - return $A($(element).childNodes).collect( function(node) { - return (node.nodeType==3 ? node.nodeValue : - ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? - Element.collectTextNodesIgnoreClass(node, className) : '')); - }).flatten().join(''); -}; - -Element.setContentZoom = function(element, percent) { - element = $(element); - element.setStyle({fontSize: (percent/100) + 'em'}); - if (Prototype.Browser.WebKit) window.scrollBy(0,0); - return element; -}; - -Element.getInlineOpacity = function(element){ - return $(element).style.opacity || ''; -}; - -Element.forceRerendering = function(element) { - try { - element = $(element); - var n = document.createTextNode(' '); - element.appendChild(n); - element.removeChild(n); - } catch(e) { } -}; - -/*--------------------------------------------------------------------------*/ - -var Effect = { - _elementDoesNotExistError: { - name: 'ElementDoesNotExistError', - message: 'The specified DOM element does not exist, but is required for this effect to operate' - }, - Transitions: { - linear: Prototype.K, - sinoidal: function(pos) { - return (-Math.cos(pos*Math.PI)/2) + .5; - }, - reverse: function(pos) { - return 1-pos; - }, - flicker: function(pos) { - var pos = ((-Math.cos(pos*Math.PI)/4) + .75) + Math.random()/4; - return pos > 1 ? 1 : pos; - }, - wobble: function(pos) { - return (-Math.cos(pos*Math.PI*(9*pos))/2) + .5; - }, - pulse: function(pos, pulses) { - return (-Math.cos((pos*((pulses||5)-.5)*2)*Math.PI)/2) + .5; - }, - spring: function(pos) { - return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6)); - }, - none: function(pos) { - return 0; - }, - full: function(pos) { - return 1; - } - }, - DefaultOptions: { - duration: 1.0, // seconds - fps: 100, // 100= assume 66fps max. - sync: false, // true for combining - from: 0.0, - to: 1.0, - delay: 0.0, - queue: 'parallel' - }, - tagifyText: function(element) { - var tagifyStyle = 'position:relative'; - if (Prototype.Browser.IE) tagifyStyle += ';zoom:1'; - - element = $(element); - $A(element.childNodes).each( function(child) { - if (child.nodeType==3) { - child.nodeValue.toArray().each( function(character) { - element.insertBefore( - new Element('span', {style: tagifyStyle}).update( - character == ' ' ? String.fromCharCode(160) : character), - child); - }); - Element.remove(child); - } - }); - }, - multiple: function(element, effect) { - var elements; - if (((typeof element == 'object') || - Object.isFunction(element)) && - (element.length)) - elements = element; - else - elements = $(element).childNodes; - - var options = Object.extend({ - speed: 0.1, - delay: 0.0 - }, arguments[2] || { }); - var masterDelay = options.delay; - - $A(elements).each( function(element, index) { - new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); - }); - }, - PAIRS: { - 'slide': ['SlideDown','SlideUp'], - 'blind': ['BlindDown','BlindUp'], - 'appear': ['Appear','Fade'] - }, - toggle: function(element, effect) { - element = $(element); - effect = (effect || 'appear').toLowerCase(); - var options = Object.extend({ - queue: { position:'end', scope:(element.id || 'global'), limit: 1 } - }, arguments[2] || { }); - Effect[element.visible() ? - Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); - } -}; - -Effect.DefaultOptions.transition = Effect.Transitions.sinoidal; - -/* ------------- core effects ------------- */ - -Effect.ScopedQueue = Class.create(Enumerable, { - initialize: function() { - this.effects = []; - this.interval = null; - }, - _each: function(iterator) { - this.effects._each(iterator); - }, - add: function(effect) { - var timestamp = new Date().getTime(); - - var position = Object.isString(effect.options.queue) ? - effect.options.queue : effect.options.queue.position; - - switch(position) { - case 'front': - // move unstarted effects after this effect - this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { - e.startOn += effect.finishOn; - e.finishOn += effect.finishOn; - }); - break; - case 'with-last': - timestamp = this.effects.pluck('startOn').max() || timestamp; - break; - case 'end': - // start effect after last queued effect has finished - timestamp = this.effects.pluck('finishOn').max() || timestamp; - break; - } - - effect.startOn += timestamp; - effect.finishOn += timestamp; - - if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) - this.effects.push(effect); - - if (!this.interval) - this.interval = setInterval(this.loop.bind(this), 15); - }, - remove: function(effect) { - this.effects = this.effects.reject(function(e) { return e==effect }); - if (this.effects.length == 0) { - clearInterval(this.interval); - this.interval = null; - } - }, - loop: function() { - var timePos = new Date().getTime(); - for(var i=0, len=this.effects.length;i= this.startOn) { - if (timePos >= this.finishOn) { - this.render(1.0); - this.cancel(); - this.event('beforeFinish'); - if (this.finish) this.finish(); - this.event('afterFinish'); - return; - } - var pos = (timePos - this.startOn) / this.totalTime, - frame = (pos * this.totalFrames).round(); - if (frame > this.currentFrame) { - this.render(pos); - this.currentFrame = frame; - } - } - }, - cancel: function() { - if (!this.options.sync) - Effect.Queues.get(Object.isString(this.options.queue) ? - 'global' : this.options.queue.scope).remove(this); - this.state = 'finished'; - }, - event: function(eventName) { - if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); - if (this.options[eventName]) this.options[eventName](this); - }, - inspect: function() { - var data = $H(); - for(property in this) - if (!Object.isFunction(this[property])) data.set(property, this[property]); - return '#'; - } -}); - -Effect.Parallel = Class.create(Effect.Base, { - initialize: function(effects) { - this.effects = effects || []; - this.start(arguments[1]); - }, - update: function(position) { - this.effects.invoke('render', position); - }, - finish: function(position) { - this.effects.each( function(effect) { - effect.render(1.0); - effect.cancel(); - effect.event('beforeFinish'); - if (effect.finish) effect.finish(position); - effect.event('afterFinish'); - }); - } -}); - -Effect.Tween = Class.create(Effect.Base, { - initialize: function(object, from, to) { - object = Object.isString(object) ? $(object) : object; - var args = $A(arguments), method = args.last(), - options = args.length == 5 ? args[3] : null; - this.method = Object.isFunction(method) ? method.bind(object) : - Object.isFunction(object[method]) ? object[method].bind(object) : - function(value) { object[method] = value }; - this.start(Object.extend({ from: from, to: to }, options || { })); - }, - update: function(position) { - this.method(position); - } -}); - -Effect.Event = Class.create(Effect.Base, { - initialize: function() { - this.start(Object.extend({ duration: 0 }, arguments[0] || { })); - }, - update: Prototype.emptyFunction -}); - -Effect.Opacity = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - // make this work on IE on elements without 'layout' - if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) - this.element.setStyle({zoom: 1}); - var options = Object.extend({ - from: this.element.getOpacity() || 0.0, - to: 1.0 - }, arguments[1] || { }); - this.start(options); - }, - update: function(position) { - this.element.setOpacity(position); - } -}); - -Effect.Move = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ - x: 0, - y: 0, - mode: 'relative' - }, arguments[1] || { }); - this.start(options); - }, - setup: function() { - this.element.makePositioned(); - this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); - this.originalTop = parseFloat(this.element.getStyle('top') || '0'); - if (this.options.mode == 'absolute') { - this.options.x = this.options.x - this.originalLeft; - this.options.y = this.options.y - this.originalTop; - } - }, - update: function(position) { - this.element.setStyle({ - left: (this.options.x * position + this.originalLeft).round() + 'px', - top: (this.options.y * position + this.originalTop).round() + 'px' - }); - } -}); - -// for backwards compatibility -Effect.MoveBy = function(element, toTop, toLeft) { - return new Effect.Move(element, - Object.extend({ x: toLeft, y: toTop }, arguments[3] || { })); -}; - -Effect.Scale = Class.create(Effect.Base, { - initialize: function(element, percent) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ - scaleX: true, - scaleY: true, - scaleContent: true, - scaleFromCenter: false, - scaleMode: 'box', // 'box' or 'contents' or { } with provided values - scaleFrom: 100.0, - scaleTo: percent - }, arguments[2] || { }); - this.start(options); - }, - setup: function() { - this.restoreAfterFinish = this.options.restoreAfterFinish || false; - this.elementPositioning = this.element.getStyle('position'); - - this.originalStyle = { }; - ['top','left','width','height','fontSize'].each( function(k) { - this.originalStyle[k] = this.element.style[k]; - }.bind(this)); - - this.originalTop = this.element.offsetTop; - this.originalLeft = this.element.offsetLeft; - - var fontSize = this.element.getStyle('font-size') || '100%'; - ['em','px','%','pt'].each( function(fontSizeType) { - if (fontSize.indexOf(fontSizeType)>0) { - this.fontSize = parseFloat(fontSize); - this.fontSizeType = fontSizeType; - } - }.bind(this)); - - this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; - - this.dims = null; - if (this.options.scaleMode=='box') - this.dims = [this.element.offsetHeight, this.element.offsetWidth]; - if (/^content/.test(this.options.scaleMode)) - this.dims = [this.element.scrollHeight, this.element.scrollWidth]; - if (!this.dims) - this.dims = [this.options.scaleMode.originalHeight, - this.options.scaleMode.originalWidth]; - }, - update: function(position) { - var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); - if (this.options.scaleContent && this.fontSize) - this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); - this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); - }, - finish: function(position) { - if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); - }, - setDimensions: function(height, width) { - var d = { }; - if (this.options.scaleX) d.width = width.round() + 'px'; - if (this.options.scaleY) d.height = height.round() + 'px'; - if (this.options.scaleFromCenter) { - var topd = (height - this.dims[0])/2; - var leftd = (width - this.dims[1])/2; - if (this.elementPositioning == 'absolute') { - if (this.options.scaleY) d.top = this.originalTop-topd + 'px'; - if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; - } else { - if (this.options.scaleY) d.top = -topd + 'px'; - if (this.options.scaleX) d.left = -leftd + 'px'; - } - } - this.element.setStyle(d); - } -}); - -Effect.Highlight = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { }); - this.start(options); - }, - setup: function() { - // Prevent executing on elements not in the layout flow - if (this.element.getStyle('display')=='none') { this.cancel(); return; } - // Disable background image during the effect - this.oldStyle = { }; - if (!this.options.keepBackgroundImage) { - this.oldStyle.backgroundImage = this.element.getStyle('background-image'); - this.element.setStyle({backgroundImage: 'none'}); - } - if (!this.options.endcolor) - this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); - if (!this.options.restorecolor) - this.options.restorecolor = this.element.getStyle('background-color'); - // init color calculations - this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); - this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this)); - }, - update: function(position) { - this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ - return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) }); - }, - finish: function() { - this.element.setStyle(Object.extend(this.oldStyle, { - backgroundColor: this.options.restorecolor - })); - } -}); - -Effect.ScrollTo = function(element) { - var options = arguments[1] || { }, - scrollOffsets = document.viewport.getScrollOffsets(), - elementOffsets = $(element).cumulativeOffset(); - - if (options.offset) elementOffsets[1] += options.offset; - - return new Effect.Tween(null, - scrollOffsets.top, - elementOffsets[1], - options, - function(p){ scrollTo(scrollOffsets.left, p.round()); } - ); -}; - -/* ------------- combination effects ------------- */ - -Effect.Fade = function(element) { - element = $(element); - var oldOpacity = element.getInlineOpacity(); - var options = Object.extend({ - from: element.getOpacity() || 1.0, - to: 0.0, - afterFinishInternal: function(effect) { - if (effect.options.to!=0) return; - effect.element.hide().setStyle({opacity: oldOpacity}); - } - }, arguments[1] || { }); - return new Effect.Opacity(element,options); -}; - -Effect.Appear = function(element) { - element = $(element); - var options = Object.extend({ - from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), - to: 1.0, - // force Safari to render floated elements properly - afterFinishInternal: function(effect) { - effect.element.forceRerendering(); - }, - beforeSetup: function(effect) { - effect.element.setOpacity(effect.options.from).show(); - }}, arguments[1] || { }); - return new Effect.Opacity(element,options); -}; - -Effect.Puff = function(element) { - element = $(element); - var oldStyle = { - opacity: element.getInlineOpacity(), - position: element.getStyle('position'), - top: element.style.top, - left: element.style.left, - width: element.style.width, - height: element.style.height - }; - return new Effect.Parallel( - [ new Effect.Scale(element, 200, - { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), - new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], - Object.extend({ duration: 1.0, - beforeSetupInternal: function(effect) { - Position.absolutize(effect.effects[0].element); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.hide().setStyle(oldStyle); } - }, arguments[1] || { }) - ); -}; - -Effect.BlindUp = function(element) { - element = $(element); - element.makeClipping(); - return new Effect.Scale(element, 0, - Object.extend({ scaleContent: false, - scaleX: false, - restoreAfterFinish: true, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping(); - } - }, arguments[1] || { }) - ); -}; - -Effect.BlindDown = function(element) { - element = $(element); - var elementDimensions = element.getDimensions(); - return new Effect.Scale(element, 100, Object.extend({ - scaleContent: false, - scaleX: false, - scaleFrom: 0, - scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, - restoreAfterFinish: true, - afterSetup: function(effect) { - effect.element.makeClipping().setStyle({height: '0px'}).show(); - }, - afterFinishInternal: function(effect) { - effect.element.undoClipping(); - } - }, arguments[1] || { })); -}; - -Effect.SwitchOff = function(element) { - element = $(element); - var oldOpacity = element.getInlineOpacity(); - return new Effect.Appear(element, Object.extend({ - duration: 0.4, - from: 0, - transition: Effect.Transitions.flicker, - afterFinishInternal: function(effect) { - new Effect.Scale(effect.element, 1, { - duration: 0.3, scaleFromCenter: true, - scaleX: false, scaleContent: false, restoreAfterFinish: true, - beforeSetup: function(effect) { - effect.element.makePositioned().makeClipping(); - }, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity}); - } - }); - } - }, arguments[1] || { })); -}; - -Effect.DropOut = function(element) { - element = $(element); - var oldStyle = { - top: element.getStyle('top'), - left: element.getStyle('left'), - opacity: element.getInlineOpacity() }; - return new Effect.Parallel( - [ new Effect.Move(element, {x: 0, y: 100, sync: true }), - new Effect.Opacity(element, { sync: true, to: 0.0 }) ], - Object.extend( - { duration: 0.5, - beforeSetup: function(effect) { - effect.effects[0].element.makePositioned(); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle); - } - }, arguments[1] || { })); -}; - -Effect.Shake = function(element) { - element = $(element); - var options = Object.extend({ - distance: 20, - duration: 0.5 - }, arguments[1] || {}); - var distance = parseFloat(options.distance); - var split = parseFloat(options.duration) / 10.0; - var oldStyle = { - top: element.getStyle('top'), - left: element.getStyle('left') }; - return new Effect.Move(element, - { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) { - effect.element.undoPositioned().setStyle(oldStyle); - }}); }}); }}); }}); }}); }}); -}; - -Effect.SlideDown = function(element) { - element = $(element).cleanWhitespace(); - // SlideDown need to have the content of the element wrapped in a container element with fixed height! - var oldInnerBottom = element.down().getStyle('bottom'); - var elementDimensions = element.getDimensions(); - return new Effect.Scale(element, 100, Object.extend({ - scaleContent: false, - scaleX: false, - scaleFrom: window.opera ? 0 : 1, - scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, - restoreAfterFinish: true, - afterSetup: function(effect) { - effect.element.makePositioned(); - effect.element.down().makePositioned(); - if (window.opera) effect.element.setStyle({top: ''}); - effect.element.makeClipping().setStyle({height: '0px'}).show(); - }, - afterUpdateInternal: function(effect) { - effect.element.down().setStyle({bottom: - (effect.dims[0] - effect.element.clientHeight) + 'px' }); - }, - afterFinishInternal: function(effect) { - effect.element.undoClipping().undoPositioned(); - effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); } - }, arguments[1] || { }) - ); -}; - -Effect.SlideUp = function(element) { - element = $(element).cleanWhitespace(); - var oldInnerBottom = element.down().getStyle('bottom'); - var elementDimensions = element.getDimensions(); - return new Effect.Scale(element, window.opera ? 0 : 1, - Object.extend({ scaleContent: false, - scaleX: false, - scaleMode: 'box', - scaleFrom: 100, - scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, - restoreAfterFinish: true, - afterSetup: function(effect) { - effect.element.makePositioned(); - effect.element.down().makePositioned(); - if (window.opera) effect.element.setStyle({top: ''}); - effect.element.makeClipping().show(); - }, - afterUpdateInternal: function(effect) { - effect.element.down().setStyle({bottom: - (effect.dims[0] - effect.element.clientHeight) + 'px' }); - }, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping().undoPositioned(); - effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); - } - }, arguments[1] || { }) - ); -}; - -// Bug in opera makes the TD containing this element expand for a instance after finish -Effect.Squish = function(element) { - return new Effect.Scale(element, window.opera ? 1 : 0, { - restoreAfterFinish: true, - beforeSetup: function(effect) { - effect.element.makeClipping(); - }, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping(); - } - }); -}; - -Effect.Grow = function(element) { - element = $(element); - var options = Object.extend({ - direction: 'center', - moveTransition: Effect.Transitions.sinoidal, - scaleTransition: Effect.Transitions.sinoidal, - opacityTransition: Effect.Transitions.full - }, arguments[1] || { }); - var oldStyle = { - top: element.style.top, - left: element.style.left, - height: element.style.height, - width: element.style.width, - opacity: element.getInlineOpacity() }; - - var dims = element.getDimensions(); - var initialMoveX, initialMoveY; - var moveX, moveY; - - switch (options.direction) { - case 'top-left': - initialMoveX = initialMoveY = moveX = moveY = 0; - break; - case 'top-right': - initialMoveX = dims.width; - initialMoveY = moveY = 0; - moveX = -dims.width; - break; - case 'bottom-left': - initialMoveX = moveX = 0; - initialMoveY = dims.height; - moveY = -dims.height; - break; - case 'bottom-right': - initialMoveX = dims.width; - initialMoveY = dims.height; - moveX = -dims.width; - moveY = -dims.height; - break; - case 'center': - initialMoveX = dims.width / 2; - initialMoveY = dims.height / 2; - moveX = -dims.width / 2; - moveY = -dims.height / 2; - break; - } - - return new Effect.Move(element, { - x: initialMoveX, - y: initialMoveY, - duration: 0.01, - beforeSetup: function(effect) { - effect.element.hide().makeClipping().makePositioned(); - }, - afterFinishInternal: function(effect) { - new Effect.Parallel( - [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), - new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), - new Effect.Scale(effect.element, 100, { - scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, - sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) - ], Object.extend({ - beforeSetup: function(effect) { - effect.effects[0].element.setStyle({height: '0px'}).show(); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle); - } - }, options) - ); - } - }); -}; - -Effect.Shrink = function(element) { - element = $(element); - var options = Object.extend({ - direction: 'center', - moveTransition: Effect.Transitions.sinoidal, - scaleTransition: Effect.Transitions.sinoidal, - opacityTransition: Effect.Transitions.none - }, arguments[1] || { }); - var oldStyle = { - top: element.style.top, - left: element.style.left, - height: element.style.height, - width: element.style.width, - opacity: element.getInlineOpacity() }; - - var dims = element.getDimensions(); - var moveX, moveY; - - switch (options.direction) { - case 'top-left': - moveX = moveY = 0; - break; - case 'top-right': - moveX = dims.width; - moveY = 0; - break; - case 'bottom-left': - moveX = 0; - moveY = dims.height; - break; - case 'bottom-right': - moveX = dims.width; - moveY = dims.height; - break; - case 'center': - moveX = dims.width / 2; - moveY = dims.height / 2; - break; - } - - return new Effect.Parallel( - [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), - new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), - new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) - ], Object.extend({ - beforeStartInternal: function(effect) { - effect.effects[0].element.makePositioned().makeClipping(); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); } - }, options) - ); -}; - -Effect.Pulsate = function(element) { - element = $(element); - var options = arguments[1] || { }, - oldOpacity = element.getInlineOpacity(), - transition = options.transition || Effect.Transitions.linear, - reverser = function(pos){ - return 1 - transition((-Math.cos((pos*(options.pulses||5)*2)*Math.PI)/2) + .5); - }; - - return new Effect.Opacity(element, - Object.extend(Object.extend({ duration: 2.0, from: 0, - afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } - }, options), {transition: reverser})); -}; - -Effect.Fold = function(element) { - element = $(element); - var oldStyle = { - top: element.style.top, - left: element.style.left, - width: element.style.width, - height: element.style.height }; - element.makeClipping(); - return new Effect.Scale(element, 5, Object.extend({ - scaleContent: false, - scaleX: false, - afterFinishInternal: function(effect) { - new Effect.Scale(element, 1, { - scaleContent: false, - scaleY: false, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping().setStyle(oldStyle); - } }); - }}, arguments[1] || { })); -}; - -Effect.Morph = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ - style: { } - }, arguments[1] || { }); - - if (!Object.isString(options.style)) this.style = $H(options.style); - else { - if (options.style.include(':')) - this.style = options.style.parseStyle(); - else { - this.element.addClassName(options.style); - this.style = $H(this.element.getStyles()); - this.element.removeClassName(options.style); - var css = this.element.getStyles(); - this.style = this.style.reject(function(style) { - return style.value == css[style.key]; - }); - options.afterFinishInternal = function(effect) { - effect.element.addClassName(effect.options.style); - effect.transforms.each(function(transform) { - effect.element.style[transform.style] = ''; - }); - }; - } - } - this.start(options); - }, - - setup: function(){ - function parseColor(color){ - if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff'; - color = color.parseColor(); - return $R(0,2).map(function(i){ - return parseInt( color.slice(i*2+1,i*2+3), 16 ); - }); - } - this.transforms = this.style.map(function(pair){ - var property = pair[0], value = pair[1], unit = null; - - if (value.parseColor('#zzzzzz') != '#zzzzzz') { - value = value.parseColor(); - unit = 'color'; - } else if (property == 'opacity') { - value = parseFloat(value); - if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) - this.element.setStyle({zoom: 1}); - } else if (Element.CSS_LENGTH.test(value)) { - var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); - value = parseFloat(components[1]); - unit = (components.length == 3) ? components[2] : null; - } - - var originalValue = this.element.getStyle(property); - return { - style: property.camelize(), - originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), - targetValue: unit=='color' ? parseColor(value) : value, - unit: unit - }; - }.bind(this)).reject(function(transform){ - return ( - (transform.originalValue == transform.targetValue) || - ( - transform.unit != 'color' && - (isNaN(transform.originalValue) || isNaN(transform.targetValue)) - ) - ); - }); - }, - update: function(position) { - var style = { }, transform, i = this.transforms.length; - while(i--) - style[(transform = this.transforms[i]).style] = - transform.unit=='color' ? '#'+ - (Math.round(transform.originalValue[0]+ - (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() + - (Math.round(transform.originalValue[1]+ - (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() + - (Math.round(transform.originalValue[2]+ - (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() : - (transform.originalValue + - (transform.targetValue - transform.originalValue) * position).toFixed(3) + - (transform.unit === null ? '' : transform.unit); - this.element.setStyle(style, true); - } -}); - -Effect.Transform = Class.create({ - initialize: function(tracks){ - this.tracks = []; - this.options = arguments[1] || { }; - this.addTracks(tracks); - }, - addTracks: function(tracks){ - tracks.each(function(track){ - track = $H(track); - var data = track.values().first(); - this.tracks.push($H({ - ids: track.keys().first(), - effect: Effect.Morph, - options: { style: data } - })); - }.bind(this)); - return this; - }, - play: function(){ - return new Effect.Parallel( - this.tracks.map(function(track){ - var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options'); - var elements = [$(ids) || $$(ids)].flatten(); - return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) }); - }).flatten(), - this.options - ); - } -}); - -Element.CSS_PROPERTIES = $w( - 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + - 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' + - 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' + - 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' + - 'fontSize fontWeight height left letterSpacing lineHeight ' + - 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+ - 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' + - 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' + - 'right textIndent top width wordSpacing zIndex'); - -Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; - -String.__parseStyleElement = document.createElement('div'); -String.prototype.parseStyle = function(){ - var style, styleRules = $H(); - if (Prototype.Browser.WebKit) - style = new Element('div',{style:this}).style; - else { - String.__parseStyleElement.innerHTML = '
            '; - style = String.__parseStyleElement.childNodes[0].style; - } - - Element.CSS_PROPERTIES.each(function(property){ - if (style[property]) styleRules.set(property, style[property]); - }); - - if (Prototype.Browser.IE && this.include('opacity')) - styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]); - - return styleRules; -}; - -if (document.defaultView && document.defaultView.getComputedStyle) { - Element.getStyles = function(element) { - var css = document.defaultView.getComputedStyle($(element), null); - return Element.CSS_PROPERTIES.inject({ }, function(styles, property) { - styles[property] = css[property]; - return styles; - }); - }; -} else { - Element.getStyles = function(element) { - element = $(element); - var css = element.currentStyle, styles; - styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) { - results[property] = css[property]; - return results; - }); - if (!styles.opacity) styles.opacity = element.getOpacity(); - return styles; - }; -} - -Effect.Methods = { - morph: function(element, style) { - element = $(element); - new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { })); - return element; - }, - visualEffect: function(element, effect, options) { - element = $(element); - var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1); - new Effect[klass](element, options); - return element; - }, - highlight: function(element, options) { - element = $(element); - new Effect.Highlight(element, options); - return element; - } -}; - -$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+ - 'pulsate shake puff squish switchOff dropOut').each( - function(effect) { - Effect.Methods[effect] = function(element, options){ - element = $(element); - Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options); - return element; - }; - } -); - -$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each( - function(f) { Effect.Methods[f] = Element[f]; } -); - -Element.addMethods(Effect.Methods); \ No newline at end of file diff --git a/public/javascripts/facebox.js b/public/javascripts/facebox.js deleted file mode 100755 index 5ad90ed..0000000 --- a/public/javascripts/facebox.js +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Facebox (for jQuery) - * version: 1.2 (05/05/2008) - * @requires jQuery v1.2 or later - * - * Examples at http://famspam.com/facebox/ - * - * Licensed under the MIT: - * http://www.opensource.org/licenses/mit-license.php - * - * Copyright 2007, 2008 Chris Wanstrath [ chris@ozmm.org ] - * - * Usage: - * - * jQuery(document).ready(function() { - * jQuery('a[rel*=facebox]').facebox() - * }) - * - * Terms - * Loads the #terms div in the box - * - * Terms - * Loads the terms.html page in the box - * - * Terms - * Loads the terms.png image in the box - * - * - * You can also use it programmatically: - * - * jQuery.facebox('some html') - * jQuery.facebox('some html', 'my-groovy-style') - * - * The above will open a facebox with "some html" as the content. - * - * jQuery.facebox(function($) { - * $.get('blah.html', function(data) { $.facebox(data) }) - * }) - * - * The above will show a loading screen before the passed function is called, - * allowing for a better ajaxy experience. - * - * The facebox function can also display an ajax page, an image, or the contents of a div: - * - * jQuery.facebox({ ajax: 'remote.html' }) - * jQuery.facebox({ ajax: 'remote.html' }, 'my-groovy-style') - * jQuery.facebox({ image: 'stairs.jpg' }) - * jQuery.facebox({ image: 'stairs.jpg' }, 'my-groovy-style') - * jQuery.facebox({ div: '#box' }) - * jQuery.facebox({ div: '#box' }, 'my-groovy-style') - * - * Want to close the facebox? Trigger the 'close.facebox' document event: - * - * jQuery(document).trigger('close.facebox') - * - * Facebox also has a bunch of other hooks: - * - * loading.facebox - * beforeReveal.facebox - * reveal.facebox (aliased as 'afterReveal.facebox') - * init.facebox - * afterClose.facebox - * - * Simply bind a function to any of these hooks: - * - * $(document).bind('reveal.facebox', function() { ...stuff to do after the facebox and contents are revealed... }) - * - */ -(function($) { - $.facebox = function(data, klass) { - $.facebox.loading() - - if (data.ajax) fillFaceboxFromAjax(data.ajax, klass) - else if (data.image) fillFaceboxFromImage(data.image, klass) - else if (data.div) fillFaceboxFromHref(data.div, klass) - else if ($.isFunction(data)) data.call($) - else $.facebox.reveal(data, klass) - } - - /* - * Public, $.facebox methods - */ - - $.extend($.facebox, { - settings: { - opacity : 0.2, - overlay : true, - loadingImage : '/facebox/loading.gif', - closeImage : '/facebox/closelabel.png', - imageTypes : [ 'png', 'jpg', 'jpeg', 'gif' ], - faceboxHtml : '\ - ' - }, - - loading: function() { - init() - if ($('#facebox .loading').length == 1) return true - showOverlay() - - $('#facebox .content').empty() - $('#facebox .body').children().hide().end(). - append('
            ') - - $('#facebox').css({ - top: getPageScroll()[1] + (getPageHeight() / 10), - left: $(window).width() / 2 - 205 - }).show() - - $(document).bind('keydown.facebox', function(e) { - if (e.keyCode == 27) $.facebox.close() - return true - }) - $(document).trigger('loading.facebox') - }, - - reveal: function(data, klass) { - $(document).trigger('beforeReveal.facebox') - if (klass) $('#facebox .content').addClass(klass) - $('#facebox .content').append(data) - $('#facebox .loading').remove() - $('#facebox .body').children().fadeIn('normal') - $('#facebox').css('left', $(window).width() / 2 - ($('#facebox .popup').width() / 2)) - $(document).trigger('reveal.facebox').trigger('afterReveal.facebox') - }, - - close: function() { - $(document).trigger('close.facebox') - return false - } - }) - - /* - * Public, $.fn methods - */ - - $.fn.facebox = function(settings) { - if ($(this).length == 0) return - - init(settings) - - function clickHandler() { - $.facebox.loading(true) - - // support for rel="facebox.inline_popup" syntax, to add a class - // also supports deprecated "facebox[.inline_popup]" syntax - var klass = this.rel.match(/facebox\[?\.(\w+)\]?/) - if (klass) klass = klass[1] - - fillFaceboxFromHref(this.href, klass) - return false - } - - return this.bind('click.facebox', clickHandler) - } - - /* - * Private methods - */ - - // called one time to setup facebox on this page - function init(settings) { - if ($.facebox.settings.inited) return true - else $.facebox.settings.inited = true - - $(document).trigger('init.facebox') - makeCompatible() - - var imageTypes = $.facebox.settings.imageTypes.join('|') - $.facebox.settings.imageTypesRegexp = new RegExp('\.(' + imageTypes + ')$', 'i') - - if (settings) $.extend($.facebox.settings, settings) - $('body').append($.facebox.settings.faceboxHtml) - - var preload = [ new Image(), new Image() ] - preload[0].src = $.facebox.settings.closeImage - preload[1].src = $.facebox.settings.loadingImage - - $('#facebox').find('.b:first, .bl').each(function() { - preload.push(new Image()) - preload.slice(-1).src = $(this).css('background-image').replace(/url\((.+)\)/, '$1') - }) - - $('#facebox .close').click($.facebox.close) - $('#facebox .close_image').attr('src', $.facebox.settings.closeImage) - } - - // getPageScroll() by quirksmode.com - function getPageScroll() { - var xScroll, yScroll; - if (self.pageYOffset) { - yScroll = self.pageYOffset; - xScroll = self.pageXOffset; - } else if (document.documentElement && document.documentElement.scrollTop) { // Explorer 6 Strict - yScroll = document.documentElement.scrollTop; - xScroll = document.documentElement.scrollLeft; - } else if (document.body) {// all other Explorers - yScroll = document.body.scrollTop; - xScroll = document.body.scrollLeft; - } - return new Array(xScroll,yScroll) - } - - // Adapted from getPageSize() by quirksmode.com - function getPageHeight() { - var windowHeight - if (self.innerHeight) { // all except Explorer - windowHeight = self.innerHeight; - } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode - windowHeight = document.documentElement.clientHeight; - } else if (document.body) { // other Explorers - windowHeight = document.body.clientHeight; - } - return windowHeight - } - - // Backwards compatibility - function makeCompatible() { - var $s = $.facebox.settings - - $s.loadingImage = $s.loading_image || $s.loadingImage - $s.closeImage = $s.close_image || $s.closeImage - $s.imageTypes = $s.image_types || $s.imageTypes - $s.faceboxHtml = $s.facebox_html || $s.faceboxHtml - } - - // Figures out what you want to display and displays it - // formats are: - // div: #id - // image: blah.extension - // ajax: anything else - function fillFaceboxFromHref(href, klass) { - // div - if (href.match(/#/)) { - var url = window.location.href.split('#')[0] - var target = href.replace(url,'') - if (target == '#') return - $.facebox.reveal($(target).html(), klass) - - // image - } else if (href.match($.facebox.settings.imageTypesRegexp)) { - fillFaceboxFromImage(href, klass) - // ajax - } else { - fillFaceboxFromAjax(href, klass) - } - } - - function fillFaceboxFromImage(href, klass) { - var image = new Image() - image.onload = function() { - $.facebox.reveal('
            ', klass) - } - image.src = href - } - - function fillFaceboxFromAjax(href, klass) { - $.get(href, function(data) { $.facebox.reveal(data, klass) }) - } - - function skipOverlay() { - return $.facebox.settings.overlay == false || $.facebox.settings.opacity === null - } - - function showOverlay() { - if (skipOverlay()) return - - if ($('#facebox_overlay').length == 0) - $("body").append('
            ') - - $('#facebox_overlay').hide().addClass("facebox_overlayBG") - .css('opacity', $.facebox.settings.opacity) - .click(function() { $(document).trigger('close.facebox') }) - .fadeIn(200) - return false - } - - function hideOverlay() { - if (skipOverlay()) return - - $('#facebox_overlay').fadeOut(200, function(){ - $("#facebox_overlay").removeClass("facebox_overlayBG") - $("#facebox_overlay").addClass("facebox_hide") - $("#facebox_overlay").remove() - }) - - return false - } - - /* - * Bindings - */ - - $(document).bind('close.facebox', function() { - $(document).unbind('keydown.facebox') - $('#facebox').fadeOut(function() { - $('#facebox .content').removeClass().addClass('content') - $('#facebox .loading').remove() - $(document).trigger('afterClose.facebox') - }) - hideOverlay() - }) - -})(jQuery); diff --git a/public/javascripts/index.html b/public/javascripts/index.html deleted file mode 100755 index e933af9..0000000 --- a/public/javascripts/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -

            you shouldn't be here.. kicking you out!

            - - diff --git a/public/javascripts/irb.js b/public/javascripts/irb.js deleted file mode 100755 index b4cb354..0000000 --- a/public/javascripts/irb.js +++ /dev/null @@ -1,110 +0,0 @@ -// -// Copyright (c) 2008 why the lucky stiff -// Copyright (c) 2010 Andrew McElroy -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, -// and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT -// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -var allStretch; -var helpPages; -var chapPages; -var defaultPage; -var toot = window.location.search.substr(1) - -//the main function, call to the effect object -function dumpAlert(obj) { - props = []; - for ( var i in obj ) { - props.push( "" + i + ": " + obj[i] ); - } - alert( props ); -} -window.onload = function() { - defaultPage = $('#helpstone .stretcher').html(); - - window.irb = new MouseApp.Irb('#irb', { - rows: 13, - name: 'IRB', - greeting: "%+r Interactive ruby ready. %-r", - ps: '\033[1;31m>>\033[m', - user: 'guest', - host: 'tryruby', - // original: irbUrl: '/irb', - irbUrl: '/tryruby/run', - init: function () { - helpPages = $(".stretcher"); - chapPages = new Array(); - for (var i = 0; i < helpPages.length; i++ ) { - var cls = helpPages[i].className.split(' '); - for (var j = 0; j < cls.length; j++) { - if (cls[j] == 'chapmark') { - chapPages.push([i, helpPages[i]]); - break; - } - } - } - }, - loadTutorial: function (id, instruct) { - $.ajax({ - url: '/tutorials/' + id , - type: 'GET', - complete: function (r) { - $('#helpstone').html("
            " + defaultPage + "
            " + r.responseText); - window.irb.init(); - window.irb.showHelp(0); - } - }); - }, - showChapter: function (n) { - if (n >= chapPages.length) return; - this.setHelpPage(chapPages[n][0], chapPages[n][1]); - }, - showHelp: function (n) { - if (n >= helpPages.length) return; - this.setHelpPage(n, helpPages[n]); - }, - popup_goto: function (u) { - $('#lilBrowser').show().css({left: '40px', top: '40px'}); - $('#lbIframe').attr('src', u); - }, - popup_make: function (s) { - $('#lilBrowser').show().css({left: '40px', top: '40px'}); - $('#lbIframe').get(0).onIframeLoad = function () { - alert($(this).html()); - alert("$(this).html()"); - return s; - }; - //$('#lbIframe').attr({src: '/blank.html'}); - src = s.replace(/\\/g, "\\\\").replace(/\"/g, "\\\""); - $('#lbIframe').attr({src: "javascript:\"" + src + "\""}); - // $('# - }, - popup_close: function () { - $('#lilBrowser').hide(); - } - }); - - if ( !toot ) { - toot = 'intro'; - } - try { - window.irb.options.loadTutorial( toot, true ); - } catch (e) {} -} diff --git a/public/javascripts/jQuery.irb.js b/public/javascripts/jQuery.irb.js deleted file mode 100644 index 765858d..0000000 --- a/public/javascripts/jQuery.irb.js +++ /dev/null @@ -1,1641 +0,0 @@ -//Try Ruby 1.5 (defacto version Number) -// March 14 2011 - -// large parts of this file are lifted from Try Haskell ( which lifted parts from try ruby without copyright notice >:-/ ) - -// Thus it is fair to include the following banner if/until there is no try haskell code left/ only code that originally existed in try ruby in the -//first place. - - // Try Haskell 1.0.1 - // Tue Feb 23 18:34:48 GMT 2010 - // - // Copyright 2010 Chris Done. All rights reserved. - // - // Redistribution and use in source and binary forms, with or without - // modification, are permitted provided that the following conditions - // are met: - // - // 1. Redistributions of source code must retain the above - // copyright notice, this list of conditions and the following - // disclaimer. - // 2. Redistributions in binary form must reproduce the above - // copyright notice, this list of conditions and the following - // disclaimer in the documentation and/or other materials - // provided with the distribution. - // - // THIS SOFTWARE IS PROVIDED BY CHRIS DONE ``AS IS'' AND ANY EXPRESS - // OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - // ARE DISCLAIMED. IN NO EVENT SHALL CHRIS DONE OR CONTRIBUTORS BE - // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - // OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - // DAMAGE. - // The views and conclusions contained in the software and - // documentation are those of the authors and should not be - // interpreted as representing official policies, either expressed or - // implied, of Chris Done. - // - // TESTED ON - // Internet Explorer 6 - // Opera 10.01 - // Chromium 4.0.237.0 (Ubuntu build 31094) - // Firefox 3.5.8 - - //IOS 4.3 (all devices) - -// Temporary fix -function opera() { - return navigator.userAgent.indexOf("Opera") == 0; -} - -function encodeHex(str) { - var result = ""; - for (var i = 0; i < str.length; i++) { - result += "%" + pad(toHex(str.charCodeAt(i) & 0xff), 2, '0'); - } - return result; -} - -//var handleJSON = function(a){ alert('Unassigned JSONP: ' + a); } -var hexv = { - "00": 0, - "01": 1, - "02": 2, - "03": 3, - "04": 4, - "05": 5, - "06": 6, - "07": 7, - "08": 8, - "09": 9, - "0A": 10, - "0B": 11, - "0C": 12, - "0D": 13, - "0E": 14, - "0F": 15, - "10": 16, - "11": 17, - "12": 18, - "13": 19, - "14": 20, - "15": 21, - "16": 22, - "17": 23, - "18": 24, - "19": 25, - "1A": 26, - "1B": 27, - "1C": 28, - "1D": 29, - "1E": 30, - "1F": 31, - "20": 32, - "21": 33, - "22": 34, - "23": 35, - "24": 36, - "25": 37, - "26": 38, - "27": 39, - "28": 40, - "29": 41, - "2A": 42, - "2B": 43, - "2C": 44, - "2D": 45, - "2E": 46, - "2F": 47, - "30": 48, - "31": 49, - "32": 50, - "33": 51, - "34": 52, - "35": 53, - "36": 54, - "37": 55, - "38": 56, - "39": 57, - "3A": 58, - "3B": 59, - "3C": 60, - "3D": 61, - "3E": 62, - "3F": 63, - "40": 64, - "41": 65, - "42": 66, - "43": 67, - "44": 68, - "45": 69, - "46": 70, - "47": 71, - "48": 72, - "49": 73, - "4A": 74, - "4B": 75, - "4C": 76, - "4D": 77, - "4E": 78, - "4F": 79, - "50": 80, - "51": 81, - "52": 82, - "53": 83, - "54": 84, - "55": 85, - "56": 86, - "57": 87, - "58": 88, - "59": 89, - "5A": 90, - "5B": 91, - "5C": 92, - "5D": 93, - "5E": 94, - "5F": 95, - "60": 96, - "61": 97, - "62": 98, - "63": 99, - "64": 100, - "65": 101, - "66": 102, - "67": 103, - "68": 104, - "69": 105, - "6A": 106, - "6B": 107, - "6C": 108, - "6D": 109, - "6E": 110, - "6F": 111, - "70": 112, - "71": 113, - "72": 114, - "73": 115, - "74": 116, - "75": 117, - "76": 118, - "77": 119, - "78": 120, - "79": 121, - "7A": 122, - "7B": 123, - "7C": 124, - "7D": 125, - "7E": 126, - "7F": 127, - "80": 128, - "81": 129, - "82": 130, - "83": 131, - "84": 132, - "85": 133, - "86": 134, - "87": 135, - "88": 136, - "89": 137, - "8A": 138, - "8B": 139, - "8C": 140, - "8D": 141, - "8E": 142, - "8F": 143, - "90": 144, - "91": 145, - "92": 146, - "93": 147, - "94": 148, - "95": 149, - "96": 150, - "97": 151, - "98": 152, - "99": 153, - "9A": 154, - "9B": 155, - "9C": 156, - "9D": 157, - "9E": 158, - "9F": 159, - "A0": 160, - "A1": 161, - "A2": 162, - "A3": 163, - "A4": 164, - "A5": 165, - "A6": 166, - "A7": 167, - "A8": 168, - "A9": 169, - "AA": 170, - "AB": 171, - "AC": 172, - "AD": 173, - "AE": 174, - "AF": 175, - "B0": 176, - "B1": 177, - "B2": 178, - "B3": 179, - "B4": 180, - "B5": 181, - "B6": 182, - "B7": 183, - "B8": 184, - "B9": 185, - "BA": 186, - "BB": 187, - "BC": 188, - "BD": 189, - "BE": 190, - "BF": 191, - "C0": 192, - "C1": 193, - "C2": 194, - "C3": 195, - "C4": 196, - "C5": 197, - "C6": 198, - "C7": 199, - "C8": 200, - "C9": 201, - "CA": 202, - "CB": 203, - "CC": 204, - "CD": 205, - "CE": 206, - "CF": 207, - "D0": 208, - "D1": 209, - "D2": 210, - "D3": 211, - "D4": 212, - "D5": 213, - "D6": 214, - "D7": 215, - "D8": 216, - "D9": 217, - "DA": 218, - "DB": 219, - "DC": 220, - "DD": 221, - "DE": 222, - "DF": 223, - "E0": 224, - "E1": 225, - "E2": 226, - "E3": 227, - "E4": 228, - "E5": 229, - "E6": 230, - "E7": 231, - "E8": 232, - "E9": 233, - "EA": 234, - "EB": 235, - "EC": 236, - "ED": 237, - "EE": 238, - "EF": 239, - "F0": 240, - "F1": 241, - "F2": 242, - "F3": 243, - "F4": 244, - "F5": 245, - "F6": 246, - "F7": 247, - "F8": 248, - "F9": 249, - "FA": 250, - "FB": 251, - "FC": 252, - "FD": 253, - "FE": 254, - "FF": 255 -}; - -function pad(str, len, pad) { - var result = str; - for (var i = str.length; i < len; i++) { - result = pad + result; - } - return result; -} - -var digitArray = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'); - -function toHex(n) { - var result = '' - var start = true; - for (var i = 32; i > 0;) { - i -= 4; - var digit = (n >> i) & 0xf; - if (!start || digit != 0) { - start = false; - result += digitArray[digit]; - } - } - return (result == '' ? '0': result); -} - - (function($) { - var raphaelPaper; - var raphaelObjs; - var tutorialGuide; - - // I don't like this at all... I intend to make this pull via ajax from a key value data store. - var pages = - [ - //////////////////////////////////////////////////////////////////////// - // Lesson 1 - // Simple addition - { - lesson: 1, - title: 'Basics; numbers, strings, etc.', - guide: - '

            ' + rmsg(['Learning By Numbers', 'Music is Math', 'Back to Basics']) - + '

            ' - + "

            To kick off let's try some maths out. Up there you can" - + " type in Haskell expressions. Try this out: 5 + 7

            " - }, - { - guide: function(result) { - if (!result) result = { - expr: '5+7', - result: 12 - }; - var complied = result.expr.replace(/ /g, '') == "5+7"; - var who = complied ? 'we': 'you'; - return '

            ' + rmsg(['Your first Haskell expression', - "First Time's a Charm"]) + '

            ' - + '

            Well done, you typed it perfect! You got back the number' + - ' ' + result.result + '. Just what ' + who + ' wanted. ' - + "

            Let's try something completely different." + - " Type in your name like this:" + - ' "chris"

            ' - }, - trigger: function(result) { - return result.type == "(Num t) => t" || - result.type == "Integer" || - result.type == "Int"; - } - }, - // Strings & types - { - guide: function(result) { - if (!result) result = { - expr: '"chris"', - result: "\"chris\"" - }; - var n = unString(result.result); - if (n) n = ", " + n; - n += "!"; - return '

            ' + rmsg(['Types of values', "What's in a name?"]) + - '

            ' - + '

            Hi there' + htmlEncode(n) - + (n != "!" ? " That's a pretty name. Honest.": "") - + " You're getting the hang of this!

            " + - "

            Note: You can chat to Haskell programmers while learning here, enter chat to start it." + - " You will join the official IRC channel of the Haskell community!

            " - + "

            Each time, you're getting back the value of the expression. So " + - "far, just a number and a list of characters.

            " + - "

            You can have lists of other stuff, too. Let's see your " + - " lottery numbers: [42,13,22]

            " - }, - trigger: function(result) { - return result.type == "[Char]" - || result.type == "String"; - } - }, - // Overview of lesson 1 - { - guide: function(result) { - if (!result) result = { - result: "[42,13,22]" - }; - return '

            ' + rmsg(["Lesson 1 done already!"]) + - '

            ' + - "

            Great, you made a list of numbers! If you win we'll split" + - " the winnings, right?

            " + - "

            Let's see what you've learned so far:

            " + - "
              " + - "
            1. How to write maths and lists of things.
            2. " + - "
            " + - "

            You can do stuff with lists. Maybe you want the lottery " + - "numbers sorted in the right order, try this: " + - "sort " + result.result + "

            " - }, - trigger: function(result) { - return result.expr.match(/^[ ]*\[[0-9, ]+\][ ]*$/) && - result.type == "(Num t) => [t]"; - } - }, - /////////////////////////////////////////////////////////////////////// - // Lesson 2 - Functions - // Functions on lists - { - lesson: 2, - title: 'Simple Functions', - guide: function(result) { - if (!result) result = { - result: "[13,23,30]" - }; - return '

            ' + rmsg(["We put the funk in function"]) + - '

            ' + - "

            Congratulations, you just used a function." + - " They're how you get things done in Haskell." + - "

            As you might've guessed, we got back " + - htmlEncode(result.result) - + ".

            Ever wanted an evil twin nemesis? Me too. " + - "Luckily, you can sort lists of characters, or " + - "strings" + - ", in the same way as numbers! sort \"chris\"

            " - }, - trigger: function(result) { - return result.expr.match(/sort/) && - result.type == "(Num t, Ord t) => [t]"; - } - }, - // Tuples - { - guide: function(result) { - if (!result) result = { - result: "\"chirs\"" - }; - nemesis = htmlEncode(unString(result.result)); - return '

            ' + - rmsg(["Tuples, because sometimes one value ain't enough!"]) + - '

            ' + - "

            Watch out for " + nemesis + "! You should keep their credentials for the police.

            " + - "

            My nemesis is 28 years of age: " + - "(28,\"chirs\")

            " - }, - trigger: function(result) { - return result.expr.match(/sort/) && - result.type == "[Char]"; - } - }, - // Functions on tuples - { - guide: function(result) { - if (!result) result = { - result: "(28,\"chirs\")" - }; - var age = result.result.match(/^\(([0-9]+)+/); - var villain = htmlEncode(result.result.replace(/\\"/g, '"')); - return '

            ' + - rmsg(["We'll keep them safe, don't worry about it."]) + - '

            ' + - "

            Is " + (age ? age[1] : "that") + " a normal age for a " + - "super-villain?

            " + - "

            You just wrote a tuple. It's a way to keep a bunch of values together in Haskell. " + - "You can put as many as you like in there:

            " + - "
            • (1,\"hats\",23/35)
            • (\"Shaggy\",\"Daphnie\",\"Velma\")
            " + - "

            Actually, let's say our villain is " + - "" + villain + "" + - ", how do you get their age?

            " + - "fst " + villain + "" - }, - trigger: function(result) { - return result.expr.match(/\([0-9]+,[ ]*"[^"]+"\)/) && - result.type == "(Num t) => (t, [Char])"; - } - }, - // Summary of lesson 2 - { - guide: function(result) { - return '

            ' + - rmsg(["Lesson 2 done! Wow, great job!", - "Lesson 2 completo!"]) + - '

            ' + - - "

            Good job! You got the age back from the tuple! Didn't " + - " even break a sweat, did you? The fst function " + - "just gets the first value. It's called \"fst\" because " + - "it's used a lot in Haskell so it really needs to be short!

            " + - - "

            Time to take a rest and see what you learned:

            " + - "
              " + - "
            1. Functions can be used on lists of any type.
            2. " + - "
            3. We can stuff values into tuples.
            4. " + - "
            5. Getting the values back from tuples is easy.
            6. " + - "
            " + - - "

            Now let's say you want " + - " to use a value more than once, how would you do it? " + - "To make our lives easier, we can say:

            " + - - "let x = 4 in x * x" - }, - trigger: function(result) { - return result.expr.match(/fst/) && - result.type == "(Num t) => t"; - } - }, - { - guide: function(result) { - return "

            Let them eat cake

            " + - - "

            You just bound a variable. " + - "That is, you bound x to the expression 4, " + - " and then you can write x in some code (the body) and " + - " it will mean the same as if you'd written 4.

            " + - - "

            It's like this: let var = expression in body

            " + - - "The in part just separates the expression from the body.

            " + - - "

            For example try: " + - "let x = 8 * 10 in x + x

            " + - - "

            So if we wanted to get the age of our villain, we could do:

            " + - - "let villain = (28,\"chirs\") in fst villain" - - }, - trigger: function(result) { - return result.expr.match(/^[ ]*let[ ]+x[ ]*=[ ]*[0-9]+[ ]*in[ ]*x[ ]*\*[ ]*x/) && - result.type == "(Num t) => t"; - } - }, - { - guide: function(result) { - return "

            Basics over, let's go!

            " + - "

            Next, let's take a short detour to learn about " + - "syntactic sugar. " + - "Try typing this out:

            " + - "

            'a' : []

            " + - "

            Or skip to lesson4 to learn about functions," + - " the meat of Haskell!"; - }, - trigger: function(result) { - return result.expr.match(/^[ ]*let[ ]+villain[ ]*=[ ]*\([0-9]+,[ ]*"[^"]+"\)[ ]*in[ ]+fst[ ]+villain[ ]*/) && - result.type == "(Num t) => t"; - } - }, - // Lesson 3: Syntactic sugar - { - lesson: 3, - title: 'Syntactic Sugar', - guide: function(result) { - return '

            ' + - rmsg(["You constructed a list!"]) + - '

            ' + - "

            Well done, that was tricky syntax. You used the (:) " + - "function. It takes two values, some value and a list, and " + - " constructs a new list" + - " out of them. We call it 'cons' for short.

            " + - "

            'a' is " + - "the character 'a', [] is an empty list. So " + - "tacking 'a' at the start of an empty list just " + - "makes a list ['a']!

            " + - "

            But thankfully we don't have to type out " + - "'a' : 'b' : [] every time to we want to make a " + - "list of characters; we can use " + - "syntactic sugar and just write" + - " ['a','b']. Don't believe me, check this!

            " + - "'a' : 'b' : [] == ['a','b']" - }, - trigger: function(result) { - return result.expr.match(/^[ ]*'a'[ ]*:[ ]*\[\][ ]*/) && - result.type == "[Char]"; - } - }, - // Booleans and string syntactic sugar - { - guide: function(result) { - return '

            ' + - rmsg(["You're on fire!"]) + - '

            ' + - "

            You're handling this syntax really well, nice!

            " + - "

            You just got a boolean value back, and it said " + - "True. That means they're equal!

            " + - "

            One final demonstration on syntactic sugar for now:

            " + - "['a','b','c'] == \"abc\"" - }, - trigger: function(result) { - return result.type == "Bool" && - result.expr.replace(/[^':\[\]\=,]/g, '') == "'':'':[]==['','']"; - } - }, - // Summary of syntactic sugar section - { - guide: function(result) { - return '

            ' + - rmsg(["Lesson 3 over! Syntactic sugar is sweet"]) + - '

            ' + - "

            Let's have a gander at what you learned:

            " + - "
              " + - "
            1. In 'a' : [], : is really just " + - " another function, just clever looking.
            2. " + - "
            3. Pretty functions like this are written like (:) when " + - " you talk about them.
            4. " + - "
            5. A list of characters ['a','b'] can just be written " + - "\"ab\". Much easier!
            6. " - + "
            " + - "

            Phew! You're getting pretty deep! Your arch nemesis, " + - nemesis + ", is gonna try to steal your " + rmsg(['mojo', - 'pizza']) + - "! Let's learn a bit more about functions and passing " + - "them around. Try this:

            map (+1) [1..5]

            "; - }, - trigger: function(result) { - return result.expr.replace(/[^\]\[',=\"]?/g, '') == "['','','']==\"\"" && - result.type == "Bool"; - } - }, - { - lesson: 4, - title: 'Functions, reloaded; passing, defining, etc.', - guide: function() { - var title = - rmsg(["Functions [of a Geisha]", - "Functions, functors, functoids, funky", - "Functions: Expanded fo' real"]); - return "

            " + title + "

            " + - - "

            Here's where the magic begins!

            " + - - "

            You just passed the (+1) " + - "function to the map function.

            " + - - "

            You can try other things like (remember: click to insert them):

            " + - - "
              " + - "
            • map (*99) [1..10]
            • " + - "
            • map (/5) [13,24,52,42]
            • " + - "
            • filter (>5) [62,3,25,7,1,9]
            • " + - "
            " + - - "

            Note that a tuple is different to a list because you can do this:

            " + - "(1,\"George\")" - }, - trigger: function(result) { - return result.expr.match(/^[ ]*map[ ]+\(\+1\)[ ]*\[1..5\][ ]*$/) && - result.type == "(Num a, Enum a) => [a]"; - } - }, - { - guide: function(result) { - return "

            Lists and Tuples

            " + - - "

            You can only " + - " have a list of numbers or a list of characters, whereas in a tuple you can throw anything in!

            " + - - "

            We've also seen that you can make a new list with (:) that joins two values together, like:

            " + - "

            1 : [2,3]

            " + - - "

            But we can't do this with tuples! You can only write a tuple and then look at what's inside. You can't make new ones on the fly like a list." + - - "

            Let's write our own functions! It's really easy. How about something simple:

            " + - "let square x = x * x in square " + rmsg([52, 10, 3]) + "" - - }, - trigger: function(result) { - return result.expr.match(/^[ ]*\(1,"[^"]+"\)[ ]*$/) && - result.type == "(Num t) => (t, [Char])"; - } - }, - { - guide: function(result) { - return "

            Let there be functions

            " + - "

            Nice one! I think you're getting used to the let syntax.

            " + - "

            You defined a function. You can read it as, as for a given " + - "parameter called x, square of " + - "x is x * x." + - "

            Some others you can try are:

            " + - "
            • let add1 x = x + 1 in add1 5
            • " + - "
            • let second x = snd x in second (3,4)
            • " + - "
            " + - "

            Let's go crazy and use our square function with map:

            " + - "let square x = x * x in map square [1..10]" - }, - trigger: function(result) { - return result.expr.match(/^[ ]*let[ ]*square[ ]+x[ ]*=[ ]*x[ ]*\*[ ]*x[ ]*in[ ]*square[ ]+[0-9]+/) && - result.type == "(Num t) => t"; - } - }, - { - guide: function(result) { - if (!result || !result.value) result = { - value: "[1,4,9,16,25,36,49,64,81,100]" - }; - return "

            Let there be functions

            " + - - "

            That's so cool! You described a simple function square and then " + - "you just passed it to another function (map) and got back " + - htmlEncode(result.value) + ", exactly what you expected!

            " + - - "

            Haskell is pretty good at composing things together like this. " + - "Some other things you can try are:

            " + - - "
              " + - "
            • let add1 x = x + 1 in map add1 [1,5,7]
            • " + - "
            • let take5s = filter (==5) in take5s [1,5,2,5,3,5]
            • " + - "
            • let take5s = filter (==5) in map take5s [[1,5],[5],[1,1]]
            • " + - "
            " + - - "

            Did you get back what you expected?

            " + - - "

            One more example for text; how do you upcase a letter?

            " + - - "

            toUpper 'a'

            " - }, - trigger: function(result) { - return result.expr.match(/^[ ]*let[ ]+square[ ]+x[ ]*=[ ]*x[ ]*\*[ ]*x[ ]*in[ ]+map[ ]+square[ ]*\[1..10\][ ]*$/) && - result.type == "(Num a, Enum a) => [a]"; - } - }, - { - guide: function(result) { - return "

            Exercise time!

            " + - - "

            Easy! Remember: characters are written like 'a' and " + - "strings (lists of characters) are written like \"a\"." + - - "

            I need you to use toUpper capitalise my whole name, " + - "\"Chris\". Give it a try." + - " You can do it, I believe in you!

            " + - - '

            Spoiler: map toUpper "Chris"

            ' - }, - trigger: function(result) { - return result.expr.match(/^toUpper 'a'$/) && - result.type == "Char"; - } - }, - { - guide: function(result) { - return "

            Lesson 4 complete!

            " + - - "

            Brilliant! You're making excellent progress! " + - "You just passed toUpper to map. No problem.

            " + - - "

            Let's go over what you've learned in this lesson:

            " + - - "
              " + - "
            1. Functions like map take other functions as parameters.
            2. " + - "
            3. Functions like (+1), (>5) and " + - "square can be passed to other functions.
            4. " + - "
            5. Defining functions is just a case of writing what " + - "to do with the parameters.
            6. " + "
            " + - - "

            Let's check out pattern matching; a way to " + - "get values from other values using patterns. Try this:

            " + - "

            let (a,b) = (10,12) in a * 2

            " + - - "

            Or you can skip this section and go to straight to lesson6; types!

            " - }, - trigger: function(result) { - return result.type == "[Char]" && - result.expr.match(/^map[ ]+toUpper/); - } - }, - { - lesson: 5, - title: 'Pattern Matching', - guide: function(result) { - var title = - rmsg(["And therefore, patterns emerge in nature.", - "And Then Patterns", - "Pattern matching!"]) - return "

            " + title + "

            " + - - "

            Jolly good show!

            " + - "

            So you had a value (10,12) and matched " + - "it against a pattern (a,b), then you were able" + - " to do stuff with the a and b!" + - - "

            Note: Pattern matching (a,b) against " + - "(1,2) to get the a is the same as" + - " doing fst (1,2), like you did in step7!

            " + - - "

            A pattern always matches the way the " + - "value was originally constructed. Remember that \"abc\" is " + - "syntactic sugar for 'a' : 'b' : 'c' : [].

            " + - - "

            So you can get the characters from a string with patterns:

            " + - - "let (a:b:c:[]) = \"xyz\" in a" - }, - trigger: function(result) { - return result.expr.match(/^[ ]*let[ ]+\(a,b\)[ ]+=[ ]+\(10,12\)[ ]+in[ ]+a[ ]*\*[ ]*2[ ]*$/) && - result.type == "(Num t) => t"; - } - }, - { - guide: function(result) { - return "

            " + rmsg(["Ignorance is bliss", "Ignoring values"]) + "

            " + - - "

            You're getting into tricky syntax, huh? I know you can handle it!

            " + - - "

            If you just want some of the values, you can ignore the others with _ (underscore) like this:

            " + - - "

            let (a:_:_:_) = \"xyz\" in a

            " + - - "

            In fact, (a:b:c:d) is short-hand for " + - "(a:(b:(c:d))), so you can just ignore the rest in one go:

            " + - - "let (a:_) = \"xyz\" in a" - }, - trigger: function(result) { - return result.expr.match(/^[ ]*let[ ]+\(a:b:c:\[\]\)[ ]*=[ ]*\"xyz\"[ ]*in[ ]+a[ ]*$/) && - result.type == "Char"; - } - }, - { - guide: function(result) { - return "

            " + rmsg(["Exercise!", "Show me the money!"]) + "

            " + - - "

            Try to get the 'a' value from this value using pattern matching:

            " + - "

            (10,\"abc\")

            " + - - "

            Spoiler: let (_,(a:_)) = (10,\"abc\") in a

            " - }, - trigger: function(result) { - return result.expr.match(/^[ ]*let[ ]*\(a:_\)[ ]*=[ ]*"xyz"[ ]*in[ ]*a[ ]*$/) && - result.type == "Char"; - } - }, - { - guide: function(result) { - return "

            " + rmsg(["Well done!", "Brilliant!", "Perfetto!"]) + "

            " + - - "

            Wizard! I think you've got pattern-matching down.

            " + - - "

            If you're still a bit unsure, here are some other things you can try:

            " + - - "
              " + - "
            • let _:_:c:_ = \"abcd\" in c
            • " + - "
            • let [a,b,c] = \"cat\" in (a,b,c)
            • " + - "
            " + - - "

            You can also grab a whole value and pattern match on it (have your cake and eat it too):

            " + - - "let abc@(a,b,c) = (10,20,30) in (abc,a,b,c)" - }, - trigger: function(result) { - return result.expr.match(/^[ ]*let[ ]*\(_,\(?a:_\)?\)[ ]*=[ ]*\(10,\"abc\"\)[ ]*in[ ]*a[ ]*$/) && - result.type == "Char"; - } - }, - { - guide: function(result) { - return "

            " + rmsg(["And that's the end of that chapter"]) + "

            " + - - "

            That was easy, right?

            " + - - "

            Let's go over what you've learned in this lesson:

            " + - - "
              " + - "
            1. Values are pattern matched, or deconstructed, by writing however they were constructed.
            2. " + - "
            3. Patterns let you use the values that you match.
            4. " + - "
            5. You can ignore whichever values you want.
            6. " + - "
            7. You can pattern match and keep hold of the original value too.
            8. " + - "
            " + - - "

            Now we get to the Deep Ones. Types!

            " + - - "

            Consider the following value: 'a'

            " - - }, - trigger: function(result) { - return result.type == "(Num t, Num t1, Num t2) => ((t, t1, t2), t, t1, t2)"; - } - }, - { - lesson: 6, - title: 'Types', - guide: function(result) { - showTypes = true; - return "

            " + rmsg(["Types", "What's in a Type?", "Types & Values"]) + "

            " + - "

            What's this? Something new!

            " + - - "

            In Haskell there are types of values. Every value belongs to a type. To demonstrate this fact, I've sneakily enabled types to be " + - "shown of every value in the console from now on.

            " + - - "

            The type of the value 'a' is Char (short for 'character', but you guessed that, right?).

            " + - - "

            You've seen the type of a character, now what about" + - " a list of characters?

            " + - "\"Spartacus\"" - }, - trigger: function(result) { - return result.type == 'Char'; - } - }, - { - guide: function(result) { - showTypes = true; - return "

            " + rmsg(["Lists of stuff, types"]) + "

            " + - - "

            I'm Spartacus!

            " + - - "

            Okay, so a list of characters has type [Char].

            " + - - "

            Notice that when we write a :: X it means the value a has type X. It's just a short-hand called a signature.

            " + - - "

            If you just want the type of a value, without actually evaluating it, you can just type:

            " + - ":t toUpper" - }, - trigger: function(result) { - return result.expr.match(/"[^"]+"/) && - result.type == '[Char]'; - } - }, - { - guide: function(result) { - showTypes = true; - return "

            " + rmsg(["Function types"]) + "

            " + - - "

            Woah! Hold your blinkin' 'orses! The type of toUpper reads: Char -> Char

            " + - - "

            It's pretty easy; a -> b means function from a to b. " + - "So

            toUpper :: Char -> Char means: for a" + - " given character (Char value) a, toUpper a has type Char.

            " + - - "

            Some other things you can try are:

            " + - - "
            • :t words
            • " + - "
            • :t unwords
            • " + - "
            • :t True
            • " + - "
            • :t not
            • " - + "
            " + - - "

            The words function is pretty handy. Want to get a list of words from a sentence?

            " + - "words \"There's jam in my pants.\"" - }, - trigger: function(result) { - return result.type == 'Char -> Char'; - } - }, - { - guide: function(result) { - showTypes = true; - return "

            " + rmsg(["Mid-way review"]) + "

            " + - - "

            The type of words was String -> [String]. You got a list of strings back! Just what you expected, right?

            " + - - "

            Let's take a rest in the middle of this lesson and go over what we've learned:

            " + - - "
              " + - "
            1. All values in Haskell have a type. We describe the types of values with signatures, like True :: Bool.
            2. " + - "
            3. Functions are values too, and they have types, notated a -> b.
            4. " + - "
            5. Functions can be defined for any type to any other type.
            6. " + - "
            7. Humble reader has a thing for jammy pants.
            8. " + - "
            " + - - "

            But what if you have a type that can contain values of any type, like a tuple?

            " + - ":t fst" - - }, - trigger: function(result) { - return result.expr.match(/^[ ]*words[ ]*\"[^"]+\"[ ]*$/) && - result.type == '[String]'; - } - }, - { - guide: function(result) { - showTypes = true; - return "

            " + rmsg(["Polymorphic functions"]) + "

            " + - - "

            Remember this one? I know you do! fst (1,2) is 1, right?

            " + - "

            We read its type

            " + - "

            fst :: (a, b) -> a

            " + - "

            as: for all types a and b, the fst has type (a,b) to a. So the fst " + - "function works on a pair of values of any types! We call such a function polymorphic." + - "

            " + - "

            Remember the drop function? Maybe you don't. I don't! Let's check out its type:

            " + - "

            :t drop

            " - }, - trigger: function(result) { - return result.type == '(a, b) -> a'; - } - }, - { - guide: function(result) { - showTypes = true; - return "

            " + rmsg(["Multi parameter functions"]) + "

            " + - - "

            So the drop function has type

            Int -> [a] -> [a].

            " + - - "

            This is something new. You've got two arrows! Relax. You can read

            " + - "

            a -> b -> c as a -> (b -> c)

            " + - - "

            In other words, drop is a function from integers (Int values) to functions of lists to lists ([a] -> [a] values). Drop is a function to another function.

            " + - - "

            Check for yourself! :t drop 3

            " - }, - trigger: function(result) { - return result.type == 'Int -> [a] -> [a]'; - } - }, - { - guide: function(result) { - showTypes = true; - return "

            " + rmsg(["Partial application"]) + "

            " + - - "

            You've got a function of type [a] -> [a]! The drop function is considered a multi-parameter function. Remember the map function? Its parameters were a function and a list. Just another multi-parameter function.

            " + - - "

            You can add another parameter and, hey presto, you get a list!

            " + - - "drop 3 \"hello!\"" - - }, - trigger: function(result) { - return result.type == '[a] -> [a]'; - } - }, - { - guide: function(result) { - showTypes = true; - return "

            " + rmsg(["Higher order functions"]) + "

            " + - - "

            'Lo bob! You've already used the map function loads. I wonder if you can guess its type?

            " + - - "

            map :: (a -> b) -> [a] -> [b] (spoiler)

            " + - - "

            It's okay to peek! Have a go at guessing these: filter, take

            " + - - "

            Tip: You can use parantheses to use more than one function. You want to double all the numbers over five? Psch!

            " + - "map (*2) (filter (>5) [10,2,16,9,4])" - }, - trigger: function(result) { - return result.expr.match(/^[ ]*drop[ ]*[0-9]+[ ]*"[^"]+"[ ]*$/) && - result.type == '[Char]'; - } - }, - { - guide: function(result) { - showTypes = true; - return "

            " + rmsg(["Phew! Rest time!"]) + "

            " + - - "

            Wow! You're doing so great! Have a look at what you know now!

            " + - - "
              " + - "
            1. Function parameters can be polymorphic; any type!
            2. " + - "
            3. Functions can have multiple parameters by returning more functions.
            4. " + - "
            5. You can wrap expressions in parentheses and apply functions to them as a whole value.
            6. " + - "
            " + - - "

            You're really making great progress. Don't hesitate to sit and play in the console between chapters to get a good feel of it!

            " + - - "

            Stay tuned for more chapters on type classes and the meaning of :t 1, :t (*), etc.

            " + - learnMore - }, - trigger: function(result) { - return result.type == '(Num a, Ord a) => [a]'; - } - } - ]; - // - // var webchat; - // - // function runWebchat() { - // if (!webchat) { - // // Create webchat frame - // var webchat = - // $(''); - // webchat.attr('width', 635); - // webchat.attr('height', 500); - // webchat.css('float', 'left'); - // webchat.css('webkit-border-radius', '3px'); - // webchat.css('moz-border-radius', '3px'); - // webchat.css('border-radius', '3px'); - // webchat.css('border', '5px solid #eeeeee'); - // - // // Extend page wrap to fit console and chat - // $('.page-wrap').css({ - // width: '1250px' - // }); - // $('.primary-content').css('margin-left', 0); - // $('.page-wrap').append(webchat.css('margin-left', '5px')); - // } - // } - - var pageTrigger = -1; - var notices = []; - var controller; - // Console controller - var learnMore; - - //////////////////////////////////////////////////////////////////////// - // Unshow a string - function unString(str) { - return str.replace(/^"(.*)"$/, "$1").replace(/\\"/, '"'); - } - - //////////////////////////////////////////////////////////////////////// - // Random message from a list of messages - function rmsg(choices) { - return choices[Math.floor((Math.random() * 100) % choices.length)]; - } - - // Simple HTML encoding - // Simply replace '<', '>' and '&' - // TODO: Use jQuery's .html() trick, or grab a proper, fast - // HTML encoder. - function htmlEncode(text, shy) { - return ( - ('' + text).replace(/&/g, '&') - .replace(/'); - handleJSON = function(r) { - script.remove(); - func(r); - }; - script.attr('src', url); - $('body').append(script); - } - - - var console = $('.console'); - controller = console.console({ - promptLabel: '> ', - continuedPromptLabel: ' .. ', /*not quiet right but good enough*/ - cancelHandle: function() { - controller.commandRef.ignore = true; - controller.finishCommand(); - controller.report(); - }, - - commandHandle: function(line, report) { - - controller.ajaxloader = $('

            Loading...

            '); - var commandRef = {}; - controller.currentLine = line; - controller.commandRef = commandRef; - controller.report = report; - if (tellAboutRet) tellAboutRet.fadeOut(function() { - $(this).remove(); - }); - - if (libTrigger(line, report)) return; - controller.inner.append(controller.ajaxloader); - controller.scrollToBottom(); - - jsonp("http://localhost:3030/tryruby/run/?cmd=" + encodeHex(line), - function(resp) { - if (commandRef.ignore) { - return; - } - controller.finishCommand(); - var result = resp; - if (pageTrigger > -1 && result.expr) { - triggerTutorialPage(pageTrigger, result); - } - if (result.type) { - if (pageTrigger == 24) showTypes = false; - handleSuccess(report, result); - } else if (result.error) { - report( - [{ - msg: result.error, - className: "jquery-console-message-error jquery-console-message-compile-error" - }] - ); - notice('compile-error', - "A compile-time error! " + - "It just means the expression wasn't quite right. " + - "Try again.", - 'prompt'); - } else if (result.exception) { - var err = limitsError(result.exception); - report( - [{ - msg: err, - className: "jquery-console-message-error jquery-console-message-exception" - }] - ); - if (err == result.exception) { - notice('compile-error', - "A run-time error! The expression was right but the" + - " result didn't make sense. Check your expression and try again.", - 'prompt'); - } - } else if (result.internal) { - report( - [{ - msg: limitsError(result.internal), - className: "jquery-console-message-error jquery-console-message-internal" - }] - ); - } else if (result.bind) { - report(); - } else if (result.result) { - if (result.expr.match(/^:modules/)) { - report( - [{ - msg: result.result.replace(/[\["\]]/g, '') - .replace(/,/g, ', '), - className: "jquery-console-message-type" - }]); - } - } - }); - - }, - - charInsertTrigger: function() { - var t = notice('tellaboutreturn', - "Hit Return when you're " + - "finished typing your expression."); - if (t) tellAboutRet = t; - return true; - }, - autofocus: true, - promptHistory: true, - historyPreserveColumn: true, - welcomeMessage: 'Interactive ruby ready' - }); - - controller.finishCommand = function() { - controller.ajaxloader.remove(); - $('.jquery-console-prompt :last').each(function() { - lastLine = controller.currentLine; - if (!$(this).hasClass('prompt-done')) { - $(this).addClass('prompt-done'); - $(this).click(function() { - controller.promptText(controller.currentLine); - }); - } - }); - } - - makeGuidSamplesClickable(); - - var match = window.location.href.match(/#([0-9]+)$/); - if (match) { - pageTrigger = match[1] - 1; - setTutorialPage(undefined, match[1] - 1); - } - - var match = window.location.href.match(/\?input=([^&]+)/); - if (match) { - controller.promptText(urlDecode(match[1])); - controller.inner.click(); - controller.typer.consoleControl(13); - } - }); - - function urlDecode(encodedString) { - var output = encodedString; - var binVal, - thisString; - var myregexp = /(%[^%]{2})/; - while ((match = myregexp.exec(output)) != null - && match.length > 1 - && match[1] != '') { - binVal = parseInt(match[1].substr(1), 16); - thisString = String.fromCharCode(binVal); - output = output.replace(match[1], thisString); - } - return output; - } - - function makeGuidSamplesClickable() { - $('.chapmark code').each(function() { - $(this).css('cursor', 'pointer'); - $(this).attr('title', 'Click me to insert "' + - $(this).text() + '" into the console.'); - $(this).click(function() { - controller.promptText($(this).text()); - controller.inner.click(); - }); - }); - } - - String.prototype.trim = function() { - return this.replace(/^[\t ]*(.*)[\t ]*$/, '$1'); - }; - - //////////////////////////////////////////////////////////////////////// - // Trigger console commands - function libTrigger(line, report) { - switch (line.trim()) { - case 'help': - { - setTutorialPage(undefined, 0); - report(); - pageTrigger = 0; - return true; - } - case 'back': - { - if (pageTrigger > 0) { - setTutorialPage(undefined, pageTrigger - 1); - pageTrigger--; - report(); - return true; - } - break; - } - case 'lessons': - { - var lessons = $('
              '); - for (var i = 0; i < pages.length; i++) { - if (pages[i].lesson) { - lessons.append($('
            1. '). - html('lesson' + pages[i].lesson + ' - ' + - pages[i].title)); - } - } - var lessonsList = '

              Lessons

              ' + lessons.html(); - tutorialGuide.animate({ - opacity: 0, - height: 0 - }, - 'fast', - function() { - tutorialGuide.html(lessonsList); - tutorialGuide.css({ - height: 'auto' - }); - tutorialGuide.animate({ - opacity: 1 - }, - 'fast'); - makeGuidSamplesClickable(); - }); - report(); - return true; - } - default: - { - if (line.trim() == 'chat') { - notice('irc', - 'Enter your nick on the right hand side and hit Connect!', - 'prompt'); - report(); - runWebchat(); - return true; - } - - var m = line.trim().match(/^link(.*)/); - if (m) { - var data; - if (m[1]) data = m[1].trim(); - else if (lastLine) data = lastLine; - if (data) { - var addr = '?input=' + encodeHex(data); - report([{ - msg: '', - className: 'latest-link' - }]); - var link = $(''). - text('link for ' + data).click(function() { - window.location.href = $(this).attr('href'); - return false; - }); - $('.latest-link').html(link).removeClass('latest-link'); - return true; - } - } - - var m = line.trim().match(/^step([0-9]+)/); - if (m) { - if ((m[1] * 1) <= pages.length) { - setTutorialPage(undefined, m[1] - 1); - report(); - pageTrigger = m[1] - 1; - return true; - } - } - var m = line.trim().match(/^help ([0-9]+)/); - if (m) { - for (var i = 0; i < pages.length; i++) { - if (pages[i].lesson == m[1] * 1) { - setTutorialPage(undefined, i); - report(); - pageTrigger = i; - return true; - } - } - } - } - }; - }; - - //////////////////////////////////////////////////////////////////////// - // Change the tutorial page - function setTutorialPage(result, n) { - if (pages[n]) { - window.location.href = '#' + (1 * n + 1); - tutorialGuide.find('#helpstone').remove(); - tutorialGuide.animate({ - opacity: 0, - height: 0 - }, - 'fast', - function() { - if (typeof(pages[n].guide) == 'function') - tutorialGuide.html(pages[n].guide(result)); - else - tutorialGuide.html(pages[n].guide); - var back = ''; - if (pageTrigger > 0) - back = 'You\'re at step' + (n + 1) - + '. Type back to go back.'; - else - back = 'You\'re at step' + (n + 1) + '. Type step' + (n + 1) - + ' to return here.'; - if (true) tutorialGuide - .append('
              ' + back + '
              ') - .append('
              Lesson: ' + - searchLessonBack(n) + - '
              '); - tutorialGuide.css({ - height: 'auto' - }); - tutorialGuide.animate({ - opacity: 1 - }, - 'fast'); - makeGuidSamplesClickable(); - }); - } - }; - - function searchLessonBack(page) { - for (var i = page; i >= 0; i--) { - if (pages[i].lesson) return pages[i].lesson; - } - return "1"; - } - - //////////////////////////////////////////////////////////////////////// - // Trigger a page according to a result - function triggerTutorialPage(n, result) { - n++; - if (pages[n] && (typeof(pages[n].trigger) == 'function') - && pages[n].trigger(result)) { - pageTrigger++; - setTutorialPage(result, n); - } - }; - - //////////////////////////////////////////////////////////////////////// - // Trigger various libraries after JSONRPC returned - function handleSuccess(report, result) { - if (result.type.match(/^Graphics\.Raphael\.Raphael[\r\n ]/)) { - runRaphael(result.result); - report(); - } - if (result.type.match(/standard/)) { - var hashrocket = ''; - var msg_value = ' => '; - if (result.result == null) { - hashrocket = ' => ' - msg_value = ''; - } - report( - [{ - msg: msg_value + result.output + hashrocket + result.result, - className: "jquery-console-message-value" - }]); - } - - if (result.type.match(/error/)) { - - report( - [{ - msg: result.error, - className: "jquery-console-message-value" - }]); - } - - if (result.type.match(/illegal/)) { - - report( - [{ - msg: 'You are not allowed to run that command!', - className: "jquery-console-message-value" - }]); - } - - - if (result.type.match(/line_continuation/)) { - report( - [{ - msg: '..', - className: "jquery-console-prompt-label" - }]); - } - - }; - - //////////////////////////////////////////////////////////////////////// - // Raphael support - function runRaphael(expr) { - raphaelPaper.clear(); - $('#raphael').parent().parent().slideDown(function() { - var exprs = expr.split(/\n/g); - for (var i = 0; i < exprs.length; i++) - raphaelRunExpr(exprs[i]); - }); - } - function raphaelRunExpr(expr) { - var expr = expr.split(/ /g); - switch (expr[0]) { - case 'new': - { - switch (expr[2]) { - case 'circle': - { - var x = expr[3], - y = expr[4], - radius = expr[5]; - var circle = raphaelPaper.circle(x * 1, y * 1, radius * 1); - circle.attr("fill", "#7360a4"); - break; - } - } - } - } - } - - function notice(name, msg, style) { - if (opera()) return; - if (!notices[name]) { - notices[name] = name; - return controller.notice(msg, style); - } - } - - function limitsError(str) { - if (str == "Terminated!") { - notice('terminated', - "This error means it took to long to work" + - " out on the server.", - 'fadeout'); - return "Terminated!"; - } else if (str == "Time limit exceeded.") { - notice('exceeded', - "This error means it took to long to work out on the server. " + - "Try again.", - 'fadeout'); - return "Terminated! Try again."; - } - return str; - } - -})(jQuery); diff --git a/public/javascripts/jquery-1.3.2.min.js b/public/javascripts/jquery-1.3.2.min.js deleted file mode 100644 index b1ae21d..0000000 --- a/public/javascripts/jquery-1.3.2.min.js +++ /dev/null @@ -1,19 +0,0 @@ -/* - * jQuery JavaScript Library v1.3.2 - * http://jquery.com/ - * - * Copyright (c) 2009 John Resig - * Dual licensed under the MIT and GPL licenses. - * http://docs.jquery.com/License - * - * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) - * Revision: 6246 - */ -(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("",""]||!O.indexOf("",""]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
              "]||!O.indexOf("",""]||(!O.indexOf("",""]||!O.indexOf("",""]||!o.support.htmlSerialize&&[1,"div
              ","
              "]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}}); -/* - * Sizzle CSS Selector Engine - v0.9.3 - * Copyright 2009, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * More information: http://sizzlejs.com/ - */ -(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return UT[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="

              ";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="
              ";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("
              ").append(M.responseText.replace(//g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='
              ';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})(); \ No newline at end of file diff --git a/public/javascripts/jquery-1.4.2.min.js b/public/javascripts/jquery-1.4.2.min.js deleted file mode 100644 index 7c24308..0000000 --- a/public/javascripts/jquery-1.4.2.min.js +++ /dev/null @@ -1,154 +0,0 @@ -/*! - * jQuery JavaScript Library v1.4.2 - * http://jquery.com/ - * - * Copyright 2010, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2010, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Sat Feb 13 22:33:48 2010 -0500 - */ -(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, -Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& -(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, -a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== -"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, -function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
              a"; -var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, -parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= -false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= -s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, -applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; -else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, -a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== -w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, -cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= -c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); -a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, -function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); -k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), -C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B=0){a.type= -e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& -f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; -if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", -e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, -"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, -d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, -e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); -t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| -g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, -CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, -g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, -text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, -setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= -h[3];l=0;for(m=h.length;l=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== -"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, -h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& -q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; -if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="

              ";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); -(function(){var g=s.createElement("div");g.innerHTML="
              ";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: -function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var j=d;j0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= -{},i;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== -"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", -d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? -a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== -1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"},F={option:[1,""],legend:[1,"
              ","
              "],thead:[1,"","
              "],tr:[2,"","
              "],td:[3,"","
              "],col:[2,"","
              "],area:[1,"",""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
              ","
              "];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= -c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, -wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, -prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, -this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); -return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, -""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); -return this}else{e=0;for(var j=d.length;e0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", -""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===""&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= -c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? -c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= -function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= -Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, -"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= -a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= -a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=//gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!== -"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("
              ").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this}, -serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), -function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href, -global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&& -e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)? -"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache=== -false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B= -false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since", -c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E|| -d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x); -g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status=== -1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b=== -"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional; -if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration=== -"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]|| -c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start; -this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now= -this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem, -e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b
              "; -a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b); -c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a, -d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top- -f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset": -"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in -e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window); diff --git a/public/javascripts/jquery.console.js b/public/javascripts/jquery.console.js deleted file mode 100644 index d45390d..0000000 --- a/public/javascripts/jquery.console.js +++ /dev/null @@ -1,609 +0,0 @@ -// JQuery Console 1.0 -// Sun Feb 21 20:28:47 GMT 2010 -// -// Copyright 2010 Chris Done, Simon David Pratt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// 1. Redistributions of source code must retain the above -// copyright notice, this list of conditions and the following -// disclaimer. -// -// 2. Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// TESTED ON -// Internet Explorer 6 -// Opera 10.01 -// Chromium 4.0.237.0 (Ubuntu build 31094) -// Firefox 3.5.8, 3.6.2 (Mac) -// Safari 4.0.5 (6531.22.7) (Mac) -// Google Chrome 5.0.375.55 (Mac) - -(function($){ - $.fn.console = function(config){ - //////////////////////////////////////////////////////////////////////// - // Constants - // Some are enums, data types, others just for optimisation - var keyCodes = { - // left - 37: moveBackward, - // right - 39: moveForward, - // up - 38: previousHistory, - // down - 40: nextHistory, - // backspace - 8: backDelete, - // delete - 46: forwardDelete, - // end - 35: moveToEnd, - // start - 36: moveToStart, - // return - 13: commandTrigger, - // tab - 18: doNothing - }; - var ctrlCodes = { - // C-a - 65: moveToStart, - // C-e - 69: moveToEnd, - // C-d - 68: forwardDelete, - // C-n - 78: nextHistory, - // C-p - 80: previousHistory, - // C-b - 66: moveBackward, - // C-f - 70: moveForward, - // C-k - 75: deleteUntilEnd - }; - var altCodes = { - // M-f - 70: moveToNextWord, - // M-b - 66: moveToPreviousWord, - // M-d - 68: deleteNextWord - }; - var cursor = ' '; - // Opera only works with this character, not or ­, - // but IE6 displays this character, which is bad, so just use - // it on Opera. - var wbr = $.browser.opera? '​' : ''; - - //////////////////////////////////////////////////////////////////////// - // Globals - var container = $(this); - var inner = $('
              '); - var typer = $(''); - // Prompt - var promptBox; - var prompt; - var promptLabel = config && config.promptLabel? config.promptLabel : "> "; - var column = 0; - var promptText = ''; - var restoreText = ''; - // Prompt history stack - var history = []; - var ringn = 0; - // For reasons unknown to The Sword of Michael himself, Opera - // triggers and sends a key character when you hit various - // keys like PgUp, End, etc. So there is no way of knowing - // when a user has typed '#' or End. My solution is in the - // typer.keydown and typer.keypress functions; I use the - // variable below to ignore the keypress event if the keydown - // event succeeds. - var cancelKeyPress = 0; - // When this value is false, the prompt will not respond to input - var acceptInput = true; - // When this value is true, the command has been canceled - var cancelCommand = false; - - // External exports object - var extern = {}; - - //////////////////////////////////////////////////////////////////////// - // Main entry point - (function(){ - container.append(inner); - inner.append(typer); - typer.css({position:'absolute',top:0,left:'-9999px'}); - if (config.welcomeMessage) - message(config.welcomeMessage,'jquery-console-welcome'); - newPromptBox(); - if (config.autofocus) { - inner.addClass('jquery-console-focus'); - typer.focus(); - setTimeout(function(){ - inner.addClass('jquery-console-focus'); - typer.focus(); - },100); - } - extern.inner = inner; - extern.typer = typer; - extern.scrollToBottom = scrollToBottom; - })(); - - //////////////////////////////////////////////////////////////////////// - // Reset terminal - extern.reset = function(){ - var welcome = true; - inner.parent().fadeOut(function(){ - inner.find('div').each(function(){ - if (!welcome) - $(this).remove(); - welcome = false; - }); - newPromptBox(); - inner.parent().fadeIn(function(){ - inner.addClass('jquery-console-focus'); - typer.focus(); - }); - }); - }; - - //////////////////////////////////////////////////////////////////////// - // Reset terminal - extern.notice = function(msg,style){ - var n = $('
              ').append($('
              ').text(msg)) - .css({visibility:'hidden'}); - container.append(n); - var focused = true; - if (style=='fadeout') - setTimeout(function(){ - n.fadeOut(function(){ - n.remove(); - }); - },4000); - else if (style=='prompt') { - var a = $('
              '); - n.append(a); - focused = false; - a.click(function(){ n.fadeOut(function(){ n.remove();inner.css({opacity:1}) }); }); - } - var h = n.height(); - n.css({height:'0px',visibility:'visible'}) - .animate({height:h+'px'},function(){ - if (!focused) inner.css({opacity:0.5}); - }); - n.css('cursor','default'); - return n; - }; - - //////////////////////////////////////////////////////////////////////// - // Make a new prompt box - function newPromptBox() { - column = 0; - promptText = ''; - ringn = 0; // Reset the position of the history ring - enableInput(); - promptBox = $('
              '); - var label = $(''); - promptBox.append(label.text(promptLabel).show()); - prompt = $(''); - promptBox.append(prompt); - inner.append(promptBox); - updatePromptDisplay(); - }; - - //////////////////////////////////////////////////////////////////////// - // Handle setting focus - container.click(function(){ - inner.addClass('jquery-console-focus'); - inner.removeClass('jquery-console-nofocus'); - typer.focus(); - scrollToBottom(); - return false; - }); - - //////////////////////////////////////////////////////////////////////// - // Handle losing focus - typer.blur(function(){ - inner.removeClass('jquery-console-focus'); - inner.addClass('jquery-console-nofocus'); - }); - - //////////////////////////////////////////////////////////////////////// - // Handle key hit before translation - // For picking up control characters like up/left/down/right - - typer.keydown(function(e){ - cancelKeyPress = 0; - var keyCode = e.keyCode; - // C-c: cancel the execution - if(e.ctrlKey && keyCode == 67) { - cancelKeyPress = keyCode; - cancelExecution(); - return false; - } - if (acceptInput) { - if (keyCode in keyCodes) { - cancelKeyPress = keyCode; - (keyCodes[keyCode])(); - return false; - } else if (e.ctrlKey && keyCode in ctrlCodes) { - cancelKeyPress = keyCode; - (ctrlCodes[keyCode])(); - return false; - } else if (e.altKey && keyCode in altCodes) { - cancelKeyPress = keyCode; - (altCodes[keyCode])(); - return false; - } - } - }); - - //////////////////////////////////////////////////////////////////////// - // Handle key press - typer.keypress(function(e){ - var keyCode = e.keyCode || e.which; - if (isIgnorableKey(e)) { - return false; - } - if (acceptInput && cancelKeyPress != keyCode && keyCode >= 32){ - if (cancelKeyPress) return false; - if (typeof config.charInsertTrigger == 'undefined' || - (typeof config.charInsertTrigger == 'function' && - config.charInsertTrigger(keyCode,promptText))) - typer.consoleInsert(keyCode); - } - if ($.browser.webkit) return false; - }); - - function isIgnorableKey(e) { - // for now just filter alt+tab that we receive on some platforms when - // user switches windows (goes away from the browser) - return ((e.keyCode == keyCodes.tab || e.keyCode == 192) && e.altKey); - }; - - //////////////////////////////////////////////////////////////////////// - // Rotate through the command history - function rotateHistory(n){ - if (history.length == 0) return; - ringn += n; - if (ringn < 0) ringn = history.length; - else if (ringn > history.length) ringn = 0; - var prevText = promptText; - if (ringn == 0) { - promptText = restoreText; - } else { - promptText = history[ringn - 1]; - } - if (config.historyPreserveColumn) { - if (promptText.length < column + 1) { - column = promptText.length; - } else if (column == 0) { - column = promptText.length; - } - } else if (config.historyColumnAtEnd) { - column = promptText.length; - } else { - column = 0; - } - updatePromptDisplay(); - }; - - function previousHistory() { - rotateHistory(-1); - }; - - function nextHistory() { - rotateHistory(1); - }; - - // Add something to the history ring - function addToHistory(line){ - history.push(line); - restoreText = ''; - }; - - // Delete the character at the current position - function deleteCharAtPos(){ - if (column < promptText.length){ - promptText = - promptText.substring(0,column) + - promptText.substring(column+1); - restoreText = promptText; - return true; - } else return false; - }; - - function backDelete() { - if (moveColumn(-1)){ - deleteCharAtPos(); - updatePromptDisplay(); - } - }; - - function forwardDelete() { - if (deleteCharAtPos()) - updatePromptDisplay(); - }; - - function deleteUntilEnd() { - while(deleteCharAtPos()) { - updatePromptDisplay(); - } - }; - - function deleteNextWord() { - // A word is defined within this context as a series of alphanumeric - // characters. - // Delete up to the next alphanumeric character - while(column < promptText.length && - !isCharAlphanumeric(promptText[column])) { - deleteCharAtPos(); - updatePromptDisplay(); - } - // Then, delete until the next non-alphanumeric character - while(column < promptText.length && - isCharAlphanumeric(promptText[column])) { - deleteCharAtPos(); - updatePromptDisplay(); - } - }; - - //////////////////////////////////////////////////////////////////////// - // Validate command and trigger it if valid, or show a validation error - function commandTrigger() { - var line = promptText; - if (typeof config.commandValidate == 'function') { - var ret = config.commandValidate(line); - if (ret == true || ret == false) { - if (ret) { - handleCommand(); - } - } else { - commandResult(ret,"jquery-console-message-error"); - } - } else { - handleCommand(); - } - }; - - // Scroll to the bottom of the view - function scrollToBottom() { - inner.attr({ scrollTop: inner.attr("scrollHeight") });; - }; - - function cancelExecution() { - if(typeof config.cancelHandle == 'function') { - config.cancelHandle(); - } - } - - //////////////////////////////////////////////////////////////////////// - // Handle a command - function handleCommand() { - if (typeof config.commandHandle == 'function') { - disableInput(); - addToHistory(promptText); - var ret = config.commandHandle(promptText,function(msgs){ - commandResult(msgs); - }); - if (typeof ret == 'boolean') { - if (ret) { - // Command succeeded without a result. - commandResult(); - } else { - commandResult('Command failed.', - "jquery-console-message-error"); - } - } else if (typeof ret == "string") { - commandResult(ret,"jquery-console-message-success"); - } else if (typeof ret == 'object' && ret.length) { - commandResult(ret); - } - } - }; - - //////////////////////////////////////////////////////////////////////// - // Disable input - function disableInput() { - acceptInput = false; - }; - - // Enable input - function enableInput() { - acceptInput = true; - } - - //////////////////////////////////////////////////////////////////////// - // Reset the prompt in invalid command - function commandResult(msg,className) { - column = -1; - updatePromptDisplay(); - if (typeof msg == 'string') { - message(msg,className); - } else { - for (var x in msg) { - var ret = msg[x]; - message(ret.msg,ret.className); - } - } - newPromptBox(); - }; - - //////////////////////////////////////////////////////////////////////// - // Display a message - function message(msg,className) { - var mesg = $('
              '); - if (className) mesg.addClass(className); - mesg.filledText(msg).hide(); - inner.append(mesg); - mesg.show(); - }; - - //////////////////////////////////////////////////////////////////////// - // Handle normal character insertion - typer.consoleInsert = function(keyCode){ - // TODO: remove redundant indirection - var char = String.fromCharCode(keyCode); - var before = promptText.substring(0,column); - var after = promptText.substring(column); - promptText = before + char + after; - moveColumn(1); - restoreText = promptText; - updatePromptDisplay(); - }; - - //////////////////////////////////////////////////////////////////////// - // Move to another column relative to this one - // Negative means go back, positive means go forward. - function moveColumn(n){ - if (column + n >= 0 && column + n <= promptText.length){ - column += n; - return true; - } else return false; - }; - - function moveForward() { - if(moveColumn(1)) { - updatePromptDisplay(); - return true; - } - return false; - }; - - function moveBackward() { - if(moveColumn(-1)) { - updatePromptDisplay(); - return true; - } - return false; - }; - - function moveToStart() { - if (moveColumn(-column)) - updatePromptDisplay(); - }; - - function moveToEnd() { - if (moveColumn(promptText.length-column)) - updatePromptDisplay(); - }; - - function moveToNextWord() { - while(column < promptText.length && - !isCharAlphanumeric(promptText[column]) && - moveForward()) { - } - while(column < promptText.length && - isCharAlphanumeric(promptText[column]) && - moveForward()) { - } - }; - - function moveToPreviousWord() { - // Move backward until we find the first alphanumeric - while(column -1 >= 0 && - !isCharAlphanumeric(promptText[column-1]) && - moveBackward()) { - } - // Move until we find the first non-alphanumeric - while(column -1 >= 0 && - isCharAlphanumeric(promptText[column-1]) && - moveBackward()) { - } - }; - - function isCharAlphanumeric(charToTest) { - if(typeof charToTest == 'string') { - var code = charToTest.charCodeAt(); - return (code >= 'A'.charCodeAt() && code <= 'Z'.charCodeAt()) || - (code >= 'a'.charCodeAt() && code <= 'z'.charCodeAt()) || - (code >= '0'.charCodeAt() && code <= '9'.charCodeAt()); - } - return false; - }; - - function doNothing() {}; - - extern.promptText = function(text){ - if (text) { - promptText = text; - if (column > promptText.length) - column = promptText.length; - updatePromptDisplay(); - } - return promptText; - }; - - //////////////////////////////////////////////////////////////////////// - // Update the prompt display - function updatePromptDisplay(){ - var line = promptText; - var html = ''; - if (column > 0 && line == ''){ - // When we have an empty line just display a cursor. - html = cursor; - } else if (column == promptText.length){ - // We're at the end of the line, so we need to display - // the text *and* cursor. - html = htmlEncode(line) + cursor; - } else { - // Grab the current character, if there is one, and - // make it the current cursor. - var before = line.substring(0, column); - var current = line.substring(column,column+1); - if (current){ - current = - '' + - htmlEncode(current) + - ''; - } - var after = line.substring(column+1); - html = htmlEncode(before) + current + htmlEncode(after); - } - prompt.html(html); - scrollToBottom(); - }; - - // Simple HTML encoding - // Simply replace '<', '>' and '&' - // TODO: Use jQuery's .html() trick, or grab a proper, fast - // HTML encoder. - function htmlEncode(text){ - return ( - text.replace(/&/g,'&') - .replace(/&]{10})/g,'$1­' + wbr) - ); - }; - - return extern; - }; - // Simple utility for printing messages - $.fn.filledText = function(txt){ - $(this).text(txt); - $(this).html($(this).html().replace(/\n/g,'
              ')); - return this; - }; -})(jQuery); diff --git a/public/javascripts/jquery.console.min.js b/public/javascripts/jquery.console.min.js deleted file mode 100644 index 7ae1e6b..0000000 --- a/public/javascripts/jquery.console.min.js +++ /dev/null @@ -1 +0,0 @@ -(function($){$.fn.console=function(config){var keyCodes={left:37,right:39,up:38,down:40,back:8,del:46,end:35,start:36,ret:13};var cursor=' ';var wbr=$.browser.opera?'​':'';var container=$(this);var inner=$('
              ');var typer=$('');var promptBox;var prompt;var promptLabel=config&&config.promptLabel?config.promptLabel:"> ";var column=0;var promptText='';var restoreText='';var history=[];var ringn=0;var cancelKeyPress=0;var extern={};(function(){container.append(inner);inner.append(typer);typer.css({position:'absolute',top:0,left:'-999px'});if(config.welcomeMessage)message(config.welcomeMessage,'jquery-console-welcome');newPromptBox();if(config.autofocus){inner.addClass('jquery-console-focus');typer.focus();setTimeout(function(){inner.addClass('jquery-console-focus');typer.focus()},100)}})();extern.reset=function(){var welcome=true;inner.parent().fadeOut(function(){inner.find('div').each(function(){if(!welcome)$(this).remove();welcome=false});newPromptBox();inner.parent().fadeIn(function(){inner.addClass('jquery-console-focus');typer.focus()})})};function newPromptBox(){column=0;promptText='';promptBox=$('
              ');var label=$('');promptBox.append(label.text(promptLabel).show());prompt=$('');promptBox.append(prompt);inner.append(promptBox);updatePromptDisplay()};container.click(function(){inner.addClass('jquery-console-focus');inner.removeClass('jquery-console-nofocus');typer.focus();scrollToBottom();return false});typer.blur(function(){inner.removeClass('jquery-console-focus');inner.addClass('jquery-console-nofocus')});typer.keydown(function(e){cancelKeyPress=0;var keyCode=e.keyCode;if(isControlCharacter(keyCode)){cancelKeyPress=keyCode;if(!typer.consoleControl(keyCode)){return false}}});typer.keypress(function(e){var keyCode=e.keyCode||e.which;if(cancelKeyPress!=keyCode&&keyCode>=32){if(cancelKeyPress)return false;typer.consoleInsert(keyCode)}if($.browser.webkit)return false});function isControlCharacter(keyCode){return((keyCode>=keyCodes.left&&keyCode<=keyCodes.down)||keyCode==keyCodes.back||keyCode==keyCodes.del||keyCode==keyCodes.end||keyCode==keyCodes.start||keyCode==keyCodes.ret)};typer.consoleControl=function(keyCode){switch(keyCode){case keyCodes.left:{moveColumn(-1);updatePromptDisplay();return false;break}case keyCodes.right:{moveColumn(1);updatePromptDisplay();return false;break}case keyCodes.back:{if(moveColumn(-1)){deleteCharAtPos();updatePromptDisplay()}return false;break}case keyCodes.del:{if(deleteCharAtPos())updatePromptDisplay();return false;break}case keyCodes.end:{if(moveColumn(promptText.length-column))updatePromptDisplay();return false;break}case keyCodes.start:{if(moveColumn(-column))updatePromptDisplay();return false;break}case keyCodes.ret:{commandTrigger();return false}case keyCodes.up:{rotateHistory(-1);return false}case keyCodes.down:{rotateHistory(1);return false}default:}};function rotateHistory(n){if(history.length==0)return;ringn+=n;if(ringn<0)ringn=history.length;else if(ringn>history.length)ringn=0;var prevText=promptText;if(ringn==0){promptText=restoreText}else{promptText=history[ringn-1]}if(config.historyPreserveColumn){if(promptText.length
              ');if(className)mesg.addClass(className);mesg.filledText(msg).hide();inner.append(mesg);mesg.show()};typer.consoleInsert=function(keyCode){var char=String.fromCharCode(keyCode);var before=promptText.substring(0,column);var after=promptText.substring(column);promptText=before+char+after;moveColumn(1);restoreText=promptText;updatePromptDisplay()};function moveColumn(n){if(column+n>=0&&column+n<=promptText.length){column+=n;return true}else return false};function updatePromptDisplay(){var line=promptText;var html='';if(column>0&&line==''){html=cursor}else if(column==promptText.length){html=htmlEncode(line)+cursor}else{var before=line.substring(0,column);var current=line.substring(column,column+1);if(current){current=''+htmlEncode(current)+''}var after=line.substring(column+1);html=htmlEncode(before)+current+htmlEncode(after)}prompt.html(html);scrollToBottom()};function htmlEncode(text){return(text.replace(/&/g,'&').replace(/&]{10})/g,'$1­'+wbr))};return extern};$.fn.filledText=function(txt){$(this).text(txt);$(this).html($(this).html().replace(/\n/g,'
              '));return this}})(jQuery); \ No newline at end of file diff --git a/public/javascripts/jquery.js b/public/javascripts/jquery.js deleted file mode 100755 index 3747929..0000000 --- a/public/javascripts/jquery.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * jQuery 1.2.3 - New Wave Javascript - * - * Copyright (c) 2008 John Resig (jquery.com) - * Dual licensed under the MIT (MIT-LICENSE.txt) - * and GPL (GPL-LICENSE.txt) licenses. - * - * $Date: 2008-02-06 00:21:25 -0500 (Wed, 06 Feb 2008) $ - * $Rev: 4663 $ - */ -(function(){if(window.jQuery)var _jQuery=window.jQuery;var jQuery=window.jQuery=function(selector,context){return new jQuery.prototype.init(selector,context);};if(window.$)var _$=window.$;window.$=jQuery;var quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;var isSimple=/^.[^:#\[\.]*$/;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;return this;}else if(typeof selector=="string"){var match=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1])selector=jQuery.clean([match[1]],context);else{var elem=document.getElementById(match[3]);if(elem)if(elem.id!=match[3])return jQuery().find(selector);else{this[0]=elem;this.length=1;return this;}else -selector=[];}}else -return new jQuery(context).find(selector);}else if(jQuery.isFunction(selector))return new jQuery(document)[jQuery.fn.ready?"ready":"load"](selector);return this.setArray(selector.constructor==Array&&selector||(selector.jquery||selector.length&&selector!=window&&!selector.nodeType&&selector[0]!=undefined&&selector[0].nodeType)&&jQuery.makeArray(selector)||[selector]);},jquery:"1.2.3",size:function(){return this.length;},length:0,get:function(num){return num==undefined?jQuery.makeArray(this):this[num];},pushStack:function(elems){var ret=jQuery(elems);ret.prevObject=this;return ret;},setArray:function(elems){this.length=0;Array.prototype.push.apply(this,elems);return this;},each:function(callback,args){return jQuery.each(this,callback,args);},index:function(elem){var ret=-1;this.each(function(i){if(this==elem)ret=i;});return ret;},attr:function(name,value,type){var options=name;if(name.constructor==String)if(value==undefined)return this.length&&jQuery[type||"attr"](this[0],name)||undefined;else{options={};options[name]=value;}return this.each(function(i){for(name in options)jQuery.attr(type?this.style:this,name,jQuery.prop(this,options[name],type,i,name));});},css:function(key,value){if((key=='width'||key=='height')&&parseFloat(value)<0)value=undefined;return this.attr(key,value,"curCSS");},text:function(text){if(typeof text!="object"&&text!=null)return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(text));var ret="";jQuery.each(text||this,function(){jQuery.each(this.childNodes,function(){if(this.nodeType!=8)ret+=this.nodeType!=1?this.nodeValue:jQuery.fn.text([this]);});});return ret;},wrapAll:function(html){if(this[0])jQuery(html,this[0].ownerDocument).clone().insertBefore(this[0]).map(function(){var elem=this;while(elem.firstChild)elem=elem.firstChild;return elem;}).append(this);return this;},wrapInner:function(html){return this.each(function(){jQuery(this).contents().wrapAll(html);});},wrap:function(html){return this.each(function(){jQuery(this).wrapAll(html);});},append:function(){return this.domManip(arguments,true,false,function(elem){if(this.nodeType==1)this.appendChild(elem);});},prepend:function(){return this.domManip(arguments,true,true,function(elem){if(this.nodeType==1)this.insertBefore(elem,this.firstChild);});},before:function(){return this.domManip(arguments,false,false,function(elem){this.parentNode.insertBefore(elem,this);});},after:function(){return this.domManip(arguments,false,true,function(elem){this.parentNode.insertBefore(elem,this.nextSibling);});},end:function(){return this.prevObject||jQuery([]);},find:function(selector){var elems=jQuery.map(this,function(elem){return jQuery.find(selector,elem);});return this.pushStack(/[^+>] [^+>]/.test(selector)||selector.indexOf("..")>-1?jQuery.unique(elems):elems);},clone:function(events){var ret=this.map(function(){if(jQuery.browser.msie&&!jQuery.isXMLDoc(this)){var clone=this.cloneNode(true),container=document.createElement("div");container.appendChild(clone);return jQuery.clean([container.innerHTML])[0];}else -return this.cloneNode(true);});var clone=ret.find("*").andSelf().each(function(){if(this[expando]!=undefined)this[expando]=null;});if(events===true)this.find("*").andSelf().each(function(i){if(this.nodeType==3)return;var events=jQuery.data(this,"events");for(var type in events)for(var handler in events[type])jQuery.event.add(clone[i],type,events[type][handler],events[type][handler].data);});return ret;},filter:function(selector){return this.pushStack(jQuery.isFunction(selector)&&jQuery.grep(this,function(elem,i){return selector.call(elem,i);})||jQuery.multiFilter(selector,this));},not:function(selector){if(selector.constructor==String)if(isSimple.test(selector))return this.pushStack(jQuery.multiFilter(selector,this,true));else -selector=jQuery.multiFilter(selector,this);var isArrayLike=selector.length&&selector[selector.length-1]!==undefined&&!selector.nodeType;return this.filter(function(){return isArrayLike?jQuery.inArray(this,selector)<0:this!=selector;});},add:function(selector){return!selector?this:this.pushStack(jQuery.merge(this.get(),selector.constructor==String?jQuery(selector).get():selector.length!=undefined&&(!selector.nodeName||jQuery.nodeName(selector,"form"))?selector:[selector]));},is:function(selector){return selector?jQuery.multiFilter(selector,this).length>0:false;},hasClass:function(selector){return this.is("."+selector);},val:function(value){if(value==undefined){if(this.length){var elem=this[0];if(jQuery.nodeName(elem,"select")){var index=elem.selectedIndex,values=[],options=elem.options,one=elem.type=="select-one";if(index<0)return null;for(var i=one?index:0,max=one?index+1:options.length;i=0||jQuery.inArray(this.name,value)>=0);else if(jQuery.nodeName(this,"select")){var values=value.constructor==Array?value:[value];jQuery("option",this).each(function(){this.selected=(jQuery.inArray(this.value,values)>=0||jQuery.inArray(this.text,values)>=0);});if(!values.length)this.selectedIndex=-1;}else -this.value=value;});},html:function(value){return value==undefined?(this.length?this[0].innerHTML:null):this.empty().append(value);},replaceWith:function(value){return this.after(value).remove();},eq:function(i){return this.slice(i,i+1);},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments));},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem);}));},andSelf:function(){return this.add(this.prevObject);},data:function(key,value){var parts=key.split(".");parts[1]=parts[1]?"."+parts[1]:"";if(value==null){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data==undefined&&this.length)data=jQuery.data(this[0],key);return data==null&&parts[1]?this.data(parts[0]):data;}else -return this.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){jQuery.data(this,key,value);});},removeData:function(key){return this.each(function(){jQuery.removeData(this,key);});},domManip:function(args,table,reverse,callback){var clone=this.length>1,elems;return this.each(function(){if(!elems){elems=jQuery.clean(args,this.ownerDocument);if(reverse)elems.reverse();}var obj=this;if(table&&jQuery.nodeName(this,"table")&&jQuery.nodeName(elems[0],"tr"))obj=this.getElementsByTagName("tbody")[0]||this.appendChild(this.ownerDocument.createElement("tbody"));var scripts=jQuery([]);jQuery.each(elems,function(){var elem=clone?jQuery(this).clone(true)[0]:this;if(jQuery.nodeName(elem,"script")){scripts=scripts.add(elem);}else{if(elem.nodeType==1)scripts=scripts.add(jQuery("script",elem).remove());callback.call(obj,elem);}});scripts.each(evalScript);});}};jQuery.prototype.init.prototype=jQuery.prototype;function evalScript(i,elem){if(elem.src)jQuery.ajax({url:elem.src,async:false,dataType:"script"});else -jQuery.globalEval(elem.text||elem.textContent||elem.innerHTML||"");if(elem.parentNode)elem.parentNode.removeChild(elem);}jQuery.extend=jQuery.fn.extend=function(){var target=arguments[0]||{},i=1,length=arguments.length,deep=false,options;if(target.constructor==Boolean){deep=target;target=arguments[1]||{};i=2;}if(typeof target!="object"&&typeof target!="function")target={};if(length==1){target=this;i=0;}for(;i-1;}},swap:function(elem,options,callback){var old={};for(var name in options){old[name]=elem.style[name];elem.style[name]=options[name];}callback.call(elem);for(var name in options)elem.style[name]=old[name];},css:function(elem,name,force){if(name=="width"||name=="height"){var val,props={position:"absolute",visibility:"hidden",display:"block"},which=name=="width"?["Left","Right"]:["Top","Bottom"];function getWH(){val=name=="width"?elem.offsetWidth:elem.offsetHeight;var padding=0,border=0;jQuery.each(which,function(){padding+=parseFloat(jQuery.curCSS(elem,"padding"+this,true))||0;border+=parseFloat(jQuery.curCSS(elem,"border"+this+"Width",true))||0;});val-=Math.round(padding+border);}if(jQuery(elem).is(":visible"))getWH();else -jQuery.swap(elem,props,getWH);return Math.max(0,val);}return jQuery.curCSS(elem,name,force);},curCSS:function(elem,name,force){var ret;function color(elem){if(!jQuery.browser.safari)return false;var ret=document.defaultView.getComputedStyle(elem,null);return!ret||ret.getPropertyValue("color")=="";}if(name=="opacity"&&jQuery.browser.msie){ret=jQuery.attr(elem.style,"opacity");return ret==""?"1":ret;}if(jQuery.browser.opera&&name=="display"){var save=elem.style.outline;elem.style.outline="0 solid black";elem.style.outline=save;}if(name.match(/float/i))name=styleFloat;if(!force&&elem.style&&elem.style[name])ret=elem.style[name];else if(document.defaultView&&document.defaultView.getComputedStyle){if(name.match(/float/i))name="float";name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var getComputedStyle=document.defaultView.getComputedStyle(elem,null);if(getComputedStyle&&!color(elem))ret=getComputedStyle.getPropertyValue(name);else{var swap=[],stack=[];for(var a=elem;a&&color(a);a=a.parentNode)stack.unshift(a);for(var i=0;i]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+">";});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("",""]||!tags.indexOf("",""]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
              "]||!tags.indexOf("",""]||(!tags.indexOf("",""]||!tags.indexOf("",""]||jQuery.browser.msie&&[1,"div
              ","
              "]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--)div=div.lastChild;if(jQuery.browser.msie){var tbody=!tags.indexOf(""&&tags.indexOf("=0;--j)if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length)tbody[j].parentNode.removeChild(tbody[j]);if(/^\s/.test(elem))div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]),div.firstChild);}elem=jQuery.makeArray(div.childNodes);}if(elem.length===0&&(!jQuery.nodeName(elem,"form")&&!jQuery.nodeName(elem,"select")))return;if(elem[0]==undefined||jQuery.nodeName(elem,"form")||elem.options)ret.push(elem);else -ret=jQuery.merge(ret,elem);});return ret;},attr:function(elem,name,value){if(!elem||elem.nodeType==3||elem.nodeType==8)return undefined;var fix=jQuery.isXMLDoc(elem)?{}:jQuery.props;if(name=="selected"&&jQuery.browser.safari)elem.parentNode.selectedIndex;if(fix[name]){if(value!=undefined)elem[fix[name]]=value;return elem[fix[name]];}else if(jQuery.browser.msie&&name=="style")return jQuery.attr(elem.style,"cssText",value);else if(value==undefined&&jQuery.browser.msie&&jQuery.nodeName(elem,"form")&&(name=="action"||name=="method"))return elem.getAttributeNode(name).nodeValue;else if(elem.tagName){if(value!=undefined){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode)throw"type property can't be changed";elem.setAttribute(name,""+value);}if(jQuery.browser.msie&&/href|src/.test(name)&&!jQuery.isXMLDoc(elem))return elem.getAttribute(name,2);return elem.getAttribute(name);}else{if(name=="opacity"&&jQuery.browser.msie){if(value!=undefined){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+(parseFloat(value).toString()=="NaN"?"":"alpha(opacity="+value*100+")");}return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100).toString():"";}name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase();});if(value!=undefined)elem[name]=value;return elem[name];}},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"");},makeArray:function(array){var ret=[];if(typeof array!="array")for(var i=0,length=array.length;i*",this).remove();while(this.firstChild)this.removeChild(this.firstChild);}},function(name,fn){jQuery.fn[name]=function(){return this.each(fn,arguments);};});jQuery.each(["Height","Width"],function(i,name){var type=name.toLowerCase();jQuery.fn[type]=function(size){return this[0]==window?jQuery.browser.opera&&document.body["client"+name]||jQuery.browser.safari&&window["inner"+name]||document.compatMode=="CSS1Compat"&&document.documentElement["client"+name]||document.body["client"+name]:this[0]==document?Math.max(Math.max(document.body["scroll"+name],document.documentElement["scroll"+name]),Math.max(document.body["offset"+name],document.documentElement["offset"+name])):size==undefined?(this.length?jQuery.css(this[0],type):null):this.css(type,size.constructor==String?size:size+"px");};});var chars=jQuery.browser.safari&&parseInt(jQuery.browser.version)<417?"(?:[\\w*_-]|\\\\.)":"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",quickChild=new RegExp("^>\\s*("+chars+"+)"),quickID=new RegExp("^("+chars+"+)(#)("+chars+"+)"),quickClass=new RegExp("^([#.]?)("+chars+"*)");jQuery.extend({expr:{"":function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},"#":function(a,i,m){return a.getAttribute("id")==m[2];},":":{lt:function(a,i,m){return im[3]-0;},nth:function(a,i,m){return m[3]-0==i;},eq:function(a,i,m){return m[3]-0==i;},first:function(a,i){return i==0;},last:function(a,i,m,r){return i==r.length-1;},even:function(a,i){return i%2==0;},odd:function(a,i){return i%2;},"first-child":function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},"last-child":function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},"only-child":function(a){return!jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},parent:function(a){return a.firstChild;},empty:function(a){return!a.firstChild;},contains:function(a,i,m){return(a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},visible:function(a){return"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},hidden:function(a){return"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},enabled:function(a){return!a.disabled;},disabled:function(a){return a.disabled;},checked:function(a){return a.checked;},selected:function(a){return a.selected||jQuery.attr(a,"selected");},text:function(a){return"text"==a.type;},radio:function(a){return"radio"==a.type;},checkbox:function(a){return"checkbox"==a.type;},file:function(a){return"file"==a.type;},password:function(a){return"password"==a.type;},submit:function(a){return"submit"==a.type;},image:function(a){return"image"==a.type;},reset:function(a){return"reset"==a.type;},button:function(a){return"button"==a.type||jQuery.nodeName(a,"button");},input:function(a){return/input|select|textarea|button/i.test(a.nodeName);},has:function(a,i,m){return jQuery.find(m[3],a).length;},header:function(a){return/h\d/i.test(a.nodeName);},animated:function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}}},parse:[/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,new RegExp("^([:.#]*)("+chars+"+)")],multiFilter:function(expr,elems,not){var old,cur=[];while(expr&&expr!=old){old=expr;var f=jQuery.filter(expr,elems,not);expr=f.t.replace(/^\s*,\s*/,"");cur=not?elems=f.r:jQuery.merge(cur,f.r);}return cur;},find:function(t,context){if(typeof t!="string")return[t];if(context&&context.nodeType!=1&&context.nodeType!=9)return[];context=context||document;var ret=[context],done=[],last,nodeName;while(t&&last!=t){var r=[];last=t;t=jQuery.trim(t);var foundToken=false;var re=quickChild;var m=re.exec(t);if(m){nodeName=m[1].toUpperCase();for(var i=0;ret[i];i++)for(var c=ret[i].firstChild;c;c=c.nextSibling)if(c.nodeType==1&&(nodeName=="*"||c.nodeName.toUpperCase()==nodeName))r.push(c);ret=r;t=t.replace(re,"");if(t.indexOf(" ")==0)continue;foundToken=true;}else{re=/^([>+~])\s*(\w*)/i;if((m=re.exec(t))!=null){r=[];var merge={};nodeName=m[2].toUpperCase();m=m[1];for(var j=0,rl=ret.length;j=0;if(!not&&pass||not&&!pass)tmp.push(r[i]);}return tmp;},filter:function(t,r,not){var last;while(t&&t!=last){last=t;var p=jQuery.parse,m;for(var i=0;p[i];i++){m=p[i].exec(t);if(m){t=t.substring(m[0].length);m[2]=m[2].replace(/\\/g,"");break;}}if(!m)break;if(m[1]==":"&&m[2]=="not")r=isSimple.test(m[3])?jQuery.filter(m[3],r,true).r:jQuery(r).not(m[3]);else if(m[1]==".")r=jQuery.classFilter(r,m[2],not);else if(m[1]=="["){var tmp=[],type=m[3];for(var i=0,rl=r.length;i=0)^not)tmp.push(a);}r=tmp;}else if(m[1]==":"&&m[2]=="nth-child"){var merge={},tmp=[],test=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3]=="even"&&"2n"||m[3]=="odd"&&"2n+1"||!/\D/.test(m[3])&&"0n+"+m[3]||m[3]),first=(test[1]+(test[2]||1))-0,last=test[3]-0;for(var i=0,rl=r.length;i=0)add=true;if(add^not)tmp.push(node);}r=tmp;}else{var fn=jQuery.expr[m[1]];if(typeof fn=="object")fn=fn[m[2]];if(typeof fn=="string")fn=eval("false||function(a,i){return "+fn+";}");r=jQuery.grep(r,function(elem,i){return fn(elem,i,m,r);},not);}}return{r:r,t:t};},dir:function(elem,dir){var matched=[];var cur=elem[dir];while(cur&&cur!=document){if(cur.nodeType==1)matched.push(cur);cur=cur[dir];}return matched;},nth:function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir])if(cur.nodeType==1&&++num==result)break;return cur;},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType==1&&(!elem||n!=elem))r.push(n);}return r;}});jQuery.event={add:function(elem,types,handler,data){if(elem.nodeType==3||elem.nodeType==8)return;if(jQuery.browser.msie&&elem.setInterval!=undefined)elem=window;if(!handler.guid)handler.guid=this.guid++;if(data!=undefined){var fn=handler;handler=function(){return fn.apply(this,arguments);};handler.data=data;handler.guid=fn.guid;}var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){var val;if(typeof jQuery=="undefined"||jQuery.event.triggered)return val;val=jQuery.event.handle.apply(arguments.callee.elem,arguments);return val;});handle.elem=elem;jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];handler.type=parts[1];var handlers=events[type];if(!handlers){handlers=events[type]={};if(!jQuery.event.special[type]||jQuery.event.special[type].setup.call(elem)===false){if(elem.addEventListener)elem.addEventListener(type,handle,false);else if(elem.attachEvent)elem.attachEvent("on"+type,handle);}}handlers[handler.guid]=handler;jQuery.event.global[type]=true;});elem=null;},guid:1,global:{},remove:function(elem,types,handler){if(elem.nodeType==3||elem.nodeType==8)return;var events=jQuery.data(elem,"events"),ret,index;if(events){if(types==undefined||(typeof types=="string"&&types.charAt(0)=="."))for(var type in events)this.remove(elem,type+(types||""));else{if(types.type){handler=types.handler;types=types.type;}jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];if(events[type]){if(handler)delete events[type][handler.guid];else -for(handler in events[type])if(!parts[1]||events[type][handler].type==parts[1])delete events[type][handler];for(ret in events[type])break;if(!ret){if(!jQuery.event.special[type]||jQuery.event.special[type].teardown.call(elem)===false){if(elem.removeEventListener)elem.removeEventListener(type,jQuery.data(elem,"handle"),false);else if(elem.detachEvent)elem.detachEvent("on"+type,jQuery.data(elem,"handle"));}ret=null;delete events[type];}}});}for(ret in events)break;if(!ret){var handle=jQuery.data(elem,"handle");if(handle)handle.elem=null;jQuery.removeData(elem,"events");jQuery.removeData(elem,"handle");}}},trigger:function(type,data,elem,donative,extra){data=jQuery.makeArray(data||[]);if(type.indexOf("!")>=0){type=type.slice(0,-1);var exclusive=true;}if(!elem){if(this.global[type])jQuery("*").add([window,document]).trigger(type,data);}else{if(elem.nodeType==3||elem.nodeType==8)return undefined;var val,ret,fn=jQuery.isFunction(elem[type]||null),event=!data[0]||!data[0].preventDefault;if(event)data.unshift(this.fix({type:type,target:elem}));data[0].type=type;if(exclusive)data[0].exclusive=true;if(jQuery.isFunction(jQuery.data(elem,"handle")))val=jQuery.data(elem,"handle").apply(elem,data);if(!fn&&elem["on"+type]&&elem["on"+type].apply(elem,data)===false)val=false;if(event)data.shift();if(extra&&jQuery.isFunction(extra)){ret=extra.apply(elem,val==null?data:data.concat(val));if(ret!==undefined)val=ret;}if(fn&&donative!==false&&val!==false&&!(jQuery.nodeName(elem,'a')&&type=="click")){this.triggered=true;try{elem[type]();}catch(e){}}this.triggered=false;}return val;},handle:function(event){var val;event=jQuery.event.fix(event||window.event||{});var parts=event.type.split(".");event.type=parts[0];var handlers=jQuery.data(this,"events")&&jQuery.data(this,"events")[event.type],args=Array.prototype.slice.call(arguments,1);args.unshift(event);for(var j in handlers){var handler=handlers[j];args[0].handler=handler;args[0].data=handler.data;if(!parts[1]&&!event.exclusive||handler.type==parts[1]){var ret=handler.apply(this,args);if(val!==false)val=ret;if(ret===false){event.preventDefault();event.stopPropagation();}}}if(jQuery.browser.msie)event.target=event.preventDefault=event.stopPropagation=event.handler=event.data=null;return val;},fix:function(event){var originalEvent=event;event=jQuery.extend({},originalEvent);event.preventDefault=function(){if(originalEvent.preventDefault)originalEvent.preventDefault();originalEvent.returnValue=false;};event.stopPropagation=function(){if(originalEvent.stopPropagation)originalEvent.stopPropagation();originalEvent.cancelBubble=true;};if(!event.target)event.target=event.srcElement||document;if(event.target.nodeType==3)event.target=originalEvent.target.parentNode;if(!event.relatedTarget&&event.fromElement)event.relatedTarget=event.fromElement==event.target?event.toElement:event.fromElement;if(event.pageX==null&&event.clientX!=null){var doc=document.documentElement,body=document.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc.clientTop||0);}if(!event.which&&((event.charCode||event.charCode===0)?event.charCode:event.keyCode))event.which=event.charCode||event.keyCode;if(!event.metaKey&&event.ctrlKey)event.metaKey=event.ctrlKey;if(!event.which&&event.button)event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)));return event;},special:{ready:{setup:function(){bindReady();return;},teardown:function(){return;}},mouseenter:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseover",jQuery.event.special.mouseenter.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseover",jQuery.event.special.mouseenter.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseenter";return jQuery.event.handle.apply(this,arguments);}},mouseleave:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseout",jQuery.event.special.mouseleave.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseout",jQuery.event.special.mouseleave.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseleave";return jQuery.event.handle.apply(this,arguments);}}}};jQuery.fn.extend({bind:function(type,data,fn){return type=="unload"?this.one(type,data,fn):this.each(function(){jQuery.event.add(this,type,fn||data,fn&&data);});},one:function(type,data,fn){return this.each(function(){jQuery.event.add(this,type,function(event){jQuery(this).unbind(event);return(fn||data).apply(this,arguments);},fn&&data);});},unbind:function(type,fn){return this.each(function(){jQuery.event.remove(this,type,fn);});},trigger:function(type,data,fn){return this.each(function(){jQuery.event.trigger(type,data,this,true,fn);});},triggerHandler:function(type,data,fn){if(this[0])return jQuery.event.trigger(type,data,this[0],false,fn);return undefined;},toggle:function(){var args=arguments;return this.click(function(event){this.lastToggle=0==this.lastToggle?1:0;event.preventDefault();return args[this.lastToggle].apply(this,arguments)||false;});},hover:function(fnOver,fnOut){return this.bind('mouseenter',fnOver).bind('mouseleave',fnOut);},ready:function(fn){bindReady();if(jQuery.isReady)fn.call(document,jQuery);else -jQuery.readyList.push(function(){return fn.call(this,jQuery);});return this;}});jQuery.extend({isReady:false,readyList:[],ready:function(){if(!jQuery.isReady){jQuery.isReady=true;if(jQuery.readyList){jQuery.each(jQuery.readyList,function(){this.apply(document);});jQuery.readyList=null;}jQuery(document).triggerHandler("ready");}}});var readyBound=false;function bindReady(){if(readyBound)return;readyBound=true;if(document.addEventListener&&!jQuery.browser.opera)document.addEventListener("DOMContentLoaded",jQuery.ready,false);if(jQuery.browser.msie&&window==top)(function(){if(jQuery.isReady)return;try{document.documentElement.doScroll("left");}catch(error){setTimeout(arguments.callee,0);return;}jQuery.ready();})();if(jQuery.browser.opera)document.addEventListener("DOMContentLoaded",function(){if(jQuery.isReady)return;for(var i=0;i=0){var selector=url.slice(off,url.length);url=url.slice(0,off);}callback=callback||function(){};var type="GET";if(params)if(jQuery.isFunction(params)){callback=params;params=null;}else{params=jQuery.param(params);type="POST";}var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(res,status){if(status=="success"||status=="notmodified")self.html(selector?jQuery("
              ").append(res.responseText.replace(//g,"")).find(selector):res.responseText);self.each(callback,[res.responseText,status,res]);}});return this;},serialize:function(){return jQuery.param(this.serializeArray());},serializeArray:function(){return this.map(function(){return jQuery.nodeName(this,"form")?jQuery.makeArray(this.elements):this;}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type));}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:val.constructor==Array?jQuery.map(val,function(val,i){return{name:elem.name,value:val};}):{name:elem.name,value:val};}).get();}});jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(i,o){jQuery.fn[o]=function(f){return this.bind(o,f);};});var jsc=(new Date).getTime();jQuery.extend({get:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data=null;}return jQuery.ajax({type:"GET",url:url,data:data,success:callback,dataType:type});},getScript:function(url,callback){return jQuery.get(url,null,callback,"script");},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},post:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data={};}return jQuery.ajax({type:"POST",url:url,data:data,success:callback,dataType:type});},ajaxSetup:function(settings){jQuery.extend(jQuery.ajaxSettings,settings);},ajaxSettings:{global:true,type:"GET",timeout:0,contentType:"application/x-www-form-urlencoded",processData:true,async:true,data:null,username:null,password:null,accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(s){var jsonp,jsre=/=\?(&|$)/g,status,data;s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));if(s.data&&s.processData&&typeof s.data!="string")s.data=jQuery.param(s.data);if(s.dataType=="jsonp"){if(s.type.toLowerCase()=="get"){if(!s.url.match(jsre))s.url+=(s.url.match(/\?/)?"&":"?")+(s.jsonp||"callback")+"=?";}else if(!s.data||!s.data.match(jsre))s.data=(s.data?s.data+"&":"")+(s.jsonp||"callback")+"=?";s.dataType="json";}if(s.dataType=="json"&&(s.data&&s.data.match(jsre)||s.url.match(jsre))){jsonp="jsonp"+jsc++;if(s.data)s.data=(s.data+"").replace(jsre,"="+jsonp+"$1");s.url=s.url.replace(jsre,"="+jsonp+"$1");s.dataType="script";window[jsonp]=function(tmp){data=tmp;success();complete();window[jsonp]=undefined;try{delete window[jsonp];}catch(e){}if(head)head.removeChild(script);};}if(s.dataType=="script"&&s.cache==null)s.cache=false;if(s.cache===false&&s.type.toLowerCase()=="get"){var ts=(new Date()).getTime();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"");}if(s.data&&s.type.toLowerCase()=="get"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null;}if(s.global&&!jQuery.active++)jQuery.event.trigger("ajaxStart");if((!s.url.indexOf("http")||!s.url.indexOf("//"))&&s.dataType=="script"&&s.type.toLowerCase()=="get"){var head=document.getElementsByTagName("head")[0];var script=document.createElement("script");script.src=s.url;if(s.scriptCharset)script.charset=s.scriptCharset;if(!jsonp){var done=false;script.onload=script.onreadystatechange=function(){if(!done&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){done=true;success();complete();head.removeChild(script);}};}head.appendChild(script);return undefined;}var requestDone=false;var xml=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();xml.open(s.type,s.url,s.async,s.username,s.password);try{if(s.data)xml.setRequestHeader("Content-Type",s.contentType);if(s.ifModified)xml.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT");xml.setRequestHeader("X-Requested-With","XMLHttpRequest");xml.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default);}catch(e){}if(s.beforeSend)s.beforeSend(xml);if(s.global)jQuery.event.trigger("ajaxSend",[xml,s]);var onreadystatechange=function(isTimeout){if(!requestDone&&xml&&(xml.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null;}status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xml)&&"error"||s.ifModified&&jQuery.httpNotModified(xml,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xml,s.dataType);}catch(e){status="parsererror";}}if(status=="success"){var modRes;try{modRes=xml.getResponseHeader("Last-Modified");}catch(e){}if(s.ifModified&&modRes)jQuery.lastModified[s.url]=modRes;if(!jsonp)success();}else -jQuery.handleError(s,xml,status);complete();if(s.async)xml=null;}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0)setTimeout(function(){if(xml){xml.abort();if(!requestDone)onreadystatechange("timeout");}},s.timeout);}try{xml.send(s.data);}catch(e){jQuery.handleError(s,xml,null,e);}if(!s.async)onreadystatechange();function success(){if(s.success)s.success(data,status);if(s.global)jQuery.event.trigger("ajaxSuccess",[xml,s]);}function complete(){if(s.complete)s.complete(xml,status);if(s.global)jQuery.event.trigger("ajaxComplete",[xml,s]);if(s.global&&!--jQuery.active)jQuery.event.trigger("ajaxStop");}return xml;},handleError:function(s,xml,status,e){if(s.error)s.error(xml,status,e);if(s.global)jQuery.event.trigger("ajaxError",[xml,s,e]);},active:0,httpSuccess:function(r){try{return!r.status&&location.protocol=="file:"||(r.status>=200&&r.status<300)||r.status==304||r.status==1223||jQuery.browser.safari&&r.status==undefined;}catch(e){}return false;},httpNotModified:function(xml,url){try{var xmlRes=xml.getResponseHeader("Last-Modified");return xml.status==304||xmlRes==jQuery.lastModified[url]||jQuery.browser.safari&&xml.status==undefined;}catch(e){}return false;},httpData:function(r,type){var ct=r.getResponseHeader("content-type");var xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0;var data=xml?r.responseXML:r.responseText;if(xml&&data.documentElement.tagName=="parsererror")throw"parsererror";if(type=="script")jQuery.globalEval(data);if(type=="json")data=eval("("+data+")");return data;},param:function(a){var s=[];if(a.constructor==Array||a.jquery)jQuery.each(a,function(){s.push(encodeURIComponent(this.name)+"="+encodeURIComponent(this.value));});else -for(var j in a)if(a[j]&&a[j].constructor==Array)jQuery.each(a[j],function(){s.push(encodeURIComponent(j)+"="+encodeURIComponent(this));});else -s.push(encodeURIComponent(j)+"="+encodeURIComponent(a[j]));return s.join("&").replace(/%20/g,"+");}});jQuery.fn.extend({show:function(speed,callback){return speed?this.animate({height:"show",width:"show",opacity:"show"},speed,callback):this.filter(":hidden").each(function(){this.style.display=this.oldblock||"";if(jQuery.css(this,"display")=="none"){var elem=jQuery("<"+this.tagName+" />").appendTo("body");this.style.display=elem.css("display");if(this.style.display=="none")this.style.display="block";elem.remove();}}).end();},hide:function(speed,callback){return speed?this.animate({height:"hide",width:"hide",opacity:"hide"},speed,callback):this.filter(":visible").each(function(){this.oldblock=this.oldblock||jQuery.css(this,"display");this.style.display="none";}).end();},_toggle:jQuery.fn.toggle,toggle:function(fn,fn2){return jQuery.isFunction(fn)&&jQuery.isFunction(fn2)?this._toggle(fn,fn2):fn?this.animate({height:"toggle",width:"toggle",opacity:"toggle"},fn,fn2):this.each(function(){jQuery(this)[jQuery(this).is(":hidden")?"show":"hide"]();});},slideDown:function(speed,callback){return this.animate({height:"show"},speed,callback);},slideUp:function(speed,callback){return this.animate({height:"hide"},speed,callback);},slideToggle:function(speed,callback){return this.animate({height:"toggle"},speed,callback);},fadeIn:function(speed,callback){return this.animate({opacity:"show"},speed,callback);},fadeOut:function(speed,callback){return this.animate({opacity:"hide"},speed,callback);},fadeTo:function(speed,to,callback){return this.animate({opacity:to},speed,callback);},animate:function(prop,speed,easing,callback){var optall=jQuery.speed(speed,easing,callback);return this[optall.queue===false?"each":"queue"](function(){if(this.nodeType!=1)return false;var opt=jQuery.extend({},optall);var hidden=jQuery(this).is(":hidden"),self=this;for(var p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden)return jQuery.isFunction(opt.complete)&&opt.complete.apply(this);if(p=="height"||p=="width"){opt.display=jQuery.css(this,"display");opt.overflow=this.style.overflow;}}if(opt.overflow!=null)this.style.overflow="hidden";opt.curAnim=jQuery.extend({},prop);jQuery.each(prop,function(name,val){var e=new jQuery.fx(self,opt,name);if(/toggle|show|hide/.test(val))e[val=="toggle"?hidden?"show":"hide":val](prop);else{var parts=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),start=e.cur(true)||0;if(parts){var end=parseFloat(parts[2]),unit=parts[3]||"px";if(unit!="px"){self.style[name]=(end||1)+unit;start=((end||1)/e.cur(true))*start;self.style[name]=start+unit;}if(parts[1])end=((parts[1]=="-="?-1:1)*end)+start;e.custom(start,end,unit);}else -e.custom(start,val,"");}});return true;});},queue:function(type,fn){if(jQuery.isFunction(type)||(type&&type.constructor==Array)){fn=type;type="fx";}if(!type||(typeof type=="string"&&!fn))return queue(this[0],type);return this.each(function(){if(fn.constructor==Array)queue(this,type,fn);else{queue(this,type).push(fn);if(queue(this,type).length==1)fn.apply(this);}});},stop:function(clearQueue,gotoEnd){var timers=jQuery.timers;if(clearQueue)this.queue([]);this.each(function(){for(var i=timers.length-1;i>=0;i--)if(timers[i].elem==this){if(gotoEnd)timers[i](true);timers.splice(i,1);}});if(!gotoEnd)this.dequeue();return this;}});var queue=function(elem,type,array){if(!elem)return undefined;type=type||"fx";var q=jQuery.data(elem,type+"queue");if(!q||array)q=jQuery.data(elem,type+"queue",array?jQuery.makeArray(array):[]);return q;};jQuery.fn.dequeue=function(type){type=type||"fx";return this.each(function(){var q=queue(this,type);q.shift();if(q.length)q[0].apply(this);});};jQuery.extend({speed:function(speed,easing,fn){var opt=speed&&speed.constructor==Object?speed:{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&easing.constructor!=Function&&easing};opt.duration=(opt.duration&&opt.duration.constructor==Number?opt.duration:{slow:600,fast:200}[opt.duration])||400;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false)jQuery(this).dequeue();if(jQuery.isFunction(opt.old))opt.old.apply(this);};return opt;},easing:{linear:function(p,n,firstNum,diff){return firstNum+diff*p;},swing:function(p,n,firstNum,diff){return((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum;}},timers:[],timerId:null,fx:function(elem,options,prop){this.options=options;this.elem=elem;this.prop=prop;if(!options.orig)options.orig={};}});jQuery.fx.prototype={update:function(){if(this.options.step)this.options.step.apply(this.elem,[this.now,this]);(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);if(this.prop=="height"||this.prop=="width")this.elem.style.display="block";},cur:function(force){if(this.elem[this.prop]!=null&&this.elem.style[this.prop]==null)return this.elem[this.prop];var r=parseFloat(jQuery.css(this.elem,this.prop,force));return r&&r>-10000?r:parseFloat(jQuery.curCSS(this.elem,this.prop))||0;},custom:function(from,to,unit){this.startTime=(new Date()).getTime();this.start=from;this.end=to;this.unit=unit||this.unit||"px";this.now=this.start;this.pos=this.state=0;this.update();var self=this;function t(gotoEnd){return self.step(gotoEnd);}t.elem=this.elem;jQuery.timers.push(t);if(jQuery.timerId==null){jQuery.timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;ithis.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var done=true;for(var i in this.options.curAnim)if(this.options.curAnim[i]!==true)done=false;if(done){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(jQuery.css(this.elem,"display")=="none")this.elem.style.display="block";}if(this.options.hide)this.elem.style.display="none";if(this.options.hide||this.options.show)for(var p in this.options.curAnim)jQuery.attr(this.elem.style,p,this.options.orig[p]);}if(done&&jQuery.isFunction(this.options.complete))this.options.complete.apply(this.elem);return false;}else{var n=t-this.startTime;this.state=n/this.options.duration;this.pos=jQuery.easing[this.options.easing||(jQuery.easing.swing?"swing":"linear")](this.state,n,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update();}return true;}};jQuery.fx.step={scrollLeft:function(fx){fx.elem.scrollLeft=fx.now;},scrollTop:function(fx){fx.elem.scrollTop=fx.now;},opacity:function(fx){jQuery.attr(fx.elem.style,"opacity",fx.now);},_default:function(fx){fx.elem.style[fx.prop]=fx.now+fx.unit;}};jQuery.fn.offset=function(){var left=0,top=0,elem=this[0],results;if(elem)with(jQuery.browser){var parent=elem.parentNode,offsetChild=elem,offsetParent=elem.offsetParent,doc=elem.ownerDocument,safari2=safari&&parseInt(version)<522&&!/adobeair/i.test(userAgent),fixed=jQuery.css(elem,"position")=="fixed";if(elem.getBoundingClientRect){var box=elem.getBoundingClientRect();add(box.left+Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),box.top+Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));add(-doc.documentElement.clientLeft,-doc.documentElement.clientTop);}else{add(elem.offsetLeft,elem.offsetTop);while(offsetParent){add(offsetParent.offsetLeft,offsetParent.offsetTop);if(mozilla&&!/^t(able|d|h)$/i.test(offsetParent.tagName)||safari&&!safari2)border(offsetParent);if(!fixed&&jQuery.css(offsetParent,"position")=="fixed")fixed=true;offsetChild=/^body$/i.test(offsetParent.tagName)?offsetChild:offsetParent;offsetParent=offsetParent.offsetParent;}while(parent&&parent.tagName&&!/^body|html$/i.test(parent.tagName)){if(!/^inline|table.*$/i.test(jQuery.css(parent,"display")))add(-parent.scrollLeft,-parent.scrollTop);if(mozilla&&jQuery.css(parent,"overflow")!="visible")border(parent);parent=parent.parentNode;}if((safari2&&(fixed||jQuery.css(offsetChild,"position")=="absolute"))||(mozilla&&jQuery.css(offsetChild,"position")!="absolute"))add(-doc.body.offsetLeft,-doc.body.offsetTop);if(fixed)add(Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));}results={top:top,left:left};}function border(elem){add(jQuery.curCSS(elem,"borderLeftWidth",true),jQuery.curCSS(elem,"borderTopWidth",true));}function add(l,t){left+=parseInt(l)||0;top+=parseInt(t)||0;}return results;};})(); \ No newline at end of file diff --git a/public/javascripts/json2.js b/public/javascripts/json2.js deleted file mode 100644 index d4f4541..0000000 --- a/public/javascripts/json2.js +++ /dev/null @@ -1 +0,0 @@ -if(!this.JSON){this.JSON={}}(function(){function f(n){return n<10?'0'+n:n}if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+'-'+f(this.getUTCMonth()+1)+'-'+f(this.getUTCDate())+'T'+f(this.getUTCHours())+':'+f(this.getUTCMinutes())+':'+f(this.getUTCSeconds())+'Z':null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key)}if(typeof rep==='function'){value=rep.call(holder,key,value)}switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null'}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object Array]'){length=value.length;for(i=0;i)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, -Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& -(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, -a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== -"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, -function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
              a"; -var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, -parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= -false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= -s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, -applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; -else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, -a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== -w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, -cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= -c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); -a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, -function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); -k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), -C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B=0){a.type= -e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& -f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; -if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", -e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, -"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, -d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, -e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); -t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| -g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, -CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, -g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, -text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, -setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= -h[3];l=0;for(m=h.length;l=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== -"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, -h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& -q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; -if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="

              ";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); -(function(){var g=s.createElement("div");g.innerHTML="
              ";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: -function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var j=d;j0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= -{},i;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== -"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", -d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? -a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== -1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"},F={option:[1,""],legend:[1,"
              ","
              "],thead:[1,"","
              "],tr:[2,"","
              "],td:[3,"","
              "],col:[2,"","
              "],area:[1,"",""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
              ","
              "];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= -c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, -wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, -prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, -this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); -return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, -""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); -return this}else{e=0;for(var j=d.length;e0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", -""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===""&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= -c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? -c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= -function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= -Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, -"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= -a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= -a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=//gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!== -"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("
              ").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this}, -serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), -function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href, -global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&& -e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)? -"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache=== -false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B= -false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since", -c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E|| -d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x); -g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status=== -1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b=== -"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional; -if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration=== -"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]|| -c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start; -this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now= -this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem, -e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b
              "; -a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b); -c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a, -d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top- -f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset": -"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in -e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window); -/*json2.js*/ -if(!this.JSON){this.JSON={}}(function(){function f(n){return n<10?'0'+n:n}if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+'-'+f(this.getUTCMonth()+1)+'-'+f(this.getUTCDate())+'T'+f(this.getUTCHours())+':'+f(this.getUTCMinutes())+':'+f(this.getUTCSeconds())+'Z':null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key)}if(typeof rep==='function'){value=rep.call(holder,key,value)}switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null'}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object Array]'){length=value.length;for(i=0;i
              ');var typer=$('');var promptBox;var prompt;var promptLabel=config&&config.promptLabel?config.promptLabel:"> ";var column=0;var promptText='';var restoreText='';var history=[];var ringn=0;var cancelKeyPress=0;var extern={};(function(){container.append(inner);inner.append(typer);typer.css({position:'absolute',top:0,left:'-999px'});if(config.welcomeMessage)message(config.welcomeMessage,'jquery-console-welcome');newPromptBox();if(config.autofocus){inner.addClass('jquery-console-focus');typer.focus();setTimeout(function(){inner.addClass('jquery-console-focus');typer.focus()},100)}})();extern.reset=function(){var welcome=true;inner.parent().fadeOut(function(){inner.find('div').each(function(){if(!welcome)$(this).remove();welcome=false});newPromptBox();inner.parent().fadeIn(function(){inner.addClass('jquery-console-focus');typer.focus()})})};function newPromptBox(){column=0;promptText='';promptBox=$('
              ');var label=$('');promptBox.append(label.text(promptLabel).show());prompt=$('');promptBox.append(prompt);inner.append(promptBox);updatePromptDisplay()};container.click(function(){inner.addClass('jquery-console-focus');inner.removeClass('jquery-console-nofocus');typer.focus();scrollToBottom();return false});typer.blur(function(){inner.removeClass('jquery-console-focus');inner.addClass('jquery-console-nofocus')});typer.keydown(function(e){cancelKeyPress=0;var keyCode=e.keyCode;if(isControlCharacter(keyCode)){cancelKeyPress=keyCode;if(!typer.consoleControl(keyCode)){return false}}});typer.keypress(function(e){var keyCode=e.keyCode||e.which;if(cancelKeyPress!=keyCode&&keyCode>=32){if(cancelKeyPress)return false;typer.consoleInsert(keyCode)}if($.browser.webkit)return false});function isControlCharacter(keyCode){return((keyCode>=keyCodes.left&&keyCode<=keyCodes.down)||keyCode==keyCodes.back||keyCode==keyCodes.del||keyCode==keyCodes.end||keyCode==keyCodes.start||keyCode==keyCodes.ret)};typer.consoleControl=function(keyCode){switch(keyCode){case keyCodes.left:{moveColumn(-1);updatePromptDisplay();return false;break}case keyCodes.right:{moveColumn(1);updatePromptDisplay();return false;break}case keyCodes.back:{if(moveColumn(-1)){deleteCharAtPos();updatePromptDisplay()}return false;break}case keyCodes.del:{if(deleteCharAtPos())updatePromptDisplay();return false;break}case keyCodes.end:{if(moveColumn(promptText.length-column))updatePromptDisplay();return false;break}case keyCodes.start:{if(moveColumn(-column))updatePromptDisplay();return false;break}case keyCodes.ret:{commandTrigger();return false}case keyCodes.up:{rotateHistory(-1);return false}case keyCodes.down:{rotateHistory(1);return false}default:}};function rotateHistory(n){if(history.length==0)return;ringn+=n;if(ringn<0)ringn=history.length;else if(ringn>history.length)ringn=0;var prevText=promptText;if(ringn==0){promptText=restoreText}else{promptText=history[ringn-1]}if(config.historyPreserveColumn){if(promptText.length
              ');if(className)mesg.addClass(className);mesg.filledText(msg).hide();inner.append(mesg);mesg.show()};typer.consoleInsert=function(keyCode){var char=String.fromCharCode(keyCode);var before=promptText.substring(0,column);var after=promptText.substring(column);promptText=before+char+after;moveColumn(1);restoreText=promptText;updatePromptDisplay()};function moveColumn(n){if(column+n>=0&&column+n<=promptText.length){column+=n;return true}else return false};function updatePromptDisplay(){var line=promptText;var html='';if(column>0&&line==''){html=cursor}else if(column==promptText.length){html=htmlEncode(line)+cursor}else{var before=line.substring(0,column);var current=line.substring(column,column+1);if(current){current=''+htmlEncode(current)+''}var after=line.substring(column+1);html=htmlEncode(before)+current+htmlEncode(after)}prompt.html(html);scrollToBottom()};function htmlEncode(text){return(text.replace(/&/g,'&').replace(/&]{10})/g,'$1­'+wbr))};return extern};$.fn.filledText=function(txt){$(this).text(txt);$(this).html($(this).html().replace(/\n/g,'
              '));return this}})(jQuery); diff --git a/public/javascripts/mouseapp_2.js b/public/javascripts/mouseapp_2.js deleted file mode 100755 index de5c777..0000000 --- a/public/javascripts/mouseapp_2.js +++ /dev/null @@ -1,913 +0,0 @@ -// -// Copyright (c) 2008 why the lucky stiff -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, -// and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT -// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -var MouseApp = { - Version: '0.12', - CharCodes: { - 0: ' ', 1: ' ', 9: ' ', - 32: ' ', 34: '"', 38: '&', - 60: '<', 62: '>', 127: '◊', - 0x20AC: '€' - }, - KeyCodes: { - Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 33, PageDown: 34, - End: 35, Home: 36, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 45, - Delete: 46, F1: 112, F2: 113, F3: 114, F4: 115, F5: 116, F6: 117, - F7: 118, F8: 119, F10: 121 - }, - CodeKeys: {}, - Modes: { 1: 'b', 2: 'u', 4: 'i', 8: 'strike' }, - ModeIds: { r: 1, u: 2, i: 4, s: 8 }, - Colors: ['black', 'blue', 'green', - 'cyan', 'red', 'purple', 'brown', - 'gray', 'dark_gray', 'lt_blue', - 'lt_green', 'lt_cyan', 'lt_red', - 'lt_purple', 'yellow', 'white'] -} -//some of these are patently false, because I need to get on a real keyboard-- not a macbook. -if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1){ - MouseApp.KeyCodes = { - Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, - End: 63275, Home: 63273, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 632325, - Delete: 46, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, - F7: 63242, F8: 63243, F10: 63244 - } - -} - -//even though I am tempted to combine chrome and opera into the same if statment, I will refrain for now -// i dont have proper access to a proper keyboard and there might be a single difference between the two -if (navigator.userAgent.indexOf("Opera") > -1){ - MouseApp.KeyCodes = { - Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, - End: 63275, Home: 63273, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 632325, - Delete: 46, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, - F7: 63242, F8: 63243, F10: 63244 - } - -} - -// i am going to comment this out, since this seems un needed. if it past december 15 2009 and this -// is still commented it, please del me -//if ( navigator.appVersion.indexOf('AppleWebKit') > 0 ) { -// MouseApp.KeyCodes = { -// Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, -// End: 63275, Home: 63273, Left: 63234, Up: 63232, Right: 63235, Down: 63233, Insert: 632325, -// Delete: 63272, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, -// F7: 63242, F8: 63243, F10: 63244 -// };// -//} -for ( var k in MouseApp.KeyCodes ) { - MouseApp.CodeKeys[MouseApp.KeyCodes[k]] = k; -} - -MouseApp.isPrintable = function(ch) { - return (ch >= 32); -}; - -MouseApp.Base = function(){}; -MouseApp.Base.prototype = { - setOptions: function(options) { - this.options = { - columns: 72, rows: 24, indent: 2, - title: 'MouseApp', - blinkRate: 500, - ps: '>', - greeting:'%+r Terminal ready. %-r' - } - $.extend(this.options, options || {}); - } -} - -MouseApp.Manager = new Object(); -$.extend(MouseApp.Manager, { - observeTerm: function(term) { - this.activeTerm = term; - if ( this.observingKeyboard ) return; - var mgr = this; - if ( term.input ) { - term.input.keypress(function(e) { mgr.onKeyPress(e) }); - if (!window.opera) term.input.keydown(function(e) { mgr.onKeyDown(e) }); - else window.setInterval(function(){term.input.focus()},1); - } else { - if (!window.opera) $(document).keydown(function(e) { mgr.onKeyDown(e) }); - $(document).keypress(function(e) { mgr.onKeyPress(e) }); - } - this.observingKeyboard = true; - }, - - onKeyDown: function(e) { - e = (e) ? e : ((event) ? event : null); - if ( e && MouseApp.CodeKeys[e.keyCode] ) { - if ( window.event ) { - this.sendKeyPress(e); - } - this.blockEvent(e); - return false; - } - return true; - }, - - onKeyPress: function(e) { - if ( !window.opera && window.event && e.keyCode != 13 && e.keyCode != 8 ) { - e.charCode = e.keyCode; e.keyCode = null; - } - if ( e.keyCode == 191 ) { /* FF 1.0.x sends this upsy quizy -- ignore */ - return; - } - return this.sendKeyPress(e); - }, - - sendKeyPress: function(e) { - var term = MouseApp.Manager.activeTerm; - term.cursorOff(); - b = term.onKeyPress(e); - term.cursorOn(); - return b; - }, - - blockEvent: function (e) { - e.cancelBubble=true; - if (window.event && !window.opera) e.keyCode=0; - if (e.stopPropagation) e.stopPropagation(); - if (e.preventDefault) e.preventDefault(); - } -}); - -/* Basic text window functionality */ -MouseApp.Window = function(element, options) { - this.element = $(element); - this.setOptions(options); - this.initWindow(); -}; - -$.extend(MouseApp.Window.prototype, (new MouseApp.Base()), { - initWindow: function() { - var html = ''; - for ( var i = 0; i < this.options.rows; i++ ) { - html += "
               
              \n"; - } - this.element.html(html); - this.typingOn(); - if (this.options.input) { - this.input = $(this.options.input); - this.input.focus(); - } - MouseApp.Manager.observeTerm(this); - this.clear(); - this.cursorOn(); - this.painting = true; - this.element.css({visibility: 'visible'}); - }, - - text: function() { - var str = ""; - for (var i = 0; i < this.screen.length; i++ ) { - for (var j = 0; j < this.options.columns; j++ ) { - var ch = this.screen[i][j]; - if ( ch[0] != 0 ) { - str += String.fromCharCode(ch[0]); - } - } - } - return str; - }, - - clear: function() { - this.rpos = 0; - this.cpos = 0; - this.screen = []; - this.element.html(''); - this.screen[0] = this.fillRow(this.options.columns, 0); - this.paint(0); - }, - - typingOn: function() { this.typing = true; }, - typingOff: function() { this.typing = false; }, - - cursorOn: function() { - if ( this.blinker ) { - clearInterval( this.blinker ); - } - this.underblink = this.screen[this.rpos][this.cpos][1]; - MouseApp.Manager.activeTerm.blink(); - this.blinker = setInterval(function(){MouseApp.Manager.activeTerm.blink();}, this.options.blinkRate); - this.cursor = true; - }, - - cursorOff: function() { - if ( this.blinker ) { - clearInterval( this.blinker ); - } - if ( this.cursor ) { - this.screen[this.rpos][this.cpos][1] = this.underblink; - this.paint(this.rpos); - this.cursor = false; - } - }, - - blink: function() { - if ( this == MouseApp.Manager.activeTerm ) { - var mode = this.screen[this.rpos][this.cpos][1]; - this.screen[this.rpos][this.cpos][1] = ( mode & 1 ) ? mode & 4094 : mode | 1; - this.paint(this.rpos); - } - }, - - fillRow: function(len, ch, mode) { - ary = [] - for (var i = 0; i < len; i++) { - ary[i] = [ch, mode]; - } - return ary; - }, - - paint: function(start, end) { - if (!this.painting) return; - - if (!end) end = start; - for (var row = start; row <= end && row < this.screen.length; row++) { - var html = ''; - var mode = 0; - var fcolor = 0; - var bcolor = 0; - var spans = 0; - for (var i = 0; i < this.options.columns; i++ ) { - var c = this.screen[row][i][0]; - var m = this.screen[row][i][1] & 15; // 4 mode bits - var f = (this.screen[row][i][1] & (15 << 4)) >> 4; // 4 foreground bits - var b = (this.screen[row][i][1] & (15 << 8)) >> 8; // 4 background bits - if ( m != mode ) { - if ( MouseApp.Modes[mode] ) html += ""; - if ( MouseApp.Modes[m] ) html += "<" + MouseApp.Modes[m] + ">"; - mode = m; - } - if ( ( f != fcolor && f == 0 ) || ( b != bcolor && b == 0 ) ) { - for ( var s = 0; s < spans; s++ ) html += ""; - fcolor = 0; bcolor = 0; - } - if ( f != fcolor ) { - if ( MouseApp.Colors[f] ) { - html += ""; - spans++; - } - fcolor = f; - } - if ( b != bcolor ) { - if ( MouseApp.Colors[b] ) html += ""; - spans++; bcolor = b; - } - html += MouseApp.CharCodes[c] ? MouseApp.CharCodes[c] : String.fromCharCode(c); - } - if ( MouseApp.Modes[mode] ) html += ""; - for ( var s = 0; s < spans; s++ ) html += ""; - var new_id = this.element.attr('id') + '_' + row; - if (!$('#' + new_id).get(0)) { - this.element.append("
               
              "); - this.scrollAllTheWayDown(); - } - $('#' + new_id).html(html); - } - }, - - onAfterKey: function() { - this.scrollAllTheWayDown(); - }, - - highlightLine: function(i) { - if (i >= 0 && i < this.screen.length) - { - $("#" + this.element.attr('id') + "_" + i); - } - }, - - scrollToLine: function(i) { - var p = this.element[0].parentNode; - if ( p.scrollHeight > p.clientHeight ) { - p.scrollTop = (p.scrollHeight - p.clientHeight); - } - }, - - scrollAllTheWayDown: function() { - var p = this.element[0].parentNode; - if ( p.scrollHeight > p.clientHeight ) { - p.scrollTop = (p.scrollHeight - p.clientHeight); - } - }, - - putc: function(ch, mode) { - if ( ch == 13 ) { - return; - } else if ( ch == 10 ) { - this.screen[this.rpos][this.cpos] = [ch, mode]; - this.advanceLine(); - } else { - this.screen[this.rpos][this.cpos] = [ch, mode]; - this.paint(this.rpos); - this.advance(); - } - }, - - zpad: function(n) { - if (n < 10) n = "0" + n; - return n; - }, - - puts: function(str, mode) { - if ( !str ) return; - var p = this.painting; - var r = this.rpos; - this.painting = false; - for ( var i = 0; i < str.length; i++ ) { - this.insertc(str.charCodeAt(i), mode); - } - this.painting = p; - this.paint(r, this.rpos); - }, - - advance: function() { - this.cpos++; - if ( this.cpos >= this.options.columns ) { - this.advanceLine(); - } - }, - - advanceLine: function() { - this.cpos = 0; - this.rpos++; - this.ensureRow(this.rpos); - this.paint(this.rpos, this.screen.length - 1); - }, - - fwdc: function() { - var r = this.rpos; - var c = this.cpos; - if ( c < this.options.columns - 1 ) { - c++; - } else if ( r < this.screen.length - 1 ) { - r++; - c = 0; - } - var ch = (c == 0 ? this.screen[r-1][this.options.columns-1] : this.screen[r][c-1]); - if ( MouseApp.isPrintable(ch[0]) ) { - this.rpos = r; - this.cpos = c; - } - }, - - fwdLine: function() { - if ( this.rpos >= this.screen.length - 1 ) return; - this.rpos++; - while ( this.cpos > 0 && !MouseApp.isPrintable(this.screen[this.rpos][this.cpos - 1][0]) ) { - this.cpos--; - } - }, - - backc: function() { - var r = this.rpos; - var c = this.cpos; - if ( c > 0 ) { - c--; - } else if ( r > 0 ) { - c = this.options.columns - 1; - r--; - } - if ( MouseApp.isPrintable(this.screen[r][c][0]) ) { - this.rpos = r; - this.cpos = c; - return true; - } - return false; - }, - - getTypingStart: function() { - var c = this.cpos; - if ( !MouseApp.isPrintable(this.screen[this.rpos][c][0]) ) { - c--; - } - var pos = null; - for ( var r = this.rpos; r >= 0; r-- ) { - while ( c >= 0 ) { - if ( !MouseApp.isPrintable(this.screen[r][c][0]) ) { - return pos; - } - pos = [r, c]; - c--; - } - c = this.options.columns - 1; - } - }, - - getTypingEnd: function(mod) { - var c = this.cpos; - if ( !MouseApp.isPrintable(this.screen[this.rpos][c][0]) ) { - c--; - } - var pos = null; - for ( var r = this.rpos; r < this.screen.length; r++ ) { - while ( c < this.options.columns ) { - if ( !this.screen[r] || !this.screen[r][c] || !MouseApp.isPrintable(this.screen[r][c][0]) ) { - if (!mod) return pos; - mod--; - } - pos = [r, c]; - c++; - } - c = 0; - } - }, - - getTypingAt: function(start, end) { - var r = start[0]; - var c = start[1]; - var str = ''; - while ( r < end[0] || c <= end[1] ) { - if ( c < this.options.columns ) { - str += String.fromCharCode(this.screen[r][c][0]); - c++; - } else { - c = 0; - r++; - } - } - return str; - }, - - ensureRow: function(r) { - if (!this.screen[r]) { - this.screen[r] = this.fillRow(this.options.columns, 0); - } - }, - - insertc: function(ch, mode) { - var r = this.rpos; var c = this.cpos; - var end = this.getTypingEnd(+1); - if (end) { - var thisc = null; - var lastc = this.screen[this.rpos][this.cpos]; - while ( r < end[0] || c <= end[1] ) { - if ( c < this.options.columns ) { - thisc = this.screen[r][c]; - this.screen[r][c] = lastc; - lastc = thisc; - c++; - } else { - c = 0; - r++; - this.ensureRow(r); - } - } - this.paint(this.rpos, end[0]); - } - this.putc(ch, mode); - }, - - delc: function() { - /* end of line */ - if ( MouseApp.isPrintable(this.screen[this.rpos][this.cpos][0]) ) { - var end = this.getTypingEnd(); - var thisc = null; - var lastc = [0, 0]; - while ( this.rpos < end[0] || this.cpos <= end[1] ) { - if ( end[1] >= 0 ) { - thisc = this.screen[end[0]][end[1]]; - this.screen[end[0]][end[1]] = lastc; - lastc = thisc; - end[1]--; - } else { - end[1] = this.options.columns - 1; - this.paint(end[0]); - end[0]--; - } - } - } - }, - - backspace: function() { - /* end of line */ - if ( !MouseApp.isPrintable(this.screen[this.rpos][this.cpos][0]) ) { - this.backc(); - this.screen[this.rpos][this.cpos] = [0, 0]; - } else { - if ( this.backc() ) this.delc(); - } - }, - - backLine: function() { - if ( this.rpos < 1 ) return; - this.rpos--; - while ( this.cpos > 0 && !MouseApp.isPrintable(this.screen[this.rpos][this.cpos - 1][0]) ) { - this.cpos--; - } - }, - - onKeyPress: function(e) { - var ch = e.keyCode; - var key_name = MouseApp.CodeKeys[ch]; - if (window.opera && !e.altKey && e.keyCode != 13 && e.keyCode != 8) key_name = null; - ch = (e.which || e.charCode || e.keyCode); - if (e.which) ch = e.which; - if (!key_name) { key_name = String.fromCharCode(ch); } - if (e.ctrlKey) { key_name = 'Ctrl' + key_name; } - - // alert([e.keyCode, e.which, key_name, this['onKey' + key_name]]); - if (this.typing && this.onAnyKey) this.onAnyKey(key_name); - if (key_name && this['onKey' + key_name]) { - if (this.typing) this['onKey' + key_name](); - MouseApp.Manager.blockEvent(e); - if (this.typing && this.onAfterKey) this.onAfterKey(key_name, true); - return false; - } - if (!e.ctrlKey) { - if (MouseApp.isPrintable(ch)) { - if (this.typing) this.insertc(ch, 0); - MouseApp.Manager.blockEvent(e); - if (this.typing && this.onAfterKey) this.onAfterKey(key_name, true); - return false; - } - } - if (this.typing && this.onAfterKey) this.onAfterKey(key_name, false); - return true; - }, - onKeyHome: function() { - var s = this.getTypingStart(); - this.rpos = s[0]; this.cpos = s[1]; - }, - onKeyEnd: function() { - var e = this.getTypingEnd(+1); - this.rpos = e[0]; this.cpos = e[1]; - }, - onKeyInsert: function() { }, - onKeyDelete: function() { this.delc(); }, - onKeyUp: function() { this.backLine(); }, - onKeyLeft: function() { this.backc(); }, - onKeyRight: function() { this.fwdc(); }, - onKeyDown: function() { this.fwdLine(); }, - onKeyBackspace: function() { this.backspace(); }, - onKeyEnter: function() { this.insertc(10, 0); }, - onKeyTab: function() { - this.insertc(32, 0); - while (this.cpos % this.options.indent != 0) this.insertc(32, 0); - } -}); - -/* Terminal running moush */ -MouseApp.Terminal = function(element, options) { - this.element = $(element); - this.setOptions(options); - this.initWindow(); - this.setup(); -}; - -$.extend(MouseApp.Terminal.prototype, MouseApp.Window.prototype, { - setup: function() { - this.history = []; - this.backupNum = this.historyNum = this.commandNum = 0; - if (this.onStart) { - this.onStart(); - } else { - this.write(this.options.greeting + "\n", true); - this.prompt(); - } - }, - - prompt: function(ps, pt) { - if (!ps) { - ps = this.options.ps; pt = true; - } - this.write(ps, pt); - this.putc(1, 0); - this.typingOn(); - }, - - getCommand: function() { - var s = this.getTypingStart(); - var e = this.getTypingEnd(); - if (!s || !e) return; - return this.getTypingAt(s, e); - }, - - clearCommand: function() { - var s = this.getTypingStart(); - var e = this.getTypingEnd(); - if (!s || !e) return; - var r = s[0]; - var c = s[1]; - this.rpos = r; this.cpos = c; - while ( r < e[0] || c <= e[1] ) { - if ( c < this.options.columns ) { - this.screen[r][c] = [0, 0]; - c++; - } else { - c = 0; - this.paint(r); - r++; - } - } - this.paint(r); - }, - - write: function(str, pcodes) { - var p = this.painting; - var r = this.rpos; - this.painting = false; - var mode = 0; - var today = new Date(); - for ( var i = 0; i < str.length; i++ ) { - if ( str.substr(i,1) == "\n" ) { - this.advanceLine(); - continue; - } else if ( str.substr(i,1) == "\033" ) { - if ( str.substr(i+1,2) == "[m" ) { - mode = 0; - i += 2; - continue; - } - if ( str.substr(i+1,5) == "[0;0m" ) { - mode = 0; - i += 5; - continue; - } - var colors = str.substr(i+1,7).match(/^\[(\d);(\d+)m/); - if ( colors ) { - var colCode = parseInt( colors[2] ); - var color = colCode % 10; - if ( colors[1] == '1' ) { - color += 8; - } - if ( colCode / 10 == 4 ) { - color = color << 4; - } - mode = (mode & 15) + color << 4; - i += colors[0].length; - continue; - } - } else if ( str.substr(i,1) == '%' && pcodes ) { - var s2 = str.substr(i,2); - switch ( s2 ) { - case '%h': - this.puts(this.options.host, mode); - i++; - continue; - case '%l': - this.puts(this.options.name, mode); - i++; - continue; - case '%n': - this.advanceLine(); - i++; - continue; - case '%s': - this.puts("moush", mode); - i++; - continue; - case '%t': - this.puts(this.zpad(today.getHours()) + ":" + this.zpad(today.getMinutes()) + ":" + - this.zpad(today.getSeconds()), mode); - i++; - continue; - case '%u': - this.puts(this.options.user, mode); - i++; - continue; - case '%v': - this.puts(MouseApp.Version, mode); - i++; - continue; - case '%!': - this.puts(this.historyNum.toString(), mode); - i++; - continue; - case '%#': - this.puts(this.commandNum.toString(), mode); - i++; - continue; - case '%+': - var kind = str.substr(i+2, 1); - if ( MouseApp.ModeIds[kind] ) { - mode = mode | MouseApp.ModeIds[kind]; - i += 2; - continue; - } - break; - case '%-': - var kind = str.substr(i+2, 1); - if ( MouseApp.ModeIds[kind] ) { - mode = mode & ( 4095 - MouseApp.ModeIds[kind] ); - i += 2; - continue; - } - break; - } - } - this.putc(str.charCodeAt(i), mode); - } - this.painting = p; - this.paint(r, this.rpos); - }, - - onKeyUp: function() { - if ( this.backupNum == 0 ) return; - if ( this.backupNum == this.historyNum ) { - this.history[this.historyNum] = this.getCommand(); - } - this.clearCommand(); - this.backupNum--; - this.puts(this.history[this.backupNum]); - }, - onKeyDown: function() { - if ( this.backupNum >= this.historyNum ) return; - this.clearCommand(); - this.backupNum++; - this.puts(this.history[this.backupNum]); - }, - onKeyEnter: function() { - var cmd = this.getCommand(); - if (cmd) { - this.history[this.historyNum] = cmd; - this.backupNum = ++this.historyNum; - } - this.commandNum++; - this.advanceLine(); - if (cmd) { - var str = this.onCommand(cmd); - if (str) { - if ( str.substr(str.length - 1, 1) != "\n" ) { - str += "\n"; - } - this.write(str); - } - } - this.prompt(); - }, - onCommand: function(line) { - // this.puts("Echoing: " + line + "\n"); - if ( line == "clear" ) { - this.clear(); - } else { - return "\033[1;37m\033[0;44mYou typed:\033[m " + line; - } - } -}); - -/* Notepad sort of editor */ -MouseApp.Notepad = function(element, options) { - this.element = $(element); - this.setOptions(options); - this.initWindow(); - this.history = []; - this.lineno = 0; -}; - -$.extend(MouseApp.Notepad.prototype, MouseApp.Window.prototype, { - csave: function() { - if ( this.cpos_save ) { - this.cpos = this.cpos_save; - } else { - this.cpos_save = this.cpos; - } - }, - onKeyUp: function() { if ( this.rpos < 1 ) { return; } this.csave(); this.backLine(); }, - onKeyDown: function() { if ( this.rpos < this.screen.length - 1 ) { this.csave(); this.fwdLine(); } }, - onAfterKey: function(key, st) { - if ( st && !(key == 'Up' || key == 'Down') ) { - this.cpos_save = null; - } - }, - insertc: function(ch, mode) { - if (ch == 10) { - this.element.append("
               
              "); - this.screen.splice(this.rpos + 1, 0, this.fillRow(this.options.columns, 0)); - var c = this.cpos; var c2 = 0; - while (c < this.options.columns) - { - if (this.screen[this.rpos][c] == 0) break; - this.screen[this.rpos + 1][c2] = this.screen[this.rpos][c]; - this.screen[this.rpos][c] = [0, 0]; - c++; c2++; - } - this.paint(this.rpos); - if (MouseApp.isPrintable(this.screen[this.rpos][c])) - { - var r = this.rpos; var c = this.cpos; - this.rpos += 1; this.cpos = c2; - this.delc(); - this.rpos = r; this.cpos = c; - } - this.putc(ch, mode); - if (this.rpos == this.screen.length - 1) - this.scrollAllTheWayDown(); - } else { - var c = this.cpos + 1; - var lastc = this.screen[this.rpos][this.cpos]; - this.putc(ch, mode); - for ( var r = this.rpos; r < this.screen.length; r++ ) { - while (c < this.options.columns) - { - var tmpc = this.screen[r][c]; - if (lastc[0] == 0) - break; - this.screen[r][c] = lastc; - lastc = tmpc; - c++; - } - if (c < this.options.columns) { - break; - } - c = 0; - } - } - }, - - backc: function() { - var r = this.rpos; - var c = this.cpos - 1; - for ( var r = this.rpos; r >= 0; r-- ) { - while ( c >= 0 ) { - this.rpos = r; - this.cpos = c; - if ( this.screen[r][c][0] != 0 ) { - this.paint(r); - return true; - } - this.screen[r][c] = [0, 0]; - c--; - } - c = this.options.columns - 1; - } - return false; - }, - delc: function() { - var c = this.cpos + 1; - for ( var r = this.rpos; r < this.screen.length; r++ ) { - while ( c < this.options.columns ) { - if ( this.screen[r][c][0] != 0 ) { - break; - } - c++; - } - if ( c < this.options.columns ) break; - c = 0; - } - - if (r >= this.screen.length) return; - - var r2 = this.rpos; - var c2 = this.cpos; - for ( var r2 = this.rpos; r2 < this.screen.length; r2++ ) { - while (c2 < this.options.columns) - { - if (this.screen[r][c][0] == 0) - break; - this.screen[r2][c2] = this.screen[r][c]; - c2++; - c++; - if (c >= this.options.columns) { - r++; - if (r >= this.options.rows) break; - c = 0; - } - } - if (c2 < this.options.columns) { - while (c2 < this.options.columns) { - this.screen[r2][c2] = [0, 0]; - c2++; - } - break; - } - c2 = 0; - } - - if (r != r2 && r < this.screen.length) - { - this.screen.splice(r, 1); - $("#" + this.element.attr('id') + "_" + this.screen.length).remove(); - } - this.paint(this.rpos, this.screen.length); - }, - onKeyBackspace: function() { - if (this.backc()) this.delc(); - } - -}); diff --git a/public/javascripts/mouseirb_2.js b/public/javascripts/mouseirb_2.js deleted file mode 100755 index 0fa5f12..0000000 --- a/public/javascripts/mouseirb_2.js +++ /dev/null @@ -1,179 +0,0 @@ -// -// Copyright (c) 2008 why the lucky stiff -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, -// and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT -// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -/* Irb running moush */ -MouseApp.Irb = function(element, options) { - this.element = $(element); - this.setOptions(options); - this.showHelp = this.options.showHelp; - if ( this.options.showChapter ) { - this.showChapter = this.options.showChapter; - } - if ( this.options.init ) { - this.init = this.options.init; - } - this.initWindow(); - this.setup(); - this.helpPage = null; - this.irbInit = false; -}; - -$.extend(MouseApp.Irb.prototype, MouseApp.Terminal.prototype, { - cmdToQuery: function(cmd) { - return "cmd=" + escape(cmd.replace(/</g, '<').replace(/>/g, '>'). - replace(/&/g, '&').replace(/\r?\n/g, "\n")).replace(/\+/g, "%2B"); - }, - - fireOffCmd: function(cmd, func) { - var irb = this; - if (!this.irbInit) - { - $.ajax({url: this.options.irbUrl + "?" + this.cmdToQuery("!INIT!IRB!"), type: "GET", - complete: (function(r) { irb.irbInit = true; irb.fireOffCmd(cmd, func); })}); - } - else - { - $.ajax({url: this.options.irbUrl + "?" + this.cmdToQuery(cmd), type: "GET", - complete: func}); - } - }, - - reply: function(str) { - var raw = str.replace(/\033\[(\d);(\d+)m/g, ''); - this.checkAnswer(raw); - if (!str.match(/^(\.\.)+$/)) { - if ( str[str.length - 1] != "\n" ) { - str += "\n"; - } - js_payload = /\033\[1;JSm(.*)\033\[m/; - js_in = str.match(js_payload); - if (js_in) { - try { - js_in = eval(js_in[1]); - } catch (e) {} - str = str.replace(js_payload, ''); - } - var pr_re = new RegExp("(^|\\n)=>"); - if ( str.match( pr_re ) ) { - str = str.replace(new RegExp("(^|\\n)=>"), "$1\033[1;34m=>\033[m"); - } else { - str = str.replace(new RegExp("(^|\\n)= (.+?) ="), "$1\033[1;33m$2\033[m"); - } - this.write(str); - this.prompt(); - } else { - this.prompt("\033[1;32m" + ".." + "\033[m", true); - this.puts(str.replace(/\./g, ' '), 0); - } - }, - - setHelpPage: function(n, page) { - if (this.helpPage) - $(this.helpPage.ele).hide('fast'); - this.helpPage = {index: n, ele: page}; - match = this.scanHelpPageFor('load'); - if (match != -1) - { - this.fireOffCmd(match, (function(r) { - $(page).show('fast'); - })); - } - else - { - $(page).show('fast'); - } - }, - - scanHelpPageFor: function(eleClass) { - match = $("div." + eleClass, this.helpPage.ele); - if ( match[0] ) return match[0].innerHTML; - else return -1; - }, - - checkAnswer: function(str) { - if ( this.helpPage ) { - match = this.scanHelpPageFor('answer'); - if ( match != -1 ) { - if ( str.match( new RegExp('^\s*=> ' + match + '\s*$', 'm') ) ) { - this.showHelp(this.helpPage.index + 1); - } - } else { - match = this.scanHelpPageFor('stdout'); - if ( match != -1 ) { - if ( match == '' ) { - if ( str == '' || str == null ) this.showHelp(this.helpPage.index + 1); - } else if ( str.match( new RegExp('^\s*' + match + '$', 'm') ) ) { - this.showHelp(this.helpPage.index + 1); - } - } - } - } - }, - - onKeyCtrld: function() { - this.clearCommand(); - this.puts("reset"); - this.onKeyEnter(); - }, - - onKeyEnter: function() { - this.typingOff(); - var cmd = this.getCommand(); - if (cmd) { - this.history[this.historyNum] = cmd; - this.backupNum = ++this.historyNum; - } - this.commandNum++; - this.advanceLine(); - if (cmd) { - if ( cmd == "clear" ) { - this.clear(); - this.prompt(); - } else if ( cmd.match(/^(back)$/) ) { - if (this.helpPage && this.helpPage.index >= 1) { - this.showHelp(this.helpPage.index - 1); - } - this.prompt(); - } else if ( cmd.match(/^(next)$/) ) { - if (this.helpPage) { - this.showHelp(this.helpPage.index + 1); - } - this.prompt(); - } else if ( cmd.match(/^(help|wtf\?*)$/) ) { - this.showHelp(1); - this.prompt(); - } else if ( regs = cmd.match(/^(help|wtf\?*)\s+#?(\d+)\s*$/) ) { - this.showChapter(parseInt(regs[2])); - this.prompt(); - } else { - var term = this; - this.fireOffCmd(cmd, (function(r) { term.reply(r.responseText ? r.responseText : ''); })); - } - } else { - this.prompt(); - } - } -}); - diff --git a/public/javascripts/raphael-min.js b/public/javascripts/raphael-min.js deleted file mode 100644 index 4a99e3e..0000000 --- a/public/javascripts/raphael-min.js +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Raphael 1.4.3 - JavaScript Vector Library - * - * Copyright (c) 2010 Dmitry Baranovskiy (http://raphaeljs.com) - * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. - */ -Raphael=function(){function m(){if(m.is(arguments[0],U)){for(var a=arguments[0],b=Aa[K](m,a.splice(0,3+m.is(a[0],O))),c=b.set(),d=0,f=a[o];d

              ";if(ha.childNodes[o]!=2)return m.type=null;ha=null}m.svg=!(m.vml=m.type=="VML");G[p]=m[p];m._id=0;m._oid=0;m.fn={};m.is=function(a,b){b=ca.call(b);return b=="object"&&a===Object(a)||b=="undefined"&&typeof a==b||b=="null"&&a==null||ca.call(ob.call(a).slice(8,-1))==b};m.setWindow=function(a){X=a;C=X.document};function ra(a){if(m.vml){var b=/^\s+|\s+$/g;ra=T(function(d){var f;d=(d+s)[I](b, -s);try{var e=new X.ActiveXObject("htmlfile");e.write("");e.close();f=e.body}catch(g){f=X.createPopup().document.body}e=f.createTextRange();try{f.style.color=d;var h=e.queryCommandValue("ForeColor");h=(h&255)<<16|h&65280|(h&16711680)>>>16;return"#"+("000000"+h[N](16)).slice(-6)}catch(i){return"none"}})}else{var c=C.createElement("i");c.title="Rapha\u00ebl Colour Picker";c.style.display="none";C.body[y](c);ra=T(function(d){c.style.color=d;return C.defaultView.getComputedStyle(c,s).getPropertyValue("color")})}return ra(a)} -function qb(){return"hsb("+[this.h,this.s,this.b]+")"}function rb(){return this.hex}m.hsb2rgb=T(function(a,b,c){if(m.is(a,"object")&&"h"in a&&"s"in a&&"b"in a){c=a.b;b=a.s;a=a.h}var d;if(c==0)return{r:0,g:0,b:0,hex:"#000"};if(a>1||b>1||c>1){a/=255;b/=255;c/=255}d=~~(a*6);a=a*6-d;var f=c*(1-b),e=c*(1-b*a),g=c*(1-b*(1-a));a=[c,e,f,f,g,c,c][d];b=[g,c,c,e,f,f,g][d];d=[f,f,g,c,c,e,f][d];a*=255;b*=255;d*=255;c={r:a,g:b,b:d,toString:rb};a=(~~a)[N](16);b=(~~b)[N](16);d=(~~d)[N](16);a=a[I](ga,"0");b=b[I](ga, -"0");d=d[I](ga,"0");c.hex="#"+a+b+d;return c},m);m.rgb2hsb=T(function(a,b,c){if(m.is(a,"object")&&"r"in a&&"g"in a&&"b"in a){c=a.b;b=a.g;a=a.r}if(m.is(a,ea)){var d=m.getRGB(a);a=d.r;b=d.g;c=d.b}if(a>1||b>1||c>1){a/=255;b/=255;c/=255}var f=Y(a,b,c),e=$(a,b,c);d=f;if(e==f)return{h:0,s:0,b:f};else{var g=f-e;e=g/f;a=a==f?(b-c)/g:b==f?2+(c-a)/g:4+(a-b)/g;a/=6;a<0&&a++;a>1&&a--}return{h:a,s:e,b:d,toString:qb}},m);var sb=/,?([achlmqrstvxz]),?/gi,sa=/\s*,\s*/,tb={hs:1,rg:1};m._path2string=function(){return this.join(",")[I](sb, -"$1")};function T(a,b,c){function d(){var f=Array[p].slice.call(arguments,0),e=f[Q]("\u25ba"),g=d.cache=d.cache||{},h=d.count=d.count||[];if(g[z](e))return c?c(g[e]):g[e];h[o]>=1000&&delete g[h.shift()];h[E](e);g[e]=a[K](b,f);return c?c(g[e]):g[e]}return d}m.getRGB=T(function(a){if(!a||(a+=s).indexOf("-")+1)return{r:-1,g:-1,b:-1,hex:"none",error:1};if(a=="none")return{r:-1,g:-1,b:-1,hex:"none"};!(tb[z](a.substring(0,2))||a.charAt()=="#")&&(a=ra(a));var b,c,d,f,e;if(a=a.match(pb)){if(a[2]){d=da(a[2].substring(5), -16);c=da(a[2].substring(3,5),16);b=da(a[2].substring(1,3),16)}if(a[3]){d=da((e=a[3].charAt(3))+e,16);c=da((e=a[3].charAt(2))+e,16);b=da((e=a[3].charAt(1))+e,16)}if(a[4]){a=a[4][H](sa);b=A(a[0]);c=A(a[1]);d=A(a[2]);f=A(a[3])}if(a[5]){a=a[5][H](sa);b=A(a[0])*2.55;c=A(a[1])*2.55;d=A(a[2])*2.55;f=A(a[3])}if(a[6]){a=a[6][H](sa);b=A(a[0]);c=A(a[1]);d=A(a[2]);return m.hsb2rgb(b,c,d)}if(a[7]){a=a[7][H](sa);b=A(a[0])*2.55;c=A(a[1])*2.55;d=A(a[2])*2.55;return m.hsb2rgb(b,c,d)}a={r:b,g:c,b:d};b=(~~b)[N](16); -c=(~~c)[N](16);d=(~~d)[N](16);b=b[I](ga,"0");c=c[I](ga,"0");d=d[I](ga,"0");a.hex="#"+b+c+d;isFinite(A(f))&&(a.o=f);return a}return{r:-1,g:-1,b:-1,hex:"none",error:1}},m);m.getColor=function(a){a=this.getColor.start=this.getColor.start||{h:0,s:1,b:a||0.75};var b=this.hsb2rgb(a.h,a.s,a.b);a.h+=0.075;if(a.h>1){a.h=0;a.s-=0.2;a.s<=0&&(this.getColor.start={h:0,s:1,b:a.b})}return b.hex};m.getColor.reset=function(){delete this.start};var ub=/([achlmqstvz])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig, -vb=/(-?\d*\.?\d*(?:e[-+]?\d+)?)\s*,?\s*/ig;m.parsePathString=T(function(a){if(!a)return null;var b={a:7,c:6,h:1,l:2,m:2,q:4,s:4,t:2,v:1,z:0},c=[];if(m.is(a,U)&&m.is(a[0],U))c=ta(a);c[o]||(a+s)[I](ub,function(d,f,e){var g=[];d=ca.call(f);e[I](vb,function(h,i){i&&g[E](+i)});if(d=="m"&&g[o]>2){c[E]([f][M](g.splice(0,2)));d="l";f=f=="m"?"l":"L"}for(;g[o]>=b[d];){c[E]([f][M](g.splice(0,b[d])));if(!b[d])break}});c[N]=m._path2string;return c});m.findDotsAtSegment=function(a,b,c,d,f,e,g,h,i){var j=1-i,l= -D(j,3)*a+D(j,2)*3*i*c+j*3*i*i*f+D(i,3)*g;j=D(j,3)*b+D(j,2)*3*i*d+j*3*i*i*e+D(i,3)*h;var n=a+2*i*(c-a)+i*i*(f-2*c+a),r=b+2*i*(d-b)+i*i*(e-2*d+b),q=c+2*i*(f-c)+i*i*(g-2*f+c),k=d+2*i*(e-d)+i*i*(h-2*e+d);a=(1-i)*a+i*c;b=(1-i)*b+i*d;f=(1-i)*f+i*g;e=(1-i)*e+i*h;h=90-w.atan((n-q)/(r-k))*180/w.PI;(n>q||r1){B=w.sqrt(B);c=B*c;d=B*d}B=c*c;var L=d*d;B=(e==g?-1:1)*w.sqrt(w.abs((B*L-B*x*x-L*k*k)/(B*x*x+L*k*k)));e=B*c*x/d+(a+h)/2;var B= -B*-d*k/c+(b+i)/2,x=w.asin(((b-B)/d).toFixed(7));k=w.asin(((i-B)/d).toFixed(7));x=ak)x-=l*2;if(!g&&k>x)k-=l*2}l=k-x;if(w.abs(l)>n){q=k;l=h;L=i;k=x+n*(g&&k>x?1:-1);h=e+c*w.cos(k);i=B+d*w.sin(k);q=Qa(h,i,c,d,f,0,g,l,L,[k,q,e,B])}l=k-x;f=w.cos(x);e=w.sin(x);g=w.cos(k);k=w.sin(k);l=w.tan(l/4);c=4/3*c*l;l=4/3*d*l;d=[a,b];a=[a+c*e,b-l*f];b=[h+c*k,i-l*g];h=[h,i];a[0]=2*d[0]-a[0];a[1]=2*d[1]-a[1];if(j)return[a,b,h][M](q);else{q=[a,b,h][M](q)[Q]()[H](","); -j=[];h=0;for(i=q[o];h1000000000000&&(n=0.5);w.abs(i)>1000000000000&&(i=0.5);if(n>0&&n<1){n=la(a,b,c,d,f,e,g,h,n);q[E](n.x);r[E](n.y)}if(i> -0&&i<1){n=la(a,b,c,d,f,e,g,h,i);q[E](n.x);r[E](n.y)}i=e-2*d+b-(h-2*e+d);j=2*(d-b)-2*(e-d);l=b-d;n=(-j+w.sqrt(j*j-4*i*l))/2/i;i=(-j-w.sqrt(j*j-4*i*l))/2/i;w.abs(n)>1000000000000&&(n=0.5);w.abs(i)>1000000000000&&(i=0.5);if(n>0&&n<1){n=la(a,b,c,d,f,e,g,h,n);q[E](n.x);r[E](n.y)}if(i>0&&i<1){n=la(a,b,c,d,f,e,g,h,i);q[E](n.x);r[E](n.y)}return{min:{x:$[K](0,q),y:$[K](0,r)},max:{x:Y[K](0,q),y:Y[K](0,r)}}}),ua=T(function(a,b){var c=ka(a),d=b&&ka(b);a={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null};b={x:0,y:0, -bx:0,by:0,X:0,Y:0,qx:null,qy:null};function f(q,k){var t;if(!q)return["C",k.x,k.y,k.x,k.y,k.x,k.y];!(q[0]in{T:1,Q:1})&&(k.qx=k.qy=null);switch(q[0]){case "M":k.X=q[1];k.Y=q[2];break;case "A":q=["C"][M](Qa[K](0,[k.x,k.y][M](q.slice(1))));break;case "S":t=k.x+(k.x-(k.bx||k.x));k=k.y+(k.y-(k.by||k.y));q=["C",t,k][M](q.slice(1));break;case "T":k.qx=k.x+(k.x-(k.qx||k.x));k.qy=k.y+(k.y-(k.qy||k.y));q=["C"][M](Pa(k.x,k.y,k.qx,k.qy,q[1],q[2]));break;case "Q":k.qx=q[1];k.qy=q[2];q=["C"][M](Pa(k.x,k.y,q[1], -q[2],q[3],q[4]));break;case "L":q=["C"][M](wa(k.x,k.y,q[1],q[2]));break;case "H":q=["C"][M](wa(k.x,k.y,q[1],k.y));break;case "V":q=["C"][M](wa(k.x,k.y,k.x,q[1]));break;case "Z":q=["C"][M](wa(k.x,k.y,k.X,k.Y));break}return q}function e(q,k){if(q[k][o]>7){q[k].shift();for(var t=q[k];t[o];)q.splice(k++,0,["C"][M](t.splice(0,6)));q.splice(k,1);i=Y(c[o],d&&d[o]||0)}}function g(q,k,t,L,B){if(q&&k&&q[B][0]=="M"&&k[B][0]!="M"){k.splice(B,0,["M",L.x,L.y]);t.bx=0;t.by=0;t.x=q[B][1];t.y=q[B][2];i=Y(c[o],d&& -d[o]||0)}}for(var h=0,i=Y(c[o],d&&d[o]||0);h0.5)*2-1;D(f-0.5,2)+D(e-0.5,2)>0.25&&(e=w.sqrt(0.25-D(f-0.5,2))*l+0.5)&&e!=0.5&&(e=e.toFixed(5)-1.0E-5*l)}return s});b=b[H](/\s*\-\s*/);if(d=="linear"){var h=b.shift();h=-A(h);if(isNaN(h))return null;h=[0,0,w.cos(h*w.PI/180),w.sin(h*w.PI/180)];var i=1/(Y(w.abs(h[2]),w.abs(h[3]))||1);h[2]*=i;h[3]*=i;if(h[2]<0){h[0]=-h[2];h[2]=0}if(h[3]<0){h[1]=-h[3];h[3]=0}}b=Ra(b);if(!b)return null; -i=a.getAttribute(aa);(i=i.match(/^url\(#(.*)\)$/))&&c.defs.removeChild(C.getElementById(i[1]));i=v(d+"Gradient");i.id="r"+(m._id++)[N](36);v(i,d=="radial"?{fx:f,fy:e}:{x1:h[0],y1:h[1],x2:h[2],y2:h[3]});c.defs[y](i);c=0;for(h=b[o];cb.height&&(b.height=e.y+e.height-b.y);e.x+e.width-b.x>b.width&&(b.width=e.x+e.width-b.x)}}a&&this.hide();return b};u[p].attr=function(a,b){if(this.removed)return this;if(a==null){a={};for(var c in this.attrs)if(this.attrs[z](c))a[c]=this.attrs[c];this._.rt.deg&&(a.rotation=this.rotate());(this._.sx!=1||this._.sy!= -1)&&(a.scale=this.scale());a.gradient&&a.fill=="none"&&(a.fill=a.gradient)&&delete a.gradient;return a}if(b==null&&m.is(a,ea)){if(a=="translation")return ya.call(this);if(a=="rotation")return this.rotate();if(a=="scale")return this.scale();if(a==aa&&this.attrs.fill=="none"&&this.attrs.gradient)return this.attrs.gradient;return this.attrs[a]}if(b==null&&m.is(a,U)){b={};c=0;for(var d=a.length;c1&&(a=1);f.opacity=a}b.fill&&(f.on=true);if(f.on==null||b.fill=="none")f.on=false;if(f.on&&b.fill)if(a=b.fill.match(Na)){f.src=a[1];f.type="tile"}else{f.color=m.getRGB(b.fill).hex;f.src= -s;f.type="solid";if(m.getRGB(b.fill).error&&(g.type in{circle:1,ellipse:1}||(b.fill+s).charAt()!="r")&&ma(g,b.fill)){d.fill="none";d.gradient=b.fill}}e&&c[y](f);f=c.getElementsByTagName("stroke")&&c.getElementsByTagName("stroke")[0];e=false;!f&&(e=f=R("stroke"));if(b.stroke&&b.stroke!="none"||b["stroke-width"]||b["stroke-opacity"]!=null||b["stroke-dasharray"]||b["stroke-miterlimit"]||b["stroke-linejoin"]||b["stroke-linecap"])f.on=true;(b.stroke=="none"||f.on==null||b.stroke==0||b["stroke-width"]== -0)&&(f.on=false);a=m.getRGB(b.stroke);f.on&&b.stroke&&(f.color=a.hex);a=((+d["stroke-opacity"]+1||2)-1)*((+d.opacity+1||2)-1)*((+a.o+1||2)-1);h=(A(b["stroke-width"])||1)*0.75;a<0&&(a=0);a>1&&(a=1);b["stroke-width"]==null&&(h=d["stroke-width"]);b["stroke-width"]&&(f.weight=h);h&&h<1&&(a*=h)&&(f.weight=1);f.opacity=a;b["stroke-linejoin"]&&(f.joinstyle=b["stroke-linejoin"]||"miter");f.miterlimit=b["stroke-miterlimit"]||8;b["stroke-linecap"]&&(f.endcap=b["stroke-linecap"]=="butt"?"flat":b["stroke-linecap"]== -"square"?"square":"round");if(b["stroke-dasharray"]){a={"-":"shortdash",".":"shortdot","-.":"shortdashdot","-..":"shortdashdotdot",". ":"dot","- ":"dash","--":"longdash","- .":"dashdot","--.":"longdashdot","--..":"longdashdotdot"};f.dashstyle=a[z](b["stroke-dasharray"])?a[b["stroke-dasharray"]]:s}e&&c[y](f)}if(g.type=="text"){f=g.paper.span.style;d.font&&(f.font=d.font);d["font-family"]&&(f.fontFamily=d["font-family"]);d["font-size"]&&(f.fontSize=d["font-size"]);d["font-weight"]&&(f.fontWeight=d["font-weight"]); -d["font-style"]&&(f.fontStyle=d["font-style"]);g.node.string&&(g.paper.span.innerHTML=(g.node.string+s)[I](/"));g.W=d.w=g.paper.span.offsetWidth;g.H=d.h=g.paper.span.offsetHeight;g.X=d.x;g.Y=d.y+F(g.H/2);switch(d["text-anchor"]){case "start":g.node.style["v-text-align"]="left";g.bbx=F(g.W/2);break;case "end":g.node.style["v-text-align"]="right";g.bbx=-F(g.W/2);break;default:g.node.style["v-text-align"]="center";break}}};ma=function(a,b){a.attrs=a.attrs|| -{};var c="linear",d=".5 .5";a.attrs.gradient=b;b=(b+s)[I](Ya,function(i,j,l){c="radial";if(j&&l){j=A(j);l=A(l);D(j-0.5,2)+D(l-0.5,2)>0.25&&(l=w.sqrt(0.25-D(j-0.5,2))*((l>0.5)*2-1)+0.5);d=j+P+l}return s});b=b[H](/\s*\-\s*/);if(c=="linear"){var f=b.shift();f=-A(f);if(isNaN(f))return null}var e=Ra(b);if(!e)return null;a=a.shape||a.node;b=a.getElementsByTagName(aa)[0]||R(aa);!b.parentNode&&a.appendChild(b);if(e[o]){b.on=true;b.method="none";b.color=e[0].color;b.color2=e[e[o]-1].color;a=[];for(var g=0, -h=e[o];g')}}catch(Kb){R=function(a){return C.createElement("<"+a+' xmlns="urn:schemas-microsoft.com:vml" class="rvml">')}}Aa=function(){var a=Sa[K](0,arguments),b=a.container,c=a.height,d=a.width,f=a.x;a=a.y;if(!b)throw new Error("VML container not found.");var e=new G,g=e.canvas=C.createElement("div"),h=g.style;f=f||0;a=a||0;d=d||512; -c=c||342;d==+d&&(d+="px");c==+c&&(c+="px");e.width=1000;e.height=1000;e.coordsize=ja*1000+P+ja*1000;e.coordorigin="0 0";e.span=C.createElement("span");e.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";g[y](e.span);h.cssText=m.format("width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden",d,c);if(b==1){C.body[y](g);h.left=f+"px";h.top=a+"px";h.position="absolute"}else b.firstChild?b.insertBefore(g, -b.firstChild):b[y](g);Fa.call(e,e,m.fn);return e};G[p].clear=function(){this.canvas.innerHTML=s;this.span=C.createElement("span");this.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";this.canvas[y](this.span);this.bottom=this.top=null};G[p].remove=function(){this.canvas.parentNode.removeChild(this.canvas);for(var a in this)this[a]=Xa(a);return true}}G[p].safari=/^Apple|^Google/.test(X.navigator.vendor)&&(!(X.navigator.userAgent.indexOf("Version/4.0")+ -1)||X.navigator.platform.slice(0,2)=="iP")?function(){var a=this.rect(-99,-99,this.width+99,this.height+99);X.setTimeout(function(){a.remove()})}:function(){};function Db(){this.returnValue=false}function Eb(){return this.originalEvent.preventDefault()}function Fb(){this.cancelBubble=true}function Gb(){return this.originalEvent.stopPropagation()}var Hb=function(){if(C.addEventListener)return function(a,b,c,d){var f=Ba&&Ca[b]?Ca[b]:b;function e(g){if(Ba&&Ca[z](b))for(var h=0,i=g.targetTouches&&g.targetTouches.length;h< -i;h++)if(g.targetTouches[h].target==a){i=g;g=g.targetTouches[h];g.originalEvent=i;g.preventDefault=Eb;g.stopPropagation=Gb;break}return c.call(d,g)}a.addEventListener(f,e,false);return function(){a.removeEventListener(f,e,false);return true}};else if(C.attachEvent)return function(a,b,c,d){function f(g){g=g||X.event;g.preventDefault=g.preventDefault||Db;g.stopPropagation=g.stopPropagation||Fb;return c.call(d,g)}a.attachEvent("on"+b,f);function e(){a.detachEvent("on"+b,f);return true}return e}}();for(ha= -Ma[o];ha--;)(function(a){m[a]=u[p][a]=function(b){if(m.is(b,"function")){this.events=this.events||[];this.events.push({name:a,f:b,unbind:Hb(this.shape||this.node||C,a,b,this)})}return this};m["un"+a]=u[p]["un"+a]=function(b){for(var c=this.events,d=c[o];d--;)if(c[d].name==a&&c[d].f==b){c[d].unbind();c.splice(d,1);!c.length&&delete this.events;return this}return this}})(Ma[ha]);u[p].hover=function(a,b){return this.mouseover(a).mouseout(b)};u[p].unhover=function(a,b){return this.unmouseover(a).unmouseout(b)}; -u[p].drag=function(a,b,c){this._drag={};var d=this.mousedown(function(g){(g.originalEvent?g.originalEvent:g).preventDefault();this._drag.x=g.clientX;this._drag.y=g.clientY;this._drag.id=g.identifier;b&&b.call(this,g.clientX,g.clientY);Raphael.mousemove(f).mouseup(e)});function f(g){var h=g.clientX,i=g.clientY;if(Ba)for(var j=g.touches.length,l;j--;){l=g.touches[j];if(l.identifier==d._drag.id){h=l.clientX;i=l.clientY;(g.originalEvent?g.originalEvent:g).preventDefault();break}}else g.preventDefault(); -a&&a.call(d,h-d._drag.x,i-d._drag.y,h,i)}function e(){d._drag={};Raphael.unmousemove(f).unmouseup(e);c&&c.call(d)}return this};G[p].circle=function(a,b,c){return ab(this,a||0,b||0,c||0)};G[p].rect=function(a,b,c,d,f){return bb(this,a||0,b||0,c||0,d||0,f||0)};G[p].ellipse=function(a,b,c,d){return cb(this,a||0,b||0,c||0,d||0)};G[p].path=function(a){a&&!m.is(a,ea)&&!m.is(a[0],U)&&(a+=s);return Za(m.format[K](m,arguments),this)};G[p].image=function(a,b,c,d,f){return db(this,a||"about:blank",b||0,c||0, -d||0,f||0)};G[p].text=function(a,b,c){return eb(this,a||0,b||0,c||s)};G[p].set=function(a){arguments[o]>1&&(a=Array[p].splice.call(arguments,0,arguments[o]));return new Z(a)};G[p].setSize=fb;G[p].top=G[p].bottom=null;G[p].raphael=m;function ib(){return this.x+P+this.y}u[p].resetScale=function(){if(this.removed)return this;this._.sx=1;this._.sy=1;this.attrs.scale="1 1"};u[p].scale=function(a,b,c,d){if(this.removed)return this;if(a==null&&b==null)return{x:this._.sx,y:this._.sy,toString:ib};b=b||a;!+b&& -(b=a);var f,e,g=this.attrs;if(a!=0){var h=this.getBBox(),i=h.x+h.width/2,j=h.y+h.height/2;f=a/this._.sx;e=b/this._.sy;c=+c||c==0?c:i;d=+d||d==0?d:j;h=~~(a/w.abs(a));var l=~~(b/w.abs(b)),n=this.node.style,r=c+(i-c)*f;j=d+(j-d)*e;switch(this.type){case "rect":case "image":var q=g.width*h*f,k=g.height*l*e;this.attr({height:k,r:g.r*$(h*f,l*e),width:q,x:r-q/2,y:j-k/2});break;case "circle":case "ellipse":this.attr({rx:g.rx*h*f,ry:g.ry*l*e,r:g.r*$(h*f,l*e),cx:r,cy:j});break;case "text":this.attr({x:r,y:j}); -break;case "path":i=Oa(g.path);for(var t=true,L=0,B=i[o];L=i)return r;l=r}});function Ha(a,b){return function(c,d,f){c=ua(c); -for(var e,g,h,i,j="",l={},n=0,r=0,q=c.length;rd){if(b&&!l.start){e=jb(e,g,h[1],h[2],h[3],h[4],h[5],h[6],d-n);j+=["C",e.start.x,e.start.y,e.m.x,e.m.y,e.x,e.y];if(f)return j;l.start=j;j=["M",e.x,e.y+"C",e.n.x,e.n.y,e.end.x,e.end.y,h[5],h[6]][Q]();n+=i;e=+h[5];g=+h[6];continue}if(!a&&!b){e=jb(e,g,h[1],h[2],h[3],h[4],h[5],h[6],d-n);return{x:e.x,y:e.y,alpha:e.alpha}}}n+=i;e=+h[5];g=+h[6]}j+=h}l.end=j;e=a?n: -b?l:m.findDotsAtSegment(e,g,h[1],h[2],h[3],h[4],h[5],h[6],1);e.alpha&&(e={x:e.x,y:e.y,alpha:e.alpha});return e}}var Ib=T(function(a,b,c,d,f,e,g,h){for(var i={x:0,y:0},j=0,l=0;l<1.01;l+=0.01){var n=la(a,b,c,d,f,e,g,h,l);l&&(j+=D(D(i.x-n.x,2)+D(i.y-n.y,2),0.5));i=n}return j}),kb=Ha(1),za=Ha(),Ia=Ha(0,1);u[p].getTotalLength=function(){if(this.type=="path"){if(this.node.getTotalLength)return this.node.getTotalLength();return kb(this.attrs.path)}};u[p].getPointAtLength=function(a){if(this.type=="path")return za(this.attrs.path, -a)};u[p].getSubpath=function(a,b){if(this.type=="path"){if(w.abs(this.getTotalLength()-b)<1.0E-6)return Ia(this.attrs.path,a).end;b=Ia(this.attrs.path,b,1);return a?Ia(b,a).end:b}};m.easing_formulas={linear:function(a){return a},"<":function(a){return D(a,3)},">":function(a){return D(a-1,3)+1},"<>":function(a){a*=2;if(a<1)return D(a,3)/2;a-=2;return(D(a,3)+2)/2},backIn:function(a){var b=1.70158;return a*a*((b+1)*a-b)},backOut:function(a){a-=1;var b=1.70158;return a*a*((b+1)*a+b)+1},elastic:function(a){if(a== -0||a==1)return a;var b=0.3,c=b/4;return D(2,-10*a)*w.sin((a-c)*2*w.PI/b)+1},bounce:function(a){var b=7.5625,c=2.75;if(a<1/c)a=b*a*a;else if(a<2/c){a-=1.5/c;a=b*a*a+0.75}else if(a<2.5/c){a-=2.25/c;a=b*a*a+0.9375}else{a-=2.625/c;a=b*a*a+0.984375}return a}};var S={length:0};function lb(){var a=+new Date;for(var b in S)if(b!="length"&&S[z](b)){var c=S[b];if(c.stop||c.el.removed){delete S[b];S[o]--}else{var d=a-c.start,f=c.ms,e=c.easing,g=c.from,h=c.diff,i=c.to,j=c.t,l=c.prev||0,n=c.el,r=c.callback,q= -{},k;if(d - - - - -

              you shouldn't be here.. kicking you out!

              - - diff --git a/public/js/irb.js b/public/js/irb.js deleted file mode 100755 index 23d83df..0000000 --- a/public/js/irb.js +++ /dev/null @@ -1,110 +0,0 @@ -// -// Copyright (c) 2008 why the lucky stiff -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, -// and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT -// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -var allStretch; -var helpPages; -var chapPages; -var defaultPage; -var toot = window.location.search.substr(1) - -//the main function, call to the effect object -function dumpAlert(obj) { - props = []; - for ( var i in obj ) { - props.push( "" + i + ": " + obj[i] ); - } - alert( props ); -} -window.onload = function() { - defaultPage = $('#helpstone .stretcher').html(); - - window.irb = new MouseApp.Irb('#irb', { - rows: 13, - name: 'IRB', - greeting: "%+r Interactive ruby ready. %-r", - ps: '\033[1;31m>>\033[m', - user: 'guest', - host: 'tryruby', - // original: irbUrl: '/irb', - irbUrl: '/irb.cgi', - init: function () { - helpPages = $(".stretcher"); - chapPages = new Array(); - for (var i = 0; i < helpPages.length; i++ ) { - var cls = helpPages[i].className.split(' '); - for (var j = 0; j < cls.length; j++) { - if (cls[j] == 'chapmark') { - chapPages.push([i, helpPages[i]]); - break; - } - } - } - }, - loadTutorial: function (id, instruct) { - $.ajax({ - url: '/tutorials/' + id + '.html', - type: 'GET', - complete: function (r) { - $('#helpstone').html("
              " + defaultPage + "
              " + r.responseText); - window.irb.init(); - window.irb.showHelp(0); - } - }); - }, - showChapter: function (n) { - if (n >= chapPages.length) return; - this.setHelpPage(chapPages[n][0], chapPages[n][1]); - }, - showHelp: function (n) { - if (n >= helpPages.length) return; - this.setHelpPage(n, helpPages[n]); - }, - popup_goto: function (u) { - $('#lilBrowser').show().css({left: '40px', top: '40px'}); - $('#lbIframe').attr('src', u); - }, - popup_make: function (s) { - $('#lilBrowser').show().css({left: '40px', top: '40px'}); - $('#lbIframe').get(0).onIframeLoad = function () { - alert($(this).html()); - alert("$(this).html()"); - return s; - }; - //$('#lbIframe').attr({src: '/blank.html'}); - src = s.replace(/\\/g, "\\\\").replace(/\"/g, "\\\""); - $('#lbIframe').attr({src: "javascript:\"" + src + "\""}); - // $('# - }, - popup_close: function () { - $('#lilBrowser').hide(); - } - }); - - if ( !toot ) { - toot = 'intro'; - } - try { - window.irb.options.loadTutorial( toot, true ); - } catch (e) {} -} diff --git a/public/js/jquery-1.3.2.min.js b/public/js/jquery-1.3.2.min.js deleted file mode 100644 index b1ae21d..0000000 --- a/public/js/jquery-1.3.2.min.js +++ /dev/null @@ -1,19 +0,0 @@ -/* - * jQuery JavaScript Library v1.3.2 - * http://jquery.com/ - * - * Copyright (c) 2009 John Resig - * Dual licensed under the MIT and GPL licenses. - * http://docs.jquery.com/License - * - * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) - * Revision: 6246 - */ -(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("",""]||!O.indexOf("",""]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
              "]||!O.indexOf("",""]||(!O.indexOf("",""]||!O.indexOf("",""]||!o.support.htmlSerialize&&[1,"div
              ","
              "]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}}); -/* - * Sizzle CSS Selector Engine - v0.9.3 - * Copyright 2009, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * More information: http://sizzlejs.com/ - */ -(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return UT[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="

              ";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="
              ";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("
              ").append(M.responseText.replace(//g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='
              ';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})(); \ No newline at end of file diff --git a/public/js/jquery.js b/public/js/jquery.js deleted file mode 100755 index 3747929..0000000 --- a/public/js/jquery.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * jQuery 1.2.3 - New Wave Javascript - * - * Copyright (c) 2008 John Resig (jquery.com) - * Dual licensed under the MIT (MIT-LICENSE.txt) - * and GPL (GPL-LICENSE.txt) licenses. - * - * $Date: 2008-02-06 00:21:25 -0500 (Wed, 06 Feb 2008) $ - * $Rev: 4663 $ - */ -(function(){if(window.jQuery)var _jQuery=window.jQuery;var jQuery=window.jQuery=function(selector,context){return new jQuery.prototype.init(selector,context);};if(window.$)var _$=window.$;window.$=jQuery;var quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;var isSimple=/^.[^:#\[\.]*$/;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;return this;}else if(typeof selector=="string"){var match=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1])selector=jQuery.clean([match[1]],context);else{var elem=document.getElementById(match[3]);if(elem)if(elem.id!=match[3])return jQuery().find(selector);else{this[0]=elem;this.length=1;return this;}else -selector=[];}}else -return new jQuery(context).find(selector);}else if(jQuery.isFunction(selector))return new jQuery(document)[jQuery.fn.ready?"ready":"load"](selector);return this.setArray(selector.constructor==Array&&selector||(selector.jquery||selector.length&&selector!=window&&!selector.nodeType&&selector[0]!=undefined&&selector[0].nodeType)&&jQuery.makeArray(selector)||[selector]);},jquery:"1.2.3",size:function(){return this.length;},length:0,get:function(num){return num==undefined?jQuery.makeArray(this):this[num];},pushStack:function(elems){var ret=jQuery(elems);ret.prevObject=this;return ret;},setArray:function(elems){this.length=0;Array.prototype.push.apply(this,elems);return this;},each:function(callback,args){return jQuery.each(this,callback,args);},index:function(elem){var ret=-1;this.each(function(i){if(this==elem)ret=i;});return ret;},attr:function(name,value,type){var options=name;if(name.constructor==String)if(value==undefined)return this.length&&jQuery[type||"attr"](this[0],name)||undefined;else{options={};options[name]=value;}return this.each(function(i){for(name in options)jQuery.attr(type?this.style:this,name,jQuery.prop(this,options[name],type,i,name));});},css:function(key,value){if((key=='width'||key=='height')&&parseFloat(value)<0)value=undefined;return this.attr(key,value,"curCSS");},text:function(text){if(typeof text!="object"&&text!=null)return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(text));var ret="";jQuery.each(text||this,function(){jQuery.each(this.childNodes,function(){if(this.nodeType!=8)ret+=this.nodeType!=1?this.nodeValue:jQuery.fn.text([this]);});});return ret;},wrapAll:function(html){if(this[0])jQuery(html,this[0].ownerDocument).clone().insertBefore(this[0]).map(function(){var elem=this;while(elem.firstChild)elem=elem.firstChild;return elem;}).append(this);return this;},wrapInner:function(html){return this.each(function(){jQuery(this).contents().wrapAll(html);});},wrap:function(html){return this.each(function(){jQuery(this).wrapAll(html);});},append:function(){return this.domManip(arguments,true,false,function(elem){if(this.nodeType==1)this.appendChild(elem);});},prepend:function(){return this.domManip(arguments,true,true,function(elem){if(this.nodeType==1)this.insertBefore(elem,this.firstChild);});},before:function(){return this.domManip(arguments,false,false,function(elem){this.parentNode.insertBefore(elem,this);});},after:function(){return this.domManip(arguments,false,true,function(elem){this.parentNode.insertBefore(elem,this.nextSibling);});},end:function(){return this.prevObject||jQuery([]);},find:function(selector){var elems=jQuery.map(this,function(elem){return jQuery.find(selector,elem);});return this.pushStack(/[^+>] [^+>]/.test(selector)||selector.indexOf("..")>-1?jQuery.unique(elems):elems);},clone:function(events){var ret=this.map(function(){if(jQuery.browser.msie&&!jQuery.isXMLDoc(this)){var clone=this.cloneNode(true),container=document.createElement("div");container.appendChild(clone);return jQuery.clean([container.innerHTML])[0];}else -return this.cloneNode(true);});var clone=ret.find("*").andSelf().each(function(){if(this[expando]!=undefined)this[expando]=null;});if(events===true)this.find("*").andSelf().each(function(i){if(this.nodeType==3)return;var events=jQuery.data(this,"events");for(var type in events)for(var handler in events[type])jQuery.event.add(clone[i],type,events[type][handler],events[type][handler].data);});return ret;},filter:function(selector){return this.pushStack(jQuery.isFunction(selector)&&jQuery.grep(this,function(elem,i){return selector.call(elem,i);})||jQuery.multiFilter(selector,this));},not:function(selector){if(selector.constructor==String)if(isSimple.test(selector))return this.pushStack(jQuery.multiFilter(selector,this,true));else -selector=jQuery.multiFilter(selector,this);var isArrayLike=selector.length&&selector[selector.length-1]!==undefined&&!selector.nodeType;return this.filter(function(){return isArrayLike?jQuery.inArray(this,selector)<0:this!=selector;});},add:function(selector){return!selector?this:this.pushStack(jQuery.merge(this.get(),selector.constructor==String?jQuery(selector).get():selector.length!=undefined&&(!selector.nodeName||jQuery.nodeName(selector,"form"))?selector:[selector]));},is:function(selector){return selector?jQuery.multiFilter(selector,this).length>0:false;},hasClass:function(selector){return this.is("."+selector);},val:function(value){if(value==undefined){if(this.length){var elem=this[0];if(jQuery.nodeName(elem,"select")){var index=elem.selectedIndex,values=[],options=elem.options,one=elem.type=="select-one";if(index<0)return null;for(var i=one?index:0,max=one?index+1:options.length;i=0||jQuery.inArray(this.name,value)>=0);else if(jQuery.nodeName(this,"select")){var values=value.constructor==Array?value:[value];jQuery("option",this).each(function(){this.selected=(jQuery.inArray(this.value,values)>=0||jQuery.inArray(this.text,values)>=0);});if(!values.length)this.selectedIndex=-1;}else -this.value=value;});},html:function(value){return value==undefined?(this.length?this[0].innerHTML:null):this.empty().append(value);},replaceWith:function(value){return this.after(value).remove();},eq:function(i){return this.slice(i,i+1);},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments));},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem);}));},andSelf:function(){return this.add(this.prevObject);},data:function(key,value){var parts=key.split(".");parts[1]=parts[1]?"."+parts[1]:"";if(value==null){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data==undefined&&this.length)data=jQuery.data(this[0],key);return data==null&&parts[1]?this.data(parts[0]):data;}else -return this.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){jQuery.data(this,key,value);});},removeData:function(key){return this.each(function(){jQuery.removeData(this,key);});},domManip:function(args,table,reverse,callback){var clone=this.length>1,elems;return this.each(function(){if(!elems){elems=jQuery.clean(args,this.ownerDocument);if(reverse)elems.reverse();}var obj=this;if(table&&jQuery.nodeName(this,"table")&&jQuery.nodeName(elems[0],"tr"))obj=this.getElementsByTagName("tbody")[0]||this.appendChild(this.ownerDocument.createElement("tbody"));var scripts=jQuery([]);jQuery.each(elems,function(){var elem=clone?jQuery(this).clone(true)[0]:this;if(jQuery.nodeName(elem,"script")){scripts=scripts.add(elem);}else{if(elem.nodeType==1)scripts=scripts.add(jQuery("script",elem).remove());callback.call(obj,elem);}});scripts.each(evalScript);});}};jQuery.prototype.init.prototype=jQuery.prototype;function evalScript(i,elem){if(elem.src)jQuery.ajax({url:elem.src,async:false,dataType:"script"});else -jQuery.globalEval(elem.text||elem.textContent||elem.innerHTML||"");if(elem.parentNode)elem.parentNode.removeChild(elem);}jQuery.extend=jQuery.fn.extend=function(){var target=arguments[0]||{},i=1,length=arguments.length,deep=false,options;if(target.constructor==Boolean){deep=target;target=arguments[1]||{};i=2;}if(typeof target!="object"&&typeof target!="function")target={};if(length==1){target=this;i=0;}for(;i-1;}},swap:function(elem,options,callback){var old={};for(var name in options){old[name]=elem.style[name];elem.style[name]=options[name];}callback.call(elem);for(var name in options)elem.style[name]=old[name];},css:function(elem,name,force){if(name=="width"||name=="height"){var val,props={position:"absolute",visibility:"hidden",display:"block"},which=name=="width"?["Left","Right"]:["Top","Bottom"];function getWH(){val=name=="width"?elem.offsetWidth:elem.offsetHeight;var padding=0,border=0;jQuery.each(which,function(){padding+=parseFloat(jQuery.curCSS(elem,"padding"+this,true))||0;border+=parseFloat(jQuery.curCSS(elem,"border"+this+"Width",true))||0;});val-=Math.round(padding+border);}if(jQuery(elem).is(":visible"))getWH();else -jQuery.swap(elem,props,getWH);return Math.max(0,val);}return jQuery.curCSS(elem,name,force);},curCSS:function(elem,name,force){var ret;function color(elem){if(!jQuery.browser.safari)return false;var ret=document.defaultView.getComputedStyle(elem,null);return!ret||ret.getPropertyValue("color")=="";}if(name=="opacity"&&jQuery.browser.msie){ret=jQuery.attr(elem.style,"opacity");return ret==""?"1":ret;}if(jQuery.browser.opera&&name=="display"){var save=elem.style.outline;elem.style.outline="0 solid black";elem.style.outline=save;}if(name.match(/float/i))name=styleFloat;if(!force&&elem.style&&elem.style[name])ret=elem.style[name];else if(document.defaultView&&document.defaultView.getComputedStyle){if(name.match(/float/i))name="float";name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var getComputedStyle=document.defaultView.getComputedStyle(elem,null);if(getComputedStyle&&!color(elem))ret=getComputedStyle.getPropertyValue(name);else{var swap=[],stack=[];for(var a=elem;a&&color(a);a=a.parentNode)stack.unshift(a);for(var i=0;i]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+">";});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("",""]||!tags.indexOf("",""]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
              "]||!tags.indexOf("",""]||(!tags.indexOf("",""]||!tags.indexOf("",""]||jQuery.browser.msie&&[1,"div
              ","
              "]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--)div=div.lastChild;if(jQuery.browser.msie){var tbody=!tags.indexOf(""&&tags.indexOf("=0;--j)if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length)tbody[j].parentNode.removeChild(tbody[j]);if(/^\s/.test(elem))div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]),div.firstChild);}elem=jQuery.makeArray(div.childNodes);}if(elem.length===0&&(!jQuery.nodeName(elem,"form")&&!jQuery.nodeName(elem,"select")))return;if(elem[0]==undefined||jQuery.nodeName(elem,"form")||elem.options)ret.push(elem);else -ret=jQuery.merge(ret,elem);});return ret;},attr:function(elem,name,value){if(!elem||elem.nodeType==3||elem.nodeType==8)return undefined;var fix=jQuery.isXMLDoc(elem)?{}:jQuery.props;if(name=="selected"&&jQuery.browser.safari)elem.parentNode.selectedIndex;if(fix[name]){if(value!=undefined)elem[fix[name]]=value;return elem[fix[name]];}else if(jQuery.browser.msie&&name=="style")return jQuery.attr(elem.style,"cssText",value);else if(value==undefined&&jQuery.browser.msie&&jQuery.nodeName(elem,"form")&&(name=="action"||name=="method"))return elem.getAttributeNode(name).nodeValue;else if(elem.tagName){if(value!=undefined){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode)throw"type property can't be changed";elem.setAttribute(name,""+value);}if(jQuery.browser.msie&&/href|src/.test(name)&&!jQuery.isXMLDoc(elem))return elem.getAttribute(name,2);return elem.getAttribute(name);}else{if(name=="opacity"&&jQuery.browser.msie){if(value!=undefined){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+(parseFloat(value).toString()=="NaN"?"":"alpha(opacity="+value*100+")");}return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100).toString():"";}name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase();});if(value!=undefined)elem[name]=value;return elem[name];}},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"");},makeArray:function(array){var ret=[];if(typeof array!="array")for(var i=0,length=array.length;i*",this).remove();while(this.firstChild)this.removeChild(this.firstChild);}},function(name,fn){jQuery.fn[name]=function(){return this.each(fn,arguments);};});jQuery.each(["Height","Width"],function(i,name){var type=name.toLowerCase();jQuery.fn[type]=function(size){return this[0]==window?jQuery.browser.opera&&document.body["client"+name]||jQuery.browser.safari&&window["inner"+name]||document.compatMode=="CSS1Compat"&&document.documentElement["client"+name]||document.body["client"+name]:this[0]==document?Math.max(Math.max(document.body["scroll"+name],document.documentElement["scroll"+name]),Math.max(document.body["offset"+name],document.documentElement["offset"+name])):size==undefined?(this.length?jQuery.css(this[0],type):null):this.css(type,size.constructor==String?size:size+"px");};});var chars=jQuery.browser.safari&&parseInt(jQuery.browser.version)<417?"(?:[\\w*_-]|\\\\.)":"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",quickChild=new RegExp("^>\\s*("+chars+"+)"),quickID=new RegExp("^("+chars+"+)(#)("+chars+"+)"),quickClass=new RegExp("^([#.]?)("+chars+"*)");jQuery.extend({expr:{"":function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},"#":function(a,i,m){return a.getAttribute("id")==m[2];},":":{lt:function(a,i,m){return im[3]-0;},nth:function(a,i,m){return m[3]-0==i;},eq:function(a,i,m){return m[3]-0==i;},first:function(a,i){return i==0;},last:function(a,i,m,r){return i==r.length-1;},even:function(a,i){return i%2==0;},odd:function(a,i){return i%2;},"first-child":function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},"last-child":function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},"only-child":function(a){return!jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},parent:function(a){return a.firstChild;},empty:function(a){return!a.firstChild;},contains:function(a,i,m){return(a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},visible:function(a){return"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},hidden:function(a){return"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},enabled:function(a){return!a.disabled;},disabled:function(a){return a.disabled;},checked:function(a){return a.checked;},selected:function(a){return a.selected||jQuery.attr(a,"selected");},text:function(a){return"text"==a.type;},radio:function(a){return"radio"==a.type;},checkbox:function(a){return"checkbox"==a.type;},file:function(a){return"file"==a.type;},password:function(a){return"password"==a.type;},submit:function(a){return"submit"==a.type;},image:function(a){return"image"==a.type;},reset:function(a){return"reset"==a.type;},button:function(a){return"button"==a.type||jQuery.nodeName(a,"button");},input:function(a){return/input|select|textarea|button/i.test(a.nodeName);},has:function(a,i,m){return jQuery.find(m[3],a).length;},header:function(a){return/h\d/i.test(a.nodeName);},animated:function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}}},parse:[/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,new RegExp("^([:.#]*)("+chars+"+)")],multiFilter:function(expr,elems,not){var old,cur=[];while(expr&&expr!=old){old=expr;var f=jQuery.filter(expr,elems,not);expr=f.t.replace(/^\s*,\s*/,"");cur=not?elems=f.r:jQuery.merge(cur,f.r);}return cur;},find:function(t,context){if(typeof t!="string")return[t];if(context&&context.nodeType!=1&&context.nodeType!=9)return[];context=context||document;var ret=[context],done=[],last,nodeName;while(t&&last!=t){var r=[];last=t;t=jQuery.trim(t);var foundToken=false;var re=quickChild;var m=re.exec(t);if(m){nodeName=m[1].toUpperCase();for(var i=0;ret[i];i++)for(var c=ret[i].firstChild;c;c=c.nextSibling)if(c.nodeType==1&&(nodeName=="*"||c.nodeName.toUpperCase()==nodeName))r.push(c);ret=r;t=t.replace(re,"");if(t.indexOf(" ")==0)continue;foundToken=true;}else{re=/^([>+~])\s*(\w*)/i;if((m=re.exec(t))!=null){r=[];var merge={};nodeName=m[2].toUpperCase();m=m[1];for(var j=0,rl=ret.length;j=0;if(!not&&pass||not&&!pass)tmp.push(r[i]);}return tmp;},filter:function(t,r,not){var last;while(t&&t!=last){last=t;var p=jQuery.parse,m;for(var i=0;p[i];i++){m=p[i].exec(t);if(m){t=t.substring(m[0].length);m[2]=m[2].replace(/\\/g,"");break;}}if(!m)break;if(m[1]==":"&&m[2]=="not")r=isSimple.test(m[3])?jQuery.filter(m[3],r,true).r:jQuery(r).not(m[3]);else if(m[1]==".")r=jQuery.classFilter(r,m[2],not);else if(m[1]=="["){var tmp=[],type=m[3];for(var i=0,rl=r.length;i=0)^not)tmp.push(a);}r=tmp;}else if(m[1]==":"&&m[2]=="nth-child"){var merge={},tmp=[],test=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3]=="even"&&"2n"||m[3]=="odd"&&"2n+1"||!/\D/.test(m[3])&&"0n+"+m[3]||m[3]),first=(test[1]+(test[2]||1))-0,last=test[3]-0;for(var i=0,rl=r.length;i=0)add=true;if(add^not)tmp.push(node);}r=tmp;}else{var fn=jQuery.expr[m[1]];if(typeof fn=="object")fn=fn[m[2]];if(typeof fn=="string")fn=eval("false||function(a,i){return "+fn+";}");r=jQuery.grep(r,function(elem,i){return fn(elem,i,m,r);},not);}}return{r:r,t:t};},dir:function(elem,dir){var matched=[];var cur=elem[dir];while(cur&&cur!=document){if(cur.nodeType==1)matched.push(cur);cur=cur[dir];}return matched;},nth:function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir])if(cur.nodeType==1&&++num==result)break;return cur;},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType==1&&(!elem||n!=elem))r.push(n);}return r;}});jQuery.event={add:function(elem,types,handler,data){if(elem.nodeType==3||elem.nodeType==8)return;if(jQuery.browser.msie&&elem.setInterval!=undefined)elem=window;if(!handler.guid)handler.guid=this.guid++;if(data!=undefined){var fn=handler;handler=function(){return fn.apply(this,arguments);};handler.data=data;handler.guid=fn.guid;}var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){var val;if(typeof jQuery=="undefined"||jQuery.event.triggered)return val;val=jQuery.event.handle.apply(arguments.callee.elem,arguments);return val;});handle.elem=elem;jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];handler.type=parts[1];var handlers=events[type];if(!handlers){handlers=events[type]={};if(!jQuery.event.special[type]||jQuery.event.special[type].setup.call(elem)===false){if(elem.addEventListener)elem.addEventListener(type,handle,false);else if(elem.attachEvent)elem.attachEvent("on"+type,handle);}}handlers[handler.guid]=handler;jQuery.event.global[type]=true;});elem=null;},guid:1,global:{},remove:function(elem,types,handler){if(elem.nodeType==3||elem.nodeType==8)return;var events=jQuery.data(elem,"events"),ret,index;if(events){if(types==undefined||(typeof types=="string"&&types.charAt(0)=="."))for(var type in events)this.remove(elem,type+(types||""));else{if(types.type){handler=types.handler;types=types.type;}jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];if(events[type]){if(handler)delete events[type][handler.guid];else -for(handler in events[type])if(!parts[1]||events[type][handler].type==parts[1])delete events[type][handler];for(ret in events[type])break;if(!ret){if(!jQuery.event.special[type]||jQuery.event.special[type].teardown.call(elem)===false){if(elem.removeEventListener)elem.removeEventListener(type,jQuery.data(elem,"handle"),false);else if(elem.detachEvent)elem.detachEvent("on"+type,jQuery.data(elem,"handle"));}ret=null;delete events[type];}}});}for(ret in events)break;if(!ret){var handle=jQuery.data(elem,"handle");if(handle)handle.elem=null;jQuery.removeData(elem,"events");jQuery.removeData(elem,"handle");}}},trigger:function(type,data,elem,donative,extra){data=jQuery.makeArray(data||[]);if(type.indexOf("!")>=0){type=type.slice(0,-1);var exclusive=true;}if(!elem){if(this.global[type])jQuery("*").add([window,document]).trigger(type,data);}else{if(elem.nodeType==3||elem.nodeType==8)return undefined;var val,ret,fn=jQuery.isFunction(elem[type]||null),event=!data[0]||!data[0].preventDefault;if(event)data.unshift(this.fix({type:type,target:elem}));data[0].type=type;if(exclusive)data[0].exclusive=true;if(jQuery.isFunction(jQuery.data(elem,"handle")))val=jQuery.data(elem,"handle").apply(elem,data);if(!fn&&elem["on"+type]&&elem["on"+type].apply(elem,data)===false)val=false;if(event)data.shift();if(extra&&jQuery.isFunction(extra)){ret=extra.apply(elem,val==null?data:data.concat(val));if(ret!==undefined)val=ret;}if(fn&&donative!==false&&val!==false&&!(jQuery.nodeName(elem,'a')&&type=="click")){this.triggered=true;try{elem[type]();}catch(e){}}this.triggered=false;}return val;},handle:function(event){var val;event=jQuery.event.fix(event||window.event||{});var parts=event.type.split(".");event.type=parts[0];var handlers=jQuery.data(this,"events")&&jQuery.data(this,"events")[event.type],args=Array.prototype.slice.call(arguments,1);args.unshift(event);for(var j in handlers){var handler=handlers[j];args[0].handler=handler;args[0].data=handler.data;if(!parts[1]&&!event.exclusive||handler.type==parts[1]){var ret=handler.apply(this,args);if(val!==false)val=ret;if(ret===false){event.preventDefault();event.stopPropagation();}}}if(jQuery.browser.msie)event.target=event.preventDefault=event.stopPropagation=event.handler=event.data=null;return val;},fix:function(event){var originalEvent=event;event=jQuery.extend({},originalEvent);event.preventDefault=function(){if(originalEvent.preventDefault)originalEvent.preventDefault();originalEvent.returnValue=false;};event.stopPropagation=function(){if(originalEvent.stopPropagation)originalEvent.stopPropagation();originalEvent.cancelBubble=true;};if(!event.target)event.target=event.srcElement||document;if(event.target.nodeType==3)event.target=originalEvent.target.parentNode;if(!event.relatedTarget&&event.fromElement)event.relatedTarget=event.fromElement==event.target?event.toElement:event.fromElement;if(event.pageX==null&&event.clientX!=null){var doc=document.documentElement,body=document.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc.clientTop||0);}if(!event.which&&((event.charCode||event.charCode===0)?event.charCode:event.keyCode))event.which=event.charCode||event.keyCode;if(!event.metaKey&&event.ctrlKey)event.metaKey=event.ctrlKey;if(!event.which&&event.button)event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)));return event;},special:{ready:{setup:function(){bindReady();return;},teardown:function(){return;}},mouseenter:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseover",jQuery.event.special.mouseenter.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseover",jQuery.event.special.mouseenter.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseenter";return jQuery.event.handle.apply(this,arguments);}},mouseleave:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseout",jQuery.event.special.mouseleave.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseout",jQuery.event.special.mouseleave.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseleave";return jQuery.event.handle.apply(this,arguments);}}}};jQuery.fn.extend({bind:function(type,data,fn){return type=="unload"?this.one(type,data,fn):this.each(function(){jQuery.event.add(this,type,fn||data,fn&&data);});},one:function(type,data,fn){return this.each(function(){jQuery.event.add(this,type,function(event){jQuery(this).unbind(event);return(fn||data).apply(this,arguments);},fn&&data);});},unbind:function(type,fn){return this.each(function(){jQuery.event.remove(this,type,fn);});},trigger:function(type,data,fn){return this.each(function(){jQuery.event.trigger(type,data,this,true,fn);});},triggerHandler:function(type,data,fn){if(this[0])return jQuery.event.trigger(type,data,this[0],false,fn);return undefined;},toggle:function(){var args=arguments;return this.click(function(event){this.lastToggle=0==this.lastToggle?1:0;event.preventDefault();return args[this.lastToggle].apply(this,arguments)||false;});},hover:function(fnOver,fnOut){return this.bind('mouseenter',fnOver).bind('mouseleave',fnOut);},ready:function(fn){bindReady();if(jQuery.isReady)fn.call(document,jQuery);else -jQuery.readyList.push(function(){return fn.call(this,jQuery);});return this;}});jQuery.extend({isReady:false,readyList:[],ready:function(){if(!jQuery.isReady){jQuery.isReady=true;if(jQuery.readyList){jQuery.each(jQuery.readyList,function(){this.apply(document);});jQuery.readyList=null;}jQuery(document).triggerHandler("ready");}}});var readyBound=false;function bindReady(){if(readyBound)return;readyBound=true;if(document.addEventListener&&!jQuery.browser.opera)document.addEventListener("DOMContentLoaded",jQuery.ready,false);if(jQuery.browser.msie&&window==top)(function(){if(jQuery.isReady)return;try{document.documentElement.doScroll("left");}catch(error){setTimeout(arguments.callee,0);return;}jQuery.ready();})();if(jQuery.browser.opera)document.addEventListener("DOMContentLoaded",function(){if(jQuery.isReady)return;for(var i=0;i=0){var selector=url.slice(off,url.length);url=url.slice(0,off);}callback=callback||function(){};var type="GET";if(params)if(jQuery.isFunction(params)){callback=params;params=null;}else{params=jQuery.param(params);type="POST";}var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(res,status){if(status=="success"||status=="notmodified")self.html(selector?jQuery("
              ").append(res.responseText.replace(//g,"")).find(selector):res.responseText);self.each(callback,[res.responseText,status,res]);}});return this;},serialize:function(){return jQuery.param(this.serializeArray());},serializeArray:function(){return this.map(function(){return jQuery.nodeName(this,"form")?jQuery.makeArray(this.elements):this;}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type));}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:val.constructor==Array?jQuery.map(val,function(val,i){return{name:elem.name,value:val};}):{name:elem.name,value:val};}).get();}});jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(i,o){jQuery.fn[o]=function(f){return this.bind(o,f);};});var jsc=(new Date).getTime();jQuery.extend({get:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data=null;}return jQuery.ajax({type:"GET",url:url,data:data,success:callback,dataType:type});},getScript:function(url,callback){return jQuery.get(url,null,callback,"script");},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},post:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data={};}return jQuery.ajax({type:"POST",url:url,data:data,success:callback,dataType:type});},ajaxSetup:function(settings){jQuery.extend(jQuery.ajaxSettings,settings);},ajaxSettings:{global:true,type:"GET",timeout:0,contentType:"application/x-www-form-urlencoded",processData:true,async:true,data:null,username:null,password:null,accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(s){var jsonp,jsre=/=\?(&|$)/g,status,data;s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));if(s.data&&s.processData&&typeof s.data!="string")s.data=jQuery.param(s.data);if(s.dataType=="jsonp"){if(s.type.toLowerCase()=="get"){if(!s.url.match(jsre))s.url+=(s.url.match(/\?/)?"&":"?")+(s.jsonp||"callback")+"=?";}else if(!s.data||!s.data.match(jsre))s.data=(s.data?s.data+"&":"")+(s.jsonp||"callback")+"=?";s.dataType="json";}if(s.dataType=="json"&&(s.data&&s.data.match(jsre)||s.url.match(jsre))){jsonp="jsonp"+jsc++;if(s.data)s.data=(s.data+"").replace(jsre,"="+jsonp+"$1");s.url=s.url.replace(jsre,"="+jsonp+"$1");s.dataType="script";window[jsonp]=function(tmp){data=tmp;success();complete();window[jsonp]=undefined;try{delete window[jsonp];}catch(e){}if(head)head.removeChild(script);};}if(s.dataType=="script"&&s.cache==null)s.cache=false;if(s.cache===false&&s.type.toLowerCase()=="get"){var ts=(new Date()).getTime();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"");}if(s.data&&s.type.toLowerCase()=="get"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null;}if(s.global&&!jQuery.active++)jQuery.event.trigger("ajaxStart");if((!s.url.indexOf("http")||!s.url.indexOf("//"))&&s.dataType=="script"&&s.type.toLowerCase()=="get"){var head=document.getElementsByTagName("head")[0];var script=document.createElement("script");script.src=s.url;if(s.scriptCharset)script.charset=s.scriptCharset;if(!jsonp){var done=false;script.onload=script.onreadystatechange=function(){if(!done&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){done=true;success();complete();head.removeChild(script);}};}head.appendChild(script);return undefined;}var requestDone=false;var xml=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();xml.open(s.type,s.url,s.async,s.username,s.password);try{if(s.data)xml.setRequestHeader("Content-Type",s.contentType);if(s.ifModified)xml.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT");xml.setRequestHeader("X-Requested-With","XMLHttpRequest");xml.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default);}catch(e){}if(s.beforeSend)s.beforeSend(xml);if(s.global)jQuery.event.trigger("ajaxSend",[xml,s]);var onreadystatechange=function(isTimeout){if(!requestDone&&xml&&(xml.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null;}status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xml)&&"error"||s.ifModified&&jQuery.httpNotModified(xml,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xml,s.dataType);}catch(e){status="parsererror";}}if(status=="success"){var modRes;try{modRes=xml.getResponseHeader("Last-Modified");}catch(e){}if(s.ifModified&&modRes)jQuery.lastModified[s.url]=modRes;if(!jsonp)success();}else -jQuery.handleError(s,xml,status);complete();if(s.async)xml=null;}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0)setTimeout(function(){if(xml){xml.abort();if(!requestDone)onreadystatechange("timeout");}},s.timeout);}try{xml.send(s.data);}catch(e){jQuery.handleError(s,xml,null,e);}if(!s.async)onreadystatechange();function success(){if(s.success)s.success(data,status);if(s.global)jQuery.event.trigger("ajaxSuccess",[xml,s]);}function complete(){if(s.complete)s.complete(xml,status);if(s.global)jQuery.event.trigger("ajaxComplete",[xml,s]);if(s.global&&!--jQuery.active)jQuery.event.trigger("ajaxStop");}return xml;},handleError:function(s,xml,status,e){if(s.error)s.error(xml,status,e);if(s.global)jQuery.event.trigger("ajaxError",[xml,s,e]);},active:0,httpSuccess:function(r){try{return!r.status&&location.protocol=="file:"||(r.status>=200&&r.status<300)||r.status==304||r.status==1223||jQuery.browser.safari&&r.status==undefined;}catch(e){}return false;},httpNotModified:function(xml,url){try{var xmlRes=xml.getResponseHeader("Last-Modified");return xml.status==304||xmlRes==jQuery.lastModified[url]||jQuery.browser.safari&&xml.status==undefined;}catch(e){}return false;},httpData:function(r,type){var ct=r.getResponseHeader("content-type");var xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0;var data=xml?r.responseXML:r.responseText;if(xml&&data.documentElement.tagName=="parsererror")throw"parsererror";if(type=="script")jQuery.globalEval(data);if(type=="json")data=eval("("+data+")");return data;},param:function(a){var s=[];if(a.constructor==Array||a.jquery)jQuery.each(a,function(){s.push(encodeURIComponent(this.name)+"="+encodeURIComponent(this.value));});else -for(var j in a)if(a[j]&&a[j].constructor==Array)jQuery.each(a[j],function(){s.push(encodeURIComponent(j)+"="+encodeURIComponent(this));});else -s.push(encodeURIComponent(j)+"="+encodeURIComponent(a[j]));return s.join("&").replace(/%20/g,"+");}});jQuery.fn.extend({show:function(speed,callback){return speed?this.animate({height:"show",width:"show",opacity:"show"},speed,callback):this.filter(":hidden").each(function(){this.style.display=this.oldblock||"";if(jQuery.css(this,"display")=="none"){var elem=jQuery("<"+this.tagName+" />").appendTo("body");this.style.display=elem.css("display");if(this.style.display=="none")this.style.display="block";elem.remove();}}).end();},hide:function(speed,callback){return speed?this.animate({height:"hide",width:"hide",opacity:"hide"},speed,callback):this.filter(":visible").each(function(){this.oldblock=this.oldblock||jQuery.css(this,"display");this.style.display="none";}).end();},_toggle:jQuery.fn.toggle,toggle:function(fn,fn2){return jQuery.isFunction(fn)&&jQuery.isFunction(fn2)?this._toggle(fn,fn2):fn?this.animate({height:"toggle",width:"toggle",opacity:"toggle"},fn,fn2):this.each(function(){jQuery(this)[jQuery(this).is(":hidden")?"show":"hide"]();});},slideDown:function(speed,callback){return this.animate({height:"show"},speed,callback);},slideUp:function(speed,callback){return this.animate({height:"hide"},speed,callback);},slideToggle:function(speed,callback){return this.animate({height:"toggle"},speed,callback);},fadeIn:function(speed,callback){return this.animate({opacity:"show"},speed,callback);},fadeOut:function(speed,callback){return this.animate({opacity:"hide"},speed,callback);},fadeTo:function(speed,to,callback){return this.animate({opacity:to},speed,callback);},animate:function(prop,speed,easing,callback){var optall=jQuery.speed(speed,easing,callback);return this[optall.queue===false?"each":"queue"](function(){if(this.nodeType!=1)return false;var opt=jQuery.extend({},optall);var hidden=jQuery(this).is(":hidden"),self=this;for(var p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden)return jQuery.isFunction(opt.complete)&&opt.complete.apply(this);if(p=="height"||p=="width"){opt.display=jQuery.css(this,"display");opt.overflow=this.style.overflow;}}if(opt.overflow!=null)this.style.overflow="hidden";opt.curAnim=jQuery.extend({},prop);jQuery.each(prop,function(name,val){var e=new jQuery.fx(self,opt,name);if(/toggle|show|hide/.test(val))e[val=="toggle"?hidden?"show":"hide":val](prop);else{var parts=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),start=e.cur(true)||0;if(parts){var end=parseFloat(parts[2]),unit=parts[3]||"px";if(unit!="px"){self.style[name]=(end||1)+unit;start=((end||1)/e.cur(true))*start;self.style[name]=start+unit;}if(parts[1])end=((parts[1]=="-="?-1:1)*end)+start;e.custom(start,end,unit);}else -e.custom(start,val,"");}});return true;});},queue:function(type,fn){if(jQuery.isFunction(type)||(type&&type.constructor==Array)){fn=type;type="fx";}if(!type||(typeof type=="string"&&!fn))return queue(this[0],type);return this.each(function(){if(fn.constructor==Array)queue(this,type,fn);else{queue(this,type).push(fn);if(queue(this,type).length==1)fn.apply(this);}});},stop:function(clearQueue,gotoEnd){var timers=jQuery.timers;if(clearQueue)this.queue([]);this.each(function(){for(var i=timers.length-1;i>=0;i--)if(timers[i].elem==this){if(gotoEnd)timers[i](true);timers.splice(i,1);}});if(!gotoEnd)this.dequeue();return this;}});var queue=function(elem,type,array){if(!elem)return undefined;type=type||"fx";var q=jQuery.data(elem,type+"queue");if(!q||array)q=jQuery.data(elem,type+"queue",array?jQuery.makeArray(array):[]);return q;};jQuery.fn.dequeue=function(type){type=type||"fx";return this.each(function(){var q=queue(this,type);q.shift();if(q.length)q[0].apply(this);});};jQuery.extend({speed:function(speed,easing,fn){var opt=speed&&speed.constructor==Object?speed:{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&easing.constructor!=Function&&easing};opt.duration=(opt.duration&&opt.duration.constructor==Number?opt.duration:{slow:600,fast:200}[opt.duration])||400;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false)jQuery(this).dequeue();if(jQuery.isFunction(opt.old))opt.old.apply(this);};return opt;},easing:{linear:function(p,n,firstNum,diff){return firstNum+diff*p;},swing:function(p,n,firstNum,diff){return((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum;}},timers:[],timerId:null,fx:function(elem,options,prop){this.options=options;this.elem=elem;this.prop=prop;if(!options.orig)options.orig={};}});jQuery.fx.prototype={update:function(){if(this.options.step)this.options.step.apply(this.elem,[this.now,this]);(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);if(this.prop=="height"||this.prop=="width")this.elem.style.display="block";},cur:function(force){if(this.elem[this.prop]!=null&&this.elem.style[this.prop]==null)return this.elem[this.prop];var r=parseFloat(jQuery.css(this.elem,this.prop,force));return r&&r>-10000?r:parseFloat(jQuery.curCSS(this.elem,this.prop))||0;},custom:function(from,to,unit){this.startTime=(new Date()).getTime();this.start=from;this.end=to;this.unit=unit||this.unit||"px";this.now=this.start;this.pos=this.state=0;this.update();var self=this;function t(gotoEnd){return self.step(gotoEnd);}t.elem=this.elem;jQuery.timers.push(t);if(jQuery.timerId==null){jQuery.timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;ithis.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var done=true;for(var i in this.options.curAnim)if(this.options.curAnim[i]!==true)done=false;if(done){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(jQuery.css(this.elem,"display")=="none")this.elem.style.display="block";}if(this.options.hide)this.elem.style.display="none";if(this.options.hide||this.options.show)for(var p in this.options.curAnim)jQuery.attr(this.elem.style,p,this.options.orig[p]);}if(done&&jQuery.isFunction(this.options.complete))this.options.complete.apply(this.elem);return false;}else{var n=t-this.startTime;this.state=n/this.options.duration;this.pos=jQuery.easing[this.options.easing||(jQuery.easing.swing?"swing":"linear")](this.state,n,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update();}return true;}};jQuery.fx.step={scrollLeft:function(fx){fx.elem.scrollLeft=fx.now;},scrollTop:function(fx){fx.elem.scrollTop=fx.now;},opacity:function(fx){jQuery.attr(fx.elem.style,"opacity",fx.now);},_default:function(fx){fx.elem.style[fx.prop]=fx.now+fx.unit;}};jQuery.fn.offset=function(){var left=0,top=0,elem=this[0],results;if(elem)with(jQuery.browser){var parent=elem.parentNode,offsetChild=elem,offsetParent=elem.offsetParent,doc=elem.ownerDocument,safari2=safari&&parseInt(version)<522&&!/adobeair/i.test(userAgent),fixed=jQuery.css(elem,"position")=="fixed";if(elem.getBoundingClientRect){var box=elem.getBoundingClientRect();add(box.left+Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),box.top+Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));add(-doc.documentElement.clientLeft,-doc.documentElement.clientTop);}else{add(elem.offsetLeft,elem.offsetTop);while(offsetParent){add(offsetParent.offsetLeft,offsetParent.offsetTop);if(mozilla&&!/^t(able|d|h)$/i.test(offsetParent.tagName)||safari&&!safari2)border(offsetParent);if(!fixed&&jQuery.css(offsetParent,"position")=="fixed")fixed=true;offsetChild=/^body$/i.test(offsetParent.tagName)?offsetChild:offsetParent;offsetParent=offsetParent.offsetParent;}while(parent&&parent.tagName&&!/^body|html$/i.test(parent.tagName)){if(!/^inline|table.*$/i.test(jQuery.css(parent,"display")))add(-parent.scrollLeft,-parent.scrollTop);if(mozilla&&jQuery.css(parent,"overflow")!="visible")border(parent);parent=parent.parentNode;}if((safari2&&(fixed||jQuery.css(offsetChild,"position")=="absolute"))||(mozilla&&jQuery.css(offsetChild,"position")!="absolute"))add(-doc.body.offsetLeft,-doc.body.offsetTop);if(fixed)add(Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));}results={top:top,left:left};}function border(elem){add(jQuery.curCSS(elem,"borderLeftWidth",true),jQuery.curCSS(elem,"borderTopWidth",true));}function add(l,t){left+=parseInt(l)||0;top+=parseInt(t)||0;}return results;};})(); \ No newline at end of file diff --git a/public/js/mouseapp_2.js b/public/js/mouseapp_2.js deleted file mode 100755 index 6ea09a4..0000000 --- a/public/js/mouseapp_2.js +++ /dev/null @@ -1,913 +0,0 @@ -// -// Copyright (c) 2008 why the lucky stiff -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, -// and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT -// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -var MouseApp = { - Version: '0.12', - CharCodes: { - 0: ' ', 1: ' ', 9: ' ', - 32: ' ', 34: '"', 38: '&', - 60: '<', 62: '>', 127: '◊', - 0x20AC: '€' - }, - KeyCodes: { - Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 33, PageDown: 34, - End: 35, Home: 36, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 45, - Delete: 46, F1: 112, F2: 113, F3: 114, F4: 115, F5: 116, F6: 117, - F7: 118, F8: 119, F10: 121 - }, - CodeKeys: {}, - Modes: { 1: 'b', 2: 'u', 4: 'i', 8: 'strike' }, - ModeIds: { r: 1, u: 2, i: 4, s: 8 }, - Colors: ['black', 'blue', 'green', - 'cyan', 'red', 'purple', 'brown', - 'gray', 'dark_gray', 'lt_blue', - 'lt_green', 'lt_cyan', 'lt_red', - 'lt_purple', 'yellow', 'white'] -} -//some of these are patently false, because I need to get on a real keyboard-- not a macbook. -if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1){ - MouseApp.KeyCodes = { - Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, - End: 63275, Home: 63273, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 632325, - Delete: 8, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, - F7: 63242, F8: 63243, F10: 63244 - } - -} - -//even though I am tempted to combine chrome and opera into the same if statment, I will refrain for now -// i dont have proper access to a proper keyboard and there might be a single difference between the two -if (navigator.userAgent.indexOf("Opera") > -1){ - MouseApp.KeyCodes = { - Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, - End: 63275, Home: 63273, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 632325, - Delete: 8, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, - F7: 63242, F8: 63243, F10: 63244 - } - -} - -// i am going to comment this out, since this seems un needed. if it past december 15 2009 and this -// is still commented it, please del me -//if ( navigator.appVersion.indexOf('AppleWebKit') > 0 ) { -// MouseApp.KeyCodes = { -// Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, -// End: 63275, Home: 63273, Left: 63234, Up: 63232, Right: 63235, Down: 63233, Insert: 632325, -// Delete: 63272, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, -// F7: 63242, F8: 63243, F10: 63244 -// };// -//} -for ( var k in MouseApp.KeyCodes ) { - MouseApp.CodeKeys[MouseApp.KeyCodes[k]] = k; -} - -MouseApp.isPrintable = function(ch) { - return (ch >= 32); -}; - -MouseApp.Base = function(){}; -MouseApp.Base.prototype = { - setOptions: function(options) { - this.options = { - columns: 72, rows: 24, indent: 2, - title: 'MouseApp', - blinkRate: 500, - ps: '>', - greeting:'%+r Terminal ready. %-r' - } - $.extend(this.options, options || {}); - } -} - -MouseApp.Manager = new Object(); -$.extend(MouseApp.Manager, { - observeTerm: function(term) { - this.activeTerm = term; - if ( this.observingKeyboard ) return; - var mgr = this; - if ( term.input ) { - term.input.keypress(function(e) { mgr.onKeyPress(e) }); - if (!window.opera) term.input.keydown(function(e) { mgr.onKeyDown(e) }); - else window.setInterval(function(){term.input.focus()},1); - } else { - if (!window.opera) $(document).keydown(function(e) { mgr.onKeyDown(e) }); - $(document).keypress(function(e) { mgr.onKeyPress(e) }); - } - this.observingKeyboard = true; - }, - - onKeyDown: function(e) { - e = (e) ? e : ((event) ? event : null); - if ( e && MouseApp.CodeKeys[e.keyCode] ) { - if ( window.event ) { - this.sendKeyPress(e); - } - this.blockEvent(e); - return false; - } - return true; - }, - - onKeyPress: function(e) { - if ( !window.opera && window.event && e.keyCode != 13 && e.keyCode != 8 ) { - e.charCode = e.keyCode; e.keyCode = null; - } - if ( e.keyCode == 191 ) { /* FF 1.0.x sends this upsy quizy -- ignore */ - return; - } - return this.sendKeyPress(e); - }, - - sendKeyPress: function(e) { - var term = MouseApp.Manager.activeTerm; - term.cursorOff(); - b = term.onKeyPress(e); - term.cursorOn(); - return b; - }, - - blockEvent: function (e) { - e.cancelBubble=true; - if (window.event && !window.opera) e.keyCode=0; - if (e.stopPropagation) e.stopPropagation(); - if (e.preventDefault) e.preventDefault(); - } -}); - -/* Basic text window functionality */ -MouseApp.Window = function(element, options) { - this.element = $(element); - this.setOptions(options); - this.initWindow(); -}; - -$.extend(MouseApp.Window.prototype, (new MouseApp.Base()), { - initWindow: function() { - var html = ''; - for ( var i = 0; i < this.options.rows; i++ ) { - html += "
               
              \n"; - } - this.element.html(html); - this.typingOn(); - if (this.options.input) { - this.input = $(this.options.input); - this.input.focus(); - } - MouseApp.Manager.observeTerm(this); - this.clear(); - this.cursorOn(); - this.painting = true; - this.element.css({visibility: 'visible'}); - }, - - text: function() { - var str = ""; - for (var i = 0; i < this.screen.length; i++ ) { - for (var j = 0; j < this.options.columns; j++ ) { - var ch = this.screen[i][j]; - if ( ch[0] != 0 ) { - str += String.fromCharCode(ch[0]); - } - } - } - return str; - }, - - clear: function() { - this.rpos = 0; - this.cpos = 0; - this.screen = []; - this.element.html(''); - this.screen[0] = this.fillRow(this.options.columns, 0); - this.paint(0); - }, - - typingOn: function() { this.typing = true; }, - typingOff: function() { this.typing = false; }, - - cursorOn: function() { - if ( this.blinker ) { - clearInterval( this.blinker ); - } - this.underblink = this.screen[this.rpos][this.cpos][1]; - MouseApp.Manager.activeTerm.blink(); - this.blinker = setInterval(function(){MouseApp.Manager.activeTerm.blink();}, this.options.blinkRate); - this.cursor = true; - }, - - cursorOff: function() { - if ( this.blinker ) { - clearInterval( this.blinker ); - } - if ( this.cursor ) { - this.screen[this.rpos][this.cpos][1] = this.underblink; - this.paint(this.rpos); - this.cursor = false; - } - }, - - blink: function() { - if ( this == MouseApp.Manager.activeTerm ) { - var mode = this.screen[this.rpos][this.cpos][1]; - this.screen[this.rpos][this.cpos][1] = ( mode & 1 ) ? mode & 4094 : mode | 1; - this.paint(this.rpos); - } - }, - - fillRow: function(len, ch, mode) { - ary = [] - for (var i = 0; i < len; i++) { - ary[i] = [ch, mode]; - } - return ary; - }, - - paint: function(start, end) { - if (!this.painting) return; - - if (!end) end = start; - for (var row = start; row <= end && row < this.screen.length; row++) { - var html = ''; - var mode = 0; - var fcolor = 0; - var bcolor = 0; - var spans = 0; - for (var i = 0; i < this.options.columns; i++ ) { - var c = this.screen[row][i][0]; - var m = this.screen[row][i][1] & 15; // 4 mode bits - var f = (this.screen[row][i][1] & (15 << 4)) >> 4; // 4 foreground bits - var b = (this.screen[row][i][1] & (15 << 8)) >> 8; // 4 background bits - if ( m != mode ) { - if ( MouseApp.Modes[mode] ) html += ""; - if ( MouseApp.Modes[m] ) html += "<" + MouseApp.Modes[m] + ">"; - mode = m; - } - if ( ( f != fcolor && f == 0 ) || ( b != bcolor && b == 0 ) ) { - for ( var s = 0; s < spans; s++ ) html += ""; - fcolor = 0; bcolor = 0; - } - if ( f != fcolor ) { - if ( MouseApp.Colors[f] ) { - html += ""; - spans++; - } - fcolor = f; - } - if ( b != bcolor ) { - if ( MouseApp.Colors[b] ) html += ""; - spans++; bcolor = b; - } - html += MouseApp.CharCodes[c] ? MouseApp.CharCodes[c] : String.fromCharCode(c); - } - if ( MouseApp.Modes[mode] ) html += ""; - for ( var s = 0; s < spans; s++ ) html += ""; - var new_id = this.element.attr('id') + '_' + row; - if (!$('#' + new_id).get(0)) { - this.element.append("
               
              "); - this.scrollAllTheWayDown(); - } - $('#' + new_id).html(html); - } - }, - - onAfterKey: function() { - this.scrollAllTheWayDown(); - }, - - highlightLine: function(i) { - if (i >= 0 && i < this.screen.length) - { - $("#" + this.element.attr('id') + "_" + i); - } - }, - - scrollToLine: function(i) { - var p = this.element[0].parentNode; - if ( p.scrollHeight > p.clientHeight ) { - p.scrollTop = (p.scrollHeight - p.clientHeight); - } - }, - - scrollAllTheWayDown: function() { - var p = this.element[0].parentNode; - if ( p.scrollHeight > p.clientHeight ) { - p.scrollTop = (p.scrollHeight - p.clientHeight); - } - }, - - putc: function(ch, mode) { - if ( ch == 13 ) { - return; - } else if ( ch == 10 ) { - this.screen[this.rpos][this.cpos] = [ch, mode]; - this.advanceLine(); - } else { - this.screen[this.rpos][this.cpos] = [ch, mode]; - this.paint(this.rpos); - this.advance(); - } - }, - - zpad: function(n) { - if (n < 10) n = "0" + n; - return n; - }, - - puts: function(str, mode) { - if ( !str ) return; - var p = this.painting; - var r = this.rpos; - this.painting = false; - for ( var i = 0; i < str.length; i++ ) { - this.insertc(str.charCodeAt(i), mode); - } - this.painting = p; - this.paint(r, this.rpos); - }, - - advance: function() { - this.cpos++; - if ( this.cpos >= this.options.columns ) { - this.advanceLine(); - } - }, - - advanceLine: function() { - this.cpos = 0; - this.rpos++; - this.ensureRow(this.rpos); - this.paint(this.rpos, this.screen.length - 1); - }, - - fwdc: function() { - var r = this.rpos; - var c = this.cpos; - if ( c < this.options.columns - 1 ) { - c++; - } else if ( r < this.screen.length - 1 ) { - r++; - c = 0; - } - var ch = (c == 0 ? this.screen[r-1][this.options.columns-1] : this.screen[r][c-1]); - if ( MouseApp.isPrintable(ch[0]) ) { - this.rpos = r; - this.cpos = c; - } - }, - - fwdLine: function() { - if ( this.rpos >= this.screen.length - 1 ) return; - this.rpos++; - while ( this.cpos > 0 && !MouseApp.isPrintable(this.screen[this.rpos][this.cpos - 1][0]) ) { - this.cpos--; - } - }, - - backc: function() { - var r = this.rpos; - var c = this.cpos; - if ( c > 0 ) { - c--; - } else if ( r > 0 ) { - c = this.options.columns - 1; - r--; - } - if ( MouseApp.isPrintable(this.screen[r][c][0]) ) { - this.rpos = r; - this.cpos = c; - return true; - } - return false; - }, - - getTypingStart: function() { - var c = this.cpos; - if ( !MouseApp.isPrintable(this.screen[this.rpos][c][0]) ) { - c--; - } - var pos = null; - for ( var r = this.rpos; r >= 0; r-- ) { - while ( c >= 0 ) { - if ( !MouseApp.isPrintable(this.screen[r][c][0]) ) { - return pos; - } - pos = [r, c]; - c--; - } - c = this.options.columns - 1; - } - }, - - getTypingEnd: function(mod) { - var c = this.cpos; - if ( !MouseApp.isPrintable(this.screen[this.rpos][c][0]) ) { - c--; - } - var pos = null; - for ( var r = this.rpos; r < this.screen.length; r++ ) { - while ( c < this.options.columns ) { - if ( !this.screen[r] || !this.screen[r][c] || !MouseApp.isPrintable(this.screen[r][c][0]) ) { - if (!mod) return pos; - mod--; - } - pos = [r, c]; - c++; - } - c = 0; - } - }, - - getTypingAt: function(start, end) { - var r = start[0]; - var c = start[1]; - var str = ''; - while ( r < end[0] || c <= end[1] ) { - if ( c < this.options.columns ) { - str += String.fromCharCode(this.screen[r][c][0]); - c++; - } else { - c = 0; - r++; - } - } - return str; - }, - - ensureRow: function(r) { - if (!this.screen[r]) { - this.screen[r] = this.fillRow(this.options.columns, 0); - } - }, - - insertc: function(ch, mode) { - var r = this.rpos; var c = this.cpos; - var end = this.getTypingEnd(+1); - if (end) { - var thisc = null; - var lastc = this.screen[this.rpos][this.cpos]; - while ( r < end[0] || c <= end[1] ) { - if ( c < this.options.columns ) { - thisc = this.screen[r][c]; - this.screen[r][c] = lastc; - lastc = thisc; - c++; - } else { - c = 0; - r++; - this.ensureRow(r); - } - } - this.paint(this.rpos, end[0]); - } - this.putc(ch, mode); - }, - - delc: function() { - /* end of line */ - if ( MouseApp.isPrintable(this.screen[this.rpos][this.cpos][0]) ) { - var end = this.getTypingEnd(); - var thisc = null; - var lastc = [0, 0]; - while ( this.rpos < end[0] || this.cpos <= end[1] ) { - if ( end[1] >= 0 ) { - thisc = this.screen[end[0]][end[1]]; - this.screen[end[0]][end[1]] = lastc; - lastc = thisc; - end[1]--; - } else { - end[1] = this.options.columns - 1; - this.paint(end[0]); - end[0]--; - } - } - } - }, - - backspace: function() { - /* end of line */ - if ( !MouseApp.isPrintable(this.screen[this.rpos][this.cpos][0]) ) { - this.backc(); - this.screen[this.rpos][this.cpos] = [0, 0]; - } else { - if ( this.backc() ) this.delc(); - } - }, - - backLine: function() { - if ( this.rpos < 1 ) return; - this.rpos--; - while ( this.cpos > 0 && !MouseApp.isPrintable(this.screen[this.rpos][this.cpos - 1][0]) ) { - this.cpos--; - } - }, - - onKeyPress: function(e) { - var ch = e.keyCode; - var key_name = MouseApp.CodeKeys[ch]; - if (window.opera && !e.altKey && e.keyCode != 13 && e.keyCode != 8) key_name = null; - ch = (e.which || e.charCode || e.keyCode); - if (e.which) ch = e.which; - if (!key_name) { key_name = String.fromCharCode(ch); } - if (e.ctrlKey) { key_name = 'Ctrl' + key_name; } - - // alert([e.keyCode, e.which, key_name, this['onKey' + key_name]]); - if (this.typing && this.onAnyKey) this.onAnyKey(key_name); - if (key_name && this['onKey' + key_name]) { - if (this.typing) this['onKey' + key_name](); - MouseApp.Manager.blockEvent(e); - if (this.typing && this.onAfterKey) this.onAfterKey(key_name, true); - return false; - } - if (!e.ctrlKey) { - if (MouseApp.isPrintable(ch)) { - if (this.typing) this.insertc(ch, 0); - MouseApp.Manager.blockEvent(e); - if (this.typing && this.onAfterKey) this.onAfterKey(key_name, true); - return false; - } - } - if (this.typing && this.onAfterKey) this.onAfterKey(key_name, false); - return true; - }, - onKeyHome: function() { - var s = this.getTypingStart(); - this.rpos = s[0]; this.cpos = s[1]; - }, - onKeyEnd: function() { - var e = this.getTypingEnd(+1); - this.rpos = e[0]; this.cpos = e[1]; - }, - onKeyInsert: function() { }, - onKeyDelete: function() { this.delc(); }, - onKeyUp: function() { this.backLine(); }, - onKeyLeft: function() { this.backc(); }, - onKeyRight: function() { this.fwdc(); }, - onKeyDown: function() { this.fwdLine(); }, - onKeyBackspace: function() { this.backspace(); }, - onKeyEnter: function() { this.insertc(10, 0); }, - onKeyTab: function() { - this.insertc(32, 0); - while (this.cpos % this.options.indent != 0) this.insertc(32, 0); - } -}); - -/* Terminal running moush */ -MouseApp.Terminal = function(element, options) { - this.element = $(element); - this.setOptions(options); - this.initWindow(); - this.setup(); -}; - -$.extend(MouseApp.Terminal.prototype, MouseApp.Window.prototype, { - setup: function() { - this.history = []; - this.backupNum = this.historyNum = this.commandNum = 0; - if (this.onStart) { - this.onStart(); - } else { - this.write(this.options.greeting + "\n", true); - this.prompt(); - } - }, - - prompt: function(ps, pt) { - if (!ps) { - ps = this.options.ps; pt = true; - } - this.write(ps, pt); - this.putc(1, 0); - this.typingOn(); - }, - - getCommand: function() { - var s = this.getTypingStart(); - var e = this.getTypingEnd(); - if (!s || !e) return; - return this.getTypingAt(s, e); - }, - - clearCommand: function() { - var s = this.getTypingStart(); - var e = this.getTypingEnd(); - if (!s || !e) return; - var r = s[0]; - var c = s[1]; - this.rpos = r; this.cpos = c; - while ( r < e[0] || c <= e[1] ) { - if ( c < this.options.columns ) { - this.screen[r][c] = [0, 0]; - c++; - } else { - c = 0; - this.paint(r); - r++; - } - } - this.paint(r); - }, - - write: function(str, pcodes) { - var p = this.painting; - var r = this.rpos; - this.painting = false; - var mode = 0; - var today = new Date(); - for ( var i = 0; i < str.length; i++ ) { - if ( str.substr(i,1) == "\n" ) { - this.advanceLine(); - continue; - } else if ( str.substr(i,1) == "\033" ) { - if ( str.substr(i+1,2) == "[m" ) { - mode = 0; - i += 2; - continue; - } - if ( str.substr(i+1,5) == "[0;0m" ) { - mode = 0; - i += 5; - continue; - } - var colors = str.substr(i+1,7).match(/^\[(\d);(\d+)m/); - if ( colors ) { - var colCode = parseInt( colors[2] ); - var color = colCode % 10; - if ( colors[1] == '1' ) { - color += 8; - } - if ( colCode / 10 == 4 ) { - color = color << 4; - } - mode = (mode & 15) + color << 4; - i += colors[0].length; - continue; - } - } else if ( str.substr(i,1) == '%' && pcodes ) { - var s2 = str.substr(i,2); - switch ( s2 ) { - case '%h': - this.puts(this.options.host, mode); - i++; - continue; - case '%l': - this.puts(this.options.name, mode); - i++; - continue; - case '%n': - this.advanceLine(); - i++; - continue; - case '%s': - this.puts("moush", mode); - i++; - continue; - case '%t': - this.puts(this.zpad(today.getHours()) + ":" + this.zpad(today.getMinutes()) + ":" + - this.zpad(today.getSeconds()), mode); - i++; - continue; - case '%u': - this.puts(this.options.user, mode); - i++; - continue; - case '%v': - this.puts(MouseApp.Version, mode); - i++; - continue; - case '%!': - this.puts(this.historyNum.toString(), mode); - i++; - continue; - case '%#': - this.puts(this.commandNum.toString(), mode); - i++; - continue; - case '%+': - var kind = str.substr(i+2, 1); - if ( MouseApp.ModeIds[kind] ) { - mode = mode | MouseApp.ModeIds[kind]; - i += 2; - continue; - } - break; - case '%-': - var kind = str.substr(i+2, 1); - if ( MouseApp.ModeIds[kind] ) { - mode = mode & ( 4095 - MouseApp.ModeIds[kind] ); - i += 2; - continue; - } - break; - } - } - this.putc(str.charCodeAt(i), mode); - } - this.painting = p; - this.paint(r, this.rpos); - }, - - onKeyUp: function() { - if ( this.backupNum == 0 ) return; - if ( this.backupNum == this.historyNum ) { - this.history[this.historyNum] = this.getCommand(); - } - this.clearCommand(); - this.backupNum--; - this.puts(this.history[this.backupNum]); - }, - onKeyDown: function() { - if ( this.backupNum >= this.historyNum ) return; - this.clearCommand(); - this.backupNum++; - this.puts(this.history[this.backupNum]); - }, - onKeyEnter: function() { - var cmd = this.getCommand(); - if (cmd) { - this.history[this.historyNum] = cmd; - this.backupNum = ++this.historyNum; - } - this.commandNum++; - this.advanceLine(); - if (cmd) { - var str = this.onCommand(cmd); - if (str) { - if ( str.substr(str.length - 1, 1) != "\n" ) { - str += "\n"; - } - this.write(str); - } - } - this.prompt(); - }, - onCommand: function(line) { - // this.puts("Echoing: " + line + "\n"); - if ( line == "clear" ) { - this.clear(); - } else { - return "\033[1;37m\033[0;44mYou typed:\033[m " + line; - } - } -}); - -/* Notepad sort of editor */ -MouseApp.Notepad = function(element, options) { - this.element = $(element); - this.setOptions(options); - this.initWindow(); - this.history = []; - this.lineno = 0; -}; - -$.extend(MouseApp.Notepad.prototype, MouseApp.Window.prototype, { - csave: function() { - if ( this.cpos_save ) { - this.cpos = this.cpos_save; - } else { - this.cpos_save = this.cpos; - } - }, - onKeyUp: function() { if ( this.rpos < 1 ) { return; } this.csave(); this.backLine(); }, - onKeyDown: function() { if ( this.rpos < this.screen.length - 1 ) { this.csave(); this.fwdLine(); } }, - onAfterKey: function(key, st) { - if ( st && !(key == 'Up' || key == 'Down') ) { - this.cpos_save = null; - } - }, - insertc: function(ch, mode) { - if (ch == 10) { - this.element.append("
               
              "); - this.screen.splice(this.rpos + 1, 0, this.fillRow(this.options.columns, 0)); - var c = this.cpos; var c2 = 0; - while (c < this.options.columns) - { - if (this.screen[this.rpos][c] == 0) break; - this.screen[this.rpos + 1][c2] = this.screen[this.rpos][c]; - this.screen[this.rpos][c] = [0, 0]; - c++; c2++; - } - this.paint(this.rpos); - if (MouseApp.isPrintable(this.screen[this.rpos][c])) - { - var r = this.rpos; var c = this.cpos; - this.rpos += 1; this.cpos = c2; - this.delc(); - this.rpos = r; this.cpos = c; - } - this.putc(ch, mode); - if (this.rpos == this.screen.length - 1) - this.scrollAllTheWayDown(); - } else { - var c = this.cpos + 1; - var lastc = this.screen[this.rpos][this.cpos]; - this.putc(ch, mode); - for ( var r = this.rpos; r < this.screen.length; r++ ) { - while (c < this.options.columns) - { - var tmpc = this.screen[r][c]; - if (lastc[0] == 0) - break; - this.screen[r][c] = lastc; - lastc = tmpc; - c++; - } - if (c < this.options.columns) { - break; - } - c = 0; - } - } - }, - - backc: function() { - var r = this.rpos; - var c = this.cpos - 1; - for ( var r = this.rpos; r >= 0; r-- ) { - while ( c >= 0 ) { - this.rpos = r; - this.cpos = c; - if ( this.screen[r][c][0] != 0 ) { - this.paint(r); - return true; - } - this.screen[r][c] = [0, 0]; - c--; - } - c = this.options.columns - 1; - } - return false; - }, - delc: function() { - var c = this.cpos + 1; - for ( var r = this.rpos; r < this.screen.length; r++ ) { - while ( c < this.options.columns ) { - if ( this.screen[r][c][0] != 0 ) { - break; - } - c++; - } - if ( c < this.options.columns ) break; - c = 0; - } - - if (r >= this.screen.length) return; - - var r2 = this.rpos; - var c2 = this.cpos; - for ( var r2 = this.rpos; r2 < this.screen.length; r2++ ) { - while (c2 < this.options.columns) - { - if (this.screen[r][c][0] == 0) - break; - this.screen[r2][c2] = this.screen[r][c]; - c2++; - c++; - if (c >= this.options.columns) { - r++; - if (r >= this.options.rows) break; - c = 0; - } - } - if (c2 < this.options.columns) { - while (c2 < this.options.columns) { - this.screen[r2][c2] = [0, 0]; - c2++; - } - break; - } - c2 = 0; - } - - if (r != r2 && r < this.screen.length) - { - this.screen.splice(r, 1); - $("#" + this.element.attr('id') + "_" + this.screen.length).remove(); - } - this.paint(this.rpos, this.screen.length); - }, - onKeyBackspace: function() { - if (this.backc()) this.delc(); - } - -}); diff --git a/public/js/mouseirb_2.js b/public/js/mouseirb_2.js deleted file mode 100755 index 0fa5f12..0000000 --- a/public/js/mouseirb_2.js +++ /dev/null @@ -1,179 +0,0 @@ -// -// Copyright (c) 2008 why the lucky stiff -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, -// and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT -// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -/* Irb running moush */ -MouseApp.Irb = function(element, options) { - this.element = $(element); - this.setOptions(options); - this.showHelp = this.options.showHelp; - if ( this.options.showChapter ) { - this.showChapter = this.options.showChapter; - } - if ( this.options.init ) { - this.init = this.options.init; - } - this.initWindow(); - this.setup(); - this.helpPage = null; - this.irbInit = false; -}; - -$.extend(MouseApp.Irb.prototype, MouseApp.Terminal.prototype, { - cmdToQuery: function(cmd) { - return "cmd=" + escape(cmd.replace(/</g, '<').replace(/>/g, '>'). - replace(/&/g, '&').replace(/\r?\n/g, "\n")).replace(/\+/g, "%2B"); - }, - - fireOffCmd: function(cmd, func) { - var irb = this; - if (!this.irbInit) - { - $.ajax({url: this.options.irbUrl + "?" + this.cmdToQuery("!INIT!IRB!"), type: "GET", - complete: (function(r) { irb.irbInit = true; irb.fireOffCmd(cmd, func); })}); - } - else - { - $.ajax({url: this.options.irbUrl + "?" + this.cmdToQuery(cmd), type: "GET", - complete: func}); - } - }, - - reply: function(str) { - var raw = str.replace(/\033\[(\d);(\d+)m/g, ''); - this.checkAnswer(raw); - if (!str.match(/^(\.\.)+$/)) { - if ( str[str.length - 1] != "\n" ) { - str += "\n"; - } - js_payload = /\033\[1;JSm(.*)\033\[m/; - js_in = str.match(js_payload); - if (js_in) { - try { - js_in = eval(js_in[1]); - } catch (e) {} - str = str.replace(js_payload, ''); - } - var pr_re = new RegExp("(^|\\n)=>"); - if ( str.match( pr_re ) ) { - str = str.replace(new RegExp("(^|\\n)=>"), "$1\033[1;34m=>\033[m"); - } else { - str = str.replace(new RegExp("(^|\\n)= (.+?) ="), "$1\033[1;33m$2\033[m"); - } - this.write(str); - this.prompt(); - } else { - this.prompt("\033[1;32m" + ".." + "\033[m", true); - this.puts(str.replace(/\./g, ' '), 0); - } - }, - - setHelpPage: function(n, page) { - if (this.helpPage) - $(this.helpPage.ele).hide('fast'); - this.helpPage = {index: n, ele: page}; - match = this.scanHelpPageFor('load'); - if (match != -1) - { - this.fireOffCmd(match, (function(r) { - $(page).show('fast'); - })); - } - else - { - $(page).show('fast'); - } - }, - - scanHelpPageFor: function(eleClass) { - match = $("div." + eleClass, this.helpPage.ele); - if ( match[0] ) return match[0].innerHTML; - else return -1; - }, - - checkAnswer: function(str) { - if ( this.helpPage ) { - match = this.scanHelpPageFor('answer'); - if ( match != -1 ) { - if ( str.match( new RegExp('^\s*=> ' + match + '\s*$', 'm') ) ) { - this.showHelp(this.helpPage.index + 1); - } - } else { - match = this.scanHelpPageFor('stdout'); - if ( match != -1 ) { - if ( match == '' ) { - if ( str == '' || str == null ) this.showHelp(this.helpPage.index + 1); - } else if ( str.match( new RegExp('^\s*' + match + '$', 'm') ) ) { - this.showHelp(this.helpPage.index + 1); - } - } - } - } - }, - - onKeyCtrld: function() { - this.clearCommand(); - this.puts("reset"); - this.onKeyEnter(); - }, - - onKeyEnter: function() { - this.typingOff(); - var cmd = this.getCommand(); - if (cmd) { - this.history[this.historyNum] = cmd; - this.backupNum = ++this.historyNum; - } - this.commandNum++; - this.advanceLine(); - if (cmd) { - if ( cmd == "clear" ) { - this.clear(); - this.prompt(); - } else if ( cmd.match(/^(back)$/) ) { - if (this.helpPage && this.helpPage.index >= 1) { - this.showHelp(this.helpPage.index - 1); - } - this.prompt(); - } else if ( cmd.match(/^(next)$/) ) { - if (this.helpPage) { - this.showHelp(this.helpPage.index + 1); - } - this.prompt(); - } else if ( cmd.match(/^(help|wtf\?*)$/) ) { - this.showHelp(1); - this.prompt(); - } else if ( regs = cmd.match(/^(help|wtf\?*)\s+#?(\d+)\s*$/) ) { - this.showChapter(parseInt(regs[2])); - this.prompt(); - } else { - var term = this; - this.fireOffCmd(cmd, (function(r) { term.reply(r.responseText ? r.responseText : ''); })); - } - } else { - this.prompt(); - } - } -}); - diff --git a/public/keypress_test.html b/public/keypress_test.html deleted file mode 100644 index 7297c4d..0000000 --- a/public/keypress_test.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - -

              Press a key, the details will be displayed below

              -
              - - - diff --git a/public/moods/index.html b/public/moods/index.html deleted file mode 100755 index e933af9..0000000 --- a/public/moods/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -

              you shouldn't be here.. kicking you out!

              - - diff --git a/public/moods/sick.gif b/public/moods/sick.gif deleted file mode 100755 index 217a67cbae60740fdc90b92e06b977cf7fc56699..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 94 zcmZ?wbhEHb|6B#{self.text}" - end - - end - - class Link - attr_accessor :text, :target - def initialize(text, target) - self.text, self.target = text, target - end - def generate_html - "#{text}" - end - - - end - - class List - attr_accessor :elements - def initialize(elements) - self.elements = elements - end - - def generate_html - items = elements.map do |elem| - text = elem.instance_of?(Paragraph) ? elem.text : elem.generate_html - "
            2. #{text}
            3. " - end.join(" ") - - "
                #{items}
              " - end - end - - - class Paragraph - attr_accessor :text - def initialize(text) - self.text = text - end - - def generate_html - "

              #{self.text}

              " - end - end - - - class ComplexPopup - attr_reader :elements - def initialize - @elements = [] - end - - (1..6).each do |n| - define_method "h#{n}".to_sym do |text| - @elements << Header.new(n, text) - end - end - - - # def h1 text - # @elements << Header.new(1, text) - # end - - def link(text, target) - @elements << Link.new(text, target) - end - - def p(text) - @elements << Paragraph.new(text) - end - - def list(&block) - lst = ComplexPopup.new - lst.instance_eval(&block) - @elements << List.new(lst.elements) - end - - def generate_html() - @elements.map(&:generate_html).join(" ") - end - - - - end - - - def self.make(&block) - result = ComplexPopup.new - result.instance_eval(&block) - - html = result.generate_html.gsub('\\', '\\\\').gsub('"', '\"') - command = "window.irb.options.popup_make(\"#{html}\")" - TryRuby::Output.javascript command - end - -end diff --git a/public/setup.rb b/public/setup.rb deleted file mode 100644 index 10c1a39..0000000 --- a/public/setup.rb +++ /dev/null @@ -1,67 +0,0 @@ -module TryRuby -SetupCode = < p:first-child{ - margin-top:0; -} -#facebox .content > p:last-child{ - margin-bottom:0; -} - -#facebox .close{ - position:absolute; - top:5px; - right:5px; - padding:2px; - background:#fff; -} -#facebox .close img{ - opacity:0.3; -} -#facebox .close:hover img{ - opacity:1.0; -} - -#facebox .loading { - text-align: center; -} - -#facebox .image { - text-align: center; -} - -#facebox img { - border: 0; - margin: 0; -} - -#facebox_overlay { - position: fixed; - top: 0px; - left: 0px; - height:100%; - width:100%; -} - -.facebox_hide { - z-index:-100; -} - -.facebox_overlayBG { - background-color: #000; - z-index: 99; -} -.facebox-footnote{ - margin-top:40px; -} \ No newline at end of file diff --git a/public/stylesheets/reset.css b/public/stylesheets/reset.css deleted file mode 100644 index d709810..0000000 --- a/public/stylesheets/reset.css +++ /dev/null @@ -1,46 +0,0 @@ -html, body, div, span, applet, object, iframe, -h1, h2, h3, h4, h5, h6, p, blockquote, pre, -a, abbr, acronym, address, big, cite, code, -del, dfn, em, font, img, ins, kbd, q, s, samp, -small, strike, strong, sub, sup, tt, var, -dl, dt, dd, ol, ul, li, -fieldset, form, label, legend, -table, caption, tbody, tfoot, thead, tr, th, td { - margin: 0; - padding: 0; - border: 0; - outline: 0; - font-weight: inherit; - font-style: inherit; - font-size: 100%; - font-family: inherit; - vertical-align: baseline; -} -/* remember to define focus styles! */ -:focus { - outline: 0; -} -body { - line-height: 1; - color: black; - background: white; -} -ol, ul { - list-style: none; -} -/* tables still need 'cellspacing="0"' in the markup */ -table { - border-collapse: separate; - border-spacing: 0; -} -caption, th, td { - text-align: left; - font-weight: normal; -} -blockquote:before, blockquote:after, -q:before, q:after { - content: ""; -} -blockquote, q { - quotes: "" ""; -} diff --git a/public/stylesheets/scaffold.css b/public/stylesheets/scaffold.css deleted file mode 100644 index 1ae7000..0000000 --- a/public/stylesheets/scaffold.css +++ /dev/null @@ -1,56 +0,0 @@ -body { background-color: #fff; color: #333; } - -body, p, ol, ul, td { - font-family: verdana, arial, helvetica, sans-serif; - font-size: 13px; - line-height: 18px; -} - -pre { - background-color: #eee; - padding: 10px; - font-size: 11px; -} - -a { color: #000; } -a:visited { color: #666; } -a:hover { color: #fff; background-color:#000; } - -div.field, div.actions { - margin-bottom: 10px; -} - -#notice { - color: green; -} - -.field_with_errors { - padding: 2px; - background-color: red; - display: table; -} - -#error_explanation { - width: 450px; - border: 2px solid red; - padding: 7px; - padding-bottom: 0; - margin-bottom: 20px; - background-color: #f0f0f0; -} - -#error_explanation h2 { - text-align: left; - font-weight: bold; - padding: 5px 5px 5px 15px; - font-size: 12px; - margin: -7px; - margin-bottom: 0px; - background-color: #c00; - color: #fff; -} - -#error_explanation ul li { - font-size: 12px; - list-style: square; -} diff --git a/public/stylesheets/site.css b/public/stylesheets/site.css deleted file mode 100755 index 62b1526..0000000 --- a/public/stylesheets/site.css +++ /dev/null @@ -1,378 +0,0 @@ -body { - font-family: verdana, arial, sans-serif; - font-size: 14px; - text-align: center; -} -h1, h2, h3, h4 { - font-family: georgia, serif; - margin: 10px 45px; padding: 0; -} -h1 { - color: #333; - font-size: 48px; - font-weight: normal; - margin: 10px 0px; -} -h3 { - color: white; - font-size: 21px; - font-weight: normal; -} -a,a:link,a:visited { - text-decoration: none; - color: #57ad11; -} -a:hover { - text-decoration: underline; - color: #57ad11; -} -a:active { - text-decoration: underline; - color: #dddddd; -} -input.keyboard-selector-input { - position: fixed; - top: 0; - _position: absolute; - _top: expression(eval(document.body.scrollTop)); - left: -300px; -} -.container { - width: 678px; - margin: 0 auto; - text-align: left; -} -.content { - width: 712px; - background: url(/images/tile.png) repeat-y; -} -#lilBrowser { - position: absolute; - background-color: white; - top: -540px; - left: -440px; - width: 510px; - height: 430px; - padding: 5px; - border: solid 1px #444; - z-index: 100; -} -h3#lbTitle { - color: #444; - font-family: verdana, arial, sans-serif; - font-size: small; - float:left; - line-height: 90%; - margin: 0; padding: 3px; -} -p#lbClose { - font-size: small; - float: right; - margin: 0; padding: 3px; -} -p#lbClose a { - display: inline; -} -.shellwin { - width: 712px; - padding-left: 12px; - background: url(/images/background.png) no-repeat; -} - -/* tutorial panes */ -.stretcher { - color: #f1f1ff; - display: none; - margin: 0; - padding: 0; - padding-left: 12px; - background: url(/images/tile.png) repeat-y; -} -.stretcher a, .stretcher a:link, .stretcher a:visited, .stretcher a:active { - text-decoration: none; - color: #a7ed91; -} -.stretcher a:hover { - text-decoration: underline; - color: #b7fd91; -} -.stretcher p { - margin: 10px 16px; -} -.stretcher dl, .stretcher ul { - background-color: white; - color: #333; - padding: 4px 8px; - font-size: 12px; - margin-left: 16px; - list-style: none; -} -.stretcher li { - margin: 6px; -} -.stretcher p code { - background-color: #874a20; - color: #fedeec; - padding: 1px 4px; -} -.stretcher p code.cmd { - background-color: #eeeeec; - color: #204a87; -} -.stretcher dt { - font-weight: bold; -} - -.chapmark { - padding: 6px 0; - margin-left: 12px; - margin-right: 22px; - color: #553; - background: #efefe1; -} -.chapmark h3 { - color: #335; -} -.chapmark a, .chapmark a:link, .chapmark a:visited, .chapmark a:active { - text-decoration: none; - color: #372d61; -} -.chapmark a:hover { - text-decoration: underline; - color: #477d51; -} -.note { color: #ddc; text-align: center; font-size: xx-small; } -ul li strong { color: #286; border-bottom: solid 2px #cca; } -ul li code { background-color: #f1f1f1; padding: 1px 3px; border-bottom: solid 2px #ddd; } -ul li code.faded { color: #899; } -code strong { background-color: #dcffb9; padding: 1px 3px; } -ul.commands li strong { display: block; float: left; width: 60px; border: none; } - -/* irb terminal */ -.terminal { - background-color: #ffffff; - border: solid 1px #204a87; - width: 678px; - height: 240px; - overflow: auto; -} -.console { - padding: 4px; margin-left: -50px; - font-family: "Andale Mono", courier, fixed, monospace; - font-size: 14px; - line-height: 16px; - color: #204a87; - text-align: left; - width: 664px; - height:220px; -} - -.console div b { - background-color: #874a20; - color: #fedeac; -} -div.answer, div.stdout, div.no_answer, div.load { - display: none; -} - -/* terminal escape colors */ -span.fore_black { color: #2e3436; } -span.fore_dark_gray { color: #888a85; } -span.fore_gray { color: #babdb6; } -span.fore_white { color: #eeeeec; } -span.fore_blue { color: #204a87; } -span.fore_lt_blue { color: #729fcf; } -span.fore_green { color: #788600; font-weight: bold; } -span.fore_lt_green { color: #cbe134; } -span.fore_cyan { color: #c4a000; } /* using cyan for yellows */ -span.fore_lt_cyan { color: #fc994f; } -span.fore_red { color: #a40000; } -span.fore_lt_red { color: #ef2929; font-weight: bold; } -span.fore_purple { color: #5c3566; } -span.fore_lt_purple { color: #ad7fa8; } -span.fore_brown { color: #8f5972; } -span.fore_lt_brown { color: #b9b9de; } -span.back_black { background-color: #2e3436; } -span.back_dark_gray { background-color: #888a85; } -span.back_gray { background-color: #babdb6; } -span.back_white { background-color: #eeeeec; } -span.back_blue { background-color: #204a87; } -span.back_lt_blue { background-color: #729fcf; } -span.back_green { background-color: #788600; } -span.back_lt_green { background-color: #cbe134; } -span.back_cyan { background-color: #c4a000; } /* using cyan for yellows */ -span.back_lt_cyan { background-color: #fce94f; } -span.back_red { background-color: #a40000; } -span.back_lt_red { background-color: #ef2929; } -span.back_purple { background-color: #5c3566; } -span.back_lt_purple { background-color: #ad7fa8; } -span.back_brown { background-color: #8f5902; } -span.back_lt_brown { background-color: #b9b96e; } - -/** no ways***/ - -div.main-wrapper-bottom { - height:4px;background-position: 0px -80px; background-repeat: no-repeat; - font-size:0 /* IE6, go figure */ -} -div.main-wrapper-borders { - background-position: -1731px 0; padding:15px; - background-repeat:repeat-y; -} -div.console-wrapper { - margin:0px auto ;width:566px; - cursor:text; - font-family:monospace; -} -div.console-wrapper-top { - height:3px;background-position: -50px -48px; background-repeat: no-repeat; - font-size:0 /* IE6, go figure */ -} -div.console-wrapper-bottom { - height:3px;background-position: -50px -51px; background-repeat: no-repeat; - font-size:0 /* IE6, go figure */ -} -div.console-wrapper-borders { - background-position: 0px 0px; padding:1px; - background-repeat:repeat-y; -} -div.guide-wrapper { - color:#fff; width:566px;margin-left:2px -} -div.guide-wrapper-top { - height:4px;background-position: 0 -65px; - font-size:0 /* IE6, go figure */ -} -div.guide-wrapper-bottom { - height:4px;background-position: 0 -70px; - font-size:0 /* IE6, go figure */ -} -div.guide-wrapper-borders { - background-position: -1166px 0px;padding:15px; - background-repeat:repeat-y; -} - -div.footer-wrapper-borders { - background-position: -566px 0px; padding:10px; - background-repeat:repeat-y; - font-size:12px -} -h1.main-header { - text-indent:-9999px; background-position: -49px 0px; - background-repeat: no-repeat; - width:318px; height:48px; margin-bottom:20px; - float:left -} - -div.footer { - line-height: 1.3em; -} - div.console div.jquery-console-inner -{ height:100%; overflow:auto; background:white} -div.console div.jquery-console-prompt-box -{ color:#437375; font-family:monospace; margin-top:0.5em; } -div.console div.jquery-console-prompt-box .prompt-done -{ cursor: pointer } -div.console div.jquery-console-prompt-box .prompt-done:hover -{ background:#453D5B; color: white; } -div.console div.jquery-console-focus span.jquery-console-cursor -{ background:#666; color:#fff; } -div.console div.jquery-console-message-error { - color:#ef0505; font-family:sans-serif; font-weight:bold; - padding-top:0.25em -} -div.console div.jquery-console-message-value -{ color:#000; font-family:monospace;padding-top:0.25em; font-weight: bold; } -div.console div.jquery-console-message-type -{ color:#382567; font-family:monospace;padding-left:0em;padding-top:0.25em; font-size:.9em } -div.console span.jquery-console-prompt-label { font-weight:bold } -div.console div.jquery-console-welcome { font-family:"DejaVu Sans",sans-serif; } - -div.share-wrapper { font-size:12px;padding:10px 0em 0em 10px } -div.share-wrapper strong { font-weight: bold } - -.clearfix:after { content:"."; display:block; height:0; clear:both; visibility:hidden } -div.menu { - float:right; - margin-right:2px; - margin-top:40px; - margin-bottom:5px -} -a.reset-btn { - float:left; - display:block; - width:59px; - height:24px; - background-position: -427px -18px; background-repeat: no-repeat; -} -a.reset-btn span { display:none } - -div.clear { clear:both } - - -div.console-wrapper .notice { - position:absolute; - bottom:0;right:0; - margin:1px; - background:#eee; - color:black; - padding:10px; - font-size:12px; - font-family:sans-serif; - font-weight:bold; -} -p.ajax-loader { background:url(../images/ajax-loader.gif); width:16px; height:16px;text-indent:-9999px } - -.notice a { padding:3px;background:#333;color:white} -.notice .action { text-align: right } - -/* Support Try Ruby! */ - - -a.trigger{ -position: absolute; -text-decoration: none; -top: 80px; right: 0; -font-size: 14px; -letter-spacing:-1px; -font-family: verdana, helvetica, arial, sans-serif; -color:#fff; -padding: 10px 10px 10px 10px; -font-weight: 500; -background:#333333 url(images/plus.png) 15% 55% no-repeat; -border:1px solid #444444; --moz-border-radius-topleft: 20px; --webkit-border-top-left-radius: 20px; --moz-border-radius-bottomleft: 20px; --webkit-border-bottom-left-radius: 20px; --moz-border-radius-bottomright: 0px; --webkit-border-bottom-right-radius: 0px; -display: block; -} - -a.trigger:hover{ -position: absolute; -text-decoration: none; -top: 80px; right: 0; -font-size: 14px; -letter-spacing:-1px; -font-family: verdana, helvetica, arial, sans-serif; -color:#fff; -padding: 10px 10px 10px 10px; -font-weight: 500; -background: green; -border:1px solid #444444; --moz-border-radius-topleft: 20px; --webkit-border-top-left-radius: 20px; --moz-border-radius-bottomleft: 20px; --webkit-border-bottom-left-radius: 20px; --moz-border-radius-bottomright: 0px; --webkit-border-bottom-right-radius: 0px; -display: block; -} - -a.active.trigger { -background:#222222 url(images/minus.png) 15% 55% no-repeat; -} - - \ No newline at end of file diff --git a/public/submodules/fakefs b/public/submodules/fakefs deleted file mode 160000 index c6168d4..0000000 --- a/public/submodules/fakefs +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c6168d41363e4c60ddf9d4cb784e6acf79ea581d diff --git a/public/test.rb b/public/test.rb deleted file mode 100755 index 8810c18..0000000 --- a/public/test.rb +++ /dev/null @@ -1,633 +0,0 @@ -#!/usr/bin/env ruby -require 'test/unit' -require 'rexml/document' -require 'hpricot' -load 'tryruby_runner.rb' - -class Integer - def weeks - self * 7*24*60*60 - end -end - - -def run_script(session,line) - session << line -end - -class TryRubyTestSession < TryRubyBaseSession - def initialize - reset - @current_includes = [] - end - - attr_accessor :start_time, :current_statement - attr_accessor :nesting_level, :past_commands, :current_includes -end - -$session = nil - -# This tests the TryRubyBaseSession#calculate_nesting_level function -class NestingLevelTest < Test::Unit::TestCase - def test_finished_statement_should_return_0 - t = TryRubyBaseSession.new - assert_equal(0, t.calculate_nesting_level("42")) - end - - def test_missing_end_should_return_1 - t = TryRubyBaseSession.new - assert_equal(1, t.calculate_nesting_level("3.times do")) - end - - def test_missing_close_brace_should_return_1 - t = TryRubyBaseSession.new - assert_equal(1, t.calculate_nesting_level("3.times {")) - end - - def test_open_class_should_return_1 - t = TryRubyBaseSession.new - assert_equal(1, t.calculate_nesting_level("class BlogEntry")) - end - - def test_closed_class_should_return_0 - t = TryRubyBaseSession.new - assert_equal(0, t.calculate_nesting_level("class BlogEntry\nend")) - end - - def test_2_unclosed_dos_should_return_2 - t = TryRubyBaseSession.new - assert_equal(2, t.calculate_nesting_level("3.times do\n4.times do")) - end - - def test_mix_of_opened_statements - t = TryRubyBaseSession.new - test_str = <<-EOF - class MyClass - def mymethod - 3.times do - 8.times { - EOF - assert_equal(4, t.calculate_nesting_level(test_str)) - end - - def test_open_and_close_on_same_line_should_return_0 - t = TryRubyBaseSession.new - assert_equal(0, t.calculate_nesting_level("3.times { puts 'lol' }")) - assert_equal(0, t.calculate_nesting_level("3.times do |v| puts 'lol'; end")) - end - - def test_half_statement - t = TryRubyBaseSession.new - assert_equal(1, t.calculate_nesting_level('true and')) - assert_equal(1, t.calculate_nesting_level('amethod(')) - end - -end - - -class TryRubyTest < Test::Unit::TestCase - # a test helper that simplifies testing the tryruby interpretor. - # It takes one optional argument session, which is the session to use for - # the test. - # It then takes a block. In the block a method input is available which is used - # to send a line to the interpretor and test the output. - # - # input takes one mandatory argument, the line, and some optional args: - # - output: The output of line should match this (defaults to "") - # - javascript: The line generated a javascript function, and should match this - # - error: The line generated an error and should match this - # - result: The line didn't generate an error or javascript, and should match this - # (defaults to nil if not supplied) - # - line_continuation: The line didn't complete, the current indent level - # should be equal to this (use true if you aren't interested in testing this) - # output, error, javascript and result can take either a: - # - Class: Tests if is the given type - # - Proc: Proc should take one param (the ) and run assertions with that value - # - Regexp: Tests (a string) against the regexp - # - : should equal - def tryruby_session(session = TryRubyTestSession.new, &block) - input_o = TryRubySession_Input.new - input_o.session = session - input_o.test = self - input_o.instance_eval(&block) - - end - - - def test_lesson1 - tryruby_session do - input '2 + 6' , result: 8 - input '"Jimmy"' , result: "Jimmy" - input '"Jimmy".reverse' , result: "ymmiJ" - input '"Jimmy".length' , result: 5 - input '"Jimmy" * 5' , result: "JimmyJimmyJimmyJimmyJimmy" - end - end - - # tests statements that should end with a line continuation - def test_line_continuations - tryruby_session do - input '3.times do |v|' , line_continuation: 1 - input '3.times { |v|', line_continuation: 2 - input '}; end', result: Proc.new {true} - input 'class MyClass', line_continuation: 1 - input "def mymethod", line_continuation: 2 - input "end; end", result: Proc.new{true} - end - end - - def test_lines_with_semicolons - tryruby_session do - input '3; 4', result: 4 - input 'puts "hello"; a = 4; 5', output: "hello\n", result: 5 - input 'a', result: 4 - input '; 42', result: 42 - end - end - - - def test_errors - tryruby_session do - input 'asdf', error: NameError, output: "" - input 'print "hello"; asdf', error: NameError, output: "hello" - end - end - - # tests statements that shouldn't end with a line continuation - def test_shouldnt_have_line_continuation - tryruby_session do - input "'helloclassend'", result: "helloclassend" - input "3.class", result: Class - end - end - - def test_illegal_ops - $session = TryRubyTestSession.new - tryruby_session $session do - input '`cat /etc/passwd`', illegal: true - input 'require "popup"', result: Proc.new{} - input '%x(cat /etc/passwd)', illegal: true - end - end - - - def test_lesson2 - tryruby_session do - input '40.reverse', error: NoMethodError - input '40.to_s.reverse', result: "04" - input '[]', result: [] - input '[12,47,35]', result: [12,47,35] - input '[12,47,35].max', result: 47 - input 'ticket = [12,47,35]', result: [12,47,35] - input 'ticket', result: [12,47,35] - input 'ticket.sort!', result: [12,35,47] - end - end - - def test_lesson3 - poem = <<-EOF -My toast has flown from my hand -And my toast has gone to the -moon. -But when I saw it on television, -Planting our flag on Halley's -comet, -More still did I want to eat it. -EOF - - tryruby_session do - # the below line should be done automatically by the interpretor - # when help 3 is loaded - # input "poem = #{poem.inspect}", result: Proc.new{} - - input 'print poem', output: poem - input "poem['toast'] = 'honeydew'", result: "honeydew" - input 'print poem', output: (poem['toast'] = 'honeydew'; poem) - input 'poem.reverse', result: poem.reverse - input 'poem.lines.to_a.reverse', result: poem.lines.to_a.reverse - input 'print poem.lines.to_a.reverse.join', output: poem.lines.to_a.reverse.join - end - end - - def test_lesson4 - tryruby_session do - input 'books = {}', result: {} - - input 'books["Gravity\'s Rainbow"] = :splendid', - result: :splendid - - input 'books["a"] = :mediocre', result: :mediocre - input 'books["b"] = :mediocre', result: :mediocre - input 'books["c"] = :mediocre', result: :mediocre - input 'books.length', result: 4 - input 'books["Gravity\'s Rainbow"]', result: :splendid - input 'books.keys', result: ["Gravity's Rainbow", "a", "b", "c"] - input 'ratings = Hash.new {0}', result: {} - - input 'books.values.each { |rate| ratings[rate] += 1 }', - result: [:splendid, :mediocre, :mediocre, :mediocre] - - input '5.times {print "Odelay!" }', - result: 5, - output: 'Odelay!Odelay!Odelay!Odelay!Odelay!' - - end - end - - def test_lesson5 - tryruby_session do - input 'Dir.entries "/"', - result: [".", "..", "Home", "Libraries", "MouseHole", "Programs", "Tutorials", - "comics.txt"] - input 'Dir["/*.txt"]', result: ["/comics.txt"] - comics_txt_text = <", value.inspect - } - input 'File.mtime("/Home/comics.txt")', result: Time - input 'File.mtime("/Home/comics.txt").hour', result: Fixnum - end - - end - - def test_lesson6 - $session = TryRubyTestSession.new - tryruby_session $session do - input 'def load_comics( path )', line_continuation: 1 - input 'comics = {}', line_continuation: 1 - input 'File.foreach(path) do |line|', line_continuation: 2 - input "name, url = line.split(': ')", line_continuation: 2 - input 'comics[name] = url.strip', line_continuation: 2 - input 'end', line_continuation: 1 - input 'comics', line_continuation: 1 - input 'end', result: nil - - input "comics = load_comics('/comics.txt')", result: - {"Achewood"=>"http://achewood.com/", - "Dinosaur Comics"=>"http://qwantz.com/", - "Perry Bible Fellowship"=>"http://cheston.com/pbf/archive.html" , - "Get Your War On"=>"http://mnftiu.cc/"} - - input "require 'popup'", result: Proc.new {} - input 'Popup.goto "http://google.com/"', - javascript: "window.irb.options.popup_goto(\"http://google.com/\")" - - input 'Popup.make {', line_continuation: 1 - input 'h1 "My Links"', line_continuation: 1 - input 'link "Go to Google", "http://google.com/"', line_continuation: 1 - input '}', javascript: - "window.irb.options.popup_make" + - "(\"

              My Links

              " + - "Go to Google\")" - - input 'Popup.make do', line_continuation: 1 - input 'h1 "Things To Do"', line_continuation: 1 - input 'list do', line_continuation: 2 - input 'p "Try out Ruby"', line_continuation: 2 - input 'p "Ride a tiger"', line_continuation: 2 - input 'p "(down River Euphrates)"', line_continuation: 2 - input 'end', line_continuation: 1 - expected = <Things To Do -
              • Try out Ruby
              • -
              • Ride a tiger
              • -
              • (down River Euphrates) -
              ") -EOF - input 'end', javascript: expected.gsub("\n", "") - -input 'Popup.make do', line_continuation: 1 -input 'h1 "Comics on the Web"', line_continuation: 1 -input 'list do', line_continuation: 2 -input 'comics.each do |name, url|', line_continuation: 3 -input 'link name, url', line_continuation: 3 -input 'end', line_continuation: 2 -input 'end', line_continuation: 1 -input 'end', javascript: Proc.new { |v| - matches = v.match(/^window.irb.options.popup_make\("(.*)"\)/) - assert_not_nil(matches) - html = matches[1].gsub(/\\(.)/, '\1') - doc = Hpricot(html) - assert_equal("Comics on the Web", (doc/:h1).inner_html) - list_items = (doc/:li/:a).map do |elem| - {href: elem.attributes['href'], title: elem.inner_html} - end - assert_equal({href: "http://achewood.com/", title: "Achewood"}, - list_items[0]) - assert_equal({href: "http://qwantz.com/", title: "Dinosaur Comics"}, - list_items[1]) - assert_equal({href: "http://cheston.com/pbf/archive.html", - title: "Perry Bible Fellowship"}, - list_items[2]) - assert_equal({href: "http://mnftiu.cc/", title: "Get Your War On"}, - list_items[3]) - - #assert_equal("", html) - } - - - - - end - - end - - - - - def test_lesson7_and_8 - $session = TryRubyTestSession.new - tryruby_session $session do - input 'Hash.new', result: {} - input 'class BlogEntry', line_continuation: 1 - input 'attr_accessor :title, :time, :fulltext, :mood', line_continuation: 1 - input 'end', result: nil - - # can't test for BlogEntry directly, as it isn't defined in this scope - input 'entry = BlogEntry.new', result: Proc.new {|v| - assert_equal("BlogEntry", v.class.name, - "line should result in a BlogEntry") - } - - input 'entry.title = "Today Mt. Hood Was Stolen!"', result: "Today Mt. Hood Was Stolen!" - - input 'entry.time = Time.now', result: Time - - input 'entry.mood = :sick', result: :sick - - str = <

              My Blog

              -
                -
              • Today Mt. Hood Was Stolen!

              • -
              • I can't believe Mt. Hood was stolen! I am speechless! - It was stolen by a giraffe who drove away in his - Cadillac Seville very nonchalant!!
              • -
              • I Left my Hoodie on the Mountain!

              • -
              • I am never going back to that mountain and - I hope a giraffe steals it.
              • -
              - EOF - - expected_xml = REXML::Document.new(expected_str.strip) - assert_match(/^window.irb.options.popup_make\(".*"\)?/m, - v, - "testing that Popup calls the correct javascript function") - actual_str = v.match(/^window.irb.options.popup_make\("(.*)"\);?/m)[1] - actual_str = "#{actual_str}" - actual_xml = REXML::Document.new(actual_str.strip) - assert_equal(expected_xml.write(StringIO.new).to_s, - actual_xml.write(StringIO.new).to_s, - "testing that html used with the javascript popup " + - "function is correct") - } - - input 'Time.now - 2.weeks', result: Time - - input 'File.read("/MouseHole/flickrpedia.user.rb")', result: String - - end # tryruby_session - - end # lesson6_and_7 - - - - - # class that performs the tests with the input sections of the - # tryrubysession test helper - class TryRubySession_Input - attr_accessor :session, :test - - # performs an assertion - # actual is the value being tested - # expected should either be a - # - Class: the class of actual should be expected - # - Regexp: actual (a string) should match the expected Regexp - # - Proc: A proc that takes one argument, actual. Assertions can - # be used inside that proc, eg assert_equal, assert. - # - : actual should equal expected - # name is the name of the input (result, output, javascript, error), - # used in messages - # line is the line being tested - def do_assert(actual, expected, name, line) - case expected - when Class - @test.assert_kind_of(expected, actual, - "Testing line `#{line}': #{name} should be a #{expected}") - when Regexp - @test.assert_match(expected, actual, - "Testing line `#{line}': #{name} should match #{expected}") - when Proc - @backtrace_pos = 0 - @test.instance_exec(actual, &expected) - - # @test.assert(expected.call(actual), - # "Testing line `#{line}': #{message} \n[#{actual}]") - else - @test.assert_equal(expected,actual, - "Testing line `#{line}' for correct #{name}") - end - end - - # runs the line using this objects session. - def do_test(line) - o = Object.new - # store the initial constants of Object - initial_constants = Object.constants - session = @session - - thread = Thread.new do - o.instance_eval do - run_script(session, line) - end - end - - result = thread.value - # restores require to its old functionality - #def Object.require(str) - # old_require(str) - #end - - # next 4 lines will revert Object to the way it was before - # run_script - diff_constants = Object.constants - initial_constants - diff_constants.each do |constant| - Object.send(:remove_const, constant) - end - result - end - - - # The input function, used with the tryruby_session test helper - # see tryruby_session for more details - def input(line, params = {}) - @backtrace_pos = 2 - params[:output] ||= "" - params[:result] ||= nil - params[:error] ||= nil - - result = do_test(line) - begin - if params[:illegal] then - @test.assert_equal(:illegal, result.type, - "Testing if line `#{line}' resulted in an illegal operation") - elsif params[:error] then - @test.assert_equal(:error, result.type, - "Testing if line `#{line}` resulted in an error") - do_assert(result.error, params[:error], "error", line) - do_assert(result.output, params[:output], "output", line) - elsif params[:javascript] then - @test.assert_nil(result.error, - "Testing line `#{line}' to ensure there was no error") - do_assert(result.javascript, params[:javascript], "javascript", line) - do_assert(result.output, params[:output], "output", line) - elsif params[:line_continuation] - @test.assert_equal(:line_continuation, result.type, - "Testing if line `#{line}' resulted in a line continuation") - if params[:line_continuation] != true then - @test.assert_equal(result.indent_level, params[:line_continuation], - "Testing if line `#{line}' triggered enough autoindent") - end - else - @test.assert_nil(result.error, - "Testing line `#{line}' to ensure there was no error") - do_assert(result.result, params[:result], "result" , line) - do_assert(result.output, params[:output], "output", line) - end - - rescue Test::Unit::AssertionFailedError => e - p e - - new_bt = Test::Unit::Util::BacktraceFilter.filter_backtrace(e.backtrace) - new_bt = new_bt[@backtrace_pos..@backtrace_pos] - e.set_backtrace(new_bt) - raise e - - end - end - end -end - -# tests if the TryRubyOutput translation, for use with mouseapp_2.js and similar -# is working correctly -class TryRubyOutputTest < Test::Unit::TestCase - def test_simple_result - t = TryRubyOutput.standard(result: [12,24]) - assert_equal("=> \033[1;20m[12, 24]", t.format_output) - end - - def test_result_and_output - t = TryRubyOutput.standard(result: 333, output: "hello") - assert_equal("hello=> \033[1;20m333", t.format_output) - end - - def test_error - begin - 40.reverse - rescue Exception => e - t = TryRubyOutput.error(error: e) - end - assert_equal("\033[1;33mNoMethodError: undefined method `reverse' for 40:Fixnum", - t.format_output) - end - - def test_error_with_output - begin - 40.reverse - rescue Exception => e - t = TryRubyOutput.error(error: e, output: "hello\nworld") - end - assert_equal("hello\nworld\033[1;33mNoMethodError: undefined method `reverse' for 40:Fixnum", - t.format_output) - end - - def test_illegal - t = TryRubyOutput.illegal - assert_equal("\033[1;33mYou aren't allowed to run that command!", - t.format_output) - end - - - - def test_line_continuation - t = TryRubyOutput.line_continuation(3) - assert_equal(".." * 3, t.format_output) - end - - def test_javascript - t = TryRubyOutput.javascript(javascript: 'alert("hello")') - # expected ends in a space to stop a visual problem in mouseapp - assert_equal("\033[1;JSmalert(\"hello\")\033[m ", t.format_output) - end - -end diff --git a/public/tmp/index.html b/public/tmp/index.html deleted file mode 100755 index e933af9..0000000 --- a/public/tmp/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -

              you shouldn't be here.. kicking you out!

              - - diff --git a/public/tryruby.rb b/public/tryruby.rb deleted file mode 100644 index 4b9bbcb..0000000 --- a/public/tryruby.rb +++ /dev/null @@ -1,174 +0,0 @@ -#$LOAD_PATH.unshift File.join(File.dirname(__FILE__), 'submodules', 'fakefs', 'lib') -require './setup.rb' -require 'ruby_parser' -require './fakefs/safe' -require 'stringio' - -module TryRuby - extend self - - class Session - attr_accessor :past_commands, :current_statement, :start_time - def initialize - @past_commands = '' - @current_statement = '' - @start_time = Time.now - end - end - - class Output - attr_reader :type, :result, :output, :error, :indent_level, :javascript - - def self.standard(params = {}) - Output.new type: :standard, result: params[:result], - output: params[:output] || '' - end - - def self.illegal - Output.new type: :illegal - end - - def self.javascript(js) - Output.new type: :javascript, javascript: js - end - - def self.no_output - Output.standard result: nil - end - - def self.line_continuation(level) - Output.new type: :line_continuation, indent_level: level - end - - def self.error(params = {}) - params[:error] ||= StandardError.new('TryRuby Error') - params[:error].message.gsub! /\(eval\):\d*/, '(TryRuby):1' - Output.new type: :error, error: params[:error], - output: params[:output] || '' - end - - def format - case @type - when :line_continuation - ".." * @indent_level - when :error - @output + "\033[1;33m#{@error.class}: #{@error.message}" - when :illegal - "\033[1;33mYou aren't allowed to run that command!" - when :javascript - "\033[1;JSm#{@javascript}\033[m " - else - @output + "=> \033[1;20m#{@result.inspect}" - end - end - - protected - def initialize(values = {}) - values.each do |variable, value| - instance_variable_set("@#{variable}", value) - end - end - end - - - class << self - attr_accessor :session - TryRuby.session = TryRuby::Session.new - end - - def calculate_nesting_level(statement) - begin - RubyParser.new.parse(statement) - 0 - rescue Racc::ParseError => e - case e.message - when /parse error on value \"\$end\" \(\$end\)/ then - new_statement = statement + "\n end" - begin - RubyParser.new.parse(new_statement) - return 1 - rescue Racc::ParseError => e - if e.message =~ /parse error on value \"end\" \(kEND\)/ then - new_statement = statement + "\n }" - end - end - begin - 1 + calculate_nesting_level(new_statement) - rescue Racc::ParseError => e - return 1 - end - else - raise e - end - end - end - - def run_line(code) - case code.strip - when '!INIT!IRB!' - return Output.no_output - when 'reset' - TryRuby.session.current_statement = '' - return Output.no_output - when 'time' - seconds = (Time.now - session.start_time).ceil - return Output.standard result: - if seconds < 60; "#{seconds} seconds" - elsif seconds < 120; "1 minute" - else; "#{seconds / 60} minutes" - end - end - - # nesting level - level = begin - calculate_nesting_level(session.current_statement + "\n" + code) - rescue Racc::ParseError, SyntaxError - 0 - end - if level > 0 - session.current_statement += "\n" + code - return Output.line_continuation(level) - end - - # run something - FakeFS.activate! - stdout_id = $stdout.to_i - $stdout = StringIO.new - cmd = <<-EOF - #{SetupCode} - $SAFE = 3 - #{session.past_commands} - $stdout = StringIO.new - begin - #{session.current_statement} - #{code} - end - EOF - begin - result = Thread.new { eval cmd, TOPLEVEL_BINDING }.value - rescue SecurityError - return Output.illegal - rescue Exception => e - return Output.error :error => e, :output => get_stdout - ensure - output = get_stdout - $stdout = IO.new(stdout_id) - FakeFS.deactivate! - end - - session.current_statement += "\n" + code - session.past_commands += "\n" + session.current_statement.strip - session.current_statement = '' - - return result if result.is_a? Output and result.type == :javascript - Output.standard result: result, output: output - end - - private - def get_stdout - raise TypeError, "$stdout is a #{$stdout.class}" unless $stdout.is_a? StringIO - $stdout.rewind - $stdout.read - end - -end diff --git a/public/tutorials/es_intro.html b/public/tutorials/es_intro.html deleted file mode 100644 index 256de2f..0000000 --- a/public/tutorials/es_intro.html +++ /dev/null @@ -1,666 +0,0 @@ - -
              -

              Usando El Prompt

              -

              La ventana azul de arriba es el prompt de Ruby. ¡Escribe una línea de código Ruby, aprieta Enter - y velo correr!

              -

              Por ejemplo, trata de escribir algo matemático. Como: 2 + 6

              -
              \d+
              -
              -
              -

              Números & Matemática

              -

              ¡Bien! Hiciste algo de matemática. ¿Ves como la respuesta salta a la vista?

              -

              Ruby reconoce números y símbolos matemáticos. Puedes probar otras cosas como:

              -
              • 4 * 10
              • -
              • 5 - 12
              • -
              • 40 / 4
              -

              Seguro, las computadoras son habilidosas y rápidas con las matemáticas. Sigamos... ¿Quieres ver tu nombre al revés? - Escribe tu primer nombre entre comillas así: "Jimmy"

              -
              "(\w+)"
              -
              -
              -

              Decir Tu Nombre Al Revés

              -

              Perfecto, has formado un string de las letras de tu nombre. Un string - es un juego de caracteres que la computadora puede procesar.

              -

              Imagina que las letras están en una cuerda donde - se cuelga la ropa y las comillas son los broches que sostienen los bordes. Las comillas marcan el comienzo y el final.

              -

              Para invertir tu nombre, escribe: "Jimmy".reverse (¡No olvides el punto!)

              -
              "(\w+)"
              -
              -
              -

              Contando Las Letras

              -

              ¡Has usado el método reverse sobre tu nombre! Poniendo tu nombre entre comillas, - hiciste un string. Luego llamaste al método reverse, que funciona sobre un string cambiando - todas las letras de atrás para adelante.

              -

              Ahora, vamos a ver cuantas letras tiene tu nombre: "Jimmy".length

              -
              \d+
              -
              -
              -

              Repitiendo

              -

              Ahora, estoy seguro que te estarás preguntando para que sirve todo esto. Bueno, estoy seguro que habrás estado en alguna - pagina web donde te gritaron, ¡Hey, tu password es muy corto! Ves, algunos programas - usan este código tan simple.

              -

              Mira esto. Vamos a multiplicar tu nombre por 5. "Jimmy" * 5

              -
              "(\w+)"
              -
              -
              -

              Hey, Sumario #1 Listo

              -

              Vamos a ver que es lo que has aprendido en el primer minuto.

              -
                -
              • El prompt. Escribiendo código en el prompt verde obtienes - una respuesta del prompt rojo. Todo código te da una respuesta.
              • -
              • Números y strings son objetos matemáticos y de texto de Ruby.
              • -
              • Métodos Has usado métodos en Ingles como reverse - y métodos simbólicos como * (el método de multiplicación.) ¡Los métodos son acciones!
              • -
              -

              Esta es la esencia del aprendizaje. Tomar cosas simples, jugar con ellas - y trasformarlas en cosas nuevas. ¿Te sientes cómodo con todo? Te aseguro que lo estas.

              -

              Bien, vamos a hacer algo incomodo. Trata de invertir un número: 40.reverse

              -
              NoMethodError: undefined method `reverse' for (\d+):Fixnum
              -
              -
              -

              ¡Basta, Te Volviste Loco!

              -

              No puedes invertir el numero cuarenta. Supongo que puedes poner tu monitor en - frente de un espejo, pero invertir un numero no tiene sentido. Ruby lanza un - mensaje de error. Ruby te dice que no hay un método reverse para los números.

              -

              Tal vez si lo conviertes en un string: 40.to_s.reverse.

              -
              \"(\d+)\"
              -
              -
              -

              Los Chicos Son Diferentes De Las Chicas

              -

              Y los números son diferentes de los strings. Aunque puedes usar métodos en cualquier objeto - en Ruby, algunos métodos solo funcionan en cierto tipo de cosas. Pero siempre puedes - convertir entre diferentes tipos usando el método "to" de Ruby.

              -
              • to_s convierte cosas a strings.
              • -
              • to_i convierte cosas a integers (números.)
              • -
              • to_a convierte cosas a arrays.
              • -
              -

              ¿Que son los arrays?! Son listas. Escribe entre un par de corchetes: [].

              -
              \[\]
              -
              -
              -

              Mantenerse en Cola

              -

              Genial, eso es una lista vacía. Las listas guardan cosas en orden. - Como esperando en la cola para palomitas de maíz. Estas atrás de alguien y jamás - pensarías en empujarlo a un costado, ¿no es así? Y con respecto al tipo detrás de ti, - mantienes un ojo sobre el, ¿correcto?

              -

              Acá hay una lista para ti. Números de la lotería: [12, 47, 35].

              -
              \[(\d+(, )?){2,}\]
              -
              -
              -

              Uno Levanta La Mano

              -

              Una lista de números de la lotería. ¿Cual es el mayor?

              -

              Prueba: [12, 47, 35].max.

              -
              (\d+)
              -
              -
              -

              Manteniendo la Lista

              -

              Bien, bien. Pero es un fastidio el tener que reescribir esa lista, ¿no es así?

              -

              Guardemos nuestros números en un ticket de esta manera: ticket = [12, 47, 35]

              -
              \[(\d+(, )?){2,}\]
              -
              -
              -

              Ahora Escribe Ticket

              -

              Ahora, escribe: ticket

              -
              \[(\d+(, )?){2,}\]
              -
              -
              -

              Guardado, Escondido

              -

              ¡Fantástico! Te has aferrado a tus números de la lotería, escondiéndolos dentro de una - variable llamada ticket.

              -

              Vamos a poner tus números en orden, que te parece? Usa: ticket.sort!

              -
              \[(\d+(, )?){2,}\]
              -
              -
              -

              Sumario #2 Está Sobre Nosotros

              -

              Tenías una lista. Ordenaste la lista. La variable ticket ahora esta cambiada.

              -

              ¿Te diste cuenta que el método sort! tiene un claro y llamativo signo de exclamación al final? - Muchas veces los métodos de Ruby gritan así si es que alteran la variable para bien. No es nada - especial, solo una marca.

              -

              Ahora, mira como te fue en tu segundo minuto:

              -
                -
              • Errors. Si tratas de invertir un número o hacer algo sospechoso, - Ruby salteara el prompt para avisarte.
              • -
              • Arrays son listas para ordenar cosas en orden.
              • -
              • Variables guardan cosas y le dan un nombre. Usaste el - signo igual para hacerlo.
                Like: ticket = [14, 37, 18].
              • -
              -

              En total hay ocho lecciones. Estás a dos octavos de camino! - Esto es cosa simple, no te parece? Las cosas buenas están mas adelante.

              -

              Cambiemos de dirección por un momento. Rellené con un poco de poesía cierta - variable para ti. Hecha un vistazo. Escribe print poem

              -
              poem = "My toast has flown from my hand\nAnd my toast has gone to the -moon.\nBut when I saw it on television,\nPlanting our flag on Halley's -comet,\nMore still did I want to eat it.\n"
              -
              My toast (.+)
              -
              -
              -

              Desgraciadamente, Tú Odias la poesía de Tostadas

              -

              Mira, esta bien. No tiene que gustarte. Hackéalo, yo invito.

              -

              En vez de tostada, ve por un melón o algo. Prueba esto: poem['toast'] = 'honeydew'

              -

              Y luego escribe print poem para ver el nuevo poema.

              -
              My honey(.+)
              -
              -
              -

              Listo, Apuntado

              -

              Los corchetes que acabas de usar son muy comunes en Ruby. Recuerda, escribiste: poem['toast'] = 'honeydew'. Esa casilla con la palabra toast tiene corchetes a ambos lados, ¿ves?

              -

              Los -corchetes son como una mira para alinear un objetivo. Exacto. Estos -corchetes significan, "Estoy buscando ____." Listo, apuntado. Aquí estas buscando -una costada e intercambiándola por una fruta.

              -

              Aquí hay una pregunta: ¿Que pasa si volteamos el poema entero? poem.reverse -

              "\\n.ti tae ot (.+)"
              -
              -
              -

              Demasiado Invertido

              -

              Está bien, seguro. Entonces todo el poema fue puesto al revés. Letra por letra. Sin embargo, yo realmente solo quería - invertir las líneas. Mover la última línea a la primera y la primera hacia abajo a la ultima. Al revés, pero no - ése revés.

              -

              Aquí esta como lograrlo: poem.lines.to_a.reverse

              -
              \["More still did I(.+)"\]
              -
              -
              -

              Rizos de Metodos Concatenados

              -

              Dime, que es lo que ves? Que paso acá? Escribiste poem.lines.to_a.reverse y ¿que pasó?

              -

              Dos cosas pasaron. Convertiste poem en una lista usando -lines.to_a. lines decide la forma en que -el string se divide, luego to_a lo -convierte en un Array. (To array.) Diferentes métodos, como -bytes y chars pueden ser usadas en lugar de -lines. Usando lines, Ruby retornará cada línea de poem.

              -

              Luego, tu revertiste, reversed, esa lista. Tenías cada línea. Las revertiste. Eso es todo.

              -

              Vamos a hilar un método más al final de todo esto: print poem.lines.to_a.reverse.join -

              More still did I(.+)
              -
              -
              -

              De Todos los Sumarios, el #3 esta aquí

              -

              Buen espectáculo, mi amigo! El método join toma la lista de líneas revertidas y las pone juntas en un string. - (Seguro, también podrías haber usado to_s.)

              -

              Tiempo de Revisión.

              -
                -
              • Exclamaciones. Métodos pueden tener signos de exclamación (y también de interrogación) en - sus nombres. No es la gran cosa. Prueba: poem.include? "my hand"
              • -
              • Corchetes. Establece objetivos y busca cosas. Busca y reemplaza.
              • -
              • Concatenar métodos te permite hacer mas cosas juntas. Partir poem, revertirlo, - reensamblarlo: poem.lines.to_a.reverse.join
              • -
              -

              En este punto, querras manosear un poco más el poema. Una lista completa de métodos - String estan - - acá. - No temas y prueba algunos (como poem.downcase o poem.delete.)

              -

              Cuando estés listo para seguir adelante, escribe: books = {}

              -
              \{\}
              -
              -
              -

              Un Pequeñín Libro en Blanco

              -

              Has hecho un hash vacío. (también conocido como: un diccionario vacío.)

              -

              Vamos a rellenar con un libro de críticas en miniatura. Acá esta nuestro sistema de calificación:

              -
                -
              • :splendid → una obra maestra.
              • -
              • :quite_good → disfrutable, por supuesto que sí.
              • -
              • :mediocre → partes iguales de bueno y malo.
              • -
              • :quite_not_good → notablemente malo.
              • -
              • :abyssmal → una perdida de tiempo.
              • -
              -

              Para calificar un libro, pon el título entre corchetes y la calificación luego del signo igual.

              -

              Por ejemplo: books["Gravity's Rainbow"] = :splendid

              -
              :\w+
              -
              -
              -

              Mas Críticas Tamaño Bocadillo

              -

              Tú sigue, agrega mas críticas. Y, si quieres ver toda la lista, - implemente escribe: books

              -

              De nuevo, las calificaciones son: :splendid, :quite_good, :mediocre, - :quite_not_good, and :abyssmal.

              -

              Estas calificaciones no son strings. Cuando colocas dos puntos frente a una palabra simple, obtienes un - symbol. Los símbolos son más baratos que los strings (en términos de memoria de la computadora.) Si usas - una palabra una y otra vez en un programa, usa un símbolo. En vez de tener miles de - copias de una palabra en memoria, la computadora guardara el símbolo solamente una vez.

              -

              Una vez que tengas tres o cuatro libros allí - dentro, escribe: books.length.

              -
              [3-9]
              -
              -
              -

              Espera, ¿Me gustó Gravity's Rainbow?

              -

              Ves, el método length funciona sobre strings, list y hashes. Una gran cosa acerca de - Ruby es que los nombres usualmente se reutilizan, lo que significa menos nombres para recordar.

              -

              Si quisieras ver una de tus críticas hechas, vuelve a poner el título entre corchetes. Pero deja de lado el - signo igual.

              -

              Al igual que aquí: books["Gravity's Rainbow"]

              -
              :\w+
              -
              -
              -

              Hashes como Pares

              -

              Ten en mente que los hashes no mantienen las cosas en orden. Ese no es su trabajo. Solo emparejará dos - cosas: una key (llave) y un valor. En tus críticas, la key es el - titulo del libro y el valor es la calificación.

              -

              Si simplemente quieres ver los títulos de los libros que calificaste: books.keys

              -
              \[".*"\]
              -
              -
              -

              ¿Eres Duro?

              -

              ¿Estás dando duras injustas críticas? Sigamos puntuando con rigurosidad:
              ratings = Hash.new {0}

              -

              Entonces, bien, ahora vamos a contar tus críticas. Trata de seguirme. Escribe:
              - books.values.each { |rate| ratings[rate] += 1 }

              -

              (La línea vertical es el signo de tubería, probablemente lo logres con AltGr+1 con tu teclado.)

              -
              \[:.+\]
              -
              -
              -

              Un Recuento

              -

              Genial, wow! Has hecho un recuento de tus calificaciones. Escribe ratings para ver las cuenta. Este nuevo - hash muestra las calificaciones y luego el numero de veces que has dado esa calificación.

              -

              Una de las asombrosas cosas nuevas que acabamos de usar es un bloque, block. Vamos a explorar - explore these more in the next summary. más esto en el próximo sumario. Pero, básicamente, un bloque es un pedazo de código Ruby - rodeado por llaves.

              -

              Probemos otro bloque: 5.times { print "Odelay!" }

              -
              Odelay!Od.*
              -
              -
              -

              Ahora Arribamos al Sumario #4

              -

              Los bloques están siempre apegados a métodos. Como el método times, que toma el bloque y lo corre - repetidas veces. (En este caso: cinco veces.)

              -

              Esta última lección fue algo mas larga. Probablemente usaste unos tres minutos aprendiendo sobre:

              -
                -
              • Hashes. El pequeño diccionario con páginas arrugadas: {}.
              • -
              • Symbols. Pequeñas, eficientes palabras con dos puntos: :splendid.
              • -
              • Blocks. Pedazos de código que pueden ser clavados a muchos métodos de Ruby. Aquí - esta el código que usaste para crear el recuento:
                books.values.each { |rate| ratings[rate] += 1 }.
              • -
              -

              En tu computadora, probablemente tienes muchos archivos diferentes. Archivos con fotos en ellos, - archivos con programas dentro. Y los archivos usualmente se organizan en carpetas, también llamadas: - directorios.

              -

              He preparado algunos directorios para ti. Echa un vistazo: - Dir.entries "/"

              -
              \["\.", .+\]
              -
              -
              -

              La Privada Colección de Dr. Dir

              -

              Acabas de listar todo lo existente en el directorio superior. El directorio raíz, indicado - por la barra en diagonal. Conteniendo algunos programas y otros tutoriales y semejantes.

              -

              Entonces, ¿que es el método Dir.entries? Bueno, es solo un método ¿si?, - entries es el método llamado sobre la variable Dir. - Y Dir tiene una colección de métodos para chequear los archivos de los directorios.

              -

              Otra pequeña cosa de la que no hemos hablado abiertamente. Argumentos de los métodos, resaltados en verde.

              -
                -
              • Dir.entries "/": Cualquier cosa listada luego de un método - es considerado acoplamiento.
              • -
              • print poem: Ves, print es un método ordinario. - Y el poema esta acoplado. Para ser impreso.
              • -
              • print "pre", "event", "ual", "ism" posee varios argumentos, - con comas entre ellos.
              • -
              -

              Para listar solamente archivos de texto en el directorio: Dir["/*.txt"]

              -
              \["\/comics\.txt"\]
              -
              -
              -

              Ven, Lee Historietas Conmigo

              -

              El método Dir[] hace como entries pero tu buscas por archivos - archivos con carácteres de comodín. ¡Aquí, vemos esos corchetes otra vez! Te das - cuenta como todavía significan, "Estoy buscando _____.".

              -

              Mas específicamente: "Estoy buscando archivos que terminen con .txt."

              -

              Abramos este archivo con historietas de una vez. Aquí esta la manera:
              - print File.read("/comics.txt")

              -
              Achewood.+
              -
              -
              -

              Mi Comicas, Tu Comicas

              -

              ¡De acuerdo! Podemos comenzar a usar archivos para guardar cosas. Esto es excelente - porque normalmente cuando salimos de Ruby, todas nuestras variables desaparecerán. - Ruby, por si mismo, olvida estas cosas. Pero si salvamos cosas en archivos, - podemos leer esos archivos en futuras escapadas a Ruby.

              -

              Hey, y ¿adivina que? ¡El directorio /Home es tuyo! ¡Te lo entrego a ti! ¡Soy generoso! Hagamos una copia del archivo de la historieta.

              -

              Querrás hacer lo siguiente: FileUtils.copy('/comics.txt', '/Home/comics.txt') -

              Si ya has creado el archivo, usa File.delete('/Home/comics.txt') para arrojarlo a la basura.

              -
              nil
              -
              -
              -

              Tu Propio Territorio

              -

              Ok, tienes una copia. Chequéala: Dir["/Home/*.txt"]

              -

              Para agregar tu propia historieta a la lista, abramos el archivo en modo append.

              -

              Empieza asi: File.open("/Home/comics.txt", "a") do |f|.

              -
              ..
              -
              -
              -

              Y Ahora, para la Sorprendente Conclusión

              -

              Asi que tu prompt ha cambiado. ¿Lo notas? Tu prompt es doble punto ahora.

              -

              En este tutorial, este prompt significa que Ruby espera que escribas más. A - medida que vayas completando con líneas de código, los doble puntos se mantendrán - hasta que hallas finalizado.

              -

              Hot tip: si quieres parar de trabajar en el código y salirte de los doble puntos, usa el comando reset. - Si quieres volver a la pagina previa del tutorial, usa el comando back.

              -

              Aquí esta tu código. Ya has escrito la primera línea, asi que simplemente ingresa la segunda. (El \n - es el carácter de Enter.

              -
              • File.open("/Home/comics.txt", "a") do |f|
              • -
              •   f << "Cat and Girl: http://catandgirl.com/\n"
              • -
              • end
              • -
              -

              Y, como te has vuelto avanzado y capaz aquí, otro tip: puedes usar las flechas hacia - arriba y hacia abajo para editar tus viejos comandos o correrlos otra vez.

              -
              ..
              -
              -
              -

              Ruby se Sienta y Espera

              -

              Esa ultima línea agrega la historieta Cat and Girl a la lista, pero Ruby seguirá esperando - hasta que hallas terminado por completo para tomar acción.

              -

              Ahora, para finalizar el código que has empezado. Empezaste un nuevo bloque cuando escribiste do. - Hasta ahora los bloques que hemos visto usaban llaves. Esta vez usaremos do y end en lugar - de las llaves. Muchos Rubyistas usan do...end cuando el bloque ocupa varias líneas.

              -

              Terminemos ese bloque ahora mismo, con: end

              -
              • File.open("/Home/comics.txt", "a") do |f|
              • -
              •   f << "Cat and Girl: http://catandgirl.com/\n"
              • -
              • end
              • -
              -
              #.File:/Home/comics\.txt \(closed\).
              -
              -
              -

              El Reloj Clavado en el Archivo

              -

              ¡Bien, bien! Has añadido esa historieta al archivo. Puedes verlo por ti mismo: print File.read("/Home/comics.txt")

              -

              ¿Qué hora era cuando cambiaste el archivo? Veamos. Escribe: File.mtime("/Home/comics.txt")

              -
              \w+ \w+ \d+ \d{2}:\d{2}:\d{2} [+-]\d{4} \d{4}
              -
              -
              -

              Sólo la Manecilla de la Hora

              -

              Estupendo, allí esta la hora. La hora exacta en la que agregaste la historieta al archivo. El mtime te devuelve un objeto Time de Ruby.

              -

              Si sólo quieres ver la hora que era, aprieta la flecha para arriba y cambia la línea a: File.mtime("/Home/comics.txt").hour

              -
              \d+
              -
              -
              -

              Hola, ¿Quién Anda Ahí? Y el Sumario #5 Agita su Sombrero!

              -

              Bien hecho, bien hecho, bien hecho, ¡bien hecho! Realmente, realmente, realmente, realmente, ¡reaaaaaaaaalllmente!

              -

              Aquí esta tu último minuto de tu vida en retrospectiva:

              -
                -
              • Archivos. ¿Que más se puede decir? Muchos métodos para editar archivos y revisar directorios.
              • -
              • Argumentos. Los argumentos son listas de cosas mandadas en un método. Separadas con comas.
              • -
              • También hablamos sobre do y end que es otra manera de hacer un bloque.
              • -
              -

              Ahora ya sabes como usar Ruby por completo. Me refiero a que tienes lo esencial. Solo necesitas seguir - aprendiendo métodos y probar bloques más complejos.

              -

              Pero existe un lado de Ruby que no hemos hablado. Hacer tus propios métodos y clases.

              -

              Ahem! Acabemos con ello de una vez.

              -

              Empieza con: def load_comics( path )

              -
              ..
              -
              -
              -

              En Ruby, Def Leppard Significa ¡Define Leppard (un Método)!

              -

              Hey, bueno, lo hiciste. Estas haciendo tu propio método. Comenzaste con def, seguido por el nombre del método. - Y una lista de argumentos que va a necesitar el método. ¡Esto no da tanto miedo ni es peligroso!

              -

              Todo lo que debemos hacer es rellenar con Ruby y terminarlo con end.

              -

              Aquí esta el código:

              -
              • def load_comics( path )
              • -
              •   comics = {}
              • -
              •   File.foreach(path) do |line|
              • -
              •     url, name = line.split(': ')
              • -
              •     comics[url] = name.strip
              • -
              •   end
              • -
              •   comics
              • -
              • end
              • -
              -

              No necesitas indentar, si no quieres. Lo hice solo para que sea más legible.

              -
              nil
              -
              -
              -

              La Madura Fruta de tu Propia Creación

              -

              Un nuevo método ha nacido. Vamos a usarlo: comics = load_comics('/comics.txt')

              -

              Si tienes un problema, puedes haberlo escrito mal. Usa el comando back y prueba otra vez.

              -
              \{.*"Achewood"=."http://achewood.com/".*\}
              -
              -
              -

              Hey, Cool, Una Cosa de Historietas

              -

              En tu ventana de Ruby arriba, mira el código que has escrito para el método load_comics. ¿Qué esta pasando? Tu estas - pasando en la variable path y estas recibiendo la variable comics. Ruby permite filtrar el hash comics - que es devuelto al final del método.

              -

              Una cantidad de métodos se usaron para realizar el trabajo. Fíjate si puedes hallarlos.

              -
              • File.foreach es el método que abre un archivo y manda cada línea al bloque. La variable line - dentro del bloque do...end va turnando con cada línea del archivo.
              • -
              • split es un método para strings, que rompe los string en colocándolo en un array. Un hacha es arrojada sobre las comas - y las líneas se cortan en dos, dándonos la url y el nombre, name, de las historietas.
              • -
              • strip remueve los espacios extra alrededor de name. Por si acaso.
              • -
              -

              Justo allí. Bravo. Tienes las historietas en un hash de Ruby. ¿Pero ahora qué? ¿Qué tan bueno es en verdad?

              -

              Hagamos una página de links. ¿Qué te parece? Vamos a necesitar una pequeña librería que hice para ti.

              -

              Escribe: require 'popup'

              -
              true
              -
              -
              -

              El Navegador de Títere

              -

              Excelente, has cargado la librería popup. Está guardada en un archivo en el directorio Libraries. Mira: Dir["/Libraries/*"]

              -

              La librería popup contiene un puñado de métodos que he escrito y te dejaran controlar ventanas emergentes aquí en Try Ruby.

              -

              Mira, prueba esto: Popup.goto "http://google.com/"

              -
              \033\[1;JSm.*popup_goto\(.*\)\033\[m.*
              -
              -
              -

              Haciendo Links e Hilando Redes

              -

              Nuestro propio adorable, pequeño popup para manipular. también puedes rellenarlo con tus cositas. Empecemos por algo pequeño:

              -
              • Popup.make {
              • -
              •   h1 "My Links"
              • -
              •   link "Go to Google", "http://google.com/"
              • -
              • }
              • -
              -

              El termino h1 (h-uno) significa encabezado de nivel uno. En HTML, es el encabezado más grande.

              -
              \033\[1;JSm.*popup_make\(.*h1.*a href.*\)\033\[m.*
              -
              -
              -

              Los Popups son tan fáciles, es una Locura

              -

              Se ve bien, lo hiciste perfecto, tal como se te pidió. Hagamos una lista entonces.

              -

              Aquí esta como haces una lista con la librería de popup:

              -
              • Popup.make do
              • -
              •   h1 "Things To Do"
              • -
              •   list do
              • -
              •     p "Try out Ruby"
              • -
              •     p "Ride a tiger"
              • -
              •     p "(down River Euphrates)"
              • -
              •   end
              • -
              • end
              • -
              -

              El método p es la manera corta para "párrafo".

              -
              \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*li.*\)\033\[m.*
              -
              -
              -

              Expandiendo las Historietas en la Tabla

              -

              Bien, esto esta yendo maravilloso. Esto es algo simple, pero mantén en mente que no sabias nada sobre Ruby hace quince minutos atrás!<

              -

              Ultimo paso. Vamos a juntar todo, ¿sabes? ¡Juntémoslo como esos juegos de - campanillas hermosas que tintinean en los pórticos bajo la hermosa luz del sol - en la playa!

              -

              Asegúrate de que las historietas están cargadas: comics = load_comics( '/comics.txt' )

              -

              Ahora, hagamos una lista de links para cada historieta:

              -
              • Popup.make do
              • -
              •   h1 "Comics on the Web"
              • -
              •   list do
              • -
              •     comics.each do |name, url|
              • -
              •       link name, url
              • -
              •     end
              • -
              •   end
              • -
              • end
              • -
              -

              Puedes clickear en los links y leer las historietas ¡inclusive en la ventana principal! ¡Bárbaro!

              -
              \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*a href.*li.*a href.*\)\033\[m.*
              -
              -
              -

              Sumario #6 lo que Significa que has Llegado Muy Lejos

              -

              Eres un clérigo nivel 6 de Ruby. Quiero decir que buen trabajo has hecho. Vamos a revisar:

              -
                -
              • Agregaste tu propio método con def y usaste ese método load_comics varias veces.
              • -
              • Librerias. Tú usaste el método require para cargar la librería popup.
                Escribiendo: require 'popup'
              • -
              • Y como si no fuera suficiente, hiciste tu propia página web para listar los archivos de historietas. ¡Hiciste un programa real!
              • -
              -

              Entonces ¿Qué podrá venir luego? ¿Qué deberías aprender posiblemente ahora? - Ja, esta es la mejor parte. Has recorrido un largo camino y ahora descubrirás - las clases. En dos lecciones mas y ya estarás hecho.

              -

              Tempranamente, creamos un hash como este: Hash.new pruébalo.

              -
              \{\}
              -
              -
              -

              No una Clase de Escuela, Una Clase Trabajadora

              -

              Ves, las llaves vacías {} son abreviaciones para Hash.new. El método new - es usado para hacer objetos de cierta clase. (Piensa "clase" como en "clase - trabajadora" — un grupo especifico de objetos similares, tienen el - mismo trabajo, la misma camisa.)

              -

              Pregúntate esto: ¿Cómo haría mi blog en Ruby? ¿Dónde deberías - comenzar? Bien, deberías guardar tus entradas del blog en un archivo, ¿cierto? - Pero ¿cómo seguirías los títulos de las entradas y el momento en que fue creado? - Y cuando cargas el archivo, ¿cómo se vería en Ruby? ¿Sería un Hash? ¿O un Array? ¿O - un Array de Arrys? ¿O alguna otra cosa?

              Yo realmente creo que querrás usar una clase. Ya estas familiarizado con varias clases: Hash, Array, String.

              -

              Hagamos una clase nueva: class BlogEntry.

              -
              ..
              -
              -
              -

              El Relleno del Blog esta Hecho de

              -

              Has abierto una nueva clase BlogEntry. ¿De que están hechas las entradas de tu blog? Un titulo, seguro. también, - la fecha en la que fue creada. El texto entero de la entrada.

              -

              Vamos a poner el estado de ánimo, también, tal como LiveJournal. La internet ha traído de vuelta las personas de palitos y emoticones - fuera de la bancarrota.¡Que emoción!

              -

              Bueno, ya tienes la primera línea de la clase, aquí esta el resto:/p> -

              • class BlogEntry
              • -
              •   attr_accessor :title, :time, :fulltext, :mood
              • -
              • end
              • -
              -
              nil
              -
              -
              -

              Accessors Son las Extremidades Colgantes

              -

              Hey, buena clase, colega. Tienes una nueva clase BlogEntry. Para comenzar una entrada:
              entry = BlogEntry.new.

              -

              En la definición de la clase, usaste un método llamado attr_accessor. Existen varios métodos attribute - atributo, como este que agregan pequeñas configuraciones a la clase. Estos atributos son simplemente variables adosadas a la clase.

              -

              Piénsalo de este modo. Una clase es como una persona. Esa forma de estrella - del humano. Y los atributos son las extremidades, las diferentes partes que - hacen un cuerpo.

              -

              Para crear el titulo de tu entrada: entry.title = "Today Mt. Hood Was Stolen!"

              -
              ".+"
              -
              -
              -

              Un Objeto, Ese Estupendo Paquete Pequeño

              -

              Sigue adelante y pon la hora: entry.time = Time.now

              -

              Y el estado de animo: entry.mood = :sick

              -

              Y el anuncio en si: entry.fulltext = "I can't believe Mt. Hood was stolen! I am speechless! It was stolen by a giraffe who drove away - in his Cadillac Seville very nonchalant!!"

              -

              Para ver toda la configuración, simplemente escribe en el prompt: entry.

              -
              #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
              -
              -
              -

              Agilizando

              -

              Genial, tu blog es impresionante. Hey, hagamos las cosas algo mas fácil. No querrás - poner la hora asi todas las veces que postees. Solo quieres escribir el titulo, - el contenido y el emoticon rápido, ¿verdad?

              -

              Vamos a agregar un método initialize.

              -
              • class BlogEntry
              • -
              •   def initialize( title, mood, fulltext )
              • -
              •     @time = Time.now
              • -
              •     @title, @mood, @fulltext = title, mood, fulltext
              • -
              •   end
              • -
              • end
              • -
              -

              Una vez que lo hallas escrito, prueba hacer una nueva entrada: BlogEntry.new

              -
              ArgumentError: wrong number of arguments \(0 for 3\).*
              -
              -
              -

              Tu le Has Enseñado al Blog a Rechazar lo Malo

              -

              ¿Viste como usamos dentro de la clase el símbolo arroba? De este modo: @time = Time.now

              -

              Fuera de la clase, usamos accesos (accessors): entry.time = Time.now Pero dentro variables de instancia: @time = Time.now - Son exactamente lo mismo, pero expresado en dos partes diferentes de tu programa.

              -

              tu blog ahora necesita un titulo, estado de ánimo y el post para funcionar. Cuando un nuevo BlogEntry es creado, el método initialize - es usado para chequear cualquier argumento para new. ¡Uh, necesitamos tres argumentos!

              -

              Prueba de nuevo con los tres.

              -

              entry2 -= BlogEntry.new( "I Left my Hoodie on the Mountain!", :confused, "I am -never going back to that mountain and I hope a giraffe steals it." )

              -
              #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
              -
              -
              -

              Una Jirafa No Ha Robado el Sumario #7

              -

              Aha, estas aquí. Y todo en una pieza. Todavía vamos a hacer tu blog realidad, pero hasta entonces, vamos a revisar, ¿bien?

              -
                -
              • Clases. Todo en Ruby es algún tipo de objeto. Las clases explican los objetos. Como ciertos objetos - trabajan. Por ejemplo, haces algunas entradas de blog y estos objetos están explicados en la clase BlogEntry. - En otras palabras: los llamas objetos del tipo BlogEntry.
              • -
              • Accessors son variables adosadas a un objeto que pueden ser usadas fuera del objeto. (entry.time = Time.now)
              • -
              • Variables de instancia son las mismas variables para accesos dentro del objeto. - Como en la definición de un método. (@time = Time.now)
              • -
              -

              Bueno, vamos a envolver las cosas, niño. Aquí esta el ultimo capitulo de la FASCINANTE épica - historia de Try Ruby! Ahora que ya has probado como todo funciona, ¿cómo vas a - usar eso alrededor de la casa y en tu tienda de comestibles? Eres una - gran persona (una de mis favoritas), pero necesitas dirección.

              -

              Vamos a terminar tu blog. Tienes entradas de blog, pero no un blog.

              -

              Pon las entradas en un array: blog = [entry, entry2]

              -
              \[#.BlogEntry:0x[0-9a-f]+.*, #.BlogEntry:0x[0-9a-f]+.*\]
              -
              -
              -

              Todo Se Trata de Combinar Cosas

              -

              Cosas hermosas pueden hacerse de partes simples de Ruby, especialmente - cuando las combinas entre ellas para formar algo nuevo. Aquí tenemos un blog - hecho de un array de clases. Y, en realidad, Ruby realmente hace buenas cosas - con este tipo de criaturas.

              -

              Aquí hay un puñado de cosas que puedes hacer con tu blog array:

              -
              • Querrás ordenar tus entradas de mas reciente a viejas. Puedes hacerlo con:
                - blog.sort_by { |entry| entry.time }.reverse
                Ve sort_by para más explicación.
              • -
              • Si quieres buscar en el blog por cualquier cosa relacionada con "cadillac":
                - blog.find_all { |entry| entry.fulltext.match(/cadillac/i) }
                - Lee mas en find_all - y match - para descubrir como funciona. También: /giraffe/i es un objeto Regexp, usado para concordar palabras.
              • -
              • Y agregar nuevas entradas con blog << new_entry
                - Y aquí la documentación del método <<.
              • -
              -

              Puedes buscar entre la lista de los métodos con los que viene Ruby en ruby-doc.org's core. - Otra buena lista hay en online pickaxe.

              -

              Un método realmente útil (probablemente yo uso esto mas que otra cosa) es map. Escribe: blog.map { |entry| entry.mood }

              -
              \[(:\w+, )+:\w+\]
              -
              -
              -

              Mira Su Cara — La Transformación Ha Comenzado

              -

              El método map recorre un array y reemplaza cada ítem con algo nuevo. ¿Dices que quieres reemplazar cada entrada de tu blog - con el nombre de Bruce Willis?. Hazlo entonces: blog.map { "Bruce Willis" }

              -

              Como el bloque siempre devuelve el string "Bruce Willis", eso es lo que obtienes. En el código que acabas de usar, la entrada entry wfue reemplazada - por solo el entry.mood.

              -

              Ahora, quiero que hagas un popup con las entradas de tu blog. Yo no te voy a - dar todo el código. Solo te voy a dar una parte.

              -
              • blog.each do |entry|
              • -
              •   h2 entry.title
              • -
              •   p entry.fulltext
              • -
              • end
              • -
              -

              Ahora, yo espero que pongas el código del popup alrededor y agregues un titulo con el nombre de tu blog usando h1. Como extra, tienes la hora de cada entrada para mostrar.

              -
              \033\[1;JSm.*popup_make\(.*h1.*h2.*li.*h2.*li.*\)\033\[m.*
              -
              -
              -

              Eres Una Especie de Gurú Web, Tengo Estrellas en Mis Ojos

              -

              Bien, ¡eso es! Este es exactamente el código que puedes usar para escribir tu - propio blog real en Ruby. Si te sientes aventurero, yo chequearía el video de - Rails videos donde muestran a un joven compañero creando un blog en 15 minutos. Solo sientete cómodo y mira.

              -

              Debo mencionar a Rails. Tú has estado aprendiendo el lenguaje Ruby, como - hablarlo. Pero Rails es grupo de librerías (algo asi como la librería de popup - que hemos estado usando.) Es un poderoso conjunto de herramientas para crear - sitios web. Si estas interesado en aprender sobre Rails, yo miraría head - por aquí directamente. ¡Empieza a usar tus habilidades en Ruby apropiadamente!

              -

              Algo que tiene Rails son métodos para manejar fechas fácilmente. Como, prueba: Time.now - 2.weeks

              -
              class Integer; def weeks; self * 7*24*60*60; end; end
              -
              \w+ \w+ \d+ \d{2}:\d{2}:\d{2} .*
              -
              -
              -

              Si Quieres Empezar Poco a Poco

              -

              Si quieres comenzar escribiendo pequeños programas en Ruby para practicar, tengo un proyecto llamado MouseHole - que es una pequeña caja de herramientas en la web para escribir programas cortos en Ruby. Puedes ver aquí algunos - scripts para ver que quiero decir.

              -

              MouseHole no es para escribir sitios web en realidad. Es para escribir - pequeños programas y correrlos dentro del navegador. Como hay un programa block - de notas para MouseHole y un programa que agrega una imagen de un ratón a los - links de la web que linkean a programas de MouseHole.

              -

              Tengo un script de MouseHole dentro de un archivo aquí mismo:
              - print File.read("/MouseHole/flickrpedia.user.rb")

              -
              .*Inserts Wikipedia links for Flickr tags.*
              -
              -
              -

              Sumario #8, El Sumario Hey-Relájate-Lo-Hiciste-Bien

              -

              Esta ultima sección se tomó un momento para relajarse, para darte algunos consejos de como - puedes usar Ruby. Si lo has disfrutado, descarga Ruby e instálalo.

              - -

              Una vez que tengas Ruby instalado, puedes usar Ruby Interactivo ejecutando el comando irb en el prompt de tu sistema. Para mas sobre Irb, esta - The Tiger's Vest para ayudarte.

              -

              Tú realmente mereces una torta doble-capa con doble-doble azúcar glaseado y - un tipo tocando una de esas guitarras que son doble-guitarra. Quiero decir - terminaste, ¡lo hiciste! No hay dudas de eso, ¡eres un gran ser certificado!

              -
              -
              - \ No newline at end of file diff --git a/public/tutorials/intro.html b/public/tutorials/intro.html deleted file mode 100644 index 56c1d1c..0000000 --- a/public/tutorials/intro.html +++ /dev/null @@ -1,680 +0,0 @@ - -
              -

              Using the Prompt

              -

              The blue window above is a Ruby prompt. Type a line of Ruby code, hit Enter - and watch it run!

              -

              For example, try typing some math. Like: 2 + 6

              -
              \d+
              -
              -
              -

              Numbers & Math

              -

              Good! You did a bit of math. See how the answer popped out?

              -

              Ruby recognizes numbers and mathematic symbols. You could try some other math like:

              -
              • 4 * 10
              • -
              • 5 - 12
              • -
              • 40 / 4
              -

              Sure, computers are handy and fast for math. Let's move on. Want to see your name reversed? - Type your first name in quotes like this: "Jimmy"

              -
              "(\w+)"
              -
              -
              -

              Say Your Name Backwards

              -

              Perfect, you've formed a string from the letters of your name. A string - is a set of characters the computer can process.

              -

              Imagine the letters are on a string of - laundry line and the quotes are clothespins holding the ends. The quotes mark the beginning and end.

              -

              To reverse your name, type: "Jimmy".reverse (Don't forget the dot!)

              -
              "(\w+)"
              -
              -
              -

              Counting the Letters

              -

              You have used the reverse method on your name! By enclosing your name in - quotes, you made a string. Then you called the reverse method, which works on strings to flip - all the letters backwards.

              -

              Now, let's see how many letters are in your name: "Jimmy".length

              -
              \d+
              -
              -
              -

              On Repeat

              -

              Now, I'm sure by now you're wondering what any of this is good for. Well, I'm sure you've been to - a website that screamed, Hey, your password is too short! See, some programs - use this simple code.

              -

              Watch this. Let's multiply your name by 5. "Jimmy" * 5

              -
              "(\w+)"
              -
              -
              -

              Hey, Summary #1 Already

              -

              Let's look at what you've learned in the first minute.

              -
                -
              • The prompt. Typing code into the green prompt gives you - an answer from a red prompt. All code gives an answer.
              • -
              • Numbers and strings are Ruby's math and text objects.
              • -
              • Methods. You've used English-language methods like reverse - and symbolic methods like * (the multiplication method.) Methods are action!
              • -
              -

              This is the essence of your learning. Taking simple things, toying with - them and turning them into new things. Feeling comfortable yet? I promise you are.

              -

              Okay, let's do something uncomfortable. Try reversing a number: 40.reverse

              -
              NoMethodError: undefined method `reverse' for (\d+):Fixnum
              -
              -
              -

              Stop, You're Barking Mad!

              -

              You can't reverse the number forty. I guess you can hold your monitor up to the - mirror, but reversing a number just doesn't make sense. Ruby has tossed an error - message. Ruby is telling you there is no method reverse for numbers.

              -

              Maybe if you turn it into a string: 40.to_s.reverse.

              -
              \"(\d+)\"
              -
              -
              -

              Boys are Different From Girls

              -

              And numbers are different from strings. While you can use methods on any object - in Ruby, some methods only work on certain types of things. But you can always - convert between different types using Ruby's "to" methods.

              -
              • to_s converts things to strings.
              • -
              • to_i converts things to integers (numbers.)
              • -
              • to_a converts things to arrays.
              • -
              -

              What are arrays?! They are lists. Type in a pair of brackets: [].

              -
              \[\]
              -
              -
              -

              Standing in Line

              -

              Great, that's an empty list. Lists store things in order. - Like standing in line for popcorn. You are behind someone and you wouldn't - dream of pushing them aside, right? And the guy behind you, you've got a - close eye on him, right?

              -

              Here's a list for you. Lottery numbers: [12, 47, 35].

              -
              \[(\d+(, )?){2,}\]
              -
              -
              -

              One Raises Its Hand

              -

              A list of lottery numbers. Which one is the highest?

              -

              Try: [12, 47, 35].max.

              -
              (\d+)
              -
              -
              -

              Tucking a List Away

              -

              Good, good. But it's annoying to have to retype that list, isn't it?

              -

              Let's save our numbers inside a ticket like so: ticket = [12, 47, 35]

              -
              \[(\d+(, )?){2,}\]
              -
              -
              -

              Now Type Ticket

              -

              Now, type: ticket

              -
              \[(\d+(, )?){2,}\]
              -
              -
              -

              Saved, Tucked Away

              -

              Fantastic! You've hung on to your lotto numbers, tucking them away inside a - variable called ticket.

              -

              Let's put your lotto numbers in order, how about? Use: ticket.sort!

              -
              \[(\d+(, )?){2,}\]
              -
              -
              -

              Summary #2 is Upon Us

              -

              You had a list. You sorted the list. The ticket variable is now changed.

              -

              Did you notice that the sort! method has a big, bright exclamation at the end? - A lot of times Ruby methods shout like that if they alter the variable for good. It's nothin - special, just a mark.

              -

              Now, look how your second minute went:

              -
                -
              • Errors. If you try to reverse a number or do anything fishy, - Ruby will skip the prompt and tell you so.
              • -
              • Arrays are lists for storing things in order.
              • -
              • Variables save a thing and give it a name. You used the - equals sign to do this.
                Like: ticket = [14, 37, 18].
              • -
              -

              In all there are eight lessons. You are two-eighths of the way there! - This is simple stuff, don't you think? Good stuff up ahead.

              -

              Let's change directions for a moment. I've stuffed a bit of poetry for you in - a certain variable. Take a look. Type print poem

              -
              poem = "My toast has flown from my hand\nAnd my toast has gone to the -moon.\nBut when I saw it on television,\nPlanting our flag on Halley's -comet,\nMore still did I want to eat it.\n"
              -
              My toast (.+)
              -
              -
              -

              Sadly, You Hate Toast Poetry

              -

              Look, it's okay. You don't have to like it. Hack it up, be my guest.

              -

              Instead of toast, go for a melon or something. Try this: poem['toast'] = 'honeydew'

              -

              And then type print poem by itself to see the new poem.

              -
              My honey(.+)
              -
              -
              -

              Ready, Aim

              -

              The square brackets you just used are very common in Ruby. Remember, you typed: poem['toast'] = 'honeydew'. That box with the word toast has a square bracket on each side, see?

              -

              The -two brackets are like sights used to line up a target. Exactly. These -brackets mean, "I am looking for ____." Ready, aim. Here you're looking -for toast and swapping it out with fruit.

              -

              Here's a question: what happens when we reverse this whole poem? poem.reverse -

              "\\n.ti tae ot (.+)"
              -
              -
              -

              Too Much Reversal

              -

              Okay, sure. So the whole poem's been turned backwards, letter-by-letter. I really want to just - reverse the lines, though. Move the last line up to first and the first line down to last. Backwards, but not - that backwards.

              -

              Here's how: poem.lines.to_a.reverse

              -
              \["More still did I(.+)"\]
              -
              -
              -

              Ringlets of Chained Methods

              -

              So what do you see? What happened there? You typed poem.lines.to_a.reverse and what happened?

              -

              Two things happened. You turned the poem into a -list using lines.to_a. lines decides the way -the string is split up, then to_a converted it into an -Array. (To array.) Different methods, such -as bytes and chars can be used in place -of lines. By using lines, ruby will return each line of the poem.

              -

              Then, you reversed that list. You had each line. You reversed them. That's it.

              -

              Let's tack one more method on the end there: print poem.lines.to_a.reverse.join -

              More still did I(.+)
              -
              -
              -

              Of All the Summaries, #3 is Here Now

              -

              Good show, my friend! The join method took that list of reversed lines and put them - together into a string. (Sure, you could have also just used to_s.)

              -

              Review time.

              -
                -
              • Exclamations. Methods may have exclamations (and also question marks) - in their name. No big deal. Try: poem.include? "my hand"
              • -
              • Square brackets. Target and find things. Search and replace.
              • -
              • Chaining methods lets you get a lot more done. Break up a poem, - reverse it, reassemble it: poem.lines.to_a.reverse.join
              • -
              -

              At this point, you may want to tinker with the poem a bit more. A complete list of all - the String methods is - - here. - Go ahead and try a few (such as poem.downcase or poem.delete.)

              -

              When you're ready to move on, type: books = {}

              -
              \{\}
              -
              -
              -

              A Wee Blank Book

              -

              You've made an empty hash. (Also known as: an empty dictionary.)

              -

              We're going to stuff some miniature book reviews in this hash. Here's our rating system:

              -
                -
              • :splendid → a masterpiece.
              • -
              • :quite_good → enjoyed, sure, yes.
              • -
              • :mediocre → equal parts great and terrible.
              • -
              • :quite_not_good → notably bad.
              • -
              • :abyssmal → steaming wreck.
              • -
              -

              To rate a book, put the title in square brackets and put the rating after the equals.

              -

              For example: books["Gravity's Rainbow"] = :splendid

              -
              :\w+
              -
              -
              -

              More Bite-Size Reviews

              -

              Keep going, fill it up with reviews. And, if you want to see the whole list, - just type: books

              -

              Again, the ratings are: :splendid, :quite_good, :mediocre, - :quite_not_good, and :abyssmal.

              -

              These ratings are not strings. When you place a colon in front of a simple word, you get a - symbol. Symbols are cheaper than strings (in terms of computer memory.) If - you use a word over and over in your program, use a symbol. Rather than having thousands of - copies of that word in memory, the computer will store the symbol only once.

              -

              Once you've got three or four books in - there, type: books.length.

              -
              [3-9]
              -
              -
              -

              Wait, Did I Like Gravity's Rainbow?

              -

              See, the length method works on strings, list and hashes. One great thing about - Ruby is that names are often reused, which means fewer names you need to remember.

              -

              If you'd like to look up one of your old reviews, again put the title in the square. But leave off - the equals.

              -

              Just like this: books["Gravity's Rainbow"]

              -
              :\w+
              -
              -
              -

              Hashes as Pairs

              -

              Keep in mind that hashes won't keep things in order. That's not their job. It'll just pair up two - things: a key and a value. In your reviews, the key is the book's - title and the value is the rating.

              -

              If you want to just see the titles of the books you've reviewed: books.keys

              -
              \[".*"\]
              -
              -
              -

              Are You Harsh?

              -

              So are you giving out harsh, unfair reviews? Let's keep score with this hash:
              ratings = Hash.new {0}

              -

              Then, okay, now let's count up your reviews. Just stay with me. Type:
              - books.values.each { |rate| ratings[rate] += 1 }

              -

              (The straight line in the code is the pipe character, probably located right above the - Enter key on your keyboard.)

              -
              \[:.+\]
              -
              -
              -

              A Tally

              -

              Great, wow! You've made a scorecard of your ratings. Type ratings to see the count. - This new hash shows a rating and then the number of times you've given that rating.

              -

              One of the amazing new things we've just used is a block. We're going to - explore these more in the next summary. But, basically, a block is a bit of Ruby code surrounded - by curly braces.

              -

              Let's try another block: 5.times { print "Odelay!" }

              -
              Odelay!Od.*
              -
              -
              -

              Now Arriving at Summary #4

              -

              Blocks are always attached to methods. Like the times method, which takes the - block and runs the code over and over. (In this case: five times.)

              -

              This last lesson was a bit longer. You've probably used up three minutes learning about:

              -
                -
              • Hashes. The little dictionary with the curly pages: {}.
              • -
              • Symbols. Tiny, efficient code words with a colon: :splendid.
              • -
              • Blocks. Chunks of code which can be tacked on to many of Ruby's methods. Here's the - code you used to build a scorecard:
                books.values.each { |rate| ratings[rate] += 1 }.
              • -
              -

              On your computer, you probably have a lot of different files. Files with pictures in them, - files with programs in them. And files are often organized into folders, also called: - directories.

              -

              I've prepared a few directories for you. Take a look: - Dir.entries "/"

              -
              \["\.", .+\]
              -
              -
              -

              The Private Collection of Dr. Dir

              -

              You've just listed out everything in the top directory. The root directory, indicated - by a single slash. Containing some programs and other tutorials and such.

              -

              So, what is the Dir.entries method? Well, it's just a method, right? - entries is a method called on the Dir variable. - And Dir has a collection of methods for checking out file directories.

              -

              One other little thing we haven't really talked about openly. Method arguments, highlighted in green.

              -
                -
              • Dir.entries "/": Anything listed after a method - is considered an attachment.
              • -
              • print poem: See, print is an ordinary method. And the - poem is attached. To be printed.
              • -
              • print "pre", "event", "ual", "ism" has several arguments, with commas - between them.
              • -
              -

              To list just the text files in that directory: Dir["/*.txt"]

              -
              \["\/comics\.txt"\]
              -
              -
              -

              Come, Read Comics With Me

              -

              The Dir[] method is like entries but you search for files - with wildcard characters. Here, we see those square brackets again! Notice how - they still mean, "I am looking for _____?"

              -

              More specifically: "I am looking for files which end with .txt."

              -

              Let's crack open this comics file, then. Here's the way:
              - print File.read("/comics.txt")

              -
              Achewood.+
              -
              -
              -

              Mi Comicas, Tu Comicas

              -

              All right! We can start to use files to store things. This is great because normally when - we exit Ruby, all our variables will be gone. Ruby, by itself, forgets these things. - But if we save things in files, we can read those files in future Ruby escapades.

              -

              Hey, and guess what? The /Home directory is yours! I gave it to you! I am generous! Let's make a copy of the comics file.

              -

              You'll want to: FileUtils.copy('/comics.txt', '/Home/comics.txt') -

              If you've already created the file, use File.delete('/Home/comics.txt') to trash it.

              -
              nil
              -
              -
              -

              Your Own Turf

              -

              Okay, you've got a copy. Check it: Dir["/Home/*.txt"]

              -

              To add your own comic to the list, let's open the file in append mode.

              -

              Start like this: File.open("/Home/comics.txt", "a") do |f|.

              -
              ..
              -
              -
              -

              And Now For the Startling Conclusion

              -

              So your prompt has changed. See that? Your prompt is a double dot now.

              -

              In this tutorial, this prompt means that Ruby is expecting you to type more. - As you type in the lines of Ruby code, the double dots will continue until you - are completely finished.

              -

              Hot tip: If you want to stop working on the code and break out of the double dots, use the reset - command. If you want to go the previous page of the tutorial, use the back command.

              -

              Here's your code. You've already typed the first line, so just enter the second line. (The \n - is an Enter character.

              -
              • File.open("/Home/comics.txt", "a") do |f|
              • -
              •   f << "Cat and Girl: http://catandgirl.com/\n"
              • -
              • end
              • -
              -

              And, since you're getting so advanced and capable here, one other tip: you can use the up and down arrow keys to - edit your old commands or run them again.

              -
              ..
              -
              -
              -

              Ruby Sits Still

              -

              That last line adds the Cat and Girl comic to the list, but Ruby's going to wait until you're totally finished to - take action.

              -

              Now, to finish the code you've started. You opened a new block when you typed do. - So far the blocks we've seen have used curly braces. This time we'll be using do and end instead - of curly braces. A lot of Rubyists will use do...end when the block goes on for many lines.

              -

              Let's get that block finished now, with: end

              -
              • File.open("/Home/comics.txt", "a") do |f|
              • -
              •   f << "Cat and Girl: http://catandgirl.com/\n"
              • -
              • end
              • -
              -
              #.File:/Home/comics\.txt \(closed\).
              -
              -
              -

              The Clock Nailed To the File

              -

              Good, good! You've added that new comic to the file. You can see for yourself: print File.read("/Home/comics.txt")

              -

              What time was it when you changed the file? Let's check. Type: File.mtime("/Home/comics.txt")

              -
              \d{4}-\d+-\d+ \d{2}:\d{2}:\d{2} [+-]\d{4}
              -
              -
              -

              Just the Hour Hand

              -

              Great, there's the time. The precise time exactly when you added to the file. The mtime gives you a Ruby Time object.

              -

              If you want to check just what hour it was, hit the up arrow key and change the line to: File.mtime("/Home/comics.txt").hour

              -
              \d+
              -
              -
              -

              Hallo, Who's There? And Summary #5 Waves Its Hat!

              -

              Well done, well done, well done, well done! Truly, truly, truly, truly, truuuuuuuuly!

              -

              Here's the last few minutes of your life in review:

              -
                -
              • Files. What more can be said? Lots of methods for editing files and lookin around in directories.
              • -
              • Arguments. Arguments are a list of things sent into a method. With commas between.
              • -
              • We also spoke about do and end which are another way to make a block.
              • -
              -

              You totally know how to use Ruby now. I mean you've got down the essentials. You just need to keep learning more methods and - try out more complex blocks.

              -

              But there's one side of Ruby we haven't settled. Making your own methods and classes.

              -

              Ahem! Let's get it over with then.

              -

              Start with: def load_comics( path )

              -
              ..
              -
              -
              -

              In Ruby, Def Leppard Means Define Leppard (a Method)!

              -

              Hey, okay, you done it. You're making your own method. You started with def, followed by the name of the method. - And a list of arguments which the method will need. This isn't too scary and dangerous!

              -

              All we have to do is fill it up with Ruby and finish it up with end.

              -

              Here's the code:

              -
              • def load_comics( path )
              • -
              •   comics = {}
              • -
              •   File.foreach(path) do |line|
              • -
              •     name, url = line.split(': ')
              • -
              •     comics[name] = url.strip
              • -
              •   end
              • -
              •   comics
              • -
              • end
              • -
              -

              No need to indent, if you don't want. I just do that to make it read easier.

              -
              nil
              -
              -
              -

              The Ripened Fruit of Your Own Creation

              -

              A new method is born. Let us use it: comics = load_comics('/comics.txt')

              -

              If you have a problem, you might have mistyped. Use the back command and try again.

              -
              \{.*"Achewood"=."http://achewood.com/".*\}
              -
              -
              -

              Hey, Cool, a Comics Thing

              -

              In your Ruby window above, look at the code you've typed for the load_comics method. What is happening? You're - passing in the path variable and you're getting back the comics variable. Ruby lets the comics - hash trickle out the end of the method.

              -

              A number of methods were used to get the job done. See if you can spot them.

              -
              • File.foreach is a method which opens a file and hands each line to the block. The line - variable inside the do...end block took turns with each line in the file.
              • -
              • split is a method for strings, which breaks the string up into an array. An axe is laid on the colon - and the line is chopped in half, giving us the url and name for each comic.
              • -
              • strip removes extra spaces around the name. Just in case.
              • -
              -

              Right on. Bravo. You've got the comics in a Ruby hash. But what now? What good is this really?

              -

              Let's make a page of links. How about that? I went ahead and loaded a little library I've made for you.

              -

              Type: next. This is temporary as I updates new lessons.

              -
              true
              -
              -
              -

              Browser Puppetry

              -

              Excellent, you've loaded the popup library. It's saved in a file in the Libraries folder. See: Dir["/Libraries/*"]

              -

              The popup library contains a bunch of methods I've written which let you control a popup here on the Try Ruby site.

              -

              Here, try this: Popup.goto "http://google.com/"

              -
              \033\[1;JSm.*popup_goto\(.*\)\033\[m.*
              -
              -
              -

              Making Links and Spinning Webs

              -

              Our own lovely, little popup to manipulate. You can also fill it with your own goodies. We'll start small:

              -
              • Popup.make {
              • -
              •   h1 "My Links"
              • -
              •   link "Go to Google", "http://google.com/"
              • -
              • }
              • -
              -

              The term h1 (h-one) means a level-one header. In HTML, this is the largest size of header.

              -
              \033\[1;JSm.*popup_make\(.*h1.*a href.*\)\033\[m.*
              -
              -
              -

              Popups Are So Easy, It's Crazy

              -

              Looks good, you did it perfectly, just as you were asked. Let's make a list then.

              -

              Here's how you make a list with the popup library:

              -
              • Popup.make do
              • -
              •   h1 "Things To Do"
              • -
              •   list do
              • -
              •     p "Try out Ruby"
              • -
              •     p "Ride a tiger"
              • -
              •     p "(down River Euphrates)"
              • -
              •   end
              • -
              • end
              • -
              -

              The p method is short for "paragraph".

              -
              \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*li.*\)\033\[m.*
              -
              -
              -

              Spread the Comics on the Table

              -

              Okay, this is coming along wonderfully. This is simple stuff, but keep in mind that you didn't know any Ruby whatsoever just fifteen minutes ago!

              -

              Last -step. Let's tie it all together, you know? Let's make it chime together -like a very nice set of glistening chimes on the beach in the -maginificent sunlight!

              -

              Make sure the comics are loaded: comics = load_comics( '/comics.txt' )

              -

              Now, let's make a list of the links to each comic:

              -
              • Popup.make do
              • -
              •   h1 "Comics on the Web"
              • -
              •   list do
              • -
              •     comics.each do |name, url|
              • -
              •       link name, url
              • -
              •     end
              • -
              •   end
              • -
              • end
              • -
              -

              You can click on the links and read the comics in the little window even! Smashing!

              -
              \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*a href.*li.*a href.*\)\033\[m.*
              -
              -
              -

              Summary #6 Which Means You've Come So Far

              -

              You're a level six Ruby cleric. I mean what a great job you've done. Let's review:

              -
                -
              • You added your own method with def and you used that load_comics method several times.
              • -
              • Libraries. You used the require method to load the popup library.
                By typing: require 'popup'
              • -
              • And if that wasn't enough, you made your own web page from a list of comics in a file. You made a real program!
              • -
              -

              So -what could possibly be next? What could you possibly have to learn now? -Ha, this is the best part. You've come such a long way that we're going -to uncover classes. For two more short lessons and you're done.

              -

              Earlier, we created a hash like this: Hash.new Try it.

              -
              \{\}
              -
              -
              -

              Not a School Class, a Working Class

              -

              You see, the empty curly braces {} is a shortcut for Hash.new. The new -method is used to make objects of a certain class. (Think "class" as in -"working class" — a specific group of objects which are similar, have -the same jobs, the same shirts.)

              -

              Ask yourself this: How would I make a blog in Ruby? -Where would you start? Well, you might store your blog entries in a -file, right? But how would you keep track of the title of the entry and -the time it was posted? And when you loaded the file, how would it look -in Ruby? Would it be a Hash? Or an Array? Or an Array of Arrays? Or -something else?

              I really think you'll want to use a class. You are already familiar with many classes: Hash, Array, String.

              -

              Let's make a new class: class BlogEntry.

              -
              ..
              -
              -
              -

              The Stuff Blogs are Made of

              -

              You've opened up a new BlogEntry class. What is your blog entry made of? A title, sure. Also, a time when the entry was posted. The - full text of the entry.

              -

              We'll do a mood setting, too, just like LiveJournal. The Internet has really brought back stick people and smileys - out of bankruptcy. Emote!

              -

              Okay, so you've got the first line of the class, here's the rest:

              -
              • class BlogEntry
              • -
              •   attr_accessor :title, :time, :fulltext, :mood
              • -
              • end
              • -
              -
              nil
              -
              -
              -

              Accessors Are the Dangling Limbs

              -

              Hey, good class, man. You've got a new BlogEntry class. To start an entry:
              entry = BlogEntry.new.

              -

              In the class definition, you used a method called attr_accessor. There are many attribute methods like - this which add little settings to classes. These attributes are just variables attached to a class.

              -

              Think -of it this way. A class is like a person. That star-shaped human thing -out there. And the attributes are the dangling limbs, the different -parts that make up a body.

              -

              To set the title of your entry: entry.title = "Today Mt. Hood Was Stolen!"

              -
              ".+"
              -
              -
              -

              An Object, That Neat Little Package

              -

              Go ahead and set the post time: entry.time = Time.now

              -

              And the mood: entry.mood = :sick

              -

              And the post itself: entry.fulltext = "I can't believe Mt. Hood was stolen! I am speechless! It was stolen by a giraffe who drove away - in his Cadillac Seville very nonchalant!!"

              -

              To see all your settings, just type at the prompt: entry.

              -
              #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
              -
              -
              -

              Quickening it Up

              -

              Cool, -you're blog is awesome. Hey, let's make things a bit easier on you. -You're not going to want to set the time like that every time you post. -You just want to type in the title and the entry and the mood quickly, -right?

              -

              Let's add an initialize method.

              -
              • class BlogEntry
              • -
              •   def initialize( title, mood, fulltext )
              • -
              •     @time = Time.now
              • -
              •     @title, @mood, @fulltext = title, mood, fulltext
              • -
              •   end
              • -
              • end
              • -
              -

              Once you've got that typed in, try making a new entry: BlogEntry.new

              -
              ArgumentError: wrong number of arguments \(0 for 3\).*
              -
              -
              -

              You've Taught Your Blog to Reject Worthless Things

              -

              Did you see how inside the class we used the at-symbols? Like this: @time = Time.now

              -

              Outside the class, we use accessors: entry.time = Time.now But inside we use instance variables: @time = Time.now - They're the exact same thing, but expressed in two different places of your program.

              -

              Your blog now needs a title, a mood and a post in order to work. When a new BlogEntry is created, the initialize method - is used to check for any arguments to new. Uh, we need three arguments!

              -

              Try it again with all three.

              -

              entry2 -= BlogEntry.new( "I Left my Hoodie on the Mountain!", :confused, "I am -never going back to that mountain and I hope a giraffe steals it." )

              -
              #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
              -
              -
              -

              A Giraffe Has Not Stolen Summary #7

              -

              Aha, you're here. And all in one piece. We're still going to make your blog real, but until then, let's review, okay?

              -
                -
              • Classes. Everything in Ruby is some kind of object. Classes explain objects. How a certain object works. - For example, you made a few blog entry objects and these objects are explained in the BlogEntry class. - In other words: you call them BlogEntry objects.
              • -
              • Accessors are variables attached to an object which can be used outside the object. (entry.time = Time.now)
              • -
              • Instance variables are the same variables you're using for accessors when inside the object. - Like in a method definition. (@time = Time.now)
              • -
              -

              Okay, -let's wrap things up, kid. Here's the last chapter of the GRIPPING epic -story of Try Ruby! Now that you've got a taste of how it all works, how -are you going to use it around the house and in your grocer's freezer? -You're a great person (one of my favorites), but you need guidance.

              -

              Let's finish your blog. You have blog entries, but no actual blog.

              -

              Put the entries into an array: blog = [entry, entry2]

              -
              \[#.BlogEntry:0x[0-9a-f]+.*, #.BlogEntry:0x[0-9a-f]+.*\]
              -
              -
              -

              It's All About Combining Things

              -

              Some -beautiful things can be done with the simple parts of Ruby, especially -when you combine them together into new things. Here we've got a blog -made of an array of classes. And, actually, Ruby really does good with -this kind of creature.

              -

              Here's a few things you can do with your array blog:

              -
              • You'll want to sort your entries from newest to oldest. You can do this with:
                - blog.sort_by { |entry| entry.time }.reverse
                See the sort_by explanation for more.
              • -
              • If you want to search your blog for anything related to "cadillac":
                - blog.find_all { |entry| entry.fulltext.match(/cadillac/i) }
                - Read all about find_all - and match - to figure out how that works. Also: the slashy /giraffe/i is a Regexp object, used for matching words.
              • -
              • Add new entries with blog << new_entry
                - And check out the << method documentation.
              • -
              -

              You can browse a list of all Ruby's built-in methods at ruby-doc.org's core list. - Another good list is at the online pickaxe.

              -

              One really useful method (I probably use this more than anything else) is map. Type: blog.map { |entry| entry.mood }

              -
              \[(:\w+, )+:\w+\]
              -
              -
              -

              Look at His Face — The Transformation Has Begun

              -

              The map method cycles through an array and replaces each item with something new. Say you wanted to replace each of your blog entries - with the name Bruce Willis. Do it so: blog.map { "Bruce Willis" }

              -

              Since the block always returns the string "Bruce Willis", that's what you get. In the code you just used, the entry was swapped out - for only the entry.mood.

              -

              Now, -I want you to make a popup with your blog entries. I'm not going to -give you all of the code. I'm just going to give you part of it.

              -
              • blog.each do |entry|
              • -
              •   h2 entry.title
              • -
              •   p entry.fulltext
              • -
              • end
              • -
              -

              Now, I expect you to put the popup code around it and add an h1 title with the name of your blog. For extra haroompf, have the time of each entry display.

              -
              \033\[1;JSm.*popup_make\(.*h1.*h2.*li.*h2.*li.*\)\033\[m.*
              -
              -
              -

              You are Some Kind of Web Guru, I Have Stars in My Eyes

              -

              Good, -that's it! This is exactly the code you can use to write your own real -Ruby blog. If you're feeling adventurous, I'd check out the Rails videos which show a swift young fellow creating a blog in 15 minutes. You just sit back and watch.

              -

              I -should mention Rails. You have been learning the Ruby language, how to -speak it. But Rails is a bunch of libraries (sort of like the popup -library we've been using.) It's a very powerful toolkit for building -websites. If you're interested in learning about Rails, I would head - over there right away. Start using your Ruby skills proper!

              -

              One thing Rails has is easy methods for dates. Like, try: Time.now - 2.weeks

              -
              class Integer; def weeks; self * 7*24*60*60; end; end
              -
              \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-+]\d{4}
              -
              -
              -

              If You Want to Start Small

              -

              If you'd like to start writing little Ruby programs just to practice, I have a project called MouseHole - which is a little web toolkit for writing short Ruby programs. You can look over a few - scripts to see what I mean.

              -

              MouseHole -isn't for writing web sites really. It's just for writing little -programs you run inside your browser. Like there's a notepad program -for MouseHole and a program which adds a mouse picture next to links on -the web which link to MouseHole programs.

              -

              I've got a MouseHole script inside a file here:
              - print File.read("/MouseHole/flickrpedia.user.rb")

              -
              .*Inserts Wikipedia links for Flickr tags.*
              -
              -
              -

              Summary #8, The Hey-Relax-You-Did-Good Summary

              -

              This last section took a moment to wind down, to give you some pointers as to how you can use Ruby. If you enjoyed yourself, - download Ruby and install it.

              - -

              Once you have Ruby installed, you can use Interactive Ruby by running irb on your system's prompt. For more on Irb, - there's The Tiger's Vest to help you.

              -

              You -really deserve a double-layer cake with double-double frosting and a -guy playing one of those guitars that's a double guitar. I mean you -finished, you really did! No doubt about it, you're a certified -red-blooded smartiac!

              -
              -
              - - diff --git a/public/tutorials/intro.html.broken b/public/tutorials/intro.html.broken deleted file mode 100755 index 5a6c27c..0000000 --- a/public/tutorials/intro.html.broken +++ /dev/null @@ -1,638 +0,0 @@ - -
              -

              Using the Prompt

              -

              The blue window above is a Ruby prompt. Type a line of Ruby code, hit Enter - and watch it run!

              -

              For example, try typing some math. Like: 2 + 6

              -
              \d+
              -
              -
              -

              Numbers & Math

              -

              Good! You did a bit of math. See how the answer popped out?

              -

              Ruby recognizes numbers and mathematic symbols. You could try some other math like:

              -
              • 4 * 10
              • -
              • 5 - 12
              • -
              • 40 / 4
              -

              Sure, computers are handy and fast for math. Let's move on. Want to see your name reversed? - Type your first name in quotes like this: "Jimmy"

              -
              "(\w+)"
              -
              -
              -

              Say Your Name Backwards

              -

              Perfect, you've formed a string from the letters of your name. A string - is a set of characters the computer can process.

              -

              Imagine the letters are on a string of - laundry line and the quotes are clothespins holding the ends. The quotes mark the beginning and end.

              -

              To reverse your name, type: "Jimmy".reverse (Don't forget the dot!)

              -
              "(\w+)"
              -
              -
              -

              Counting the Letters

              -

              You have used the reverse method on your name! By enclosing your name in - quotes, you made a string. Then you called the reverse method, which works on strings to flip - all the letters backwards.

              -

              Now, let's see how many letters are in your name: "Jimmy".length

              -
              \d+
              -
              -
              -

              On Repeat

              -

              Now, I'm sure by now you're wondering what any of this is good for. Well, I'm sure you've been to - a website that screamed, Hey, your password is too short! See, some programs - use this simple code.

              -

              Watch this. Let's multiply your name by 5. "Jimmy" * 5

              -
              "(\w+)"
              -
              -
              -

              Hey, Summary #1 Already

              -

              Let's look at what you've learned in the first minute.

              -
                -
              • The prompt. Typing code into the green prompt gives you - an answer from a red prompt. All code gives an answer.
              • -
              • Numbers and strings are Ruby's math and text objects.
              • -
              • Methods. You've used English-language methods like reverse - and symbolic methods like * (the multiplication method.) Methods are action!
              • -
              -

              This is the essence of your learning. Taking simple things, toying with - them and turning them into new things. Feeling comfortable yet? I promise you are.

              -

              Okay, let's do something uncomfortable. Try reversing a number: 40.reverse

              -
              NoMethodError: undefined method `reverse' for (\d+):Fixnum
              -
              -
              -

              Stop, You're Barking Mad!

              -

              You can't reverse the number forty. I guess you can hold your monitor up to the - mirror, but reversing a number just doesn't make sense. Ruby has tossed an error - message. Ruby is telling you there is no method reverse for numbers.

              -

              Maybe if you turn it into a string: 40.to_s.reverse.

              -
              \"(\d+)\"
              -
              -
              -

              Boys are Different From Girls

              -

              And numbers are different from strings. While you can use methods on any object - in Ruby, some methods only work on certain types of things. But you can always - convert between different types using Ruby's "to" methods.

              -
              • to_s converts things to strings.
              • -
              • to_i converts things to integers (numbers.)
              • -
              • to_a converts things to arrays.
              • -
              -

              What are arrays?! They are lists. Type in a pair of brackets: [].

              -
              \[\]
              -
              -
              -

              Standing in Line

              -

              Great, that's an empty list. Lists store things in order. - Like standing in line for popcorn. You are behind someone and you wouldn't - dream of pushing them aside, right? And the guy behind you, you've got a - close eye on him, right?

              -

              Here's a list for you. Lottery numbers: [12, 47, 35].

              -
              \[(\d+(, )?){2,}\]
              -
              -
              -

              One Raises Its Hand

              -

              A list of lottery numbers. Which one is the highest?

              -

              Try: [12, 47, 35].max.

              -
              (\d+)
              -
              -
              -

              Tucking a List Away

              -

              Good, good. But it's annoying to have to retype that list, isn't it?

              -

              Let's save our numbers inside a ticket like so: ticket = [12, 47, 35]

              -
              \[(\d+(, )?){2,}\]
              -
              -
              -

              Now Type Ticket

              -

              Now, type: ticket

              -
              \[(\d+(, )?){2,}\]
              -
              -
              -

              Saved, Tucked Away

              -

              Fantastic! You've hung on to your lotto numbers, tucking them away inside a - variable called ticket.

              -

              Let's put your lotto numbers in order, how about? Use: ticket.sort!

              -
              \[(\d+(, )?){2,}\]
              -
              -
              -

              Summary #2 is Upon Us

              -

              You had a list. You sorted the list. The ticket variable is now changed.

              -

              Did you notice that the sort! method has a big, bright exclamation at the end? - A lot of times Ruby methods shout like that if they alter the variable for good. It's nothin - special, just a mark.

              -

              Now, look how your second minute went:

              -
                -
              • Errors. If you try to reverse a number or do anything fishy, - Ruby will skip the prompt and tell you so.
              • -
              • Arrays are lists for storing things in order.
              • -
              • Variables save a thing and give it a name. You used the - equals sign to do this.
                Like: ticket = [14, 37, 18].
              • -
              -

              In all there are eight lessons. You are two-eighths of the way there! - This is simple stuff, don't you think? Good stuff up ahead.

              -

              Let's change directions for a moment. I've stuffed a bit of poetry for you in - a certain variable. Take a look. Type print poem

              -
              poem = "My toast has flown from my hand\nAnd my toast has gone to the -moon.\nBut when I saw it on television,\nPlanting our flag on Halley's -comet,\nMore still did I want to eat it.\n"
              -
              My toast (.+)
              -
              -
              -

              Sadly, You Hate Toast Poetry

              -

              Look, it's okay. You don't have to like it. Hack it up, be my guest.

              -

              Instead of toast, go for a melon or something. Try this: poem['toast'] = 'honeydew'

              -

              And then type print poem by itself to see the new poem.

              -
              My honey(.+)
              -
              -
              -

              Ready, Aim

              -

              The square brackets you just used are very common in Ruby. Remember, you typed: poem['toast'] = 'honeydew'. That box with the word toast has a square bracket on each side, see?

              -

              The -two brackets are like sights used to line up a target. Exactly. These -brackets mean, "I am looking for ____." Ready, aim. Here you're looking -for toast and swapping it out with fruit.

              -

              Here's a question: what happens when we reverse this whole poem? poem.reverse -

              "\\n.ti tae ot (.+)"
              -
              -
              -

              Too Much Reversal

              -

              Okay, sure. So the whole poem's been turned backwards, letter-by-letter. I really want to just - reverse the lines, though. Move the last line up to first and the first line down to last. Backwards, but not - that backwards.

              -

              Here's how: poem.lines.to_a.reverse

              -
              \["More still did I(.+)"\]
              -
              -
              -

              Ringlets of Chained Methods

              -

              So what do you see? What happened there? You typed poem.lines.to_a.reverse and what happened?

              -

              Two things happened. You turned the poem into a -list using lines.to_a. lines decides the way -the string is split up, then to_a converted it into an -Array. (To array.) Different methods, such -as bytes and chars can be used in place -of lines. By using lines, ruby will return each line of the poem.

              -

              Then, you reversed that list. You had each line. You reversed them. That's it.

              -

              Let's tack one more method on the end there: print poem.lines.to_a.reverse.join -

              More still did I(.+)
              -
              -
              -

              Of All the Summaries, #3 is Here Now

              -

              Good show, my friend! The join method took that list of reversed lines and put them - together into a string. (Sure, you could have also just used to_s.)

              -

              Review time.

              -
                -
              • Exclamations. Methods may have exclamations (and also question marks) - in their name. No big deal. Try: poem.include? "my hand"
              • -
              • Square brackets. Target and find things. Search and replace.
              • -
              • Chaining methods lets you get a lot more done. Break up a poem, - reverse it, reassemble it: poem.lines.to_a.reverse.join
              • -
              -

              At this point, you may want to tinker with the poem a bit more. A complete list of all - the String methods is - - here. - Go ahead and try a few (such as poem.downcase or poem.delete.)

              -

              When you're ready to move on, type: books = {}

              -
              \{\}
              -
              -
              -

              A Wee Blank Book

              -

              You've made an empty hash. (Also known as: an empty dictionary.)

              -

              We're going to stuff some miniature book reviews in this hash. Here's our rating system:

              -
                -
              • :splendid → a masterpiece.
              • -
              • :quite_good → enjoyed, sure, yes.
              • -
              • :mediocre → equal parts great and terrible.
              • -
              • :quite_not_good → notably bad.
              • -
              • :abyssmal → steaming wreck.
              • -
              -

              To rate a book, put the title in square brackets and put the rating after the equals.

              -

              For example: books["Gravity's Rainbow"] = :splendid

              -
              :\w+
              -
              -
              -

              More Bite-Size Reviews

              -

              Keep going, fill it up with reviews. And, if you want to see the whole list, - just type: books

              -

              Again, the ratings are: :splendid, :quite_good, :mediocre, - :quite_not_good, and :abyssmal.

              -

              These ratings are not strings. When you place a colon in front of a simple word, you get a - symbol. Symbols are cheaper than strings (in terms of computer memory.) If - you use a word over and over in your program, use a symbol. Rather than having thousands of - copies of that word in memory, the computer will store the symbol only once.

              -

              Once you've got three or four books in - there, type: books.length.

              -
              [3-9]
              -
              -
              -

              Wait, Did I Like Gravity's Rainbow?

              -

              See, the length method works on strings, list and hashes. One great thing about - Ruby is that names are often reused, which means fewer names you need to remember.

              -

              If you'd like to look up one of your old reviews, again put the title in the square. But leave off - the equals.

              -

              Just like this: books["Gravity's Rainbow"]

              -
              :\w+
              -
              -
              -

              Hashes as Pairs

              -

              Keep in mind that hashes won't keep things in order. That's not their job. It'll just pair up two - things: a key and a value. In your reviews, the key is the book's - title and the value is the rating.

              -

              If you want to just see the titles of the books you've reviewed: books.keys

              -
              \[".*"\]
              -
              -
              -

              Are You Harsh?

              -

              So are you giving out harsh, unfair reviews? Let's keep score with this hash:
              ratings = Hash.new {0}

              -

              Then, okay, now let's count up your reviews. Just stay with me. Type:
              - books.values.each { |rate| ratings[rate] += 1 }

              -

              (The straight line in the code is the pipe character, probably located right above the - Enter key on your keyboard.)

              -
              \[:.+\]
              -
              -
              -

              A Tally

              -

              Great, wow! You've made a scorecard of your ratings. Type ratings to see the count. - This new hash shows a rating and then the number of times you've given that rating.

              -

              One of the amazing new things we've just used is a block. We're going to - explore these more in the next summary. But, basically, a block is a bit of Ruby code surrounded - by curly braces.

              -

              Let's try another block: 5.times { print "Odelay!" }

              -
              Odelay!Od.*
              -
              -
              -

              Now Arriving at Summary #4

              -

              Blocks are always attached to methods. Like the times method, which takes the - block and runs the code over and over. (In this case: five times.)

              -

              This last lesson was a bit longer. You've probably used up three minutes learning about:

              -
                -
              • Hashes. The little dictionary with the curly pages: {}.
              • -
              • Symbols. Tiny, efficient code words with a colon: :splendid.
              • -
              • Blocks. Chunks of code which can be tacked on to many of Ruby's methods. Here's the - code you used to build a scorecard:
                books.values.each { |rate| ratings[rate] += 1 }.
              • -
              -<<<<<<< HEAD - - -======= -

              On your computer, you probably have a lot of different files. Files with pictures in them, - files with programs in them. And files are often organized into folders, also called: - directories.

              -

              I've prepared a few directories for you. Take a look: - Dir.entries "/"

              -
              \["\.", .+\]
              -
              -
              -

              The Private Collection of Dr. Dir

              -

              You've just listed out everything in the top directory. The root directory, indicated - by a single slash. Containing some programs and other tutorials and such.

              -

              So, what is the Dir.entries method? Well, it's just a method, right? - entries is a method called on the Dir variable. - And Dir has a collection of methods for checking out file directories.

              -

              One other little thing we haven't really talked about openly. Method arguments, highlighted in green.

              -
                -
              • Dir.entries "/": Anything listed after a method - is considered an attachment.
              • -
              • print poem: See, print is an ordinary method. And the - poem is attached. To be printed.
              • -
              • print "pre", "event", "ual", "ism" has several arguments, with commas - between them.
              • -
              -

              To list just the text files in that directory: Dir["/*.txt"]

              -
              \["\/comics\.txt"\]
              -
              -
              -

              Come, Read Comics With Me

              -

              The Dir[] method is like entries but you search for files - with wildcard characters. Here, we see those square brackets again! Notice how - they still mean, "I am looking for _____?"

              -

              More specifically: "I am looking for files which end with .txt."

              -

              Let's crack open this comics file, then. Here's the way:
              - print File.read("/comics.txt")

              -
              Achewood.+
              -
              -
              -

              Mi Comicas, Tu Comicas

              -

              All right! We can start to use files to store things. This is great because normally when - we exit Ruby, all our variables will be gone. Ruby, by itself, forgets these things. - But if we save things in files, we can read those files in future Ruby escapades.

              -

              Hey, and guess what? The /Home directory is yours! I gave it to you! I am generous! Let's make a copy of the comics file.

              -

              You'll want to: FileUtils.copy('/comics.txt', '/Home/comics.txt') -

              If you've already created the file, use File.delete('/Home/comics.txt') to trash it.

              -
              nil
              -
              -
              -

              Your Own Turf

              -

              Okay, you've got a copy. Check it: Dir["/Home/*.txt"]

              -

              To add your own comic to the list, let's open the file in append mode.

              -

              Start like this: File.open("/Home/comics.txt", "a") do |f|.

              -
              ..
              -
              -
              -

              And Now For the Startling Conclusion

              -

              So your prompt has changed. See that? Your prompt is a double dot now.

              -

              In this tutorial, this prompt means that Ruby is expecting you to type more. - As you type in the lines of Ruby code, the double dots will continue until you - are completely finished.

              -

              Hot tip: If you want to stop working on the code and break out of the double dots, use the reset - command. If you want to go the previous page of the tutorial, use the back command.

              -

              Here's your code. You've already typed the first line, so just enter the second line. (The \n - is an Enter character.

              -
              • File.open("/Home/comics.txt", "a") do |f|
              • -
              •   f << "Cat and Girl: http://catandgirl.com/\n"
              • -
              • end
              • -
              -

              And, since you're getting so advanced and capable here, one other tip: you can use the up and down arrow keys to - edit your old commands or run them again.

              -
              ..
              -
              -
              -

              Ruby Sits Still

              -

              That last line adds the Cat and Girl comic to the list, but Ruby's going to wait until you're totally finished to - take action.

              -

              Now, to finish the code you've started. You opened a new block when you typed do. - So far the blocks we've seen have used curly braces. This time we'll be using do and end instead - of curly braces. A lot of Rubyists will use do...end when the block goes on for many lines.

              -

              Let's get that block finished now, with: end

              -
              • File.open("/Home/comics.txt", "a") do |f|
              • -
              •   f << "Cat and Girl: http://catandgirl.com/\n"
              • -
              • end
              • -
              -
              #.File:/Home/comics\.txt \(closed\).
              -
              -
              -

              The Clock Nailed To the File

              -

              Good, good! You've added that new comic to the file. You can see for yourself: print File.read("/Home/comics.txt")

              -

              What time was it when you changed the file? Let's check. Type: File.mtime("/Home/comics.txt")

              -
              \d{4}-\d+-\d+ \d{2}:\d{2}:\d{2} [+-]\d{4}
              -
              -
              -

              Just the Hour Hand

              -

              Great, there's the time. The precise time exactly when you added to the file. The mtime gives you a Ruby Time object.

              -

              If you want to check just what hour it was, hit the up arrow key and change the line to: File.mtime("/Home/comics.txt").hour

              -
              \d+
              ->>>>>>> nanothief/master -
              - -
              -

              Hallo, Who's There? And Summary #5 Waves Its Hat!

              -

              Well done, well done, well done, well done! Truly, truly, truly, truly, truuuuuuuuly!

              -

              Here's the last few minutes of your life in review:

              -
                -
              • Arguments. Arguments are a list of things sent into a method. With commas between.
              • -
              • We also spoke about do and end which are another way to make a block.
              • -
              -

              You totally know how to use Ruby now. I mean you've got down the essentials. You just need to keep learning more methods and - try out more complex blocks.

              -

              But there's one side of Ruby we haven't settled. Making your own methods and classes.

              -

              Ahem! Let's get it over with then.

              -
              -
              -

              In Ruby, Def Leppard Means Define Leppard (a Method)!

              -

              Hey, okay, you done it. You're making your own method. You started with def, followed by the name of the method. - And a list of arguments which the method will need. This isn't too scary and dangerous!

              -

              All we have to do is fill it up with Ruby and finish it up with end.

              -
              -
              -

              Hey, Cool, a Popup

              -

              Let's make a page of links. How about that? We'll need to load a little library I've made for you.

              -

              Type: require 'popup'

              -
              true
              -
              -
              -

              Browser Puppetry

              -

              Excellent, you've loaded the popup library.

              -

              The popup library contains a bunch of methods I've written which let you control a popup here on the Try Ruby site.

              -

              Here, try this: Popup.goto "http://google.com/"

              -
              \033\[1;JSm.*popup_goto\(.*\)\033\[m.*
              -
              -
              -

              Making Links and Spinning Webs

              -

              Our own lovely, little popup to manipulate. You can also fill it with your own goodies. We'll start small:

              -
              • Popup.make {
              • -
              •   h1 "My Links"
              • -
              •   link "Go to Google", "http://google.com/"
              • -
              • }
              • -
              -

              The term h1 (h-one) means a level-one header. In HTML, this is the largest size of header.

              -
              \033\[1;JSm.*popup_make\(.*h1.*a href.*\)\033\[m.*
              -
              -
              -

              Popups Are So Easy, It's Crazy

              -

              Looks good, you did it perfectly, just as you were asked. Let's make a list then.

              -

              Here's how you make a list with the popup library:

              -
              • Popup.make do
              • -
              •   h1 "Things To Do"
              • -
              •   list do
              • -
              •     p "Try out Ruby"
              • -
              •     p "Ride a tiger"
              • -
              •     p "(down River Euphrates)"
              • -
              •   end
              • -
              • end
              • -
              -

              The p method is short for "paragraph".

              -
              \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*li.*\)\033\[m.*
              -
              -
              -

              Spread the Comics on the Table

              -

              Okay, this is coming along wonderfully. This is simple stuff, but keep in mind that you didn't know any Ruby whatsoever just fifteen minutes ago!

              -

              Last -step. Let's tie it all together, you know? Let's make it chime together -like a very nice set of glistening chimes on the beach in the -maginificent sunlight!

              -

              Now, let's make a list of the links to each comic:

              -
              • Popup.make do
              • -
              •   h1 "Comics on the Web"
              • -
              •   list do
              • -
              •     comics.each do |name, url|
              • -
              •       link name, url
              • -
              •     end
              • -
              •   end
              • -
              • end
              • -
              -

              You can click on the links and read the comics in the little window even! Smashing!

              -
              \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*a href.*li.*a href.*\)\033\[m.*
              -
              -
              -

              Summary #6 Which Means You've Come So Far

              -

              You're a level six Ruby cleric. I mean what a great job you've done. Let's review:

              -
                -
              • You added your own method with def and you used that [coming soon]
              • -
              • You used the require method to load the popup library.
                By typing: require 'popup'
              • -
              • And if that wasn't enough, you made your own web page from a list of comics in a file no you havent. You made a real program!
              • -
              -

              So -what could possibly be next? What could you possibly have to learn now? -Ha, this is the best part. You've come such a long way that we're going -to uncover classes. For two more short lessons and you're done.

              -

              Earlier, we created a hash like this: Hash.new Try it.

              -
              \{\}
              -
              -
              -

              Not a School Class, a Working Class

              -

              You see, the empty curly braces {} is a shortcut for Hash.new. The new -method is used to make objects of a certain class. (Think "class" as in -"working class" — a specific group of objects which are similar, have -the same jobs, the same shirts.)

              -

              Ask yourself this: How would I make a blog in Ruby? -Where would you start? Well, you might store your blog entries in a -file, right? But how would you keep track of the title of the entry and -the time it was posted? And when you loaded the file, how would it look -in Ruby? Would it be a Hash? Or an Array? Or an Array of Arrays? Or -something else?

              I really think you'll want to use a class. You are already familiar with many classes: Hash, Array, String.

              -

              Let's make a new class: class BlogEntry.

              -
              ..
              -
              -
              -

              The Stuff Blogs are Made of

              -

              You've opened up a new BlogEntry class. What is your blog entry made of? A title, sure. Also, a time when the entry was posted. The - full text of the entry.

              -

              We'll do a mood setting, too, just like LiveJournal. The Internet has really brought back stick people and smileys - out of bankruptcy. Emote!

              -

              Okay, so you've got the first line of the class, here's the rest:

              -
              • class BlogEntry
              • -
              •   attr_accessor :title, :time, :fulltext, :mood
              • -
              • end
              • -
              -
              nil
              -
              -
              -

              Accessors Are the Dangling Limbs

              -

              Hey, good class, man. You've got a new BlogEntry class. To start an entry:
              entry = BlogEntry.new.

              -

              In the class definition, you used a method called attr_accessor. There are many attribute methods like - this which add little settings to classes. These attributes are just variables attached to a class.

              -

              Think -of it this way. A class is like a person. That star-shaped human thing -out there. And the attributes are the dangling limbs, the different -parts that make up a body.

              -

              To set the title of your entry: entry.title = "Today Mt. Hood Was Stolen!"

              -
              ".+"
              -
              -
              -

              An Object, That Neat Little Package

              -

              Go ahead and set the post time: entry.time = Time.now

              -

              And the mood: entry.mood = :sick

              -

              And the post itself: entry.fulltext = "I can't believe Mt. Hood was stolen! I am speechless! It was stolen by a giraffe who drove away - in his Cadillac Seville very nonchalant!!"

              -

              To see all your settings, just type at the prompt: entry.

              -
              #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
              -
              -
              -

              Quickening it Up

              -

              Cool, -you're blog is awesome. Hey, let's make things a bit easier on you. -You're not going to want to set the time like that every time you post. -You just want to type in the title and the entry and the mood quickly, -right?

              -

              Let's add an initialize method.

              -
              • class BlogEntry
              • -
              •   def initialize( title, mood, fulltext )
              • -
              •     @time = Time.now
              • -
              •     @title, @mood, @fulltext = title, mood, fulltext
              • -
              •   end
              • -
              • end
              • -
              -

              Once you've got that typed in, try making a new entry: BlogEntry.new

              -
              ArgumentError: wrong number of arguments \(0 for 3\).*
              -
              -
              -

              You've Taught Your Blog to Reject Worthless Things

              -

              Did you see how inside the class we used the at-symbols? Like this: @time = Time.now

              -

              Outside the class, we use accessors: entry.time = Time.now But inside we use instance variables: @time = Time.now - They're the exact same thing, but expressed in two different places of your program.

              -

              Your blog now needs a title, a mood and a post in order to work. When a new BlogEntry is created, the initialize method - is used to check for any arguments to new. Uh, we need three arguments!

              -

              Try it again with all three.

              -

              entry2 -= BlogEntry.new( "I Left my Hoodie on the Mountain!", :confused, "I am -never going back to that mountain and I hope a giraffe steals it." )

              -
              #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
              -
              -
              -

              A Giraffe Has Not Stolen Summary #7

              -

              Aha, you're here. And all in one piece. We're still going to make your blog real, but until then, let's review, okay?

              -
                -
              • Classes. Everything in Ruby is some kind of object. Classes explain objects. How a certain object works. - For example, you made a few blog entry objects and these objects are explained in the BlogEntry class. - In other words: you call them BlogEntry objects.
              • -
              • Accessors are variables attached to an object which can be used outside the object. (entry.time = Time.now)
              • -
              • Instance variables are the same variables you're using for accessors when inside the object. - Like in a method definition. (@time = Time.now)
              • -
              -

              Okay, -let's wrap things up, kid. Here's the last chapter of the GRIPPING epic -story of Try Ruby! Now that you've got a taste of how it all works, how -are you going to use it around the house and in your grocer's freezer? -You're a great person (one of my favorites), but you need guidance.

              -

              Let's finish your blog. You have blog entries, but no actual blog.

              -

              Put the entries into an array: blog = [entry, entry2]

              -
              \[#.BlogEntry:0x[0-9a-f]+.*, #.BlogEntry:0x[0-9a-f]+.*\]
              -
              -
              -

              It's All About Combining Things

              -

              Some -beautiful things can be done with the simple parts of Ruby, especially -when you combine them together into new things. Here we've got a blog -made of an array of classes. And, actually, Ruby really does good with -this kind of creature.

              -

              Here's a few things you can do with your array blog:

              -
              • You'll want to sort your entries from newest to oldest. You can do this with:
                - blog.sort_by { |entry| entry.time }.reverse
                See the sort_by explanation for more.
              • -
              • If you want to search your blog for anything related to "cadillac":
                - blog.find_all { |entry| entry.fulltext.match(/cadillac/i) }
                - Read all about find_all - and match - to figure out how that works. Also: the slashy /giraffe/i is a Regexp object, used for matching words.
              • -
              • Add new entries with blog << new_entry
                - And check out the << method documentation.
              • -
              -

              You can browse a list of all Ruby's built-in methods at ruby-doc.org's core list. - Another good list is at the online pickaxe.

              -

              One really useful method (I probably use this more than anything else) is map. Type: blog.map { |entry| entry.mood }

              -
              \[(:\w+, )+:\w+\]
              -
              -
              -

              Look at His Face — The Transformation Has Begun

              -

              The map method cycles through an array and replaces each item with something new. Say you wanted to replace each of your blog entries - with the name Bruce Willis. Do it so: blog.map { "Bruce Willis" }

              -

              Since the block always returns the string "Bruce Willis", that's what you get. In the code you just used, the entry was swapped out - for only the entry.mood.

              -

              Now, -I want you to make a popup with your blog entries. I'm not going to -give you all of the code. I'm just going to give you part of it.

              -
              • blog.each do |entry|
              • -
              •   h2 entry.title
              • -
              •   p entry.fulltext
              • -
              • end
              • -
              -

              Now, I expect you to put the popup code around it and add an h1 title with the name of your blog. For extra haroompf, have the time of each entry display.

              -
              \033\[1;JSm.*popup_make\(.*h1.*h2.*li.*h2.*li.*\)\033\[m.*
              -
              -
              -

              You are Some Kind of Web Guru, I Have Stars in My Eyes

              -

              Good, -that's it! This is exactly the code you can use to write your own real -Ruby blog. If you're feeling adventurous, I'd check out the Rails videos which show a swift young fellow creating a blog in 15 minutes. You just sit back and watch.

              -

              I -should mention Rails. You have been learning the Ruby language, how to -speak it. But Rails is a bunch of libraries (sort of like the popup -library we've been using.) It's a very powerful toolkit for building -websites. If you're interested in learning about Rails, I would head - over there right away. Start using your Ruby skills proper!

              -

              One thing Rails has is easy methods for dates. Like, try: Time.now - 2.weeks

              -
              class Integer; def weeks; self * 7*24*60*60; end; end
              -
              \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-+]\d{4}
              -
              -
              -

              Summary #8, The Hey-Relax-You-Did-Good Summary

              -

              This last section took a moment to wind down, to give you some pointers as to how you can use Ruby. If you enjoyed yourself, - download Ruby and install it.

              - -

              Once you have Ruby installed, you can use Interactive Ruby by running irb on your system's prompt. For more on Irb, - there's The Tiger's Vest to help you.

              -

              You -really deserve a double-layer cake with double-double frosting and a -guy playing one of those guitars that's a double guitar. I mean you -finished, you really did! No doubt about it, you're a certified -red-blooded smartiac!

              -
              -
              - diff --git a/public/tutorials/intro_files/sick.gif b/public/tutorials/intro_files/sick.gif deleted file mode 100755 index 217a67cbae60740fdc90b92e06b977cf7fc56699..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 94 zcmZ?wbhEHb|6B Date: Fri, 8 Jul 2011 18:14:51 -0500 Subject: [PATCH 09/16] ignore tryruby directory for right now. trying an idea that occured to me today. yes I should be doing this on a nonmaster branch. if this works it will work with heroku :-) --- tryruby/.gitignore | 4 + tryruby/Gemfile | 33 + tryruby/README | 256 + tryruby/Rakefile | 7 + .../app/controllers/application_controller.rb | 3 + tryruby/app/controllers/index_controller.rb | 8 + .../app/controllers/tutorials_controller.rb | 6 + tryruby/app/helpers/application_helper.rb | 2 + tryruby/app/helpers/index_helper.rb | 2 + tryruby/app/helpers/tutorials_helper.rb | 2 + tryruby/app/views/index/index.html.erb | 0 tryruby/app/views/index/terminal.html.erb | 0 .../app/views/layouts/application.html.erb | 175 + tryruby/app/views/layouts/blank.html.erb | 0 tryruby/app/views/tutorials/intro.html.erb | 680 ++ tryruby/config.ru | 4 + tryruby/config/application.rb | 42 + tryruby/config/boot.rb | 6 + tryruby/config/database.yml | 22 + tryruby/config/environment.rb | 5 + tryruby/config/environments/development.rb | 26 + tryruby/config/environments/production.rb | 49 + tryruby/config/environments/test.rb | 35 + .../initializers/backtrace_silencers.rb | 7 + tryruby/config/initializers/inflections.rb | 10 + tryruby/config/initializers/mime_types.rb | 5 + tryruby/config/initializers/secret_token.rb | 7 + tryruby/config/initializers/session_store.rb | 8 + tryruby/config/locales/en.yml | 5 + tryruby/config/routes.rb | 62 + tryruby/db/seeds.rb | 7 + tryruby/doc/README_FOR_APP | 2 + tryruby/lib/tasks/.gitkeep | 0 tryruby/public/404.html | 26 + tryruby/public/422.html | 26 + tryruby/public/500.html | 26 + tryruby/public/favicon.ico | 0 tryruby/public/images/background.png | Bin 0 -> 35315 bytes tryruby/public/images/footer.png | Bin 0 -> 6840 bytes tryruby/public/images/header.png | Bin 0 -> 51873 bytes tryruby/public/images/index.html | 8 + tryruby/public/images/rails.png | Bin 0 -> 6646 bytes tryruby/public/images/tile.png | Bin 0 -> 305 bytes tryruby/public/javascripts/application.js | 2 + tryruby/public/javascripts/console.js | 288 + tryruby/public/javascripts/controls.js | 963 +++ tryruby/public/javascripts/dragdrop.js | 973 +++ tryruby/public/javascripts/effects.js | 1128 ++++ tryruby/public/javascripts/facebox.js | 309 + tryruby/public/javascripts/index.html | 8 + tryruby/public/javascripts/irb.js | 110 + tryruby/public/javascripts/jQuery.irb.js | 1641 +++++ .../public/javascripts/jquery-1.3.2.min.js | 19 + .../public/javascripts/jquery-1.4.2.min.js | 154 + tryruby/public/javascripts/jquery.console.js | 609 ++ .../public/javascripts/jquery.console.min.js | 1 + tryruby/public/javascripts/jquery.js | 32 + tryruby/public/javascripts/json2.js | 1 + tryruby/public/javascripts/lib.min.js | 159 + tryruby/public/javascripts/mouseapp_2.js | 913 +++ tryruby/public/javascripts/mouseirb_2.js | 179 + tryruby/public/javascripts/prototype.js | 6001 +++++++++++++++++ tryruby/public/javascripts/rails.js | 191 + tryruby/public/javascripts/raphael-min.js | 113 + tryruby/public/robots.txt | 5 + tryruby/public/stylesheets/.gitkeep | 0 tryruby/public/stylesheets/facebox.css | 83 + tryruby/public/stylesheets/reset.css | 46 + tryruby/public/stylesheets/scaffold.css | 56 + tryruby/public/stylesheets/site.css | 378 ++ tryruby/script/rails | 6 + .../test/functional/index_controller_test.rb | 9 + .../functional/tutorials_controller_test.rb | 9 + tryruby/test/performance/browsing_test.rb | 9 + tryruby/test/test_helper.rb | 13 + .../test/unit/helpers/index_helper_test.rb | 4 + .../unit/helpers/tutorials_helper_test.rb | 4 + tryruby/vendor/plugins/.gitkeep | 0 78 files changed, 15982 insertions(+) create mode 100644 tryruby/.gitignore create mode 100644 tryruby/Gemfile create mode 100644 tryruby/README create mode 100644 tryruby/Rakefile create mode 100644 tryruby/app/controllers/application_controller.rb create mode 100644 tryruby/app/controllers/index_controller.rb create mode 100644 tryruby/app/controllers/tutorials_controller.rb create mode 100644 tryruby/app/helpers/application_helper.rb create mode 100644 tryruby/app/helpers/index_helper.rb create mode 100644 tryruby/app/helpers/tutorials_helper.rb create mode 100644 tryruby/app/views/index/index.html.erb create mode 100644 tryruby/app/views/index/terminal.html.erb create mode 100644 tryruby/app/views/layouts/application.html.erb create mode 100644 tryruby/app/views/layouts/blank.html.erb create mode 100644 tryruby/app/views/tutorials/intro.html.erb create mode 100644 tryruby/config.ru create mode 100644 tryruby/config/application.rb create mode 100644 tryruby/config/boot.rb create mode 100644 tryruby/config/database.yml create mode 100644 tryruby/config/environment.rb create mode 100644 tryruby/config/environments/development.rb create mode 100644 tryruby/config/environments/production.rb create mode 100644 tryruby/config/environments/test.rb create mode 100644 tryruby/config/initializers/backtrace_silencers.rb create mode 100644 tryruby/config/initializers/inflections.rb create mode 100644 tryruby/config/initializers/mime_types.rb create mode 100644 tryruby/config/initializers/secret_token.rb create mode 100644 tryruby/config/initializers/session_store.rb create mode 100644 tryruby/config/locales/en.yml create mode 100644 tryruby/config/routes.rb create mode 100644 tryruby/db/seeds.rb create mode 100644 tryruby/doc/README_FOR_APP create mode 100644 tryruby/lib/tasks/.gitkeep create mode 100644 tryruby/public/404.html create mode 100644 tryruby/public/422.html create mode 100644 tryruby/public/500.html create mode 100644 tryruby/public/favicon.ico create mode 100755 tryruby/public/images/background.png create mode 100755 tryruby/public/images/footer.png create mode 100644 tryruby/public/images/header.png create mode 100755 tryruby/public/images/index.html create mode 100644 tryruby/public/images/rails.png create mode 100755 tryruby/public/images/tile.png create mode 100644 tryruby/public/javascripts/application.js create mode 100644 tryruby/public/javascripts/console.js create mode 100644 tryruby/public/javascripts/controls.js create mode 100644 tryruby/public/javascripts/dragdrop.js create mode 100644 tryruby/public/javascripts/effects.js create mode 100755 tryruby/public/javascripts/facebox.js create mode 100755 tryruby/public/javascripts/index.html create mode 100755 tryruby/public/javascripts/irb.js create mode 100644 tryruby/public/javascripts/jQuery.irb.js create mode 100644 tryruby/public/javascripts/jquery-1.3.2.min.js create mode 100644 tryruby/public/javascripts/jquery-1.4.2.min.js create mode 100644 tryruby/public/javascripts/jquery.console.js create mode 100644 tryruby/public/javascripts/jquery.console.min.js create mode 100755 tryruby/public/javascripts/jquery.js create mode 100644 tryruby/public/javascripts/json2.js create mode 100644 tryruby/public/javascripts/lib.min.js create mode 100755 tryruby/public/javascripts/mouseapp_2.js create mode 100755 tryruby/public/javascripts/mouseirb_2.js create mode 100644 tryruby/public/javascripts/prototype.js create mode 100644 tryruby/public/javascripts/rails.js create mode 100644 tryruby/public/javascripts/raphael-min.js create mode 100644 tryruby/public/robots.txt create mode 100644 tryruby/public/stylesheets/.gitkeep create mode 100755 tryruby/public/stylesheets/facebox.css create mode 100644 tryruby/public/stylesheets/reset.css create mode 100644 tryruby/public/stylesheets/scaffold.css create mode 100755 tryruby/public/stylesheets/site.css create mode 100755 tryruby/script/rails create mode 100644 tryruby/test/functional/index_controller_test.rb create mode 100644 tryruby/test/functional/tutorials_controller_test.rb create mode 100644 tryruby/test/performance/browsing_test.rb create mode 100644 tryruby/test/test_helper.rb create mode 100644 tryruby/test/unit/helpers/index_helper_test.rb create mode 100644 tryruby/test/unit/helpers/tutorials_helper_test.rb create mode 100644 tryruby/vendor/plugins/.gitkeep diff --git a/tryruby/.gitignore b/tryruby/.gitignore new file mode 100644 index 0000000..f0fa30c --- /dev/null +++ b/tryruby/.gitignore @@ -0,0 +1,4 @@ +.bundle +db/*.sqlite3 +log/*.log +tmp/ diff --git a/tryruby/Gemfile b/tryruby/Gemfile new file mode 100644 index 0000000..b55f320 --- /dev/null +++ b/tryruby/Gemfile @@ -0,0 +1,33 @@ +source 'http://rubygems.org' + +gem 'rails', '3.0.9' + +# Bundle edge Rails instead: +# gem 'rails', :git => 'git://github.com/rails/rails.git' + +gem 'sqlite3' + +# Use unicorn as the web server +# gem 'unicorn' + +# Deploy with Capistrano +# gem 'capistrano' +gem "fakefs", :require => "fakefs/safe" + gem 'chronic' + +# To use debugger (ruby-debug for Ruby 1.8.7+, ruby-debug19 for Ruby 1.9.2+) +# gem 'ruby-debug' +# gem 'ruby-debug19', :require => 'ruby-debug' + +# Bundle the extra gems: +# gem 'bj' +# gem 'nokogiri' +# gem 'sqlite3-ruby', :require => 'sqlite3' +# gem 'aws-s3', :require => 'aws/s3' + +# Bundle gems for the local environment. Make sure to +# put test-only gems in this group so their generators +# and rake tasks are available in development mode: +# group :development, :test do +# gem 'webrat' +# end diff --git a/tryruby/README b/tryruby/README new file mode 100644 index 0000000..fe7013d --- /dev/null +++ b/tryruby/README @@ -0,0 +1,256 @@ +== Welcome to Rails + +Rails is a web-application framework that includes everything needed to create +database-backed web applications according to the Model-View-Control pattern. + +This pattern splits the view (also called the presentation) into "dumb" +templates that are primarily responsible for inserting pre-built data in between +HTML tags. The model contains the "smart" domain objects (such as Account, +Product, Person, Post) that holds all the business logic and knows how to +persist themselves to a database. The controller handles the incoming requests +(such as Save New Account, Update Product, Show Post) by manipulating the model +and directing data to the view. + +In Rails, the model is handled by what's called an object-relational mapping +layer entitled Active Record. This layer allows you to present the data from +database rows as objects and embellish these data objects with business logic +methods. You can read more about Active Record in +link:files/vendor/rails/activerecord/README.html. + +The controller and view are handled by the Action Pack, which handles both +layers by its two parts: Action View and Action Controller. These two layers +are bundled in a single package due to their heavy interdependence. This is +unlike the relationship between the Active Record and Action Pack that is much +more separate. Each of these packages can be used independently outside of +Rails. You can read more about Action Pack in +link:files/vendor/rails/actionpack/README.html. + + +== Getting Started + +1. At the command prompt, create a new Rails application: + rails new myapp (where myapp is the application name) + +2. Change directory to myapp and start the web server: + cd myapp; rails server (run with --help for options) + +3. Go to http://localhost:3000/ and you'll see: + "Welcome aboard: You're riding Ruby on Rails!" + +4. Follow the guidelines to start developing your application. You can find +the following resources handy: + +* The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html +* Ruby on Rails Tutorial Book: http://www.railstutorial.org/ + + +== Debugging Rails + +Sometimes your application goes wrong. Fortunately there are a lot of tools that +will help you debug it and get it back on the rails. + +First area to check is the application log files. Have "tail -f" commands +running on the server.log and development.log. Rails will automatically display +debugging and runtime information to these files. Debugging info will also be +shown in the browser on requests from 127.0.0.1. + +You can also log your own messages directly into the log file from your code +using the Ruby logger class from inside your controllers. Example: + + class WeblogController < ActionController::Base + def destroy + @weblog = Weblog.find(params[:id]) + @weblog.destroy + logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!") + end + end + +The result will be a message in your log file along the lines of: + + Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1! + +More information on how to use the logger is at http://www.ruby-doc.org/core/ + +Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are +several books available online as well: + +* Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe) +* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide) + +These two books will bring you up to speed on the Ruby language and also on +programming in general. + + +== Debugger + +Debugger support is available through the debugger command when you start your +Mongrel or WEBrick server with --debugger. This means that you can break out of +execution at any point in the code, investigate and change the model, and then, +resume execution! You need to install ruby-debug to run the server in debugging +mode. With gems, use sudo gem install ruby-debug. Example: + + class WeblogController < ActionController::Base + def index + @posts = Post.find(:all) + debugger + end + end + +So the controller will accept the action, run the first line, then present you +with a IRB prompt in the server window. Here you can do things like: + + >> @posts.inspect + => "[#nil, "body"=>nil, "id"=>"1"}>, + #"Rails", "body"=>"Only ten..", "id"=>"2"}>]" + >> @posts.first.title = "hello from a debugger" + => "hello from a debugger" + +...and even better, you can examine how your runtime objects actually work: + + >> f = @posts.first + => #nil, "body"=>nil, "id"=>"1"}> + >> f. + Display all 152 possibilities? (y or n) + +Finally, when you're ready to resume execution, you can enter "cont". + + +== Console + +The console is a Ruby shell, which allows you to interact with your +application's domain model. Here you'll have all parts of the application +configured, just like it is when the application is running. You can inspect +domain models, change values, and save to the database. Starting the script +without arguments will launch it in the development environment. + +To start the console, run rails console from the application +directory. + +Options: + +* Passing the -s, --sandbox argument will rollback any modifications + made to the database. +* Passing an environment name as an argument will load the corresponding + environment. Example: rails console production. + +To reload your controllers and models after launching the console run +reload! + +More information about irb can be found at: +link:http://www.rubycentral.com/pickaxe/irb.html + + +== dbconsole + +You can go to the command line of your database directly through rails +dbconsole. You would be connected to the database with the credentials +defined in database.yml. Starting the script without arguments will connect you +to the development database. Passing an argument will connect you to a different +database, like rails dbconsole production. Currently works for MySQL, +PostgreSQL and SQLite 3. + +== Description of Contents + +The default directory structure of a generated Ruby on Rails application: + + |-- app + | |-- controllers + | |-- helpers + | |-- mailers + | |-- models + | `-- views + | `-- layouts + |-- config + | |-- environments + | |-- initializers + | `-- locales + |-- db + |-- doc + |-- lib + | `-- tasks + |-- log + |-- public + | |-- images + | |-- javascripts + | `-- stylesheets + |-- script + |-- test + | |-- fixtures + | |-- functional + | |-- integration + | |-- performance + | `-- unit + |-- tmp + | |-- cache + | |-- pids + | |-- sessions + | `-- sockets + `-- vendor + `-- plugins + +app + Holds all the code that's specific to this particular application. + +app/controllers + Holds controllers that should be named like weblogs_controller.rb for + automated URL mapping. All controllers should descend from + ApplicationController which itself descends from ActionController::Base. + +app/models + Holds models that should be named like post.rb. Models descend from + ActiveRecord::Base by default. + +app/views + Holds the template files for the view that should be named like + weblogs/index.html.erb for the WeblogsController#index action. All views use + eRuby syntax by default. + +app/views/layouts + Holds the template files for layouts to be used with views. This models the + common header/footer method of wrapping views. In your views, define a layout + using the layout :default and create a file named default.html.erb. + Inside default.html.erb, call <% yield %> to render the view using this + layout. + +app/helpers + Holds view helpers that should be named like weblogs_helper.rb. These are + generated for you automatically when using generators for controllers. + Helpers can be used to wrap functionality for your views into methods. + +config + Configuration files for the Rails environment, the routing map, the database, + and other dependencies. + +db + Contains the database schema in schema.rb. db/migrate contains all the + sequence of Migrations for your schema. + +doc + This directory is where your application documentation will be stored when + generated using rake doc:app + +lib + Application specific libraries. Basically, any kind of custom code that + doesn't belong under controllers, models, or helpers. This directory is in + the load path. + +public + The directory available for the web server. Contains subdirectories for + images, stylesheets, and javascripts. Also contains the dispatchers and the + default HTML files. This should be set as the DOCUMENT_ROOT of your web + server. + +script + Helper scripts for automation and generation. + +test + Unit and functional tests along with fixtures. When using the rails generate + command, template test files will be generated for you and placed in this + directory. + +vendor + External libraries that the application depends on. Also includes the plugins + subdirectory. If the app has frozen rails, those gems also go here, under + vendor/rails/. This directory is in the load path. diff --git a/tryruby/Rakefile b/tryruby/Rakefile new file mode 100644 index 0000000..1e7daf6 --- /dev/null +++ b/tryruby/Rakefile @@ -0,0 +1,7 @@ +# Add your own tasks in files placed in lib/tasks ending in .rake, +# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. + +require File.expand_path('../config/application', __FILE__) +require 'rake' + +Tryruby::Application.load_tasks diff --git a/tryruby/app/controllers/application_controller.rb b/tryruby/app/controllers/application_controller.rb new file mode 100644 index 0000000..e8065d9 --- /dev/null +++ b/tryruby/app/controllers/application_controller.rb @@ -0,0 +1,3 @@ +class ApplicationController < ActionController::Base + protect_from_forgery +end diff --git a/tryruby/app/controllers/index_controller.rb b/tryruby/app/controllers/index_controller.rb new file mode 100644 index 0000000..6a4089a --- /dev/null +++ b/tryruby/app/controllers/index_controller.rb @@ -0,0 +1,8 @@ +class IndexController < ApplicationController + def terminal + end + + def index + + end +end diff --git a/tryruby/app/controllers/tutorials_controller.rb b/tryruby/app/controllers/tutorials_controller.rb new file mode 100644 index 0000000..662119f --- /dev/null +++ b/tryruby/app/controllers/tutorials_controller.rb @@ -0,0 +1,6 @@ +class TutorialsController < ApplicationController +layout 'blank' + def intro + end + +end diff --git a/tryruby/app/helpers/application_helper.rb b/tryruby/app/helpers/application_helper.rb new file mode 100644 index 0000000..de6be79 --- /dev/null +++ b/tryruby/app/helpers/application_helper.rb @@ -0,0 +1,2 @@ +module ApplicationHelper +end diff --git a/tryruby/app/helpers/index_helper.rb b/tryruby/app/helpers/index_helper.rb new file mode 100644 index 0000000..cdc64c7 --- /dev/null +++ b/tryruby/app/helpers/index_helper.rb @@ -0,0 +1,2 @@ +module IndexHelper +end diff --git a/tryruby/app/helpers/tutorials_helper.rb b/tryruby/app/helpers/tutorials_helper.rb new file mode 100644 index 0000000..30716fd --- /dev/null +++ b/tryruby/app/helpers/tutorials_helper.rb @@ -0,0 +1,2 @@ +module TutorialsHelper +end diff --git a/tryruby/app/views/index/index.html.erb b/tryruby/app/views/index/index.html.erb new file mode 100644 index 0000000..e69de29 diff --git a/tryruby/app/views/index/terminal.html.erb b/tryruby/app/views/index/terminal.html.erb new file mode 100644 index 0000000..e69de29 diff --git a/tryruby/app/views/layouts/application.html.erb b/tryruby/app/views/layouts/application.html.erb new file mode 100644 index 0000000..6de65d3 --- /dev/null +++ b/tryruby/app/views/layouts/application.html.erb @@ -0,0 +1,175 @@ + + + + + + + + + + + try ruby! (in your browser) + + + + + + + + + + + + + + + + + + + + +
              + +
              + +
              +
              + +

              A Popup Browser

              +

              [x]

              +
              + +
              +
              + +
              +
              + <%= yield %> +
              +
              +
              +
              +
              +

              Got 15 minutes? Give Ruby a shot right now!

              +

              Ruby is a programming language from Japan + (available at ruby-lang.org) + which is revolutionizing the web. + The beauty of Ruby is found in its balance between simplicity and power.

              + +

              Try out Ruby code in the prompt above. In addition + to Ruby's builtin methods, the following commands are available:

              +
                +
              • help + Start the 15 minute interactive tutorial. Trust me, it's very basic!
              • +
              • help 2 + Hop to chapter two.
              • + +
              • clear + Clear screen. Useful if your browser starts slowing down. + Your command history will be remembered. +
              • back + Go back one screen in the tutorial.
              • +
              • reset + Reset the interpreter if you get too deep. (or Ctrl-D!)
              • +
              • next +Allows you to skip to the next section of a lesson.
              • + +
              • time + A stopwatch. Prints the time your session has been open.
              • +
              +

              If you happen to leave or refresh the page, your session will still be here for + unless it is left inactive for ten minutes.

              +
              +
              +
              + +
              +
              Trapped in double dots? A quote or something was left open. Type: reset or hit Ctrl-D.
              +
              + +

              This place was sired by why the lucky stiff. + Please contact me using the email address at that link.is maintained by Andrew McElroy and David Miani. For support issues, please post a ticket or contact Sophrinix on github. +

              + +
              + + + + + + + + +Please Support
              Try Ruby!
              + + + diff --git a/tryruby/app/views/layouts/blank.html.erb b/tryruby/app/views/layouts/blank.html.erb new file mode 100644 index 0000000..e69de29 diff --git a/tryruby/app/views/tutorials/intro.html.erb b/tryruby/app/views/tutorials/intro.html.erb new file mode 100644 index 0000000..56c1d1c --- /dev/null +++ b/tryruby/app/views/tutorials/intro.html.erb @@ -0,0 +1,680 @@ + +
              +

              Using the Prompt

              +

              The blue window above is a Ruby prompt. Type a line of Ruby code, hit Enter + and watch it run!

              +

              For example, try typing some math. Like: 2 + 6

              +
              \d+
              +
              +
              +

              Numbers & Math

              +

              Good! You did a bit of math. See how the answer popped out?

              +

              Ruby recognizes numbers and mathematic symbols. You could try some other math like:

              +
              • 4 * 10
              • +
              • 5 - 12
              • +
              • 40 / 4
              +

              Sure, computers are handy and fast for math. Let's move on. Want to see your name reversed? + Type your first name in quotes like this: "Jimmy"

              +
              "(\w+)"
              +
              +
              +

              Say Your Name Backwards

              +

              Perfect, you've formed a string from the letters of your name. A string + is a set of characters the computer can process.

              +

              Imagine the letters are on a string of + laundry line and the quotes are clothespins holding the ends. The quotes mark the beginning and end.

              +

              To reverse your name, type: "Jimmy".reverse (Don't forget the dot!)

              +
              "(\w+)"
              +
              +
              +

              Counting the Letters

              +

              You have used the reverse method on your name! By enclosing your name in + quotes, you made a string. Then you called the reverse method, which works on strings to flip + all the letters backwards.

              +

              Now, let's see how many letters are in your name: "Jimmy".length

              +
              \d+
              +
              +
              +

              On Repeat

              +

              Now, I'm sure by now you're wondering what any of this is good for. Well, I'm sure you've been to + a website that screamed, Hey, your password is too short! See, some programs + use this simple code.

              +

              Watch this. Let's multiply your name by 5. "Jimmy" * 5

              +
              "(\w+)"
              +
              +
              +

              Hey, Summary #1 Already

              +

              Let's look at what you've learned in the first minute.

              +
                +
              • The prompt. Typing code into the green prompt gives you + an answer from a red prompt. All code gives an answer.
              • +
              • Numbers and strings are Ruby's math and text objects.
              • +
              • Methods. You've used English-language methods like reverse + and symbolic methods like * (the multiplication method.) Methods are action!
              • +
              +

              This is the essence of your learning. Taking simple things, toying with + them and turning them into new things. Feeling comfortable yet? I promise you are.

              +

              Okay, let's do something uncomfortable. Try reversing a number: 40.reverse

              +
              NoMethodError: undefined method `reverse' for (\d+):Fixnum
              +
              +
              +

              Stop, You're Barking Mad!

              +

              You can't reverse the number forty. I guess you can hold your monitor up to the + mirror, but reversing a number just doesn't make sense. Ruby has tossed an error + message. Ruby is telling you there is no method reverse for numbers.

              +

              Maybe if you turn it into a string: 40.to_s.reverse.

              +
              \"(\d+)\"
              +
              +
              +

              Boys are Different From Girls

              +

              And numbers are different from strings. While you can use methods on any object + in Ruby, some methods only work on certain types of things. But you can always + convert between different types using Ruby's "to" methods.

              +
              • to_s converts things to strings.
              • +
              • to_i converts things to integers (numbers.)
              • +
              • to_a converts things to arrays.
              • +
              +

              What are arrays?! They are lists. Type in a pair of brackets: [].

              +
              \[\]
              +
              +
              +

              Standing in Line

              +

              Great, that's an empty list. Lists store things in order. + Like standing in line for popcorn. You are behind someone and you wouldn't + dream of pushing them aside, right? And the guy behind you, you've got a + close eye on him, right?

              +

              Here's a list for you. Lottery numbers: [12, 47, 35].

              +
              \[(\d+(, )?){2,}\]
              +
              +
              +

              One Raises Its Hand

              +

              A list of lottery numbers. Which one is the highest?

              +

              Try: [12, 47, 35].max.

              +
              (\d+)
              +
              +
              +

              Tucking a List Away

              +

              Good, good. But it's annoying to have to retype that list, isn't it?

              +

              Let's save our numbers inside a ticket like so: ticket = [12, 47, 35]

              +
              \[(\d+(, )?){2,}\]
              +
              +
              +

              Now Type Ticket

              +

              Now, type: ticket

              +
              \[(\d+(, )?){2,}\]
              +
              +
              +

              Saved, Tucked Away

              +

              Fantastic! You've hung on to your lotto numbers, tucking them away inside a + variable called ticket.

              +

              Let's put your lotto numbers in order, how about? Use: ticket.sort!

              +
              \[(\d+(, )?){2,}\]
              +
              +
              +

              Summary #2 is Upon Us

              +

              You had a list. You sorted the list. The ticket variable is now changed.

              +

              Did you notice that the sort! method has a big, bright exclamation at the end? + A lot of times Ruby methods shout like that if they alter the variable for good. It's nothin + special, just a mark.

              +

              Now, look how your second minute went:

              +
                +
              • Errors. If you try to reverse a number or do anything fishy, + Ruby will skip the prompt and tell you so.
              • +
              • Arrays are lists for storing things in order.
              • +
              • Variables save a thing and give it a name. You used the + equals sign to do this.
                Like: ticket = [14, 37, 18].
              • +
              +

              In all there are eight lessons. You are two-eighths of the way there! + This is simple stuff, don't you think? Good stuff up ahead.

              +

              Let's change directions for a moment. I've stuffed a bit of poetry for you in + a certain variable. Take a look. Type print poem

              +
              poem = "My toast has flown from my hand\nAnd my toast has gone to the +moon.\nBut when I saw it on television,\nPlanting our flag on Halley's +comet,\nMore still did I want to eat it.\n"
              +
              My toast (.+)
              +
              +
              +

              Sadly, You Hate Toast Poetry

              +

              Look, it's okay. You don't have to like it. Hack it up, be my guest.

              +

              Instead of toast, go for a melon or something. Try this: poem['toast'] = 'honeydew'

              +

              And then type print poem by itself to see the new poem.

              +
              My honey(.+)
              +
              +
              +

              Ready, Aim

              +

              The square brackets you just used are very common in Ruby. Remember, you typed: poem['toast'] = 'honeydew'. That box with the word toast has a square bracket on each side, see?

              +

              The +two brackets are like sights used to line up a target. Exactly. These +brackets mean, "I am looking for ____." Ready, aim. Here you're looking +for toast and swapping it out with fruit.

              +

              Here's a question: what happens when we reverse this whole poem? poem.reverse +

              "\\n.ti tae ot (.+)"
              +
              +
              +

              Too Much Reversal

              +

              Okay, sure. So the whole poem's been turned backwards, letter-by-letter. I really want to just + reverse the lines, though. Move the last line up to first and the first line down to last. Backwards, but not + that backwards.

              +

              Here's how: poem.lines.to_a.reverse

              +
              \["More still did I(.+)"\]
              +
              +
              +

              Ringlets of Chained Methods

              +

              So what do you see? What happened there? You typed poem.lines.to_a.reverse and what happened?

              +

              Two things happened. You turned the poem into a +list using lines.to_a. lines decides the way +the string is split up, then to_a converted it into an +Array. (To array.) Different methods, such +as bytes and chars can be used in place +of lines. By using lines, ruby will return each line of the poem.

              +

              Then, you reversed that list. You had each line. You reversed them. That's it.

              +

              Let's tack one more method on the end there: print poem.lines.to_a.reverse.join +

              More still did I(.+)
              +
              +
              +

              Of All the Summaries, #3 is Here Now

              +

              Good show, my friend! The join method took that list of reversed lines and put them + together into a string. (Sure, you could have also just used to_s.)

              +

              Review time.

              +
                +
              • Exclamations. Methods may have exclamations (and also question marks) + in their name. No big deal. Try: poem.include? "my hand"
              • +
              • Square brackets. Target and find things. Search and replace.
              • +
              • Chaining methods lets you get a lot more done. Break up a poem, + reverse it, reassemble it: poem.lines.to_a.reverse.join
              • +
              +

              At this point, you may want to tinker with the poem a bit more. A complete list of all + the String methods is + + here. + Go ahead and try a few (such as poem.downcase or poem.delete.)

              +

              When you're ready to move on, type: books = {}

              +
              \{\}
              +
              +
              +

              A Wee Blank Book

              +

              You've made an empty hash. (Also known as: an empty dictionary.)

              +

              We're going to stuff some miniature book reviews in this hash. Here's our rating system:

              +
                +
              • :splendid → a masterpiece.
              • +
              • :quite_good → enjoyed, sure, yes.
              • +
              • :mediocre → equal parts great and terrible.
              • +
              • :quite_not_good → notably bad.
              • +
              • :abyssmal → steaming wreck.
              • +
              +

              To rate a book, put the title in square brackets and put the rating after the equals.

              +

              For example: books["Gravity's Rainbow"] = :splendid

              +
              :\w+
              +
              +
              +

              More Bite-Size Reviews

              +

              Keep going, fill it up with reviews. And, if you want to see the whole list, + just type: books

              +

              Again, the ratings are: :splendid, :quite_good, :mediocre, + :quite_not_good, and :abyssmal.

              +

              These ratings are not strings. When you place a colon in front of a simple word, you get a + symbol. Symbols are cheaper than strings (in terms of computer memory.) If + you use a word over and over in your program, use a symbol. Rather than having thousands of + copies of that word in memory, the computer will store the symbol only once.

              +

              Once you've got three or four books in + there, type: books.length.

              +
              [3-9]
              +
              +
              +

              Wait, Did I Like Gravity's Rainbow?

              +

              See, the length method works on strings, list and hashes. One great thing about + Ruby is that names are often reused, which means fewer names you need to remember.

              +

              If you'd like to look up one of your old reviews, again put the title in the square. But leave off + the equals.

              +

              Just like this: books["Gravity's Rainbow"]

              +
              :\w+
              +
              +
              +

              Hashes as Pairs

              +

              Keep in mind that hashes won't keep things in order. That's not their job. It'll just pair up two + things: a key and a value. In your reviews, the key is the book's + title and the value is the rating.

              +

              If you want to just see the titles of the books you've reviewed: books.keys

              +
              \[".*"\]
              +
              +
              +

              Are You Harsh?

              +

              So are you giving out harsh, unfair reviews? Let's keep score with this hash:
              ratings = Hash.new {0}

              +

              Then, okay, now let's count up your reviews. Just stay with me. Type:
              + books.values.each { |rate| ratings[rate] += 1 }

              +

              (The straight line in the code is the pipe character, probably located right above the + Enter key on your keyboard.)

              +
              \[:.+\]
              +
              +
              +

              A Tally

              +

              Great, wow! You've made a scorecard of your ratings. Type ratings to see the count. + This new hash shows a rating and then the number of times you've given that rating.

              +

              One of the amazing new things we've just used is a block. We're going to + explore these more in the next summary. But, basically, a block is a bit of Ruby code surrounded + by curly braces.

              +

              Let's try another block: 5.times { print "Odelay!" }

              +
              Odelay!Od.*
              +
              +
              +

              Now Arriving at Summary #4

              +

              Blocks are always attached to methods. Like the times method, which takes the + block and runs the code over and over. (In this case: five times.)

              +

              This last lesson was a bit longer. You've probably used up three minutes learning about:

              +
                +
              • Hashes. The little dictionary with the curly pages: {}.
              • +
              • Symbols. Tiny, efficient code words with a colon: :splendid.
              • +
              • Blocks. Chunks of code which can be tacked on to many of Ruby's methods. Here's the + code you used to build a scorecard:
                books.values.each { |rate| ratings[rate] += 1 }.
              • +
              +

              On your computer, you probably have a lot of different files. Files with pictures in them, + files with programs in them. And files are often organized into folders, also called: + directories.

              +

              I've prepared a few directories for you. Take a look: + Dir.entries "/"

              +
              \["\.", .+\]
              +
              +
              +

              The Private Collection of Dr. Dir

              +

              You've just listed out everything in the top directory. The root directory, indicated + by a single slash. Containing some programs and other tutorials and such.

              +

              So, what is the Dir.entries method? Well, it's just a method, right? + entries is a method called on the Dir variable. + And Dir has a collection of methods for checking out file directories.

              +

              One other little thing we haven't really talked about openly. Method arguments, highlighted in green.

              +
                +
              • Dir.entries "/": Anything listed after a method + is considered an attachment.
              • +
              • print poem: See, print is an ordinary method. And the + poem is attached. To be printed.
              • +
              • print "pre", "event", "ual", "ism" has several arguments, with commas + between them.
              • +
              +

              To list just the text files in that directory: Dir["/*.txt"]

              +
              \["\/comics\.txt"\]
              +
              +
              +

              Come, Read Comics With Me

              +

              The Dir[] method is like entries but you search for files + with wildcard characters. Here, we see those square brackets again! Notice how + they still mean, "I am looking for _____?"

              +

              More specifically: "I am looking for files which end with .txt."

              +

              Let's crack open this comics file, then. Here's the way:
              + print File.read("/comics.txt")

              +
              Achewood.+
              +
              +
              +

              Mi Comicas, Tu Comicas

              +

              All right! We can start to use files to store things. This is great because normally when + we exit Ruby, all our variables will be gone. Ruby, by itself, forgets these things. + But if we save things in files, we can read those files in future Ruby escapades.

              +

              Hey, and guess what? The /Home directory is yours! I gave it to you! I am generous! Let's make a copy of the comics file.

              +

              You'll want to: FileUtils.copy('/comics.txt', '/Home/comics.txt') +

              If you've already created the file, use File.delete('/Home/comics.txt') to trash it.

              +
              nil
              +
              +
              +

              Your Own Turf

              +

              Okay, you've got a copy. Check it: Dir["/Home/*.txt"]

              +

              To add your own comic to the list, let's open the file in append mode.

              +

              Start like this: File.open("/Home/comics.txt", "a") do |f|.

              +
              ..
              +
              +
              +

              And Now For the Startling Conclusion

              +

              So your prompt has changed. See that? Your prompt is a double dot now.

              +

              In this tutorial, this prompt means that Ruby is expecting you to type more. + As you type in the lines of Ruby code, the double dots will continue until you + are completely finished.

              +

              Hot tip: If you want to stop working on the code and break out of the double dots, use the reset + command. If you want to go the previous page of the tutorial, use the back command.

              +

              Here's your code. You've already typed the first line, so just enter the second line. (The \n + is an Enter character.

              +
              • File.open("/Home/comics.txt", "a") do |f|
              • +
              •   f << "Cat and Girl: http://catandgirl.com/\n"
              • +
              • end
              • +
              +

              And, since you're getting so advanced and capable here, one other tip: you can use the up and down arrow keys to + edit your old commands or run them again.

              +
              ..
              +
              +
              +

              Ruby Sits Still

              +

              That last line adds the Cat and Girl comic to the list, but Ruby's going to wait until you're totally finished to + take action.

              +

              Now, to finish the code you've started. You opened a new block when you typed do. + So far the blocks we've seen have used curly braces. This time we'll be using do and end instead + of curly braces. A lot of Rubyists will use do...end when the block goes on for many lines.

              +

              Let's get that block finished now, with: end

              +
              • File.open("/Home/comics.txt", "a") do |f|
              • +
              •   f << "Cat and Girl: http://catandgirl.com/\n"
              • +
              • end
              • +
              +
              #.File:/Home/comics\.txt \(closed\).
              +
              +
              +

              The Clock Nailed To the File

              +

              Good, good! You've added that new comic to the file. You can see for yourself: print File.read("/Home/comics.txt")

              +

              What time was it when you changed the file? Let's check. Type: File.mtime("/Home/comics.txt")

              +
              \d{4}-\d+-\d+ \d{2}:\d{2}:\d{2} [+-]\d{4}
              +
              +
              +

              Just the Hour Hand

              +

              Great, there's the time. The precise time exactly when you added to the file. The mtime gives you a Ruby Time object.

              +

              If you want to check just what hour it was, hit the up arrow key and change the line to: File.mtime("/Home/comics.txt").hour

              +
              \d+
              +
              +
              +

              Hallo, Who's There? And Summary #5 Waves Its Hat!

              +

              Well done, well done, well done, well done! Truly, truly, truly, truly, truuuuuuuuly!

              +

              Here's the last few minutes of your life in review:

              +
                +
              • Files. What more can be said? Lots of methods for editing files and lookin around in directories.
              • +
              • Arguments. Arguments are a list of things sent into a method. With commas between.
              • +
              • We also spoke about do and end which are another way to make a block.
              • +
              +

              You totally know how to use Ruby now. I mean you've got down the essentials. You just need to keep learning more methods and + try out more complex blocks.

              +

              But there's one side of Ruby we haven't settled. Making your own methods and classes.

              +

              Ahem! Let's get it over with then.

              +

              Start with: def load_comics( path )

              +
              ..
              +
              +
              +

              In Ruby, Def Leppard Means Define Leppard (a Method)!

              +

              Hey, okay, you done it. You're making your own method. You started with def, followed by the name of the method. + And a list of arguments which the method will need. This isn't too scary and dangerous!

              +

              All we have to do is fill it up with Ruby and finish it up with end.

              +

              Here's the code:

              +
              • def load_comics( path )
              • +
              •   comics = {}
              • +
              •   File.foreach(path) do |line|
              • +
              •     name, url = line.split(': ')
              • +
              •     comics[name] = url.strip
              • +
              •   end
              • +
              •   comics
              • +
              • end
              • +
              +

              No need to indent, if you don't want. I just do that to make it read easier.

              +
              nil
              +
              +
              +

              The Ripened Fruit of Your Own Creation

              +

              A new method is born. Let us use it: comics = load_comics('/comics.txt')

              +

              If you have a problem, you might have mistyped. Use the back command and try again.

              +
              \{.*"Achewood"=."http://achewood.com/".*\}
              +
              +
              +

              Hey, Cool, a Comics Thing

              +

              In your Ruby window above, look at the code you've typed for the load_comics method. What is happening? You're + passing in the path variable and you're getting back the comics variable. Ruby lets the comics + hash trickle out the end of the method.

              +

              A number of methods were used to get the job done. See if you can spot them.

              +
              • File.foreach is a method which opens a file and hands each line to the block. The line + variable inside the do...end block took turns with each line in the file.
              • +
              • split is a method for strings, which breaks the string up into an array. An axe is laid on the colon + and the line is chopped in half, giving us the url and name for each comic.
              • +
              • strip removes extra spaces around the name. Just in case.
              • +
              +

              Right on. Bravo. You've got the comics in a Ruby hash. But what now? What good is this really?

              +

              Let's make a page of links. How about that? I went ahead and loaded a little library I've made for you.

              +

              Type: next. This is temporary as I updates new lessons.

              +
              true
              +
              +
              +

              Browser Puppetry

              +

              Excellent, you've loaded the popup library. It's saved in a file in the Libraries folder. See: Dir["/Libraries/*"]

              +

              The popup library contains a bunch of methods I've written which let you control a popup here on the Try Ruby site.

              +

              Here, try this: Popup.goto "http://google.com/"

              +
              \033\[1;JSm.*popup_goto\(.*\)\033\[m.*
              +
              +
              +

              Making Links and Spinning Webs

              +

              Our own lovely, little popup to manipulate. You can also fill it with your own goodies. We'll start small:

              +
              • Popup.make {
              • +
              •   h1 "My Links"
              • +
              •   link "Go to Google", "http://google.com/"
              • +
              • }
              • +
              +

              The term h1 (h-one) means a level-one header. In HTML, this is the largest size of header.

              +
              \033\[1;JSm.*popup_make\(.*h1.*a href.*\)\033\[m.*
              +
              +
              +

              Popups Are So Easy, It's Crazy

              +

              Looks good, you did it perfectly, just as you were asked. Let's make a list then.

              +

              Here's how you make a list with the popup library:

              +
              • Popup.make do
              • +
              •   h1 "Things To Do"
              • +
              •   list do
              • +
              •     p "Try out Ruby"
              • +
              •     p "Ride a tiger"
              • +
              •     p "(down River Euphrates)"
              • +
              •   end
              • +
              • end
              • +
              +

              The p method is short for "paragraph".

              +
              \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*li.*\)\033\[m.*
              +
              +
              +

              Spread the Comics on the Table

              +

              Okay, this is coming along wonderfully. This is simple stuff, but keep in mind that you didn't know any Ruby whatsoever just fifteen minutes ago!

              +

              Last +step. Let's tie it all together, you know? Let's make it chime together +like a very nice set of glistening chimes on the beach in the +maginificent sunlight!

              +

              Make sure the comics are loaded: comics = load_comics( '/comics.txt' )

              +

              Now, let's make a list of the links to each comic:

              +
              • Popup.make do
              • +
              •   h1 "Comics on the Web"
              • +
              •   list do
              • +
              •     comics.each do |name, url|
              • +
              •       link name, url
              • +
              •     end
              • +
              •   end
              • +
              • end
              • +
              +

              You can click on the links and read the comics in the little window even! Smashing!

              +
              \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*a href.*li.*a href.*\)\033\[m.*
              +
              +
              +

              Summary #6 Which Means You've Come So Far

              +

              You're a level six Ruby cleric. I mean what a great job you've done. Let's review:

              +
                +
              • You added your own method with def and you used that load_comics method several times.
              • +
              • Libraries. You used the require method to load the popup library.
                By typing: require 'popup'
              • +
              • And if that wasn't enough, you made your own web page from a list of comics in a file. You made a real program!
              • +
              +

              So +what could possibly be next? What could you possibly have to learn now? +Ha, this is the best part. You've come such a long way that we're going +to uncover classes. For two more short lessons and you're done.

              +

              Earlier, we created a hash like this: Hash.new Try it.

              +
              \{\}
              +
              +
              +

              Not a School Class, a Working Class

              +

              You see, the empty curly braces {} is a shortcut for Hash.new. The new +method is used to make objects of a certain class. (Think "class" as in +"working class" — a specific group of objects which are similar, have +the same jobs, the same shirts.)

              +

              Ask yourself this: How would I make a blog in Ruby? +Where would you start? Well, you might store your blog entries in a +file, right? But how would you keep track of the title of the entry and +the time it was posted? And when you loaded the file, how would it look +in Ruby? Would it be a Hash? Or an Array? Or an Array of Arrays? Or +something else?

              I really think you'll want to use a class. You are already familiar with many classes: Hash, Array, String.

              +

              Let's make a new class: class BlogEntry.

              +
              ..
              +
              +
              +

              The Stuff Blogs are Made of

              +

              You've opened up a new BlogEntry class. What is your blog entry made of? A title, sure. Also, a time when the entry was posted. The + full text of the entry.

              +

              We'll do a mood setting, too, just like LiveJournal. The Internet has really brought back stick people and smileys + out of bankruptcy. Emote!

              +

              Okay, so you've got the first line of the class, here's the rest:

              +
              • class BlogEntry
              • +
              •   attr_accessor :title, :time, :fulltext, :mood
              • +
              • end
              • +
              +
              nil
              +
              +
              +

              Accessors Are the Dangling Limbs

              +

              Hey, good class, man. You've got a new BlogEntry class. To start an entry:
              entry = BlogEntry.new.

              +

              In the class definition, you used a method called attr_accessor. There are many attribute methods like + this which add little settings to classes. These attributes are just variables attached to a class.

              +

              Think +of it this way. A class is like a person. That star-shaped human thing +out there. And the attributes are the dangling limbs, the different +parts that make up a body.

              +

              To set the title of your entry: entry.title = "Today Mt. Hood Was Stolen!"

              +
              ".+"
              +
              +
              +

              An Object, That Neat Little Package

              +

              Go ahead and set the post time: entry.time = Time.now

              +

              And the mood: entry.mood = :sick

              +

              And the post itself: entry.fulltext = "I can't believe Mt. Hood was stolen! I am speechless! It was stolen by a giraffe who drove away + in his Cadillac Seville very nonchalant!!"

              +

              To see all your settings, just type at the prompt: entry.

              +
              #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
              +
              +
              +

              Quickening it Up

              +

              Cool, +you're blog is awesome. Hey, let's make things a bit easier on you. +You're not going to want to set the time like that every time you post. +You just want to type in the title and the entry and the mood quickly, +right?

              +

              Let's add an initialize method.

              +
              • class BlogEntry
              • +
              •   def initialize( title, mood, fulltext )
              • +
              •     @time = Time.now
              • +
              •     @title, @mood, @fulltext = title, mood, fulltext
              • +
              •   end
              • +
              • end
              • +
              +

              Once you've got that typed in, try making a new entry: BlogEntry.new

              +
              ArgumentError: wrong number of arguments \(0 for 3\).*
              +
              +
              +

              You've Taught Your Blog to Reject Worthless Things

              +

              Did you see how inside the class we used the at-symbols? Like this: @time = Time.now

              +

              Outside the class, we use accessors: entry.time = Time.now But inside we use instance variables: @time = Time.now + They're the exact same thing, but expressed in two different places of your program.

              +

              Your blog now needs a title, a mood and a post in order to work. When a new BlogEntry is created, the initialize method + is used to check for any arguments to new. Uh, we need three arguments!

              +

              Try it again with all three.

              +

              entry2 += BlogEntry.new( "I Left my Hoodie on the Mountain!", :confused, "I am +never going back to that mountain and I hope a giraffe steals it." )

              +
              #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
              +
              +
              +

              A Giraffe Has Not Stolen Summary #7

              +

              Aha, you're here. And all in one piece. We're still going to make your blog real, but until then, let's review, okay?

              +
                +
              • Classes. Everything in Ruby is some kind of object. Classes explain objects. How a certain object works. + For example, you made a few blog entry objects and these objects are explained in the BlogEntry class. + In other words: you call them BlogEntry objects.
              • +
              • Accessors are variables attached to an object which can be used outside the object. (entry.time = Time.now)
              • +
              • Instance variables are the same variables you're using for accessors when inside the object. + Like in a method definition. (@time = Time.now)
              • +
              +

              Okay, +let's wrap things up, kid. Here's the last chapter of the GRIPPING epic +story of Try Ruby! Now that you've got a taste of how it all works, how +are you going to use it around the house and in your grocer's freezer? +You're a great person (one of my favorites), but you need guidance.

              +

              Let's finish your blog. You have blog entries, but no actual blog.

              +

              Put the entries into an array: blog = [entry, entry2]

              +
              \[#.BlogEntry:0x[0-9a-f]+.*, #.BlogEntry:0x[0-9a-f]+.*\]
              +
              +
              +

              It's All About Combining Things

              +

              Some +beautiful things can be done with the simple parts of Ruby, especially +when you combine them together into new things. Here we've got a blog +made of an array of classes. And, actually, Ruby really does good with +this kind of creature.

              +

              Here's a few things you can do with your array blog:

              +
              • You'll want to sort your entries from newest to oldest. You can do this with:
                + blog.sort_by { |entry| entry.time }.reverse
                See the sort_by explanation for more.
              • +
              • If you want to search your blog for anything related to "cadillac":
                + blog.find_all { |entry| entry.fulltext.match(/cadillac/i) }
                + Read all about find_all + and match + to figure out how that works. Also: the slashy /giraffe/i is a Regexp object, used for matching words.
              • +
              • Add new entries with blog << new_entry
                + And check out the << method documentation.
              • +
              +

              You can browse a list of all Ruby's built-in methods at ruby-doc.org's core list. + Another good list is at the online pickaxe.

              +

              One really useful method (I probably use this more than anything else) is map. Type: blog.map { |entry| entry.mood }

              +
              \[(:\w+, )+:\w+\]
              +
              +
              +

              Look at His Face — The Transformation Has Begun

              +

              The map method cycles through an array and replaces each item with something new. Say you wanted to replace each of your blog entries + with the name Bruce Willis. Do it so: blog.map { "Bruce Willis" }

              +

              Since the block always returns the string "Bruce Willis", that's what you get. In the code you just used, the entry was swapped out + for only the entry.mood.

              +

              Now, +I want you to make a popup with your blog entries. I'm not going to +give you all of the code. I'm just going to give you part of it.

              +
              • blog.each do |entry|
              • +
              •   h2 entry.title
              • +
              •   p entry.fulltext
              • +
              • end
              • +
              +

              Now, I expect you to put the popup code around it and add an h1 title with the name of your blog. For extra haroompf, have the time of each entry display.

              +
              \033\[1;JSm.*popup_make\(.*h1.*h2.*li.*h2.*li.*\)\033\[m.*
              +
              +
              +

              You are Some Kind of Web Guru, I Have Stars in My Eyes

              +

              Good, +that's it! This is exactly the code you can use to write your own real +Ruby blog. If you're feeling adventurous, I'd check out the Rails videos which show a swift young fellow creating a blog in 15 minutes. You just sit back and watch.

              +

              I +should mention Rails. You have been learning the Ruby language, how to +speak it. But Rails is a bunch of libraries (sort of like the popup +library we've been using.) It's a very powerful toolkit for building +websites. If you're interested in learning about Rails, I would head + over there right away. Start using your Ruby skills proper!

              +

              One thing Rails has is easy methods for dates. Like, try: Time.now - 2.weeks

              +
              class Integer; def weeks; self * 7*24*60*60; end; end
              +
              \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-+]\d{4}
              +
              +
              +

              If You Want to Start Small

              +

              If you'd like to start writing little Ruby programs just to practice, I have a project called MouseHole + which is a little web toolkit for writing short Ruby programs. You can look over a few + scripts to see what I mean.

              +

              MouseHole +isn't for writing web sites really. It's just for writing little +programs you run inside your browser. Like there's a notepad program +for MouseHole and a program which adds a mouse picture next to links on +the web which link to MouseHole programs.

              +

              I've got a MouseHole script inside a file here:
              + print File.read("/MouseHole/flickrpedia.user.rb")

              +
              .*Inserts Wikipedia links for Flickr tags.*
              +
              +
              +

              Summary #8, The Hey-Relax-You-Did-Good Summary

              +

              This last section took a moment to wind down, to give you some pointers as to how you can use Ruby. If you enjoyed yourself, + download Ruby and install it.

              + +

              Once you have Ruby installed, you can use Interactive Ruby by running irb on your system's prompt. For more on Irb, + there's The Tiger's Vest to help you.

              +

              You +really deserve a double-layer cake with double-double frosting and a +guy playing one of those guitars that's a double guitar. I mean you +finished, you really did! No doubt about it, you're a certified +red-blooded smartiac!

              +
              +
              + + diff --git a/tryruby/config.ru b/tryruby/config.ru new file mode 100644 index 0000000..73c9258 --- /dev/null +++ b/tryruby/config.ru @@ -0,0 +1,4 @@ +# This file is used by Rack-based servers to start the application. + +require ::File.expand_path('../config/environment', __FILE__) +run Tryruby::Application diff --git a/tryruby/config/application.rb b/tryruby/config/application.rb new file mode 100644 index 0000000..d12142e --- /dev/null +++ b/tryruby/config/application.rb @@ -0,0 +1,42 @@ +require File.expand_path('../boot', __FILE__) + +require 'rails/all' + +# If you have a Gemfile, require the gems listed there, including any gems +# you've limited to :test, :development, or :production. +Bundler.require(:default, Rails.env) if defined?(Bundler) + +module Tryruby + class Application < Rails::Application + # Settings in config/environments/* take precedence over those specified here. + # Application configuration should go into files in config/initializers + # -- all .rb files in that directory are automatically loaded. + + # Custom directories with classes and modules you want to be autoloadable. + # config.autoload_paths += %W(#{config.root}/extras) + + # Only load the plugins named here, in the order given (default is alphabetical). + # :all can be used as a placeholder for all plugins not explicitly named. + # config.plugins = [ :exception_notification, :ssl_requirement, :all ] + + # Activate observers that should always be running. + # config.active_record.observers = :cacher, :garbage_collector, :forum_observer + + # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. + # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. + # config.time_zone = 'Central Time (US & Canada)' + + # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. + # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] + # config.i18n.default_locale = :de + + # JavaScript files you want as :defaults (application.js is always included). + # config.action_view.javascript_expansions[:defaults] = %w(jquery rails) + + # Configure the default encoding used in templates for Ruby 1.9. + config.encoding = "utf-8" + + # Configure sensitive parameters which will be filtered from the log file. + config.filter_parameters += [:password] + end +end diff --git a/tryruby/config/boot.rb b/tryruby/config/boot.rb new file mode 100644 index 0000000..4489e58 --- /dev/null +++ b/tryruby/config/boot.rb @@ -0,0 +1,6 @@ +require 'rubygems' + +# Set up gems listed in the Gemfile. +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) + +require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) diff --git a/tryruby/config/database.yml b/tryruby/config/database.yml new file mode 100644 index 0000000..90d87cc --- /dev/null +++ b/tryruby/config/database.yml @@ -0,0 +1,22 @@ +# SQLite version 3.x +# gem install sqlite3 +development: + adapter: sqlite3 + database: db/development.sqlite3 + pool: 5 + timeout: 5000 + +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". +# Do not set this db to the same as development or production. +test: + adapter: sqlite3 + database: db/test.sqlite3 + pool: 5 + timeout: 5000 + +production: + adapter: sqlite3 + database: db/production.sqlite3 + pool: 5 + timeout: 5000 diff --git a/tryruby/config/environment.rb b/tryruby/config/environment.rb new file mode 100644 index 0000000..8e899fa --- /dev/null +++ b/tryruby/config/environment.rb @@ -0,0 +1,5 @@ +# Load the rails application +require File.expand_path('../application', __FILE__) + +# Initialize the rails application +Tryruby::Application.initialize! diff --git a/tryruby/config/environments/development.rb b/tryruby/config/environments/development.rb new file mode 100644 index 0000000..38d039f --- /dev/null +++ b/tryruby/config/environments/development.rb @@ -0,0 +1,26 @@ +Tryruby::Application.configure do + # Settings specified here will take precedence over those in config/application.rb + + # In the development environment your application's code is reloaded on + # every request. This slows down response time but is perfect for development + # since you don't have to restart the webserver when you make code changes. + config.cache_classes = false + + # Log error messages when you accidentally call methods on nil. + config.whiny_nils = true + + # Show full error reports and disable caching + config.consider_all_requests_local = true + config.action_view.debug_rjs = true + config.action_controller.perform_caching = false + + # Don't care if the mailer can't send + config.action_mailer.raise_delivery_errors = false + + # Print deprecation notices to the Rails logger + config.active_support.deprecation = :log + + # Only use best-standards-support built into browsers + config.action_dispatch.best_standards_support = :builtin +end + diff --git a/tryruby/config/environments/production.rb b/tryruby/config/environments/production.rb new file mode 100644 index 0000000..fdd5b09 --- /dev/null +++ b/tryruby/config/environments/production.rb @@ -0,0 +1,49 @@ +Tryruby::Application.configure do + # Settings specified here will take precedence over those in config/application.rb + + # The production environment is meant for finished, "live" apps. + # Code is not reloaded between requests + config.cache_classes = true + + # Full error reports are disabled and caching is turned on + config.consider_all_requests_local = false + config.action_controller.perform_caching = true + + # Specifies the header that your server uses for sending files + config.action_dispatch.x_sendfile_header = "X-Sendfile" + + # For nginx: + # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' + + # If you have no front-end server that supports something like X-Sendfile, + # just comment this out and Rails will serve the files + + # See everything in the log (default is :info) + # config.log_level = :debug + + # Use a different logger for distributed setups + # config.logger = SyslogLogger.new + + # Use a different cache store in production + # config.cache_store = :mem_cache_store + + # Disable Rails's static asset server + # In production, Apache or nginx will already do this + config.serve_static_assets = false + + # Enable serving of images, stylesheets, and javascripts from an asset server + # config.action_controller.asset_host = "http://assets.example.com" + + # Disable delivery errors, bad email addresses will be ignored + # config.action_mailer.raise_delivery_errors = false + + # Enable threaded mode + # config.threadsafe! + + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation can not be found) + config.i18n.fallbacks = true + + # Send deprecation notices to registered listeners + config.active_support.deprecation = :notify +end diff --git a/tryruby/config/environments/test.rb b/tryruby/config/environments/test.rb new file mode 100644 index 0000000..6bf007b --- /dev/null +++ b/tryruby/config/environments/test.rb @@ -0,0 +1,35 @@ +Tryruby::Application.configure do + # Settings specified here will take precedence over those in config/application.rb + + # The test environment is used exclusively to run your application's + # test suite. You never need to work with it otherwise. Remember that + # your test database is "scratch space" for the test suite and is wiped + # and recreated between test runs. Don't rely on the data there! + config.cache_classes = true + + # Log error messages when you accidentally call methods on nil. + config.whiny_nils = true + + # Show full error reports and disable caching + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Raise exceptions instead of rendering exception templates + config.action_dispatch.show_exceptions = false + + # Disable request forgery protection in test environment + config.action_controller.allow_forgery_protection = false + + # Tell Action Mailer not to deliver emails to the real world. + # The :test delivery method accumulates sent emails in the + # ActionMailer::Base.deliveries array. + config.action_mailer.delivery_method = :test + + # Use SQL instead of Active Record's schema dumper when creating the test database. + # This is necessary if your schema can't be completely dumped by the schema dumper, + # like if you have constraints or database-specific column types + # config.active_record.schema_format = :sql + + # Print deprecation notices to the stderr + config.active_support.deprecation = :stderr +end diff --git a/tryruby/config/initializers/backtrace_silencers.rb b/tryruby/config/initializers/backtrace_silencers.rb new file mode 100644 index 0000000..59385cd --- /dev/null +++ b/tryruby/config/initializers/backtrace_silencers.rb @@ -0,0 +1,7 @@ +# Be sure to restart your server when you modify this file. + +# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. +# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } + +# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. +# Rails.backtrace_cleaner.remove_silencers! diff --git a/tryruby/config/initializers/inflections.rb b/tryruby/config/initializers/inflections.rb new file mode 100644 index 0000000..9e8b013 --- /dev/null +++ b/tryruby/config/initializers/inflections.rb @@ -0,0 +1,10 @@ +# Be sure to restart your server when you modify this file. + +# Add new inflection rules using the following format +# (all these examples are active by default): +# ActiveSupport::Inflector.inflections do |inflect| +# inflect.plural /^(ox)$/i, '\1en' +# inflect.singular /^(ox)en/i, '\1' +# inflect.irregular 'person', 'people' +# inflect.uncountable %w( fish sheep ) +# end diff --git a/tryruby/config/initializers/mime_types.rb b/tryruby/config/initializers/mime_types.rb new file mode 100644 index 0000000..72aca7e --- /dev/null +++ b/tryruby/config/initializers/mime_types.rb @@ -0,0 +1,5 @@ +# Be sure to restart your server when you modify this file. + +# Add new mime types for use in respond_to blocks: +# Mime::Type.register "text/richtext", :rtf +# Mime::Type.register_alias "text/html", :iphone diff --git a/tryruby/config/initializers/secret_token.rb b/tryruby/config/initializers/secret_token.rb new file mode 100644 index 0000000..88f9a7f --- /dev/null +++ b/tryruby/config/initializers/secret_token.rb @@ -0,0 +1,7 @@ +# Be sure to restart your server when you modify this file. + +# Your secret key for verifying the integrity of signed cookies. +# If you change this key, all old signed cookies will become invalid! +# Make sure the secret is at least 30 characters and all random, +# no regular words or you'll be exposed to dictionary attacks. +Tryruby::Application.config.secret_token = '0b9697ad5c8979de943825eeb25418d1f8cf963ad4e3a6758acc2558ae77b0c097997142fea5c9cb5969f2126ee433aefccbae922c04943ca4074d2c31e9c608' diff --git a/tryruby/config/initializers/session_store.rb b/tryruby/config/initializers/session_store.rb new file mode 100644 index 0000000..b4dee00 --- /dev/null +++ b/tryruby/config/initializers/session_store.rb @@ -0,0 +1,8 @@ +# Be sure to restart your server when you modify this file. + +Tryruby::Application.config.session_store :cookie_store, :key => '_tryruby_session' + +# Use the database for sessions instead of the cookie-based default, +# which shouldn't be used to store highly confidential information +# (create the session table with "rails generate session_migration") +# Tryruby::Application.config.session_store :active_record_store diff --git a/tryruby/config/locales/en.yml b/tryruby/config/locales/en.yml new file mode 100644 index 0000000..a747bfa --- /dev/null +++ b/tryruby/config/locales/en.yml @@ -0,0 +1,5 @@ +# Sample localization file for English. Add more files in this directory for other locales. +# See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points. + +en: + hello: "Hello world" diff --git a/tryruby/config/routes.rb b/tryruby/config/routes.rb new file mode 100644 index 0000000..c11e155 --- /dev/null +++ b/tryruby/config/routes.rb @@ -0,0 +1,62 @@ +Tryruby::Application.routes.draw do + get "tutorials/intro" + + root :to => "index#index" + + # The priority is based upon order of creation: + # first created -> highest priority. + + # Sample of regular route: + # match 'products/:id' => 'catalog#view' + # Keep in mind you can assign values other than :controller and :action + + # Sample of named route: + # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase + # This route can be invoked with purchase_url(:id => product.id) + + # Sample resource route (maps HTTP verbs to controller actions automatically): + # resources :products + + # Sample resource route with options: + # resources :products do + # member do + # get 'short' + # post 'toggle' + # end + # + # collection do + # get 'sold' + # end + # end + + # Sample resource route with sub-resources: + # resources :products do + # resources :comments, :sales + # resource :seller + # end + + # Sample resource route with more complex sub-resources + # resources :products do + # resources :comments + # resources :sales do + # get 'recent', :on => :collection + # end + # end + + # Sample resource route within a namespace: + # namespace :admin do + # # Directs /admin/products/* to Admin::ProductsController + # # (app/controllers/admin/products_controller.rb) + # resources :products + # end + + # You can have the root of your site routed with "root" + # just remember to delete public/index.html. + # root :to => "welcome#index" + + # See how all your routes lay out with "rake routes" + + # This is a legacy wild controller route that's not recommended for RESTful applications. + # Note: This route will make all actions in every controller accessible via GET requests. + # match ':controller(/:action(/:id(.:format)))' +end diff --git a/tryruby/db/seeds.rb b/tryruby/db/seeds.rb new file mode 100644 index 0000000..664d8c7 --- /dev/null +++ b/tryruby/db/seeds.rb @@ -0,0 +1,7 @@ +# This file should contain all the record creation needed to seed the database with its default values. +# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). +# +# Examples: +# +# cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }]) +# Mayor.create(:name => 'Daley', :city => cities.first) diff --git a/tryruby/doc/README_FOR_APP b/tryruby/doc/README_FOR_APP new file mode 100644 index 0000000..fe41f5c --- /dev/null +++ b/tryruby/doc/README_FOR_APP @@ -0,0 +1,2 @@ +Use this README file to introduce your application and point to useful places in the API for learning more. +Run "rake doc:app" to generate API documentation for your models, controllers, helpers, and libraries. diff --git a/tryruby/lib/tasks/.gitkeep b/tryruby/lib/tasks/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tryruby/public/404.html b/tryruby/public/404.html new file mode 100644 index 0000000..9a48320 --- /dev/null +++ b/tryruby/public/404.html @@ -0,0 +1,26 @@ + + + + The page you were looking for doesn't exist (404) + + + + + +
              +

              The page you were looking for doesn't exist.

              +

              You may have mistyped the address or the page may have moved.

              +
              + + diff --git a/tryruby/public/422.html b/tryruby/public/422.html new file mode 100644 index 0000000..83660ab --- /dev/null +++ b/tryruby/public/422.html @@ -0,0 +1,26 @@ + + + + The change you wanted was rejected (422) + + + + + +
              +

              The change you wanted was rejected.

              +

              Maybe you tried to change something you didn't have access to.

              +
              + + diff --git a/tryruby/public/500.html b/tryruby/public/500.html new file mode 100644 index 0000000..b80307f --- /dev/null +++ b/tryruby/public/500.html @@ -0,0 +1,26 @@ + + + + We're sorry, but something went wrong (500) + + + + + +
              +

              We're sorry, but something went wrong.

              +

              We've been notified about this issue and we'll take a look at it shortly.

              +
              + + diff --git a/tryruby/public/favicon.ico b/tryruby/public/favicon.ico new file mode 100644 index 0000000..e69de29 diff --git a/tryruby/public/images/background.png b/tryruby/public/images/background.png new file mode 100755 index 0000000000000000000000000000000000000000..3a2dee031614731e46c00b5f8416d471908af982 GIT binary patch literal 35315 zcmV)WK(4=uP)U03uCCnN+uz>Y;o#rV(9hS_)ZpOYp`f3c zmzU(@U5-re2Y+uPI9(B$Ofz`(!I&(GG?)uW=K;osk_tgE4)pO}`F%gV);la$%m z*R`{=m6VgEq@&2k$DN#;x3;#~*x2Ug<-NPR=H=zBtE;iFuc@e~+S=IT;^ENF%h=b~ z!N0%9#=_0Z%(=I>pq`z|$;s8!(wLQ%!@|Ae;o-unWv?s=;r2|nVH4J#Jjq>pq-tps;IoY zx4*x-v$C+9>()6~SnzRSwV zwY0Reva+F{o}8JQ)Y8$Pot&4Jm8GPlmXws8o13Mhqs`09mz0#%)6?46*rcMOzrMbl znwpoDmDJMG+u7Ow|NqR(%goBk)YH?Po13Jgqp7H<+S%EsrKOdWl)1RLoST}jt*xAz zo42*Kp`f6wsi~Khl-k+Yv9Pe0l$F%e(!062nV6W`*xA3my|b~gq@$v=v9PwYv((bl z%*)Ef!^5Paqs+?7w6U_=+1T6I*`1r3yt%ranwy=RoVvHSyScclsi~!-qMe$Wt*or2 zqNA&-slL0rq@kjvqN3Z_*u=rY&CAKd!NHc5l%t`cpPik}%FC9OmDSVIx3#p+%gng7 zwV$4ymz9>dxU-j*mdwe@=;!B_l$Ds5mCee^>FDUy($dw^(|l|yy8r-&c}YY;RCwC# zy$fiSXSzRXL=4`D8dHt;G11yiJRJ*~RH#mzLN4R>QWz9Pjke>~QQYhZMhC0i2aB?2 zRQ{%d|FcyXC`3#I-6~#?5JWL()W%DTP%UlkWs7XK-Ei;^|9#GR?(g${Yps~I+STdo zmPpiyTAYY@|v2Ok*ij{wrb_eFMmKU8EIx8Boto! z!OLkpBin$Uf)I<*@PimvL>~l{4^mt|NT(1f`G1fxgN&4(H+n@muHXkB^c3uaB$p2| z68s<+qCM);*YA1$y`}s?Mmis4>Z(|{YUQd`t45BTH?O9=v9Y?k`v1W3um9Qy8+qp6 zuYpb;ITBiV)yw!^319SD2{T&Qz}3o?JmH(kSIUYVR=ynhsfy<-HPcB@M6S(80wvx>{MGVYRO&%_Sc#W+U3wrU<6yya`wRQpE$l{PZ8@@rs& zW92Go<5l#cBxs7dmH1GA1@=4$Kt~rY5Gq%)qh8nu4A@rFTt&t&i^B^j93x4#1#IkWS6MgTgjNETtl6VpD(QU;f)Uf3P$q7uxcbvUZamH zESAS4dTMNpM3a#sea+?sIg*(n)<{NsO*95V0Yeayy!M*dFtOK&<*Go2*t}*dr9aXj zmDflmH&Wyg?*M28P_wKl8wF!Nk~q@*wNR>&&WqukFPSQ@EGY-wYk{ssc`d}$nvArn zs+p8(AiwKvKTO+BAm$D$gh+`qu12T zn^yzo@C7pr2v-rH3`x|?BPyarJx*)bU>-^EjcX#!Q@ycY&B&lc>zW$&t|2pufPfrt zqyWrgFD4|@d447l#d@S*tA|8nZ+Ni9x`tLthGz3>NUx7*%{*m1FGtEXT&R&kND5aY z(WGV^2{E);LJHmzZc8s1D+L7uc@h-=kpF(aP*NmP{wfl7TzSOk>_9@gQ=HfBlW7$RgKg*7s?7(<2FnVw|QbH zJfw#6l$=DX5z-@TBV4SPZChC-NVD_iul{ z2pjno_;gY3Q*&cp%B04~r?u2BNe2@9%=6+1J{6(HJv0t$UIw1?V#&M&!+BAvNqr_B z^KzhElTxU(c2N@Z^lM&BuO>Ij2{XTY^U`ib`c2J^^1PZJS}NIG^O8pMA`AR@Y>iwI zoygS4d?sTjmy1(*O_-y94Sn<=lVHHNa``f+U?e8xejz?$6$5$(W|#m|Cj5Acf4L{5 z@a0C{h?Lt})aB(~ZON9`l-IEJZadP= zLIul}poh(kaDod$}^s@yfH+Js5qUtV5Q?zyXh zw0n&w>HKn_?8;h`gfmZf9Fzw?*AkvUc9cWO!$#T4o{VxUSV%%2dUtAMP1)DIJf(C> zpgitm;~LHj{&7Vke?VRYeLS(^f8q!ya%kjNUMc@kM&l1Op>Gd8nl$zxY|M^HZ^xSQ zA4WO*8l_sU`GJ(zWSP~E&;Vu!3wGh4UJ*rX^EtWZufHTr!n(%PnK%mp$b* z6l{&8j!YUk0V7R0ArUDqRh@%2G5{BmfU~Ad8^NB9)L4AQ;t;L?G>V&+ST;)>C^5W5rw0$O9(-dg7c!BM%rrXEOa1t}z~K zq7|o{Vx+<~X&hgnhr_F0DNg~WC&J(xwXg>1jbB+K{a}oEE7Fi6-5ND!zw!WR2r=(9 zak}c5ppgybxG1l1Bm0z+4%%WtzGh9l4cSo^?^mp0LuIryudGS8_B;-T^{2n&0pa@hL07C@JDZOAlD~PWNzhx#sYXXHWnCOK|w^LfWAmxkixN`u{Wc@ z;}+;UB~Ds6GAl@pR#1?hLGKtPq7|g^D~J`@QjStCFtdVGq6LbR7Aj}T1%j-x(-o?q zAaE;)Nfi_{X5Q`IQcj6mkjfy6TTo!=K~~*Zum~F&e_|0eGX41N*LB#*)p#g#w)mo^ z5q#-y%g6}|q`l0lQG{F;g^^Opqfk%~NV{jpR0UdhSr!zSe?cH8@Jdy%0_Os&PJulF zMp@YvG)7pCnvWT8b+(iPpSUUojh>=Qryw{KxMDZD>SjmTg^b(8C|V&y1H?y7qwj(2 zDO;t&dE|=Z`X;WJ-))-Gzw_uv$P+8()F)2liaI`$-@+fmi8oAOTCH$0ucmu-0jsN3 zua?z1uU1C}L~C+wWDUJvDNrzt(?}Kt1zuKNP~c)ZdlohFvKs#(>)b+owWdj<<-@CL z!DNjAR3}ji3PP?qP)?5OXp^c7szbqi!9Av~8*`%UfSIk@$!@4+b+y*W%B3ku6Ir}$ zC=+aCTphSIMwMwySE`UywS2A^Fc}(o&Yb$+hepN|d14)$$?)$$Je1)B2A%QcI0n}qe<}feJfIF5xxT)>?7yN$o>Ng#SI1}aA{hkC zGoDhMYUu$rspfldQfntxv!pbZc)2r=m@GA2)XImOTwQefZGbEDeFs;*9!ECxfJHBQ`NjBow=sRLsGB$u{-sxTIcntJ&8(j|abg`cvJPtK0rp-L z3HV=zi|op46E9+O{Ss%wT(rmsum?w61KuL14)}|d#v(xzCpHaFp#}@Igu1DO;Udd# zQAkd-!e)`o72lX-Lphiau-b@;ZqNV=AsS^P2`?Jptg@vXq9y>Wq64f;G>D-Yj0DMv za%jUSj@!rq25PNk1r0kqV1Rr+h7T5V%6@-2aU$2xnKQ9sV%_A)Q8T|7FUHSr)X{N_ z=W%`6Czlt;Cvq8x;lo8m-HS$kF@E-KT!H^71lqU^K3T+#{BLE@-f$*Y;O7hcN8f+} zlLyq{1%FqJPIFc{}DS-8@WAOmDoHy|g< zVoI))%^9o3-vkAj>%wfwm`lv>$(&kFlx;&N6Ut=XIr8SXb-aPP-^^a3Gx`9kD5sY# zWicTZb)l0&8?d|X?&LZJuhWDk3j!U-^aBfMc(+GCu}&qGmIV$pTM-!;*=HtrIwNn#@>} zb-~#gp~>PtxlXo-3L!{YQm)g1mIDZuBXWV{nW_`6la=NGpHN+hoi$~{s8iyTg}KnI z<7(=or4b~=0HveCY$;Ek9ImnzlYQJk-zuY#Cr>sUbg96P75oo9>f^Ql3x_rGFU!iP zlPA*8;oO*5_tza0e{#@@zY66alxM|%pRIX*RP5q8bM%8nvXOs(zKmO$o4JlZWzeh+ z7jTy2CzCpwpc?<(Si!kWBpp2~m|ew0{s~AO8&=ebEyyeIV>p_z3Ep{8K|ydrAQXk5 z_y>mQPv0*1aYQ!?Lwpb(y(;RMw=$AM>gd~y)qW!T64?q4Tu0WTlRH77QH7#a@L6E| zv!u*xZaIuWJjtDp4l=B$F#b%RljYnh6k%d+lnJ|n(JG{bR5seSiFJCZWAF-toyeUq zu|f@Upj<&g8D}D`36*+?E5{=nCh`XfZXo4TKL^_w&SN-`*Z!}UUw+v&^5v7h zk#$srXp2+&P&3YgsWN9&*X#GSY$?x)Ltz5yiee`5ZH*?$-h+BZ|lIs6bQvSY;|f?$q3E%i*XJ`r>d=gSJo zcTU8FLaCowW=VO@oKQ>eCWVn)CPo4-m2_VeCvm4{Wnj6NT)zz-H{e?z|_E;RDu%dPk^8GE^`KI16MAnd_K zbv>E%B1lgbW$7%+(mIu8#U*K1R+g0JA-SGB%7jHelPik>6DgPFJ2?}TrHPALY|@j^ z$Cu%A#oA%RenY>HD>U+o*2^bPS|`h;UfQ~h6)unk4Mu7wu}oC2LbX;p0j11X`wa;e z;#TIYWG#ftg13e)GYn0rtiC?*tJg=i%s7_WTo@`~eVIk8m+bPGoIe|)K=mogd?Z&N z(G4K=4lbX`8D-bJmV>BH{__0!R{VfGZ0&ERS|k4pHuBoF@ZsY8FQu2&(T#e4ulEga z&0e40GgXwvB%!QNZ&@Er<5o6N1mK%5bG-VDnLeNNkDpw98d~-Kmfz&+Q@ndj>Bmk^ zPtgpnbRM5PfBteSey$icY{7)Mk$(f73?D9Fl>HJ8ZtdqVqlHM)Xia>Q0-Y?2%*yBi ziESJ*n~R<&Cq;Pjq&!iQs+u$*1Sp@jT2)FZ*fH+pVH*o$xqJX z1CBPIP?mX3?j)6vqkM|j%dOYYgn>`u*5oz0R@hVU{ubDLit*2XD%7>smrv$3xogPj zWY}hAgeJ`R{0jJ3v0}wqY~-m^7fiTHzv45T$ao~LU9ot@*dzg zR#;wx>t&caR%b^UrcKB)M+PBv((<5{Z5w3j-9*6;05b=}CuurIH#Q-3YyAXf@I40bkkhx< zz6I%d+}6wIDL#_D{Ox53br~OF#DQ?F=!`GK1~9Mz(zFI8F#Q%&0d~lw^;3|1f_UHy z@G>&Myz`peHRMAf zTB(b^#ipVTYyA{A{4$JI?qm31F=574`o)IU$P2KO=}?AanZ~u&jAI4AS41nDn^gi~ z#bu|x+?wi~8YI~9az!R%vRe_e#tn2FR%8kht$WDYhxrMTOE6y%Q_g2{nXByOc}y;I zQYeM7So?Uv3~b~Y-^dG~k%z5aym-ah6|IXYE_5`#TUXGEq{N;jGG8nt<+5UhJPIpX z*NT}@UBOnI6N9eBS1UrZl6h+0jAH~e^jhPk7hE5GaPP!4<9>##^SZDWU`nhi}8&wvLyLh_8}1b`3P2TF+;X4 zR+Gi8i^XZJSV^?SC~aj#vRScMFjt_CVt||owvt51%0#V6&rC(oiUzH^B6~DwHFL=v z0xn)*Yw^XW8>P${w1CMy{yjy zePn0!hhZPXd3@$-N+T~AMjtPRt$i_GjGy_SpS$4)c zuotcTV*I?jnA&tI^fCNP?`q|5=@+kBBOjZAEj|@bY-#0T{O<9P78`j;dSjL_9hSIf zegabwF{O}P#;jB3fz7bYbh9}fe%$1SdEu~xcGypl+^}A!o!8{jK@a1P6!^ve(1S*< zrQexsjeKCoq4ZDh5UKVPeU7)K0V5!zb6TaYbjSMm}+( z^0&2fs|%`KBmd>hf1H6%=3{vn!A#Wynww_W0r2-GWZl&}or0gj)TC$xTh4Vm^~gsVdK>PW3_ZnA}u%o0_Pp zDDhLpF*=WbTU$GceyOK5a^=+%XU?E{f|yF*`}YKT=@Wq_6U1hM8AlT`nV{Ydc|x$7 z-~jMGVM0`*^ven66W|PTf{~4QI1qk0Xot5TCCOkS!6xK4xrnPHHzA7cf&!C7;QOeu6$l+JF<72oQqf_WwEq=kbZ(!ht+@ZuMI*tdV~UoqYAonUC?~ zMX$!O_rM1y>4@~6d9KFC@||3iUY6cJdU8FwEgkOd-dvx+Dhu< z`ENyyTw7aPc@>W9tH)*>Q)iqUJI1eL65bYK#dgO;W@>sfj4lL0l)~$nYezwtq3#+- zAuZet0iSU!H1V-x7S5O(FZER#$3o~pDx`ZXa0tN!=$IGfB{{_p6s)w$FVD$^61p5i zFCEKsa<+}PnAWD4CBOq96JMF&mA**ru3XC$FBmMq&F_L)S=`AaTX9y7gET)py|+_A9f$1G6`5`yP5Io(}pyFm5K#~+`# zO8*%IKUYvAkEh?FERFn!-_4y{i@p38Je6U5eCFdb(9tKZehi);UxgKX?D+U&!1(wC zO!1*0-7)xJjb9w#V{|)11|Q?c7?^_OfSQ{V`CUxk}Tk9}@(|K+!R@ z0&w{Dah2mD#(&rpZT?@Rg#7S*l|o^9_#KBMQyjP+` zyn2Ei^P3zR|38=)=%L#%C-EopC!j_D0=@d%NpmO7oi_jV*XdV{x<;NvoeT%|32J2= zHsP6FDr04GRHj>3rpQ!G&rT(Moj4&&Z%8JrQJBii!Fn8(89AJA6e@cLugrIHl^KDP z{&`6bLhvgEOWEc(xk_`^cB^D4(Qubenlx!H9LVFxH_`8}wML#le-fR^)XfZ} zYG;rq3?SdhN%<|66Lz=oc}>otXtzev6M0R}Js&43!&4HP4L(+2AJ3gM4L(8XXi+ztF#>rwSi%tlGCu2waMB>;q#STZQ@oL<*9uP zjZEk9_#xZkMjk&O$K3g@lanK(B3Fk=y|A6slYUaq@iM3>!%5lE_-T`ylzsdkH@Vus za&pdeQkoRua|N|4ey|ualYY;+HS+7@$IpjmhJOfRD@!|1;<>=+WD+k(X93h{63=QU zP4cta@ObEKQn+e72T-d4Y(^S&k5n$6kaD3Nq7)`*jCcZ7ry=j4_hrdbawgaOj90S4 z`ANn|o8;Ocf5~Zoxk{^6@TrOCk8f&f8Zu-i{>Jjq$W7y6@Tok>k6LSxoJZ}X zNxcB6?ZGa+u(mdXS#5yJpp9jf^N1l@F6$B%Cs^7_n~ zGwJs^b0h!i4^xJ`-o$6Je#DrMFZd)f4L>~NCyu$3=1+ou56+*4hxUAYD(L4QYzm*Q zK{1WI=FXosZ7%=gaXvbt7BT0tp?rYBIq4}N{!9?R=HtIbCrv|8#=;*JPMbDu5>6)} z6Z8iGqD-UcXg3X6Vv6W2{4p?n@CR?8GM83>fd&YKkL)z0jpzu?Y;cK;rp@J?=MpPi zV;EvIDX+;*qJOCX#rc8&%em7yPYg6)%Ac>~a6pMM3gYMjp>e+{N?wzjM6yZLQjSQ#sc=>cO-?|wxoF@1AHm1#=6c%$?HO(8C{j_N^Q-^6R zHlS(dp+Tq3bwIi&^MhBUoj=X773H*GF?Uj=n-+U}$|hoo~LAd#;kYxasvKXyc>Z^t)%Vk^d3@8}*Q;A>7M!DD%lIQ#+`~&$lDnVe-cn zdYRXF^<7W4vASm)!V> zM1(TlG0b0bo>yGt@GU!^$yp&4B9_t(yBI$o&z#wvY~-2L$V~!3FL#lQ!cdL!4}Q9t zPC8#O_!f{8!_$}5d>>ALg4K9yCygB1ux!6z)w?j8s`#F6nL=M^oB$6KB+vo_SIlLNztzIl1Sh(Uj-pdQrptCzoN* z^`ym4ZQ2HXe7ZZ?$lXVeQX|u`4DZ*)4SS#bUThUW~?@1O8}w{Oe7eOOx)m zRMQL%o!|_b)HEM2-xXfh$#@H(6s%JyC<}jX3Ln7l1VZ1%h zfuN|z2gf`n*VOd-c#%>LO)lY3@4O}F2#E|*>)5@ zSDfzN7&Y=Aj&>i_L-}uSjBk1|{yUD>GirvwaeS)#X!q$uhc?o$vbRQt)`m_Vf`cvj zi%m|qDF{K{L&)s=Az}GFe56^AbGQ##KLni+76tN1Z6nzAL%!E3%!S!Dv4G{w zAsT<1K8xGF|NeWtuP1k0BL)Tj9&%6$LuN{mh!~ksXnwIhi;2Xx94LP;_%o$k=!qBx zzFyPWHpBpieE&T{0y5W&h3kjpLK%hMZ<8_z9jo1Xvsd;)-`a&f{jW1uy?tu3$!8miQ36j9 zhTV2lECCi*GerPT8KQz0#b1vM0Y)j3^HBjtTZ9LPZOjPG;W~3B@!CewXOaQuH9)QPx(|Rm^X?_bSkArN0n7b?sPYN3Z@@dY#aw4ES4o2c?xv*q0`T1 zoyO7Ked_MfQ~!SS?x|C!ln0Kxr@AF&Fu=2$-rXd+8`(inK)9=dqiTD%o9+bMeJYG@ z_P;CWs-mY4mfd$17g(KUcX}`t_o%8*f%>RSrHZIIs_{U5T3x!)qWj+^6*f4E1d;!# zfA3~o38uBc2R#SMh@e@H&m{d>1e9N#wNj_AC^D3a)oa za%$ErvIC=8cgYkT@2bOTai!I)S>gl-J^{=!E3)b4`6)!gFceKKy7AS0_jI?y-epKe zCv&1TYnBGb?<;IJYu0Jw&0a2~(0teE~3NjQ zk(VulP9BFJJLqISG>gvXL-Z4lXOP+AL|Q*o}rvEXXQYdwqO=*BiYU((i{?9p2=RL6K=Wm z0OR2IY24Ijx@*}}o<-s4`iu%h6(iE*`Haw!2JPH4CPD_79|GfEZsZ?T@Q*8&VIRNw zCjEZ=sFC601-|{5wJ{#_I2_t2PsO2)DdX8Qu~Xe4^E(vTACk+V7&``imJl2=tF$9l z9|{Q^N=G#%0b!G38ika9E$2r0P-@^qsgdXqc*c8{p3x7WEL+iYIn=@Dk-?|eln-ru z{&<$;o_@EfQ@M|e-`q~WY@Qk!|I;1_;U9qGrbr`?8z=S~xx01BO1Y9sru>xH)1o5p zGR~W@`$h&9EGD?oNt}o1#|1v)T;RZZ+&Cq;QNP1j0un+A1R7#H&edt0<0?@$1}0fk z-k4I>aRJ&e^dynmxv=KrHX<9!hLf@!r&6~wZnJ!if;MZ)R-SQ^`Z&i?1>+o=)+)+Y zamFp9PZe|^QzI|1MlLRf&&|uixg2ik1W8RA;l_>W#A)p#srjWdce;(SG7)a0*=!7z zOAl_nn2hCpQ+lYAL^Od&^Jj>GiCn9+rjfCSJNrV7Ed8E&51JQJ!M(g+hyd+o8d5o#WMQY z)|4sZd{Gf^igrR)l&36nP2w9y!KQH0C<0+Ev+m-}o3f1KFXImtcp5_=58ghQev`d5 z@|(ptq?aj$H?Zx;5sx>P*}%Ns7{{|^Z%kRnpmcwOAA>h=GKHmYu;&|70>Bhe%A7A# zmT{X+nG$U1@`i$sBSMkylqno8;7n1~8{=g0hA^Xl;l9Ddu_DW+@OLN4?2Tpo7*Kjs zECGRjV~PmT@Qqw4WBtit+!SLx1qtHTP=&Ot;{vRD%i$3!mM!JrWSjYhZ7KDuanxPo z!l9wte~yy_W$HsS7$AvHzls}qJFAMx zW*L6~;lAfdBny)sMsdpu*?a~@E zNwZ#@WNV9;*#ogm-BhJ`nv&r&h{X&G4l2OKNX2DQs3 zRDXMdd)Aa~v*7(^v2oWjdg8^#y|_4RvO+6f_LPeg+h3d@sTH)QQZNnvrti${(6768 z-QIP(Fa7NiY2<&wM&3@R@|)XxJKoGNf3C5%VMf#941RAGZ_jqW7Pd#TNqauVmwblX^*RYN>4;+ttKi{H!u@FsoM^*+w%$&mfQAVxZOnJr?`W+3$EF29~>sZO4dB* zxC+SPFha1w5t=%SYOwdPJEILA979IrvY~9?gF`73fnBJWY9vs?Ya9qT}QAdOZ+U~kbSu!b7V#Dsbef##NP4xFgLL=Y4&7Hh!m)NS$ z;CO@%-@e_;y!m#MZx2AJ!!+9y_$hIvnu9Y!1uJKhDfsrxF}Ekow{K77vVD7wl()xK zN>`8V!EAe)k_NaOC`Wm3_e8d5sHQb?nq;%59PjyHpGrg~QzLmVYGU|Uv8gXM@)>Pp z_>g=X$1ZHRW&%K&$V|91`iI^w%M*-IZ#$BLm%ua=Jq5_CWGTW z(*W5~-j(nTz=^WP5qIrMX}#O<+BKN^6+Tz=-SoKfOy!xY*2sPP_PwoR*DgJ`>1In> z=yI2v@!YRdmr2vxktCC`0i_xU&$QZfy4#|-ZCTvTl*#i_$dU4G@BAG1=h4WXa(a{7 zR;+9wa-zH|?yGcEcBS9b+p#wtxwmikg#&rhrpG(3R#slE#76!zHu9!TeNkn-d^;Y= zb*$<^o3!1P4tG}%u)8vc-<9E>$wx|(3scZ@P zuHNEgMLFt{UCDmfm6qbJo->3t?)!Mhm@)LHHhd#vC&Q)h?HA+4_&E>gQGCH+{P^*h zF=OcujaVa(*|F*Ici%xb`_CA`^EtpNCVhM7-Z!f_3A?_%Wto9Y-=4g(qmtz|^q5QE z9?<*#Fe-hsB--1(%Z_qiX~oQTeKQw~Pg@x9sbU8VXk_|}4%*27vI83V@#DUa@nmLC zy7eVDjm;~0Ae>S{^;HX|DJzB&ykKay5=bT*;&yC(TRGYH4Kcdy{Dp5ID#i>gTyDES zp{7={TR>c$D8`T7%zq$1wX$5 zCoUYt(91ihyL;3M`XekMSH zhMU;@u}r~+)`$R;$9)L}9}v3Wk}YwL3WQ^yO{l_kU;Os)9Y%!9cc^@fpL-rtJTf96 z3`yQR-$b~?AFaOYON1X&E`*QIDJDfP^7zgH(6p~)%t(F3wy&nh_SsW@EX1h_-#w-n zNQ#MrBZZ+g%==1I5PU~ZDj1C2HZcNiKF9+MF6fcK4?CMSxyXIRb%)Z> zAUgt!O@U2cjbZ?N+e8WMARI|x2XP~R`XZW}Fb@7CXA>)sk4ukCG$J8oPk9HSknJX< z^*9(jHcw{OR~SDQdsi^^&z>>}`Z8%ICnZ3BgvT2tHRaEl$ilO4atAQ)smh82&;NZrRMG4bb-E#)z0ByA>)aK%32B|LU; z%_&V@jFJ2v+pc6o`SBRGqKIQO2>I?X>SOrDReCIYZ0ySc%RAVHBUR+Jl=8+KivKF8^AM}BkekJr z4#OJVL3?8ZjzaISm?3Ja&zQg`jnNKEe9R87-!UeYL>81&!!XkwJEE{VB3e5Vad*VK zkR9b6(IzUDxOMpO4cYj0uh0 zhZNA~d}O27x+n+w@Ud>JtU$LeSdGP%YTy$%UO=!8XR$x}0X~KyM}b(UOBa*<$0F?j zvrd4N3$NFi1H;F>$Fl8M$Eo&P z5sN-CmVU32M?Iq2CrKj*$|)G3zEPq3_)_*s%EQ)VOIh;nlh}klsmR_cW*=O#rrgKv zy0%%8fdH(FV^#4~3zlSPtXs z*NcjZ=&$F*jSOGc@goLX_o2Q%o(8AS@#8ji*f!C~8%s@EA2*h%vOz_8#$G*n{k>kD=fiHU<4_O34SyHyrM5d{m z8}C|Nsy@ zVU1c;bfD-U`N=6n5m%=P+leUe458CfEMT9%aA-w5j> zGBZp?Qxn^gKr~y*>J?|9=2p7nxkp#+7!AKI=11} zhKAAGwly_vvlAH``4OJgMbz-p_cC?uU35L6i#0{wqUgFh%d03hElPTuM3m@8hPwLHt>*R+4ftDu4OOM z4l}It=zU(*TY2ixF{31>*BI;!=S(Uq$l!N6jCEoD<9y)TW9DAj{q$i9`U)($F~5p30@kUD_qe@KD0an)gy2_ zz?MZ2>k(Q2&?B~g#Bms}=#k<+QWFY$AjEt`w?{<{@P33dLX->|G!Fp;YCQEa3{u3G z2I54Idcy(!&ILlXJ>aVNC|Ak`1CoYETvMr(7K|xiZ3I-DrQ(E%JCHSH+b3qo-+-wh zXg>&B>i9?tN7qN}kfxWiqD)u9JHUPMNYY2E2FBrl4Mo}_)??a~v|pr@b9XoN@q<&R zj{f^mJCQ-spyL3&9`WJ*h@x?ivyLyAy#PK^c>`4l7uctSL#1jsAa3B(Aj=}Mf5hJf za3hK|Fh@cmAV1OtJxPz$05lv3%b;{QAV+VYU7?mbz%|B=gE_TO5wm$D!8NN#2lV?A z=?Gu4C?ZJ_D|4XSfP2|MWT*fHh!1x|gKi6>QCA!=CJm1cNEsg$Ny-gHIZ!?jwt#Cy zREx;!fbws6q&s$iceNpG9_L`@*-}O>)WA5EPU29HLSr&%2~8Ws8Bi)*Ig33SPUGFX zcRv{Y;D6)atl~z7BYF4e-L91z-1NWO7~NxzqyL5z`v29~jcvU90Sx+MPj(`AJ{awL zc{IP|oE}YIu55fU;b^f5My$i@XhKm0zm(yfcug-0ZsAE7g%FMmW^Xc-Fs5o4tzyFw z_|fKL**X~C_@k{RIZ!s;=+Rc)h5#4nHCVNhlx#b4p=_yZU@PHhzm>i;qXYK_zq<`N zQ8ox`2i>?(gha&A4OVR1w$Wm}dw1sp?Bmi0^f%1xM1JsKcjxZiqeFjTSIZ?_gI0y9 zb6N7)AG*~TB(Sv)1bufy8a&rA)|dE=C6t9d8sd0bncWt7w?xufj2@kuq>tSYu|U=C z(SbrXlzs7b2RaRLoQ9OLF!pY(X>61g z(#hEqr_q#tE|jS{opdKKl!BUgkPXm6Z%PQi?(?>TjEY3H)SbwIG8CPG2_MVUNiHPs zWKAdT%xKy>-qhV%)J`%&Ph@^S2g>&`8U~^B5dG&-k*pKq07`V?DU)0nFD3!LMHdc@P3GQ|Gvx&gC_KB#q}d=yi*rH zcyRIJMf#JJp^-PB7z|2F$&8wsS0KkL-&jnBowR7;rq=4bqcu54ot<#DI{ZIQYzU15iz7hW&R*1 z%BCS>_IMD?ty~hL6s!AyO}Wza!o#LCC&~{Vu+anAs|U6_S`OX0Qnz!ZzDfzY*-@4_ zrCbqd88Qx8aXa}a54dq2ut%xWmC~n*($b3?Hqc+;vqpx_M$A$=nQ=m9$SzzvNk(!O ziHQtx>-0i&;uNFtfJ~7;<^I6gKj7RX?gLXP3Ud@S_AARDa7-fA$+)E^RX;8OC%|cT zdNto3lYcez_L=jHD#Kk}`k>SbDqs(^?xoxzd{If(l=<0tklZsqsHnqT zwW!-3$d0m?kbO|sR&1WVQs143rE*mZe&x`KrChAS|K>ebNc(K%YTnx;- zMMN^<%69Pn3||*xdNEy#bJ3@jE#-??heXo8sy@zV260h=H8Zi!nsUHO7Q+HC{>7M3 z!jb}C%!RVj3HZU7m!Fk>=9-5TpG7+sliF|*PGcB_^tbq|kx2%s(hZ+o+<-L54kn+K zvYgxhvy1QrA~4$k+&6&YB5FT_*Tv5eqm*yt0b)>sLk)4X0?i0ST}>r}Y_v3-eO8LU;~S`q>7Ne|C{m*??0(fow_{iBL+3 zE~fq&F~-a(8N7V<857TzGQCPKvI`XmjW^(fPw)sz<> z0mzYx#3(tUhU5RyTyzE(d$j7+$l0*hj#-4fm|x02cwD@gZ^}LS zT>SAVU+hi1i#^aQETl$$!#6SvQEhlJUW}jbD5NgMJA4%`U*17~kTq b}X6WEoFQ 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 + + + + +

              you shouldn't be here.. kicking you out!

              + + diff --git a/tryruby/public/images/rails.png b/tryruby/public/images/rails.png new file mode 100644 index 0000000000000000000000000000000000000000..d5edc04e65f555e3ba4dcdaad39dc352e75b575e GIT binary patch literal 6646 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 AQ~&?~ literal 0 HcmV?d00001 diff --git a/tryruby/public/images/tile.png b/tryruby/public/images/tile.png new file mode 100755 index 0000000000000000000000000000000000000000..399139f26d14e29a407d8b4bb8473ad2279edc41 GIT binary patch literal 305 zcmV-10nYx3P)e#ZdVeV@YYlo&$tx`(sO@ILaF1IwM9!1&Y00000NkvXXu0mjf DW=Vhn literal 0 HcmV?d00001 diff --git a/tryruby/public/javascripts/application.js b/tryruby/public/javascripts/application.js new file mode 100644 index 0000000..fe45776 --- /dev/null +++ b/tryruby/public/javascripts/application.js @@ -0,0 +1,2 @@ +// Place your application-specific JavaScript functions and classes here +// This file is automatically included by javascript_include_tag :defaults diff --git a/tryruby/public/javascripts/console.js b/tryruby/public/javascripts/console.js new file mode 100644 index 0000000..e7e8b79 --- /dev/null +++ b/tryruby/public/javascripts/console.js @@ -0,0 +1,288 @@ +jQuery.fn.debug = function() { + var msg = jqArray.args(arguments); + $("
              ").addClass("error").text(msg.join(", ")).prependTo(this); +} + +jQConsole = function(input, output) { + + var args = jqArray.args + + var input = input; + + // History + var command_history = []; + var command_selected = 0; + + var local_scope = safe_scope(); + + function hide_fn(fn) { return function() { return fn.apply(this, arguments); } } + hide_fn.desc = "A function that creates a wrapper that hides the implementation of another function"; + function queue_fn(fn, time) { if(!time) time = 0; return function() { setTimeout(fn, time); } } + queue_fn.desc = "Turns a function into a function that's called later"; + + var keys = function (o) { + var r = []; + if (typeof o != "object") return r; + for (var k in o) r.push(k); + return r; + } + var refocus = queue_fn(function() { input.blur().focus(); }); + var reset_input = queue_fn(function() { input.val("").blur().focus(); }); + function no_recurse(fn, max_depth) { + var count = 0; + if(!max_depth) max_depth = 1; + return function() { + count++; + if(count > max_depth) { + count--; return; + } else { + fn.apply(this, arguments); + } + } + } + + function hook_fn(fn, listener) { + fn.listener = function() { return listener; } + fn.apply = function(thisArg, argArray) { + if(fn == caller) return; + listener(); + return fn.apply(thisArg, argArray); + }; + } + + hook_fn(history, function() { print("Yo"); }); + + $(document).ready(page_onload); + + function page_onload() { + input = $(input); + output = $(output); + input.keypress(map_keyboard()); + $(document).click(refocus); + refocus(); + } + page_onload = hide_fn(page_onload); + + function clear() { output.html(""); } + + function history() { + return command_history.join("\n"); + } + + var keyLogging = false; + + function map_keyboard() { + var cmdKeys = keymap(); + with(cmdKeys) { + mapKeyCode(toggleKeyLogging, 120); + map(executeCommand, {keyCode:13, ctrlKey:true}); + //mapKeyCode(executeCommand, 13); + mapKeyCode(refocus, 9); + map(historyLast, {keyCode:38, ctrlKey:true}); + map(historyNext, {keyCode:40, ctrlKey:true}); + map(function() { return false; }, {keyCode:123}); + } + return function(e) { + if(keyLogging) + log("keyCode: " + e.keyCode, " shiftKey: " + e.shiftKey, " ctrlKey: " + e.ctrlKey); + resize_input(); + return cmdKeys.dispatch(e); + } + } + + function toggleKeyLogging() { keyLogging = !keyLogging; } + + function historyLast() { + command_selected = Math.max(0, command_selected - 1); + edit_command(command_history[command_selected]); + } + + function historyNext() { + command_selected = Math.min(command_history.length, command_selected + 1); + var cmd = (command_selected == command_history.length) ? "" : command_history[command_selected]; + edit_command(cmd); + } + + function tryComplete() { + + refocus(); + } + + function executeCommand(cmd) { + cmd = (!cmd) ? input.val() : cmd; + reset_input(); + var result = evalInScope(cmd, default_scope); + command_selected = command_history.length; + logCommand(cmd, result); + setTimeout(function() { input.attr("rows", 1); }, 2); + return false; + } + + function evalInScope(cmd, scope) { + try { + + //if(!scope) return eval.apply(our_scope, [cmd]); + with(scope) { + with(jQConsole.our_scope) { + return eval(cmd); + } + } + + //move_modified_scope(local_scope, global_scope); + } + catch(e) { + return e.message; + } + } + + function move_modified_scope(l, g) { + + for(var k in g) { + if(g[k] && typeof l[k] == 'undefined') { + l[k] = g[k]; + g[k] = null; + } + } + } + + function safe_scope() { + var s = {}, g = jQConsole.global_scope; + for(var k in g) { s[k] = null; } + s.global_scope = jQConsole.global_scope; + return s; + } + + var encoders = { + "object": function(o, l) { + if(o.constructor == Array) + return encode_array(o); + //return "[array]"; + return "{ " + encode_obj(o, l) + " }"; + }, + "function": function(v) { return v.toString(); }, + "string": function(v) { return "\"" + v + "\""; }, + "undefined": function() { return "undefined"; }, + _default: function(v) { return v.toString(); } + } + + function encode_array(a) { + var r = a.map(enc); + return "[" + r.join(",") + "]"; + } + + enc = function(v, l, root) { + root = root || true; + if(v == null) return (root) ? "" : "null" + l; + if(encoders[typeof v]) return encoders[typeof v](v); + //log("enc", v, l); + return encoders._default(v, l); + } + + function encode_obj(val, expand) { + if(expand <= 0) { return val.toString(); } + var r = []; + for(var i in val) { + r.push(i + ": " + enc(val[i], expand - 1, false)); + } + return r.join(",\n"); + } + + function encode_reg(s) { + return s.replace(/([\\/\t\n])/g, "\\$1"); + } + + function reg_lookup_fn(lookup) { + var re = new RegExp(encode_reg(keys(lookup).join("")), "ig"); + return re; + } + + function print(msg) { + var className = (typeof msg == "function") ? "cmd" : "print"; + msg = enc(msg, 3); + if(!msg) return; + var out = $($.PRE({"className":className}, msg)); + if(className == "cmd") { out.click(select_command); } + output.prepend(out); + } + + function logCommand(cmd, result) { + command_history.push(cmd); + if(result != undefined) { + output.prepend(jQuery.dump(result)); + } + $($.PRE({className:'cmd'}, cmd)).click(select_command).prependTo(output); + //print(result); + return cmd; + } + + function select_command() { + edit_command($(this).text()); + } + + function edit_command(cmd) { + input.val(cmd); + resize_input(); + input.get(0).select(); + } + + function log() { + var msg = args(arguments); + $("
              ").text(msg.join(", ")).prependTo(output); + } + + function resize_input() + { + setTimeout(do_resize, 0); + + function do_resize() { + var rows = input.val().split(/\n/).length + // + 1 // prevent scrollbar flickering in Mozilla + + (window.opera ? 1 : 0); // leave room for scrollbar in Opera + + // without this check, it is impossible to select text in Opera 7.60 or Opera 8.0. + if (input.attr("rows") != rows) + input.attr("rows", rows); + } + } + + var default_scope = { + "log": log, + "history": history, + alert: function(msg) { alert(msg); } + } + disable_functions(default_scope, "window,document,t1"); + + function disable_functions(obj, list) { + var list = list.split(","); + for(var i in list) { + obj[list[i]] = {}; + } + } + + return this; +}; + +jQuery.extend(jQuery.fn, { + "autoresize": function() + { + var thisp = this; + setTimeout(do_resize, 0); + + function do_resize() { + var s = thisp.val() || ""; + var rows = s.split(/\n/).length; + // + 1 // prevent scrollbar flickering in Mozilla + + (window.opera ? 1 : 0); // leave room for scrollbar in Opera + + // without this check, it is impossible to select text in Opera 7.60 or Opera 8.0. + if (thisp.attr("rows") != rows) + thisp.attr("rows", rows); + } + return this; + } +}) + + + +jQConsole.global_scope = this; +jQConsole.our_scope = {}; \ No newline at end of file diff --git a/tryruby/public/javascripts/controls.js b/tryruby/public/javascripts/controls.js new file mode 100644 index 0000000..ca29aef --- /dev/null +++ b/tryruby/public/javascripts/controls.js @@ -0,0 +1,963 @@ +// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// (c) 2005-2008 Ivan Krstic (http://blogs.law.harvard.edu/ivan) +// (c) 2005-2008 Jon Tirsen (http://www.tirsen.com) +// Contributors: +// Richard Livsey +// Rahul Bhargava +// Rob Wills +// +// script.aculo.us is freely distributable under the terms of an MIT-style license. +// For details, see the script.aculo.us web site: http://script.aculo.us/ + +// Autocompleter.Base handles all the autocompletion functionality +// that's independent of the data source for autocompletion. This +// includes drawing the autocompletion menu, observing keyboard +// and mouse events, and similar. +// +// Specific autocompleters need to provide, at the very least, +// a getUpdatedChoices function that will be invoked every time +// the text inside the monitored textbox changes. This method +// should get the text for which to provide autocompletion by +// invoking this.getToken(), NOT by directly accessing +// this.element.value. This is to allow incremental tokenized +// autocompletion. Specific auto-completion logic (AJAX, etc) +// belongs in getUpdatedChoices. +// +// Tokenized incremental autocompletion is enabled automatically +// when an autocompleter is instantiated with the 'tokens' option +// in the options parameter, e.g.: +// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' }); +// will incrementally autocomplete with a comma as the token. +// Additionally, ',' in the above example can be replaced with +// a token array, e.g. { tokens: [',', '\n'] } which +// enables autocompletion on multiple tokens. This is most +// useful when one of the tokens is \n (a newline), as it +// allows smart autocompletion after linebreaks. + +if(typeof Effect == 'undefined') + throw("controls.js requires including script.aculo.us' effects.js library"); + +var Autocompleter = { }; +Autocompleter.Base = Class.create({ + baseInitialize: function(element, update, options) { + element = $(element); + this.element = element; + this.update = $(update); + this.hasFocus = false; + this.changed = false; + this.active = false; + this.index = 0; + this.entryCount = 0; + this.oldElementValue = this.element.value; + + if(this.setOptions) + this.setOptions(options); + else + this.options = options || { }; + + this.options.paramName = this.options.paramName || this.element.name; + this.options.tokens = this.options.tokens || []; + this.options.frequency = this.options.frequency || 0.4; + this.options.minChars = this.options.minChars || 1; + this.options.onShow = this.options.onShow || + function(element, update){ + if(!update.style.position || update.style.position=='absolute') { + update.style.position = 'absolute'; + Position.clone(element, update, { + setHeight: false, + offsetTop: element.offsetHeight + }); + } + Effect.Appear(update,{duration:0.15}); + }; + this.options.onHide = this.options.onHide || + function(element, update){ new Effect.Fade(update,{duration:0.15}) }; + + if(typeof(this.options.tokens) == 'string') + this.options.tokens = new Array(this.options.tokens); + // Force carriage returns as token delimiters anyway + if (!this.options.tokens.include('\n')) + this.options.tokens.push('\n'); + + this.observer = null; + + this.element.setAttribute('autocomplete','off'); + + Element.hide(this.update); + + Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this)); + Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this)); + }, + + show: function() { + if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update); + if(!this.iefix && + (Prototype.Browser.IE) && + (Element.getStyle(this.update, 'position')=='absolute')) { + new Insertion.After(this.update, + ''); + this.iefix = $(this.update.id+'_iefix'); + } + if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50); + }, + + fixIEOverlapping: function() { + Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)}); + this.iefix.style.zIndex = 1; + this.update.style.zIndex = 2; + Element.show(this.iefix); + }, + + hide: function() { + this.stopIndicator(); + if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update); + if(this.iefix) Element.hide(this.iefix); + }, + + startIndicator: function() { + if(this.options.indicator) Element.show(this.options.indicator); + }, + + stopIndicator: function() { + if(this.options.indicator) Element.hide(this.options.indicator); + }, + + onKeyPress: function(event) { + if(this.active) + switch(event.keyCode) { + case Event.KEY_TAB: + case Event.KEY_RETURN: + this.selectEntry(); + Event.stop(event); + case Event.KEY_ESC: + this.hide(); + this.active = false; + Event.stop(event); + return; + case Event.KEY_LEFT: + case Event.KEY_RIGHT: + return; + case Event.KEY_UP: + this.markPrevious(); + this.render(); + Event.stop(event); + return; + case Event.KEY_DOWN: + this.markNext(); + this.render(); + Event.stop(event); + return; + } + else + if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || + (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return; + + this.changed = true; + this.hasFocus = true; + + if(this.observer) clearTimeout(this.observer); + this.observer = + setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); + }, + + activate: function() { + this.changed = false; + this.hasFocus = true; + this.getUpdatedChoices(); + }, + + onHover: function(event) { + var element = Event.findElement(event, 'LI'); + if(this.index != element.autocompleteIndex) + { + this.index = element.autocompleteIndex; + this.render(); + } + Event.stop(event); + }, + + onClick: function(event) { + var element = Event.findElement(event, 'LI'); + this.index = element.autocompleteIndex; + this.selectEntry(); + this.hide(); + }, + + onBlur: function(event) { + // needed to make click events working + setTimeout(this.hide.bind(this), 250); + this.hasFocus = false; + this.active = false; + }, + + render: function() { + if(this.entryCount > 0) { + for (var i = 0; i < this.entryCount; i++) + this.index==i ? + Element.addClassName(this.getEntry(i),"selected") : + Element.removeClassName(this.getEntry(i),"selected"); + if(this.hasFocus) { + this.show(); + this.active = true; + } + } else { + this.active = false; + this.hide(); + } + }, + + markPrevious: function() { + if(this.index > 0) this.index--; + else this.index = this.entryCount-1; + this.getEntry(this.index).scrollIntoView(true); + }, + + markNext: function() { + if(this.index < this.entryCount-1) this.index++; + else this.index = 0; + this.getEntry(this.index).scrollIntoView(false); + }, + + getEntry: function(index) { + return this.update.firstChild.childNodes[index]; + }, + + getCurrentEntry: function() { + return this.getEntry(this.index); + }, + + selectEntry: function() { + this.active = false; + this.updateElement(this.getCurrentEntry()); + }, + + updateElement: function(selectedElement) { + if (this.options.updateElement) { + this.options.updateElement(selectedElement); + return; + } + var value = ''; + if (this.options.select) { + var nodes = $(selectedElement).select('.' + this.options.select) || []; + if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); + } else + value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); + + var bounds = this.getTokenBounds(); + if (bounds[0] != -1) { + var newValue = this.element.value.substr(0, bounds[0]); + var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/); + if (whitespace) + newValue += whitespace[0]; + this.element.value = newValue + value + this.element.value.substr(bounds[1]); + } else { + this.element.value = value; + } + this.oldElementValue = this.element.value; + this.element.focus(); + + if (this.options.afterUpdateElement) + this.options.afterUpdateElement(this.element, selectedElement); + }, + + updateChoices: function(choices) { + if(!this.changed && this.hasFocus) { + this.update.innerHTML = choices; + Element.cleanWhitespace(this.update); + Element.cleanWhitespace(this.update.down()); + + if(this.update.firstChild && this.update.down().childNodes) { + this.entryCount = + this.update.down().childNodes.length; + for (var i = 0; i < this.entryCount; i++) { + var entry = this.getEntry(i); + entry.autocompleteIndex = i; + this.addObservers(entry); + } + } else { + this.entryCount = 0; + } + + this.stopIndicator(); + this.index = 0; + + if(this.entryCount==1 && this.options.autoSelect) { + this.selectEntry(); + this.hide(); + } else { + this.render(); + } + } + }, + + addObservers: function(element) { + Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this)); + Event.observe(element, "click", this.onClick.bindAsEventListener(this)); + }, + + onObserverEvent: function() { + this.changed = false; + this.tokenBounds = null; + if(this.getToken().length>=this.options.minChars) { + this.getUpdatedChoices(); + } else { + this.active = false; + this.hide(); + } + this.oldElementValue = this.element.value; + }, + + getToken: function() { + var bounds = this.getTokenBounds(); + return this.element.value.substring(bounds[0], bounds[1]).strip(); + }, + + getTokenBounds: function() { + if (null != this.tokenBounds) return this.tokenBounds; + var value = this.element.value; + if (value.strip().empty()) return [-1, 0]; + var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue); + var offset = (diff == this.oldElementValue.length ? 1 : 0); + var prevTokenPos = -1, nextTokenPos = value.length; + var tp; + for (var index = 0, l = this.options.tokens.length; index < l; ++index) { + tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1); + if (tp > prevTokenPos) prevTokenPos = tp; + tp = value.indexOf(this.options.tokens[index], diff + offset); + if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp; + } + return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]); + } +}); + +Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) { + var boundary = Math.min(newS.length, oldS.length); + for (var index = 0; index < boundary; ++index) + if (newS[index] != oldS[index]) + return index; + return boundary; +}; + +Ajax.Autocompleter = Class.create(Autocompleter.Base, { + initialize: function(element, update, url, options) { + this.baseInitialize(element, update, options); + this.options.asynchronous = true; + this.options.onComplete = this.onComplete.bind(this); + this.options.defaultParams = this.options.parameters || null; + this.url = url; + }, + + getUpdatedChoices: function() { + this.startIndicator(); + + var entry = encodeURIComponent(this.options.paramName) + '=' + + encodeURIComponent(this.getToken()); + + this.options.parameters = this.options.callback ? + this.options.callback(this.element, entry) : entry; + + if(this.options.defaultParams) + this.options.parameters += '&' + this.options.defaultParams; + + new Ajax.Request(this.url, this.options); + }, + + onComplete: function(request) { + this.updateChoices(request.responseText); + } +}); + +// The local array autocompleter. Used when you'd prefer to +// inject an array of autocompletion options into the page, rather +// than sending out Ajax queries, which can be quite slow sometimes. +// +// The constructor takes four parameters. The first two are, as usual, +// the id of the monitored textbox, and id of the autocompletion menu. +// The third is the array you want to autocomplete from, and the fourth +// is the options block. +// +// Extra local autocompletion options: +// - choices - How many autocompletion choices to offer +// +// - partialSearch - If false, the autocompleter will match entered +// text only at the beginning of strings in the +// autocomplete array. Defaults to true, which will +// match text at the beginning of any *word* in the +// strings in the autocomplete array. If you want to +// search anywhere in the string, additionally set +// the option fullSearch to true (default: off). +// +// - fullSsearch - Search anywhere in autocomplete array strings. +// +// - partialChars - How many characters to enter before triggering +// a partial match (unlike minChars, which defines +// how many characters are required to do any match +// at all). Defaults to 2. +// +// - ignoreCase - Whether to ignore case when autocompleting. +// Defaults to true. +// +// It's possible to pass in a custom function as the 'selector' +// option, if you prefer to write your own autocompletion logic. +// In that case, the other options above will not apply unless +// you support them. + +Autocompleter.Local = Class.create(Autocompleter.Base, { + initialize: function(element, update, array, options) { + this.baseInitialize(element, update, options); + this.options.array = array; + }, + + getUpdatedChoices: function() { + this.updateChoices(this.options.selector(this)); + }, + + setOptions: function(options) { + this.options = Object.extend({ + choices: 10, + partialSearch: true, + partialChars: 2, + ignoreCase: true, + fullSearch: false, + selector: function(instance) { + var ret = []; // Beginning matches + var partial = []; // Inside matches + var entry = instance.getToken(); + var count = 0; + + for (var i = 0; i < instance.options.array.length && + ret.length < instance.options.choices ; i++) { + + var elem = instance.options.array[i]; + var foundPos = instance.options.ignoreCase ? + elem.toLowerCase().indexOf(entry.toLowerCase()) : + elem.indexOf(entry); + + while (foundPos != -1) { + if (foundPos == 0 && elem.length != entry.length) { + ret.push("
            4. " + elem.substr(0, entry.length) + "" + + elem.substr(entry.length) + "
            5. "); + break; + } else if (entry.length >= instance.options.partialChars && + instance.options.partialSearch && foundPos != -1) { + if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) { + partial.push("
            6. " + elem.substr(0, foundPos) + "" + + elem.substr(foundPos, entry.length) + "" + elem.substr( + foundPos + entry.length) + "
            7. "); + break; + } + } + + foundPos = instance.options.ignoreCase ? + elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : + elem.indexOf(entry, foundPos + 1); + + } + } + if (partial.length) + ret = ret.concat(partial.slice(0, instance.options.choices - ret.length)); + return "
                " + ret.join('') + "
              "; + } + }, options || { }); + } +}); + +// AJAX in-place editor and collection editor +// Full rewrite by Christophe Porteneuve (April 2007). + +// Use this if you notice weird scrolling problems on some browsers, +// the DOM might be a bit confused when this gets called so do this +// waits 1 ms (with setTimeout) until it does the activation +Field.scrollFreeActivate = function(field) { + setTimeout(function() { + Field.activate(field); + }, 1); +}; + +Ajax.InPlaceEditor = Class.create({ + initialize: function(element, url, options) { + this.url = url; + this.element = element = $(element); + this.prepareOptions(); + this._controls = { }; + arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!! + Object.extend(this.options, options || { }); + if (!this.options.formId && this.element.id) { + this.options.formId = this.element.id + '-inplaceeditor'; + if ($(this.options.formId)) + this.options.formId = ''; + } + if (this.options.externalControl) + this.options.externalControl = $(this.options.externalControl); + if (!this.options.externalControl) + this.options.externalControlOnly = false; + this._originalBackground = this.element.getStyle('background-color') || 'transparent'; + this.element.title = this.options.clickToEditText; + this._boundCancelHandler = this.handleFormCancellation.bind(this); + this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this); + this._boundFailureHandler = this.handleAJAXFailure.bind(this); + this._boundSubmitHandler = this.handleFormSubmission.bind(this); + this._boundWrapperHandler = this.wrapUp.bind(this); + this.registerListeners(); + }, + checkForEscapeOrReturn: function(e) { + if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return; + if (Event.KEY_ESC == e.keyCode) + this.handleFormCancellation(e); + else if (Event.KEY_RETURN == e.keyCode) + this.handleFormSubmission(e); + }, + createControl: function(mode, handler, extraClasses) { + var control = this.options[mode + 'Control']; + var text = this.options[mode + 'Text']; + if ('button' == control) { + var btn = document.createElement('input'); + btn.type = 'submit'; + btn.value = text; + btn.className = 'editor_' + mode + '_button'; + if ('cancel' == mode) + btn.onclick = this._boundCancelHandler; + this._form.appendChild(btn); + this._controls[mode] = btn; + } else if ('link' == control) { + var link = document.createElement('a'); + link.href = '#'; + link.appendChild(document.createTextNode(text)); + link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler; + link.className = 'editor_' + mode + '_link'; + if (extraClasses) + link.className += ' ' + extraClasses; + this._form.appendChild(link); + this._controls[mode] = link; + } + }, + createEditField: function() { + var text = (this.options.loadTextURL ? this.options.loadingText : this.getText()); + var fld; + if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) { + fld = document.createElement('input'); + fld.type = 'text'; + var size = this.options.size || this.options.cols || 0; + if (0 < size) fld.size = size; + } else { + fld = document.createElement('textarea'); + fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows); + fld.cols = this.options.cols || 40; + } + fld.name = this.options.paramName; + fld.value = text; // No HTML breaks conversion anymore + fld.className = 'editor_field'; + if (this.options.submitOnBlur) + fld.onblur = this._boundSubmitHandler; + this._controls.editor = fld; + if (this.options.loadTextURL) + this.loadExternalText(); + this._form.appendChild(this._controls.editor); + }, + createForm: function() { + var ipe = this; + function addText(mode, condition) { + var text = ipe.options['text' + mode + 'Controls']; + if (!text || condition === false) return; + ipe._form.appendChild(document.createTextNode(text)); + }; + this._form = $(document.createElement('form')); + this._form.id = this.options.formId; + this._form.addClassName(this.options.formClassName); + this._form.onsubmit = this._boundSubmitHandler; + this.createEditField(); + if ('textarea' == this._controls.editor.tagName.toLowerCase()) + this._form.appendChild(document.createElement('br')); + if (this.options.onFormCustomization) + this.options.onFormCustomization(this, this._form); + addText('Before', this.options.okControl || this.options.cancelControl); + this.createControl('ok', this._boundSubmitHandler); + addText('Between', this.options.okControl && this.options.cancelControl); + this.createControl('cancel', this._boundCancelHandler, 'editor_cancel'); + addText('After', this.options.okControl || this.options.cancelControl); + }, + destroy: function() { + if (this._oldInnerHTML) + this.element.innerHTML = this._oldInnerHTML; + this.leaveEditMode(); + this.unregisterListeners(); + }, + enterEditMode: function(e) { + if (this._saving || this._editing) return; + this._editing = true; + this.triggerCallback('onEnterEditMode'); + if (this.options.externalControl) + this.options.externalControl.hide(); + this.element.hide(); + this.createForm(); + this.element.parentNode.insertBefore(this._form, this.element); + if (!this.options.loadTextURL) + this.postProcessEditField(); + if (e) Event.stop(e); + }, + enterHover: function(e) { + if (this.options.hoverClassName) + this.element.addClassName(this.options.hoverClassName); + if (this._saving) return; + this.triggerCallback('onEnterHover'); + }, + getText: function() { + return this.element.innerHTML.unescapeHTML(); + }, + handleAJAXFailure: function(transport) { + this.triggerCallback('onFailure', transport); + if (this._oldInnerHTML) { + this.element.innerHTML = this._oldInnerHTML; + this._oldInnerHTML = null; + } + }, + handleFormCancellation: function(e) { + this.wrapUp(); + if (e) Event.stop(e); + }, + handleFormSubmission: function(e) { + var form = this._form; + var value = $F(this._controls.editor); + this.prepareSubmission(); + var params = this.options.callback(form, value) || ''; + if (Object.isString(params)) + params = params.toQueryParams(); + params.editorId = this.element.id; + if (this.options.htmlResponse) { + var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions); + Object.extend(options, { + parameters: params, + onComplete: this._boundWrapperHandler, + onFailure: this._boundFailureHandler + }); + new Ajax.Updater({ success: this.element }, this.url, options); + } else { + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: params, + onComplete: this._boundWrapperHandler, + onFailure: this._boundFailureHandler + }); + new Ajax.Request(this.url, options); + } + if (e) Event.stop(e); + }, + leaveEditMode: function() { + this.element.removeClassName(this.options.savingClassName); + this.removeForm(); + this.leaveHover(); + this.element.style.backgroundColor = this._originalBackground; + this.element.show(); + if (this.options.externalControl) + this.options.externalControl.show(); + this._saving = false; + this._editing = false; + this._oldInnerHTML = null; + this.triggerCallback('onLeaveEditMode'); + }, + leaveHover: function(e) { + if (this.options.hoverClassName) + this.element.removeClassName(this.options.hoverClassName); + if (this._saving) return; + this.triggerCallback('onLeaveHover'); + }, + loadExternalText: function() { + this._form.addClassName(this.options.loadingClassName); + this._controls.editor.disabled = true; + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: 'editorId=' + encodeURIComponent(this.element.id), + onComplete: Prototype.emptyFunction, + onSuccess: function(transport) { + this._form.removeClassName(this.options.loadingClassName); + var text = transport.responseText; + if (this.options.stripLoadedTextTags) + text = text.stripTags(); + this._controls.editor.value = text; + this._controls.editor.disabled = false; + this.postProcessEditField(); + }.bind(this), + onFailure: this._boundFailureHandler + }); + new Ajax.Request(this.options.loadTextURL, options); + }, + postProcessEditField: function() { + var fpc = this.options.fieldPostCreation; + if (fpc) + $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate'](); + }, + prepareOptions: function() { + this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions); + Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks); + [this._extraDefaultOptions].flatten().compact().each(function(defs) { + Object.extend(this.options, defs); + }.bind(this)); + }, + prepareSubmission: function() { + this._saving = true; + this.removeForm(); + this.leaveHover(); + this.showSaving(); + }, + registerListeners: function() { + this._listeners = { }; + var listener; + $H(Ajax.InPlaceEditor.Listeners).each(function(pair) { + listener = this[pair.value].bind(this); + this._listeners[pair.key] = listener; + if (!this.options.externalControlOnly) + this.element.observe(pair.key, listener); + if (this.options.externalControl) + this.options.externalControl.observe(pair.key, listener); + }.bind(this)); + }, + removeForm: function() { + if (!this._form) return; + this._form.remove(); + this._form = null; + this._controls = { }; + }, + showSaving: function() { + this._oldInnerHTML = this.element.innerHTML; + this.element.innerHTML = this.options.savingText; + this.element.addClassName(this.options.savingClassName); + this.element.style.backgroundColor = this._originalBackground; + this.element.show(); + }, + triggerCallback: function(cbName, arg) { + if ('function' == typeof this.options[cbName]) { + this.options[cbName](this, arg); + } + }, + unregisterListeners: function() { + $H(this._listeners).each(function(pair) { + if (!this.options.externalControlOnly) + this.element.stopObserving(pair.key, pair.value); + if (this.options.externalControl) + this.options.externalControl.stopObserving(pair.key, pair.value); + }.bind(this)); + }, + wrapUp: function(transport) { + this.leaveEditMode(); + // Can't use triggerCallback due to backward compatibility: requires + // binding + direct element + this._boundComplete(transport, this.element); + } +}); + +Object.extend(Ajax.InPlaceEditor.prototype, { + dispose: Ajax.InPlaceEditor.prototype.destroy +}); + +Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, { + initialize: function($super, element, url, options) { + this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions; + $super(element, url, options); + }, + + createEditField: function() { + var list = document.createElement('select'); + list.name = this.options.paramName; + list.size = 1; + this._controls.editor = list; + this._collection = this.options.collection || []; + if (this.options.loadCollectionURL) + this.loadCollection(); + else + this.checkForExternalText(); + this._form.appendChild(this._controls.editor); + }, + + loadCollection: function() { + this._form.addClassName(this.options.loadingClassName); + this.showLoadingText(this.options.loadingCollectionText); + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: 'editorId=' + encodeURIComponent(this.element.id), + onComplete: Prototype.emptyFunction, + onSuccess: function(transport) { + var js = transport.responseText.strip(); + if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check + throw('Server returned an invalid collection representation.'); + this._collection = eval(js); + this.checkForExternalText(); + }.bind(this), + onFailure: this.onFailure + }); + new Ajax.Request(this.options.loadCollectionURL, options); + }, + + showLoadingText: function(text) { + this._controls.editor.disabled = true; + var tempOption = this._controls.editor.firstChild; + if (!tempOption) { + tempOption = document.createElement('option'); + tempOption.value = ''; + this._controls.editor.appendChild(tempOption); + tempOption.selected = true; + } + tempOption.update((text || '').stripScripts().stripTags()); + }, + + checkForExternalText: function() { + this._text = this.getText(); + if (this.options.loadTextURL) + this.loadExternalText(); + else + this.buildOptionList(); + }, + + loadExternalText: function() { + this.showLoadingText(this.options.loadingText); + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: 'editorId=' + encodeURIComponent(this.element.id), + onComplete: Prototype.emptyFunction, + onSuccess: function(transport) { + this._text = transport.responseText.strip(); + this.buildOptionList(); + }.bind(this), + onFailure: this.onFailure + }); + new Ajax.Request(this.options.loadTextURL, options); + }, + + buildOptionList: function() { + this._form.removeClassName(this.options.loadingClassName); + this._collection = this._collection.map(function(entry) { + return 2 === entry.length ? entry : [entry, entry].flatten(); + }); + var marker = ('value' in this.options) ? this.options.value : this._text; + var textFound = this._collection.any(function(entry) { + return entry[0] == marker; + }.bind(this)); + this._controls.editor.update(''); + var option; + this._collection.each(function(entry, index) { + option = document.createElement('option'); + option.value = entry[0]; + option.selected = textFound ? entry[0] == marker : 0 == index; + option.appendChild(document.createTextNode(entry[1])); + this._controls.editor.appendChild(option); + }.bind(this)); + this._controls.editor.disabled = false; + Field.scrollFreeActivate(this._controls.editor); + } +}); + +//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! **** +//**** This only exists for a while, in order to let **** +//**** users adapt to the new API. Read up on the new **** +//**** API and convert your code to it ASAP! **** + +Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) { + if (!options) return; + function fallback(name, expr) { + if (name in options || expr === undefined) return; + options[name] = expr; + }; + fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' : + options.cancelLink == options.cancelButton == false ? false : undefined))); + fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' : + options.okLink == options.okButton == false ? false : undefined))); + fallback('highlightColor', options.highlightcolor); + fallback('highlightEndColor', options.highlightendcolor); +}; + +Object.extend(Ajax.InPlaceEditor, { + DefaultOptions: { + ajaxOptions: { }, + autoRows: 3, // Use when multi-line w/ rows == 1 + cancelControl: 'link', // 'link'|'button'|false + cancelText: 'cancel', + clickToEditText: 'Click to edit', + externalControl: null, // id|elt + externalControlOnly: false, + fieldPostCreation: 'activate', // 'activate'|'focus'|false + formClassName: 'inplaceeditor-form', + formId: null, // id|elt + highlightColor: '#ffff99', + highlightEndColor: '#ffffff', + hoverClassName: '', + htmlResponse: true, + loadingClassName: 'inplaceeditor-loading', + loadingText: 'Loading...', + okControl: 'button', // 'link'|'button'|false + okText: 'ok', + paramName: 'value', + rows: 1, // If 1 and multi-line, uses autoRows + savingClassName: 'inplaceeditor-saving', + savingText: 'Saving...', + size: 0, + stripLoadedTextTags: false, + submitOnBlur: false, + textAfterControls: '', + textBeforeControls: '', + textBetweenControls: '' + }, + DefaultCallbacks: { + callback: function(form) { + return Form.serialize(form); + }, + onComplete: function(transport, element) { + // For backward compatibility, this one is bound to the IPE, and passes + // the element directly. It was too often customized, so we don't break it. + new Effect.Highlight(element, { + startcolor: this.options.highlightColor, keepBackgroundImage: true }); + }, + onEnterEditMode: null, + onEnterHover: function(ipe) { + ipe.element.style.backgroundColor = ipe.options.highlightColor; + if (ipe._effect) + ipe._effect.cancel(); + }, + onFailure: function(transport, ipe) { + alert('Error communication with the server: ' + transport.responseText.stripTags()); + }, + onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls. + onLeaveEditMode: null, + onLeaveHover: function(ipe) { + ipe._effect = new Effect.Highlight(ipe.element, { + startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor, + restorecolor: ipe._originalBackground, keepBackgroundImage: true + }); + } + }, + Listeners: { + click: 'enterEditMode', + keydown: 'checkForEscapeOrReturn', + mouseover: 'enterHover', + mouseout: 'leaveHover' + } +}); + +Ajax.InPlaceCollectionEditor.DefaultOptions = { + loadingCollectionText: 'Loading options...' +}; + +// Delayed observer, like Form.Element.Observer, +// but waits for delay after last key input +// Ideal for live-search fields + +Form.Element.DelayedObserver = Class.create({ + initialize: function(element, delay, callback) { + this.delay = delay || 0.5; + this.element = $(element); + this.callback = callback; + this.timer = null; + this.lastValue = $F(this.element); + Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this)); + }, + delayedListener: function(event) { + if(this.lastValue == $F(this.element)) return; + if(this.timer) clearTimeout(this.timer); + this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000); + this.lastValue = $F(this.element); + }, + onTimerEvent: function() { + this.timer = null; + this.callback(this.element, $F(this.element)); + } +}); \ No newline at end of file diff --git a/tryruby/public/javascripts/dragdrop.js b/tryruby/public/javascripts/dragdrop.js new file mode 100644 index 0000000..07229f9 --- /dev/null +++ b/tryruby/public/javascripts/dragdrop.js @@ -0,0 +1,973 @@ +// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// (c) 2005-2008 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz) +// +// script.aculo.us is freely distributable under the terms of an MIT-style license. +// For details, see the script.aculo.us web site: http://script.aculo.us/ + +if(Object.isUndefined(Effect)) + throw("dragdrop.js requires including script.aculo.us' effects.js library"); + +var Droppables = { + drops: [], + + remove: function(element) { + this.drops = this.drops.reject(function(d) { return d.element==$(element) }); + }, + + add: function(element) { + element = $(element); + var options = Object.extend({ + greedy: true, + hoverclass: null, + tree: false + }, arguments[1] || { }); + + // cache containers + if(options.containment) { + options._containers = []; + var containment = options.containment; + if(Object.isArray(containment)) { + containment.each( function(c) { options._containers.push($(c)) }); + } else { + options._containers.push($(containment)); + } + } + + if(options.accept) options.accept = [options.accept].flatten(); + + Element.makePositioned(element); // fix IE + options.element = element; + + this.drops.push(options); + }, + + findDeepestChild: function(drops) { + deepest = drops[0]; + + for (i = 1; i < drops.length; ++i) + if (Element.isParent(drops[i].element, deepest.element)) + deepest = drops[i]; + + return deepest; + }, + + isContained: function(element, drop) { + var containmentNode; + if(drop.tree) { + containmentNode = element.treeNode; + } else { + containmentNode = element.parentNode; + } + return drop._containers.detect(function(c) { return containmentNode == c }); + }, + + isAffected: function(point, element, drop) { + return ( + (drop.element!=element) && + ((!drop._containers) || + this.isContained(element, drop)) && + ((!drop.accept) || + (Element.classNames(element).detect( + function(v) { return drop.accept.include(v) } ) )) && + Position.within(drop.element, point[0], point[1]) ); + }, + + deactivate: function(drop) { + if(drop.hoverclass) + Element.removeClassName(drop.element, drop.hoverclass); + this.last_active = null; + }, + + activate: function(drop) { + if(drop.hoverclass) + Element.addClassName(drop.element, drop.hoverclass); + this.last_active = drop; + }, + + show: function(point, element) { + if(!this.drops.length) return; + var drop, affected = []; + + this.drops.each( function(drop) { + if(Droppables.isAffected(point, element, drop)) + affected.push(drop); + }); + + if(affected.length>0) + drop = Droppables.findDeepestChild(affected); + + if(this.last_active && this.last_active != drop) this.deactivate(this.last_active); + if (drop) { + Position.within(drop.element, point[0], point[1]); + if(drop.onHover) + drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); + + if (drop != this.last_active) Droppables.activate(drop); + } + }, + + fire: function(event, element) { + if(!this.last_active) return; + Position.prepare(); + + if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active)) + if (this.last_active.onDrop) { + this.last_active.onDrop(element, this.last_active.element, event); + return true; + } + }, + + reset: function() { + if(this.last_active) + this.deactivate(this.last_active); + } +}; + +var Draggables = { + drags: [], + observers: [], + + register: function(draggable) { + if(this.drags.length == 0) { + this.eventMouseUp = this.endDrag.bindAsEventListener(this); + this.eventMouseMove = this.updateDrag.bindAsEventListener(this); + this.eventKeypress = this.keyPress.bindAsEventListener(this); + + Event.observe(document, "mouseup", this.eventMouseUp); + Event.observe(document, "mousemove", this.eventMouseMove); + Event.observe(document, "keypress", this.eventKeypress); + } + this.drags.push(draggable); + }, + + unregister: function(draggable) { + this.drags = this.drags.reject(function(d) { return d==draggable }); + if(this.drags.length == 0) { + Event.stopObserving(document, "mouseup", this.eventMouseUp); + Event.stopObserving(document, "mousemove", this.eventMouseMove); + Event.stopObserving(document, "keypress", this.eventKeypress); + } + }, + + activate: function(draggable) { + if(draggable.options.delay) { + this._timeout = setTimeout(function() { + Draggables._timeout = null; + window.focus(); + Draggables.activeDraggable = draggable; + }.bind(this), draggable.options.delay); + } else { + window.focus(); // allows keypress events if window isn't currently focused, fails for Safari + this.activeDraggable = draggable; + } + }, + + deactivate: function() { + this.activeDraggable = null; + }, + + updateDrag: function(event) { + if(!this.activeDraggable) return; + var pointer = [Event.pointerX(event), Event.pointerY(event)]; + // Mozilla-based browsers fire successive mousemove events with + // the same coordinates, prevent needless redrawing (moz bug?) + if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return; + this._lastPointer = pointer; + + this.activeDraggable.updateDrag(event, pointer); + }, + + endDrag: function(event) { + if(this._timeout) { + clearTimeout(this._timeout); + this._timeout = null; + } + if(!this.activeDraggable) return; + this._lastPointer = null; + this.activeDraggable.endDrag(event); + this.activeDraggable = null; + }, + + keyPress: function(event) { + if(this.activeDraggable) + this.activeDraggable.keyPress(event); + }, + + addObserver: function(observer) { + this.observers.push(observer); + this._cacheObserverCallbacks(); + }, + + removeObserver: function(element) { // element instead of observer fixes mem leaks + this.observers = this.observers.reject( function(o) { return o.element==element }); + this._cacheObserverCallbacks(); + }, + + notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag' + if(this[eventName+'Count'] > 0) + this.observers.each( function(o) { + if(o[eventName]) o[eventName](eventName, draggable, event); + }); + if(draggable.options[eventName]) draggable.options[eventName](draggable, event); + }, + + _cacheObserverCallbacks: function() { + ['onStart','onEnd','onDrag'].each( function(eventName) { + Draggables[eventName+'Count'] = Draggables.observers.select( + function(o) { return o[eventName]; } + ).length; + }); + } +}; + +/*--------------------------------------------------------------------------*/ + +var Draggable = Class.create({ + initialize: function(element) { + var defaults = { + handle: false, + reverteffect: function(element, top_offset, left_offset) { + var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02; + new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur, + queue: {scope:'_draggable', position:'end'} + }); + }, + endeffect: function(element) { + var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0; + new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity, + queue: {scope:'_draggable', position:'end'}, + afterFinish: function(){ + Draggable._dragging[element] = false + } + }); + }, + zindex: 1000, + revert: false, + quiet: false, + scroll: false, + scrollSensitivity: 20, + scrollSpeed: 15, + snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] } + delay: 0 + }; + + if(!arguments[1] || Object.isUndefined(arguments[1].endeffect)) + Object.extend(defaults, { + starteffect: function(element) { + element._opacity = Element.getOpacity(element); + Draggable._dragging[element] = true; + new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7}); + } + }); + + var options = Object.extend(defaults, arguments[1] || { }); + + this.element = $(element); + + if(options.handle && Object.isString(options.handle)) + this.handle = this.element.down('.'+options.handle, 0); + + if(!this.handle) this.handle = $(options.handle); + if(!this.handle) this.handle = this.element; + + if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) { + options.scroll = $(options.scroll); + this._isScrollChild = Element.childOf(this.element, options.scroll); + } + + Element.makePositioned(this.element); // fix IE + + this.options = options; + this.dragging = false; + + this.eventMouseDown = this.initDrag.bindAsEventListener(this); + Event.observe(this.handle, "mousedown", this.eventMouseDown); + + Draggables.register(this); + }, + + destroy: function() { + Event.stopObserving(this.handle, "mousedown", this.eventMouseDown); + Draggables.unregister(this); + }, + + currentDelta: function() { + return([ + parseInt(Element.getStyle(this.element,'left') || '0'), + parseInt(Element.getStyle(this.element,'top') || '0')]); + }, + + initDrag: function(event) { + if(!Object.isUndefined(Draggable._dragging[this.element]) && + Draggable._dragging[this.element]) return; + if(Event.isLeftClick(event)) { + // abort on form elements, fixes a Firefox issue + var src = Event.element(event); + if((tag_name = src.tagName.toUpperCase()) && ( + tag_name=='INPUT' || + tag_name=='SELECT' || + tag_name=='OPTION' || + tag_name=='BUTTON' || + tag_name=='TEXTAREA')) return; + + var pointer = [Event.pointerX(event), Event.pointerY(event)]; + var pos = Position.cumulativeOffset(this.element); + this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) }); + + Draggables.activate(this); + Event.stop(event); + } + }, + + startDrag: function(event) { + this.dragging = true; + if(!this.delta) + this.delta = this.currentDelta(); + + if(this.options.zindex) { + this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0); + this.element.style.zIndex = this.options.zindex; + } + + if(this.options.ghosting) { + this._clone = this.element.cloneNode(true); + this._originallyAbsolute = (this.element.getStyle('position') == 'absolute'); + if (!this._originallyAbsolute) + Position.absolutize(this.element); + this.element.parentNode.insertBefore(this._clone, this.element); + } + + if(this.options.scroll) { + if (this.options.scroll == window) { + var where = this._getWindowScroll(this.options.scroll); + this.originalScrollLeft = where.left; + this.originalScrollTop = where.top; + } else { + this.originalScrollLeft = this.options.scroll.scrollLeft; + this.originalScrollTop = this.options.scroll.scrollTop; + } + } + + Draggables.notify('onStart', this, event); + + if(this.options.starteffect) this.options.starteffect(this.element); + }, + + updateDrag: function(event, pointer) { + if(!this.dragging) this.startDrag(event); + + if(!this.options.quiet){ + Position.prepare(); + Droppables.show(pointer, this.element); + } + + Draggables.notify('onDrag', this, event); + + this.draw(pointer); + if(this.options.change) this.options.change(this); + + if(this.options.scroll) { + this.stopScrolling(); + + var p; + if (this.options.scroll == window) { + with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; } + } else { + p = Position.page(this.options.scroll); + p[0] += this.options.scroll.scrollLeft + Position.deltaX; + p[1] += this.options.scroll.scrollTop + Position.deltaY; + p.push(p[0]+this.options.scroll.offsetWidth); + p.push(p[1]+this.options.scroll.offsetHeight); + } + var speed = [0,0]; + if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity); + if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity); + if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity); + if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity); + this.startScrolling(speed); + } + + // fix AppleWebKit rendering + if(Prototype.Browser.WebKit) window.scrollBy(0,0); + + Event.stop(event); + }, + + finishDrag: function(event, success) { + this.dragging = false; + + if(this.options.quiet){ + Position.prepare(); + var pointer = [Event.pointerX(event), Event.pointerY(event)]; + Droppables.show(pointer, this.element); + } + + if(this.options.ghosting) { + if (!this._originallyAbsolute) + Position.relativize(this.element); + delete this._originallyAbsolute; + Element.remove(this._clone); + this._clone = null; + } + + var dropped = false; + if(success) { + dropped = Droppables.fire(event, this.element); + if (!dropped) dropped = false; + } + if(dropped && this.options.onDropped) this.options.onDropped(this.element); + Draggables.notify('onEnd', this, event); + + var revert = this.options.revert; + if(revert && Object.isFunction(revert)) revert = revert(this.element); + + var d = this.currentDelta(); + if(revert && this.options.reverteffect) { + if (dropped == 0 || revert != 'failure') + this.options.reverteffect(this.element, + d[1]-this.delta[1], d[0]-this.delta[0]); + } else { + this.delta = d; + } + + if(this.options.zindex) + this.element.style.zIndex = this.originalZ; + + if(this.options.endeffect) + this.options.endeffect(this.element); + + Draggables.deactivate(this); + Droppables.reset(); + }, + + keyPress: function(event) { + if(event.keyCode!=Event.KEY_ESC) return; + this.finishDrag(event, false); + Event.stop(event); + }, + + endDrag: function(event) { + if(!this.dragging) return; + this.stopScrolling(); + this.finishDrag(event, true); + Event.stop(event); + }, + + draw: function(point) { + var pos = Position.cumulativeOffset(this.element); + if(this.options.ghosting) { + var r = Position.realOffset(this.element); + pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY; + } + + var d = this.currentDelta(); + pos[0] -= d[0]; pos[1] -= d[1]; + + if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) { + pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft; + pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop; + } + + var p = [0,1].map(function(i){ + return (point[i]-pos[i]-this.offset[i]) + }.bind(this)); + + if(this.options.snap) { + if(Object.isFunction(this.options.snap)) { + p = this.options.snap(p[0],p[1],this); + } else { + if(Object.isArray(this.options.snap)) { + p = p.map( function(v, i) { + return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this)); + } else { + p = p.map( function(v) { + return (v/this.options.snap).round()*this.options.snap }.bind(this)); + } + }} + + var style = this.element.style; + if((!this.options.constraint) || (this.options.constraint=='horizontal')) + style.left = p[0] + "px"; + if((!this.options.constraint) || (this.options.constraint=='vertical')) + style.top = p[1] + "px"; + + if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering + }, + + stopScrolling: function() { + if(this.scrollInterval) { + clearInterval(this.scrollInterval); + this.scrollInterval = null; + Draggables._lastScrollPointer = null; + } + }, + + startScrolling: function(speed) { + if(!(speed[0] || speed[1])) return; + this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed]; + this.lastScrolled = new Date(); + this.scrollInterval = setInterval(this.scroll.bind(this), 10); + }, + + scroll: function() { + var current = new Date(); + var delta = current - this.lastScrolled; + this.lastScrolled = current; + if(this.options.scroll == window) { + with (this._getWindowScroll(this.options.scroll)) { + if (this.scrollSpeed[0] || this.scrollSpeed[1]) { + var d = delta / 1000; + this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] ); + } + } + } else { + this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; + this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000; + } + + Position.prepare(); + Droppables.show(Draggables._lastPointer, this.element); + Draggables.notify('onDrag', this); + if (this._isScrollChild) { + Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer); + Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000; + Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000; + if (Draggables._lastScrollPointer[0] < 0) + Draggables._lastScrollPointer[0] = 0; + if (Draggables._lastScrollPointer[1] < 0) + Draggables._lastScrollPointer[1] = 0; + this.draw(Draggables._lastScrollPointer); + } + + if(this.options.change) this.options.change(this); + }, + + _getWindowScroll: function(w) { + var T, L, W, H; + with (w.document) { + if (w.document.documentElement && documentElement.scrollTop) { + T = documentElement.scrollTop; + L = documentElement.scrollLeft; + } else if (w.document.body) { + T = body.scrollTop; + L = body.scrollLeft; + } + if (w.innerWidth) { + W = w.innerWidth; + H = w.innerHeight; + } else if (w.document.documentElement && documentElement.clientWidth) { + W = documentElement.clientWidth; + H = documentElement.clientHeight; + } else { + W = body.offsetWidth; + H = body.offsetHeight; + } + } + return { top: T, left: L, width: W, height: H }; + } +}); + +Draggable._dragging = { }; + +/*--------------------------------------------------------------------------*/ + +var SortableObserver = Class.create({ + initialize: function(element, observer) { + this.element = $(element); + this.observer = observer; + this.lastValue = Sortable.serialize(this.element); + }, + + onStart: function() { + this.lastValue = Sortable.serialize(this.element); + }, + + onEnd: function() { + Sortable.unmark(); + if(this.lastValue != Sortable.serialize(this.element)) + this.observer(this.element) + } +}); + +var Sortable = { + SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/, + + sortables: { }, + + _findRootElement: function(element) { + while (element.tagName.toUpperCase() != "BODY") { + if(element.id && Sortable.sortables[element.id]) return element; + element = element.parentNode; + } + }, + + options: function(element) { + element = Sortable._findRootElement($(element)); + if(!element) return; + return Sortable.sortables[element.id]; + }, + + destroy: function(element){ + element = $(element); + var s = Sortable.sortables[element.id]; + + if(s) { + Draggables.removeObserver(s.element); + s.droppables.each(function(d){ Droppables.remove(d) }); + s.draggables.invoke('destroy'); + + delete Sortable.sortables[s.element.id]; + } + }, + + create: function(element) { + element = $(element); + var options = Object.extend({ + element: element, + tag: 'li', // assumes li children, override with tag: 'tagname' + dropOnEmpty: false, + tree: false, + treeTag: 'ul', + overlap: 'vertical', // one of 'vertical', 'horizontal' + constraint: 'vertical', // one of 'vertical', 'horizontal', false + containment: element, // also takes array of elements (or id's); or false + handle: false, // or a CSS class + only: false, + delay: 0, + hoverclass: null, + ghosting: false, + quiet: false, + scroll: false, + scrollSensitivity: 20, + scrollSpeed: 15, + format: this.SERIALIZE_RULE, + + // these take arrays of elements or ids and can be + // used for better initialization performance + elements: false, + handles: false, + + onChange: Prototype.emptyFunction, + onUpdate: Prototype.emptyFunction + }, arguments[1] || { }); + + // clear any old sortable with same element + this.destroy(element); + + // build options for the draggables + var options_for_draggable = { + revert: true, + quiet: options.quiet, + scroll: options.scroll, + scrollSpeed: options.scrollSpeed, + scrollSensitivity: options.scrollSensitivity, + delay: options.delay, + ghosting: options.ghosting, + constraint: options.constraint, + handle: options.handle }; + + if(options.starteffect) + options_for_draggable.starteffect = options.starteffect; + + if(options.reverteffect) + options_for_draggable.reverteffect = options.reverteffect; + else + if(options.ghosting) options_for_draggable.reverteffect = function(element) { + element.style.top = 0; + element.style.left = 0; + }; + + if(options.endeffect) + options_for_draggable.endeffect = options.endeffect; + + if(options.zindex) + options_for_draggable.zindex = options.zindex; + + // build options for the droppables + var options_for_droppable = { + overlap: options.overlap, + containment: options.containment, + tree: options.tree, + hoverclass: options.hoverclass, + onHover: Sortable.onHover + }; + + var options_for_tree = { + onHover: Sortable.onEmptyHover, + overlap: options.overlap, + containment: options.containment, + hoverclass: options.hoverclass + }; + + // fix for gecko engine + Element.cleanWhitespace(element); + + options.draggables = []; + options.droppables = []; + + // drop on empty handling + if(options.dropOnEmpty || options.tree) { + Droppables.add(element, options_for_tree); + options.droppables.push(element); + } + + (options.elements || this.findElements(element, options) || []).each( function(e,i) { + var handle = options.handles ? $(options.handles[i]) : + (options.handle ? $(e).select('.' + options.handle)[0] : e); + options.draggables.push( + new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); + Droppables.add(e, options_for_droppable); + if(options.tree) e.treeNode = element; + options.droppables.push(e); + }); + + if(options.tree) { + (Sortable.findTreeElements(element, options) || []).each( function(e) { + Droppables.add(e, options_for_tree); + e.treeNode = element; + options.droppables.push(e); + }); + } + + // keep reference + this.sortables[element.id] = options; + + // for onupdate + Draggables.addObserver(new SortableObserver(element, options.onUpdate)); + + }, + + // return all suitable-for-sortable elements in a guaranteed order + findElements: function(element, options) { + return Element.findChildren( + element, options.only, options.tree ? true : false, options.tag); + }, + + findTreeElements: function(element, options) { + return Element.findChildren( + element, options.only, options.tree ? true : false, options.treeTag); + }, + + onHover: function(element, dropon, overlap) { + if(Element.isParent(dropon, element)) return; + + if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) { + return; + } else if(overlap>0.5) { + Sortable.mark(dropon, 'before'); + if(dropon.previousSibling != element) { + var oldParentNode = element.parentNode; + element.style.visibility = "hidden"; // fix gecko rendering + dropon.parentNode.insertBefore(element, dropon); + if(dropon.parentNode!=oldParentNode) + Sortable.options(oldParentNode).onChange(element); + Sortable.options(dropon.parentNode).onChange(element); + } + } else { + Sortable.mark(dropon, 'after'); + var nextElement = dropon.nextSibling || null; + if(nextElement != element) { + var oldParentNode = element.parentNode; + element.style.visibility = "hidden"; // fix gecko rendering + dropon.parentNode.insertBefore(element, nextElement); + if(dropon.parentNode!=oldParentNode) + Sortable.options(oldParentNode).onChange(element); + Sortable.options(dropon.parentNode).onChange(element); + } + } + }, + + onEmptyHover: function(element, dropon, overlap) { + var oldParentNode = element.parentNode; + var droponOptions = Sortable.options(dropon); + + if(!Element.isParent(dropon, element)) { + var index; + + var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only}); + var child = null; + + if(children) { + var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap); + + for (index = 0; index < children.length; index += 1) { + if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) { + offset -= Element.offsetSize (children[index], droponOptions.overlap); + } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) { + child = index + 1 < children.length ? children[index + 1] : null; + break; + } else { + child = children[index]; + break; + } + } + } + + dropon.insertBefore(element, child); + + Sortable.options(oldParentNode).onChange(element); + droponOptions.onChange(element); + } + }, + + unmark: function() { + if(Sortable._marker) Sortable._marker.hide(); + }, + + mark: function(dropon, position) { + // mark on ghosting only + var sortable = Sortable.options(dropon.parentNode); + if(sortable && !sortable.ghosting) return; + + if(!Sortable._marker) { + Sortable._marker = + ($('dropmarker') || Element.extend(document.createElement('DIV'))). + hide().addClassName('dropmarker').setStyle({position:'absolute'}); + document.getElementsByTagName("body").item(0).appendChild(Sortable._marker); + } + var offsets = Position.cumulativeOffset(dropon); + Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'}); + + if(position=='after') + if(sortable.overlap == 'horizontal') + Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'}); + else + Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'}); + + Sortable._marker.show(); + }, + + _tree: function(element, options, parent) { + var children = Sortable.findElements(element, options) || []; + + for (var i = 0; i < children.length; ++i) { + var match = children[i].id.match(options.format); + + if (!match) continue; + + var child = { + id: encodeURIComponent(match ? match[1] : null), + element: element, + parent: parent, + children: [], + position: parent.children.length, + container: $(children[i]).down(options.treeTag) + }; + + /* Get the element containing the children and recurse over it */ + if (child.container) + this._tree(child.container, options, child); + + parent.children.push (child); + } + + return parent; + }, + + tree: function(element) { + element = $(element); + var sortableOptions = this.options(element); + var options = Object.extend({ + tag: sortableOptions.tag, + treeTag: sortableOptions.treeTag, + only: sortableOptions.only, + name: element.id, + format: sortableOptions.format + }, arguments[1] || { }); + + var root = { + id: null, + parent: null, + children: [], + container: element, + position: 0 + }; + + return Sortable._tree(element, options, root); + }, + + /* Construct a [i] index for a particular node */ + _constructIndex: function(node) { + var index = ''; + do { + if (node.id) index = '[' + node.position + ']' + index; + } while ((node = node.parent) != null); + return index; + }, + + sequence: function(element) { + element = $(element); + var options = Object.extend(this.options(element), arguments[1] || { }); + + return $(this.findElements(element, options) || []).map( function(item) { + return item.id.match(options.format) ? item.id.match(options.format)[1] : ''; + }); + }, + + setSequence: function(element, new_sequence) { + element = $(element); + var options = Object.extend(this.options(element), arguments[2] || { }); + + var nodeMap = { }; + this.findElements(element, options).each( function(n) { + if (n.id.match(options.format)) + nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode]; + n.parentNode.removeChild(n); + }); + + new_sequence.each(function(ident) { + var n = nodeMap[ident]; + if (n) { + n[1].appendChild(n[0]); + delete nodeMap[ident]; + } + }); + }, + + serialize: function(element) { + element = $(element); + var options = Object.extend(Sortable.options(element), arguments[1] || { }); + var name = encodeURIComponent( + (arguments[1] && arguments[1].name) ? arguments[1].name : element.id); + + if (options.tree) { + return Sortable.tree(element, arguments[1]).children.map( function (item) { + return [name + Sortable._constructIndex(item) + "[id]=" + + encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)); + }).flatten().join('&'); + } else { + return Sortable.sequence(element, arguments[1]).map( function(item) { + return name + "[]=" + encodeURIComponent(item); + }).join('&'); + } + } +}; + +// Returns true if child is contained within element +Element.isParent = function(child, element) { + if (!child.parentNode || child == element) return false; + if (child.parentNode == element) return true; + return Element.isParent(child.parentNode, element); +}; + +Element.findChildren = function(element, only, recursive, tagName) { + if(!element.hasChildNodes()) return null; + tagName = tagName.toUpperCase(); + if(only) only = [only].flatten(); + var elements = []; + $A(element.childNodes).each( function(e) { + if(e.tagName && e.tagName.toUpperCase()==tagName && + (!only || (Element.classNames(e).detect(function(v) { return only.include(v) })))) + elements.push(e); + if(recursive) { + var grandchildren = Element.findChildren(e, only, recursive, tagName); + if(grandchildren) elements.push(grandchildren); + } + }); + + return (elements.length>0 ? elements.flatten() : []); +}; + +Element.offsetSize = function (element, type) { + return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')]; +}; \ No newline at end of file diff --git a/tryruby/public/javascripts/effects.js b/tryruby/public/javascripts/effects.js new file mode 100644 index 0000000..5a639d2 --- /dev/null +++ b/tryruby/public/javascripts/effects.js @@ -0,0 +1,1128 @@ +// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// Contributors: +// Justin Palmer (http://encytemedia.com/) +// Mark Pilgrim (http://diveintomark.org/) +// Martin Bialasinki +// +// script.aculo.us is freely distributable under the terms of an MIT-style license. +// For details, see the script.aculo.us web site: http://script.aculo.us/ + +// converts rgb() and #xxx to #xxxxxx format, +// returns self (or first argument) if not convertable +String.prototype.parseColor = function() { + var color = '#'; + if (this.slice(0,4) == 'rgb(') { + var cols = this.slice(4,this.length-1).split(','); + var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); + } else { + if (this.slice(0,1) == '#') { + if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); + if (this.length==7) color = this.toLowerCase(); + } + } + return (color.length==7 ? color : (arguments[0] || this)); +}; + +/*--------------------------------------------------------------------------*/ + +Element.collectTextNodes = function(element) { + return $A($(element).childNodes).collect( function(node) { + return (node.nodeType==3 ? node.nodeValue : + (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); + }).flatten().join(''); +}; + +Element.collectTextNodesIgnoreClass = function(element, className) { + return $A($(element).childNodes).collect( function(node) { + return (node.nodeType==3 ? node.nodeValue : + ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? + Element.collectTextNodesIgnoreClass(node, className) : '')); + }).flatten().join(''); +}; + +Element.setContentZoom = function(element, percent) { + element = $(element); + element.setStyle({fontSize: (percent/100) + 'em'}); + if (Prototype.Browser.WebKit) window.scrollBy(0,0); + return element; +}; + +Element.getInlineOpacity = function(element){ + return $(element).style.opacity || ''; +}; + +Element.forceRerendering = function(element) { + try { + element = $(element); + var n = document.createTextNode(' '); + element.appendChild(n); + element.removeChild(n); + } catch(e) { } +}; + +/*--------------------------------------------------------------------------*/ + +var Effect = { + _elementDoesNotExistError: { + name: 'ElementDoesNotExistError', + message: 'The specified DOM element does not exist, but is required for this effect to operate' + }, + Transitions: { + linear: Prototype.K, + sinoidal: function(pos) { + return (-Math.cos(pos*Math.PI)/2) + .5; + }, + reverse: function(pos) { + return 1-pos; + }, + flicker: function(pos) { + var pos = ((-Math.cos(pos*Math.PI)/4) + .75) + Math.random()/4; + return pos > 1 ? 1 : pos; + }, + wobble: function(pos) { + return (-Math.cos(pos*Math.PI*(9*pos))/2) + .5; + }, + pulse: function(pos, pulses) { + return (-Math.cos((pos*((pulses||5)-.5)*2)*Math.PI)/2) + .5; + }, + spring: function(pos) { + return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6)); + }, + none: function(pos) { + return 0; + }, + full: function(pos) { + return 1; + } + }, + DefaultOptions: { + duration: 1.0, // seconds + fps: 100, // 100= assume 66fps max. + sync: false, // true for combining + from: 0.0, + to: 1.0, + delay: 0.0, + queue: 'parallel' + }, + tagifyText: function(element) { + var tagifyStyle = 'position:relative'; + if (Prototype.Browser.IE) tagifyStyle += ';zoom:1'; + + element = $(element); + $A(element.childNodes).each( function(child) { + if (child.nodeType==3) { + child.nodeValue.toArray().each( function(character) { + element.insertBefore( + new Element('span', {style: tagifyStyle}).update( + character == ' ' ? String.fromCharCode(160) : character), + child); + }); + Element.remove(child); + } + }); + }, + multiple: function(element, effect) { + var elements; + if (((typeof element == 'object') || + Object.isFunction(element)) && + (element.length)) + elements = element; + else + elements = $(element).childNodes; + + var options = Object.extend({ + speed: 0.1, + delay: 0.0 + }, arguments[2] || { }); + var masterDelay = options.delay; + + $A(elements).each( function(element, index) { + new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); + }); + }, + PAIRS: { + 'slide': ['SlideDown','SlideUp'], + 'blind': ['BlindDown','BlindUp'], + 'appear': ['Appear','Fade'] + }, + toggle: function(element, effect) { + element = $(element); + effect = (effect || 'appear').toLowerCase(); + var options = Object.extend({ + queue: { position:'end', scope:(element.id || 'global'), limit: 1 } + }, arguments[2] || { }); + Effect[element.visible() ? + Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); + } +}; + +Effect.DefaultOptions.transition = Effect.Transitions.sinoidal; + +/* ------------- core effects ------------- */ + +Effect.ScopedQueue = Class.create(Enumerable, { + initialize: function() { + this.effects = []; + this.interval = null; + }, + _each: function(iterator) { + this.effects._each(iterator); + }, + add: function(effect) { + var timestamp = new Date().getTime(); + + var position = Object.isString(effect.options.queue) ? + effect.options.queue : effect.options.queue.position; + + switch(position) { + case 'front': + // move unstarted effects after this effect + this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { + e.startOn += effect.finishOn; + e.finishOn += effect.finishOn; + }); + break; + case 'with-last': + timestamp = this.effects.pluck('startOn').max() || timestamp; + break; + case 'end': + // start effect after last queued effect has finished + timestamp = this.effects.pluck('finishOn').max() || timestamp; + break; + } + + effect.startOn += timestamp; + effect.finishOn += timestamp; + + if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) + this.effects.push(effect); + + if (!this.interval) + this.interval = setInterval(this.loop.bind(this), 15); + }, + remove: function(effect) { + this.effects = this.effects.reject(function(e) { return e==effect }); + if (this.effects.length == 0) { + clearInterval(this.interval); + this.interval = null; + } + }, + loop: function() { + var timePos = new Date().getTime(); + for(var i=0, len=this.effects.length;i= this.startOn) { + if (timePos >= this.finishOn) { + this.render(1.0); + this.cancel(); + this.event('beforeFinish'); + if (this.finish) this.finish(); + this.event('afterFinish'); + return; + } + var pos = (timePos - this.startOn) / this.totalTime, + frame = (pos * this.totalFrames).round(); + if (frame > this.currentFrame) { + this.render(pos); + this.currentFrame = frame; + } + } + }, + cancel: function() { + if (!this.options.sync) + Effect.Queues.get(Object.isString(this.options.queue) ? + 'global' : this.options.queue.scope).remove(this); + this.state = 'finished'; + }, + event: function(eventName) { + if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); + if (this.options[eventName]) this.options[eventName](this); + }, + inspect: function() { + var data = $H(); + for(property in this) + if (!Object.isFunction(this[property])) data.set(property, this[property]); + return '#'; + } +}); + +Effect.Parallel = Class.create(Effect.Base, { + initialize: function(effects) { + this.effects = effects || []; + this.start(arguments[1]); + }, + update: function(position) { + this.effects.invoke('render', position); + }, + finish: function(position) { + this.effects.each( function(effect) { + effect.render(1.0); + effect.cancel(); + effect.event('beforeFinish'); + if (effect.finish) effect.finish(position); + effect.event('afterFinish'); + }); + } +}); + +Effect.Tween = Class.create(Effect.Base, { + initialize: function(object, from, to) { + object = Object.isString(object) ? $(object) : object; + var args = $A(arguments), method = args.last(), + options = args.length == 5 ? args[3] : null; + this.method = Object.isFunction(method) ? method.bind(object) : + Object.isFunction(object[method]) ? object[method].bind(object) : + function(value) { object[method] = value }; + this.start(Object.extend({ from: from, to: to }, options || { })); + }, + update: function(position) { + this.method(position); + } +}); + +Effect.Event = Class.create(Effect.Base, { + initialize: function() { + this.start(Object.extend({ duration: 0 }, arguments[0] || { })); + }, + update: Prototype.emptyFunction +}); + +Effect.Opacity = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + // make this work on IE on elements without 'layout' + if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) + this.element.setStyle({zoom: 1}); + var options = Object.extend({ + from: this.element.getOpacity() || 0.0, + to: 1.0 + }, arguments[1] || { }); + this.start(options); + }, + update: function(position) { + this.element.setOpacity(position); + } +}); + +Effect.Move = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ + x: 0, + y: 0, + mode: 'relative' + }, arguments[1] || { }); + this.start(options); + }, + setup: function() { + this.element.makePositioned(); + this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); + this.originalTop = parseFloat(this.element.getStyle('top') || '0'); + if (this.options.mode == 'absolute') { + this.options.x = this.options.x - this.originalLeft; + this.options.y = this.options.y - this.originalTop; + } + }, + update: function(position) { + this.element.setStyle({ + left: (this.options.x * position + this.originalLeft).round() + 'px', + top: (this.options.y * position + this.originalTop).round() + 'px' + }); + } +}); + +// for backwards compatibility +Effect.MoveBy = function(element, toTop, toLeft) { + return new Effect.Move(element, + Object.extend({ x: toLeft, y: toTop }, arguments[3] || { })); +}; + +Effect.Scale = Class.create(Effect.Base, { + initialize: function(element, percent) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ + scaleX: true, + scaleY: true, + scaleContent: true, + scaleFromCenter: false, + scaleMode: 'box', // 'box' or 'contents' or { } with provided values + scaleFrom: 100.0, + scaleTo: percent + }, arguments[2] || { }); + this.start(options); + }, + setup: function() { + this.restoreAfterFinish = this.options.restoreAfterFinish || false; + this.elementPositioning = this.element.getStyle('position'); + + this.originalStyle = { }; + ['top','left','width','height','fontSize'].each( function(k) { + this.originalStyle[k] = this.element.style[k]; + }.bind(this)); + + this.originalTop = this.element.offsetTop; + this.originalLeft = this.element.offsetLeft; + + var fontSize = this.element.getStyle('font-size') || '100%'; + ['em','px','%','pt'].each( function(fontSizeType) { + if (fontSize.indexOf(fontSizeType)>0) { + this.fontSize = parseFloat(fontSize); + this.fontSizeType = fontSizeType; + } + }.bind(this)); + + this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; + + this.dims = null; + if (this.options.scaleMode=='box') + this.dims = [this.element.offsetHeight, this.element.offsetWidth]; + if (/^content/.test(this.options.scaleMode)) + this.dims = [this.element.scrollHeight, this.element.scrollWidth]; + if (!this.dims) + this.dims = [this.options.scaleMode.originalHeight, + this.options.scaleMode.originalWidth]; + }, + update: function(position) { + var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); + if (this.options.scaleContent && this.fontSize) + this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); + this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); + }, + finish: function(position) { + if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); + }, + setDimensions: function(height, width) { + var d = { }; + if (this.options.scaleX) d.width = width.round() + 'px'; + if (this.options.scaleY) d.height = height.round() + 'px'; + if (this.options.scaleFromCenter) { + var topd = (height - this.dims[0])/2; + var leftd = (width - this.dims[1])/2; + if (this.elementPositioning == 'absolute') { + if (this.options.scaleY) d.top = this.originalTop-topd + 'px'; + if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; + } else { + if (this.options.scaleY) d.top = -topd + 'px'; + if (this.options.scaleX) d.left = -leftd + 'px'; + } + } + this.element.setStyle(d); + } +}); + +Effect.Highlight = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { }); + this.start(options); + }, + setup: function() { + // Prevent executing on elements not in the layout flow + if (this.element.getStyle('display')=='none') { this.cancel(); return; } + // Disable background image during the effect + this.oldStyle = { }; + if (!this.options.keepBackgroundImage) { + this.oldStyle.backgroundImage = this.element.getStyle('background-image'); + this.element.setStyle({backgroundImage: 'none'}); + } + if (!this.options.endcolor) + this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); + if (!this.options.restorecolor) + this.options.restorecolor = this.element.getStyle('background-color'); + // init color calculations + this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); + this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this)); + }, + update: function(position) { + this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ + return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) }); + }, + finish: function() { + this.element.setStyle(Object.extend(this.oldStyle, { + backgroundColor: this.options.restorecolor + })); + } +}); + +Effect.ScrollTo = function(element) { + var options = arguments[1] || { }, + scrollOffsets = document.viewport.getScrollOffsets(), + elementOffsets = $(element).cumulativeOffset(); + + if (options.offset) elementOffsets[1] += options.offset; + + return new Effect.Tween(null, + scrollOffsets.top, + elementOffsets[1], + options, + function(p){ scrollTo(scrollOffsets.left, p.round()); } + ); +}; + +/* ------------- combination effects ------------- */ + +Effect.Fade = function(element) { + element = $(element); + var oldOpacity = element.getInlineOpacity(); + var options = Object.extend({ + from: element.getOpacity() || 1.0, + to: 0.0, + afterFinishInternal: function(effect) { + if (effect.options.to!=0) return; + effect.element.hide().setStyle({opacity: oldOpacity}); + } + }, arguments[1] || { }); + return new Effect.Opacity(element,options); +}; + +Effect.Appear = function(element) { + element = $(element); + var options = Object.extend({ + from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), + to: 1.0, + // force Safari to render floated elements properly + afterFinishInternal: function(effect) { + effect.element.forceRerendering(); + }, + beforeSetup: function(effect) { + effect.element.setOpacity(effect.options.from).show(); + }}, arguments[1] || { }); + return new Effect.Opacity(element,options); +}; + +Effect.Puff = function(element) { + element = $(element); + var oldStyle = { + opacity: element.getInlineOpacity(), + position: element.getStyle('position'), + top: element.style.top, + left: element.style.left, + width: element.style.width, + height: element.style.height + }; + return new Effect.Parallel( + [ new Effect.Scale(element, 200, + { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), + new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], + Object.extend({ duration: 1.0, + beforeSetupInternal: function(effect) { + Position.absolutize(effect.effects[0].element); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide().setStyle(oldStyle); } + }, arguments[1] || { }) + ); +}; + +Effect.BlindUp = function(element) { + element = $(element); + element.makeClipping(); + return new Effect.Scale(element, 0, + Object.extend({ scaleContent: false, + scaleX: false, + restoreAfterFinish: true, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping(); + } + }, arguments[1] || { }) + ); +}; + +Effect.BlindDown = function(element) { + element = $(element); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, 100, Object.extend({ + scaleContent: false, + scaleX: false, + scaleFrom: 0, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makeClipping().setStyle({height: '0px'}).show(); + }, + afterFinishInternal: function(effect) { + effect.element.undoClipping(); + } + }, arguments[1] || { })); +}; + +Effect.SwitchOff = function(element) { + element = $(element); + var oldOpacity = element.getInlineOpacity(); + return new Effect.Appear(element, Object.extend({ + duration: 0.4, + from: 0, + transition: Effect.Transitions.flicker, + afterFinishInternal: function(effect) { + new Effect.Scale(effect.element, 1, { + duration: 0.3, scaleFromCenter: true, + scaleX: false, scaleContent: false, restoreAfterFinish: true, + beforeSetup: function(effect) { + effect.element.makePositioned().makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity}); + } + }); + } + }, arguments[1] || { })); +}; + +Effect.DropOut = function(element) { + element = $(element); + var oldStyle = { + top: element.getStyle('top'), + left: element.getStyle('left'), + opacity: element.getInlineOpacity() }; + return new Effect.Parallel( + [ new Effect.Move(element, {x: 0, y: 100, sync: true }), + new Effect.Opacity(element, { sync: true, to: 0.0 }) ], + Object.extend( + { duration: 0.5, + beforeSetup: function(effect) { + effect.effects[0].element.makePositioned(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle); + } + }, arguments[1] || { })); +}; + +Effect.Shake = function(element) { + element = $(element); + var options = Object.extend({ + distance: 20, + duration: 0.5 + }, arguments[1] || {}); + var distance = parseFloat(options.distance); + var split = parseFloat(options.duration) / 10.0; + var oldStyle = { + top: element.getStyle('top'), + left: element.getStyle('left') }; + return new Effect.Move(element, + { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) { + effect.element.undoPositioned().setStyle(oldStyle); + }}); }}); }}); }}); }}); }}); +}; + +Effect.SlideDown = function(element) { + element = $(element).cleanWhitespace(); + // SlideDown need to have the content of the element wrapped in a container element with fixed height! + var oldInnerBottom = element.down().getStyle('bottom'); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, 100, Object.extend({ + scaleContent: false, + scaleX: false, + scaleFrom: window.opera ? 0 : 1, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makePositioned(); + effect.element.down().makePositioned(); + if (window.opera) effect.element.setStyle({top: ''}); + effect.element.makeClipping().setStyle({height: '0px'}).show(); + }, + afterUpdateInternal: function(effect) { + effect.element.down().setStyle({bottom: + (effect.dims[0] - effect.element.clientHeight) + 'px' }); + }, + afterFinishInternal: function(effect) { + effect.element.undoClipping().undoPositioned(); + effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); } + }, arguments[1] || { }) + ); +}; + +Effect.SlideUp = function(element) { + element = $(element).cleanWhitespace(); + var oldInnerBottom = element.down().getStyle('bottom'); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, window.opera ? 0 : 1, + Object.extend({ scaleContent: false, + scaleX: false, + scaleMode: 'box', + scaleFrom: 100, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makePositioned(); + effect.element.down().makePositioned(); + if (window.opera) effect.element.setStyle({top: ''}); + effect.element.makeClipping().show(); + }, + afterUpdateInternal: function(effect) { + effect.element.down().setStyle({bottom: + (effect.dims[0] - effect.element.clientHeight) + 'px' }); + }, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping().undoPositioned(); + effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); + } + }, arguments[1] || { }) + ); +}; + +// Bug in opera makes the TD containing this element expand for a instance after finish +Effect.Squish = function(element) { + return new Effect.Scale(element, window.opera ? 1 : 0, { + restoreAfterFinish: true, + beforeSetup: function(effect) { + effect.element.makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping(); + } + }); +}; + +Effect.Grow = function(element) { + element = $(element); + var options = Object.extend({ + direction: 'center', + moveTransition: Effect.Transitions.sinoidal, + scaleTransition: Effect.Transitions.sinoidal, + opacityTransition: Effect.Transitions.full + }, arguments[1] || { }); + var oldStyle = { + top: element.style.top, + left: element.style.left, + height: element.style.height, + width: element.style.width, + opacity: element.getInlineOpacity() }; + + var dims = element.getDimensions(); + var initialMoveX, initialMoveY; + var moveX, moveY; + + switch (options.direction) { + case 'top-left': + initialMoveX = initialMoveY = moveX = moveY = 0; + break; + case 'top-right': + initialMoveX = dims.width; + initialMoveY = moveY = 0; + moveX = -dims.width; + break; + case 'bottom-left': + initialMoveX = moveX = 0; + initialMoveY = dims.height; + moveY = -dims.height; + break; + case 'bottom-right': + initialMoveX = dims.width; + initialMoveY = dims.height; + moveX = -dims.width; + moveY = -dims.height; + break; + case 'center': + initialMoveX = dims.width / 2; + initialMoveY = dims.height / 2; + moveX = -dims.width / 2; + moveY = -dims.height / 2; + break; + } + + return new Effect.Move(element, { + x: initialMoveX, + y: initialMoveY, + duration: 0.01, + beforeSetup: function(effect) { + effect.element.hide().makeClipping().makePositioned(); + }, + afterFinishInternal: function(effect) { + new Effect.Parallel( + [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), + new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), + new Effect.Scale(effect.element, 100, { + scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, + sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) + ], Object.extend({ + beforeSetup: function(effect) { + effect.effects[0].element.setStyle({height: '0px'}).show(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle); + } + }, options) + ); + } + }); +}; + +Effect.Shrink = function(element) { + element = $(element); + var options = Object.extend({ + direction: 'center', + moveTransition: Effect.Transitions.sinoidal, + scaleTransition: Effect.Transitions.sinoidal, + opacityTransition: Effect.Transitions.none + }, arguments[1] || { }); + var oldStyle = { + top: element.style.top, + left: element.style.left, + height: element.style.height, + width: element.style.width, + opacity: element.getInlineOpacity() }; + + var dims = element.getDimensions(); + var moveX, moveY; + + switch (options.direction) { + case 'top-left': + moveX = moveY = 0; + break; + case 'top-right': + moveX = dims.width; + moveY = 0; + break; + case 'bottom-left': + moveX = 0; + moveY = dims.height; + break; + case 'bottom-right': + moveX = dims.width; + moveY = dims.height; + break; + case 'center': + moveX = dims.width / 2; + moveY = dims.height / 2; + break; + } + + return new Effect.Parallel( + [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), + new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), + new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) + ], Object.extend({ + beforeStartInternal: function(effect) { + effect.effects[0].element.makePositioned().makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); } + }, options) + ); +}; + +Effect.Pulsate = function(element) { + element = $(element); + var options = arguments[1] || { }, + oldOpacity = element.getInlineOpacity(), + transition = options.transition || Effect.Transitions.linear, + reverser = function(pos){ + return 1 - transition((-Math.cos((pos*(options.pulses||5)*2)*Math.PI)/2) + .5); + }; + + return new Effect.Opacity(element, + Object.extend(Object.extend({ duration: 2.0, from: 0, + afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } + }, options), {transition: reverser})); +}; + +Effect.Fold = function(element) { + element = $(element); + var oldStyle = { + top: element.style.top, + left: element.style.left, + width: element.style.width, + height: element.style.height }; + element.makeClipping(); + return new Effect.Scale(element, 5, Object.extend({ + scaleContent: false, + scaleX: false, + afterFinishInternal: function(effect) { + new Effect.Scale(element, 1, { + scaleContent: false, + scaleY: false, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping().setStyle(oldStyle); + } }); + }}, arguments[1] || { })); +}; + +Effect.Morph = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ + style: { } + }, arguments[1] || { }); + + if (!Object.isString(options.style)) this.style = $H(options.style); + else { + if (options.style.include(':')) + this.style = options.style.parseStyle(); + else { + this.element.addClassName(options.style); + this.style = $H(this.element.getStyles()); + this.element.removeClassName(options.style); + var css = this.element.getStyles(); + this.style = this.style.reject(function(style) { + return style.value == css[style.key]; + }); + options.afterFinishInternal = function(effect) { + effect.element.addClassName(effect.options.style); + effect.transforms.each(function(transform) { + effect.element.style[transform.style] = ''; + }); + }; + } + } + this.start(options); + }, + + setup: function(){ + function parseColor(color){ + if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff'; + color = color.parseColor(); + return $R(0,2).map(function(i){ + return parseInt( color.slice(i*2+1,i*2+3), 16 ); + }); + } + this.transforms = this.style.map(function(pair){ + var property = pair[0], value = pair[1], unit = null; + + if (value.parseColor('#zzzzzz') != '#zzzzzz') { + value = value.parseColor(); + unit = 'color'; + } else if (property == 'opacity') { + value = parseFloat(value); + if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) + this.element.setStyle({zoom: 1}); + } else if (Element.CSS_LENGTH.test(value)) { + var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); + value = parseFloat(components[1]); + unit = (components.length == 3) ? components[2] : null; + } + + var originalValue = this.element.getStyle(property); + return { + style: property.camelize(), + originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), + targetValue: unit=='color' ? parseColor(value) : value, + unit: unit + }; + }.bind(this)).reject(function(transform){ + return ( + (transform.originalValue == transform.targetValue) || + ( + transform.unit != 'color' && + (isNaN(transform.originalValue) || isNaN(transform.targetValue)) + ) + ); + }); + }, + update: function(position) { + var style = { }, transform, i = this.transforms.length; + while(i--) + style[(transform = this.transforms[i]).style] = + transform.unit=='color' ? '#'+ + (Math.round(transform.originalValue[0]+ + (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() + + (Math.round(transform.originalValue[1]+ + (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() + + (Math.round(transform.originalValue[2]+ + (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() : + (transform.originalValue + + (transform.targetValue - transform.originalValue) * position).toFixed(3) + + (transform.unit === null ? '' : transform.unit); + this.element.setStyle(style, true); + } +}); + +Effect.Transform = Class.create({ + initialize: function(tracks){ + this.tracks = []; + this.options = arguments[1] || { }; + this.addTracks(tracks); + }, + addTracks: function(tracks){ + tracks.each(function(track){ + track = $H(track); + var data = track.values().first(); + this.tracks.push($H({ + ids: track.keys().first(), + effect: Effect.Morph, + options: { style: data } + })); + }.bind(this)); + return this; + }, + play: function(){ + return new Effect.Parallel( + this.tracks.map(function(track){ + var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options'); + var elements = [$(ids) || $$(ids)].flatten(); + return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) }); + }).flatten(), + this.options + ); + } +}); + +Element.CSS_PROPERTIES = $w( + 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + + 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' + + 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' + + 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' + + 'fontSize fontWeight height left letterSpacing lineHeight ' + + 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+ + 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' + + 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' + + 'right textIndent top width wordSpacing zIndex'); + +Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; + +String.__parseStyleElement = document.createElement('div'); +String.prototype.parseStyle = function(){ + var style, styleRules = $H(); + if (Prototype.Browser.WebKit) + style = new Element('div',{style:this}).style; + else { + String.__parseStyleElement.innerHTML = '
              '; + style = String.__parseStyleElement.childNodes[0].style; + } + + Element.CSS_PROPERTIES.each(function(property){ + if (style[property]) styleRules.set(property, style[property]); + }); + + if (Prototype.Browser.IE && this.include('opacity')) + styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]); + + return styleRules; +}; + +if (document.defaultView && document.defaultView.getComputedStyle) { + Element.getStyles = function(element) { + var css = document.defaultView.getComputedStyle($(element), null); + return Element.CSS_PROPERTIES.inject({ }, function(styles, property) { + styles[property] = css[property]; + return styles; + }); + }; +} else { + Element.getStyles = function(element) { + element = $(element); + var css = element.currentStyle, styles; + styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) { + results[property] = css[property]; + return results; + }); + if (!styles.opacity) styles.opacity = element.getOpacity(); + return styles; + }; +} + +Effect.Methods = { + morph: function(element, style) { + element = $(element); + new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { })); + return element; + }, + visualEffect: function(element, effect, options) { + element = $(element); + var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1); + new Effect[klass](element, options); + return element; + }, + highlight: function(element, options) { + element = $(element); + new Effect.Highlight(element, options); + return element; + } +}; + +$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+ + 'pulsate shake puff squish switchOff dropOut').each( + function(effect) { + Effect.Methods[effect] = function(element, options){ + element = $(element); + Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options); + return element; + }; + } +); + +$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each( + function(f) { Effect.Methods[f] = Element[f]; } +); + +Element.addMethods(Effect.Methods); \ No newline at end of file diff --git a/tryruby/public/javascripts/facebox.js b/tryruby/public/javascripts/facebox.js new file mode 100755 index 0000000..5ad90ed --- /dev/null +++ b/tryruby/public/javascripts/facebox.js @@ -0,0 +1,309 @@ +/* + * Facebox (for jQuery) + * version: 1.2 (05/05/2008) + * @requires jQuery v1.2 or later + * + * Examples at http://famspam.com/facebox/ + * + * Licensed under the MIT: + * http://www.opensource.org/licenses/mit-license.php + * + * Copyright 2007, 2008 Chris Wanstrath [ chris@ozmm.org ] + * + * Usage: + * + * jQuery(document).ready(function() { + * jQuery('a[rel*=facebox]').facebox() + * }) + * + * Terms + * Loads the #terms div in the box + * + * Terms + * Loads the terms.html page in the box + * + * Terms + * Loads the terms.png image in the box + * + * + * You can also use it programmatically: + * + * jQuery.facebox('some html') + * jQuery.facebox('some html', 'my-groovy-style') + * + * The above will open a facebox with "some html" as the content. + * + * jQuery.facebox(function($) { + * $.get('blah.html', function(data) { $.facebox(data) }) + * }) + * + * The above will show a loading screen before the passed function is called, + * allowing for a better ajaxy experience. + * + * The facebox function can also display an ajax page, an image, or the contents of a div: + * + * jQuery.facebox({ ajax: 'remote.html' }) + * jQuery.facebox({ ajax: 'remote.html' }, 'my-groovy-style') + * jQuery.facebox({ image: 'stairs.jpg' }) + * jQuery.facebox({ image: 'stairs.jpg' }, 'my-groovy-style') + * jQuery.facebox({ div: '#box' }) + * jQuery.facebox({ div: '#box' }, 'my-groovy-style') + * + * Want to close the facebox? Trigger the 'close.facebox' document event: + * + * jQuery(document).trigger('close.facebox') + * + * Facebox also has a bunch of other hooks: + * + * loading.facebox + * beforeReveal.facebox + * reveal.facebox (aliased as 'afterReveal.facebox') + * init.facebox + * afterClose.facebox + * + * Simply bind a function to any of these hooks: + * + * $(document).bind('reveal.facebox', function() { ...stuff to do after the facebox and contents are revealed... }) + * + */ +(function($) { + $.facebox = function(data, klass) { + $.facebox.loading() + + if (data.ajax) fillFaceboxFromAjax(data.ajax, klass) + else if (data.image) fillFaceboxFromImage(data.image, klass) + else if (data.div) fillFaceboxFromHref(data.div, klass) + else if ($.isFunction(data)) data.call($) + else $.facebox.reveal(data, klass) + } + + /* + * Public, $.facebox methods + */ + + $.extend($.facebox, { + settings: { + opacity : 0.2, + overlay : true, + loadingImage : '/facebox/loading.gif', + closeImage : '/facebox/closelabel.png', + imageTypes : [ 'png', 'jpg', 'jpeg', 'gif' ], + faceboxHtml : '\ + ' + }, + + loading: function() { + init() + if ($('#facebox .loading').length == 1) return true + showOverlay() + + $('#facebox .content').empty() + $('#facebox .body').children().hide().end(). + append('
              ') + + $('#facebox').css({ + top: getPageScroll()[1] + (getPageHeight() / 10), + left: $(window).width() / 2 - 205 + }).show() + + $(document).bind('keydown.facebox', function(e) { + if (e.keyCode == 27) $.facebox.close() + return true + }) + $(document).trigger('loading.facebox') + }, + + reveal: function(data, klass) { + $(document).trigger('beforeReveal.facebox') + if (klass) $('#facebox .content').addClass(klass) + $('#facebox .content').append(data) + $('#facebox .loading').remove() + $('#facebox .body').children().fadeIn('normal') + $('#facebox').css('left', $(window).width() / 2 - ($('#facebox .popup').width() / 2)) + $(document).trigger('reveal.facebox').trigger('afterReveal.facebox') + }, + + close: function() { + $(document).trigger('close.facebox') + return false + } + }) + + /* + * Public, $.fn methods + */ + + $.fn.facebox = function(settings) { + if ($(this).length == 0) return + + init(settings) + + function clickHandler() { + $.facebox.loading(true) + + // support for rel="facebox.inline_popup" syntax, to add a class + // also supports deprecated "facebox[.inline_popup]" syntax + var klass = this.rel.match(/facebox\[?\.(\w+)\]?/) + if (klass) klass = klass[1] + + fillFaceboxFromHref(this.href, klass) + return false + } + + return this.bind('click.facebox', clickHandler) + } + + /* + * Private methods + */ + + // called one time to setup facebox on this page + function init(settings) { + if ($.facebox.settings.inited) return true + else $.facebox.settings.inited = true + + $(document).trigger('init.facebox') + makeCompatible() + + var imageTypes = $.facebox.settings.imageTypes.join('|') + $.facebox.settings.imageTypesRegexp = new RegExp('\.(' + imageTypes + ')$', 'i') + + if (settings) $.extend($.facebox.settings, settings) + $('body').append($.facebox.settings.faceboxHtml) + + var preload = [ new Image(), new Image() ] + preload[0].src = $.facebox.settings.closeImage + preload[1].src = $.facebox.settings.loadingImage + + $('#facebox').find('.b:first, .bl').each(function() { + preload.push(new Image()) + preload.slice(-1).src = $(this).css('background-image').replace(/url\((.+)\)/, '$1') + }) + + $('#facebox .close').click($.facebox.close) + $('#facebox .close_image').attr('src', $.facebox.settings.closeImage) + } + + // getPageScroll() by quirksmode.com + function getPageScroll() { + var xScroll, yScroll; + if (self.pageYOffset) { + yScroll = self.pageYOffset; + xScroll = self.pageXOffset; + } else if (document.documentElement && document.documentElement.scrollTop) { // Explorer 6 Strict + yScroll = document.documentElement.scrollTop; + xScroll = document.documentElement.scrollLeft; + } else if (document.body) {// all other Explorers + yScroll = document.body.scrollTop; + xScroll = document.body.scrollLeft; + } + return new Array(xScroll,yScroll) + } + + // Adapted from getPageSize() by quirksmode.com + function getPageHeight() { + var windowHeight + if (self.innerHeight) { // all except Explorer + windowHeight = self.innerHeight; + } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode + windowHeight = document.documentElement.clientHeight; + } else if (document.body) { // other Explorers + windowHeight = document.body.clientHeight; + } + return windowHeight + } + + // Backwards compatibility + function makeCompatible() { + var $s = $.facebox.settings + + $s.loadingImage = $s.loading_image || $s.loadingImage + $s.closeImage = $s.close_image || $s.closeImage + $s.imageTypes = $s.image_types || $s.imageTypes + $s.faceboxHtml = $s.facebox_html || $s.faceboxHtml + } + + // Figures out what you want to display and displays it + // formats are: + // div: #id + // image: blah.extension + // ajax: anything else + function fillFaceboxFromHref(href, klass) { + // div + if (href.match(/#/)) { + var url = window.location.href.split('#')[0] + var target = href.replace(url,'') + if (target == '#') return + $.facebox.reveal($(target).html(), klass) + + // image + } else if (href.match($.facebox.settings.imageTypesRegexp)) { + fillFaceboxFromImage(href, klass) + // ajax + } else { + fillFaceboxFromAjax(href, klass) + } + } + + function fillFaceboxFromImage(href, klass) { + var image = new Image() + image.onload = function() { + $.facebox.reveal('
              ', klass) + } + image.src = href + } + + function fillFaceboxFromAjax(href, klass) { + $.get(href, function(data) { $.facebox.reveal(data, klass) }) + } + + function skipOverlay() { + return $.facebox.settings.overlay == false || $.facebox.settings.opacity === null + } + + function showOverlay() { + if (skipOverlay()) return + + if ($('#facebox_overlay').length == 0) + $("body").append('
              ') + + $('#facebox_overlay').hide().addClass("facebox_overlayBG") + .css('opacity', $.facebox.settings.opacity) + .click(function() { $(document).trigger('close.facebox') }) + .fadeIn(200) + return false + } + + function hideOverlay() { + if (skipOverlay()) return + + $('#facebox_overlay').fadeOut(200, function(){ + $("#facebox_overlay").removeClass("facebox_overlayBG") + $("#facebox_overlay").addClass("facebox_hide") + $("#facebox_overlay").remove() + }) + + return false + } + + /* + * Bindings + */ + + $(document).bind('close.facebox', function() { + $(document).unbind('keydown.facebox') + $('#facebox').fadeOut(function() { + $('#facebox .content').removeClass().addClass('content') + $('#facebox .loading').remove() + $(document).trigger('afterClose.facebox') + }) + hideOverlay() + }) + +})(jQuery); diff --git a/tryruby/public/javascripts/index.html b/tryruby/public/javascripts/index.html new file mode 100755 index 0000000..e933af9 --- /dev/null +++ b/tryruby/public/javascripts/index.html @@ -0,0 +1,8 @@ + + + + + +

              you shouldn't be here.. kicking you out!

              + + diff --git a/tryruby/public/javascripts/irb.js b/tryruby/public/javascripts/irb.js new file mode 100755 index 0000000..b4cb354 --- /dev/null +++ b/tryruby/public/javascripts/irb.js @@ -0,0 +1,110 @@ +// +// Copyright (c) 2008 why the lucky stiff +// Copyright (c) 2010 Andrew McElroy +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +var allStretch; +var helpPages; +var chapPages; +var defaultPage; +var toot = window.location.search.substr(1) + +//the main function, call to the effect object +function dumpAlert(obj) { + props = []; + for ( var i in obj ) { + props.push( "" + i + ": " + obj[i] ); + } + alert( props ); +} +window.onload = function() { + defaultPage = $('#helpstone .stretcher').html(); + + window.irb = new MouseApp.Irb('#irb', { + rows: 13, + name: 'IRB', + greeting: "%+r Interactive ruby ready. %-r", + ps: '\033[1;31m>>\033[m', + user: 'guest', + host: 'tryruby', + // original: irbUrl: '/irb', + irbUrl: '/tryruby/run', + init: function () { + helpPages = $(".stretcher"); + chapPages = new Array(); + for (var i = 0; i < helpPages.length; i++ ) { + var cls = helpPages[i].className.split(' '); + for (var j = 0; j < cls.length; j++) { + if (cls[j] == 'chapmark') { + chapPages.push([i, helpPages[i]]); + break; + } + } + } + }, + loadTutorial: function (id, instruct) { + $.ajax({ + url: '/tutorials/' + id , + type: 'GET', + complete: function (r) { + $('#helpstone').html("
              " + defaultPage + "
              " + r.responseText); + window.irb.init(); + window.irb.showHelp(0); + } + }); + }, + showChapter: function (n) { + if (n >= chapPages.length) return; + this.setHelpPage(chapPages[n][0], chapPages[n][1]); + }, + showHelp: function (n) { + if (n >= helpPages.length) return; + this.setHelpPage(n, helpPages[n]); + }, + popup_goto: function (u) { + $('#lilBrowser').show().css({left: '40px', top: '40px'}); + $('#lbIframe').attr('src', u); + }, + popup_make: function (s) { + $('#lilBrowser').show().css({left: '40px', top: '40px'}); + $('#lbIframe').get(0).onIframeLoad = function () { + alert($(this).html()); + alert("$(this).html()"); + return s; + }; + //$('#lbIframe').attr({src: '/blank.html'}); + src = s.replace(/\\/g, "\\\\").replace(/\"/g, "\\\""); + $('#lbIframe').attr({src: "javascript:\"" + src + "\""}); + // $('# + }, + popup_close: function () { + $('#lilBrowser').hide(); + } + }); + + if ( !toot ) { + toot = 'intro'; + } + try { + window.irb.options.loadTutorial( toot, true ); + } catch (e) {} +} diff --git a/tryruby/public/javascripts/jQuery.irb.js b/tryruby/public/javascripts/jQuery.irb.js new file mode 100644 index 0000000..765858d --- /dev/null +++ b/tryruby/public/javascripts/jQuery.irb.js @@ -0,0 +1,1641 @@ +//Try Ruby 1.5 (defacto version Number) +// March 14 2011 + +// large parts of this file are lifted from Try Haskell ( which lifted parts from try ruby without copyright notice >:-/ ) + +// Thus it is fair to include the following banner if/until there is no try haskell code left/ only code that originally existed in try ruby in the +//first place. + + // Try Haskell 1.0.1 + // Tue Feb 23 18:34:48 GMT 2010 + // + // Copyright 2010 Chris Done. All rights reserved. + // + // Redistribution and use in source and binary forms, with or without + // modification, are permitted provided that the following conditions + // are met: + // + // 1. Redistributions of source code must retain the above + // copyright notice, this list of conditions and the following + // disclaimer. + // 2. Redistributions in binary form must reproduce the above + // copyright notice, this list of conditions and the following + // disclaimer in the documentation and/or other materials + // provided with the distribution. + // + // THIS SOFTWARE IS PROVIDED BY CHRIS DONE ``AS IS'' AND ANY EXPRESS + // OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + // ARE DISCLAIMED. IN NO EVENT SHALL CHRIS DONE OR CONTRIBUTORS BE + // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + // OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + // DAMAGE. + // The views and conclusions contained in the software and + // documentation are those of the authors and should not be + // interpreted as representing official policies, either expressed or + // implied, of Chris Done. + // + // TESTED ON + // Internet Explorer 6 + // Opera 10.01 + // Chromium 4.0.237.0 (Ubuntu build 31094) + // Firefox 3.5.8 + + //IOS 4.3 (all devices) + +// Temporary fix +function opera() { + return navigator.userAgent.indexOf("Opera") == 0; +} + +function encodeHex(str) { + var result = ""; + for (var i = 0; i < str.length; i++) { + result += "%" + pad(toHex(str.charCodeAt(i) & 0xff), 2, '0'); + } + return result; +} + +//var handleJSON = function(a){ alert('Unassigned JSONP: ' + a); } +var hexv = { + "00": 0, + "01": 1, + "02": 2, + "03": 3, + "04": 4, + "05": 5, + "06": 6, + "07": 7, + "08": 8, + "09": 9, + "0A": 10, + "0B": 11, + "0C": 12, + "0D": 13, + "0E": 14, + "0F": 15, + "10": 16, + "11": 17, + "12": 18, + "13": 19, + "14": 20, + "15": 21, + "16": 22, + "17": 23, + "18": 24, + "19": 25, + "1A": 26, + "1B": 27, + "1C": 28, + "1D": 29, + "1E": 30, + "1F": 31, + "20": 32, + "21": 33, + "22": 34, + "23": 35, + "24": 36, + "25": 37, + "26": 38, + "27": 39, + "28": 40, + "29": 41, + "2A": 42, + "2B": 43, + "2C": 44, + "2D": 45, + "2E": 46, + "2F": 47, + "30": 48, + "31": 49, + "32": 50, + "33": 51, + "34": 52, + "35": 53, + "36": 54, + "37": 55, + "38": 56, + "39": 57, + "3A": 58, + "3B": 59, + "3C": 60, + "3D": 61, + "3E": 62, + "3F": 63, + "40": 64, + "41": 65, + "42": 66, + "43": 67, + "44": 68, + "45": 69, + "46": 70, + "47": 71, + "48": 72, + "49": 73, + "4A": 74, + "4B": 75, + "4C": 76, + "4D": 77, + "4E": 78, + "4F": 79, + "50": 80, + "51": 81, + "52": 82, + "53": 83, + "54": 84, + "55": 85, + "56": 86, + "57": 87, + "58": 88, + "59": 89, + "5A": 90, + "5B": 91, + "5C": 92, + "5D": 93, + "5E": 94, + "5F": 95, + "60": 96, + "61": 97, + "62": 98, + "63": 99, + "64": 100, + "65": 101, + "66": 102, + "67": 103, + "68": 104, + "69": 105, + "6A": 106, + "6B": 107, + "6C": 108, + "6D": 109, + "6E": 110, + "6F": 111, + "70": 112, + "71": 113, + "72": 114, + "73": 115, + "74": 116, + "75": 117, + "76": 118, + "77": 119, + "78": 120, + "79": 121, + "7A": 122, + "7B": 123, + "7C": 124, + "7D": 125, + "7E": 126, + "7F": 127, + "80": 128, + "81": 129, + "82": 130, + "83": 131, + "84": 132, + "85": 133, + "86": 134, + "87": 135, + "88": 136, + "89": 137, + "8A": 138, + "8B": 139, + "8C": 140, + "8D": 141, + "8E": 142, + "8F": 143, + "90": 144, + "91": 145, + "92": 146, + "93": 147, + "94": 148, + "95": 149, + "96": 150, + "97": 151, + "98": 152, + "99": 153, + "9A": 154, + "9B": 155, + "9C": 156, + "9D": 157, + "9E": 158, + "9F": 159, + "A0": 160, + "A1": 161, + "A2": 162, + "A3": 163, + "A4": 164, + "A5": 165, + "A6": 166, + "A7": 167, + "A8": 168, + "A9": 169, + "AA": 170, + "AB": 171, + "AC": 172, + "AD": 173, + "AE": 174, + "AF": 175, + "B0": 176, + "B1": 177, + "B2": 178, + "B3": 179, + "B4": 180, + "B5": 181, + "B6": 182, + "B7": 183, + "B8": 184, + "B9": 185, + "BA": 186, + "BB": 187, + "BC": 188, + "BD": 189, + "BE": 190, + "BF": 191, + "C0": 192, + "C1": 193, + "C2": 194, + "C3": 195, + "C4": 196, + "C5": 197, + "C6": 198, + "C7": 199, + "C8": 200, + "C9": 201, + "CA": 202, + "CB": 203, + "CC": 204, + "CD": 205, + "CE": 206, + "CF": 207, + "D0": 208, + "D1": 209, + "D2": 210, + "D3": 211, + "D4": 212, + "D5": 213, + "D6": 214, + "D7": 215, + "D8": 216, + "D9": 217, + "DA": 218, + "DB": 219, + "DC": 220, + "DD": 221, + "DE": 222, + "DF": 223, + "E0": 224, + "E1": 225, + "E2": 226, + "E3": 227, + "E4": 228, + "E5": 229, + "E6": 230, + "E7": 231, + "E8": 232, + "E9": 233, + "EA": 234, + "EB": 235, + "EC": 236, + "ED": 237, + "EE": 238, + "EF": 239, + "F0": 240, + "F1": 241, + "F2": 242, + "F3": 243, + "F4": 244, + "F5": 245, + "F6": 246, + "F7": 247, + "F8": 248, + "F9": 249, + "FA": 250, + "FB": 251, + "FC": 252, + "FD": 253, + "FE": 254, + "FF": 255 +}; + +function pad(str, len, pad) { + var result = str; + for (var i = str.length; i < len; i++) { + result = pad + result; + } + return result; +} + +var digitArray = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'); + +function toHex(n) { + var result = '' + var start = true; + for (var i = 32; i > 0;) { + i -= 4; + var digit = (n >> i) & 0xf; + if (!start || digit != 0) { + start = false; + result += digitArray[digit]; + } + } + return (result == '' ? '0': result); +} + + (function($) { + var raphaelPaper; + var raphaelObjs; + var tutorialGuide; + + // I don't like this at all... I intend to make this pull via ajax from a key value data store. + var pages = + [ + //////////////////////////////////////////////////////////////////////// + // Lesson 1 + // Simple addition + { + lesson: 1, + title: 'Basics; numbers, strings, etc.', + guide: + '

              ' + rmsg(['Learning By Numbers', 'Music is Math', 'Back to Basics']) + + '

              ' + + "

              To kick off let's try some maths out. Up there you can" + + " type in Haskell expressions. Try this out: 5 + 7

              " + }, + { + guide: function(result) { + if (!result) result = { + expr: '5+7', + result: 12 + }; + var complied = result.expr.replace(/ /g, '') == "5+7"; + var who = complied ? 'we': 'you'; + return '

              ' + rmsg(['Your first Haskell expression', + "First Time's a Charm"]) + '

              ' + + '

              Well done, you typed it perfect! You got back the number' + + ' ' + result.result + '. Just what ' + who + ' wanted. ' + + "

              Let's try something completely different." + + " Type in your name like this:" + + ' "chris"

              ' + }, + trigger: function(result) { + return result.type == "(Num t) => t" || + result.type == "Integer" || + result.type == "Int"; + } + }, + // Strings & types + { + guide: function(result) { + if (!result) result = { + expr: '"chris"', + result: "\"chris\"" + }; + var n = unString(result.result); + if (n) n = ", " + n; + n += "!"; + return '

              ' + rmsg(['Types of values', "What's in a name?"]) + + '

              ' + + '

              Hi there' + htmlEncode(n) + + (n != "!" ? " That's a pretty name. Honest.": "") + + " You're getting the hang of this!

              " + + "

              Note: You can chat to Haskell programmers while learning here, enter chat to start it." + + " You will join the official IRC channel of the Haskell community!

              " + + "

              Each time, you're getting back the value of the expression. So " + + "far, just a number and a list of characters.

              " + + "

              You can have lists of other stuff, too. Let's see your " + + " lottery numbers: [42,13,22]

              " + }, + trigger: function(result) { + return result.type == "[Char]" + || result.type == "String"; + } + }, + // Overview of lesson 1 + { + guide: function(result) { + if (!result) result = { + result: "[42,13,22]" + }; + return '

              ' + rmsg(["Lesson 1 done already!"]) + + '

              ' + + "

              Great, you made a list of numbers! If you win we'll split" + + " the winnings, right?

              " + + "

              Let's see what you've learned so far:

              " + + "
                " + + "
              1. How to write maths and lists of things.
              2. " + + "
              " + + "

              You can do stuff with lists. Maybe you want the lottery " + + "numbers sorted in the right order, try this: " + + "sort " + result.result + "

              " + }, + trigger: function(result) { + return result.expr.match(/^[ ]*\[[0-9, ]+\][ ]*$/) && + result.type == "(Num t) => [t]"; + } + }, + /////////////////////////////////////////////////////////////////////// + // Lesson 2 - Functions + // Functions on lists + { + lesson: 2, + title: 'Simple Functions', + guide: function(result) { + if (!result) result = { + result: "[13,23,30]" + }; + return '

              ' + rmsg(["We put the funk in function"]) + + '

              ' + + "

              Congratulations, you just used a function." + + " They're how you get things done in Haskell." + + "

              As you might've guessed, we got back " + + htmlEncode(result.result) + + ".

              Ever wanted an evil twin nemesis? Me too. " + + "Luckily, you can sort lists of characters, or " + + "strings" + + ", in the same way as numbers! sort \"chris\"

              " + }, + trigger: function(result) { + return result.expr.match(/sort/) && + result.type == "(Num t, Ord t) => [t]"; + } + }, + // Tuples + { + guide: function(result) { + if (!result) result = { + result: "\"chirs\"" + }; + nemesis = htmlEncode(unString(result.result)); + return '

              ' + + rmsg(["Tuples, because sometimes one value ain't enough!"]) + + '

              ' + + "

              Watch out for " + nemesis + "! You should keep their credentials for the police.

              " + + "

              My nemesis is 28 years of age: " + + "(28,\"chirs\")

              " + }, + trigger: function(result) { + return result.expr.match(/sort/) && + result.type == "[Char]"; + } + }, + // Functions on tuples + { + guide: function(result) { + if (!result) result = { + result: "(28,\"chirs\")" + }; + var age = result.result.match(/^\(([0-9]+)+/); + var villain = htmlEncode(result.result.replace(/\\"/g, '"')); + return '

              ' + + rmsg(["We'll keep them safe, don't worry about it."]) + + '

              ' + + "

              Is " + (age ? age[1] : "that") + " a normal age for a " + + "super-villain?

              " + + "

              You just wrote a tuple. It's a way to keep a bunch of values together in Haskell. " + + "You can put as many as you like in there:

              " + + "
              • (1,\"hats\",23/35)
              • (\"Shaggy\",\"Daphnie\",\"Velma\")
              " + + "

              Actually, let's say our villain is " + + "" + villain + "" + + ", how do you get their age?

              " + + "fst " + villain + "" + }, + trigger: function(result) { + return result.expr.match(/\([0-9]+,[ ]*"[^"]+"\)/) && + result.type == "(Num t) => (t, [Char])"; + } + }, + // Summary of lesson 2 + { + guide: function(result) { + return '

              ' + + rmsg(["Lesson 2 done! Wow, great job!", + "Lesson 2 completo!"]) + + '

              ' + + + "

              Good job! You got the age back from the tuple! Didn't " + + " even break a sweat, did you? The fst function " + + "just gets the first value. It's called \"fst\" because " + + "it's used a lot in Haskell so it really needs to be short!

              " + + + "

              Time to take a rest and see what you learned:

              " + + "
                " + + "
              1. Functions can be used on lists of any type.
              2. " + + "
              3. We can stuff values into tuples.
              4. " + + "
              5. Getting the values back from tuples is easy.
              6. " + + "
              " + + + "

              Now let's say you want " + + " to use a value more than once, how would you do it? " + + "To make our lives easier, we can say:

              " + + + "let x = 4 in x * x" + }, + trigger: function(result) { + return result.expr.match(/fst/) && + result.type == "(Num t) => t"; + } + }, + { + guide: function(result) { + return "

              Let them eat cake

              " + + + "

              You just bound a variable. " + + "That is, you bound x to the expression 4, " + + " and then you can write x in some code (the body) and " + + " it will mean the same as if you'd written 4.

              " + + + "

              It's like this: let var = expression in body

              " + + + "The in part just separates the expression from the body.

              " + + + "

              For example try: " + + "let x = 8 * 10 in x + x

              " + + + "

              So if we wanted to get the age of our villain, we could do:

              " + + + "let villain = (28,\"chirs\") in fst villain" + + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]+x[ ]*=[ ]*[0-9]+[ ]*in[ ]*x[ ]*\*[ ]*x/) && + result.type == "(Num t) => t"; + } + }, + { + guide: function(result) { + return "

              Basics over, let's go!

              " + + "

              Next, let's take a short detour to learn about " + + "syntactic sugar. " + + "Try typing this out:

              " + + "

              'a' : []

              " + + "

              Or skip to lesson4 to learn about functions," + + " the meat of Haskell!"; + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]+villain[ ]*=[ ]*\([0-9]+,[ ]*"[^"]+"\)[ ]*in[ ]+fst[ ]+villain[ ]*/) && + result.type == "(Num t) => t"; + } + }, + // Lesson 3: Syntactic sugar + { + lesson: 3, + title: 'Syntactic Sugar', + guide: function(result) { + return '

              ' + + rmsg(["You constructed a list!"]) + + '

              ' + + "

              Well done, that was tricky syntax. You used the (:) " + + "function. It takes two values, some value and a list, and " + + " constructs a new list" + + " out of them. We call it 'cons' for short.

              " + + "

              'a' is " + + "the character 'a', [] is an empty list. So " + + "tacking 'a' at the start of an empty list just " + + "makes a list ['a']!

              " + + "

              But thankfully we don't have to type out " + + "'a' : 'b' : [] every time to we want to make a " + + "list of characters; we can use " + + "syntactic sugar and just write" + + " ['a','b']. Don't believe me, check this!

              " + + "'a' : 'b' : [] == ['a','b']" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*'a'[ ]*:[ ]*\[\][ ]*/) && + result.type == "[Char]"; + } + }, + // Booleans and string syntactic sugar + { + guide: function(result) { + return '

              ' + + rmsg(["You're on fire!"]) + + '

              ' + + "

              You're handling this syntax really well, nice!

              " + + "

              You just got a boolean value back, and it said " + + "True. That means they're equal!

              " + + "

              One final demonstration on syntactic sugar for now:

              " + + "['a','b','c'] == \"abc\"" + }, + trigger: function(result) { + return result.type == "Bool" && + result.expr.replace(/[^':\[\]\=,]/g, '') == "'':'':[]==['','']"; + } + }, + // Summary of syntactic sugar section + { + guide: function(result) { + return '

              ' + + rmsg(["Lesson 3 over! Syntactic sugar is sweet"]) + + '

              ' + + "

              Let's have a gander at what you learned:

              " + + "
                " + + "
              1. In 'a' : [], : is really just " + + " another function, just clever looking.
              2. " + + "
              3. Pretty functions like this are written like (:) when " + + " you talk about them.
              4. " + + "
              5. A list of characters ['a','b'] can just be written " + + "\"ab\". Much easier!
              6. " + + "
              " + + "

              Phew! You're getting pretty deep! Your arch nemesis, " + + nemesis + ", is gonna try to steal your " + rmsg(['mojo', + 'pizza']) + + "! Let's learn a bit more about functions and passing " + + "them around. Try this:

              map (+1) [1..5]

              "; + }, + trigger: function(result) { + return result.expr.replace(/[^\]\[',=\"]?/g, '') == "['','','']==\"\"" && + result.type == "Bool"; + } + }, + { + lesson: 4, + title: 'Functions, reloaded; passing, defining, etc.', + guide: function() { + var title = + rmsg(["Functions [of a Geisha]", + "Functions, functors, functoids, funky", + "Functions: Expanded fo' real"]); + return "

              " + title + "

              " + + + "

              Here's where the magic begins!

              " + + + "

              You just passed the (+1) " + + "function to the map function.

              " + + + "

              You can try other things like (remember: click to insert them):

              " + + + "
                " + + "
              • map (*99) [1..10]
              • " + + "
              • map (/5) [13,24,52,42]
              • " + + "
              • filter (>5) [62,3,25,7,1,9]
              • " + + "
              " + + + "

              Note that a tuple is different to a list because you can do this:

              " + + "(1,\"George\")" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*map[ ]+\(\+1\)[ ]*\[1..5\][ ]*$/) && + result.type == "(Num a, Enum a) => [a]"; + } + }, + { + guide: function(result) { + return "

              Lists and Tuples

              " + + + "

              You can only " + + " have a list of numbers or a list of characters, whereas in a tuple you can throw anything in!

              " + + + "

              We've also seen that you can make a new list with (:) that joins two values together, like:

              " + + "

              1 : [2,3]

              " + + + "

              But we can't do this with tuples! You can only write a tuple and then look at what's inside. You can't make new ones on the fly like a list." + + + "

              Let's write our own functions! It's really easy. How about something simple:

              " + + "let square x = x * x in square " + rmsg([52, 10, 3]) + "" + + }, + trigger: function(result) { + return result.expr.match(/^[ ]*\(1,"[^"]+"\)[ ]*$/) && + result.type == "(Num t) => (t, [Char])"; + } + }, + { + guide: function(result) { + return "

              Let there be functions

              " + + "

              Nice one! I think you're getting used to the let syntax.

              " + + "

              You defined a function. You can read it as, as for a given " + + "parameter called x, square of " + + "x is x * x." + + "

              Some others you can try are:

              " + + "
              • let add1 x = x + 1 in add1 5
              • " + + "
              • let second x = snd x in second (3,4)
              • " + + "
              " + + "

              Let's go crazy and use our square function with map:

              " + + "let square x = x * x in map square [1..10]" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]*square[ ]+x[ ]*=[ ]*x[ ]*\*[ ]*x[ ]*in[ ]*square[ ]+[0-9]+/) && + result.type == "(Num t) => t"; + } + }, + { + guide: function(result) { + if (!result || !result.value) result = { + value: "[1,4,9,16,25,36,49,64,81,100]" + }; + return "

              Let there be functions

              " + + + "

              That's so cool! You described a simple function square and then " + + "you just passed it to another function (map) and got back " + + htmlEncode(result.value) + ", exactly what you expected!

              " + + + "

              Haskell is pretty good at composing things together like this. " + + "Some other things you can try are:

              " + + + "
                " + + "
              • let add1 x = x + 1 in map add1 [1,5,7]
              • " + + "
              • let take5s = filter (==5) in take5s [1,5,2,5,3,5]
              • " + + "
              • let take5s = filter (==5) in map take5s [[1,5],[5],[1,1]]
              • " + + "
              " + + + "

              Did you get back what you expected?

              " + + + "

              One more example for text; how do you upcase a letter?

              " + + + "

              toUpper 'a'

              " + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]+square[ ]+x[ ]*=[ ]*x[ ]*\*[ ]*x[ ]*in[ ]+map[ ]+square[ ]*\[1..10\][ ]*$/) && + result.type == "(Num a, Enum a) => [a]"; + } + }, + { + guide: function(result) { + return "

              Exercise time!

              " + + + "

              Easy! Remember: characters are written like 'a' and " + + "strings (lists of characters) are written like \"a\"." + + + "

              I need you to use toUpper capitalise my whole name, " + + "\"Chris\". Give it a try." + + " You can do it, I believe in you!

              " + + + '

              Spoiler: map toUpper "Chris"

              ' + }, + trigger: function(result) { + return result.expr.match(/^toUpper 'a'$/) && + result.type == "Char"; + } + }, + { + guide: function(result) { + return "

              Lesson 4 complete!

              " + + + "

              Brilliant! You're making excellent progress! " + + "You just passed toUpper to map. No problem.

              " + + + "

              Let's go over what you've learned in this lesson:

              " + + + "
                " + + "
              1. Functions like map take other functions as parameters.
              2. " + + "
              3. Functions like (+1), (>5) and " + + "square can be passed to other functions.
              4. " + + "
              5. Defining functions is just a case of writing what " + + "to do with the parameters.
              6. " + "
              " + + + "

              Let's check out pattern matching; a way to " + + "get values from other values using patterns. Try this:

              " + + "

              let (a,b) = (10,12) in a * 2

              " + + + "

              Or you can skip this section and go to straight to lesson6; types!

              " + }, + trigger: function(result) { + return result.type == "[Char]" && + result.expr.match(/^map[ ]+toUpper/); + } + }, + { + lesson: 5, + title: 'Pattern Matching', + guide: function(result) { + var title = + rmsg(["And therefore, patterns emerge in nature.", + "And Then Patterns", + "Pattern matching!"]) + return "

              " + title + "

              " + + + "

              Jolly good show!

              " + + "

              So you had a value (10,12) and matched " + + "it against a pattern (a,b), then you were able" + + " to do stuff with the a and b!" + + + "

              Note: Pattern matching (a,b) against " + + "(1,2) to get the a is the same as" + + " doing fst (1,2), like you did in step7!

              " + + + "

              A pattern always matches the way the " + + "value was originally constructed. Remember that \"abc\" is " + + "syntactic sugar for 'a' : 'b' : 'c' : [].

              " + + + "

              So you can get the characters from a string with patterns:

              " + + + "let (a:b:c:[]) = \"xyz\" in a" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]+\(a,b\)[ ]+=[ ]+\(10,12\)[ ]+in[ ]+a[ ]*\*[ ]*2[ ]*$/) && + result.type == "(Num t) => t"; + } + }, + { + guide: function(result) { + return "

              " + rmsg(["Ignorance is bliss", "Ignoring values"]) + "

              " + + + "

              You're getting into tricky syntax, huh? I know you can handle it!

              " + + + "

              If you just want some of the values, you can ignore the others with _ (underscore) like this:

              " + + + "

              let (a:_:_:_) = \"xyz\" in a

              " + + + "

              In fact, (a:b:c:d) is short-hand for " + + "(a:(b:(c:d))), so you can just ignore the rest in one go:

              " + + + "let (a:_) = \"xyz\" in a" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]+\(a:b:c:\[\]\)[ ]*=[ ]*\"xyz\"[ ]*in[ ]+a[ ]*$/) && + result.type == "Char"; + } + }, + { + guide: function(result) { + return "

              " + rmsg(["Exercise!", "Show me the money!"]) + "

              " + + + "

              Try to get the 'a' value from this value using pattern matching:

              " + + "

              (10,\"abc\")

              " + + + "

              Spoiler: let (_,(a:_)) = (10,\"abc\") in a

              " + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]*\(a:_\)[ ]*=[ ]*"xyz"[ ]*in[ ]*a[ ]*$/) && + result.type == "Char"; + } + }, + { + guide: function(result) { + return "

              " + rmsg(["Well done!", "Brilliant!", "Perfetto!"]) + "

              " + + + "

              Wizard! I think you've got pattern-matching down.

              " + + + "

              If you're still a bit unsure, here are some other things you can try:

              " + + + "
                " + + "
              • let _:_:c:_ = \"abcd\" in c
              • " + + "
              • let [a,b,c] = \"cat\" in (a,b,c)
              • " + + "
              " + + + "

              You can also grab a whole value and pattern match on it (have your cake and eat it too):

              " + + + "let abc@(a,b,c) = (10,20,30) in (abc,a,b,c)" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*let[ ]*\(_,\(?a:_\)?\)[ ]*=[ ]*\(10,\"abc\"\)[ ]*in[ ]*a[ ]*$/) && + result.type == "Char"; + } + }, + { + guide: function(result) { + return "

              " + rmsg(["And that's the end of that chapter"]) + "

              " + + + "

              That was easy, right?

              " + + + "

              Let's go over what you've learned in this lesson:

              " + + + "
                " + + "
              1. Values are pattern matched, or deconstructed, by writing however they were constructed.
              2. " + + "
              3. Patterns let you use the values that you match.
              4. " + + "
              5. You can ignore whichever values you want.
              6. " + + "
              7. You can pattern match and keep hold of the original value too.
              8. " + + "
              " + + + "

              Now we get to the Deep Ones. Types!

              " + + + "

              Consider the following value: 'a'

              " + + }, + trigger: function(result) { + return result.type == "(Num t, Num t1, Num t2) => ((t, t1, t2), t, t1, t2)"; + } + }, + { + lesson: 6, + title: 'Types', + guide: function(result) { + showTypes = true; + return "

              " + rmsg(["Types", "What's in a Type?", "Types & Values"]) + "

              " + + "

              What's this? Something new!

              " + + + "

              In Haskell there are types of values. Every value belongs to a type. To demonstrate this fact, I've sneakily enabled types to be " + + "shown of every value in the console from now on.

              " + + + "

              The type of the value 'a' is Char (short for 'character', but you guessed that, right?).

              " + + + "

              You've seen the type of a character, now what about" + + " a list of characters?

              " + + "\"Spartacus\"" + }, + trigger: function(result) { + return result.type == 'Char'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

              " + rmsg(["Lists of stuff, types"]) + "

              " + + + "

              I'm Spartacus!

              " + + + "

              Okay, so a list of characters has type [Char].

              " + + + "

              Notice that when we write a :: X it means the value a has type X. It's just a short-hand called a signature.

              " + + + "

              If you just want the type of a value, without actually evaluating it, you can just type:

              " + + ":t toUpper" + }, + trigger: function(result) { + return result.expr.match(/"[^"]+"/) && + result.type == '[Char]'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

              " + rmsg(["Function types"]) + "

              " + + + "

              Woah! Hold your blinkin' 'orses! The type of toUpper reads: Char -> Char

              " + + + "

              It's pretty easy; a -> b means function from a to b. " + + "So

              toUpper :: Char -> Char means: for a" + + " given character (Char value) a, toUpper a has type Char.

              " + + + "

              Some other things you can try are:

              " + + + "
              • :t words
              • " + + "
              • :t unwords
              • " + + "
              • :t True
              • " + + "
              • :t not
              • " + + "
              " + + + "

              The words function is pretty handy. Want to get a list of words from a sentence?

              " + + "words \"There's jam in my pants.\"" + }, + trigger: function(result) { + return result.type == 'Char -> Char'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

              " + rmsg(["Mid-way review"]) + "

              " + + + "

              The type of words was String -> [String]. You got a list of strings back! Just what you expected, right?

              " + + + "

              Let's take a rest in the middle of this lesson and go over what we've learned:

              " + + + "
                " + + "
              1. All values in Haskell have a type. We describe the types of values with signatures, like True :: Bool.
              2. " + + "
              3. Functions are values too, and they have types, notated a -> b.
              4. " + + "
              5. Functions can be defined for any type to any other type.
              6. " + + "
              7. Humble reader has a thing for jammy pants.
              8. " + + "
              " + + + "

              But what if you have a type that can contain values of any type, like a tuple?

              " + + ":t fst" + + }, + trigger: function(result) { + return result.expr.match(/^[ ]*words[ ]*\"[^"]+\"[ ]*$/) && + result.type == '[String]'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

              " + rmsg(["Polymorphic functions"]) + "

              " + + + "

              Remember this one? I know you do! fst (1,2) is 1, right?

              " + + "

              We read its type

              " + + "

              fst :: (a, b) -> a

              " + + "

              as: for all types a and b, the fst has type (a,b) to a. So the fst " + + "function works on a pair of values of any types! We call such a function polymorphic." + + "

              " + + "

              Remember the drop function? Maybe you don't. I don't! Let's check out its type:

              " + + "

              :t drop

              " + }, + trigger: function(result) { + return result.type == '(a, b) -> a'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

              " + rmsg(["Multi parameter functions"]) + "

              " + + + "

              So the drop function has type

              Int -> [a] -> [a].

              " + + + "

              This is something new. You've got two arrows! Relax. You can read

              " + + "

              a -> b -> c as a -> (b -> c)

              " + + + "

              In other words, drop is a function from integers (Int values) to functions of lists to lists ([a] -> [a] values). Drop is a function to another function.

              " + + + "

              Check for yourself! :t drop 3

              " + }, + trigger: function(result) { + return result.type == 'Int -> [a] -> [a]'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

              " + rmsg(["Partial application"]) + "

              " + + + "

              You've got a function of type [a] -> [a]! The drop function is considered a multi-parameter function. Remember the map function? Its parameters were a function and a list. Just another multi-parameter function.

              " + + + "

              You can add another parameter and, hey presto, you get a list!

              " + + + "drop 3 \"hello!\"" + + }, + trigger: function(result) { + return result.type == '[a] -> [a]'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

              " + rmsg(["Higher order functions"]) + "

              " + + + "

              'Lo bob! You've already used the map function loads. I wonder if you can guess its type?

              " + + + "

              map :: (a -> b) -> [a] -> [b] (spoiler)

              " + + + "

              It's okay to peek! Have a go at guessing these: filter, take

              " + + + "

              Tip: You can use parantheses to use more than one function. You want to double all the numbers over five? Psch!

              " + + "map (*2) (filter (>5) [10,2,16,9,4])" + }, + trigger: function(result) { + return result.expr.match(/^[ ]*drop[ ]*[0-9]+[ ]*"[^"]+"[ ]*$/) && + result.type == '[Char]'; + } + }, + { + guide: function(result) { + showTypes = true; + return "

              " + rmsg(["Phew! Rest time!"]) + "

              " + + + "

              Wow! You're doing so great! Have a look at what you know now!

              " + + + "
                " + + "
              1. Function parameters can be polymorphic; any type!
              2. " + + "
              3. Functions can have multiple parameters by returning more functions.
              4. " + + "
              5. You can wrap expressions in parentheses and apply functions to them as a whole value.
              6. " + + "
              " + + + "

              You're really making great progress. Don't hesitate to sit and play in the console between chapters to get a good feel of it!

              " + + + "

              Stay tuned for more chapters on type classes and the meaning of :t 1, :t (*), etc.

              " + + learnMore + }, + trigger: function(result) { + return result.type == '(Num a, Ord a) => [a]'; + } + } + ]; + // + // var webchat; + // + // function runWebchat() { + // if (!webchat) { + // // Create webchat frame + // var webchat = + // $(''); + // webchat.attr('width', 635); + // webchat.attr('height', 500); + // webchat.css('float', 'left'); + // webchat.css('webkit-border-radius', '3px'); + // webchat.css('moz-border-radius', '3px'); + // webchat.css('border-radius', '3px'); + // webchat.css('border', '5px solid #eeeeee'); + // + // // Extend page wrap to fit console and chat + // $('.page-wrap').css({ + // width: '1250px' + // }); + // $('.primary-content').css('margin-left', 0); + // $('.page-wrap').append(webchat.css('margin-left', '5px')); + // } + // } + + var pageTrigger = -1; + var notices = []; + var controller; + // Console controller + var learnMore; + + //////////////////////////////////////////////////////////////////////// + // Unshow a string + function unString(str) { + return str.replace(/^"(.*)"$/, "$1").replace(/\\"/, '"'); + } + + //////////////////////////////////////////////////////////////////////// + // Random message from a list of messages + function rmsg(choices) { + return choices[Math.floor((Math.random() * 100) % choices.length)]; + } + + // Simple HTML encoding + // Simply replace '<', '>' and '&' + // TODO: Use jQuery's .html() trick, or grab a proper, fast + // HTML encoder. + function htmlEncode(text, shy) { + return ( + ('' + text).replace(/&/g, '&') + .replace(/'); + handleJSON = function(r) { + script.remove(); + func(r); + }; + script.attr('src', url); + $('body').append(script); + } + + + var console = $('.console'); + controller = console.console({ + promptLabel: '> ', + continuedPromptLabel: ' .. ', /*not quiet right but good enough*/ + cancelHandle: function() { + controller.commandRef.ignore = true; + controller.finishCommand(); + controller.report(); + }, + + commandHandle: function(line, report) { + + controller.ajaxloader = $('

              Loading...

              '); + var commandRef = {}; + controller.currentLine = line; + controller.commandRef = commandRef; + controller.report = report; + if (tellAboutRet) tellAboutRet.fadeOut(function() { + $(this).remove(); + }); + + if (libTrigger(line, report)) return; + controller.inner.append(controller.ajaxloader); + controller.scrollToBottom(); + + jsonp("http://localhost:3030/tryruby/run/?cmd=" + encodeHex(line), + function(resp) { + if (commandRef.ignore) { + return; + } + controller.finishCommand(); + var result = resp; + if (pageTrigger > -1 && result.expr) { + triggerTutorialPage(pageTrigger, result); + } + if (result.type) { + if (pageTrigger == 24) showTypes = false; + handleSuccess(report, result); + } else if (result.error) { + report( + [{ + msg: result.error, + className: "jquery-console-message-error jquery-console-message-compile-error" + }] + ); + notice('compile-error', + "A compile-time error! " + + "It just means the expression wasn't quite right. " + + "Try again.", + 'prompt'); + } else if (result.exception) { + var err = limitsError(result.exception); + report( + [{ + msg: err, + className: "jquery-console-message-error jquery-console-message-exception" + }] + ); + if (err == result.exception) { + notice('compile-error', + "A run-time error! The expression was right but the" + + " result didn't make sense. Check your expression and try again.", + 'prompt'); + } + } else if (result.internal) { + report( + [{ + msg: limitsError(result.internal), + className: "jquery-console-message-error jquery-console-message-internal" + }] + ); + } else if (result.bind) { + report(); + } else if (result.result) { + if (result.expr.match(/^:modules/)) { + report( + [{ + msg: result.result.replace(/[\["\]]/g, '') + .replace(/,/g, ', '), + className: "jquery-console-message-type" + }]); + } + } + }); + + }, + + charInsertTrigger: function() { + var t = notice('tellaboutreturn', + "Hit Return when you're " + + "finished typing your expression."); + if (t) tellAboutRet = t; + return true; + }, + autofocus: true, + promptHistory: true, + historyPreserveColumn: true, + welcomeMessage: 'Interactive ruby ready' + }); + + controller.finishCommand = function() { + controller.ajaxloader.remove(); + $('.jquery-console-prompt :last').each(function() { + lastLine = controller.currentLine; + if (!$(this).hasClass('prompt-done')) { + $(this).addClass('prompt-done'); + $(this).click(function() { + controller.promptText(controller.currentLine); + }); + } + }); + } + + makeGuidSamplesClickable(); + + var match = window.location.href.match(/#([0-9]+)$/); + if (match) { + pageTrigger = match[1] - 1; + setTutorialPage(undefined, match[1] - 1); + } + + var match = window.location.href.match(/\?input=([^&]+)/); + if (match) { + controller.promptText(urlDecode(match[1])); + controller.inner.click(); + controller.typer.consoleControl(13); + } + }); + + function urlDecode(encodedString) { + var output = encodedString; + var binVal, + thisString; + var myregexp = /(%[^%]{2})/; + while ((match = myregexp.exec(output)) != null + && match.length > 1 + && match[1] != '') { + binVal = parseInt(match[1].substr(1), 16); + thisString = String.fromCharCode(binVal); + output = output.replace(match[1], thisString); + } + return output; + } + + function makeGuidSamplesClickable() { + $('.chapmark code').each(function() { + $(this).css('cursor', 'pointer'); + $(this).attr('title', 'Click me to insert "' + + $(this).text() + '" into the console.'); + $(this).click(function() { + controller.promptText($(this).text()); + controller.inner.click(); + }); + }); + } + + String.prototype.trim = function() { + return this.replace(/^[\t ]*(.*)[\t ]*$/, '$1'); + }; + + //////////////////////////////////////////////////////////////////////// + // Trigger console commands + function libTrigger(line, report) { + switch (line.trim()) { + case 'help': + { + setTutorialPage(undefined, 0); + report(); + pageTrigger = 0; + return true; + } + case 'back': + { + if (pageTrigger > 0) { + setTutorialPage(undefined, pageTrigger - 1); + pageTrigger--; + report(); + return true; + } + break; + } + case 'lessons': + { + var lessons = $('
                '); + for (var i = 0; i < pages.length; i++) { + if (pages[i].lesson) { + lessons.append($('
              1. '). + html('lesson' + pages[i].lesson + ' - ' + + pages[i].title)); + } + } + var lessonsList = '

                Lessons

                ' + lessons.html(); + tutorialGuide.animate({ + opacity: 0, + height: 0 + }, + 'fast', + function() { + tutorialGuide.html(lessonsList); + tutorialGuide.css({ + height: 'auto' + }); + tutorialGuide.animate({ + opacity: 1 + }, + 'fast'); + makeGuidSamplesClickable(); + }); + report(); + return true; + } + default: + { + if (line.trim() == 'chat') { + notice('irc', + 'Enter your nick on the right hand side and hit Connect!', + 'prompt'); + report(); + runWebchat(); + return true; + } + + var m = line.trim().match(/^link(.*)/); + if (m) { + var data; + if (m[1]) data = m[1].trim(); + else if (lastLine) data = lastLine; + if (data) { + var addr = '?input=' + encodeHex(data); + report([{ + msg: '', + className: 'latest-link' + }]); + var link = $(''). + text('link for ' + data).click(function() { + window.location.href = $(this).attr('href'); + return false; + }); + $('.latest-link').html(link).removeClass('latest-link'); + return true; + } + } + + var m = line.trim().match(/^step([0-9]+)/); + if (m) { + if ((m[1] * 1) <= pages.length) { + setTutorialPage(undefined, m[1] - 1); + report(); + pageTrigger = m[1] - 1; + return true; + } + } + var m = line.trim().match(/^help ([0-9]+)/); + if (m) { + for (var i = 0; i < pages.length; i++) { + if (pages[i].lesson == m[1] * 1) { + setTutorialPage(undefined, i); + report(); + pageTrigger = i; + return true; + } + } + } + } + }; + }; + + //////////////////////////////////////////////////////////////////////// + // Change the tutorial page + function setTutorialPage(result, n) { + if (pages[n]) { + window.location.href = '#' + (1 * n + 1); + tutorialGuide.find('#helpstone').remove(); + tutorialGuide.animate({ + opacity: 0, + height: 0 + }, + 'fast', + function() { + if (typeof(pages[n].guide) == 'function') + tutorialGuide.html(pages[n].guide(result)); + else + tutorialGuide.html(pages[n].guide); + var back = ''; + if (pageTrigger > 0) + back = 'You\'re at step' + (n + 1) + + '. Type back to go back.'; + else + back = 'You\'re at step' + (n + 1) + '. Type step' + (n + 1) + + ' to return here.'; + if (true) tutorialGuide + .append('
                ' + back + '
                ') + .append('
                Lesson: ' + + searchLessonBack(n) + + '
                '); + tutorialGuide.css({ + height: 'auto' + }); + tutorialGuide.animate({ + opacity: 1 + }, + 'fast'); + makeGuidSamplesClickable(); + }); + } + }; + + function searchLessonBack(page) { + for (var i = page; i >= 0; i--) { + if (pages[i].lesson) return pages[i].lesson; + } + return "1"; + } + + //////////////////////////////////////////////////////////////////////// + // Trigger a page according to a result + function triggerTutorialPage(n, result) { + n++; + if (pages[n] && (typeof(pages[n].trigger) == 'function') + && pages[n].trigger(result)) { + pageTrigger++; + setTutorialPage(result, n); + } + }; + + //////////////////////////////////////////////////////////////////////// + // Trigger various libraries after JSONRPC returned + function handleSuccess(report, result) { + if (result.type.match(/^Graphics\.Raphael\.Raphael[\r\n ]/)) { + runRaphael(result.result); + report(); + } + if (result.type.match(/standard/)) { + var hashrocket = ''; + var msg_value = ' => '; + if (result.result == null) { + hashrocket = ' => ' + msg_value = ''; + } + report( + [{ + msg: msg_value + result.output + hashrocket + result.result, + className: "jquery-console-message-value" + }]); + } + + if (result.type.match(/error/)) { + + report( + [{ + msg: result.error, + className: "jquery-console-message-value" + }]); + } + + if (result.type.match(/illegal/)) { + + report( + [{ + msg: 'You are not allowed to run that command!', + className: "jquery-console-message-value" + }]); + } + + + if (result.type.match(/line_continuation/)) { + report( + [{ + msg: '..', + className: "jquery-console-prompt-label" + }]); + } + + }; + + //////////////////////////////////////////////////////////////////////// + // Raphael support + function runRaphael(expr) { + raphaelPaper.clear(); + $('#raphael').parent().parent().slideDown(function() { + var exprs = expr.split(/\n/g); + for (var i = 0; i < exprs.length; i++) + raphaelRunExpr(exprs[i]); + }); + } + function raphaelRunExpr(expr) { + var expr = expr.split(/ /g); + switch (expr[0]) { + case 'new': + { + switch (expr[2]) { + case 'circle': + { + var x = expr[3], + y = expr[4], + radius = expr[5]; + var circle = raphaelPaper.circle(x * 1, y * 1, radius * 1); + circle.attr("fill", "#7360a4"); + break; + } + } + } + } + } + + function notice(name, msg, style) { + if (opera()) return; + if (!notices[name]) { + notices[name] = name; + return controller.notice(msg, style); + } + } + + function limitsError(str) { + if (str == "Terminated!") { + notice('terminated', + "This error means it took to long to work" + + " out on the server.", + 'fadeout'); + return "Terminated!"; + } else if (str == "Time limit exceeded.") { + notice('exceeded', + "This error means it took to long to work out on the server. " + + "Try again.", + 'fadeout'); + return "Terminated! Try again."; + } + return str; + } + +})(jQuery); diff --git a/tryruby/public/javascripts/jquery-1.3.2.min.js b/tryruby/public/javascripts/jquery-1.3.2.min.js new file mode 100644 index 0000000..b1ae21d --- /dev/null +++ b/tryruby/public/javascripts/jquery-1.3.2.min.js @@ -0,0 +1,19 @@ +/* + * jQuery JavaScript Library v1.3.2 + * http://jquery.com/ + * + * Copyright (c) 2009 John Resig + * Dual licensed under the MIT and GPL licenses. + * http://docs.jquery.com/License + * + * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) + * Revision: 6246 + */ +(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("",""]||!O.indexOf("",""]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
                "]||!O.indexOf("",""]||(!O.indexOf("",""]||!O.indexOf("",""]||!o.support.htmlSerialize&&[1,"div
                ","
                "]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}}); +/* + * Sizzle CSS Selector Engine - v0.9.3 + * Copyright 2009, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return UT[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="

                ";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="
                ";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("
                ").append(M.responseText.replace(//g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='
                ';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})(); \ No newline at end of file diff --git a/tryruby/public/javascripts/jquery-1.4.2.min.js b/tryruby/public/javascripts/jquery-1.4.2.min.js new file mode 100644 index 0000000..7c24308 --- /dev/null +++ b/tryruby/public/javascripts/jquery-1.4.2.min.js @@ -0,0 +1,154 @@ +/*! + * jQuery JavaScript Library v1.4.2 + * http://jquery.com/ + * + * Copyright 2010, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2010, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Sat Feb 13 22:33:48 2010 -0500 + */ +(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, +Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& +(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, +a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== +"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, +function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
                a"; +var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, +parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= +false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= +s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, +applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; +else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, +a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== +w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, +cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= +c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); +a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, +function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); +k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), +C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B=0){a.type= +e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& +f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; +if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", +e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, +"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, +d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, +e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); +t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| +g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, +CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, +g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, +text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, +setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= +h[3];l=0;for(m=h.length;l=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== +"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, +h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& +q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; +if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="

                ";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); +(function(){var g=s.createElement("div");g.innerHTML="
                ";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: +function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var j=d;j0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= +{},i;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== +"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", +d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? +a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== +1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"},F={option:[1,""],legend:[1,"
                ","
                "],thead:[1,"","
                "],tr:[2,"","
                "],td:[3,"","
                "],col:[2,"","
                "],area:[1,"",""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
                ","
                "];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= +c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, +wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, +prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, +this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); +return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, +""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); +return this}else{e=0;for(var j=d.length;e0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", +""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===""&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= +c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? +c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= +function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= +Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, +"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= +a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= +a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=//gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!== +"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("
                ").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this}, +serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), +function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href, +global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&& +e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)? +"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache=== +false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B= +false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since", +c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E|| +d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x); +g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status=== +1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b=== +"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional; +if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration=== +"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]|| +c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start; +this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now= +this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem, +e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b
                "; +a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b); +c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a, +d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top- +f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset": +"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in +e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window); diff --git a/tryruby/public/javascripts/jquery.console.js b/tryruby/public/javascripts/jquery.console.js new file mode 100644 index 0000000..d45390d --- /dev/null +++ b/tryruby/public/javascripts/jquery.console.js @@ -0,0 +1,609 @@ +// JQuery Console 1.0 +// Sun Feb 21 20:28:47 GMT 2010 +// +// Copyright 2010 Chris Done, Simon David Pratt. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above +// copyright notice, this list of conditions and the following +// disclaimer. +// +// 2. Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// TESTED ON +// Internet Explorer 6 +// Opera 10.01 +// Chromium 4.0.237.0 (Ubuntu build 31094) +// Firefox 3.5.8, 3.6.2 (Mac) +// Safari 4.0.5 (6531.22.7) (Mac) +// Google Chrome 5.0.375.55 (Mac) + +(function($){ + $.fn.console = function(config){ + //////////////////////////////////////////////////////////////////////// + // Constants + // Some are enums, data types, others just for optimisation + var keyCodes = { + // left + 37: moveBackward, + // right + 39: moveForward, + // up + 38: previousHistory, + // down + 40: nextHistory, + // backspace + 8: backDelete, + // delete + 46: forwardDelete, + // end + 35: moveToEnd, + // start + 36: moveToStart, + // return + 13: commandTrigger, + // tab + 18: doNothing + }; + var ctrlCodes = { + // C-a + 65: moveToStart, + // C-e + 69: moveToEnd, + // C-d + 68: forwardDelete, + // C-n + 78: nextHistory, + // C-p + 80: previousHistory, + // C-b + 66: moveBackward, + // C-f + 70: moveForward, + // C-k + 75: deleteUntilEnd + }; + var altCodes = { + // M-f + 70: moveToNextWord, + // M-b + 66: moveToPreviousWord, + // M-d + 68: deleteNextWord + }; + var cursor = ' '; + // Opera only works with this character, not or ­, + // but IE6 displays this character, which is bad, so just use + // it on Opera. + var wbr = $.browser.opera? '​' : ''; + + //////////////////////////////////////////////////////////////////////// + // Globals + var container = $(this); + var inner = $('
                '); + var typer = $(''); + // Prompt + var promptBox; + var prompt; + var promptLabel = config && config.promptLabel? config.promptLabel : "> "; + var column = 0; + var promptText = ''; + var restoreText = ''; + // Prompt history stack + var history = []; + var ringn = 0; + // For reasons unknown to The Sword of Michael himself, Opera + // triggers and sends a key character when you hit various + // keys like PgUp, End, etc. So there is no way of knowing + // when a user has typed '#' or End. My solution is in the + // typer.keydown and typer.keypress functions; I use the + // variable below to ignore the keypress event if the keydown + // event succeeds. + var cancelKeyPress = 0; + // When this value is false, the prompt will not respond to input + var acceptInput = true; + // When this value is true, the command has been canceled + var cancelCommand = false; + + // External exports object + var extern = {}; + + //////////////////////////////////////////////////////////////////////// + // Main entry point + (function(){ + container.append(inner); + inner.append(typer); + typer.css({position:'absolute',top:0,left:'-9999px'}); + if (config.welcomeMessage) + message(config.welcomeMessage,'jquery-console-welcome'); + newPromptBox(); + if (config.autofocus) { + inner.addClass('jquery-console-focus'); + typer.focus(); + setTimeout(function(){ + inner.addClass('jquery-console-focus'); + typer.focus(); + },100); + } + extern.inner = inner; + extern.typer = typer; + extern.scrollToBottom = scrollToBottom; + })(); + + //////////////////////////////////////////////////////////////////////// + // Reset terminal + extern.reset = function(){ + var welcome = true; + inner.parent().fadeOut(function(){ + inner.find('div').each(function(){ + if (!welcome) + $(this).remove(); + welcome = false; + }); + newPromptBox(); + inner.parent().fadeIn(function(){ + inner.addClass('jquery-console-focus'); + typer.focus(); + }); + }); + }; + + //////////////////////////////////////////////////////////////////////// + // Reset terminal + extern.notice = function(msg,style){ + var n = $('
                ').append($('
                ').text(msg)) + .css({visibility:'hidden'}); + container.append(n); + var focused = true; + if (style=='fadeout') + setTimeout(function(){ + n.fadeOut(function(){ + n.remove(); + }); + },4000); + else if (style=='prompt') { + var a = $('
                '); + n.append(a); + focused = false; + a.click(function(){ n.fadeOut(function(){ n.remove();inner.css({opacity:1}) }); }); + } + var h = n.height(); + n.css({height:'0px',visibility:'visible'}) + .animate({height:h+'px'},function(){ + if (!focused) inner.css({opacity:0.5}); + }); + n.css('cursor','default'); + return n; + }; + + //////////////////////////////////////////////////////////////////////// + // Make a new prompt box + function newPromptBox() { + column = 0; + promptText = ''; + ringn = 0; // Reset the position of the history ring + enableInput(); + promptBox = $('
                '); + var label = $(''); + promptBox.append(label.text(promptLabel).show()); + prompt = $(''); + promptBox.append(prompt); + inner.append(promptBox); + updatePromptDisplay(); + }; + + //////////////////////////////////////////////////////////////////////// + // Handle setting focus + container.click(function(){ + inner.addClass('jquery-console-focus'); + inner.removeClass('jquery-console-nofocus'); + typer.focus(); + scrollToBottom(); + return false; + }); + + //////////////////////////////////////////////////////////////////////// + // Handle losing focus + typer.blur(function(){ + inner.removeClass('jquery-console-focus'); + inner.addClass('jquery-console-nofocus'); + }); + + //////////////////////////////////////////////////////////////////////// + // Handle key hit before translation + // For picking up control characters like up/left/down/right + + typer.keydown(function(e){ + cancelKeyPress = 0; + var keyCode = e.keyCode; + // C-c: cancel the execution + if(e.ctrlKey && keyCode == 67) { + cancelKeyPress = keyCode; + cancelExecution(); + return false; + } + if (acceptInput) { + if (keyCode in keyCodes) { + cancelKeyPress = keyCode; + (keyCodes[keyCode])(); + return false; + } else if (e.ctrlKey && keyCode in ctrlCodes) { + cancelKeyPress = keyCode; + (ctrlCodes[keyCode])(); + return false; + } else if (e.altKey && keyCode in altCodes) { + cancelKeyPress = keyCode; + (altCodes[keyCode])(); + return false; + } + } + }); + + //////////////////////////////////////////////////////////////////////// + // Handle key press + typer.keypress(function(e){ + var keyCode = e.keyCode || e.which; + if (isIgnorableKey(e)) { + return false; + } + if (acceptInput && cancelKeyPress != keyCode && keyCode >= 32){ + if (cancelKeyPress) return false; + if (typeof config.charInsertTrigger == 'undefined' || + (typeof config.charInsertTrigger == 'function' && + config.charInsertTrigger(keyCode,promptText))) + typer.consoleInsert(keyCode); + } + if ($.browser.webkit) return false; + }); + + function isIgnorableKey(e) { + // for now just filter alt+tab that we receive on some platforms when + // user switches windows (goes away from the browser) + return ((e.keyCode == keyCodes.tab || e.keyCode == 192) && e.altKey); + }; + + //////////////////////////////////////////////////////////////////////// + // Rotate through the command history + function rotateHistory(n){ + if (history.length == 0) return; + ringn += n; + if (ringn < 0) ringn = history.length; + else if (ringn > history.length) ringn = 0; + var prevText = promptText; + if (ringn == 0) { + promptText = restoreText; + } else { + promptText = history[ringn - 1]; + } + if (config.historyPreserveColumn) { + if (promptText.length < column + 1) { + column = promptText.length; + } else if (column == 0) { + column = promptText.length; + } + } else if (config.historyColumnAtEnd) { + column = promptText.length; + } else { + column = 0; + } + updatePromptDisplay(); + }; + + function previousHistory() { + rotateHistory(-1); + }; + + function nextHistory() { + rotateHistory(1); + }; + + // Add something to the history ring + function addToHistory(line){ + history.push(line); + restoreText = ''; + }; + + // Delete the character at the current position + function deleteCharAtPos(){ + if (column < promptText.length){ + promptText = + promptText.substring(0,column) + + promptText.substring(column+1); + restoreText = promptText; + return true; + } else return false; + }; + + function backDelete() { + if (moveColumn(-1)){ + deleteCharAtPos(); + updatePromptDisplay(); + } + }; + + function forwardDelete() { + if (deleteCharAtPos()) + updatePromptDisplay(); + }; + + function deleteUntilEnd() { + while(deleteCharAtPos()) { + updatePromptDisplay(); + } + }; + + function deleteNextWord() { + // A word is defined within this context as a series of alphanumeric + // characters. + // Delete up to the next alphanumeric character + while(column < promptText.length && + !isCharAlphanumeric(promptText[column])) { + deleteCharAtPos(); + updatePromptDisplay(); + } + // Then, delete until the next non-alphanumeric character + while(column < promptText.length && + isCharAlphanumeric(promptText[column])) { + deleteCharAtPos(); + updatePromptDisplay(); + } + }; + + //////////////////////////////////////////////////////////////////////// + // Validate command and trigger it if valid, or show a validation error + function commandTrigger() { + var line = promptText; + if (typeof config.commandValidate == 'function') { + var ret = config.commandValidate(line); + if (ret == true || ret == false) { + if (ret) { + handleCommand(); + } + } else { + commandResult(ret,"jquery-console-message-error"); + } + } else { + handleCommand(); + } + }; + + // Scroll to the bottom of the view + function scrollToBottom() { + inner.attr({ scrollTop: inner.attr("scrollHeight") });; + }; + + function cancelExecution() { + if(typeof config.cancelHandle == 'function') { + config.cancelHandle(); + } + } + + //////////////////////////////////////////////////////////////////////// + // Handle a command + function handleCommand() { + if (typeof config.commandHandle == 'function') { + disableInput(); + addToHistory(promptText); + var ret = config.commandHandle(promptText,function(msgs){ + commandResult(msgs); + }); + if (typeof ret == 'boolean') { + if (ret) { + // Command succeeded without a result. + commandResult(); + } else { + commandResult('Command failed.', + "jquery-console-message-error"); + } + } else if (typeof ret == "string") { + commandResult(ret,"jquery-console-message-success"); + } else if (typeof ret == 'object' && ret.length) { + commandResult(ret); + } + } + }; + + //////////////////////////////////////////////////////////////////////// + // Disable input + function disableInput() { + acceptInput = false; + }; + + // Enable input + function enableInput() { + acceptInput = true; + } + + //////////////////////////////////////////////////////////////////////// + // Reset the prompt in invalid command + function commandResult(msg,className) { + column = -1; + updatePromptDisplay(); + if (typeof msg == 'string') { + message(msg,className); + } else { + for (var x in msg) { + var ret = msg[x]; + message(ret.msg,ret.className); + } + } + newPromptBox(); + }; + + //////////////////////////////////////////////////////////////////////// + // Display a message + function message(msg,className) { + var mesg = $('
                '); + if (className) mesg.addClass(className); + mesg.filledText(msg).hide(); + inner.append(mesg); + mesg.show(); + }; + + //////////////////////////////////////////////////////////////////////// + // Handle normal character insertion + typer.consoleInsert = function(keyCode){ + // TODO: remove redundant indirection + var char = String.fromCharCode(keyCode); + var before = promptText.substring(0,column); + var after = promptText.substring(column); + promptText = before + char + after; + moveColumn(1); + restoreText = promptText; + updatePromptDisplay(); + }; + + //////////////////////////////////////////////////////////////////////// + // Move to another column relative to this one + // Negative means go back, positive means go forward. + function moveColumn(n){ + if (column + n >= 0 && column + n <= promptText.length){ + column += n; + return true; + } else return false; + }; + + function moveForward() { + if(moveColumn(1)) { + updatePromptDisplay(); + return true; + } + return false; + }; + + function moveBackward() { + if(moveColumn(-1)) { + updatePromptDisplay(); + return true; + } + return false; + }; + + function moveToStart() { + if (moveColumn(-column)) + updatePromptDisplay(); + }; + + function moveToEnd() { + if (moveColumn(promptText.length-column)) + updatePromptDisplay(); + }; + + function moveToNextWord() { + while(column < promptText.length && + !isCharAlphanumeric(promptText[column]) && + moveForward()) { + } + while(column < promptText.length && + isCharAlphanumeric(promptText[column]) && + moveForward()) { + } + }; + + function moveToPreviousWord() { + // Move backward until we find the first alphanumeric + while(column -1 >= 0 && + !isCharAlphanumeric(promptText[column-1]) && + moveBackward()) { + } + // Move until we find the first non-alphanumeric + while(column -1 >= 0 && + isCharAlphanumeric(promptText[column-1]) && + moveBackward()) { + } + }; + + function isCharAlphanumeric(charToTest) { + if(typeof charToTest == 'string') { + var code = charToTest.charCodeAt(); + return (code >= 'A'.charCodeAt() && code <= 'Z'.charCodeAt()) || + (code >= 'a'.charCodeAt() && code <= 'z'.charCodeAt()) || + (code >= '0'.charCodeAt() && code <= '9'.charCodeAt()); + } + return false; + }; + + function doNothing() {}; + + extern.promptText = function(text){ + if (text) { + promptText = text; + if (column > promptText.length) + column = promptText.length; + updatePromptDisplay(); + } + return promptText; + }; + + //////////////////////////////////////////////////////////////////////// + // Update the prompt display + function updatePromptDisplay(){ + var line = promptText; + var html = ''; + if (column > 0 && line == ''){ + // When we have an empty line just display a cursor. + html = cursor; + } else if (column == promptText.length){ + // We're at the end of the line, so we need to display + // the text *and* cursor. + html = htmlEncode(line) + cursor; + } else { + // Grab the current character, if there is one, and + // make it the current cursor. + var before = line.substring(0, column); + var current = line.substring(column,column+1); + if (current){ + current = + '' + + htmlEncode(current) + + ''; + } + var after = line.substring(column+1); + html = htmlEncode(before) + current + htmlEncode(after); + } + prompt.html(html); + scrollToBottom(); + }; + + // Simple HTML encoding + // Simply replace '<', '>' and '&' + // TODO: Use jQuery's .html() trick, or grab a proper, fast + // HTML encoder. + function htmlEncode(text){ + return ( + text.replace(/&/g,'&') + .replace(/&]{10})/g,'$1­' + wbr) + ); + }; + + return extern; + }; + // Simple utility for printing messages + $.fn.filledText = function(txt){ + $(this).text(txt); + $(this).html($(this).html().replace(/\n/g,'
                ')); + return this; + }; +})(jQuery); diff --git a/tryruby/public/javascripts/jquery.console.min.js b/tryruby/public/javascripts/jquery.console.min.js new file mode 100644 index 0000000..7ae1e6b --- /dev/null +++ b/tryruby/public/javascripts/jquery.console.min.js @@ -0,0 +1 @@ +(function($){$.fn.console=function(config){var keyCodes={left:37,right:39,up:38,down:40,back:8,del:46,end:35,start:36,ret:13};var cursor=' ';var wbr=$.browser.opera?'​':'';var container=$(this);var inner=$('
                ');var typer=$('');var promptBox;var prompt;var promptLabel=config&&config.promptLabel?config.promptLabel:"> ";var column=0;var promptText='';var restoreText='';var history=[];var ringn=0;var cancelKeyPress=0;var extern={};(function(){container.append(inner);inner.append(typer);typer.css({position:'absolute',top:0,left:'-999px'});if(config.welcomeMessage)message(config.welcomeMessage,'jquery-console-welcome');newPromptBox();if(config.autofocus){inner.addClass('jquery-console-focus');typer.focus();setTimeout(function(){inner.addClass('jquery-console-focus');typer.focus()},100)}})();extern.reset=function(){var welcome=true;inner.parent().fadeOut(function(){inner.find('div').each(function(){if(!welcome)$(this).remove();welcome=false});newPromptBox();inner.parent().fadeIn(function(){inner.addClass('jquery-console-focus');typer.focus()})})};function newPromptBox(){column=0;promptText='';promptBox=$('
                ');var label=$('');promptBox.append(label.text(promptLabel).show());prompt=$('');promptBox.append(prompt);inner.append(promptBox);updatePromptDisplay()};container.click(function(){inner.addClass('jquery-console-focus');inner.removeClass('jquery-console-nofocus');typer.focus();scrollToBottom();return false});typer.blur(function(){inner.removeClass('jquery-console-focus');inner.addClass('jquery-console-nofocus')});typer.keydown(function(e){cancelKeyPress=0;var keyCode=e.keyCode;if(isControlCharacter(keyCode)){cancelKeyPress=keyCode;if(!typer.consoleControl(keyCode)){return false}}});typer.keypress(function(e){var keyCode=e.keyCode||e.which;if(cancelKeyPress!=keyCode&&keyCode>=32){if(cancelKeyPress)return false;typer.consoleInsert(keyCode)}if($.browser.webkit)return false});function isControlCharacter(keyCode){return((keyCode>=keyCodes.left&&keyCode<=keyCodes.down)||keyCode==keyCodes.back||keyCode==keyCodes.del||keyCode==keyCodes.end||keyCode==keyCodes.start||keyCode==keyCodes.ret)};typer.consoleControl=function(keyCode){switch(keyCode){case keyCodes.left:{moveColumn(-1);updatePromptDisplay();return false;break}case keyCodes.right:{moveColumn(1);updatePromptDisplay();return false;break}case keyCodes.back:{if(moveColumn(-1)){deleteCharAtPos();updatePromptDisplay()}return false;break}case keyCodes.del:{if(deleteCharAtPos())updatePromptDisplay();return false;break}case keyCodes.end:{if(moveColumn(promptText.length-column))updatePromptDisplay();return false;break}case keyCodes.start:{if(moveColumn(-column))updatePromptDisplay();return false;break}case keyCodes.ret:{commandTrigger();return false}case keyCodes.up:{rotateHistory(-1);return false}case keyCodes.down:{rotateHistory(1);return false}default:}};function rotateHistory(n){if(history.length==0)return;ringn+=n;if(ringn<0)ringn=history.length;else if(ringn>history.length)ringn=0;var prevText=promptText;if(ringn==0){promptText=restoreText}else{promptText=history[ringn-1]}if(config.historyPreserveColumn){if(promptText.length
                ');if(className)mesg.addClass(className);mesg.filledText(msg).hide();inner.append(mesg);mesg.show()};typer.consoleInsert=function(keyCode){var char=String.fromCharCode(keyCode);var before=promptText.substring(0,column);var after=promptText.substring(column);promptText=before+char+after;moveColumn(1);restoreText=promptText;updatePromptDisplay()};function moveColumn(n){if(column+n>=0&&column+n<=promptText.length){column+=n;return true}else return false};function updatePromptDisplay(){var line=promptText;var html='';if(column>0&&line==''){html=cursor}else if(column==promptText.length){html=htmlEncode(line)+cursor}else{var before=line.substring(0,column);var current=line.substring(column,column+1);if(current){current=''+htmlEncode(current)+''}var after=line.substring(column+1);html=htmlEncode(before)+current+htmlEncode(after)}prompt.html(html);scrollToBottom()};function htmlEncode(text){return(text.replace(/&/g,'&').replace(/&]{10})/g,'$1­'+wbr))};return extern};$.fn.filledText=function(txt){$(this).text(txt);$(this).html($(this).html().replace(/\n/g,'
                '));return this}})(jQuery); \ No newline at end of file diff --git a/tryruby/public/javascripts/jquery.js b/tryruby/public/javascripts/jquery.js new file mode 100755 index 0000000..3747929 --- /dev/null +++ b/tryruby/public/javascripts/jquery.js @@ -0,0 +1,32 @@ +/* + * jQuery 1.2.3 - New Wave Javascript + * + * Copyright (c) 2008 John Resig (jquery.com) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * $Date: 2008-02-06 00:21:25 -0500 (Wed, 06 Feb 2008) $ + * $Rev: 4663 $ + */ +(function(){if(window.jQuery)var _jQuery=window.jQuery;var jQuery=window.jQuery=function(selector,context){return new jQuery.prototype.init(selector,context);};if(window.$)var _$=window.$;window.$=jQuery;var quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;var isSimple=/^.[^:#\[\.]*$/;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;return this;}else if(typeof selector=="string"){var match=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1])selector=jQuery.clean([match[1]],context);else{var elem=document.getElementById(match[3]);if(elem)if(elem.id!=match[3])return jQuery().find(selector);else{this[0]=elem;this.length=1;return this;}else +selector=[];}}else +return new jQuery(context).find(selector);}else if(jQuery.isFunction(selector))return new jQuery(document)[jQuery.fn.ready?"ready":"load"](selector);return this.setArray(selector.constructor==Array&&selector||(selector.jquery||selector.length&&selector!=window&&!selector.nodeType&&selector[0]!=undefined&&selector[0].nodeType)&&jQuery.makeArray(selector)||[selector]);},jquery:"1.2.3",size:function(){return this.length;},length:0,get:function(num){return num==undefined?jQuery.makeArray(this):this[num];},pushStack:function(elems){var ret=jQuery(elems);ret.prevObject=this;return ret;},setArray:function(elems){this.length=0;Array.prototype.push.apply(this,elems);return this;},each:function(callback,args){return jQuery.each(this,callback,args);},index:function(elem){var ret=-1;this.each(function(i){if(this==elem)ret=i;});return ret;},attr:function(name,value,type){var options=name;if(name.constructor==String)if(value==undefined)return this.length&&jQuery[type||"attr"](this[0],name)||undefined;else{options={};options[name]=value;}return this.each(function(i){for(name in options)jQuery.attr(type?this.style:this,name,jQuery.prop(this,options[name],type,i,name));});},css:function(key,value){if((key=='width'||key=='height')&&parseFloat(value)<0)value=undefined;return this.attr(key,value,"curCSS");},text:function(text){if(typeof text!="object"&&text!=null)return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(text));var ret="";jQuery.each(text||this,function(){jQuery.each(this.childNodes,function(){if(this.nodeType!=8)ret+=this.nodeType!=1?this.nodeValue:jQuery.fn.text([this]);});});return ret;},wrapAll:function(html){if(this[0])jQuery(html,this[0].ownerDocument).clone().insertBefore(this[0]).map(function(){var elem=this;while(elem.firstChild)elem=elem.firstChild;return elem;}).append(this);return this;},wrapInner:function(html){return this.each(function(){jQuery(this).contents().wrapAll(html);});},wrap:function(html){return this.each(function(){jQuery(this).wrapAll(html);});},append:function(){return this.domManip(arguments,true,false,function(elem){if(this.nodeType==1)this.appendChild(elem);});},prepend:function(){return this.domManip(arguments,true,true,function(elem){if(this.nodeType==1)this.insertBefore(elem,this.firstChild);});},before:function(){return this.domManip(arguments,false,false,function(elem){this.parentNode.insertBefore(elem,this);});},after:function(){return this.domManip(arguments,false,true,function(elem){this.parentNode.insertBefore(elem,this.nextSibling);});},end:function(){return this.prevObject||jQuery([]);},find:function(selector){var elems=jQuery.map(this,function(elem){return jQuery.find(selector,elem);});return this.pushStack(/[^+>] [^+>]/.test(selector)||selector.indexOf("..")>-1?jQuery.unique(elems):elems);},clone:function(events){var ret=this.map(function(){if(jQuery.browser.msie&&!jQuery.isXMLDoc(this)){var clone=this.cloneNode(true),container=document.createElement("div");container.appendChild(clone);return jQuery.clean([container.innerHTML])[0];}else +return this.cloneNode(true);});var clone=ret.find("*").andSelf().each(function(){if(this[expando]!=undefined)this[expando]=null;});if(events===true)this.find("*").andSelf().each(function(i){if(this.nodeType==3)return;var events=jQuery.data(this,"events");for(var type in events)for(var handler in events[type])jQuery.event.add(clone[i],type,events[type][handler],events[type][handler].data);});return ret;},filter:function(selector){return this.pushStack(jQuery.isFunction(selector)&&jQuery.grep(this,function(elem,i){return selector.call(elem,i);})||jQuery.multiFilter(selector,this));},not:function(selector){if(selector.constructor==String)if(isSimple.test(selector))return this.pushStack(jQuery.multiFilter(selector,this,true));else +selector=jQuery.multiFilter(selector,this);var isArrayLike=selector.length&&selector[selector.length-1]!==undefined&&!selector.nodeType;return this.filter(function(){return isArrayLike?jQuery.inArray(this,selector)<0:this!=selector;});},add:function(selector){return!selector?this:this.pushStack(jQuery.merge(this.get(),selector.constructor==String?jQuery(selector).get():selector.length!=undefined&&(!selector.nodeName||jQuery.nodeName(selector,"form"))?selector:[selector]));},is:function(selector){return selector?jQuery.multiFilter(selector,this).length>0:false;},hasClass:function(selector){return this.is("."+selector);},val:function(value){if(value==undefined){if(this.length){var elem=this[0];if(jQuery.nodeName(elem,"select")){var index=elem.selectedIndex,values=[],options=elem.options,one=elem.type=="select-one";if(index<0)return null;for(var i=one?index:0,max=one?index+1:options.length;i=0||jQuery.inArray(this.name,value)>=0);else if(jQuery.nodeName(this,"select")){var values=value.constructor==Array?value:[value];jQuery("option",this).each(function(){this.selected=(jQuery.inArray(this.value,values)>=0||jQuery.inArray(this.text,values)>=0);});if(!values.length)this.selectedIndex=-1;}else +this.value=value;});},html:function(value){return value==undefined?(this.length?this[0].innerHTML:null):this.empty().append(value);},replaceWith:function(value){return this.after(value).remove();},eq:function(i){return this.slice(i,i+1);},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments));},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem);}));},andSelf:function(){return this.add(this.prevObject);},data:function(key,value){var parts=key.split(".");parts[1]=parts[1]?"."+parts[1]:"";if(value==null){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data==undefined&&this.length)data=jQuery.data(this[0],key);return data==null&&parts[1]?this.data(parts[0]):data;}else +return this.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){jQuery.data(this,key,value);});},removeData:function(key){return this.each(function(){jQuery.removeData(this,key);});},domManip:function(args,table,reverse,callback){var clone=this.length>1,elems;return this.each(function(){if(!elems){elems=jQuery.clean(args,this.ownerDocument);if(reverse)elems.reverse();}var obj=this;if(table&&jQuery.nodeName(this,"table")&&jQuery.nodeName(elems[0],"tr"))obj=this.getElementsByTagName("tbody")[0]||this.appendChild(this.ownerDocument.createElement("tbody"));var scripts=jQuery([]);jQuery.each(elems,function(){var elem=clone?jQuery(this).clone(true)[0]:this;if(jQuery.nodeName(elem,"script")){scripts=scripts.add(elem);}else{if(elem.nodeType==1)scripts=scripts.add(jQuery("script",elem).remove());callback.call(obj,elem);}});scripts.each(evalScript);});}};jQuery.prototype.init.prototype=jQuery.prototype;function evalScript(i,elem){if(elem.src)jQuery.ajax({url:elem.src,async:false,dataType:"script"});else +jQuery.globalEval(elem.text||elem.textContent||elem.innerHTML||"");if(elem.parentNode)elem.parentNode.removeChild(elem);}jQuery.extend=jQuery.fn.extend=function(){var target=arguments[0]||{},i=1,length=arguments.length,deep=false,options;if(target.constructor==Boolean){deep=target;target=arguments[1]||{};i=2;}if(typeof target!="object"&&typeof target!="function")target={};if(length==1){target=this;i=0;}for(;i-1;}},swap:function(elem,options,callback){var old={};for(var name in options){old[name]=elem.style[name];elem.style[name]=options[name];}callback.call(elem);for(var name in options)elem.style[name]=old[name];},css:function(elem,name,force){if(name=="width"||name=="height"){var val,props={position:"absolute",visibility:"hidden",display:"block"},which=name=="width"?["Left","Right"]:["Top","Bottom"];function getWH(){val=name=="width"?elem.offsetWidth:elem.offsetHeight;var padding=0,border=0;jQuery.each(which,function(){padding+=parseFloat(jQuery.curCSS(elem,"padding"+this,true))||0;border+=parseFloat(jQuery.curCSS(elem,"border"+this+"Width",true))||0;});val-=Math.round(padding+border);}if(jQuery(elem).is(":visible"))getWH();else +jQuery.swap(elem,props,getWH);return Math.max(0,val);}return jQuery.curCSS(elem,name,force);},curCSS:function(elem,name,force){var ret;function color(elem){if(!jQuery.browser.safari)return false;var ret=document.defaultView.getComputedStyle(elem,null);return!ret||ret.getPropertyValue("color")=="";}if(name=="opacity"&&jQuery.browser.msie){ret=jQuery.attr(elem.style,"opacity");return ret==""?"1":ret;}if(jQuery.browser.opera&&name=="display"){var save=elem.style.outline;elem.style.outline="0 solid black";elem.style.outline=save;}if(name.match(/float/i))name=styleFloat;if(!force&&elem.style&&elem.style[name])ret=elem.style[name];else if(document.defaultView&&document.defaultView.getComputedStyle){if(name.match(/float/i))name="float";name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var getComputedStyle=document.defaultView.getComputedStyle(elem,null);if(getComputedStyle&&!color(elem))ret=getComputedStyle.getPropertyValue(name);else{var swap=[],stack=[];for(var a=elem;a&&color(a);a=a.parentNode)stack.unshift(a);for(var i=0;i]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+">";});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("",""]||!tags.indexOf("",""]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
                "]||!tags.indexOf("",""]||(!tags.indexOf("",""]||!tags.indexOf("",""]||jQuery.browser.msie&&[1,"div
                ","
                "]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--)div=div.lastChild;if(jQuery.browser.msie){var tbody=!tags.indexOf(""&&tags.indexOf("=0;--j)if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length)tbody[j].parentNode.removeChild(tbody[j]);if(/^\s/.test(elem))div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]),div.firstChild);}elem=jQuery.makeArray(div.childNodes);}if(elem.length===0&&(!jQuery.nodeName(elem,"form")&&!jQuery.nodeName(elem,"select")))return;if(elem[0]==undefined||jQuery.nodeName(elem,"form")||elem.options)ret.push(elem);else +ret=jQuery.merge(ret,elem);});return ret;},attr:function(elem,name,value){if(!elem||elem.nodeType==3||elem.nodeType==8)return undefined;var fix=jQuery.isXMLDoc(elem)?{}:jQuery.props;if(name=="selected"&&jQuery.browser.safari)elem.parentNode.selectedIndex;if(fix[name]){if(value!=undefined)elem[fix[name]]=value;return elem[fix[name]];}else if(jQuery.browser.msie&&name=="style")return jQuery.attr(elem.style,"cssText",value);else if(value==undefined&&jQuery.browser.msie&&jQuery.nodeName(elem,"form")&&(name=="action"||name=="method"))return elem.getAttributeNode(name).nodeValue;else if(elem.tagName){if(value!=undefined){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode)throw"type property can't be changed";elem.setAttribute(name,""+value);}if(jQuery.browser.msie&&/href|src/.test(name)&&!jQuery.isXMLDoc(elem))return elem.getAttribute(name,2);return elem.getAttribute(name);}else{if(name=="opacity"&&jQuery.browser.msie){if(value!=undefined){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+(parseFloat(value).toString()=="NaN"?"":"alpha(opacity="+value*100+")");}return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100).toString():"";}name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase();});if(value!=undefined)elem[name]=value;return elem[name];}},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"");},makeArray:function(array){var ret=[];if(typeof array!="array")for(var i=0,length=array.length;i*",this).remove();while(this.firstChild)this.removeChild(this.firstChild);}},function(name,fn){jQuery.fn[name]=function(){return this.each(fn,arguments);};});jQuery.each(["Height","Width"],function(i,name){var type=name.toLowerCase();jQuery.fn[type]=function(size){return this[0]==window?jQuery.browser.opera&&document.body["client"+name]||jQuery.browser.safari&&window["inner"+name]||document.compatMode=="CSS1Compat"&&document.documentElement["client"+name]||document.body["client"+name]:this[0]==document?Math.max(Math.max(document.body["scroll"+name],document.documentElement["scroll"+name]),Math.max(document.body["offset"+name],document.documentElement["offset"+name])):size==undefined?(this.length?jQuery.css(this[0],type):null):this.css(type,size.constructor==String?size:size+"px");};});var chars=jQuery.browser.safari&&parseInt(jQuery.browser.version)<417?"(?:[\\w*_-]|\\\\.)":"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",quickChild=new RegExp("^>\\s*("+chars+"+)"),quickID=new RegExp("^("+chars+"+)(#)("+chars+"+)"),quickClass=new RegExp("^([#.]?)("+chars+"*)");jQuery.extend({expr:{"":function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},"#":function(a,i,m){return a.getAttribute("id")==m[2];},":":{lt:function(a,i,m){return im[3]-0;},nth:function(a,i,m){return m[3]-0==i;},eq:function(a,i,m){return m[3]-0==i;},first:function(a,i){return i==0;},last:function(a,i,m,r){return i==r.length-1;},even:function(a,i){return i%2==0;},odd:function(a,i){return i%2;},"first-child":function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},"last-child":function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},"only-child":function(a){return!jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},parent:function(a){return a.firstChild;},empty:function(a){return!a.firstChild;},contains:function(a,i,m){return(a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},visible:function(a){return"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},hidden:function(a){return"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},enabled:function(a){return!a.disabled;},disabled:function(a){return a.disabled;},checked:function(a){return a.checked;},selected:function(a){return a.selected||jQuery.attr(a,"selected");},text:function(a){return"text"==a.type;},radio:function(a){return"radio"==a.type;},checkbox:function(a){return"checkbox"==a.type;},file:function(a){return"file"==a.type;},password:function(a){return"password"==a.type;},submit:function(a){return"submit"==a.type;},image:function(a){return"image"==a.type;},reset:function(a){return"reset"==a.type;},button:function(a){return"button"==a.type||jQuery.nodeName(a,"button");},input:function(a){return/input|select|textarea|button/i.test(a.nodeName);},has:function(a,i,m){return jQuery.find(m[3],a).length;},header:function(a){return/h\d/i.test(a.nodeName);},animated:function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}}},parse:[/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,new RegExp("^([:.#]*)("+chars+"+)")],multiFilter:function(expr,elems,not){var old,cur=[];while(expr&&expr!=old){old=expr;var f=jQuery.filter(expr,elems,not);expr=f.t.replace(/^\s*,\s*/,"");cur=not?elems=f.r:jQuery.merge(cur,f.r);}return cur;},find:function(t,context){if(typeof t!="string")return[t];if(context&&context.nodeType!=1&&context.nodeType!=9)return[];context=context||document;var ret=[context],done=[],last,nodeName;while(t&&last!=t){var r=[];last=t;t=jQuery.trim(t);var foundToken=false;var re=quickChild;var m=re.exec(t);if(m){nodeName=m[1].toUpperCase();for(var i=0;ret[i];i++)for(var c=ret[i].firstChild;c;c=c.nextSibling)if(c.nodeType==1&&(nodeName=="*"||c.nodeName.toUpperCase()==nodeName))r.push(c);ret=r;t=t.replace(re,"");if(t.indexOf(" ")==0)continue;foundToken=true;}else{re=/^([>+~])\s*(\w*)/i;if((m=re.exec(t))!=null){r=[];var merge={};nodeName=m[2].toUpperCase();m=m[1];for(var j=0,rl=ret.length;j=0;if(!not&&pass||not&&!pass)tmp.push(r[i]);}return tmp;},filter:function(t,r,not){var last;while(t&&t!=last){last=t;var p=jQuery.parse,m;for(var i=0;p[i];i++){m=p[i].exec(t);if(m){t=t.substring(m[0].length);m[2]=m[2].replace(/\\/g,"");break;}}if(!m)break;if(m[1]==":"&&m[2]=="not")r=isSimple.test(m[3])?jQuery.filter(m[3],r,true).r:jQuery(r).not(m[3]);else if(m[1]==".")r=jQuery.classFilter(r,m[2],not);else if(m[1]=="["){var tmp=[],type=m[3];for(var i=0,rl=r.length;i=0)^not)tmp.push(a);}r=tmp;}else if(m[1]==":"&&m[2]=="nth-child"){var merge={},tmp=[],test=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3]=="even"&&"2n"||m[3]=="odd"&&"2n+1"||!/\D/.test(m[3])&&"0n+"+m[3]||m[3]),first=(test[1]+(test[2]||1))-0,last=test[3]-0;for(var i=0,rl=r.length;i=0)add=true;if(add^not)tmp.push(node);}r=tmp;}else{var fn=jQuery.expr[m[1]];if(typeof fn=="object")fn=fn[m[2]];if(typeof fn=="string")fn=eval("false||function(a,i){return "+fn+";}");r=jQuery.grep(r,function(elem,i){return fn(elem,i,m,r);},not);}}return{r:r,t:t};},dir:function(elem,dir){var matched=[];var cur=elem[dir];while(cur&&cur!=document){if(cur.nodeType==1)matched.push(cur);cur=cur[dir];}return matched;},nth:function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir])if(cur.nodeType==1&&++num==result)break;return cur;},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType==1&&(!elem||n!=elem))r.push(n);}return r;}});jQuery.event={add:function(elem,types,handler,data){if(elem.nodeType==3||elem.nodeType==8)return;if(jQuery.browser.msie&&elem.setInterval!=undefined)elem=window;if(!handler.guid)handler.guid=this.guid++;if(data!=undefined){var fn=handler;handler=function(){return fn.apply(this,arguments);};handler.data=data;handler.guid=fn.guid;}var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){var val;if(typeof jQuery=="undefined"||jQuery.event.triggered)return val;val=jQuery.event.handle.apply(arguments.callee.elem,arguments);return val;});handle.elem=elem;jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];handler.type=parts[1];var handlers=events[type];if(!handlers){handlers=events[type]={};if(!jQuery.event.special[type]||jQuery.event.special[type].setup.call(elem)===false){if(elem.addEventListener)elem.addEventListener(type,handle,false);else if(elem.attachEvent)elem.attachEvent("on"+type,handle);}}handlers[handler.guid]=handler;jQuery.event.global[type]=true;});elem=null;},guid:1,global:{},remove:function(elem,types,handler){if(elem.nodeType==3||elem.nodeType==8)return;var events=jQuery.data(elem,"events"),ret,index;if(events){if(types==undefined||(typeof types=="string"&&types.charAt(0)=="."))for(var type in events)this.remove(elem,type+(types||""));else{if(types.type){handler=types.handler;types=types.type;}jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];if(events[type]){if(handler)delete events[type][handler.guid];else +for(handler in events[type])if(!parts[1]||events[type][handler].type==parts[1])delete events[type][handler];for(ret in events[type])break;if(!ret){if(!jQuery.event.special[type]||jQuery.event.special[type].teardown.call(elem)===false){if(elem.removeEventListener)elem.removeEventListener(type,jQuery.data(elem,"handle"),false);else if(elem.detachEvent)elem.detachEvent("on"+type,jQuery.data(elem,"handle"));}ret=null;delete events[type];}}});}for(ret in events)break;if(!ret){var handle=jQuery.data(elem,"handle");if(handle)handle.elem=null;jQuery.removeData(elem,"events");jQuery.removeData(elem,"handle");}}},trigger:function(type,data,elem,donative,extra){data=jQuery.makeArray(data||[]);if(type.indexOf("!")>=0){type=type.slice(0,-1);var exclusive=true;}if(!elem){if(this.global[type])jQuery("*").add([window,document]).trigger(type,data);}else{if(elem.nodeType==3||elem.nodeType==8)return undefined;var val,ret,fn=jQuery.isFunction(elem[type]||null),event=!data[0]||!data[0].preventDefault;if(event)data.unshift(this.fix({type:type,target:elem}));data[0].type=type;if(exclusive)data[0].exclusive=true;if(jQuery.isFunction(jQuery.data(elem,"handle")))val=jQuery.data(elem,"handle").apply(elem,data);if(!fn&&elem["on"+type]&&elem["on"+type].apply(elem,data)===false)val=false;if(event)data.shift();if(extra&&jQuery.isFunction(extra)){ret=extra.apply(elem,val==null?data:data.concat(val));if(ret!==undefined)val=ret;}if(fn&&donative!==false&&val!==false&&!(jQuery.nodeName(elem,'a')&&type=="click")){this.triggered=true;try{elem[type]();}catch(e){}}this.triggered=false;}return val;},handle:function(event){var val;event=jQuery.event.fix(event||window.event||{});var parts=event.type.split(".");event.type=parts[0];var handlers=jQuery.data(this,"events")&&jQuery.data(this,"events")[event.type],args=Array.prototype.slice.call(arguments,1);args.unshift(event);for(var j in handlers){var handler=handlers[j];args[0].handler=handler;args[0].data=handler.data;if(!parts[1]&&!event.exclusive||handler.type==parts[1]){var ret=handler.apply(this,args);if(val!==false)val=ret;if(ret===false){event.preventDefault();event.stopPropagation();}}}if(jQuery.browser.msie)event.target=event.preventDefault=event.stopPropagation=event.handler=event.data=null;return val;},fix:function(event){var originalEvent=event;event=jQuery.extend({},originalEvent);event.preventDefault=function(){if(originalEvent.preventDefault)originalEvent.preventDefault();originalEvent.returnValue=false;};event.stopPropagation=function(){if(originalEvent.stopPropagation)originalEvent.stopPropagation();originalEvent.cancelBubble=true;};if(!event.target)event.target=event.srcElement||document;if(event.target.nodeType==3)event.target=originalEvent.target.parentNode;if(!event.relatedTarget&&event.fromElement)event.relatedTarget=event.fromElement==event.target?event.toElement:event.fromElement;if(event.pageX==null&&event.clientX!=null){var doc=document.documentElement,body=document.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc.clientTop||0);}if(!event.which&&((event.charCode||event.charCode===0)?event.charCode:event.keyCode))event.which=event.charCode||event.keyCode;if(!event.metaKey&&event.ctrlKey)event.metaKey=event.ctrlKey;if(!event.which&&event.button)event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)));return event;},special:{ready:{setup:function(){bindReady();return;},teardown:function(){return;}},mouseenter:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseover",jQuery.event.special.mouseenter.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseover",jQuery.event.special.mouseenter.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseenter";return jQuery.event.handle.apply(this,arguments);}},mouseleave:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseout",jQuery.event.special.mouseleave.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseout",jQuery.event.special.mouseleave.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseleave";return jQuery.event.handle.apply(this,arguments);}}}};jQuery.fn.extend({bind:function(type,data,fn){return type=="unload"?this.one(type,data,fn):this.each(function(){jQuery.event.add(this,type,fn||data,fn&&data);});},one:function(type,data,fn){return this.each(function(){jQuery.event.add(this,type,function(event){jQuery(this).unbind(event);return(fn||data).apply(this,arguments);},fn&&data);});},unbind:function(type,fn){return this.each(function(){jQuery.event.remove(this,type,fn);});},trigger:function(type,data,fn){return this.each(function(){jQuery.event.trigger(type,data,this,true,fn);});},triggerHandler:function(type,data,fn){if(this[0])return jQuery.event.trigger(type,data,this[0],false,fn);return undefined;},toggle:function(){var args=arguments;return this.click(function(event){this.lastToggle=0==this.lastToggle?1:0;event.preventDefault();return args[this.lastToggle].apply(this,arguments)||false;});},hover:function(fnOver,fnOut){return this.bind('mouseenter',fnOver).bind('mouseleave',fnOut);},ready:function(fn){bindReady();if(jQuery.isReady)fn.call(document,jQuery);else +jQuery.readyList.push(function(){return fn.call(this,jQuery);});return this;}});jQuery.extend({isReady:false,readyList:[],ready:function(){if(!jQuery.isReady){jQuery.isReady=true;if(jQuery.readyList){jQuery.each(jQuery.readyList,function(){this.apply(document);});jQuery.readyList=null;}jQuery(document).triggerHandler("ready");}}});var readyBound=false;function bindReady(){if(readyBound)return;readyBound=true;if(document.addEventListener&&!jQuery.browser.opera)document.addEventListener("DOMContentLoaded",jQuery.ready,false);if(jQuery.browser.msie&&window==top)(function(){if(jQuery.isReady)return;try{document.documentElement.doScroll("left");}catch(error){setTimeout(arguments.callee,0);return;}jQuery.ready();})();if(jQuery.browser.opera)document.addEventListener("DOMContentLoaded",function(){if(jQuery.isReady)return;for(var i=0;i=0){var selector=url.slice(off,url.length);url=url.slice(0,off);}callback=callback||function(){};var type="GET";if(params)if(jQuery.isFunction(params)){callback=params;params=null;}else{params=jQuery.param(params);type="POST";}var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(res,status){if(status=="success"||status=="notmodified")self.html(selector?jQuery("
                ").append(res.responseText.replace(//g,"")).find(selector):res.responseText);self.each(callback,[res.responseText,status,res]);}});return this;},serialize:function(){return jQuery.param(this.serializeArray());},serializeArray:function(){return this.map(function(){return jQuery.nodeName(this,"form")?jQuery.makeArray(this.elements):this;}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type));}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:val.constructor==Array?jQuery.map(val,function(val,i){return{name:elem.name,value:val};}):{name:elem.name,value:val};}).get();}});jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(i,o){jQuery.fn[o]=function(f){return this.bind(o,f);};});var jsc=(new Date).getTime();jQuery.extend({get:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data=null;}return jQuery.ajax({type:"GET",url:url,data:data,success:callback,dataType:type});},getScript:function(url,callback){return jQuery.get(url,null,callback,"script");},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},post:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data={};}return jQuery.ajax({type:"POST",url:url,data:data,success:callback,dataType:type});},ajaxSetup:function(settings){jQuery.extend(jQuery.ajaxSettings,settings);},ajaxSettings:{global:true,type:"GET",timeout:0,contentType:"application/x-www-form-urlencoded",processData:true,async:true,data:null,username:null,password:null,accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(s){var jsonp,jsre=/=\?(&|$)/g,status,data;s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));if(s.data&&s.processData&&typeof s.data!="string")s.data=jQuery.param(s.data);if(s.dataType=="jsonp"){if(s.type.toLowerCase()=="get"){if(!s.url.match(jsre))s.url+=(s.url.match(/\?/)?"&":"?")+(s.jsonp||"callback")+"=?";}else if(!s.data||!s.data.match(jsre))s.data=(s.data?s.data+"&":"")+(s.jsonp||"callback")+"=?";s.dataType="json";}if(s.dataType=="json"&&(s.data&&s.data.match(jsre)||s.url.match(jsre))){jsonp="jsonp"+jsc++;if(s.data)s.data=(s.data+"").replace(jsre,"="+jsonp+"$1");s.url=s.url.replace(jsre,"="+jsonp+"$1");s.dataType="script";window[jsonp]=function(tmp){data=tmp;success();complete();window[jsonp]=undefined;try{delete window[jsonp];}catch(e){}if(head)head.removeChild(script);};}if(s.dataType=="script"&&s.cache==null)s.cache=false;if(s.cache===false&&s.type.toLowerCase()=="get"){var ts=(new Date()).getTime();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"");}if(s.data&&s.type.toLowerCase()=="get"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null;}if(s.global&&!jQuery.active++)jQuery.event.trigger("ajaxStart");if((!s.url.indexOf("http")||!s.url.indexOf("//"))&&s.dataType=="script"&&s.type.toLowerCase()=="get"){var head=document.getElementsByTagName("head")[0];var script=document.createElement("script");script.src=s.url;if(s.scriptCharset)script.charset=s.scriptCharset;if(!jsonp){var done=false;script.onload=script.onreadystatechange=function(){if(!done&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){done=true;success();complete();head.removeChild(script);}};}head.appendChild(script);return undefined;}var requestDone=false;var xml=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();xml.open(s.type,s.url,s.async,s.username,s.password);try{if(s.data)xml.setRequestHeader("Content-Type",s.contentType);if(s.ifModified)xml.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT");xml.setRequestHeader("X-Requested-With","XMLHttpRequest");xml.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default);}catch(e){}if(s.beforeSend)s.beforeSend(xml);if(s.global)jQuery.event.trigger("ajaxSend",[xml,s]);var onreadystatechange=function(isTimeout){if(!requestDone&&xml&&(xml.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null;}status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xml)&&"error"||s.ifModified&&jQuery.httpNotModified(xml,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xml,s.dataType);}catch(e){status="parsererror";}}if(status=="success"){var modRes;try{modRes=xml.getResponseHeader("Last-Modified");}catch(e){}if(s.ifModified&&modRes)jQuery.lastModified[s.url]=modRes;if(!jsonp)success();}else +jQuery.handleError(s,xml,status);complete();if(s.async)xml=null;}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0)setTimeout(function(){if(xml){xml.abort();if(!requestDone)onreadystatechange("timeout");}},s.timeout);}try{xml.send(s.data);}catch(e){jQuery.handleError(s,xml,null,e);}if(!s.async)onreadystatechange();function success(){if(s.success)s.success(data,status);if(s.global)jQuery.event.trigger("ajaxSuccess",[xml,s]);}function complete(){if(s.complete)s.complete(xml,status);if(s.global)jQuery.event.trigger("ajaxComplete",[xml,s]);if(s.global&&!--jQuery.active)jQuery.event.trigger("ajaxStop");}return xml;},handleError:function(s,xml,status,e){if(s.error)s.error(xml,status,e);if(s.global)jQuery.event.trigger("ajaxError",[xml,s,e]);},active:0,httpSuccess:function(r){try{return!r.status&&location.protocol=="file:"||(r.status>=200&&r.status<300)||r.status==304||r.status==1223||jQuery.browser.safari&&r.status==undefined;}catch(e){}return false;},httpNotModified:function(xml,url){try{var xmlRes=xml.getResponseHeader("Last-Modified");return xml.status==304||xmlRes==jQuery.lastModified[url]||jQuery.browser.safari&&xml.status==undefined;}catch(e){}return false;},httpData:function(r,type){var ct=r.getResponseHeader("content-type");var xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0;var data=xml?r.responseXML:r.responseText;if(xml&&data.documentElement.tagName=="parsererror")throw"parsererror";if(type=="script")jQuery.globalEval(data);if(type=="json")data=eval("("+data+")");return data;},param:function(a){var s=[];if(a.constructor==Array||a.jquery)jQuery.each(a,function(){s.push(encodeURIComponent(this.name)+"="+encodeURIComponent(this.value));});else +for(var j in a)if(a[j]&&a[j].constructor==Array)jQuery.each(a[j],function(){s.push(encodeURIComponent(j)+"="+encodeURIComponent(this));});else +s.push(encodeURIComponent(j)+"="+encodeURIComponent(a[j]));return s.join("&").replace(/%20/g,"+");}});jQuery.fn.extend({show:function(speed,callback){return speed?this.animate({height:"show",width:"show",opacity:"show"},speed,callback):this.filter(":hidden").each(function(){this.style.display=this.oldblock||"";if(jQuery.css(this,"display")=="none"){var elem=jQuery("<"+this.tagName+" />").appendTo("body");this.style.display=elem.css("display");if(this.style.display=="none")this.style.display="block";elem.remove();}}).end();},hide:function(speed,callback){return speed?this.animate({height:"hide",width:"hide",opacity:"hide"},speed,callback):this.filter(":visible").each(function(){this.oldblock=this.oldblock||jQuery.css(this,"display");this.style.display="none";}).end();},_toggle:jQuery.fn.toggle,toggle:function(fn,fn2){return jQuery.isFunction(fn)&&jQuery.isFunction(fn2)?this._toggle(fn,fn2):fn?this.animate({height:"toggle",width:"toggle",opacity:"toggle"},fn,fn2):this.each(function(){jQuery(this)[jQuery(this).is(":hidden")?"show":"hide"]();});},slideDown:function(speed,callback){return this.animate({height:"show"},speed,callback);},slideUp:function(speed,callback){return this.animate({height:"hide"},speed,callback);},slideToggle:function(speed,callback){return this.animate({height:"toggle"},speed,callback);},fadeIn:function(speed,callback){return this.animate({opacity:"show"},speed,callback);},fadeOut:function(speed,callback){return this.animate({opacity:"hide"},speed,callback);},fadeTo:function(speed,to,callback){return this.animate({opacity:to},speed,callback);},animate:function(prop,speed,easing,callback){var optall=jQuery.speed(speed,easing,callback);return this[optall.queue===false?"each":"queue"](function(){if(this.nodeType!=1)return false;var opt=jQuery.extend({},optall);var hidden=jQuery(this).is(":hidden"),self=this;for(var p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden)return jQuery.isFunction(opt.complete)&&opt.complete.apply(this);if(p=="height"||p=="width"){opt.display=jQuery.css(this,"display");opt.overflow=this.style.overflow;}}if(opt.overflow!=null)this.style.overflow="hidden";opt.curAnim=jQuery.extend({},prop);jQuery.each(prop,function(name,val){var e=new jQuery.fx(self,opt,name);if(/toggle|show|hide/.test(val))e[val=="toggle"?hidden?"show":"hide":val](prop);else{var parts=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),start=e.cur(true)||0;if(parts){var end=parseFloat(parts[2]),unit=parts[3]||"px";if(unit!="px"){self.style[name]=(end||1)+unit;start=((end||1)/e.cur(true))*start;self.style[name]=start+unit;}if(parts[1])end=((parts[1]=="-="?-1:1)*end)+start;e.custom(start,end,unit);}else +e.custom(start,val,"");}});return true;});},queue:function(type,fn){if(jQuery.isFunction(type)||(type&&type.constructor==Array)){fn=type;type="fx";}if(!type||(typeof type=="string"&&!fn))return queue(this[0],type);return this.each(function(){if(fn.constructor==Array)queue(this,type,fn);else{queue(this,type).push(fn);if(queue(this,type).length==1)fn.apply(this);}});},stop:function(clearQueue,gotoEnd){var timers=jQuery.timers;if(clearQueue)this.queue([]);this.each(function(){for(var i=timers.length-1;i>=0;i--)if(timers[i].elem==this){if(gotoEnd)timers[i](true);timers.splice(i,1);}});if(!gotoEnd)this.dequeue();return this;}});var queue=function(elem,type,array){if(!elem)return undefined;type=type||"fx";var q=jQuery.data(elem,type+"queue");if(!q||array)q=jQuery.data(elem,type+"queue",array?jQuery.makeArray(array):[]);return q;};jQuery.fn.dequeue=function(type){type=type||"fx";return this.each(function(){var q=queue(this,type);q.shift();if(q.length)q[0].apply(this);});};jQuery.extend({speed:function(speed,easing,fn){var opt=speed&&speed.constructor==Object?speed:{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&easing.constructor!=Function&&easing};opt.duration=(opt.duration&&opt.duration.constructor==Number?opt.duration:{slow:600,fast:200}[opt.duration])||400;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false)jQuery(this).dequeue();if(jQuery.isFunction(opt.old))opt.old.apply(this);};return opt;},easing:{linear:function(p,n,firstNum,diff){return firstNum+diff*p;},swing:function(p,n,firstNum,diff){return((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum;}},timers:[],timerId:null,fx:function(elem,options,prop){this.options=options;this.elem=elem;this.prop=prop;if(!options.orig)options.orig={};}});jQuery.fx.prototype={update:function(){if(this.options.step)this.options.step.apply(this.elem,[this.now,this]);(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);if(this.prop=="height"||this.prop=="width")this.elem.style.display="block";},cur:function(force){if(this.elem[this.prop]!=null&&this.elem.style[this.prop]==null)return this.elem[this.prop];var r=parseFloat(jQuery.css(this.elem,this.prop,force));return r&&r>-10000?r:parseFloat(jQuery.curCSS(this.elem,this.prop))||0;},custom:function(from,to,unit){this.startTime=(new Date()).getTime();this.start=from;this.end=to;this.unit=unit||this.unit||"px";this.now=this.start;this.pos=this.state=0;this.update();var self=this;function t(gotoEnd){return self.step(gotoEnd);}t.elem=this.elem;jQuery.timers.push(t);if(jQuery.timerId==null){jQuery.timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;ithis.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var done=true;for(var i in this.options.curAnim)if(this.options.curAnim[i]!==true)done=false;if(done){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(jQuery.css(this.elem,"display")=="none")this.elem.style.display="block";}if(this.options.hide)this.elem.style.display="none";if(this.options.hide||this.options.show)for(var p in this.options.curAnim)jQuery.attr(this.elem.style,p,this.options.orig[p]);}if(done&&jQuery.isFunction(this.options.complete))this.options.complete.apply(this.elem);return false;}else{var n=t-this.startTime;this.state=n/this.options.duration;this.pos=jQuery.easing[this.options.easing||(jQuery.easing.swing?"swing":"linear")](this.state,n,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update();}return true;}};jQuery.fx.step={scrollLeft:function(fx){fx.elem.scrollLeft=fx.now;},scrollTop:function(fx){fx.elem.scrollTop=fx.now;},opacity:function(fx){jQuery.attr(fx.elem.style,"opacity",fx.now);},_default:function(fx){fx.elem.style[fx.prop]=fx.now+fx.unit;}};jQuery.fn.offset=function(){var left=0,top=0,elem=this[0],results;if(elem)with(jQuery.browser){var parent=elem.parentNode,offsetChild=elem,offsetParent=elem.offsetParent,doc=elem.ownerDocument,safari2=safari&&parseInt(version)<522&&!/adobeair/i.test(userAgent),fixed=jQuery.css(elem,"position")=="fixed";if(elem.getBoundingClientRect){var box=elem.getBoundingClientRect();add(box.left+Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),box.top+Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));add(-doc.documentElement.clientLeft,-doc.documentElement.clientTop);}else{add(elem.offsetLeft,elem.offsetTop);while(offsetParent){add(offsetParent.offsetLeft,offsetParent.offsetTop);if(mozilla&&!/^t(able|d|h)$/i.test(offsetParent.tagName)||safari&&!safari2)border(offsetParent);if(!fixed&&jQuery.css(offsetParent,"position")=="fixed")fixed=true;offsetChild=/^body$/i.test(offsetParent.tagName)?offsetChild:offsetParent;offsetParent=offsetParent.offsetParent;}while(parent&&parent.tagName&&!/^body|html$/i.test(parent.tagName)){if(!/^inline|table.*$/i.test(jQuery.css(parent,"display")))add(-parent.scrollLeft,-parent.scrollTop);if(mozilla&&jQuery.css(parent,"overflow")!="visible")border(parent);parent=parent.parentNode;}if((safari2&&(fixed||jQuery.css(offsetChild,"position")=="absolute"))||(mozilla&&jQuery.css(offsetChild,"position")!="absolute"))add(-doc.body.offsetLeft,-doc.body.offsetTop);if(fixed)add(Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));}results={top:top,left:left};}function border(elem){add(jQuery.curCSS(elem,"borderLeftWidth",true),jQuery.curCSS(elem,"borderTopWidth",true));}function add(l,t){left+=parseInt(l)||0;top+=parseInt(t)||0;}return results;};})(); \ No newline at end of file diff --git a/tryruby/public/javascripts/json2.js b/tryruby/public/javascripts/json2.js new file mode 100644 index 0000000..d4f4541 --- /dev/null +++ b/tryruby/public/javascripts/json2.js @@ -0,0 +1 @@ +if(!this.JSON){this.JSON={}}(function(){function f(n){return n<10?'0'+n:n}if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+'-'+f(this.getUTCMonth()+1)+'-'+f(this.getUTCDate())+'T'+f(this.getUTCHours())+':'+f(this.getUTCMinutes())+':'+f(this.getUTCSeconds())+'Z':null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key)}if(typeof rep==='function'){value=rep.call(holder,key,value)}switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null'}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object Array]'){length=value.length;for(i=0;i)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, +Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& +(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, +a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== +"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, +function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
                a"; +var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, +parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= +false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= +s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, +applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; +else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, +a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== +w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, +cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= +c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); +a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, +function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); +k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), +C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B=0){a.type= +e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& +f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; +if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", +e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, +"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, +d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, +e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); +t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| +g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, +CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, +g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, +text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, +setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= +h[3];l=0;for(m=h.length;l=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== +"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, +h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& +q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; +if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="

                ";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); +(function(){var g=s.createElement("div");g.innerHTML="
                ";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: +function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var j=d;j0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= +{},i;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== +"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", +d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? +a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== +1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"},F={option:[1,""],legend:[1,"
                ","
                "],thead:[1,"","
                "],tr:[2,"","
                "],td:[3,"","
                "],col:[2,"","
                "],area:[1,"",""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
                ","
                "];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= +c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, +wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, +prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, +this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); +return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, +""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); +return this}else{e=0;for(var j=d.length;e0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", +""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===""&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= +c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? +c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= +function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= +Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, +"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= +a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= +a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=//gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!== +"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("
                ").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this}, +serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), +function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href, +global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&& +e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)? +"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache=== +false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B= +false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since", +c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E|| +d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x); +g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status=== +1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b=== +"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional; +if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration=== +"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]|| +c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start; +this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now= +this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem, +e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b
                "; +a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b); +c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a, +d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top- +f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset": +"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in +e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window); +/*json2.js*/ +if(!this.JSON){this.JSON={}}(function(){function f(n){return n<10?'0'+n:n}if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+'-'+f(this.getUTCMonth()+1)+'-'+f(this.getUTCDate())+'T'+f(this.getUTCHours())+':'+f(this.getUTCMinutes())+':'+f(this.getUTCSeconds())+'Z':null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key)}if(typeof rep==='function'){value=rep.call(holder,key,value)}switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null'}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object Array]'){length=value.length;for(i=0;i
                ');var typer=$('');var promptBox;var prompt;var promptLabel=config&&config.promptLabel?config.promptLabel:"> ";var column=0;var promptText='';var restoreText='';var history=[];var ringn=0;var cancelKeyPress=0;var extern={};(function(){container.append(inner);inner.append(typer);typer.css({position:'absolute',top:0,left:'-999px'});if(config.welcomeMessage)message(config.welcomeMessage,'jquery-console-welcome');newPromptBox();if(config.autofocus){inner.addClass('jquery-console-focus');typer.focus();setTimeout(function(){inner.addClass('jquery-console-focus');typer.focus()},100)}})();extern.reset=function(){var welcome=true;inner.parent().fadeOut(function(){inner.find('div').each(function(){if(!welcome)$(this).remove();welcome=false});newPromptBox();inner.parent().fadeIn(function(){inner.addClass('jquery-console-focus');typer.focus()})})};function newPromptBox(){column=0;promptText='';promptBox=$('
                ');var label=$('');promptBox.append(label.text(promptLabel).show());prompt=$('');promptBox.append(prompt);inner.append(promptBox);updatePromptDisplay()};container.click(function(){inner.addClass('jquery-console-focus');inner.removeClass('jquery-console-nofocus');typer.focus();scrollToBottom();return false});typer.blur(function(){inner.removeClass('jquery-console-focus');inner.addClass('jquery-console-nofocus')});typer.keydown(function(e){cancelKeyPress=0;var keyCode=e.keyCode;if(isControlCharacter(keyCode)){cancelKeyPress=keyCode;if(!typer.consoleControl(keyCode)){return false}}});typer.keypress(function(e){var keyCode=e.keyCode||e.which;if(cancelKeyPress!=keyCode&&keyCode>=32){if(cancelKeyPress)return false;typer.consoleInsert(keyCode)}if($.browser.webkit)return false});function isControlCharacter(keyCode){return((keyCode>=keyCodes.left&&keyCode<=keyCodes.down)||keyCode==keyCodes.back||keyCode==keyCodes.del||keyCode==keyCodes.end||keyCode==keyCodes.start||keyCode==keyCodes.ret)};typer.consoleControl=function(keyCode){switch(keyCode){case keyCodes.left:{moveColumn(-1);updatePromptDisplay();return false;break}case keyCodes.right:{moveColumn(1);updatePromptDisplay();return false;break}case keyCodes.back:{if(moveColumn(-1)){deleteCharAtPos();updatePromptDisplay()}return false;break}case keyCodes.del:{if(deleteCharAtPos())updatePromptDisplay();return false;break}case keyCodes.end:{if(moveColumn(promptText.length-column))updatePromptDisplay();return false;break}case keyCodes.start:{if(moveColumn(-column))updatePromptDisplay();return false;break}case keyCodes.ret:{commandTrigger();return false}case keyCodes.up:{rotateHistory(-1);return false}case keyCodes.down:{rotateHistory(1);return false}default:}};function rotateHistory(n){if(history.length==0)return;ringn+=n;if(ringn<0)ringn=history.length;else if(ringn>history.length)ringn=0;var prevText=promptText;if(ringn==0){promptText=restoreText}else{promptText=history[ringn-1]}if(config.historyPreserveColumn){if(promptText.length
                ');if(className)mesg.addClass(className);mesg.filledText(msg).hide();inner.append(mesg);mesg.show()};typer.consoleInsert=function(keyCode){var char=String.fromCharCode(keyCode);var before=promptText.substring(0,column);var after=promptText.substring(column);promptText=before+char+after;moveColumn(1);restoreText=promptText;updatePromptDisplay()};function moveColumn(n){if(column+n>=0&&column+n<=promptText.length){column+=n;return true}else return false};function updatePromptDisplay(){var line=promptText;var html='';if(column>0&&line==''){html=cursor}else if(column==promptText.length){html=htmlEncode(line)+cursor}else{var before=line.substring(0,column);var current=line.substring(column,column+1);if(current){current=''+htmlEncode(current)+''}var after=line.substring(column+1);html=htmlEncode(before)+current+htmlEncode(after)}prompt.html(html);scrollToBottom()};function htmlEncode(text){return(text.replace(/&/g,'&').replace(/&]{10})/g,'$1­'+wbr))};return extern};$.fn.filledText=function(txt){$(this).text(txt);$(this).html($(this).html().replace(/\n/g,'
                '));return this}})(jQuery); diff --git a/tryruby/public/javascripts/mouseapp_2.js b/tryruby/public/javascripts/mouseapp_2.js new file mode 100755 index 0000000..de5c777 --- /dev/null +++ b/tryruby/public/javascripts/mouseapp_2.js @@ -0,0 +1,913 @@ +// +// Copyright (c) 2008 why the lucky stiff +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +var MouseApp = { + Version: '0.12', + CharCodes: { + 0: ' ', 1: ' ', 9: ' ', + 32: ' ', 34: '"', 38: '&', + 60: '<', 62: '>', 127: '◊', + 0x20AC: '€' + }, + KeyCodes: { + Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 33, PageDown: 34, + End: 35, Home: 36, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 45, + Delete: 46, F1: 112, F2: 113, F3: 114, F4: 115, F5: 116, F6: 117, + F7: 118, F8: 119, F10: 121 + }, + CodeKeys: {}, + Modes: { 1: 'b', 2: 'u', 4: 'i', 8: 'strike' }, + ModeIds: { r: 1, u: 2, i: 4, s: 8 }, + Colors: ['black', 'blue', 'green', + 'cyan', 'red', 'purple', 'brown', + 'gray', 'dark_gray', 'lt_blue', + 'lt_green', 'lt_cyan', 'lt_red', + 'lt_purple', 'yellow', 'white'] +} +//some of these are patently false, because I need to get on a real keyboard-- not a macbook. +if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1){ + MouseApp.KeyCodes = { + Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, + End: 63275, Home: 63273, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 632325, + Delete: 46, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, + F7: 63242, F8: 63243, F10: 63244 + } + +} + +//even though I am tempted to combine chrome and opera into the same if statment, I will refrain for now +// i dont have proper access to a proper keyboard and there might be a single difference between the two +if (navigator.userAgent.indexOf("Opera") > -1){ + MouseApp.KeyCodes = { + Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, + End: 63275, Home: 63273, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 632325, + Delete: 46, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, + F7: 63242, F8: 63243, F10: 63244 + } + +} + +// i am going to comment this out, since this seems un needed. if it past december 15 2009 and this +// is still commented it, please del me +//if ( navigator.appVersion.indexOf('AppleWebKit') > 0 ) { +// MouseApp.KeyCodes = { +// Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, +// End: 63275, Home: 63273, Left: 63234, Up: 63232, Right: 63235, Down: 63233, Insert: 632325, +// Delete: 63272, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, +// F7: 63242, F8: 63243, F10: 63244 +// };// +//} +for ( var k in MouseApp.KeyCodes ) { + MouseApp.CodeKeys[MouseApp.KeyCodes[k]] = k; +} + +MouseApp.isPrintable = function(ch) { + return (ch >= 32); +}; + +MouseApp.Base = function(){}; +MouseApp.Base.prototype = { + setOptions: function(options) { + this.options = { + columns: 72, rows: 24, indent: 2, + title: 'MouseApp', + blinkRate: 500, + ps: '>', + greeting:'%+r Terminal ready. %-r' + } + $.extend(this.options, options || {}); + } +} + +MouseApp.Manager = new Object(); +$.extend(MouseApp.Manager, { + observeTerm: function(term) { + this.activeTerm = term; + if ( this.observingKeyboard ) return; + var mgr = this; + if ( term.input ) { + term.input.keypress(function(e) { mgr.onKeyPress(e) }); + if (!window.opera) term.input.keydown(function(e) { mgr.onKeyDown(e) }); + else window.setInterval(function(){term.input.focus()},1); + } else { + if (!window.opera) $(document).keydown(function(e) { mgr.onKeyDown(e) }); + $(document).keypress(function(e) { mgr.onKeyPress(e) }); + } + this.observingKeyboard = true; + }, + + onKeyDown: function(e) { + e = (e) ? e : ((event) ? event : null); + if ( e && MouseApp.CodeKeys[e.keyCode] ) { + if ( window.event ) { + this.sendKeyPress(e); + } + this.blockEvent(e); + return false; + } + return true; + }, + + onKeyPress: function(e) { + if ( !window.opera && window.event && e.keyCode != 13 && e.keyCode != 8 ) { + e.charCode = e.keyCode; e.keyCode = null; + } + if ( e.keyCode == 191 ) { /* FF 1.0.x sends this upsy quizy -- ignore */ + return; + } + return this.sendKeyPress(e); + }, + + sendKeyPress: function(e) { + var term = MouseApp.Manager.activeTerm; + term.cursorOff(); + b = term.onKeyPress(e); + term.cursorOn(); + return b; + }, + + blockEvent: function (e) { + e.cancelBubble=true; + if (window.event && !window.opera) e.keyCode=0; + if (e.stopPropagation) e.stopPropagation(); + if (e.preventDefault) e.preventDefault(); + } +}); + +/* Basic text window functionality */ +MouseApp.Window = function(element, options) { + this.element = $(element); + this.setOptions(options); + this.initWindow(); +}; + +$.extend(MouseApp.Window.prototype, (new MouseApp.Base()), { + initWindow: function() { + var html = ''; + for ( var i = 0; i < this.options.rows; i++ ) { + html += "
                 
                \n"; + } + this.element.html(html); + this.typingOn(); + if (this.options.input) { + this.input = $(this.options.input); + this.input.focus(); + } + MouseApp.Manager.observeTerm(this); + this.clear(); + this.cursorOn(); + this.painting = true; + this.element.css({visibility: 'visible'}); + }, + + text: function() { + var str = ""; + for (var i = 0; i < this.screen.length; i++ ) { + for (var j = 0; j < this.options.columns; j++ ) { + var ch = this.screen[i][j]; + if ( ch[0] != 0 ) { + str += String.fromCharCode(ch[0]); + } + } + } + return str; + }, + + clear: function() { + this.rpos = 0; + this.cpos = 0; + this.screen = []; + this.element.html(''); + this.screen[0] = this.fillRow(this.options.columns, 0); + this.paint(0); + }, + + typingOn: function() { this.typing = true; }, + typingOff: function() { this.typing = false; }, + + cursorOn: function() { + if ( this.blinker ) { + clearInterval( this.blinker ); + } + this.underblink = this.screen[this.rpos][this.cpos][1]; + MouseApp.Manager.activeTerm.blink(); + this.blinker = setInterval(function(){MouseApp.Manager.activeTerm.blink();}, this.options.blinkRate); + this.cursor = true; + }, + + cursorOff: function() { + if ( this.blinker ) { + clearInterval( this.blinker ); + } + if ( this.cursor ) { + this.screen[this.rpos][this.cpos][1] = this.underblink; + this.paint(this.rpos); + this.cursor = false; + } + }, + + blink: function() { + if ( this == MouseApp.Manager.activeTerm ) { + var mode = this.screen[this.rpos][this.cpos][1]; + this.screen[this.rpos][this.cpos][1] = ( mode & 1 ) ? mode & 4094 : mode | 1; + this.paint(this.rpos); + } + }, + + fillRow: function(len, ch, mode) { + ary = [] + for (var i = 0; i < len; i++) { + ary[i] = [ch, mode]; + } + return ary; + }, + + paint: function(start, end) { + if (!this.painting) return; + + if (!end) end = start; + for (var row = start; row <= end && row < this.screen.length; row++) { + var html = ''; + var mode = 0; + var fcolor = 0; + var bcolor = 0; + var spans = 0; + for (var i = 0; i < this.options.columns; i++ ) { + var c = this.screen[row][i][0]; + var m = this.screen[row][i][1] & 15; // 4 mode bits + var f = (this.screen[row][i][1] & (15 << 4)) >> 4; // 4 foreground bits + var b = (this.screen[row][i][1] & (15 << 8)) >> 8; // 4 background bits + if ( m != mode ) { + if ( MouseApp.Modes[mode] ) html += ""; + if ( MouseApp.Modes[m] ) html += "<" + MouseApp.Modes[m] + ">"; + mode = m; + } + if ( ( f != fcolor && f == 0 ) || ( b != bcolor && b == 0 ) ) { + for ( var s = 0; s < spans; s++ ) html += ""; + fcolor = 0; bcolor = 0; + } + if ( f != fcolor ) { + if ( MouseApp.Colors[f] ) { + html += ""; + spans++; + } + fcolor = f; + } + if ( b != bcolor ) { + if ( MouseApp.Colors[b] ) html += ""; + spans++; bcolor = b; + } + html += MouseApp.CharCodes[c] ? MouseApp.CharCodes[c] : String.fromCharCode(c); + } + if ( MouseApp.Modes[mode] ) html += ""; + for ( var s = 0; s < spans; s++ ) html += ""; + var new_id = this.element.attr('id') + '_' + row; + if (!$('#' + new_id).get(0)) { + this.element.append("
                 
                "); + this.scrollAllTheWayDown(); + } + $('#' + new_id).html(html); + } + }, + + onAfterKey: function() { + this.scrollAllTheWayDown(); + }, + + highlightLine: function(i) { + if (i >= 0 && i < this.screen.length) + { + $("#" + this.element.attr('id') + "_" + i); + } + }, + + scrollToLine: function(i) { + var p = this.element[0].parentNode; + if ( p.scrollHeight > p.clientHeight ) { + p.scrollTop = (p.scrollHeight - p.clientHeight); + } + }, + + scrollAllTheWayDown: function() { + var p = this.element[0].parentNode; + if ( p.scrollHeight > p.clientHeight ) { + p.scrollTop = (p.scrollHeight - p.clientHeight); + } + }, + + putc: function(ch, mode) { + if ( ch == 13 ) { + return; + } else if ( ch == 10 ) { + this.screen[this.rpos][this.cpos] = [ch, mode]; + this.advanceLine(); + } else { + this.screen[this.rpos][this.cpos] = [ch, mode]; + this.paint(this.rpos); + this.advance(); + } + }, + + zpad: function(n) { + if (n < 10) n = "0" + n; + return n; + }, + + puts: function(str, mode) { + if ( !str ) return; + var p = this.painting; + var r = this.rpos; + this.painting = false; + for ( var i = 0; i < str.length; i++ ) { + this.insertc(str.charCodeAt(i), mode); + } + this.painting = p; + this.paint(r, this.rpos); + }, + + advance: function() { + this.cpos++; + if ( this.cpos >= this.options.columns ) { + this.advanceLine(); + } + }, + + advanceLine: function() { + this.cpos = 0; + this.rpos++; + this.ensureRow(this.rpos); + this.paint(this.rpos, this.screen.length - 1); + }, + + fwdc: function() { + var r = this.rpos; + var c = this.cpos; + if ( c < this.options.columns - 1 ) { + c++; + } else if ( r < this.screen.length - 1 ) { + r++; + c = 0; + } + var ch = (c == 0 ? this.screen[r-1][this.options.columns-1] : this.screen[r][c-1]); + if ( MouseApp.isPrintable(ch[0]) ) { + this.rpos = r; + this.cpos = c; + } + }, + + fwdLine: function() { + if ( this.rpos >= this.screen.length - 1 ) return; + this.rpos++; + while ( this.cpos > 0 && !MouseApp.isPrintable(this.screen[this.rpos][this.cpos - 1][0]) ) { + this.cpos--; + } + }, + + backc: function() { + var r = this.rpos; + var c = this.cpos; + if ( c > 0 ) { + c--; + } else if ( r > 0 ) { + c = this.options.columns - 1; + r--; + } + if ( MouseApp.isPrintable(this.screen[r][c][0]) ) { + this.rpos = r; + this.cpos = c; + return true; + } + return false; + }, + + getTypingStart: function() { + var c = this.cpos; + if ( !MouseApp.isPrintable(this.screen[this.rpos][c][0]) ) { + c--; + } + var pos = null; + for ( var r = this.rpos; r >= 0; r-- ) { + while ( c >= 0 ) { + if ( !MouseApp.isPrintable(this.screen[r][c][0]) ) { + return pos; + } + pos = [r, c]; + c--; + } + c = this.options.columns - 1; + } + }, + + getTypingEnd: function(mod) { + var c = this.cpos; + if ( !MouseApp.isPrintable(this.screen[this.rpos][c][0]) ) { + c--; + } + var pos = null; + for ( var r = this.rpos; r < this.screen.length; r++ ) { + while ( c < this.options.columns ) { + if ( !this.screen[r] || !this.screen[r][c] || !MouseApp.isPrintable(this.screen[r][c][0]) ) { + if (!mod) return pos; + mod--; + } + pos = [r, c]; + c++; + } + c = 0; + } + }, + + getTypingAt: function(start, end) { + var r = start[0]; + var c = start[1]; + var str = ''; + while ( r < end[0] || c <= end[1] ) { + if ( c < this.options.columns ) { + str += String.fromCharCode(this.screen[r][c][0]); + c++; + } else { + c = 0; + r++; + } + } + return str; + }, + + ensureRow: function(r) { + if (!this.screen[r]) { + this.screen[r] = this.fillRow(this.options.columns, 0); + } + }, + + insertc: function(ch, mode) { + var r = this.rpos; var c = this.cpos; + var end = this.getTypingEnd(+1); + if (end) { + var thisc = null; + var lastc = this.screen[this.rpos][this.cpos]; + while ( r < end[0] || c <= end[1] ) { + if ( c < this.options.columns ) { + thisc = this.screen[r][c]; + this.screen[r][c] = lastc; + lastc = thisc; + c++; + } else { + c = 0; + r++; + this.ensureRow(r); + } + } + this.paint(this.rpos, end[0]); + } + this.putc(ch, mode); + }, + + delc: function() { + /* end of line */ + if ( MouseApp.isPrintable(this.screen[this.rpos][this.cpos][0]) ) { + var end = this.getTypingEnd(); + var thisc = null; + var lastc = [0, 0]; + while ( this.rpos < end[0] || this.cpos <= end[1] ) { + if ( end[1] >= 0 ) { + thisc = this.screen[end[0]][end[1]]; + this.screen[end[0]][end[1]] = lastc; + lastc = thisc; + end[1]--; + } else { + end[1] = this.options.columns - 1; + this.paint(end[0]); + end[0]--; + } + } + } + }, + + backspace: function() { + /* end of line */ + if ( !MouseApp.isPrintable(this.screen[this.rpos][this.cpos][0]) ) { + this.backc(); + this.screen[this.rpos][this.cpos] = [0, 0]; + } else { + if ( this.backc() ) this.delc(); + } + }, + + backLine: function() { + if ( this.rpos < 1 ) return; + this.rpos--; + while ( this.cpos > 0 && !MouseApp.isPrintable(this.screen[this.rpos][this.cpos - 1][0]) ) { + this.cpos--; + } + }, + + onKeyPress: function(e) { + var ch = e.keyCode; + var key_name = MouseApp.CodeKeys[ch]; + if (window.opera && !e.altKey && e.keyCode != 13 && e.keyCode != 8) key_name = null; + ch = (e.which || e.charCode || e.keyCode); + if (e.which) ch = e.which; + if (!key_name) { key_name = String.fromCharCode(ch); } + if (e.ctrlKey) { key_name = 'Ctrl' + key_name; } + + // alert([e.keyCode, e.which, key_name, this['onKey' + key_name]]); + if (this.typing && this.onAnyKey) this.onAnyKey(key_name); + if (key_name && this['onKey' + key_name]) { + if (this.typing) this['onKey' + key_name](); + MouseApp.Manager.blockEvent(e); + if (this.typing && this.onAfterKey) this.onAfterKey(key_name, true); + return false; + } + if (!e.ctrlKey) { + if (MouseApp.isPrintable(ch)) { + if (this.typing) this.insertc(ch, 0); + MouseApp.Manager.blockEvent(e); + if (this.typing && this.onAfterKey) this.onAfterKey(key_name, true); + return false; + } + } + if (this.typing && this.onAfterKey) this.onAfterKey(key_name, false); + return true; + }, + onKeyHome: function() { + var s = this.getTypingStart(); + this.rpos = s[0]; this.cpos = s[1]; + }, + onKeyEnd: function() { + var e = this.getTypingEnd(+1); + this.rpos = e[0]; this.cpos = e[1]; + }, + onKeyInsert: function() { }, + onKeyDelete: function() { this.delc(); }, + onKeyUp: function() { this.backLine(); }, + onKeyLeft: function() { this.backc(); }, + onKeyRight: function() { this.fwdc(); }, + onKeyDown: function() { this.fwdLine(); }, + onKeyBackspace: function() { this.backspace(); }, + onKeyEnter: function() { this.insertc(10, 0); }, + onKeyTab: function() { + this.insertc(32, 0); + while (this.cpos % this.options.indent != 0) this.insertc(32, 0); + } +}); + +/* Terminal running moush */ +MouseApp.Terminal = function(element, options) { + this.element = $(element); + this.setOptions(options); + this.initWindow(); + this.setup(); +}; + +$.extend(MouseApp.Terminal.prototype, MouseApp.Window.prototype, { + setup: function() { + this.history = []; + this.backupNum = this.historyNum = this.commandNum = 0; + if (this.onStart) { + this.onStart(); + } else { + this.write(this.options.greeting + "\n", true); + this.prompt(); + } + }, + + prompt: function(ps, pt) { + if (!ps) { + ps = this.options.ps; pt = true; + } + this.write(ps, pt); + this.putc(1, 0); + this.typingOn(); + }, + + getCommand: function() { + var s = this.getTypingStart(); + var e = this.getTypingEnd(); + if (!s || !e) return; + return this.getTypingAt(s, e); + }, + + clearCommand: function() { + var s = this.getTypingStart(); + var e = this.getTypingEnd(); + if (!s || !e) return; + var r = s[0]; + var c = s[1]; + this.rpos = r; this.cpos = c; + while ( r < e[0] || c <= e[1] ) { + if ( c < this.options.columns ) { + this.screen[r][c] = [0, 0]; + c++; + } else { + c = 0; + this.paint(r); + r++; + } + } + this.paint(r); + }, + + write: function(str, pcodes) { + var p = this.painting; + var r = this.rpos; + this.painting = false; + var mode = 0; + var today = new Date(); + for ( var i = 0; i < str.length; i++ ) { + if ( str.substr(i,1) == "\n" ) { + this.advanceLine(); + continue; + } else if ( str.substr(i,1) == "\033" ) { + if ( str.substr(i+1,2) == "[m" ) { + mode = 0; + i += 2; + continue; + } + if ( str.substr(i+1,5) == "[0;0m" ) { + mode = 0; + i += 5; + continue; + } + var colors = str.substr(i+1,7).match(/^\[(\d);(\d+)m/); + if ( colors ) { + var colCode = parseInt( colors[2] ); + var color = colCode % 10; + if ( colors[1] == '1' ) { + color += 8; + } + if ( colCode / 10 == 4 ) { + color = color << 4; + } + mode = (mode & 15) + color << 4; + i += colors[0].length; + continue; + } + } else if ( str.substr(i,1) == '%' && pcodes ) { + var s2 = str.substr(i,2); + switch ( s2 ) { + case '%h': + this.puts(this.options.host, mode); + i++; + continue; + case '%l': + this.puts(this.options.name, mode); + i++; + continue; + case '%n': + this.advanceLine(); + i++; + continue; + case '%s': + this.puts("moush", mode); + i++; + continue; + case '%t': + this.puts(this.zpad(today.getHours()) + ":" + this.zpad(today.getMinutes()) + ":" + + this.zpad(today.getSeconds()), mode); + i++; + continue; + case '%u': + this.puts(this.options.user, mode); + i++; + continue; + case '%v': + this.puts(MouseApp.Version, mode); + i++; + continue; + case '%!': + this.puts(this.historyNum.toString(), mode); + i++; + continue; + case '%#': + this.puts(this.commandNum.toString(), mode); + i++; + continue; + case '%+': + var kind = str.substr(i+2, 1); + if ( MouseApp.ModeIds[kind] ) { + mode = mode | MouseApp.ModeIds[kind]; + i += 2; + continue; + } + break; + case '%-': + var kind = str.substr(i+2, 1); + if ( MouseApp.ModeIds[kind] ) { + mode = mode & ( 4095 - MouseApp.ModeIds[kind] ); + i += 2; + continue; + } + break; + } + } + this.putc(str.charCodeAt(i), mode); + } + this.painting = p; + this.paint(r, this.rpos); + }, + + onKeyUp: function() { + if ( this.backupNum == 0 ) return; + if ( this.backupNum == this.historyNum ) { + this.history[this.historyNum] = this.getCommand(); + } + this.clearCommand(); + this.backupNum--; + this.puts(this.history[this.backupNum]); + }, + onKeyDown: function() { + if ( this.backupNum >= this.historyNum ) return; + this.clearCommand(); + this.backupNum++; + this.puts(this.history[this.backupNum]); + }, + onKeyEnter: function() { + var cmd = this.getCommand(); + if (cmd) { + this.history[this.historyNum] = cmd; + this.backupNum = ++this.historyNum; + } + this.commandNum++; + this.advanceLine(); + if (cmd) { + var str = this.onCommand(cmd); + if (str) { + if ( str.substr(str.length - 1, 1) != "\n" ) { + str += "\n"; + } + this.write(str); + } + } + this.prompt(); + }, + onCommand: function(line) { + // this.puts("Echoing: " + line + "\n"); + if ( line == "clear" ) { + this.clear(); + } else { + return "\033[1;37m\033[0;44mYou typed:\033[m " + line; + } + } +}); + +/* Notepad sort of editor */ +MouseApp.Notepad = function(element, options) { + this.element = $(element); + this.setOptions(options); + this.initWindow(); + this.history = []; + this.lineno = 0; +}; + +$.extend(MouseApp.Notepad.prototype, MouseApp.Window.prototype, { + csave: function() { + if ( this.cpos_save ) { + this.cpos = this.cpos_save; + } else { + this.cpos_save = this.cpos; + } + }, + onKeyUp: function() { if ( this.rpos < 1 ) { return; } this.csave(); this.backLine(); }, + onKeyDown: function() { if ( this.rpos < this.screen.length - 1 ) { this.csave(); this.fwdLine(); } }, + onAfterKey: function(key, st) { + if ( st && !(key == 'Up' || key == 'Down') ) { + this.cpos_save = null; + } + }, + insertc: function(ch, mode) { + if (ch == 10) { + this.element.append("
                 
                "); + this.screen.splice(this.rpos + 1, 0, this.fillRow(this.options.columns, 0)); + var c = this.cpos; var c2 = 0; + while (c < this.options.columns) + { + if (this.screen[this.rpos][c] == 0) break; + this.screen[this.rpos + 1][c2] = this.screen[this.rpos][c]; + this.screen[this.rpos][c] = [0, 0]; + c++; c2++; + } + this.paint(this.rpos); + if (MouseApp.isPrintable(this.screen[this.rpos][c])) + { + var r = this.rpos; var c = this.cpos; + this.rpos += 1; this.cpos = c2; + this.delc(); + this.rpos = r; this.cpos = c; + } + this.putc(ch, mode); + if (this.rpos == this.screen.length - 1) + this.scrollAllTheWayDown(); + } else { + var c = this.cpos + 1; + var lastc = this.screen[this.rpos][this.cpos]; + this.putc(ch, mode); + for ( var r = this.rpos; r < this.screen.length; r++ ) { + while (c < this.options.columns) + { + var tmpc = this.screen[r][c]; + if (lastc[0] == 0) + break; + this.screen[r][c] = lastc; + lastc = tmpc; + c++; + } + if (c < this.options.columns) { + break; + } + c = 0; + } + } + }, + + backc: function() { + var r = this.rpos; + var c = this.cpos - 1; + for ( var r = this.rpos; r >= 0; r-- ) { + while ( c >= 0 ) { + this.rpos = r; + this.cpos = c; + if ( this.screen[r][c][0] != 0 ) { + this.paint(r); + return true; + } + this.screen[r][c] = [0, 0]; + c--; + } + c = this.options.columns - 1; + } + return false; + }, + delc: function() { + var c = this.cpos + 1; + for ( var r = this.rpos; r < this.screen.length; r++ ) { + while ( c < this.options.columns ) { + if ( this.screen[r][c][0] != 0 ) { + break; + } + c++; + } + if ( c < this.options.columns ) break; + c = 0; + } + + if (r >= this.screen.length) return; + + var r2 = this.rpos; + var c2 = this.cpos; + for ( var r2 = this.rpos; r2 < this.screen.length; r2++ ) { + while (c2 < this.options.columns) + { + if (this.screen[r][c][0] == 0) + break; + this.screen[r2][c2] = this.screen[r][c]; + c2++; + c++; + if (c >= this.options.columns) { + r++; + if (r >= this.options.rows) break; + c = 0; + } + } + if (c2 < this.options.columns) { + while (c2 < this.options.columns) { + this.screen[r2][c2] = [0, 0]; + c2++; + } + break; + } + c2 = 0; + } + + if (r != r2 && r < this.screen.length) + { + this.screen.splice(r, 1); + $("#" + this.element.attr('id') + "_" + this.screen.length).remove(); + } + this.paint(this.rpos, this.screen.length); + }, + onKeyBackspace: function() { + if (this.backc()) this.delc(); + } + +}); diff --git a/tryruby/public/javascripts/mouseirb_2.js b/tryruby/public/javascripts/mouseirb_2.js new file mode 100755 index 0000000..0fa5f12 --- /dev/null +++ b/tryruby/public/javascripts/mouseirb_2.js @@ -0,0 +1,179 @@ +// +// Copyright (c) 2008 why the lucky stiff +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// + +/* Irb running moush */ +MouseApp.Irb = function(element, options) { + this.element = $(element); + this.setOptions(options); + this.showHelp = this.options.showHelp; + if ( this.options.showChapter ) { + this.showChapter = this.options.showChapter; + } + if ( this.options.init ) { + this.init = this.options.init; + } + this.initWindow(); + this.setup(); + this.helpPage = null; + this.irbInit = false; +}; + +$.extend(MouseApp.Irb.prototype, MouseApp.Terminal.prototype, { + cmdToQuery: function(cmd) { + return "cmd=" + escape(cmd.replace(/</g, '<').replace(/>/g, '>'). + replace(/&/g, '&').replace(/\r?\n/g, "\n")).replace(/\+/g, "%2B"); + }, + + fireOffCmd: function(cmd, func) { + var irb = this; + if (!this.irbInit) + { + $.ajax({url: this.options.irbUrl + "?" + this.cmdToQuery("!INIT!IRB!"), type: "GET", + complete: (function(r) { irb.irbInit = true; irb.fireOffCmd(cmd, func); })}); + } + else + { + $.ajax({url: this.options.irbUrl + "?" + this.cmdToQuery(cmd), type: "GET", + complete: func}); + } + }, + + reply: function(str) { + var raw = str.replace(/\033\[(\d);(\d+)m/g, ''); + this.checkAnswer(raw); + if (!str.match(/^(\.\.)+$/)) { + if ( str[str.length - 1] != "\n" ) { + str += "\n"; + } + js_payload = /\033\[1;JSm(.*)\033\[m/; + js_in = str.match(js_payload); + if (js_in) { + try { + js_in = eval(js_in[1]); + } catch (e) {} + str = str.replace(js_payload, ''); + } + var pr_re = new RegExp("(^|\\n)=>"); + if ( str.match( pr_re ) ) { + str = str.replace(new RegExp("(^|\\n)=>"), "$1\033[1;34m=>\033[m"); + } else { + str = str.replace(new RegExp("(^|\\n)= (.+?) ="), "$1\033[1;33m$2\033[m"); + } + this.write(str); + this.prompt(); + } else { + this.prompt("\033[1;32m" + ".." + "\033[m", true); + this.puts(str.replace(/\./g, ' '), 0); + } + }, + + setHelpPage: function(n, page) { + if (this.helpPage) + $(this.helpPage.ele).hide('fast'); + this.helpPage = {index: n, ele: page}; + match = this.scanHelpPageFor('load'); + if (match != -1) + { + this.fireOffCmd(match, (function(r) { + $(page).show('fast'); + })); + } + else + { + $(page).show('fast'); + } + }, + + scanHelpPageFor: function(eleClass) { + match = $("div." + eleClass, this.helpPage.ele); + if ( match[0] ) return match[0].innerHTML; + else return -1; + }, + + checkAnswer: function(str) { + if ( this.helpPage ) { + match = this.scanHelpPageFor('answer'); + if ( match != -1 ) { + if ( str.match( new RegExp('^\s*=> ' + match + '\s*$', 'm') ) ) { + this.showHelp(this.helpPage.index + 1); + } + } else { + match = this.scanHelpPageFor('stdout'); + if ( match != -1 ) { + if ( match == '' ) { + if ( str == '' || str == null ) this.showHelp(this.helpPage.index + 1); + } else if ( str.match( new RegExp('^\s*' + match + '$', 'm') ) ) { + this.showHelp(this.helpPage.index + 1); + } + } + } + } + }, + + onKeyCtrld: function() { + this.clearCommand(); + this.puts("reset"); + this.onKeyEnter(); + }, + + onKeyEnter: function() { + this.typingOff(); + var cmd = this.getCommand(); + if (cmd) { + this.history[this.historyNum] = cmd; + this.backupNum = ++this.historyNum; + } + this.commandNum++; + this.advanceLine(); + if (cmd) { + if ( cmd == "clear" ) { + this.clear(); + this.prompt(); + } else if ( cmd.match(/^(back)$/) ) { + if (this.helpPage && this.helpPage.index >= 1) { + this.showHelp(this.helpPage.index - 1); + } + this.prompt(); + } else if ( cmd.match(/^(next)$/) ) { + if (this.helpPage) { + this.showHelp(this.helpPage.index + 1); + } + this.prompt(); + } else if ( cmd.match(/^(help|wtf\?*)$/) ) { + this.showHelp(1); + this.prompt(); + } else if ( regs = cmd.match(/^(help|wtf\?*)\s+#?(\d+)\s*$/) ) { + this.showChapter(parseInt(regs[2])); + this.prompt(); + } else { + var term = this; + this.fireOffCmd(cmd, (function(r) { term.reply(r.responseText ? r.responseText : ''); })); + } + } else { + this.prompt(); + } + } +}); + diff --git a/tryruby/public/javascripts/prototype.js b/tryruby/public/javascripts/prototype.js new file mode 100644 index 0000000..06249a6 --- /dev/null +++ b/tryruby/public/javascripts/prototype.js @@ -0,0 +1,6001 @@ +/* Prototype JavaScript framework, version 1.7_rc2 + * (c) 2005-2010 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://www.prototypejs.org/ + * + *--------------------------------------------------------------------------*/ + +var Prototype = { + + Version: '1.7_rc2', + + Browser: (function(){ + var ua = navigator.userAgent; + var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]'; + return { + IE: !!window.attachEvent && !isOpera, + Opera: isOpera, + WebKit: ua.indexOf('AppleWebKit/') > -1, + Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1, + MobileSafari: /Apple.*Mobile/.test(ua) + } + })(), + + BrowserFeatures: { + XPath: !!document.evaluate, + + SelectorsAPI: !!document.querySelector, + + ElementExtensions: (function() { + var constructor = window.Element || window.HTMLElement; + return !!(constructor && constructor.prototype); + })(), + SpecificElementExtensions: (function() { + if (typeof window.HTMLDivElement !== 'undefined') + return true; + + var div = document.createElement('div'), + form = document.createElement('form'), + isSupported = false; + + if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) { + isSupported = true; + } + + div = form = null; + + return isSupported; + })() + }, + + ScriptFragment: ']*>([\\S\\s]*?)<\/script>', + JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, + + emptyFunction: function() { }, + + K: function(x) { return x } +}; + +if (Prototype.Browser.MobileSafari) + Prototype.BrowserFeatures.SpecificElementExtensions = false; + + +var Abstract = { }; + + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) { } + } + + return returnValue; + } +}; + +/* Based on Alex Arnell's inheritance implementation. */ + +var Class = (function() { + + var IS_DONTENUM_BUGGY = (function(){ + for (var p in { toString: 1 }) { + if (p === 'toString') return false; + } + return true; + })(); + + function subclass() {}; + function create() { + var parent = null, properties = $A(arguments); + if (Object.isFunction(properties[0])) + parent = properties.shift(); + + function klass() { + this.initialize.apply(this, arguments); + } + + Object.extend(klass, Class.Methods); + klass.superclass = parent; + klass.subclasses = []; + + if (parent) { + subclass.prototype = parent.prototype; + klass.prototype = new subclass; + parent.subclasses.push(klass); + } + + for (var i = 0, length = properties.length; i < length; i++) + klass.addMethods(properties[i]); + + if (!klass.prototype.initialize) + klass.prototype.initialize = Prototype.emptyFunction; + + klass.prototype.constructor = klass; + return klass; + } + + function addMethods(source) { + var ancestor = this.superclass && this.superclass.prototype, + properties = Object.keys(source); + + if (IS_DONTENUM_BUGGY) { + if (source.toString != Object.prototype.toString) + properties.push("toString"); + if (source.valueOf != Object.prototype.valueOf) + properties.push("valueOf"); + } + + for (var i = 0, length = properties.length; i < length; i++) { + var property = properties[i], value = source[property]; + if (ancestor && Object.isFunction(value) && + value.argumentNames()[0] == "$super") { + var method = value; + value = (function(m) { + return function() { return ancestor[m].apply(this, arguments); }; + })(property).wrap(method); + + value.valueOf = method.valueOf.bind(method); + value.toString = method.toString.bind(method); + } + this.prototype[property] = value; + } + + return this; + } + + return { + create: create, + Methods: { + addMethods: addMethods + } + }; +})(); +(function() { + + var _toString = Object.prototype.toString, + NULL_TYPE = 'Null', + UNDEFINED_TYPE = 'Undefined', + BOOLEAN_TYPE = 'Boolean', + NUMBER_TYPE = 'Number', + STRING_TYPE = 'String', + OBJECT_TYPE = 'Object', + BOOLEAN_CLASS = '[object Boolean]', + NUMBER_CLASS = '[object Number]', + STRING_CLASS = '[object String]', + ARRAY_CLASS = '[object Array]', + NATIVE_JSON_STRINGIFY_SUPPORT = window.JSON && + typeof JSON.stringify === 'function' && + JSON.stringify(0) === '0' && + typeof JSON.stringify(Prototype.K) === 'undefined'; + + function Type(o) { + switch(o) { + case null: return NULL_TYPE; + case (void 0): return UNDEFINED_TYPE; + } + var type = typeof o; + switch(type) { + case 'boolean': return BOOLEAN_TYPE; + case 'number': return NUMBER_TYPE; + case 'string': return STRING_TYPE; + } + return OBJECT_TYPE; + } + + function extend(destination, source) { + for (var property in source) + destination[property] = source[property]; + return destination; + } + + function inspect(object) { + try { + if (isUndefined(object)) return 'undefined'; + if (object === null) return 'null'; + return object.inspect ? object.inspect() : String(object); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } + } + + function toJSON(value) { + return Str('', { '': value }, []); + } + + function Str(key, holder, stack) { + var value = holder[key], + type = typeof value; + + if (Type(value) === OBJECT_TYPE && typeof value.toJSON === 'function') { + value = value.toJSON(key); + } + + var _class = _toString.call(value); + + switch (_class) { + case NUMBER_CLASS: + case BOOLEAN_CLASS: + case STRING_CLASS: + value = value.valueOf(); + } + + switch (value) { + case null: return 'null'; + case true: return 'true'; + case false: return 'false'; + } + + type = typeof value; + switch (type) { + case 'string': + return value.inspect(true); + case 'number': + return isFinite(value) ? String(value) : 'null'; + case 'object': + + for (var i = 0, length = stack.length; i < length; i++) { + if (stack[i] === value) { throw new TypeError(); } + } + stack.push(value); + + var partial = []; + if (_class === ARRAY_CLASS) { + for (var i = 0, length = value.length; i < length; i++) { + var str = Str(i, value, stack); + partial.push(typeof str === 'undefined' ? 'null' : str); + } + partial = '[' + partial.join(',') + ']'; + } else { + var keys = Object.keys(value); + for (var i = 0, length = keys.length; i < length; i++) { + var key = keys[i], str = Str(key, value, stack); + if (typeof str !== "undefined") { + partial.push(key.inspect(true)+ ':' + str); + } + } + partial = '{' + partial.join(',') + '}'; + } + stack.pop(); + return partial; + } + } + + function stringify(object) { + return JSON.stringify(object); + } + + function toQueryString(object) { + return $H(object).toQueryString(); + } + + function toHTML(object) { + return object && object.toHTML ? object.toHTML() : String.interpret(object); + } + + function keys(object) { + if (Type(object) !== OBJECT_TYPE) { throw new TypeError(); } + var results = []; + for (var property in object) { + if (object.hasOwnProperty(property)) { + results.push(property); + } + } + return results; + } + + function values(object) { + var results = []; + for (var property in object) + results.push(object[property]); + return results; + } + + function clone(object) { + return extend({ }, object); + } + + function isElement(object) { + return !!(object && object.nodeType == 1); + } + + function isArray(object) { + return _toString.call(object) === ARRAY_CLASS; + } + + var hasNativeIsArray = (typeof Array.isArray == 'function') + && Array.isArray([]) && !Array.isArray({}); + + if (hasNativeIsArray) { + isArray = Array.isArray; + } + + function isHash(object) { + return object instanceof Hash; + } + + function isFunction(object) { + return typeof object === "function"; + } + + function isString(object) { + return _toString.call(object) === STRING_CLASS; + } + + function isNumber(object) { + return _toString.call(object) === NUMBER_CLASS; + } + + function isUndefined(object) { + return typeof object === "undefined"; + } + + extend(Object, { + extend: extend, + inspect: inspect, + toJSON: NATIVE_JSON_STRINGIFY_SUPPORT ? stringify : toJSON, + toQueryString: toQueryString, + toHTML: toHTML, + keys: Object.keys || keys, + values: values, + clone: clone, + isElement: isElement, + isArray: isArray, + isHash: isHash, + isFunction: isFunction, + isString: isString, + isNumber: isNumber, + isUndefined: isUndefined + }); +})(); +Object.extend(Function.prototype, (function() { + var slice = Array.prototype.slice; + + function update(array, args) { + var arrayLength = array.length, length = args.length; + while (length--) array[arrayLength + length] = args[length]; + return array; + } + + function merge(array, args) { + array = slice.call(array, 0); + return update(array, args); + } + + function argumentNames() { + var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1] + .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '') + .replace(/\s+/g, '').split(','); + return names.length == 1 && !names[0] ? [] : names; + } + + function bind(context) { + if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; + var __method = this, args = slice.call(arguments, 1); + return function() { + var a = merge(args, arguments); + return __method.apply(context, a); + } + } + + function bindAsEventListener(context) { + var __method = this, args = slice.call(arguments, 1); + return function(event) { + var a = update([event || window.event], args); + return __method.apply(context, a); + } + } + + function curry() { + if (!arguments.length) return this; + var __method = this, args = slice.call(arguments, 0); + return function() { + var a = merge(args, arguments); + return __method.apply(this, a); + } + } + + function delay(timeout) { + var __method = this, args = slice.call(arguments, 1); + timeout = timeout * 1000; + return window.setTimeout(function() { + return __method.apply(__method, args); + }, timeout); + } + + function defer() { + var args = update([0.01], arguments); + return this.delay.apply(this, args); + } + + function wrap(wrapper) { + var __method = this; + return function() { + var a = update([__method.bind(this)], arguments); + return wrapper.apply(this, a); + } + } + + function methodize() { + if (this._methodized) return this._methodized; + var __method = this; + return this._methodized = function() { + var a = update([this], arguments); + return __method.apply(null, a); + }; + } + + return { + argumentNames: argumentNames, + bind: bind, + bindAsEventListener: bindAsEventListener, + curry: curry, + delay: delay, + defer: defer, + wrap: wrap, + methodize: methodize + } +})()); + + + +(function(proto) { + + + function toISOString() { + return this.getUTCFullYear() + '-' + + (this.getUTCMonth() + 1).toPaddedString(2) + '-' + + this.getUTCDate().toPaddedString(2) + 'T' + + this.getUTCHours().toPaddedString(2) + ':' + + this.getUTCMinutes().toPaddedString(2) + ':' + + this.getUTCSeconds().toPaddedString(2) + 'Z'; + } + + + function toJSON() { + return this.toISOString(); + } + + if (!proto.toISOString) proto.toISOString = toISOString; + if (!proto.toJSON) proto.toJSON = toJSON; + +})(Date.prototype); + + +RegExp.prototype.match = RegExp.prototype.test; + +RegExp.escape = function(str) { + return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); +}; +var PeriodicalExecuter = Class.create({ + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + execute: function() { + this.callback(this); + }, + + stop: function() { + if (!this.timer) return; + clearInterval(this.timer); + this.timer = null; + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.execute(); + this.currentlyExecuting = false; + } catch(e) { + this.currentlyExecuting = false; + throw e; + } + } + } +}); +Object.extend(String, { + interpret: function(value) { + return value == null ? '' : String(value); + }, + specialChar: { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '\\': '\\\\' + } +}); + +Object.extend(String.prototype, (function() { + var NATIVE_JSON_PARSE_SUPPORT = window.JSON && + typeof JSON.parse === 'function' && + JSON.parse('{"test": true}').test; + + function prepareReplacement(replacement) { + if (Object.isFunction(replacement)) return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; + } + + function gsub(pattern, replacement) { + var result = '', source = this, match; + replacement = prepareReplacement(replacement); + + if (Object.isString(pattern)) + pattern = RegExp.escape(pattern); + + if (!(pattern.length || pattern.source)) { + replacement = replacement(''); + return replacement + source.split('').join(replacement) + replacement; + } + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += String.interpret(replacement(match)); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + } + + function sub(pattern, replacement, count) { + replacement = prepareReplacement(replacement); + count = Object.isUndefined(count) ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + } + + function scan(pattern, iterator) { + this.gsub(pattern, iterator); + return String(this); + } + + function truncate(length, truncation) { + length = length || 30; + truncation = Object.isUndefined(truncation) ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : String(this); + } + + function strip() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + } + + function stripTags() { + return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, ''); + } + + function stripScripts() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + } + + function extractScripts() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'), + matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + } + + function evalScripts() { + return this.extractScripts().map(function(script) { return eval(script) }); + } + + function escapeHTML() { + return this.replace(/&/g,'&').replace(//g,'>'); + } + + function unescapeHTML() { + return this.stripTags().replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&'); + } + + + function toQueryParams(separator) { + var match = this.strip().match(/([^?#]*)(#.*)?$/); + if (!match) return { }; + + return match[1].split(separator || '&').inject({ }, function(hash, pair) { + if ((pair = pair.split('='))[0]) { + var key = decodeURIComponent(pair.shift()), + value = pair.length > 1 ? pair.join('=') : pair[0]; + + if (value != undefined) value = decodeURIComponent(value); + + if (key in hash) { + if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; + hash[key].push(value); + } + else hash[key] = value; + } + return hash; + }); + } + + function toArray() { + return this.split(''); + } + + function succ() { + return this.slice(0, this.length - 1) + + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); + } + + function times(count) { + return count < 1 ? '' : new Array(count + 1).join(this); + } + + function camelize() { + return this.replace(/-+(.)?/g, function(match, chr) { + return chr ? chr.toUpperCase() : ''; + }); + } + + function capitalize() { + return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); + } + + function underscore() { + return this.replace(/::/g, '/') + .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2') + .replace(/([a-z\d])([A-Z])/g, '$1_$2') + .replace(/-/g, '_') + .toLowerCase(); + } + + function dasherize() { + return this.replace(/_/g, '-'); + } + + function inspect(useDoubleQuotes) { + var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) { + if (character in String.specialChar) { + return String.specialChar[character]; + } + return '\\u00' + character.charCodeAt().toPaddedString(2, 16); + }); + if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + } + + function unfilterJSON(filter) { + return this.replace(filter || Prototype.JSONFilter, '$1'); + } + + function isJSON() { + var str = this; + if (str.blank()) return false; + str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'); + str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'); + str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, ''); + return (/^[\],:{}\s]*$/).test(str); + } + + function evalJSON(sanitize) { + var json = this.unfilterJSON(), + cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; + if (cx.test(json)) { + json = json.replace(cx, function (a) { + return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }); + } + try { + if (!sanitize || json.isJSON()) return eval('(' + json + ')'); + } catch (e) { } + throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); + } + + function parseJSON() { + var json = this.unfilterJSON(); + return JSON.parse(json); + } + + function include(pattern) { + return this.indexOf(pattern) > -1; + } + + function startsWith(pattern) { + return this.lastIndexOf(pattern, 0) === 0; + } + + function endsWith(pattern) { + var d = this.length - pattern.length; + return d >= 0 && this.indexOf(pattern, d) === d; + } + + function empty() { + return this == ''; + } + + function blank() { + return /^\s*$/.test(this); + } + + function interpolate(object, pattern) { + return new Template(this, pattern).evaluate(object); + } + + return { + gsub: gsub, + sub: sub, + scan: scan, + truncate: truncate, + strip: String.prototype.trim || strip, + stripTags: stripTags, + stripScripts: stripScripts, + extractScripts: extractScripts, + evalScripts: evalScripts, + escapeHTML: escapeHTML, + unescapeHTML: unescapeHTML, + toQueryParams: toQueryParams, + parseQuery: toQueryParams, + toArray: toArray, + succ: succ, + times: times, + camelize: camelize, + capitalize: capitalize, + underscore: underscore, + dasherize: dasherize, + inspect: inspect, + unfilterJSON: unfilterJSON, + isJSON: isJSON, + evalJSON: NATIVE_JSON_PARSE_SUPPORT ? parseJSON : evalJSON, + include: include, + startsWith: startsWith, + endsWith: endsWith, + empty: empty, + blank: blank, + interpolate: interpolate + }; +})()); + +var Template = Class.create({ + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + if (object && Object.isFunction(object.toTemplateReplacements)) + object = object.toTemplateReplacements(); + + return this.template.gsub(this.pattern, function(match) { + if (object == null) return (match[1] + ''); + + var before = match[1] || ''; + if (before == '\\') return match[2]; + + var ctx = object, expr = match[3], + pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; + + match = pattern.exec(expr); + if (match == null) return before; + + while (match != null) { + var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1]; + ctx = ctx[comp]; + if (null == ctx || '' == match[3]) break; + expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); + match = pattern.exec(expr); + } + + return before + String.interpret(ctx); + }); + } +}); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; + +var $break = { }; + +var Enumerable = (function() { + function each(iterator, context) { + var index = 0; + try { + this._each(function(value) { + iterator.call(context, value, index++); + }); + } catch (e) { + if (e != $break) throw e; + } + return this; + } + + function eachSlice(number, iterator, context) { + var index = -number, slices = [], array = this.toArray(); + if (number < 1) return array; + while ((index += number) < array.length) + slices.push(array.slice(index, index+number)); + return slices.collect(iterator, context); + } + + function all(iterator, context) { + iterator = iterator || Prototype.K; + var result = true; + this.each(function(value, index) { + result = result && !!iterator.call(context, value, index); + if (!result) throw $break; + }); + return result; + } + + function any(iterator, context) { + iterator = iterator || Prototype.K; + var result = false; + this.each(function(value, index) { + if (result = !!iterator.call(context, value, index)) + throw $break; + }); + return result; + } + + function collect(iterator, context) { + iterator = iterator || Prototype.K; + var results = []; + this.each(function(value, index) { + results.push(iterator.call(context, value, index)); + }); + return results; + } + + function detect(iterator, context) { + var result; + this.each(function(value, index) { + if (iterator.call(context, value, index)) { + result = value; + throw $break; + } + }); + return result; + } + + function findAll(iterator, context) { + var results = []; + this.each(function(value, index) { + if (iterator.call(context, value, index)) + results.push(value); + }); + return results; + } + + function grep(filter, iterator, context) { + iterator = iterator || Prototype.K; + var results = []; + + if (Object.isString(filter)) + filter = new RegExp(RegExp.escape(filter)); + + this.each(function(value, index) { + if (filter.match(value)) + results.push(iterator.call(context, value, index)); + }); + return results; + } + + function include(object) { + if (Object.isFunction(this.indexOf)) + if (this.indexOf(object) != -1) return true; + + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + } + + function inGroupsOf(number, fillWith) { + fillWith = Object.isUndefined(fillWith) ? null : fillWith; + return this.eachSlice(number, function(slice) { + while(slice.length < number) slice.push(fillWith); + return slice; + }); + } + + function inject(memo, iterator, context) { + this.each(function(value, index) { + memo = iterator.call(context, memo, value, index); + }); + return memo; + } + + function invoke(method) { + var args = $A(arguments).slice(1); + return this.map(function(value) { + return value[method].apply(value, args); + }); + } + + function max(iterator, context) { + iterator = iterator || Prototype.K; + var result; + this.each(function(value, index) { + value = iterator.call(context, value, index); + if (result == null || value >= result) + result = value; + }); + return result; + } + + function min(iterator, context) { + iterator = iterator || Prototype.K; + var result; + this.each(function(value, index) { + value = iterator.call(context, value, index); + if (result == null || value < result) + result = value; + }); + return result; + } + + function partition(iterator, context) { + iterator = iterator || Prototype.K; + var trues = [], falses = []; + this.each(function(value, index) { + (iterator.call(context, value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + } + + function pluck(property) { + var results = []; + this.each(function(value) { + results.push(value[property]); + }); + return results; + } + + function reject(iterator, context) { + var results = []; + this.each(function(value, index) { + if (!iterator.call(context, value, index)) + results.push(value); + }); + return results; + } + + function sortBy(iterator, context) { + return this.map(function(value, index) { + return { + value: value, + criteria: iterator.call(context, value, index) + }; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + } + + function toArray() { + return this.map(); + } + + function zip() { + var iterator = Prototype.K, args = $A(arguments); + if (Object.isFunction(args.last())) + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + return iterator(collections.pluck(index)); + }); + } + + function size() { + return this.toArray().length; + } + + function inspect() { + return '#'; + } + + + + + + + + + + return { + each: each, + eachSlice: eachSlice, + all: all, + every: all, + any: any, + some: any, + collect: collect, + map: collect, + detect: detect, + findAll: findAll, + select: findAll, + filter: findAll, + grep: grep, + include: include, + member: include, + inGroupsOf: inGroupsOf, + inject: inject, + invoke: invoke, + max: max, + min: min, + partition: partition, + pluck: pluck, + reject: reject, + sortBy: sortBy, + toArray: toArray, + entries: toArray, + zip: zip, + size: size, + inspect: inspect, + find: detect + }; +})(); + +function $A(iterable) { + if (!iterable) return []; + if ('toArray' in Object(iterable)) return iterable.toArray(); + var length = iterable.length || 0, results = new Array(length); + while (length--) results[length] = iterable[length]; + return results; +} + + +function $w(string) { + if (!Object.isString(string)) return []; + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + +Array.from = $A; + + +(function() { + var arrayProto = Array.prototype, + slice = arrayProto.slice, + _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available + + function each(iterator) { + for (var i = 0, length = this.length; i < length; i++) + iterator(this[i]); + } + if (!_each) _each = each; + + function clear() { + this.length = 0; + return this; + } + + function first() { + return this[0]; + } + + function last() { + return this[this.length - 1]; + } + + function compact() { + return this.select(function(value) { + return value != null; + }); + } + + function flatten() { + return this.inject([], function(array, value) { + if (Object.isArray(value)) + return array.concat(value.flatten()); + array.push(value); + return array; + }); + } + + function without() { + var values = slice.call(arguments, 0); + return this.select(function(value) { + return !values.include(value); + }); + } + + function reverse(inline) { + return (inline === false ? this.toArray() : this)._reverse(); + } + + function uniq(sorted) { + return this.inject([], function(array, value, index) { + if (0 == index || (sorted ? array.last() != value : !array.include(value))) + array.push(value); + return array; + }); + } + + function intersect(array) { + return this.uniq().findAll(function(item) { + return array.detect(function(value) { return item === value }); + }); + } + + + function clone() { + return slice.call(this, 0); + } + + function size() { + return this.length; + } + + function inspect() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + } + + function indexOf(item, i) { + i || (i = 0); + var length = this.length; + if (i < 0) i = length + i; + for (; i < length; i++) + if (this[i] === item) return i; + return -1; + } + + function lastIndexOf(item, i) { + i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; + var n = this.slice(0, i).reverse().indexOf(item); + return (n < 0) ? n : i - n - 1; + } + + function concat() { + var array = slice.call(this, 0), item; + for (var i = 0, length = arguments.length; i < length; i++) { + item = arguments[i]; + if (Object.isArray(item) && !('callee' in item)) { + for (var j = 0, arrayLength = item.length; j < arrayLength; j++) + array.push(item[j]); + } else { + array.push(item); + } + } + return array; + } + + Object.extend(arrayProto, Enumerable); + + if (!arrayProto._reverse) + arrayProto._reverse = arrayProto.reverse; + + Object.extend(arrayProto, { + _each: _each, + clear: clear, + first: first, + last: last, + compact: compact, + flatten: flatten, + without: without, + reverse: reverse, + uniq: uniq, + intersect: intersect, + clone: clone, + toArray: clone, + size: size, + inspect: inspect + }); + + var CONCAT_ARGUMENTS_BUGGY = (function() { + return [].concat(arguments)[0][0] !== 1; + })(1,2) + + if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat; + + if (!arrayProto.indexOf) arrayProto.indexOf = indexOf; + if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf; +})(); +function $H(object) { + return new Hash(object); +}; + +var Hash = Class.create(Enumerable, (function() { + function initialize(object) { + this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); + } + + + function _each(iterator) { + for (var key in this._object) { + var value = this._object[key], pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + } + + function set(key, value) { + return this._object[key] = value; + } + + function get(key) { + if (this._object[key] !== Object.prototype[key]) + return this._object[key]; + } + + function unset(key) { + var value = this._object[key]; + delete this._object[key]; + return value; + } + + function toObject() { + return Object.clone(this._object); + } + + + + function keys() { + return this.pluck('key'); + } + + function values() { + return this.pluck('value'); + } + + function index(value) { + var match = this.detect(function(pair) { + return pair.value === value; + }); + return match && match.key; + } + + function merge(object) { + return this.clone().update(object); + } + + function update(object) { + return new Hash(object).inject(this, function(result, pair) { + result.set(pair.key, pair.value); + return result; + }); + } + + function toQueryPair(key, value) { + if (Object.isUndefined(value)) return key; + return key + '=' + encodeURIComponent(String.interpret(value)); + } + + function toQueryString() { + return this.inject([], function(results, pair) { + var key = encodeURIComponent(pair.key), values = pair.value; + + if (values && typeof values == 'object') { + if (Object.isArray(values)) + return results.concat(values.map(toQueryPair.curry(key))); + } else results.push(toQueryPair(key, values)); + return results; + }).join('&'); + } + + function inspect() { + return '#'; + } + + function clone() { + return new Hash(this); + } + + return { + initialize: initialize, + _each: _each, + set: set, + get: get, + unset: unset, + toObject: toObject, + toTemplateReplacements: toObject, + keys: keys, + values: values, + index: index, + merge: merge, + update: update, + toQueryString: toQueryString, + inspect: inspect, + toJSON: toObject, + clone: clone + }; +})()); + +Hash.from = $H; +Object.extend(Number.prototype, (function() { + function toColorPart() { + return this.toPaddedString(2, 16); + } + + function succ() { + return this + 1; + } + + function times(iterator, context) { + $R(0, this, true).each(iterator, context); + return this; + } + + function toPaddedString(length, radix) { + var string = this.toString(radix || 10); + return '0'.times(length - string.length) + string; + } + + function abs() { + return Math.abs(this); + } + + function round() { + return Math.round(this); + } + + function ceil() { + return Math.ceil(this); + } + + function floor() { + return Math.floor(this); + } + + return { + toColorPart: toColorPart, + succ: succ, + times: times, + toPaddedString: toPaddedString, + abs: abs, + round: round, + ceil: ceil, + floor: floor + }; +})()); + +function $R(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var ObjectRange = Class.create(Enumerable, (function() { + function initialize(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + } + + function _each(iterator) { + var value = this.start; + while (this.include(value)) { + iterator(value); + value = value.succ(); + } + } + + function include(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } + + return { + initialize: initialize, + _each: _each, + include: include + }; +})()); + + + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || false; + }, + + activeRequestCount: 0 +}; + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responder) { + if (!this.include(responder)) + this.responders.push(responder); + }, + + unregister: function(responder) { + this.responders = this.responders.without(responder); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (Object.isFunction(responder[callback])) { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) { } + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { Ajax.activeRequestCount++ }, + onComplete: function() { Ajax.activeRequestCount-- } +}); +Ajax.Base = Class.create({ + initialize: function(options) { + this.options = { + method: 'post', + asynchronous: true, + contentType: 'application/x-www-form-urlencoded', + encoding: 'UTF-8', + parameters: '', + evalJSON: true, + evalJS: true + }; + Object.extend(this.options, options || { }); + + this.options.method = this.options.method.toLowerCase(); + + if (Object.isString(this.options.parameters)) + this.options.parameters = this.options.parameters.toQueryParams(); + else if (Object.isHash(this.options.parameters)) + this.options.parameters = this.options.parameters.toObject(); + } +}); +Ajax.Request = Class.create(Ajax.Base, { + _complete: false, + + initialize: function($super, url, options) { + $super(options); + this.transport = Ajax.getTransport(); + this.request(url); + }, + + request: function(url) { + this.url = url; + this.method = this.options.method; + var params = Object.clone(this.options.parameters); + + if (!['get', 'post'].include(this.method)) { + params['_method'] = this.method; + this.method = 'post'; + } + + this.parameters = params; + + if (params = Object.toQueryString(params)) { + if (this.method == 'get') + this.url += (this.url.include('?') ? '&' : '?') + params; + else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + params += '&_='; + } + + try { + var response = new Ajax.Response(this); + if (this.options.onCreate) this.options.onCreate(response); + Ajax.Responders.dispatch('onCreate', this, response); + + this.transport.open(this.method.toUpperCase(), this.url, + this.options.asynchronous); + + if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); + + this.transport.onreadystatechange = this.onStateChange.bind(this); + this.setRequestHeaders(); + + this.body = this.method == 'post' ? (this.options.postBody || params) : null; + this.transport.send(this.body); + + /* Force Firefox to handle ready state 4 for synchronous requests */ + if (!this.options.asynchronous && this.transport.overrideMimeType) + this.onStateChange(); + + } + catch (e) { + this.dispatchException(e); + } + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState > 1 && !((readyState == 4) && this._complete)) + this.respondToReadyState(this.transport.readyState); + }, + + setRequestHeaders: function() { + var headers = { + 'X-Requested-With': 'XMLHttpRequest', + 'X-Prototype-Version': Prototype.Version, + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }; + + if (this.method == 'post') { + headers['Content-type'] = this.options.contentType + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + /* Force "Connection: close" for older Mozilla browsers to work + * around a bug where XMLHttpRequest sends an incorrect + * Content-length header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType && + (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) + headers['Connection'] = 'close'; + } + + if (typeof this.options.requestHeaders == 'object') { + var extras = this.options.requestHeaders; + + if (Object.isFunction(extras.push)) + for (var i = 0, length = extras.length; i < length; i += 2) + headers[extras[i]] = extras[i+1]; + else + $H(extras).each(function(pair) { headers[pair.key] = pair.value }); + } + + for (var name in headers) + this.transport.setRequestHeader(name, headers[name]); + }, + + success: function() { + var status = this.getStatus(); + return !status || (status >= 200 && status < 300); + }, + + getStatus: function() { + try { + return this.transport.status || 0; + } catch (e) { return 0 } + }, + + respondToReadyState: function(readyState) { + var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); + + if (state == 'Complete') { + try { + this._complete = true; + (this.options['on' + response.status] + || this.options['on' + (this.success() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(response, response.headerJSON); + } catch (e) { + this.dispatchException(e); + } + + var contentType = response.getHeader('Content-type'); + if (this.options.evalJS == 'force' + || (this.options.evalJS && this.isSameOrigin() && contentType + && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) + this.evalResponse(); + } + + try { + (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); + Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); + } catch (e) { + this.dispatchException(e); + } + + if (state == 'Complete') { + this.transport.onreadystatechange = Prototype.emptyFunction; + } + }, + + isSameOrigin: function() { + var m = this.url.match(/^\s*https?:\/\/[^\/]*/); + return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({ + protocol: location.protocol, + domain: document.domain, + port: location.port ? ':' + location.port : '' + })); + }, + + getHeader: function(name) { + try { + return this.transport.getResponseHeader(name) || null; + } catch (e) { return null; } + }, + + evalResponse: function() { + try { + return eval((this.transport.responseText || '').unfilterJSON()); + } catch (e) { + this.dispatchException(e); + } + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + + + + + + + + +Ajax.Response = Class.create({ + initialize: function(request){ + this.request = request; + var transport = this.transport = request.transport, + readyState = this.readyState = transport.readyState; + + if ((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { + this.status = this.getStatus(); + this.statusText = this.getStatusText(); + this.responseText = String.interpret(transport.responseText); + this.headerJSON = this._getHeaderJSON(); + } + + if (readyState == 4) { + var xml = transport.responseXML; + this.responseXML = Object.isUndefined(xml) ? null : xml; + this.responseJSON = this._getResponseJSON(); + } + }, + + status: 0, + + statusText: '', + + getStatus: Ajax.Request.prototype.getStatus, + + getStatusText: function() { + try { + return this.transport.statusText || ''; + } catch (e) { return '' } + }, + + getHeader: Ajax.Request.prototype.getHeader, + + getAllHeaders: function() { + try { + return this.getAllResponseHeaders(); + } catch (e) { return null } + }, + + getResponseHeader: function(name) { + return this.transport.getResponseHeader(name); + }, + + getAllResponseHeaders: function() { + return this.transport.getAllResponseHeaders(); + }, + + _getHeaderJSON: function() { + var json = this.getHeader('X-JSON'); + if (!json) return null; + json = decodeURIComponent(escape(json)); + try { + return json.evalJSON(this.request.options.sanitizeJSON || + !this.request.isSameOrigin()); + } catch (e) { + this.request.dispatchException(e); + } + }, + + _getResponseJSON: function() { + var options = this.request.options; + if (!options.evalJSON || (options.evalJSON != 'force' && + !(this.getHeader('Content-type') || '').include('application/json')) || + this.responseText.blank()) + return null; + try { + return this.responseText.evalJSON(options.sanitizeJSON || + !this.request.isSameOrigin()); + } catch (e) { + this.request.dispatchException(e); + } + } +}); + +Ajax.Updater = Class.create(Ajax.Request, { + initialize: function($super, container, url, options) { + this.container = { + success: (container.success || container), + failure: (container.failure || (container.success ? null : container)) + }; + + options = Object.clone(options); + var onComplete = options.onComplete; + options.onComplete = (function(response, json) { + this.updateContent(response.responseText); + if (Object.isFunction(onComplete)) onComplete(response, json); + }).bind(this); + + $super(url, options); + }, + + updateContent: function(responseText) { + var receiver = this.container[this.success() ? 'success' : 'failure'], + options = this.options; + + if (!options.evalScripts) responseText = responseText.stripScripts(); + + if (receiver = $(receiver)) { + if (options.insertion) { + if (Object.isString(options.insertion)) { + var insertion = { }; insertion[options.insertion] = responseText; + receiver.insert(insertion); + } + else options.insertion(receiver, responseText); + } + else receiver.update(responseText); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { + initialize: function($super, container, url, options) { + $super(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = { }; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.options.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(response) { + if (this.options.decay) { + this.decay = (response.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = response.responseText; + } + this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); + + +function $(element) { + if (arguments.length > 1) { + for (var i = 0, elements = [], length = arguments.length; i < length; i++) + elements.push($(arguments[i])); + return elements; + } + if (Object.isString(element)) + element = document.getElementById(element); + return Element.extend(element); +} + +if (Prototype.BrowserFeatures.XPath) { + document._getElementsByXPath = function(expression, parentElement) { + var results = []; + var query = document.evaluate(expression, $(parentElement) || document, + null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + for (var i = 0, length = query.snapshotLength; i < length; i++) + results.push(Element.extend(query.snapshotItem(i))); + return results; + }; +} + +/*--------------------------------------------------------------------------*/ + +if (!Node) var Node = { }; + +if (!Node.ELEMENT_NODE) { + Object.extend(Node, { + ELEMENT_NODE: 1, + ATTRIBUTE_NODE: 2, + TEXT_NODE: 3, + CDATA_SECTION_NODE: 4, + ENTITY_REFERENCE_NODE: 5, + ENTITY_NODE: 6, + PROCESSING_INSTRUCTION_NODE: 7, + COMMENT_NODE: 8, + DOCUMENT_NODE: 9, + DOCUMENT_TYPE_NODE: 10, + DOCUMENT_FRAGMENT_NODE: 11, + NOTATION_NODE: 12 + }); +} + + + +(function(global) { + + var HAS_EXTENDED_CREATE_ELEMENT_SYNTAX = (function(){ + try { + var el = document.createElement(''); + return el.tagName.toLowerCase() === 'input' && el.name === 'x'; + } + catch(err) { + return false; + } + })(); + + var element = global.Element; + + global.Element = function(tagName, attributes) { + attributes = attributes || { }; + tagName = tagName.toLowerCase(); + var cache = Element.cache; + if (HAS_EXTENDED_CREATE_ELEMENT_SYNTAX && attributes.name) { + tagName = '<' + tagName + ' name="' + attributes.name + '">'; + delete attributes.name; + return Element.writeAttribute(document.createElement(tagName), attributes); + } + if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); + return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); + }; + + Object.extend(global.Element, element || { }); + if (element) global.Element.prototype = element.prototype; + +})(this); + +Element.idCounter = 1; +Element.cache = { }; + +function purgeElement(element) { + var uid = element._prototypeUID; + if (uid) { + Element.stopObserving(element); + element._prototypeUID = void 0; + delete Element.Storage[uid]; + } +} + +Element.Methods = { + visible: function(element) { + return $(element).style.display != 'none'; + }, + + toggle: function(element) { + element = $(element); + Element[Element.visible(element) ? 'hide' : 'show'](element); + return element; + }, + + hide: function(element) { + element = $(element); + element.style.display = 'none'; + return element; + }, + + show: function(element) { + element = $(element); + element.style.display = ''; + return element; + }, + + remove: function(element) { + element = $(element); + element.parentNode.removeChild(element); + return element; + }, + + update: (function(){ + + var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){ + var el = document.createElement("select"), + isBuggy = true; + el.innerHTML = ""; + if (el.options && el.options[0]) { + isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION"; + } + el = null; + return isBuggy; + })(); + + var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){ + try { + var el = document.createElement("table"); + if (el && el.tBodies) { + el.innerHTML = "test"; + var isBuggy = typeof el.tBodies[0] == "undefined"; + el = null; + return isBuggy; + } + } catch (e) { + return true; + } + })(); + + var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () { + var s = document.createElement("script"), + isBuggy = false; + try { + s.appendChild(document.createTextNode("")); + isBuggy = !s.firstChild || + s.firstChild && s.firstChild.nodeType !== 3; + } catch (e) { + isBuggy = true; + } + s = null; + return isBuggy; + })(); + + function update(element, content) { + element = $(element); + + var descendants = element.getElementsByTagName('*'), + i = descendants.length; + while (i--) purgeElement(descendants[i]); + + if (content && content.toElement) + content = content.toElement(); + + if (Object.isElement(content)) + return element.update().insert(content); + + content = Object.toHTML(content); + + var tagName = element.tagName.toUpperCase(); + + if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) { + element.text = content; + return element; + } + + if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY) { + if (tagName in Element._insertionTranslations.tags) { + while (element.firstChild) { + element.removeChild(element.firstChild); + } + Element._getContentFromAnonymousElement(tagName, content.stripScripts()) + .each(function(node) { + element.appendChild(node) + }); + } + else { + element.innerHTML = content.stripScripts(); + } + } + else { + element.innerHTML = content.stripScripts(); + } + + content.evalScripts.bind(content).defer(); + return element; + } + + return update; + })(), + + replace: function(element, content) { + element = $(element); + if (content && content.toElement) content = content.toElement(); + else if (!Object.isElement(content)) { + content = Object.toHTML(content); + var range = element.ownerDocument.createRange(); + range.selectNode(element); + content.evalScripts.bind(content).defer(); + content = range.createContextualFragment(content.stripScripts()); + } + element.parentNode.replaceChild(content, element); + return element; + }, + + insert: function(element, insertions) { + element = $(element); + + if (Object.isString(insertions) || Object.isNumber(insertions) || + Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) + insertions = {bottom:insertions}; + + var content, insert, tagName, childNodes; + + for (var position in insertions) { + content = insertions[position]; + position = position.toLowerCase(); + insert = Element._insertionTranslations[position]; + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) { + insert(element, content); + continue; + } + + content = Object.toHTML(content); + + tagName = ((position == 'before' || position == 'after') + ? element.parentNode : element).tagName.toUpperCase(); + + childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); + + if (position == 'top' || position == 'after') childNodes.reverse(); + childNodes.each(insert.curry(element)); + + content.evalScripts.bind(content).defer(); + } + + return element; + }, + + wrap: function(element, wrapper, attributes) { + element = $(element); + if (Object.isElement(wrapper)) + $(wrapper).writeAttribute(attributes || { }); + else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); + else wrapper = new Element('div', wrapper); + if (element.parentNode) + element.parentNode.replaceChild(wrapper, element); + wrapper.appendChild(element); + return wrapper; + }, + + inspect: function(element) { + element = $(element); + var result = '<' + element.tagName.toLowerCase(); + $H({'id': 'id', 'className': 'class'}).each(function(pair) { + var property = pair.first(), + attribute = pair.last(), + value = (element[property] || '').toString(); + if (value) result += ' ' + attribute + '=' + value.inspect(true); + }); + return result + '>'; + }, + + recursivelyCollect: function(element, property, maximumLength) { + element = $(element); + maximumLength = maximumLength || -1; + var elements = []; + + while (element = element[property]) { + if (element.nodeType == 1) + elements.push(Element.extend(element)); + if (elements.length == maximumLength) + break; + } + + return elements; + }, + + ancestors: function(element) { + return Element.recursivelyCollect(element, 'parentNode'); + }, + + descendants: function(element) { + return Element.select(element, "*"); + }, + + firstDescendant: function(element) { + element = $(element).firstChild; + while (element && element.nodeType != 1) element = element.nextSibling; + return $(element); + }, + + immediateDescendants: function(element) { + var results = [], child = $(element).firstChild; + while (child) { + if (child.nodeType === 1) { + results.push(Element.extend(child)); + } + child = child.nextSibling; + } + return results; + }, + + previousSiblings: function(element, maximumLength) { + return Element.recursivelyCollect(element, 'previousSibling'); + }, + + nextSiblings: function(element) { + return Element.recursivelyCollect(element, 'nextSibling'); + }, + + siblings: function(element) { + element = $(element); + return Element.previousSiblings(element).reverse() + .concat(Element.nextSiblings(element)); + }, + + match: function(element, selector) { + element = $(element); + if (Object.isString(selector)) + return Prototype.Selector.match(element, selector); + return selector.match(element); + }, + + up: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(element.parentNode); + var ancestors = Element.ancestors(element); + return Object.isNumber(expression) ? ancestors[expression] : + Prototype.Selector.find(ancestors, expression, index); + }, + + down: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return Element.firstDescendant(element); + return Object.isNumber(expression) ? Element.descendants(element)[expression] : + Element.select(element, expression)[index || 0]; + }, + + previous: function(element, expression, index) { + element = $(element); + if (Object.isNumber(expression)) index = expression, expression = false; + if (!Object.isNumber(index)) index = 0; + + if (expression) { + return Prototype.Selector.find(element.previousSiblings(), expression, index); + } else { + return element.recursivelyCollect("previousSibling", index + 1)[index]; + } + }, + + next: function(element, expression, index) { + element = $(element); + if (Object.isNumber(expression)) index = expression, expression = false; + if (!Object.isNumber(index)) index = 0; + + if (expression) { + return Prototype.Selector.find(element.nextSiblings(), expression, index); + } else { + var maximumLength = Object.isNumber(index) ? index + 1 : 1; + return element.recursivelyCollect("nextSibling", index + 1)[index]; + } + }, + + + select: function(element) { + element = $(element); + var expressions = Array.prototype.slice.call(arguments, 1).join(', '); + return Prototype.Selector.select(expressions, element); + }, + + adjacent: function(element) { + element = $(element); + var expressions = Array.prototype.slice.call(arguments, 1).join(', '); + return Prototype.Selector.select(expressions, element.parentNode).without(element); + }, + + identify: function(element) { + element = $(element); + var id = Element.readAttribute(element, 'id'); + if (id) return id; + do { id = 'anonymous_element_' + Element.idCounter++ } while ($(id)); + Element.writeAttribute(element, 'id', id); + return id; + }, + + readAttribute: function(element, name) { + element = $(element); + if (Prototype.Browser.IE) { + var t = Element._attributeTranslations.read; + if (t.values[name]) return t.values[name](element, name); + if (t.names[name]) name = t.names[name]; + if (name.include(':')) { + return (!element.attributes || !element.attributes[name]) ? null : + element.attributes[name].value; + } + } + return element.getAttribute(name); + }, + + writeAttribute: function(element, name, value) { + element = $(element); + var attributes = { }, t = Element._attributeTranslations.write; + + if (typeof name == 'object') attributes = name; + else attributes[name] = Object.isUndefined(value) ? true : value; + + for (var attr in attributes) { + name = t.names[attr] || attr; + value = attributes[attr]; + if (t.values[attr]) name = t.values[attr](element, value); + if (value === false || value === null) + element.removeAttribute(name); + else if (value === true) + element.setAttribute(name, name); + else element.setAttribute(name, value); + } + return element; + }, + + getHeight: function(element) { + return Element.getDimensions(element).height; + }, + + getWidth: function(element) { + return Element.getDimensions(element).width; + }, + + classNames: function(element) { + return new Element.ClassNames(element); + }, + + hasClassName: function(element, className) { + if (!(element = $(element))) return; + var elementClassName = element.className; + return (elementClassName.length > 0 && (elementClassName == className || + new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName))); + }, + + addClassName: function(element, className) { + if (!(element = $(element))) return; + if (!Element.hasClassName(element, className)) + element.className += (element.className ? ' ' : '') + className; + return element; + }, + + removeClassName: function(element, className) { + if (!(element = $(element))) return; + element.className = element.className.replace( + new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip(); + return element; + }, + + toggleClassName: function(element, className) { + if (!(element = $(element))) return; + return Element[Element.hasClassName(element, className) ? + 'removeClassName' : 'addClassName'](element, className); + }, + + cleanWhitespace: function(element) { + element = $(element); + var node = element.firstChild; + while (node) { + var nextNode = node.nextSibling; + if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) + element.removeChild(node); + node = nextNode; + } + return element; + }, + + empty: function(element) { + return $(element).innerHTML.blank(); + }, + + descendantOf: function(element, ancestor) { + element = $(element), ancestor = $(ancestor); + + if (element.compareDocumentPosition) + return (element.compareDocumentPosition(ancestor) & 8) === 8; + + if (ancestor.contains) + return ancestor.contains(element) && ancestor !== element; + + while (element = element.parentNode) + if (element == ancestor) return true; + + return false; + }, + + scrollTo: function(element) { + element = $(element); + var pos = Element.cumulativeOffset(element); + window.scrollTo(pos[0], pos[1]); + return element; + }, + + getStyle: function(element, style) { + element = $(element); + style = style == 'float' ? 'cssFloat' : style.camelize(); + var value = element.style[style]; + if (!value || value == 'auto') { + var css = document.defaultView.getComputedStyle(element, null); + value = css ? css[style] : null; + } + if (style == 'opacity') return value ? parseFloat(value) : 1.0; + return value == 'auto' ? null : value; + }, + + getOpacity: function(element) { + return $(element).getStyle('opacity'); + }, + + setStyle: function(element, styles) { + element = $(element); + var elementStyle = element.style, match; + if (Object.isString(styles)) { + element.style.cssText += ';' + styles; + return styles.include('opacity') ? + element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; + } + for (var property in styles) + if (property == 'opacity') element.setOpacity(styles[property]); + else + elementStyle[(property == 'float' || property == 'cssFloat') ? + (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') : + property] = styles[property]; + + return element; + }, + + setOpacity: function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + return element; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + element._madePositioned = true; + element.style.position = 'relative'; + if (Prototype.Browser.Opera) { + element.style.top = 0; + element.style.left = 0; + } + } + return element; + }, + + undoPositioned: function(element) { + element = $(element); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + return element; + }, + + makeClipping: function(element) { + element = $(element); + if (element._overflow) return element; + element._overflow = Element.getStyle(element, 'overflow') || 'auto'; + if (element._overflow !== 'hidden') + element.style.overflow = 'hidden'; + return element; + }, + + undoClipping: function(element) { + element = $(element); + if (!element._overflow) return element; + element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; + element._overflow = null; + return element; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + if (element.parentNode) { + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + } + return Element._returnOffset(valueL, valueT); + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + if (element.tagName.toUpperCase() == 'BODY') break; + var p = Element.getStyle(element, 'position'); + if (p !== 'static') break; + } + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + absolutize: function(element) { + element = $(element); + if (Element.getStyle(element, 'position') == 'absolute') return element; + + var offsets = Element.positionedOffset(element), + top = offsets[1], + left = offsets[0], + width = element.clientWidth, + height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + return element; + }, + + relativize: function(element) { + element = $(element); + if (Element.getStyle(element, 'position') == 'relative') return element; + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0), + left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + return element; + }, + + cumulativeScrollOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + getOffsetParent: function(element) { + if (element.offsetParent) return $(element.offsetParent); + if (element == document.body) return $(element); + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return $(element); + + return $(document.body); + }, + + viewportOffset: function(forElement) { + var valueT = 0, + valueL = 0, + element = forElement; + + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + if (element.offsetParent == document.body && + Element.getStyle(element, 'position') == 'absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + + return Element._returnOffset(valueL, valueT); + }, + + clonePosition: function(element, source) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || { }); + + source = $(source); + var p = Element.viewportOffset(source), delta = [0, 0], parent = null; + + element = $(element); + + if (Element.getStyle(element, 'position') == 'absolute') { + parent = Element.getOffsetParent(element); + delta = Element.viewportOffset(parent); + } + + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if (options.setWidth) element.style.width = source.offsetWidth + 'px'; + if (options.setHeight) element.style.height = source.offsetHeight + 'px'; + return element; + } +}; + +Object.extend(Element.Methods, { + getElementsBySelector: Element.Methods.select, + + childElements: Element.Methods.immediateDescendants +}); + +Element._attributeTranslations = { + write: { + names: { + className: 'class', + htmlFor: 'for' + }, + values: { } + } +}; + +if (Prototype.Browser.Opera) { + Element.Methods.getStyle = Element.Methods.getStyle.wrap( + function(proceed, element, style) { + switch (style) { + case 'left': case 'top': case 'right': case 'bottom': + if (proceed(element, 'position') === 'static') return null; + case 'height': case 'width': + if (!Element.visible(element)) return null; + + var dim = parseInt(proceed(element, style), 10); + + if (dim !== element['offset' + style.capitalize()]) + return dim + 'px'; + + var properties; + if (style === 'height') { + properties = ['border-top-width', 'padding-top', + 'padding-bottom', 'border-bottom-width']; + } + else { + properties = ['border-left-width', 'padding-left', + 'padding-right', 'border-right-width']; + } + return properties.inject(dim, function(memo, property) { + var val = proceed(element, property); + return val === null ? memo : memo - parseInt(val, 10); + }) + 'px'; + default: return proceed(element, style); + } + } + ); + + Element.Methods.readAttribute = Element.Methods.readAttribute.wrap( + function(proceed, element, attribute) { + if (attribute === 'title') return element.title; + return proceed(element, attribute); + } + ); +} + +else if (Prototype.Browser.IE) { + Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap( + function(proceed, element) { + element = $(element); + if (!element.parentNode) return $(document.body); + var position = element.getStyle('position'); + if (position !== 'static') return proceed(element); + element.setStyle({ position: 'relative' }); + var value = proceed(element); + element.setStyle({ position: position }); + return value; + } + ); + + $w('positionedOffset viewportOffset').each(function(method) { + Element.Methods[method] = Element.Methods[method].wrap( + function(proceed, element) { + element = $(element); + if (!element.parentNode) return Element._returnOffset(0, 0); + var position = element.getStyle('position'); + if (position !== 'static') return proceed(element); + var offsetParent = element.getOffsetParent(); + if (offsetParent && offsetParent.getStyle('position') === 'fixed') + offsetParent.setStyle({ zoom: 1 }); + element.setStyle({ position: 'relative' }); + var value = proceed(element); + element.setStyle({ position: position }); + return value; + } + ); + }); + + Element.Methods.getStyle = function(element, style) { + element = $(element); + style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); + var value = element.style[style]; + if (!value && element.currentStyle) value = element.currentStyle[style]; + + if (style == 'opacity') { + if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) + if (value[1]) return parseFloat(value[1]) / 100; + return 1.0; + } + + if (value == 'auto') { + if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) + return element['offset' + style.capitalize()] + 'px'; + return null; + } + return value; + }; + + Element.Methods.setOpacity = function(element, value) { + function stripAlpha(filter){ + return filter.replace(/alpha\([^\)]*\)/gi,''); + } + element = $(element); + var currentStyle = element.currentStyle; + if ((currentStyle && !currentStyle.hasLayout) || + (!currentStyle && element.style.zoom == 'normal')) + element.style.zoom = 1; + + var filter = element.getStyle('filter'), style = element.style; + if (value == 1 || value === '') { + (filter = stripAlpha(filter)) ? + style.filter = filter : style.removeAttribute('filter'); + return element; + } else if (value < 0.00001) value = 0; + style.filter = stripAlpha(filter) + + 'alpha(opacity=' + (value * 100) + ')'; + return element; + }; + + Element._attributeTranslations = (function(){ + + var classProp = 'className', + forProp = 'for', + el = document.createElement('div'); + + el.setAttribute(classProp, 'x'); + + if (el.className !== 'x') { + el.setAttribute('class', 'x'); + if (el.className === 'x') { + classProp = 'class'; + } + } + el = null; + + el = document.createElement('label'); + el.setAttribute(forProp, 'x'); + if (el.htmlFor !== 'x') { + el.setAttribute('htmlFor', 'x'); + if (el.htmlFor === 'x') { + forProp = 'htmlFor'; + } + } + el = null; + + return { + read: { + names: { + 'class': classProp, + 'className': classProp, + 'for': forProp, + 'htmlFor': forProp + }, + values: { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute); + }, + _getAttr2: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + _getAttrNode: function(element, attribute) { + var node = element.getAttributeNode(attribute); + return node ? node.value : ""; + }, + _getEv: (function(){ + + var el = document.createElement('div'), f; + el.onclick = Prototype.emptyFunction; + var value = el.getAttribute('onclick'); + + if (String(value).indexOf('{') > -1) { + f = function(element, attribute) { + attribute = element.getAttribute(attribute); + if (!attribute) return null; + attribute = attribute.toString(); + attribute = attribute.split('{')[1]; + attribute = attribute.split('}')[0]; + return attribute.strip(); + }; + } + else if (value === '') { + f = function(element, attribute) { + attribute = element.getAttribute(attribute); + if (!attribute) return null; + return attribute.strip(); + }; + } + el = null; + return f; + })(), + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + title: function(element) { + return element.title; + } + } + } + } + })(); + + Element._attributeTranslations.write = { + names: Object.extend({ + cellpadding: 'cellPadding', + cellspacing: 'cellSpacing' + }, Element._attributeTranslations.read.names), + values: { + checked: function(element, value) { + element.checked = !!value; + }, + + style: function(element, value) { + element.style.cssText = value ? value : ''; + } + } + }; + + Element._attributeTranslations.has = {}; + + $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + + 'encType maxLength readOnly longDesc frameBorder').each(function(attr) { + Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; + Element._attributeTranslations.has[attr.toLowerCase()] = attr; + }); + + (function(v) { + Object.extend(v, { + href: v._getAttr2, + src: v._getAttr2, + type: v._getAttr, + action: v._getAttrNode, + disabled: v._flag, + checked: v._flag, + readonly: v._flag, + multiple: v._flag, + onload: v._getEv, + onunload: v._getEv, + onclick: v._getEv, + ondblclick: v._getEv, + onmousedown: v._getEv, + onmouseup: v._getEv, + onmouseover: v._getEv, + onmousemove: v._getEv, + onmouseout: v._getEv, + onfocus: v._getEv, + onblur: v._getEv, + onkeypress: v._getEv, + onkeydown: v._getEv, + onkeyup: v._getEv, + onsubmit: v._getEv, + onreset: v._getEv, + onselect: v._getEv, + onchange: v._getEv + }); + })(Element._attributeTranslations.read.values); + + if (Prototype.BrowserFeatures.ElementExtensions) { + (function() { + function _descendants(element) { + var nodes = element.getElementsByTagName('*'), results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName !== "!") // Filter out comment nodes. + results.push(node); + return results; + } + + Element.Methods.down = function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return element.firstDescendant(); + return Object.isNumber(expression) ? _descendants(element)[expression] : + Element.select(element, expression)[index || 0]; + } + })(); + } + +} + +else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1) ? 0.999999 : + (value === '') ? '' : (value < 0.00001) ? 0 : value; + return element; + }; +} + +else if (Prototype.Browser.WebKit) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + + if (value == 1) + if (element.tagName.toUpperCase() == 'IMG' && element.width) { + element.width++; element.width--; + } else try { + var n = document.createTextNode(' '); + element.appendChild(n); + element.removeChild(n); + } catch (e) { } + + return element; + }; + + Element.Methods.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return Element._returnOffset(valueL, valueT); + }; +} + +if ('outerHTML' in document.documentElement) { + Element.Methods.replace = function(element, content) { + element = $(element); + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) { + element.parentNode.replaceChild(content, element); + return element; + } + + content = Object.toHTML(content); + var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); + + if (Element._insertionTranslations.tags[tagName]) { + var nextSibling = element.next(), + fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); + parent.removeChild(element); + if (nextSibling) + fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); + else + fragments.each(function(node) { parent.appendChild(node) }); + } + else element.outerHTML = content.stripScripts(); + + content.evalScripts.bind(content).defer(); + return element; + }; +} + +Element._returnOffset = function(l, t) { + var result = [l, t]; + result.left = l; + result.top = t; + return result; +}; + +Element._getContentFromAnonymousElement = function(tagName, html) { + var div = new Element('div'), + t = Element._insertionTranslations.tags[tagName]; + if (t) { + div.innerHTML = t[0] + html + t[1]; + for (var i = t[2]; i--; ) { + div = div.firstChild; + } + } + else { + div.innerHTML = html; + } + return $A(div.childNodes); +}; + +Element._insertionTranslations = { + before: function(element, node) { + element.parentNode.insertBefore(node, element); + }, + top: function(element, node) { + element.insertBefore(node, element.firstChild); + }, + bottom: function(element, node) { + element.appendChild(node); + }, + after: function(element, node) { + element.parentNode.insertBefore(node, element.nextSibling); + }, + tags: { + TABLE: ['', '
                ', 1], + TBODY: ['', '
                ', 2], + TR: ['', '
                ', 3], + TD: ['
                ', '
                ', 4], + SELECT: ['', 1] + } +}; + +(function() { + var tags = Element._insertionTranslations.tags; + Object.extend(tags, { + THEAD: tags.TBODY, + TFOOT: tags.TBODY, + TH: tags.TD + }); +})(); + +Element.Methods.Simulated = { + hasAttribute: function(element, attribute) { + attribute = Element._attributeTranslations.has[attribute] || attribute; + var node = $(element).getAttributeNode(attribute); + return !!(node && node.specified); + } +}; + +Element.Methods.ByTag = { }; + +Object.extend(Element, Element.Methods); + +(function(div) { + + if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) { + window.HTMLElement = { }; + window.HTMLElement.prototype = div['__proto__']; + Prototype.BrowserFeatures.ElementExtensions = true; + } + + div = null; + +})(document.createElement('div')); + +Element.extend = (function() { + + function checkDeficiency(tagName) { + if (typeof window.Element != 'undefined') { + var proto = window.Element.prototype; + if (proto) { + var id = '_' + (Math.random()+'').slice(2), + el = document.createElement(tagName); + proto[id] = 'x'; + var isBuggy = (el[id] !== 'x'); + delete proto[id]; + el = null; + return isBuggy; + } + } + return false; + } + + function extendElementWith(element, methods) { + for (var property in methods) { + var value = methods[property]; + if (Object.isFunction(value) && !(property in element)) + element[property] = value.methodize(); + } + } + + var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object'); + + if (Prototype.BrowserFeatures.SpecificElementExtensions) { + if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) { + return function(element) { + if (element && typeof element._extendedByPrototype == 'undefined') { + var t = element.tagName; + if (t && (/^(?:object|applet|embed)$/i.test(t))) { + extendElementWith(element, Element.Methods); + extendElementWith(element, Element.Methods.Simulated); + extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]); + } + } + return element; + } + } + return Prototype.K; + } + + var Methods = { }, ByTag = Element.Methods.ByTag; + + var extend = Object.extend(function(element) { + if (!element || typeof element._extendedByPrototype != 'undefined' || + element.nodeType != 1 || element == window) return element; + + var methods = Object.clone(Methods), + tagName = element.tagName.toUpperCase(); + + if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); + + extendElementWith(element, methods); + + element._extendedByPrototype = Prototype.emptyFunction; + return element; + + }, { + refresh: function() { + if (!Prototype.BrowserFeatures.ElementExtensions) { + Object.extend(Methods, Element.Methods); + Object.extend(Methods, Element.Methods.Simulated); + } + } + }); + + extend.refresh(); + return extend; +})(); + +if (document.documentElement.hasAttribute) { + Element.hasAttribute = function(element, attribute) { + return element.hasAttribute(attribute); + }; +} +else { + Element.hasAttribute = Element.Methods.Simulated.hasAttribute; +} + +Element.addMethods = function(methods) { + var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; + + if (!methods) { + Object.extend(Form, Form.Methods); + Object.extend(Form.Element, Form.Element.Methods); + Object.extend(Element.Methods.ByTag, { + "FORM": Object.clone(Form.Methods), + "INPUT": Object.clone(Form.Element.Methods), + "SELECT": Object.clone(Form.Element.Methods), + "TEXTAREA": Object.clone(Form.Element.Methods) + }); + } + + if (arguments.length == 2) { + var tagName = methods; + methods = arguments[1]; + } + + if (!tagName) Object.extend(Element.Methods, methods || { }); + else { + if (Object.isArray(tagName)) tagName.each(extend); + else extend(tagName); + } + + function extend(tagName) { + tagName = tagName.toUpperCase(); + if (!Element.Methods.ByTag[tagName]) + Element.Methods.ByTag[tagName] = { }; + Object.extend(Element.Methods.ByTag[tagName], methods); + } + + function copy(methods, destination, onlyIfAbsent) { + onlyIfAbsent = onlyIfAbsent || false; + for (var property in methods) { + var value = methods[property]; + if (!Object.isFunction(value)) continue; + if (!onlyIfAbsent || !(property in destination)) + destination[property] = value.methodize(); + } + } + + function findDOMClass(tagName) { + var klass; + var trans = { + "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", + "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", + "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", + "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", + "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": + "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": + "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": + "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": + "FrameSet", "IFRAME": "IFrame" + }; + if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName.capitalize() + 'Element'; + if (window[klass]) return window[klass]; + + var element = document.createElement(tagName), + proto = element['__proto__'] || element.constructor.prototype; + + element = null; + return proto; + } + + var elementPrototype = window.HTMLElement ? HTMLElement.prototype : + Element.prototype; + + if (F.ElementExtensions) { + copy(Element.Methods, elementPrototype); + copy(Element.Methods.Simulated, elementPrototype, true); + } + + if (F.SpecificElementExtensions) { + for (var tag in Element.Methods.ByTag) { + var klass = findDOMClass(tag); + if (Object.isUndefined(klass)) continue; + copy(T[tag], klass.prototype); + } + } + + Object.extend(Element, Element.Methods); + delete Element.ByTag; + + if (Element.extend.refresh) Element.extend.refresh(); + Element.cache = { }; +}; + + +document.viewport = { + + getDimensions: function() { + return { width: this.getWidth(), height: this.getHeight() }; + }, + + getScrollOffsets: function() { + return Element._returnOffset( + window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, + window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); + } +}; + +(function(viewport) { + var B = Prototype.Browser, doc = document, element, property = {}; + + function getRootElement() { + if (B.WebKit && !doc.evaluate) + return document; + + if (B.Opera && window.parseFloat(window.opera.version()) < 9.5) + return document.body; + + return document.documentElement; + } + + function define(D) { + if (!element) element = getRootElement(); + + property[D] = 'client' + D; + + viewport['get' + D] = function() { return element[property[D]] }; + return viewport['get' + D](); + } + + viewport.getWidth = define.curry('Width'); + + viewport.getHeight = define.curry('Height'); +})(document.viewport); + + +Element.Storage = { + UID: 1 +}; + +Element.addMethods({ + getStorage: function(element) { + if (!(element = $(element))) return; + + var uid; + if (element === window) { + uid = 0; + } else { + if (typeof element._prototypeUID === "undefined") + element._prototypeUID = Element.Storage.UID++; + uid = element._prototypeUID; + } + + if (!Element.Storage[uid]) + Element.Storage[uid] = $H(); + + return Element.Storage[uid]; + }, + + store: function(element, key, value) { + if (!(element = $(element))) return; + + if (arguments.length === 2) { + Element.getStorage(element).update(key); + } else { + Element.getStorage(element).set(key, value); + } + + return element; + }, + + retrieve: function(element, key, defaultValue) { + if (!(element = $(element))) return; + var hash = Element.getStorage(element), value = hash.get(key); + + if (Object.isUndefined(value)) { + hash.set(key, defaultValue); + value = defaultValue; + } + + return value; + }, + + clone: function(element, deep) { + if (!(element = $(element))) return; + var clone = element.cloneNode(deep); + clone._prototypeUID = void 0; + if (deep) { + var descendants = Element.select(clone, '*'), + i = descendants.length; + while (i--) { + descendants[i]._prototypeUID = void 0; + } + } + return Element.extend(clone); + }, + + purge: function(element) { + if (!(element = $(element))) return; + purgeElement(element); + + var descendants = element.getElementsByTagName('*'), + i = descendants.length; + + while (i--) purgeElement(descendants[i]); + + return null; + } +}); + +(function() { + + function toDecimal(pctString) { + var match = pctString.match(/^(\d+)%?$/i); + if (!match) return null; + return (Number(match[1]) / 100); + } + + function getPixelValue(value, property) { + if (Object.isElement(value)) { + element = value; + value = element.getStyle(property); + } + if (value === null) { + return null; + } + + if ((/^(?:-)?\d+(\.\d+)?(px)?$/i).test(value)) { + return window.parseFloat(value); + } + + if (/\d/.test(value) && element.runtimeStyle) { + var style = element.style.left, rStyle = element.runtimeStyle.left; + element.runtimeStyle.left = element.currentStyle.left; + element.style.left = value || 0; + value = element.style.pixelLeft; + element.style.left = style; + element.runtimeStyle.left = rStyle; + + return value; + } + + if (value.include('%')) { + var decimal = toDecimal(value); + var whole; + if (property.include('left') || property.include('right') || + property.include('width')) { + whole = $(element.parentNode).measure('width'); + } else if (property.include('top') || property.include('bottom') || + property.include('height')) { + whole = $(element.parentNode).measure('height'); + } + + return whole * decimal; + } + + return 0; + } + + function toCSSPixels(number) { + if (Object.isString(number) && number.endsWith('px')) { + return number; + } + return number + 'px'; + } + + function isDisplayed(element) { + var originalElement = element; + while (element && element.parentNode) { + var display = element.getStyle('display'); + if (display === 'none') { + return false; + } + element = $(element.parentNode); + } + return true; + } + + var hasLayout = Prototype.K; + if ('currentStyle' in document.documentElement) { + hasLayout = function(element) { + if (!element.currentStyle.hasLayout) { + element.style.zoom = 1; + } + return element; + }; + } + + function cssNameFor(key) { + if (key.include('border')) key = key + '-width'; + return key.camelize(); + } + + Element.Layout = Class.create(Hash, { + initialize: function($super, element, preCompute) { + $super(); + this.element = $(element); + + Element.Layout.PROPERTIES.each( function(property) { + this._set(property, null); + }, this); + + if (preCompute) { + this._preComputing = true; + this._begin(); + Element.Layout.PROPERTIES.each( this._compute, this ); + this._end(); + this._preComputing = false; + } + }, + + _set: function(property, value) { + return Hash.prototype.set.call(this, property, value); + }, + + set: function(property, value) { + throw "Properties of Element.Layout are read-only."; + }, + + get: function($super, property) { + var value = $super(property); + return value === null ? this._compute(property) : value; + }, + + _begin: function() { + if (this._prepared) return; + + var element = this.element; + if (isDisplayed(element)) { + this._prepared = true; + return; + } + + var originalStyles = { + position: element.style.position || '', + width: element.style.width || '', + visibility: element.style.visibility || '', + display: element.style.display || '' + }; + + element.store('prototype_original_styles', originalStyles); + + var position = element.getStyle('position'), + width = element.getStyle('width'); + + element.setStyle({ + position: 'absolute', + visibility: 'hidden', + display: 'block' + }); + + var positionedWidth = element.getStyle('width'); + + var newWidth; + if (width && (positionedWidth === width)) { + newWidth = getPixelValue(width); + } else if (width && (position === 'absolute' || position === 'fixed')) { + newWidth = getPixelValue(width); + } else { + var parent = element.parentNode, pLayout = $(parent).getLayout(); + + newWidth = pLayout.get('width') - + this.get('margin-left') - + this.get('border-left') - + this.get('padding-left') - + this.get('padding-right') - + this.get('border-right') - + this.get('margin-right'); + } + + element.setStyle({ width: newWidth + 'px' }); + + this._prepared = true; + }, + + _end: function() { + var element = this.element; + var originalStyles = element.retrieve('prototype_original_styles'); + element.store('prototype_original_styles', null); + element.setStyle(originalStyles); + this._prepared = false; + }, + + _compute: function(property) { + var COMPUTATIONS = Element.Layout.COMPUTATIONS; + if (!(property in COMPUTATIONS)) { + throw "Property not found."; + } + return this._set(property, COMPUTATIONS[property].call(this, this.element)); + }, + + toObject: function() { + var args = $A(arguments); + var keys = (args.length === 0) ? Element.Layout.PROPERTIES : + args.join(' ').split(' '); + var obj = {}; + keys.each( function(key) { + if (!Element.Layout.PROPERTIES.include(key)) return; + var value = this.get(key); + if (value != null) obj[key] = value; + }, this); + return obj; + }, + + toHash: function() { + var obj = this.toObject.apply(this, arguments); + return new Hash(obj); + }, + + toCSS: function() { + var args = $A(arguments); + var keys = (args.length === 0) ? Element.Layout.PROPERTIES : + args.join(' ').split(' '); + var css = {}; + + keys.each( function(key) { + if (!Element.Layout.PROPERTIES.include(key)) return; + if (Element.Layout.COMPOSITE_PROPERTIES.include(key)) return; + + var value = this.get(key); + if (value != null) css[cssNameFor(key)] = value + 'px'; + }, this); + return css; + }, + + inspect: function() { + return "#"; + } + }); + + Object.extend(Element.Layout, { + PROPERTIES: $w('height width top left right bottom border-left border-right border-top border-bottom padding-left padding-right padding-top padding-bottom margin-top margin-bottom margin-left margin-right padding-box-width padding-box-height border-box-width border-box-height margin-box-width margin-box-height'), + + COMPOSITE_PROPERTIES: $w('padding-box-width padding-box-height margin-box-width margin-box-height border-box-width border-box-height'), + + COMPUTATIONS: { + 'height': function(element) { + if (!this._preComputing) this._begin(); + + var bHeight = this.get('border-box-height'); + if (bHeight <= 0) return 0; + + var bTop = this.get('border-top'), + bBottom = this.get('border-bottom'); + + var pTop = this.get('padding-top'), + pBottom = this.get('padding-bottom'); + + if (!this._preComputing) this._end(); + + return bHeight - bTop - bBottom - pTop - pBottom; + }, + + 'width': function(element) { + if (!this._preComputing) this._begin(); + + var bWidth = this.get('border-box-width'); + if (bWidth <= 0) return 0; + + var bLeft = this.get('border-left'), + bRight = this.get('border-right'); + + var pLeft = this.get('padding-left'), + pRight = this.get('padding-right'); + + if (!this._preComputing) this._end(); + + return bWidth - bLeft - bRight - pLeft - pRight; + }, + + 'padding-box-height': function(element) { + var height = this.get('height'), + pTop = this.get('padding-top'), + pBottom = this.get('padding-bottom'); + + return height + pTop + pBottom; + }, + + 'padding-box-width': function(element) { + var width = this.get('width'), + pLeft = this.get('padding-left'), + pRight = this.get('padding-right'); + + return width + pLeft + pRight; + }, + + 'border-box-height': function(element) { + return element.offsetHeight; + }, + + 'border-box-width': function(element) { + return element.offsetWidth; + }, + + 'margin-box-height': function(element) { + var bHeight = this.get('border-box-height'), + mTop = this.get('margin-top'), + mBottom = this.get('margin-bottom'); + + if (bHeight <= 0) return 0; + + return bHeight + mTop + mBottom; + }, + + 'margin-box-width': function(element) { + var bWidth = this.get('border-box-width'), + mLeft = this.get('margin-left'), + mRight = this.get('margin-right'); + + if (bWidth <= 0) return 0; + + return bWidth + mLeft + mRight; + }, + + 'top': function(element) { + var offset = element.positionedOffset(); + return offset.top; + }, + + 'bottom': function(element) { + var offset = element.positionedOffset(), + parent = element.getOffsetParent(), + pHeight = parent.measure('height'); + + var mHeight = this.get('border-box-height'); + + return pHeight - mHeight - offset.top; + }, + + 'left': function(element) { + var offset = element.positionedOffset(); + return offset.left; + }, + + 'right': function(element) { + var offset = element.positionedOffset(), + parent = element.getOffsetParent(), + pWidth = parent.measure('width'); + + var mWidth = this.get('border-box-width'); + + return pWidth - mWidth - offset.left; + }, + + 'padding-top': function(element) { + return getPixelValue(element, 'paddingTop'); + }, + + 'padding-bottom': function(element) { + return getPixelValue(element, 'paddingBottom'); + }, + + 'padding-left': function(element) { + return getPixelValue(element, 'paddingLeft'); + }, + + 'padding-right': function(element) { + return getPixelValue(element, 'paddingRight'); + }, + + 'border-top': function(element) { + return Object.isNumber(element.clientTop) ? element.clientTop : + getPixelValue(element, 'borderTopWidth'); + }, + + 'border-bottom': function(element) { + return Object.isNumber(element.clientBottom) ? element.clientBottom : + getPixelValue(element, 'borderBottomWidth'); + }, + + 'border-left': function(element) { + return Object.isNumber(element.clientLeft) ? element.clientLeft : + getPixelValue(element, 'borderLeftWidth'); + }, + + 'border-right': function(element) { + return Object.isNumber(element.clientRight) ? element.clientRight : + getPixelValue(element, 'borderRightWidth'); + }, + + 'margin-top': function(element) { + return getPixelValue(element, 'marginTop'); + }, + + 'margin-bottom': function(element) { + return getPixelValue(element, 'marginBottom'); + }, + + 'margin-left': function(element) { + return getPixelValue(element, 'marginLeft'); + }, + + 'margin-right': function(element) { + return getPixelValue(element, 'marginRight'); + } + } + }); + + if ('getBoundingClientRect' in document.documentElement) { + Object.extend(Element.Layout.COMPUTATIONS, { + 'right': function(element) { + var parent = hasLayout(element.getOffsetParent()); + var rect = element.getBoundingClientRect(), + pRect = parent.getBoundingClientRect(); + + return (pRect.right - rect.right).round(); + }, + + 'bottom': function(element) { + var parent = hasLayout(element.getOffsetParent()); + var rect = element.getBoundingClientRect(), + pRect = parent.getBoundingClientRect(); + + return (pRect.bottom - rect.bottom).round(); + } + }); + } + + Element.Offset = Class.create({ + initialize: function(left, top) { + this.left = left.round(); + this.top = top.round(); + + this[0] = this.left; + this[1] = this.top; + }, + + relativeTo: function(offset) { + return new Element.Offset( + this.left - offset.left, + this.top - offset.top + ); + }, + + inspect: function() { + return "#".interpolate(this); + }, + + toString: function() { + return "[#{left}, #{top}]".interpolate(this); + }, + + toArray: function() { + return [this.left, this.top]; + } + }); + + function getLayout(element, preCompute) { + return new Element.Layout(element, preCompute); + } + + function measure(element, property) { + return $(element).getLayout().get(property); + } + + function getDimensions(element) { + var layout = $(element).getLayout(); + return { + width: layout.get('width'), + height: layout.get('height') + }; + } + + function getOffsetParent(element) { + if (isDetached(element)) return $(document.body); + + var isInline = (Element.getStyle(element, 'display') === 'inline'); + if (!isInline && element.offsetParent) return $(element.offsetParent); + if (element === document.body) return $(element); + + while ((element = element.parentNode) && element !== document.body) { + if (Element.getStyle(element, 'position') !== 'static') { + return (element.nodeName === 'HTML') ? $(document.body) : $(element); + } + } + + return $(document.body); + } + + + function cumulativeOffset(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return new Element.Offset(valueL, valueT); + } + + function positionedOffset(element) { + var layout = element.getLayout(); + + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + if (isBody(element)) break; + var p = Element.getStyle(element, 'position'); + if (p !== 'static') break; + } + } while (element); + + valueL -= layout.get('margin-top'); + valueT -= layout.get('margin-left'); + + return new Element.Offset(valueL, valueT); + } + + function cumulativeScrollOffset(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return new Element.Offset(valueL, valueT); + } + + function viewportOffset(forElement) { + var valueT = 0, valueL = 0, docBody = document.body; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == docBody && + Element.getStyle(element, 'position') == 'absolute') break; + } while (element = element.offsetParent); + + element = forElement; + do { + if (element != docBody) { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + return new Element.Offset(valueL, valueT); + } + + function absolutize(element) { + element = $(element); + + if (Element.getStyle(element, 'position') === 'absolute') { + return element; + } + + var offsetParent = getOffsetParent(element); + var eOffset = element.viewportOffset(), + pOffset = offsetParent.viewportOffset(); + + var offset = eOffset.relativeTo(pOffset); + var layout = element.getLayout(); + + element.store('prototype_absolutize_original_styles', { + left: element.getStyle('left'), + top: element.getStyle('top'), + width: element.getStyle('width'), + height: element.getStyle('height') + }); + + element.setStyle({ + position: 'absolute', + top: offset.top + 'px', + left: offset.left + 'px', + width: layout.get('width') + 'px', + height: layout.get('height') + 'px' + }); + + return element; + } + + function relativize(element) { + element = $(element); + if (Element.getStyle(element, 'position') === 'relative') { + return element; + } + + var originalStyles = + element.retrieve('prototype_absolutize_original_styles'); + + if (originalStyles) element.setStyle(originalStyles); + return element; + } + + Element.addMethods({ + getLayout: getLayout, + measure: measure, + getDimensions: getDimensions, + getOffsetParent: getOffsetParent, + cumulativeOffset: cumulativeOffset, + positionedOffset: positionedOffset, + cumulativeScrollOffset: cumulativeScrollOffset, + viewportOffset: viewportOffset, + absolutize: absolutize, + relativize: relativize + }); + + function isBody(element) { + return element.nodeName.toUpperCase() === 'BODY'; + } + + function isDetached(element) { + return element !== document.body && + !Element.descendantOf(element, document.body); + } + + if ('getBoundingClientRect' in document.documentElement) { + Element.addMethods({ + viewportOffset: function(element) { + element = $(element); + if (isDetached(element)) return new Element.Offset(0, 0); + + var rect = element.getBoundingClientRect(), + docEl = document.documentElement; + return new Element.Offset(rect.left - docEl.clientLeft, + rect.top - docEl.clientTop); + }, + + positionedOffset: function(element) { + element = $(element); + var parent = element.getOffsetParent(); + if (isDetached(element)) return new Element.Offset(0, 0); + + if (element.offsetParent && + element.offsetParent.nodeName.toUpperCase() === 'HTML') { + return positionedOffset(element); + } + + var eOffset = element.viewportOffset(), + pOffset = isBody(parent) ? viewportOffset(parent) : + parent.viewportOffset(); + var retOffset = eOffset.relativeTo(pOffset); + + var layout = element.getLayout(); + var top = retOffset.top - layout.get('margin-top'); + var left = retOffset.left - layout.get('margin-left'); + + return new Element.Offset(left, top); + } + }); + } +})(); +window.$$ = function() { + var expression = $A(arguments).join(', '); + return Prototype.Selector.select(expression, document); +}; + +Prototype.Selector = (function() { + + function select() { + throw new Error('Method "Prototype.Selector.select" must be defined.'); + } + + function match() { + throw new Error('Method "Prototype.Selector.match" must be defined.'); + } + + function find(elements, expression, index) { + index = index || 0; + var match = Prototype.Selector.match, length = elements.length, matchIndex = 0, i; + + for (i = 0; i < length; i++) { + if (match(elements[i], expression) && index == matchIndex++) { + return Element.extend(elements[i]); + } + } + } + + function extendElements(elements) { + for (var i = 0, length = elements.length; i < length; i++) { + Element.extend(elements[i]); + } + return elements; + } + + + var K = Prototype.K; + + return { + select: select, + match: match, + find: find, + extendElements: (Element.extend === K) ? K : extendElements, + extendElement: Element.extend + }; +})(); +Prototype._original_property = window.Sizzle; +/*! + * Sizzle CSS Selector Engine - v1.0 + * Copyright 2009, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true; + +[0, 0].sort(function(){ + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function(selector, context, results, seed) { + results = results || []; + var origContext = context = context || document; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var parts = [], m, set, checkSet, check, mode, extra, prune = true, contextXML = isXML(context), + soFar = selector; + + while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context ); + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) + selector += parts.shift(); + + set = posProcess( selector, set ); + } + } + } else { + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + var ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; + } + + if ( context ) { + var ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray(set); + } else { + prune = false; + } + + while ( parts.length ) { + var cur = parts.pop(), pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + throw "Syntax error, unrecognized expression: " + (cur || selector); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + } else if ( context && context.nodeType === 1 ) { + for ( var i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + } else { + for ( var i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function(results){ + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort(sortOrder); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[i-1] ) { + results.splice(i--, 1); + } + } + } + } + + return results; +}; + +Sizzle.matches = function(expr, set){ + return Sizzle(expr, null, null, set); +}; + +Sizzle.find = function(expr, context, isXML){ + var set, match; + + if ( !expr ) { + return []; + } + + for ( var i = 0, l = Expr.order.length; i < l; i++ ) { + var type = Expr.order[i], match; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + var left = match[1]; + match.splice(1,1); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace(/\\/g, ""); + set = Expr.find[ type ]( match, context, isXML ); + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = context.getElementsByTagName("*"); + } + + return {set: set, expr: expr}; +}; + +Sizzle.filter = function(expr, set, inplace, not){ + var old = expr, result = [], curLoop = set, match, anyFound, + isXMLFilter = set && set[0] && isXML(set[0]); + + while ( expr && set.length ) { + for ( var type in Expr.filter ) { + if ( (match = Expr.match[ type ].exec( expr )) != null ) { + var filter = Expr.filter[ type ], found, item; + anyFound = false; + + if ( curLoop == result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( var i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + var pass = not ^ !!found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + } else { + curLoop[i] = false; + } + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + if ( expr == old ) { + if ( anyFound == null ) { + throw "Syntax error, unrecognized expression: " + expr; + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +var Expr = Sizzle.selectors = { + order: [ "ID", "NAME", "TAG" ], + match: { + ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/, + CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/, + NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/ + }, + leftMatch: {}, + attrMap: { + "class": "className", + "for": "htmlFor" + }, + attrHandle: { + href: function(elem){ + return elem.getAttribute("href"); + } + }, + relative: { + "+": function(checkSet, part, isXML){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !/\W/.test(part), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag && !isXML ) { + part = part.toUpperCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + ">": function(checkSet, part, isXML){ + var isPartStr = typeof part === "string"; + + if ( isPartStr && !/\W/.test(part) ) { + part = isXML ? part : part.toUpperCase(); + + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName === part ? parent : false; + } + } + } else { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + "": function(checkSet, part, isXML){ + var doneName = done++, checkFn = dirCheck; + + if ( !/\W/.test(part) ) { + var nodeCheck = part = isXML ? part : part.toUpperCase(); + checkFn = dirNodeCheck; + } + + checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML); + }, + "~": function(checkSet, part, isXML){ + var doneName = done++, checkFn = dirCheck; + + if ( typeof part === "string" && !/\W/.test(part) ) { + var nodeCheck = part = isXML ? part : part.toUpperCase(); + checkFn = dirNodeCheck; + } + + checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML); + } + }, + find: { + ID: function(match, context, isXML){ + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + return m ? [m] : []; + } + }, + NAME: function(match, context, isXML){ + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], results = context.getElementsByName(match[1]); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + TAG: function(match, context){ + return context.getElementsByTagName(match[1]); + } + }, + preFilter: { + CLASS: function(match, curLoop, inplace, result, not, isXML){ + match = " " + match[1].replace(/\\/g, "") + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) { + if ( !inplace ) + result.push( elem ); + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + ID: function(match){ + return match[1].replace(/\\/g, ""); + }, + TAG: function(match, curLoop){ + for ( var i = 0; curLoop[i] === false; i++ ){} + return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase(); + }, + CHILD: function(match){ + if ( match[1] == "nth" ) { + var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec( + match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + + match[0] = done++; + + return match; + }, + ATTR: function(match, curLoop, inplace, result, not, isXML){ + var name = match[1].replace(/\\/g, ""); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + PSEUDO: function(match, curLoop, inplace, result, not){ + if ( match[1] === "not" ) { + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + if ( !inplace ) { + result.push.apply( result, ret ); + } + return false; + } + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + POS: function(match){ + match.unshift( true ); + return match; + } + }, + filters: { + enabled: function(elem){ + return elem.disabled === false && elem.type !== "hidden"; + }, + disabled: function(elem){ + return elem.disabled === true; + }, + checked: function(elem){ + return elem.checked === true; + }, + selected: function(elem){ + elem.parentNode.selectedIndex; + return elem.selected === true; + }, + parent: function(elem){ + return !!elem.firstChild; + }, + empty: function(elem){ + return !elem.firstChild; + }, + has: function(elem, i, match){ + return !!Sizzle( match[3], elem ).length; + }, + header: function(elem){ + return /h\d/i.test( elem.nodeName ); + }, + text: function(elem){ + return "text" === elem.type; + }, + radio: function(elem){ + return "radio" === elem.type; + }, + checkbox: function(elem){ + return "checkbox" === elem.type; + }, + file: function(elem){ + return "file" === elem.type; + }, + password: function(elem){ + return "password" === elem.type; + }, + submit: function(elem){ + return "submit" === elem.type; + }, + image: function(elem){ + return "image" === elem.type; + }, + reset: function(elem){ + return "reset" === elem.type; + }, + button: function(elem){ + return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON"; + }, + input: function(elem){ + return /input|select|textarea|button/i.test(elem.nodeName); + } + }, + setFilters: { + first: function(elem, i){ + return i === 0; + }, + last: function(elem, i, match, array){ + return i === array.length - 1; + }, + even: function(elem, i){ + return i % 2 === 0; + }, + odd: function(elem, i){ + return i % 2 === 1; + }, + lt: function(elem, i, match){ + return i < match[3] - 0; + }, + gt: function(elem, i, match){ + return i > match[3] - 0; + }, + nth: function(elem, i, match){ + return match[3] - 0 == i; + }, + eq: function(elem, i, match){ + return match[3] - 0 == i; + } + }, + filter: { + PSEUDO: function(elem, match, i, array){ + var name = match[1], filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0; + } else if ( name === "not" ) { + var not = match[3]; + + for ( var i = 0, l = not.length; i < l; i++ ) { + if ( not[i] === elem ) { + return false; + } + } + + return true; + } + }, + CHILD: function(elem, match){ + var type = match[1], node = elem; + switch (type) { + case 'only': + case 'first': + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) return false; + } + if ( type == 'first') return true; + node = elem; + case 'last': + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) return false; + } + return true; + case 'nth': + var first = match[2], last = match[3]; + + if ( first == 1 && last == 0 ) { + return true; + } + + var doneName = match[0], + parent = elem.parentNode; + + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { + var count = 0; + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + parent.sizcache = doneName; + } + + var diff = elem.nodeIndex - last; + if ( first == 0 ) { + return diff == 0; + } else { + return ( diff % first == 0 && diff / first >= 0 ); + } + } + }, + ID: function(elem, match){ + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + TAG: function(elem, match){ + return (match === "*" && elem.nodeType === 1) || elem.nodeName === match; + }, + CLASS: function(elem, match){ + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + ATTR: function(elem, match){ + var name = match[1], + result = Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value != check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + POS: function(elem, match, i, array){ + var name = match[2], filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source ); +} + +var makeArray = function(array, results) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 ); + +} catch(e){ + makeArray = function(array, results) { + var ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + } else { + if ( typeof array.length === "number" ) { + for ( var i = 0, l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + } else { + for ( var i = 0; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + if ( a == b ) { + hasDuplicate = true; + } + return 0; + } + + var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; + if ( ret === 0 ) { + hasDuplicate = true; + } + return ret; + }; +} else if ( "sourceIndex" in document.documentElement ) { + sortOrder = function( a, b ) { + if ( !a.sourceIndex || !b.sourceIndex ) { + if ( a == b ) { + hasDuplicate = true; + } + return 0; + } + + var ret = a.sourceIndex - b.sourceIndex; + if ( ret === 0 ) { + hasDuplicate = true; + } + return ret; + }; +} else if ( document.createRange ) { + sortOrder = function( a, b ) { + if ( !a.ownerDocument || !b.ownerDocument ) { + if ( a == b ) { + hasDuplicate = true; + } + return 0; + } + + var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); + aRange.setStart(a, 0); + aRange.setEnd(a, 0); + bRange.setStart(b, 0); + bRange.setEnd(b, 0); + var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange); + if ( ret === 0 ) { + hasDuplicate = true; + } + return ret; + }; +} + +(function(){ + var form = document.createElement("div"), + id = "script" + (new Date).getTime(); + form.innerHTML = ""; + + var root = document.documentElement; + root.insertBefore( form, root.firstChild ); + + if ( !!document.getElementById( id ) ) { + Expr.find.ID = function(match, context, isXML){ + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; + } + }; + + Expr.filter.ID = function(elem, match){ + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + root = form = null; // release memory in IE +})(); + +(function(){ + + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function(match, context){ + var results = context.getElementsByTagName(match[1]); + + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + div.innerHTML = ""; + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + Expr.attrHandle.href = function(elem){ + return elem.getAttribute("href", 2); + }; + } + + div = null; // release memory in IE +})(); + +if ( document.querySelectorAll ) (function(){ + var oldSizzle = Sizzle, div = document.createElement("div"); + div.innerHTML = "

                "; + + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function(query, context, extra, seed){ + context = context || document; + + if ( !seed && context.nodeType === 9 && !isXML(context) ) { + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(e){} + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + div = null; // release memory in IE +})(); + +if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){ + var div = document.createElement("div"); + div.innerHTML = "
                "; + + if ( div.getElementsByClassName("e").length === 0 ) + return; + + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) + return; + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function(match, context, isXML) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + div = null; // release memory in IE +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + var sibDir = dir == "previousSibling" && !isXML; + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + if ( sibDir && elem.nodeType === 1 ){ + elem.sizcache = doneName; + elem.sizset = i; + } + elem = elem[dir]; + var match = false; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( elem.nodeName === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + var sibDir = dir == "previousSibling" && !isXML; + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + if ( sibDir && elem.nodeType === 1 ) { + elem.sizcache = doneName; + elem.sizset = i; + } + elem = elem[dir]; + var match = false; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem.sizcache = doneName; + elem.sizset = i; + } + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +var contains = document.compareDocumentPosition ? function(a, b){ + return a.compareDocumentPosition(b) & 16; +} : function(a, b){ + return a !== b && (a.contains ? a.contains(b) : true); +}; + +var isXML = function(elem){ + return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" || + !!elem.ownerDocument && elem.ownerDocument.documentElement.nodeName !== "HTML"; +}; + +var posProcess = function(selector, context){ + var tmpSet = [], later = "", match, + root = context.nodeType ? [context] : context; + + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet ); + } + + return Sizzle.filter( later, tmpSet ); +}; + + +window.Sizzle = Sizzle; + +})(); + +;(function(engine) { + var extendElements = Prototype.Selector.extendElements; + + function select(selector, scope) { + return extendElements(engine(selector, scope || document)); + } + + function match(element, selector) { + return engine.matches(selector, [element]).length == 1; + } + + Prototype.Selector.engine = engine; + Prototype.Selector.select = select; + Prototype.Selector.match = match; +})(Sizzle); + +window.Sizzle = Prototype._original_property; +delete Prototype._original_property; + +var Form = { + reset: function(form) { + form = $(form); + form.reset(); + return form; + }, + + serializeElements: function(elements, options) { + if (typeof options != 'object') options = { hash: !!options }; + else if (Object.isUndefined(options.hash)) options.hash = true; + var key, value, submitted = false, submit = options.submit; + + var data = elements.inject({ }, function(result, element) { + if (!element.disabled && element.name) { + key = element.name; value = $(element).getValue(); + if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted && + submit !== false && (!submit || key == submit) && (submitted = true)))) { + if (key in result) { + if (!Object.isArray(result[key])) result[key] = [result[key]]; + result[key].push(value); + } + else result[key] = value; + } + } + return result; + }); + + return options.hash ? data : Object.toQueryString(data); + } +}; + +Form.Methods = { + serialize: function(form, options) { + return Form.serializeElements(Form.getElements(form), options); + }, + + getElements: function(form) { + var elements = $(form).getElementsByTagName('*'), + element, + arr = [ ], + serializers = Form.Element.Serializers; + for (var i = 0; element = elements[i]; i++) { + arr.push(element); + } + return arr.inject([], function(elements, child) { + if (serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + }) + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) return $A(inputs).map(Element.extend); + + for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || (name && input.name != name)) + continue; + matchingInputs.push(Element.extend(input)); + } + + return matchingInputs; + }, + + disable: function(form) { + form = $(form); + Form.getElements(form).invoke('disable'); + return form; + }, + + enable: function(form) { + form = $(form); + Form.getElements(form).invoke('enable'); + return form; + }, + + findFirstElement: function(form) { + var elements = $(form).getElements().findAll(function(element) { + return 'hidden' != element.type && !element.disabled; + }); + var firstByIndex = elements.findAll(function(element) { + return element.hasAttribute('tabIndex') && element.tabIndex >= 0; + }).sortBy(function(element) { return element.tabIndex }).first(); + + return firstByIndex ? firstByIndex : elements.find(function(element) { + return /^(?:input|select|textarea)$/i.test(element.tagName); + }); + }, + + focusFirstElement: function(form) { + form = $(form); + form.findFirstElement().activate(); + return form; + }, + + request: function(form, options) { + form = $(form), options = Object.clone(options || { }); + + var params = options.parameters, action = form.readAttribute('action') || ''; + if (action.blank()) action = window.location.href; + options.parameters = form.serialize(true); + + if (params) { + if (Object.isString(params)) params = params.toQueryParams(); + Object.extend(options.parameters, params); + } + + if (form.hasAttribute('method') && !options.method) + options.method = form.method; + + return new Ajax.Request(action, options); + } +}; + +/*--------------------------------------------------------------------------*/ + + +Form.Element = { + focus: function(element) { + $(element).focus(); + return element; + }, + + select: function(element) { + $(element).select(); + return element; + } +}; + +Form.Element.Methods = { + + serialize: function(element) { + element = $(element); + if (!element.disabled && element.name) { + var value = element.getValue(); + if (value != undefined) { + var pair = { }; + pair[element.name] = value; + return Object.toQueryString(pair); + } + } + return ''; + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + return Form.Element.Serializers[method](element); + }, + + setValue: function(element, value) { + element = $(element); + var method = element.tagName.toLowerCase(); + Form.Element.Serializers[method](element, value); + return element; + }, + + clear: function(element) { + $(element).value = ''; + return element; + }, + + present: function(element) { + return $(element).value != ''; + }, + + activate: function(element) { + element = $(element); + try { + element.focus(); + if (element.select && (element.tagName.toLowerCase() != 'input' || + !(/^(?:button|reset|submit)$/i.test(element.type)))) + element.select(); + } catch (e) { } + return element; + }, + + disable: function(element) { + element = $(element); + element.disabled = true; + return element; + }, + + enable: function(element) { + element = $(element); + element.disabled = false; + return element; + } +}; + +/*--------------------------------------------------------------------------*/ + +var Field = Form.Element; + +var $F = Form.Element.Methods.getValue; + +/*--------------------------------------------------------------------------*/ + +Form.Element.Serializers = { + input: function(element, value) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element, value); + default: + return Form.Element.Serializers.textarea(element, value); + } + }, + + inputSelector: function(element, value) { + if (Object.isUndefined(value)) return element.checked ? element.value : null; + else element.checked = !!value; + }, + + textarea: function(element, value) { + if (Object.isUndefined(value)) return element.value; + else element.value = value; + }, + + select: function(element, value) { + if (Object.isUndefined(value)) + return this[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + else { + var opt, currentValue, single = !Object.isArray(value); + for (var i = 0, length = element.length; i < length; i++) { + opt = element.options[i]; + currentValue = this.optionValue(opt); + if (single) { + if (currentValue == value) { + opt.selected = true; + return; + } + } + else opt.selected = value.include(currentValue); + } + } + }, + + selectOne: function(element) { + var index = element.selectedIndex; + return index >= 0 ? this.optionValue(element.options[index]) : null; + }, + + selectMany: function(element) { + var values, length = element.length; + if (!length) return null; + + for (var i = 0, values = []; i < length; i++) { + var opt = element.options[i]; + if (opt.selected) values.push(this.optionValue(opt)); + } + return values; + }, + + optionValue: function(opt) { + return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; + } +}; + +/*--------------------------------------------------------------------------*/ + + +Abstract.TimedObserver = Class.create(PeriodicalExecuter, { + initialize: function($super, element, frequency, callback) { + $super(callback, frequency); + this.element = $(element); + this.lastValue = this.getValue(); + }, + + execute: function() { + var value = this.getValue(); + if (Object.isString(this.lastValue) && Object.isString(value) ? + this.lastValue != value : String(this.lastValue) != String(value)) { + this.callback(this.element, value); + this.lastValue = value; + } + } +}); + +Form.Element.Observer = Class.create(Abstract.TimedObserver, { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(Abstract.TimedObserver, { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = Class.create({ + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + Form.getElements(this.element).each(this.registerCallback, this); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + default: + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +}); + +Form.Element.EventObserver = Class.create(Abstract.EventObserver, { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(Abstract.EventObserver, { + getValue: function() { + return Form.serialize(this.element); + } +}); +(function() { + + var Event = { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + KEY_INSERT: 45, + + cache: {} + }; + + var docEl = document.documentElement; + var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl + && 'onmouseleave' in docEl; + + var _isButton; + if (Prototype.Browser.IE) { + var buttonMap = { 0: 1, 1: 4, 2: 2 }; + _isButton = function(event, code) { + return event.button === buttonMap[code]; + }; + } else if (Prototype.Browser.WebKit) { + _isButton = function(event, code) { + switch (code) { + case 0: return event.which == 1 && !event.metaKey; + case 1: return event.which == 1 && event.metaKey; + default: return false; + } + }; + } else { + _isButton = function(event, code) { + return event.which ? (event.which === code + 1) : (event.button === code); + }; + } + + function isLeftClick(event) { return _isButton(event, 0) } + + function isMiddleClick(event) { return _isButton(event, 1) } + + function isRightClick(event) { return _isButton(event, 2) } + + function element(event) { + event = Event.extend(event); + + var node = event.target, type = event.type, + currentTarget = event.currentTarget; + + if (currentTarget && currentTarget.tagName) { + if (type === 'load' || type === 'error' || + (type === 'click' && currentTarget.tagName.toLowerCase() === 'input' + && currentTarget.type === 'radio')) + node = currentTarget; + } + + if (node.nodeType == Node.TEXT_NODE) + node = node.parentNode; + + return Element.extend(node); + } + + function findElement(event, expression) { + var element = Event.element(event); + if (!expression) return element; + while (element) { + if (Object.isElement(element) && Prototype.Selector.match(element, expression)) { + return Element.extend(element); + } + element = element.parentNode; + } + } + + function pointer(event) { + return { x: pointerX(event), y: pointerY(event) }; + } + + function pointerX(event) { + var docElement = document.documentElement, + body = document.body || { scrollLeft: 0 }; + + return event.pageX || (event.clientX + + (docElement.scrollLeft || body.scrollLeft) - + (docElement.clientLeft || 0)); + } + + function pointerY(event) { + var docElement = document.documentElement, + body = document.body || { scrollTop: 0 }; + + return event.pageY || (event.clientY + + (docElement.scrollTop || body.scrollTop) - + (docElement.clientTop || 0)); + } + + + function stop(event) { + Event.extend(event); + event.preventDefault(); + event.stopPropagation(); + + event.stopped = true; + } + + Event.Methods = { + isLeftClick: isLeftClick, + isMiddleClick: isMiddleClick, + isRightClick: isRightClick, + + element: element, + findElement: findElement, + + pointer: pointer, + pointerX: pointerX, + pointerY: pointerY, + + stop: stop + }; + + + var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { + m[name] = Event.Methods[name].methodize(); + return m; + }); + + if (Prototype.Browser.IE) { + function _relatedTarget(event) { + var element; + switch (event.type) { + case 'mouseover': element = event.fromElement; break; + case 'mouseout': element = event.toElement; break; + default: return null; + } + return Element.extend(element); + } + + Object.extend(methods, { + stopPropagation: function() { this.cancelBubble = true }, + preventDefault: function() { this.returnValue = false }, + inspect: function() { return '[object Event]' } + }); + + Event.extend = function(event, element) { + if (!event) return false; + if (event._extendedByPrototype) return event; + + event._extendedByPrototype = Prototype.emptyFunction; + var pointer = Event.pointer(event); + + Object.extend(event, { + target: event.srcElement || element, + relatedTarget: _relatedTarget(event), + pageX: pointer.x, + pageY: pointer.y + }); + + return Object.extend(event, methods); + }; + } else { + Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__; + Object.extend(Event.prototype, methods); + Event.extend = Prototype.K; + } + + function _createResponder(element, eventName, handler) { + var registry = Element.retrieve(element, 'prototype_event_registry'); + + if (Object.isUndefined(registry)) { + CACHE.push(element); + registry = Element.retrieve(element, 'prototype_event_registry', $H()); + } + + var respondersForEvent = registry.get(eventName); + if (Object.isUndefined(respondersForEvent)) { + respondersForEvent = []; + registry.set(eventName, respondersForEvent); + } + + if (respondersForEvent.pluck('handler').include(handler)) return false; + + var responder; + if (eventName.include(":")) { + responder = function(event) { + if (Object.isUndefined(event.eventName)) + return false; + + if (event.eventName !== eventName) + return false; + + Event.extend(event, element); + handler.call(element, event); + }; + } else { + if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED && + (eventName === "mouseenter" || eventName === "mouseleave")) { + if (eventName === "mouseenter" || eventName === "mouseleave") { + responder = function(event) { + Event.extend(event, element); + + var parent = event.relatedTarget; + while (parent && parent !== element) { + try { parent = parent.parentNode; } + catch(e) { parent = element; } + } + + if (parent === element) return; + + handler.call(element, event); + }; + } + } else { + responder = function(event) { + Event.extend(event, element); + handler.call(element, event); + }; + } + } + + responder.handler = handler; + respondersForEvent.push(responder); + return responder; + } + + function _destroyCache() { + for (var i = 0, length = CACHE.length; i < length; i++) { + Event.stopObserving(CACHE[i]); + CACHE[i] = null; + } + } + + var CACHE = []; + + if (Prototype.Browser.IE) + window.attachEvent('onunload', _destroyCache); + + if (Prototype.Browser.WebKit) + window.addEventListener('unload', Prototype.emptyFunction, false); + + + var _getDOMEventName = Prototype.K, + translations = { mouseenter: "mouseover", mouseleave: "mouseout" }; + + if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) { + _getDOMEventName = function(eventName) { + return (translations[eventName] || eventName); + }; + } + + function observe(element, eventName, handler) { + element = $(element); + + var responder = _createResponder(element, eventName, handler); + + if (!responder) return element; + + if (eventName.include(':')) { + if (element.addEventListener) + element.addEventListener("dataavailable", responder, false); + else { + element.attachEvent("ondataavailable", responder); + element.attachEvent("onfilterchange", responder); + } + } else { + var actualEventName = _getDOMEventName(eventName); + + if (element.addEventListener) + element.addEventListener(actualEventName, responder, false); + else + element.attachEvent("on" + actualEventName, responder); + } + + return element; + } + + function stopObserving(element, eventName, handler) { + element = $(element); + + var registry = Element.retrieve(element, 'prototype_event_registry'); + if (!registry) return element; + + if (!eventName) { + registry.each( function(pair) { + var eventName = pair.key; + stopObserving(element, eventName); + }); + return element; + } + + var responders = registry.get(eventName); + if (!responders) return element; + + if (!handler) { + responders.each(function(r) { + stopObserving(element, eventName, r.handler); + }); + return element; + } + + var responder = responders.find( function(r) { return r.handler === handler; }); + if (!responder) return element; + + if (eventName.include(':')) { + if (element.removeEventListener) + element.removeEventListener("dataavailable", responder, false); + else { + element.detachEvent("ondataavailable", responder); + element.detachEvent("onfilterchange", responder); + } + } else { + var actualEventName = _getDOMEventName(eventName); + if (element.removeEventListener) + element.removeEventListener(actualEventName, responder, false); + else + element.detachEvent('on' + actualEventName, responder); + } + + registry.set(eventName, responders.without(responder)); + + return element; + } + + function fire(element, eventName, memo, bubble) { + element = $(element); + + if (Object.isUndefined(bubble)) + bubble = true; + + if (element == document && document.createEvent && !element.dispatchEvent) + element = document.documentElement; + + var event; + if (document.createEvent) { + event = document.createEvent('HTMLEvents'); + event.initEvent('dataavailable', true, true); + } else { + event = document.createEventObject(); + event.eventType = bubble ? 'ondataavailable' : 'onfilterchange'; + } + + event.eventName = eventName; + event.memo = memo || { }; + + if (document.createEvent) + element.dispatchEvent(event); + else + element.fireEvent(event.eventType, event); + + return Event.extend(event); + } + + Event.Handler = Class.create({ + initialize: function(element, eventName, selector, callback) { + this.element = $(element); + this.eventName = eventName; + this.selector = selector; + this.callback = callback; + this.handler = this.handleEvent.bind(this); + }, + + start: function() { + Event.observe(this.element, this.eventName, this.handler); + return this; + }, + + stop: function() { + Event.stopObserving(this.element, this.eventName, this.handler); + return this; + }, + + handleEvent: function(event) { + var element = event.findElement(this.selector); + if (element) this.callback.call(this.element, event, element); + } + }); + + function on(element, eventName, selector, callback) { + element = $(element); + if (Object.isFunction(selector) && Object.isUndefined(callback)) { + callback = selector, selector = null; + } + + return new Event.Handler(element, eventName, selector, callback).start(); + } + + Object.extend(Event, Event.Methods); + + Object.extend(Event, { + fire: fire, + observe: observe, + stopObserving: stopObserving, + on: on + }); + + Element.addMethods({ + fire: fire, + + observe: observe, + + stopObserving: stopObserving, + + on: on + }); + + Object.extend(document, { + fire: fire.methodize(), + + observe: observe.methodize(), + + stopObserving: stopObserving.methodize(), + + on: on.methodize(), + + loaded: false + }); + + if (window.Event) Object.extend(window.Event, Event); + else window.Event = Event; +})(); + +(function() { + /* Support for the DOMContentLoaded event is based on work by Dan Webb, + Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */ + + var timer; + + function fireContentLoadedEvent() { + if (document.loaded) return; + if (timer) window.clearTimeout(timer); + document.loaded = true; + document.fire('dom:loaded'); + } + + function checkReadyState() { + if (document.readyState === 'complete') { + document.stopObserving('readystatechange', checkReadyState); + fireContentLoadedEvent(); + } + } + + function pollDoScroll() { + try { document.documentElement.doScroll('left'); } + catch(e) { + timer = pollDoScroll.defer(); + return; + } + fireContentLoadedEvent(); + } + + if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false); + } else { + document.observe('readystatechange', checkReadyState); + if (window == top) + timer = pollDoScroll.defer(); + } + + Event.observe(window, 'load', fireContentLoadedEvent); +})(); + +Element.addMethods(); + +/*------------------------------- DEPRECATED -------------------------------*/ + +Hash.toQueryString = Object.toQueryString; + +var Toggle = { display: Element.toggle }; + +Element.Methods.childOf = Element.Methods.descendantOf; + +var Insertion = { + Before: function(element, content) { + return Element.insert(element, {before:content}); + }, + + Top: function(element, content) { + return Element.insert(element, {top:content}); + }, + + Bottom: function(element, content) { + return Element.insert(element, {bottom:content}); + }, + + After: function(element, content) { + return Element.insert(element, {after:content}); + } +}; + +var $continue = new Error('"throw $continue" is deprecated, use "return" instead'); + +var Position = { + includeScrollOffsets: false, + + prepare: function() { + this.deltaX = window.pageXOffset + || document.documentElement.scrollLeft + || document.body.scrollLeft + || 0; + this.deltaY = window.pageYOffset + || document.documentElement.scrollTop + || document.body.scrollTop + || 0; + }, + + within: function(element, x, y) { + if (this.includeScrollOffsets) + return this.withinIncludingScrolloffsets(element, x, y); + this.xcomp = x; + this.ycomp = y; + this.offset = Element.cumulativeOffset(element); + + return (y >= this.offset[1] && + y < this.offset[1] + element.offsetHeight && + x >= this.offset[0] && + x < this.offset[0] + element.offsetWidth); + }, + + withinIncludingScrolloffsets: function(element, x, y) { + var offsetcache = Element.cumulativeScrollOffset(element); + + this.xcomp = x + offsetcache[0] - this.deltaX; + this.ycomp = y + offsetcache[1] - this.deltaY; + this.offset = Element.cumulativeOffset(element); + + return (this.ycomp >= this.offset[1] && + this.ycomp < this.offset[1] + element.offsetHeight && + this.xcomp >= this.offset[0] && + this.xcomp < this.offset[0] + element.offsetWidth); + }, + + overlap: function(mode, element) { + if (!mode) return 0; + if (mode == 'vertical') + return ((this.offset[1] + element.offsetHeight) - this.ycomp) / + element.offsetHeight; + if (mode == 'horizontal') + return ((this.offset[0] + element.offsetWidth) - this.xcomp) / + element.offsetWidth; + }, + + + cumulativeOffset: Element.Methods.cumulativeOffset, + + positionedOffset: Element.Methods.positionedOffset, + + absolutize: function(element) { + Position.prepare(); + return Element.absolutize(element); + }, + + relativize: function(element) { + Position.prepare(); + return Element.relativize(element); + }, + + realOffset: Element.Methods.cumulativeScrollOffset, + + offsetParent: Element.Methods.getOffsetParent, + + page: Element.Methods.viewportOffset, + + clone: function(source, target, options) { + options = options || { }; + return Element.clonePosition(target, source, options); + } +}; + +/*--------------------------------------------------------------------------*/ + +if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){ + function iter(name) { + return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]"; + } + + instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ? + function(element, className) { + className = className.toString().strip(); + var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className); + return cond ? document._getElementsByXPath('.//*' + cond, element) : []; + } : function(element, className) { + className = className.toString().strip(); + var elements = [], classNames = (/\s/.test(className) ? $w(className) : null); + if (!classNames && !className) return elements; + + var nodes = $(element).getElementsByTagName('*'); + className = ' ' + className + ' '; + + for (var i = 0, child, cn; child = nodes[i]; i++) { + if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) || + (classNames && classNames.all(function(name) { + return !name.toString().blank() && cn.include(' ' + name + ' '); + })))) + elements.push(Element.extend(child)); + } + return elements; + }; + + return function(className, parentElement) { + return $(parentElement || document.body).getElementsByClassName(className); + }; +}(Element.Methods); + +/*--------------------------------------------------------------------------*/ + +Element.ClassNames = Class.create(); +Element.ClassNames.prototype = { + initialize: function(element) { + this.element = $(element); + }, + + _each: function(iterator) { + this.element.className.split(/\s+/).select(function(name) { + return name.length > 0; + })._each(iterator); + }, + + set: function(className) { + this.element.className = className; + }, + + add: function(classNameToAdd) { + if (this.include(classNameToAdd)) return; + this.set($A(this).concat(classNameToAdd).join(' ')); + }, + + remove: function(classNameToRemove) { + if (!this.include(classNameToRemove)) return; + this.set($A(this).without(classNameToRemove).join(' ')); + }, + + toString: function() { + return $A(this).join(' '); + } +}; + +Object.extend(Element.ClassNames.prototype, Enumerable); + +/*--------------------------------------------------------------------------*/ + +(function() { + window.Selector = Class.create({ + initialize: function(expression) { + this.expression = expression.strip(); + }, + + findElements: function(rootElement) { + return Prototype.Selector.select(this.expression, rootElement); + }, + + match: function(element) { + return Prototype.Selector.match(element, this.expression); + }, + + toString: function() { + return this.expression; + }, + + inspect: function() { + return "#"; + } + }); + + Object.extend(Selector, { + matchElements: function(elements, expression) { + var match = Prototype.Selector.match, + results = []; + + for (var i = 0, length = elements.length; i < length; i++) { + var element = elements[i]; + if (match(element, expression)) { + results.push(Element.extend(element)); + } + } + return results; + }, + + findElement: function(elements, expression, index) { + index = index || 0; + var matchIndex = 0, element; + for (var i = 0, length = elements.length; i < length; i++) { + element = elements[i]; + if (Prototype.Selector.match(element, expression) && index === matchIndex++) { + return Element.extend(element); + } + } + }, + + findChildElements: function(element, expressions) { + var selector = expressions.toArray().join(', '); + return Prototype.Selector.select(selector, element || document); + } + }); +})(); diff --git a/tryruby/public/javascripts/rails.js b/tryruby/public/javascripts/rails.js new file mode 100644 index 0000000..aed6aed --- /dev/null +++ b/tryruby/public/javascripts/rails.js @@ -0,0 +1,191 @@ +(function() { + // Technique from Juriy Zaytsev + // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ + function isEventSupported(eventName) { + var el = document.createElement('div'); + eventName = 'on' + eventName; + var isSupported = (eventName in el); + if (!isSupported) { + el.setAttribute(eventName, 'return;'); + isSupported = typeof el[eventName] == 'function'; + } + el = null; + return isSupported; + } + + function isForm(element) { + return Object.isElement(element) && element.nodeName.toUpperCase() == 'FORM' + } + + function isInput(element) { + if (Object.isElement(element)) { + var name = element.nodeName.toUpperCase() + return name == 'INPUT' || name == 'SELECT' || name == 'TEXTAREA' + } + else return false + } + + var submitBubbles = isEventSupported('submit'), + changeBubbles = isEventSupported('change') + + if (!submitBubbles || !changeBubbles) { + // augment the Event.Handler class to observe custom events when needed + Event.Handler.prototype.initialize = Event.Handler.prototype.initialize.wrap( + function(init, element, eventName, selector, callback) { + init(element, eventName, selector, callback) + // is the handler being attached to an element that doesn't support this event? + if ( (!submitBubbles && this.eventName == 'submit' && !isForm(this.element)) || + (!changeBubbles && this.eventName == 'change' && !isInput(this.element)) ) { + // "submit" => "emulated:submit" + this.eventName = 'emulated:' + this.eventName + } + } + ) + } + + if (!submitBubbles) { + // discover forms on the page by observing focus events which always bubble + document.on('focusin', 'form', function(focusEvent, form) { + // special handler for the real "submit" event (one-time operation) + if (!form.retrieve('emulated:submit')) { + form.on('submit', function(submitEvent) { + var emulated = form.fire('emulated:submit', submitEvent, true) + // if custom event received preventDefault, cancel the real one too + if (emulated.returnValue === false) submitEvent.preventDefault() + }) + form.store('emulated:submit', true) + } + }) + } + + if (!changeBubbles) { + // discover form inputs on the page + document.on('focusin', 'input, select, texarea', function(focusEvent, input) { + // special handler for real "change" events + if (!input.retrieve('emulated:change')) { + input.on('change', function(changeEvent) { + input.fire('emulated:change', changeEvent, true) + }) + input.store('emulated:change', true) + } + }) + } + + function handleRemote(element) { + var method, url, params; + + var event = element.fire("ajax:before"); + if (event.stopped) return false; + + if (element.tagName.toLowerCase() === 'form') { + method = element.readAttribute('method') || 'post'; + url = element.readAttribute('action'); + params = element.serialize(); + } else { + method = element.readAttribute('data-method') || 'get'; + url = element.readAttribute('href'); + params = {}; + } + + new Ajax.Request(url, { + method: method, + parameters: params, + evalScripts: true, + + onComplete: function(request) { element.fire("ajax:complete", request); }, + onSuccess: function(request) { element.fire("ajax:success", request); }, + onFailure: function(request) { element.fire("ajax:failure", request); } + }); + + element.fire("ajax:after"); + } + + function handleMethod(element) { + var method = element.readAttribute('data-method'), + url = element.readAttribute('href'), + csrf_param = $$('meta[name=csrf-param]')[0], + csrf_token = $$('meta[name=csrf-token]')[0]; + + var form = new Element('form', { method: "POST", action: url, style: "display: none;" }); + element.parentNode.insert(form); + + if (method !== 'post') { + var field = new Element('input', { type: 'hidden', name: '_method', value: method }); + form.insert(field); + } + + if (csrf_param) { + var param = csrf_param.readAttribute('content'), + token = csrf_token.readAttribute('content'), + field = new Element('input', { type: 'hidden', name: param, value: token }); + form.insert(field); + } + + form.submit(); + } + + + document.on("click", "*[data-confirm]", function(event, element) { + var message = element.readAttribute('data-confirm'); + if (!confirm(message)) event.stop(); + }); + + document.on("click", "a[data-remote]", function(event, element) { + if (event.stopped) return; + handleRemote(element); + event.stop(); + }); + + document.on("click", "a[data-method]", function(event, element) { + if (event.stopped) return; + handleMethod(element); + event.stop(); + }); + + document.on("submit", function(event) { + var element = event.findElement(), + message = element.readAttribute('data-confirm'); + if (message && !confirm(message)) { + event.stop(); + return false; + } + + var inputs = element.select("input[type=submit][data-disable-with]"); + inputs.each(function(input) { + input.disabled = true; + input.writeAttribute('data-original-value', input.value); + input.value = input.readAttribute('data-disable-with'); + }); + + var element = event.findElement("form[data-remote]"); + if (element) { + handleRemote(element); + event.stop(); + } + }); + + document.on("ajax:after", "form", function(event, element) { + var inputs = element.select("input[type=submit][disabled=true][data-disable-with]"); + inputs.each(function(input) { + input.value = input.readAttribute('data-original-value'); + input.removeAttribute('data-original-value'); + input.disabled = false; + }); + }); + + Ajax.Responders.register({ + onCreate: function(request) { + var csrf_meta_tag = $$('meta[name=csrf-token]')[0]; + + if (csrf_meta_tag) { + var header = 'X-CSRF-Token', + token = csrf_meta_tag.readAttribute('content'); + + if (!request.options.requestHeaders) { + request.options.requestHeaders = {}; + } + request.options.requestHeaders[header] = token; + } + } + }); +})(); diff --git a/tryruby/public/javascripts/raphael-min.js b/tryruby/public/javascripts/raphael-min.js new file mode 100644 index 0000000..4a99e3e --- /dev/null +++ b/tryruby/public/javascripts/raphael-min.js @@ -0,0 +1,113 @@ +/* + * Raphael 1.4.3 - JavaScript Vector Library + * + * Copyright (c) 2010 Dmitry Baranovskiy (http://raphaeljs.com) + * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. + */ +Raphael=function(){function m(){if(m.is(arguments[0],U)){for(var a=arguments[0],b=Aa[K](m,a.splice(0,3+m.is(a[0],O))),c=b.set(),d=0,f=a[o];d

                ";if(ha.childNodes[o]!=2)return m.type=null;ha=null}m.svg=!(m.vml=m.type=="VML");G[p]=m[p];m._id=0;m._oid=0;m.fn={};m.is=function(a,b){b=ca.call(b);return b=="object"&&a===Object(a)||b=="undefined"&&typeof a==b||b=="null"&&a==null||ca.call(ob.call(a).slice(8,-1))==b};m.setWindow=function(a){X=a;C=X.document};function ra(a){if(m.vml){var b=/^\s+|\s+$/g;ra=T(function(d){var f;d=(d+s)[I](b, +s);try{var e=new X.ActiveXObject("htmlfile");e.write("");e.close();f=e.body}catch(g){f=X.createPopup().document.body}e=f.createTextRange();try{f.style.color=d;var h=e.queryCommandValue("ForeColor");h=(h&255)<<16|h&65280|(h&16711680)>>>16;return"#"+("000000"+h[N](16)).slice(-6)}catch(i){return"none"}})}else{var c=C.createElement("i");c.title="Rapha\u00ebl Colour Picker";c.style.display="none";C.body[y](c);ra=T(function(d){c.style.color=d;return C.defaultView.getComputedStyle(c,s).getPropertyValue("color")})}return ra(a)} +function qb(){return"hsb("+[this.h,this.s,this.b]+")"}function rb(){return this.hex}m.hsb2rgb=T(function(a,b,c){if(m.is(a,"object")&&"h"in a&&"s"in a&&"b"in a){c=a.b;b=a.s;a=a.h}var d;if(c==0)return{r:0,g:0,b:0,hex:"#000"};if(a>1||b>1||c>1){a/=255;b/=255;c/=255}d=~~(a*6);a=a*6-d;var f=c*(1-b),e=c*(1-b*a),g=c*(1-b*(1-a));a=[c,e,f,f,g,c,c][d];b=[g,c,c,e,f,f,g][d];d=[f,f,g,c,c,e,f][d];a*=255;b*=255;d*=255;c={r:a,g:b,b:d,toString:rb};a=(~~a)[N](16);b=(~~b)[N](16);d=(~~d)[N](16);a=a[I](ga,"0");b=b[I](ga, +"0");d=d[I](ga,"0");c.hex="#"+a+b+d;return c},m);m.rgb2hsb=T(function(a,b,c){if(m.is(a,"object")&&"r"in a&&"g"in a&&"b"in a){c=a.b;b=a.g;a=a.r}if(m.is(a,ea)){var d=m.getRGB(a);a=d.r;b=d.g;c=d.b}if(a>1||b>1||c>1){a/=255;b/=255;c/=255}var f=Y(a,b,c),e=$(a,b,c);d=f;if(e==f)return{h:0,s:0,b:f};else{var g=f-e;e=g/f;a=a==f?(b-c)/g:b==f?2+(c-a)/g:4+(a-b)/g;a/=6;a<0&&a++;a>1&&a--}return{h:a,s:e,b:d,toString:qb}},m);var sb=/,?([achlmqrstvxz]),?/gi,sa=/\s*,\s*/,tb={hs:1,rg:1};m._path2string=function(){return this.join(",")[I](sb, +"$1")};function T(a,b,c){function d(){var f=Array[p].slice.call(arguments,0),e=f[Q]("\u25ba"),g=d.cache=d.cache||{},h=d.count=d.count||[];if(g[z](e))return c?c(g[e]):g[e];h[o]>=1000&&delete g[h.shift()];h[E](e);g[e]=a[K](b,f);return c?c(g[e]):g[e]}return d}m.getRGB=T(function(a){if(!a||(a+=s).indexOf("-")+1)return{r:-1,g:-1,b:-1,hex:"none",error:1};if(a=="none")return{r:-1,g:-1,b:-1,hex:"none"};!(tb[z](a.substring(0,2))||a.charAt()=="#")&&(a=ra(a));var b,c,d,f,e;if(a=a.match(pb)){if(a[2]){d=da(a[2].substring(5), +16);c=da(a[2].substring(3,5),16);b=da(a[2].substring(1,3),16)}if(a[3]){d=da((e=a[3].charAt(3))+e,16);c=da((e=a[3].charAt(2))+e,16);b=da((e=a[3].charAt(1))+e,16)}if(a[4]){a=a[4][H](sa);b=A(a[0]);c=A(a[1]);d=A(a[2]);f=A(a[3])}if(a[5]){a=a[5][H](sa);b=A(a[0])*2.55;c=A(a[1])*2.55;d=A(a[2])*2.55;f=A(a[3])}if(a[6]){a=a[6][H](sa);b=A(a[0]);c=A(a[1]);d=A(a[2]);return m.hsb2rgb(b,c,d)}if(a[7]){a=a[7][H](sa);b=A(a[0])*2.55;c=A(a[1])*2.55;d=A(a[2])*2.55;return m.hsb2rgb(b,c,d)}a={r:b,g:c,b:d};b=(~~b)[N](16); +c=(~~c)[N](16);d=(~~d)[N](16);b=b[I](ga,"0");c=c[I](ga,"0");d=d[I](ga,"0");a.hex="#"+b+c+d;isFinite(A(f))&&(a.o=f);return a}return{r:-1,g:-1,b:-1,hex:"none",error:1}},m);m.getColor=function(a){a=this.getColor.start=this.getColor.start||{h:0,s:1,b:a||0.75};var b=this.hsb2rgb(a.h,a.s,a.b);a.h+=0.075;if(a.h>1){a.h=0;a.s-=0.2;a.s<=0&&(this.getColor.start={h:0,s:1,b:a.b})}return b.hex};m.getColor.reset=function(){delete this.start};var ub=/([achlmqstvz])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig, +vb=/(-?\d*\.?\d*(?:e[-+]?\d+)?)\s*,?\s*/ig;m.parsePathString=T(function(a){if(!a)return null;var b={a:7,c:6,h:1,l:2,m:2,q:4,s:4,t:2,v:1,z:0},c=[];if(m.is(a,U)&&m.is(a[0],U))c=ta(a);c[o]||(a+s)[I](ub,function(d,f,e){var g=[];d=ca.call(f);e[I](vb,function(h,i){i&&g[E](+i)});if(d=="m"&&g[o]>2){c[E]([f][M](g.splice(0,2)));d="l";f=f=="m"?"l":"L"}for(;g[o]>=b[d];){c[E]([f][M](g.splice(0,b[d])));if(!b[d])break}});c[N]=m._path2string;return c});m.findDotsAtSegment=function(a,b,c,d,f,e,g,h,i){var j=1-i,l= +D(j,3)*a+D(j,2)*3*i*c+j*3*i*i*f+D(i,3)*g;j=D(j,3)*b+D(j,2)*3*i*d+j*3*i*i*e+D(i,3)*h;var n=a+2*i*(c-a)+i*i*(f-2*c+a),r=b+2*i*(d-b)+i*i*(e-2*d+b),q=c+2*i*(f-c)+i*i*(g-2*f+c),k=d+2*i*(e-d)+i*i*(h-2*e+d);a=(1-i)*a+i*c;b=(1-i)*b+i*d;f=(1-i)*f+i*g;e=(1-i)*e+i*h;h=90-w.atan((n-q)/(r-k))*180/w.PI;(n>q||r1){B=w.sqrt(B);c=B*c;d=B*d}B=c*c;var L=d*d;B=(e==g?-1:1)*w.sqrt(w.abs((B*L-B*x*x-L*k*k)/(B*x*x+L*k*k)));e=B*c*x/d+(a+h)/2;var B= +B*-d*k/c+(b+i)/2,x=w.asin(((b-B)/d).toFixed(7));k=w.asin(((i-B)/d).toFixed(7));x=ak)x-=l*2;if(!g&&k>x)k-=l*2}l=k-x;if(w.abs(l)>n){q=k;l=h;L=i;k=x+n*(g&&k>x?1:-1);h=e+c*w.cos(k);i=B+d*w.sin(k);q=Qa(h,i,c,d,f,0,g,l,L,[k,q,e,B])}l=k-x;f=w.cos(x);e=w.sin(x);g=w.cos(k);k=w.sin(k);l=w.tan(l/4);c=4/3*c*l;l=4/3*d*l;d=[a,b];a=[a+c*e,b-l*f];b=[h+c*k,i-l*g];h=[h,i];a[0]=2*d[0]-a[0];a[1]=2*d[1]-a[1];if(j)return[a,b,h][M](q);else{q=[a,b,h][M](q)[Q]()[H](","); +j=[];h=0;for(i=q[o];h1000000000000&&(n=0.5);w.abs(i)>1000000000000&&(i=0.5);if(n>0&&n<1){n=la(a,b,c,d,f,e,g,h,n);q[E](n.x);r[E](n.y)}if(i> +0&&i<1){n=la(a,b,c,d,f,e,g,h,i);q[E](n.x);r[E](n.y)}i=e-2*d+b-(h-2*e+d);j=2*(d-b)-2*(e-d);l=b-d;n=(-j+w.sqrt(j*j-4*i*l))/2/i;i=(-j-w.sqrt(j*j-4*i*l))/2/i;w.abs(n)>1000000000000&&(n=0.5);w.abs(i)>1000000000000&&(i=0.5);if(n>0&&n<1){n=la(a,b,c,d,f,e,g,h,n);q[E](n.x);r[E](n.y)}if(i>0&&i<1){n=la(a,b,c,d,f,e,g,h,i);q[E](n.x);r[E](n.y)}return{min:{x:$[K](0,q),y:$[K](0,r)},max:{x:Y[K](0,q),y:Y[K](0,r)}}}),ua=T(function(a,b){var c=ka(a),d=b&&ka(b);a={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null};b={x:0,y:0, +bx:0,by:0,X:0,Y:0,qx:null,qy:null};function f(q,k){var t;if(!q)return["C",k.x,k.y,k.x,k.y,k.x,k.y];!(q[0]in{T:1,Q:1})&&(k.qx=k.qy=null);switch(q[0]){case "M":k.X=q[1];k.Y=q[2];break;case "A":q=["C"][M](Qa[K](0,[k.x,k.y][M](q.slice(1))));break;case "S":t=k.x+(k.x-(k.bx||k.x));k=k.y+(k.y-(k.by||k.y));q=["C",t,k][M](q.slice(1));break;case "T":k.qx=k.x+(k.x-(k.qx||k.x));k.qy=k.y+(k.y-(k.qy||k.y));q=["C"][M](Pa(k.x,k.y,k.qx,k.qy,q[1],q[2]));break;case "Q":k.qx=q[1];k.qy=q[2];q=["C"][M](Pa(k.x,k.y,q[1], +q[2],q[3],q[4]));break;case "L":q=["C"][M](wa(k.x,k.y,q[1],q[2]));break;case "H":q=["C"][M](wa(k.x,k.y,q[1],k.y));break;case "V":q=["C"][M](wa(k.x,k.y,k.x,q[1]));break;case "Z":q=["C"][M](wa(k.x,k.y,k.X,k.Y));break}return q}function e(q,k){if(q[k][o]>7){q[k].shift();for(var t=q[k];t[o];)q.splice(k++,0,["C"][M](t.splice(0,6)));q.splice(k,1);i=Y(c[o],d&&d[o]||0)}}function g(q,k,t,L,B){if(q&&k&&q[B][0]=="M"&&k[B][0]!="M"){k.splice(B,0,["M",L.x,L.y]);t.bx=0;t.by=0;t.x=q[B][1];t.y=q[B][2];i=Y(c[o],d&& +d[o]||0)}}for(var h=0,i=Y(c[o],d&&d[o]||0);h0.5)*2-1;D(f-0.5,2)+D(e-0.5,2)>0.25&&(e=w.sqrt(0.25-D(f-0.5,2))*l+0.5)&&e!=0.5&&(e=e.toFixed(5)-1.0E-5*l)}return s});b=b[H](/\s*\-\s*/);if(d=="linear"){var h=b.shift();h=-A(h);if(isNaN(h))return null;h=[0,0,w.cos(h*w.PI/180),w.sin(h*w.PI/180)];var i=1/(Y(w.abs(h[2]),w.abs(h[3]))||1);h[2]*=i;h[3]*=i;if(h[2]<0){h[0]=-h[2];h[2]=0}if(h[3]<0){h[1]=-h[3];h[3]=0}}b=Ra(b);if(!b)return null; +i=a.getAttribute(aa);(i=i.match(/^url\(#(.*)\)$/))&&c.defs.removeChild(C.getElementById(i[1]));i=v(d+"Gradient");i.id="r"+(m._id++)[N](36);v(i,d=="radial"?{fx:f,fy:e}:{x1:h[0],y1:h[1],x2:h[2],y2:h[3]});c.defs[y](i);c=0;for(h=b[o];cb.height&&(b.height=e.y+e.height-b.y);e.x+e.width-b.x>b.width&&(b.width=e.x+e.width-b.x)}}a&&this.hide();return b};u[p].attr=function(a,b){if(this.removed)return this;if(a==null){a={};for(var c in this.attrs)if(this.attrs[z](c))a[c]=this.attrs[c];this._.rt.deg&&(a.rotation=this.rotate());(this._.sx!=1||this._.sy!= +1)&&(a.scale=this.scale());a.gradient&&a.fill=="none"&&(a.fill=a.gradient)&&delete a.gradient;return a}if(b==null&&m.is(a,ea)){if(a=="translation")return ya.call(this);if(a=="rotation")return this.rotate();if(a=="scale")return this.scale();if(a==aa&&this.attrs.fill=="none"&&this.attrs.gradient)return this.attrs.gradient;return this.attrs[a]}if(b==null&&m.is(a,U)){b={};c=0;for(var d=a.length;c1&&(a=1);f.opacity=a}b.fill&&(f.on=true);if(f.on==null||b.fill=="none")f.on=false;if(f.on&&b.fill)if(a=b.fill.match(Na)){f.src=a[1];f.type="tile"}else{f.color=m.getRGB(b.fill).hex;f.src= +s;f.type="solid";if(m.getRGB(b.fill).error&&(g.type in{circle:1,ellipse:1}||(b.fill+s).charAt()!="r")&&ma(g,b.fill)){d.fill="none";d.gradient=b.fill}}e&&c[y](f);f=c.getElementsByTagName("stroke")&&c.getElementsByTagName("stroke")[0];e=false;!f&&(e=f=R("stroke"));if(b.stroke&&b.stroke!="none"||b["stroke-width"]||b["stroke-opacity"]!=null||b["stroke-dasharray"]||b["stroke-miterlimit"]||b["stroke-linejoin"]||b["stroke-linecap"])f.on=true;(b.stroke=="none"||f.on==null||b.stroke==0||b["stroke-width"]== +0)&&(f.on=false);a=m.getRGB(b.stroke);f.on&&b.stroke&&(f.color=a.hex);a=((+d["stroke-opacity"]+1||2)-1)*((+d.opacity+1||2)-1)*((+a.o+1||2)-1);h=(A(b["stroke-width"])||1)*0.75;a<0&&(a=0);a>1&&(a=1);b["stroke-width"]==null&&(h=d["stroke-width"]);b["stroke-width"]&&(f.weight=h);h&&h<1&&(a*=h)&&(f.weight=1);f.opacity=a;b["stroke-linejoin"]&&(f.joinstyle=b["stroke-linejoin"]||"miter");f.miterlimit=b["stroke-miterlimit"]||8;b["stroke-linecap"]&&(f.endcap=b["stroke-linecap"]=="butt"?"flat":b["stroke-linecap"]== +"square"?"square":"round");if(b["stroke-dasharray"]){a={"-":"shortdash",".":"shortdot","-.":"shortdashdot","-..":"shortdashdotdot",". ":"dot","- ":"dash","--":"longdash","- .":"dashdot","--.":"longdashdot","--..":"longdashdotdot"};f.dashstyle=a[z](b["stroke-dasharray"])?a[b["stroke-dasharray"]]:s}e&&c[y](f)}if(g.type=="text"){f=g.paper.span.style;d.font&&(f.font=d.font);d["font-family"]&&(f.fontFamily=d["font-family"]);d["font-size"]&&(f.fontSize=d["font-size"]);d["font-weight"]&&(f.fontWeight=d["font-weight"]); +d["font-style"]&&(f.fontStyle=d["font-style"]);g.node.string&&(g.paper.span.innerHTML=(g.node.string+s)[I](/"));g.W=d.w=g.paper.span.offsetWidth;g.H=d.h=g.paper.span.offsetHeight;g.X=d.x;g.Y=d.y+F(g.H/2);switch(d["text-anchor"]){case "start":g.node.style["v-text-align"]="left";g.bbx=F(g.W/2);break;case "end":g.node.style["v-text-align"]="right";g.bbx=-F(g.W/2);break;default:g.node.style["v-text-align"]="center";break}}};ma=function(a,b){a.attrs=a.attrs|| +{};var c="linear",d=".5 .5";a.attrs.gradient=b;b=(b+s)[I](Ya,function(i,j,l){c="radial";if(j&&l){j=A(j);l=A(l);D(j-0.5,2)+D(l-0.5,2)>0.25&&(l=w.sqrt(0.25-D(j-0.5,2))*((l>0.5)*2-1)+0.5);d=j+P+l}return s});b=b[H](/\s*\-\s*/);if(c=="linear"){var f=b.shift();f=-A(f);if(isNaN(f))return null}var e=Ra(b);if(!e)return null;a=a.shape||a.node;b=a.getElementsByTagName(aa)[0]||R(aa);!b.parentNode&&a.appendChild(b);if(e[o]){b.on=true;b.method="none";b.color=e[0].color;b.color2=e[e[o]-1].color;a=[];for(var g=0, +h=e[o];g')}}catch(Kb){R=function(a){return C.createElement("<"+a+' xmlns="urn:schemas-microsoft.com:vml" class="rvml">')}}Aa=function(){var a=Sa[K](0,arguments),b=a.container,c=a.height,d=a.width,f=a.x;a=a.y;if(!b)throw new Error("VML container not found.");var e=new G,g=e.canvas=C.createElement("div"),h=g.style;f=f||0;a=a||0;d=d||512; +c=c||342;d==+d&&(d+="px");c==+c&&(c+="px");e.width=1000;e.height=1000;e.coordsize=ja*1000+P+ja*1000;e.coordorigin="0 0";e.span=C.createElement("span");e.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";g[y](e.span);h.cssText=m.format("width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden",d,c);if(b==1){C.body[y](g);h.left=f+"px";h.top=a+"px";h.position="absolute"}else b.firstChild?b.insertBefore(g, +b.firstChild):b[y](g);Fa.call(e,e,m.fn);return e};G[p].clear=function(){this.canvas.innerHTML=s;this.span=C.createElement("span");this.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";this.canvas[y](this.span);this.bottom=this.top=null};G[p].remove=function(){this.canvas.parentNode.removeChild(this.canvas);for(var a in this)this[a]=Xa(a);return true}}G[p].safari=/^Apple|^Google/.test(X.navigator.vendor)&&(!(X.navigator.userAgent.indexOf("Version/4.0")+ +1)||X.navigator.platform.slice(0,2)=="iP")?function(){var a=this.rect(-99,-99,this.width+99,this.height+99);X.setTimeout(function(){a.remove()})}:function(){};function Db(){this.returnValue=false}function Eb(){return this.originalEvent.preventDefault()}function Fb(){this.cancelBubble=true}function Gb(){return this.originalEvent.stopPropagation()}var Hb=function(){if(C.addEventListener)return function(a,b,c,d){var f=Ba&&Ca[b]?Ca[b]:b;function e(g){if(Ba&&Ca[z](b))for(var h=0,i=g.targetTouches&&g.targetTouches.length;h< +i;h++)if(g.targetTouches[h].target==a){i=g;g=g.targetTouches[h];g.originalEvent=i;g.preventDefault=Eb;g.stopPropagation=Gb;break}return c.call(d,g)}a.addEventListener(f,e,false);return function(){a.removeEventListener(f,e,false);return true}};else if(C.attachEvent)return function(a,b,c,d){function f(g){g=g||X.event;g.preventDefault=g.preventDefault||Db;g.stopPropagation=g.stopPropagation||Fb;return c.call(d,g)}a.attachEvent("on"+b,f);function e(){a.detachEvent("on"+b,f);return true}return e}}();for(ha= +Ma[o];ha--;)(function(a){m[a]=u[p][a]=function(b){if(m.is(b,"function")){this.events=this.events||[];this.events.push({name:a,f:b,unbind:Hb(this.shape||this.node||C,a,b,this)})}return this};m["un"+a]=u[p]["un"+a]=function(b){for(var c=this.events,d=c[o];d--;)if(c[d].name==a&&c[d].f==b){c[d].unbind();c.splice(d,1);!c.length&&delete this.events;return this}return this}})(Ma[ha]);u[p].hover=function(a,b){return this.mouseover(a).mouseout(b)};u[p].unhover=function(a,b){return this.unmouseover(a).unmouseout(b)}; +u[p].drag=function(a,b,c){this._drag={};var d=this.mousedown(function(g){(g.originalEvent?g.originalEvent:g).preventDefault();this._drag.x=g.clientX;this._drag.y=g.clientY;this._drag.id=g.identifier;b&&b.call(this,g.clientX,g.clientY);Raphael.mousemove(f).mouseup(e)});function f(g){var h=g.clientX,i=g.clientY;if(Ba)for(var j=g.touches.length,l;j--;){l=g.touches[j];if(l.identifier==d._drag.id){h=l.clientX;i=l.clientY;(g.originalEvent?g.originalEvent:g).preventDefault();break}}else g.preventDefault(); +a&&a.call(d,h-d._drag.x,i-d._drag.y,h,i)}function e(){d._drag={};Raphael.unmousemove(f).unmouseup(e);c&&c.call(d)}return this};G[p].circle=function(a,b,c){return ab(this,a||0,b||0,c||0)};G[p].rect=function(a,b,c,d,f){return bb(this,a||0,b||0,c||0,d||0,f||0)};G[p].ellipse=function(a,b,c,d){return cb(this,a||0,b||0,c||0,d||0)};G[p].path=function(a){a&&!m.is(a,ea)&&!m.is(a[0],U)&&(a+=s);return Za(m.format[K](m,arguments),this)};G[p].image=function(a,b,c,d,f){return db(this,a||"about:blank",b||0,c||0, +d||0,f||0)};G[p].text=function(a,b,c){return eb(this,a||0,b||0,c||s)};G[p].set=function(a){arguments[o]>1&&(a=Array[p].splice.call(arguments,0,arguments[o]));return new Z(a)};G[p].setSize=fb;G[p].top=G[p].bottom=null;G[p].raphael=m;function ib(){return this.x+P+this.y}u[p].resetScale=function(){if(this.removed)return this;this._.sx=1;this._.sy=1;this.attrs.scale="1 1"};u[p].scale=function(a,b,c,d){if(this.removed)return this;if(a==null&&b==null)return{x:this._.sx,y:this._.sy,toString:ib};b=b||a;!+b&& +(b=a);var f,e,g=this.attrs;if(a!=0){var h=this.getBBox(),i=h.x+h.width/2,j=h.y+h.height/2;f=a/this._.sx;e=b/this._.sy;c=+c||c==0?c:i;d=+d||d==0?d:j;h=~~(a/w.abs(a));var l=~~(b/w.abs(b)),n=this.node.style,r=c+(i-c)*f;j=d+(j-d)*e;switch(this.type){case "rect":case "image":var q=g.width*h*f,k=g.height*l*e;this.attr({height:k,r:g.r*$(h*f,l*e),width:q,x:r-q/2,y:j-k/2});break;case "circle":case "ellipse":this.attr({rx:g.rx*h*f,ry:g.ry*l*e,r:g.r*$(h*f,l*e),cx:r,cy:j});break;case "text":this.attr({x:r,y:j}); +break;case "path":i=Oa(g.path);for(var t=true,L=0,B=i[o];L=i)return r;l=r}});function Ha(a,b){return function(c,d,f){c=ua(c); +for(var e,g,h,i,j="",l={},n=0,r=0,q=c.length;rd){if(b&&!l.start){e=jb(e,g,h[1],h[2],h[3],h[4],h[5],h[6],d-n);j+=["C",e.start.x,e.start.y,e.m.x,e.m.y,e.x,e.y];if(f)return j;l.start=j;j=["M",e.x,e.y+"C",e.n.x,e.n.y,e.end.x,e.end.y,h[5],h[6]][Q]();n+=i;e=+h[5];g=+h[6];continue}if(!a&&!b){e=jb(e,g,h[1],h[2],h[3],h[4],h[5],h[6],d-n);return{x:e.x,y:e.y,alpha:e.alpha}}}n+=i;e=+h[5];g=+h[6]}j+=h}l.end=j;e=a?n: +b?l:m.findDotsAtSegment(e,g,h[1],h[2],h[3],h[4],h[5],h[6],1);e.alpha&&(e={x:e.x,y:e.y,alpha:e.alpha});return e}}var Ib=T(function(a,b,c,d,f,e,g,h){for(var i={x:0,y:0},j=0,l=0;l<1.01;l+=0.01){var n=la(a,b,c,d,f,e,g,h,l);l&&(j+=D(D(i.x-n.x,2)+D(i.y-n.y,2),0.5));i=n}return j}),kb=Ha(1),za=Ha(),Ia=Ha(0,1);u[p].getTotalLength=function(){if(this.type=="path"){if(this.node.getTotalLength)return this.node.getTotalLength();return kb(this.attrs.path)}};u[p].getPointAtLength=function(a){if(this.type=="path")return za(this.attrs.path, +a)};u[p].getSubpath=function(a,b){if(this.type=="path"){if(w.abs(this.getTotalLength()-b)<1.0E-6)return Ia(this.attrs.path,a).end;b=Ia(this.attrs.path,b,1);return a?Ia(b,a).end:b}};m.easing_formulas={linear:function(a){return a},"<":function(a){return D(a,3)},">":function(a){return D(a-1,3)+1},"<>":function(a){a*=2;if(a<1)return D(a,3)/2;a-=2;return(D(a,3)+2)/2},backIn:function(a){var b=1.70158;return a*a*((b+1)*a-b)},backOut:function(a){a-=1;var b=1.70158;return a*a*((b+1)*a+b)+1},elastic:function(a){if(a== +0||a==1)return a;var b=0.3,c=b/4;return D(2,-10*a)*w.sin((a-c)*2*w.PI/b)+1},bounce:function(a){var b=7.5625,c=2.75;if(a<1/c)a=b*a*a;else if(a<2/c){a-=1.5/c;a=b*a*a+0.75}else if(a<2.5/c){a-=2.25/c;a=b*a*a+0.9375}else{a-=2.625/c;a=b*a*a+0.984375}return a}};var S={length:0};function lb(){var a=+new Date;for(var b in S)if(b!="length"&&S[z](b)){var c=S[b];if(c.stop||c.el.removed){delete S[b];S[o]--}else{var d=a-c.start,f=c.ms,e=c.easing,g=c.from,h=c.diff,i=c.to,j=c.t,l=c.prev||0,n=c.el,r=c.callback,q= +{},k;if(d p:first-child{ + margin-top:0; +} +#facebox .content > p:last-child{ + margin-bottom:0; +} + +#facebox .close{ + position:absolute; + top:5px; + right:5px; + padding:2px; + background:#fff; +} +#facebox .close img{ + opacity:0.3; +} +#facebox .close:hover img{ + opacity:1.0; +} + +#facebox .loading { + text-align: center; +} + +#facebox .image { + text-align: center; +} + +#facebox img { + border: 0; + margin: 0; +} + +#facebox_overlay { + position: fixed; + top: 0px; + left: 0px; + height:100%; + width:100%; +} + +.facebox_hide { + z-index:-100; +} + +.facebox_overlayBG { + background-color: #000; + z-index: 99; +} +.facebox-footnote{ + margin-top:40px; +} \ No newline at end of file diff --git a/tryruby/public/stylesheets/reset.css b/tryruby/public/stylesheets/reset.css new file mode 100644 index 0000000..d709810 --- /dev/null +++ b/tryruby/public/stylesheets/reset.css @@ -0,0 +1,46 @@ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, font, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td { + margin: 0; + padding: 0; + border: 0; + outline: 0; + font-weight: inherit; + font-style: inherit; + font-size: 100%; + font-family: inherit; + vertical-align: baseline; +} +/* remember to define focus styles! */ +:focus { + outline: 0; +} +body { + line-height: 1; + color: black; + background: white; +} +ol, ul { + list-style: none; +} +/* tables still need 'cellspacing="0"' in the markup */ +table { + border-collapse: separate; + border-spacing: 0; +} +caption, th, td { + text-align: left; + font-weight: normal; +} +blockquote:before, blockquote:after, +q:before, q:after { + content: ""; +} +blockquote, q { + quotes: "" ""; +} diff --git a/tryruby/public/stylesheets/scaffold.css b/tryruby/public/stylesheets/scaffold.css new file mode 100644 index 0000000..1ae7000 --- /dev/null +++ b/tryruby/public/stylesheets/scaffold.css @@ -0,0 +1,56 @@ +body { background-color: #fff; color: #333; } + +body, p, ol, ul, td { + font-family: verdana, arial, helvetica, sans-serif; + font-size: 13px; + line-height: 18px; +} + +pre { + background-color: #eee; + padding: 10px; + font-size: 11px; +} + +a { color: #000; } +a:visited { color: #666; } +a:hover { color: #fff; background-color:#000; } + +div.field, div.actions { + margin-bottom: 10px; +} + +#notice { + color: green; +} + +.field_with_errors { + padding: 2px; + background-color: red; + display: table; +} + +#error_explanation { + width: 450px; + border: 2px solid red; + padding: 7px; + padding-bottom: 0; + margin-bottom: 20px; + background-color: #f0f0f0; +} + +#error_explanation h2 { + text-align: left; + font-weight: bold; + padding: 5px 5px 5px 15px; + font-size: 12px; + margin: -7px; + margin-bottom: 0px; + background-color: #c00; + color: #fff; +} + +#error_explanation ul li { + font-size: 12px; + list-style: square; +} diff --git a/tryruby/public/stylesheets/site.css b/tryruby/public/stylesheets/site.css new file mode 100755 index 0000000..62b1526 --- /dev/null +++ b/tryruby/public/stylesheets/site.css @@ -0,0 +1,378 @@ +body { + font-family: verdana, arial, sans-serif; + font-size: 14px; + text-align: center; +} +h1, h2, h3, h4 { + font-family: georgia, serif; + margin: 10px 45px; padding: 0; +} +h1 { + color: #333; + font-size: 48px; + font-weight: normal; + margin: 10px 0px; +} +h3 { + color: white; + font-size: 21px; + font-weight: normal; +} +a,a:link,a:visited { + text-decoration: none; + color: #57ad11; +} +a:hover { + text-decoration: underline; + color: #57ad11; +} +a:active { + text-decoration: underline; + color: #dddddd; +} +input.keyboard-selector-input { + position: fixed; + top: 0; + _position: absolute; + _top: expression(eval(document.body.scrollTop)); + left: -300px; +} +.container { + width: 678px; + margin: 0 auto; + text-align: left; +} +.content { + width: 712px; + background: url(/images/tile.png) repeat-y; +} +#lilBrowser { + position: absolute; + background-color: white; + top: -540px; + left: -440px; + width: 510px; + height: 430px; + padding: 5px; + border: solid 1px #444; + z-index: 100; +} +h3#lbTitle { + color: #444; + font-family: verdana, arial, sans-serif; + font-size: small; + float:left; + line-height: 90%; + margin: 0; padding: 3px; +} +p#lbClose { + font-size: small; + float: right; + margin: 0; padding: 3px; +} +p#lbClose a { + display: inline; +} +.shellwin { + width: 712px; + padding-left: 12px; + background: url(/images/background.png) no-repeat; +} + +/* tutorial panes */ +.stretcher { + color: #f1f1ff; + display: none; + margin: 0; + padding: 0; + padding-left: 12px; + background: url(/images/tile.png) repeat-y; +} +.stretcher a, .stretcher a:link, .stretcher a:visited, .stretcher a:active { + text-decoration: none; + color: #a7ed91; +} +.stretcher a:hover { + text-decoration: underline; + color: #b7fd91; +} +.stretcher p { + margin: 10px 16px; +} +.stretcher dl, .stretcher ul { + background-color: white; + color: #333; + padding: 4px 8px; + font-size: 12px; + margin-left: 16px; + list-style: none; +} +.stretcher li { + margin: 6px; +} +.stretcher p code { + background-color: #874a20; + color: #fedeec; + padding: 1px 4px; +} +.stretcher p code.cmd { + background-color: #eeeeec; + color: #204a87; +} +.stretcher dt { + font-weight: bold; +} + +.chapmark { + padding: 6px 0; + margin-left: 12px; + margin-right: 22px; + color: #553; + background: #efefe1; +} +.chapmark h3 { + color: #335; +} +.chapmark a, .chapmark a:link, .chapmark a:visited, .chapmark a:active { + text-decoration: none; + color: #372d61; +} +.chapmark a:hover { + text-decoration: underline; + color: #477d51; +} +.note { color: #ddc; text-align: center; font-size: xx-small; } +ul li strong { color: #286; border-bottom: solid 2px #cca; } +ul li code { background-color: #f1f1f1; padding: 1px 3px; border-bottom: solid 2px #ddd; } +ul li code.faded { color: #899; } +code strong { background-color: #dcffb9; padding: 1px 3px; } +ul.commands li strong { display: block; float: left; width: 60px; border: none; } + +/* irb terminal */ +.terminal { + background-color: #ffffff; + border: solid 1px #204a87; + width: 678px; + height: 240px; + overflow: auto; +} +.console { + padding: 4px; margin-left: -50px; + font-family: "Andale Mono", courier, fixed, monospace; + font-size: 14px; + line-height: 16px; + color: #204a87; + text-align: left; + width: 664px; + height:220px; +} + +.console div b { + background-color: #874a20; + color: #fedeac; +} +div.answer, div.stdout, div.no_answer, div.load { + display: none; +} + +/* terminal escape colors */ +span.fore_black { color: #2e3436; } +span.fore_dark_gray { color: #888a85; } +span.fore_gray { color: #babdb6; } +span.fore_white { color: #eeeeec; } +span.fore_blue { color: #204a87; } +span.fore_lt_blue { color: #729fcf; } +span.fore_green { color: #788600; font-weight: bold; } +span.fore_lt_green { color: #cbe134; } +span.fore_cyan { color: #c4a000; } /* using cyan for yellows */ +span.fore_lt_cyan { color: #fc994f; } +span.fore_red { color: #a40000; } +span.fore_lt_red { color: #ef2929; font-weight: bold; } +span.fore_purple { color: #5c3566; } +span.fore_lt_purple { color: #ad7fa8; } +span.fore_brown { color: #8f5972; } +span.fore_lt_brown { color: #b9b9de; } +span.back_black { background-color: #2e3436; } +span.back_dark_gray { background-color: #888a85; } +span.back_gray { background-color: #babdb6; } +span.back_white { background-color: #eeeeec; } +span.back_blue { background-color: #204a87; } +span.back_lt_blue { background-color: #729fcf; } +span.back_green { background-color: #788600; } +span.back_lt_green { background-color: #cbe134; } +span.back_cyan { background-color: #c4a000; } /* using cyan for yellows */ +span.back_lt_cyan { background-color: #fce94f; } +span.back_red { background-color: #a40000; } +span.back_lt_red { background-color: #ef2929; } +span.back_purple { background-color: #5c3566; } +span.back_lt_purple { background-color: #ad7fa8; } +span.back_brown { background-color: #8f5902; } +span.back_lt_brown { background-color: #b9b96e; } + +/** no ways***/ + +div.main-wrapper-bottom { + height:4px;background-position: 0px -80px; background-repeat: no-repeat; + font-size:0 /* IE6, go figure */ +} +div.main-wrapper-borders { + background-position: -1731px 0; padding:15px; + background-repeat:repeat-y; +} +div.console-wrapper { + margin:0px auto ;width:566px; + cursor:text; + font-family:monospace; +} +div.console-wrapper-top { + height:3px;background-position: -50px -48px; background-repeat: no-repeat; + font-size:0 /* IE6, go figure */ +} +div.console-wrapper-bottom { + height:3px;background-position: -50px -51px; background-repeat: no-repeat; + font-size:0 /* IE6, go figure */ +} +div.console-wrapper-borders { + background-position: 0px 0px; padding:1px; + background-repeat:repeat-y; +} +div.guide-wrapper { + color:#fff; width:566px;margin-left:2px +} +div.guide-wrapper-top { + height:4px;background-position: 0 -65px; + font-size:0 /* IE6, go figure */ +} +div.guide-wrapper-bottom { + height:4px;background-position: 0 -70px; + font-size:0 /* IE6, go figure */ +} +div.guide-wrapper-borders { + background-position: -1166px 0px;padding:15px; + background-repeat:repeat-y; +} + +div.footer-wrapper-borders { + background-position: -566px 0px; padding:10px; + background-repeat:repeat-y; + font-size:12px +} +h1.main-header { + text-indent:-9999px; background-position: -49px 0px; + background-repeat: no-repeat; + width:318px; height:48px; margin-bottom:20px; + float:left +} + +div.footer { + line-height: 1.3em; +} + div.console div.jquery-console-inner +{ height:100%; overflow:auto; background:white} +div.console div.jquery-console-prompt-box +{ color:#437375; font-family:monospace; margin-top:0.5em; } +div.console div.jquery-console-prompt-box .prompt-done +{ cursor: pointer } +div.console div.jquery-console-prompt-box .prompt-done:hover +{ background:#453D5B; color: white; } +div.console div.jquery-console-focus span.jquery-console-cursor +{ background:#666; color:#fff; } +div.console div.jquery-console-message-error { + color:#ef0505; font-family:sans-serif; font-weight:bold; + padding-top:0.25em +} +div.console div.jquery-console-message-value +{ color:#000; font-family:monospace;padding-top:0.25em; font-weight: bold; } +div.console div.jquery-console-message-type +{ color:#382567; font-family:monospace;padding-left:0em;padding-top:0.25em; font-size:.9em } +div.console span.jquery-console-prompt-label { font-weight:bold } +div.console div.jquery-console-welcome { font-family:"DejaVu Sans",sans-serif; } + +div.share-wrapper { font-size:12px;padding:10px 0em 0em 10px } +div.share-wrapper strong { font-weight: bold } + +.clearfix:after { content:"."; display:block; height:0; clear:both; visibility:hidden } +div.menu { + float:right; + margin-right:2px; + margin-top:40px; + margin-bottom:5px +} +a.reset-btn { + float:left; + display:block; + width:59px; + height:24px; + background-position: -427px -18px; background-repeat: no-repeat; +} +a.reset-btn span { display:none } + +div.clear { clear:both } + + +div.console-wrapper .notice { + position:absolute; + bottom:0;right:0; + margin:1px; + background:#eee; + color:black; + padding:10px; + font-size:12px; + font-family:sans-serif; + font-weight:bold; +} +p.ajax-loader { background:url(../images/ajax-loader.gif); width:16px; height:16px;text-indent:-9999px } + +.notice a { padding:3px;background:#333;color:white} +.notice .action { text-align: right } + +/* Support Try Ruby! */ + + +a.trigger{ +position: absolute; +text-decoration: none; +top: 80px; right: 0; +font-size: 14px; +letter-spacing:-1px; +font-family: verdana, helvetica, arial, sans-serif; +color:#fff; +padding: 10px 10px 10px 10px; +font-weight: 500; +background:#333333 url(images/plus.png) 15% 55% no-repeat; +border:1px solid #444444; +-moz-border-radius-topleft: 20px; +-webkit-border-top-left-radius: 20px; +-moz-border-radius-bottomleft: 20px; +-webkit-border-bottom-left-radius: 20px; +-moz-border-radius-bottomright: 0px; +-webkit-border-bottom-right-radius: 0px; +display: block; +} + +a.trigger:hover{ +position: absolute; +text-decoration: none; +top: 80px; right: 0; +font-size: 14px; +letter-spacing:-1px; +font-family: verdana, helvetica, arial, sans-serif; +color:#fff; +padding: 10px 10px 10px 10px; +font-weight: 500; +background: green; +border:1px solid #444444; +-moz-border-radius-topleft: 20px; +-webkit-border-top-left-radius: 20px; +-moz-border-radius-bottomleft: 20px; +-webkit-border-bottom-left-radius: 20px; +-moz-border-radius-bottomright: 0px; +-webkit-border-bottom-right-radius: 0px; +display: block; +} + +a.active.trigger { +background:#222222 url(images/minus.png) 15% 55% no-repeat; +} + + \ No newline at end of file diff --git a/tryruby/script/rails b/tryruby/script/rails new file mode 100755 index 0000000..f8da2cf --- /dev/null +++ b/tryruby/script/rails @@ -0,0 +1,6 @@ +#!/usr/bin/env ruby +# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. + +APP_PATH = File.expand_path('../../config/application', __FILE__) +require File.expand_path('../../config/boot', __FILE__) +require 'rails/commands' diff --git a/tryruby/test/functional/index_controller_test.rb b/tryruby/test/functional/index_controller_test.rb new file mode 100644 index 0000000..005acb0 --- /dev/null +++ b/tryruby/test/functional/index_controller_test.rb @@ -0,0 +1,9 @@ +require 'test_helper' + +class IndexControllerTest < ActionController::TestCase + test "should get terminal" do + get :terminal + assert_response :success + end + +end diff --git a/tryruby/test/functional/tutorials_controller_test.rb b/tryruby/test/functional/tutorials_controller_test.rb new file mode 100644 index 0000000..937e313 --- /dev/null +++ b/tryruby/test/functional/tutorials_controller_test.rb @@ -0,0 +1,9 @@ +require 'test_helper' + +class TutorialsControllerTest < ActionController::TestCase + test "should get intro" do + get :intro + assert_response :success + end + +end diff --git a/tryruby/test/performance/browsing_test.rb b/tryruby/test/performance/browsing_test.rb new file mode 100644 index 0000000..867fc8c --- /dev/null +++ b/tryruby/test/performance/browsing_test.rb @@ -0,0 +1,9 @@ +require 'test_helper' +require 'rails/performance_test_help' + +# Profiling results for each test method are written to tmp/performance. +class BrowsingTest < ActionDispatch::PerformanceTest + def test_homepage + get '/' + end +end diff --git a/tryruby/test/test_helper.rb b/tryruby/test/test_helper.rb new file mode 100644 index 0000000..8bf1192 --- /dev/null +++ b/tryruby/test/test_helper.rb @@ -0,0 +1,13 @@ +ENV["RAILS_ENV"] = "test" +require File.expand_path('../../config/environment', __FILE__) +require 'rails/test_help' + +class ActiveSupport::TestCase + # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order. + # + # Note: You'll currently still have to declare fixtures explicitly in integration tests + # -- they do not yet inherit this setting + fixtures :all + + # Add more helper methods to be used by all tests here... +end diff --git a/tryruby/test/unit/helpers/index_helper_test.rb b/tryruby/test/unit/helpers/index_helper_test.rb new file mode 100644 index 0000000..104f529 --- /dev/null +++ b/tryruby/test/unit/helpers/index_helper_test.rb @@ -0,0 +1,4 @@ +require 'test_helper' + +class IndexHelperTest < ActionView::TestCase +end diff --git a/tryruby/test/unit/helpers/tutorials_helper_test.rb b/tryruby/test/unit/helpers/tutorials_helper_test.rb new file mode 100644 index 0000000..dae016c --- /dev/null +++ b/tryruby/test/unit/helpers/tutorials_helper_test.rb @@ -0,0 +1,4 @@ +require 'test_helper' + +class TutorialsHelperTest < ActionView::TestCase +end diff --git a/tryruby/vendor/plugins/.gitkeep b/tryruby/vendor/plugins/.gitkeep new file mode 100644 index 0000000..e69de29 From cda2de24a92e8fbbcf7b26b9d4a0a58b6374f757 Mon Sep 17 00:00:00 2001 From: Andrew McElroy Date: Fri, 8 Jul 2011 18:18:54 -0500 Subject: [PATCH 10/16] non rack legacy is in the legacy branch. i will clean up branches soon. I am trying to make try ruby heroku friendly --- non-rack-legacy/public/.gitignore | 2 - non-rack-legacy/public/blank.html | 4 - non-rack-legacy/public/comics.txt | 4 - non-rack-legacy/public/es_index.html | 96 - non-rack-legacy/public/images/background.png | Bin 35315 -> 0 bytes non-rack-legacy/public/images/footer.png | Bin 6840 -> 0 bytes non-rack-legacy/public/images/header.png | Bin 51873 -> 0 bytes non-rack-legacy/public/images/tile.png | Bin 305 -> 0 bytes non-rack-legacy/public/index.html | 166 -- non-rack-legacy/public/irb.cgi | 38 - .../public/javascripts/application.js | 2 - non-rack-legacy/public/javascripts/console.js | 288 --- .../public/javascripts/controls.js | 963 ---------- .../public/javascripts/dragdrop.js | 973 ---------- non-rack-legacy/public/javascripts/effects.js | 1128 ----------- non-rack-legacy/public/javascripts/facebox.js | 309 ---- non-rack-legacy/public/javascripts/index.html | 8 - non-rack-legacy/public/javascripts/irb.js | 110 -- .../public/javascripts/jQuery.irb.js | 1641 ----------------- .../public/javascripts/jquery-1.3.2.min.js | 19 - .../public/javascripts/jquery-1.4.2.min.js | 154 -- .../public/javascripts/jquery.console.js | 609 ------ .../public/javascripts/jquery.console.min.js | 1 - non-rack-legacy/public/javascripts/jquery.js | 32 - non-rack-legacy/public/javascripts/json2.js | 1 - non-rack-legacy/public/javascripts/lib.min.js | 159 -- .../public/javascripts/mouseapp_2.js | 913 --------- .../public/javascripts/mouseirb_2.js | 179 -- .../public/javascripts/raphael-min.js | 113 -- non-rack-legacy/public/js/index.html | 8 - non-rack-legacy/public/js/irb.js | 110 -- non-rack-legacy/public/js/jquery-1.3.2.min.js | 19 - non-rack-legacy/public/js/jquery.js | 32 - non-rack-legacy/public/js/mouseapp_2.js | 913 --------- non-rack-legacy/public/js/mouseirb_2.js | 179 -- non-rack-legacy/public/keypress_test.html | 37 - non-rack-legacy/public/moods/index.html | 8 - non-rack-legacy/public/moods/sick.gif | Bin 94 -> 0 bytes non-rack-legacy/public/popup.rb | 114 -- non-rack-legacy/public/setup.rb | 67 - non-rack-legacy/public/site.css | 211 --- .../public/stylesheets/facebox.css | 83 - non-rack-legacy/public/stylesheets/reset.css | 46 - .../public/stylesheets/scaffold.css | 56 - non-rack-legacy/public/stylesheets/site.css | 378 ---- non-rack-legacy/public/test.rb | 633 ------- .../public/{images => tmp}/index.html | 0 non-rack-legacy/public/tryruby.rb | 174 -- .../public/tutorials/es_intro.html | 666 ------- non-rack-legacy/public/tutorials/intro.html | 680 ------- .../public/tutorials/intro.html.broken | 638 ------- .../public/tutorials/intro_files/sick.gif | Bin 94 -> 0 bytes 52 files changed, 12964 deletions(-) delete mode 100644 non-rack-legacy/public/.gitignore delete mode 100755 non-rack-legacy/public/blank.html delete mode 100755 non-rack-legacy/public/comics.txt delete mode 100644 non-rack-legacy/public/es_index.html delete mode 100755 non-rack-legacy/public/images/background.png delete mode 100755 non-rack-legacy/public/images/footer.png delete mode 100644 non-rack-legacy/public/images/header.png delete mode 100755 non-rack-legacy/public/images/tile.png delete mode 100644 non-rack-legacy/public/index.html delete mode 100755 non-rack-legacy/public/irb.cgi delete mode 100644 non-rack-legacy/public/javascripts/application.js delete mode 100644 non-rack-legacy/public/javascripts/console.js delete mode 100644 non-rack-legacy/public/javascripts/controls.js delete mode 100644 non-rack-legacy/public/javascripts/dragdrop.js delete mode 100644 non-rack-legacy/public/javascripts/effects.js delete mode 100755 non-rack-legacy/public/javascripts/facebox.js delete mode 100755 non-rack-legacy/public/javascripts/index.html delete mode 100755 non-rack-legacy/public/javascripts/irb.js delete mode 100644 non-rack-legacy/public/javascripts/jQuery.irb.js delete mode 100644 non-rack-legacy/public/javascripts/jquery-1.3.2.min.js delete mode 100644 non-rack-legacy/public/javascripts/jquery-1.4.2.min.js delete mode 100644 non-rack-legacy/public/javascripts/jquery.console.js delete mode 100644 non-rack-legacy/public/javascripts/jquery.console.min.js delete mode 100755 non-rack-legacy/public/javascripts/jquery.js delete mode 100644 non-rack-legacy/public/javascripts/json2.js delete mode 100644 non-rack-legacy/public/javascripts/lib.min.js delete mode 100755 non-rack-legacy/public/javascripts/mouseapp_2.js delete mode 100755 non-rack-legacy/public/javascripts/mouseirb_2.js delete mode 100644 non-rack-legacy/public/javascripts/raphael-min.js delete mode 100755 non-rack-legacy/public/js/index.html delete mode 100755 non-rack-legacy/public/js/irb.js delete mode 100644 non-rack-legacy/public/js/jquery-1.3.2.min.js delete mode 100755 non-rack-legacy/public/js/jquery.js delete mode 100755 non-rack-legacy/public/js/mouseapp_2.js delete mode 100755 non-rack-legacy/public/js/mouseirb_2.js delete mode 100644 non-rack-legacy/public/keypress_test.html delete mode 100755 non-rack-legacy/public/moods/index.html delete mode 100755 non-rack-legacy/public/moods/sick.gif delete mode 100755 non-rack-legacy/public/popup.rb delete mode 100644 non-rack-legacy/public/setup.rb delete mode 100755 non-rack-legacy/public/site.css delete mode 100755 non-rack-legacy/public/stylesheets/facebox.css delete mode 100644 non-rack-legacy/public/stylesheets/reset.css delete mode 100644 non-rack-legacy/public/stylesheets/scaffold.css delete mode 100755 non-rack-legacy/public/stylesheets/site.css delete mode 100755 non-rack-legacy/public/test.rb rename non-rack-legacy/public/{images => tmp}/index.html (100%) delete mode 100644 non-rack-legacy/public/tryruby.rb delete mode 100644 non-rack-legacy/public/tutorials/es_intro.html delete mode 100644 non-rack-legacy/public/tutorials/intro.html delete mode 100755 non-rack-legacy/public/tutorials/intro.html.broken delete mode 100755 non-rack-legacy/public/tutorials/intro_files/sick.gif diff --git a/non-rack-legacy/public/.gitignore b/non-rack-legacy/public/.gitignore deleted file mode 100644 index a1632ab..0000000 --- a/non-rack-legacy/public/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -tmp/ - diff --git a/non-rack-legacy/public/blank.html b/non-rack-legacy/public/blank.html deleted file mode 100755 index 7879e1c..0000000 --- a/non-rack-legacy/public/blank.html +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/non-rack-legacy/public/comics.txt b/non-rack-legacy/public/comics.txt deleted file mode 100755 index 7dfc8e6..0000000 --- a/non-rack-legacy/public/comics.txt +++ /dev/null @@ -1,4 +0,0 @@ -Achewood: http://achewood.com/ -Dinosaur Comics: http://qwantz.com/ -Perry Bible Fellowship: http://cheston.com/pbf/archive.html -Get Your War On: http://mnftiu.cc/ diff --git a/non-rack-legacy/public/es_index.html b/non-rack-legacy/public/es_index.html deleted file mode 100644 index 7519e36..0000000 --- a/non-rack-legacy/public/es_index.html +++ /dev/null @@ -1,96 +0,0 @@ - - - - - try ruby! (en tu navegador) - - - - - - - - - -
                - -
                -
                -
                - -

                A Popup Browser

                -

                [x]

                -
                - -
                -
                - -
                -
                -
                -
                -
                -
                -

                ¿Tienes 15 minutos? ¡Prueba Ruby ahora mismo!

                -

                Ruby es un lenguaje de programación de Japón - (disponible en ruby-lang.org) - que está revolucionando la web. - La belleza de Ruby se encuentra en su balance entre la simplicidad y el poder.

                - -

                Prueba código Ruby en el prompt de arriba. Además de los métodos - originales de Ruby, los siguientes comandos están disponibles:

                -
                  -
                • help - Empieza el tutorial interactivo de 15 minutos. ¡Creeme, es muy básico!
                • -
                • help 2 - Salta al capítulo 2.
                • - -
                • clear - Limpia la pantalla. Útil si tu navegador empieza a alerdarce. - Tu historial de comandos será recordado. -
                • back - Retrocede una pantalla en el tutorial.
                • -
                • reset - Resetea el interprete. (o Ctrl-D!)
                • -
                • next - Te permite saltear la siguiente lección
                • - -
                • time - Detiene el reloj. Imprime cuanto tiempo tu sesión estuvo abierta.
                • -
                -

                Si te pasa de dejar o refrescar la página, tu sesión seguirá aquí a menos que - se deje inactiva por diez minutos.

                -
                -
                -
                - -
                -
                ¿Atrapado en los dos puntos? Unas comillas o algo fue dejado abierto. Escribe: reset o aprieta Ctrl-D.
                -
                - -

                This place was sired by why the lucky stiff. - Please contact me using the email address at that link.is maintained by Andrew McElroy and David Miani. For support issues, please post a ticket or contact Sophrinix on github.
                Por asuntos de traducción, mandar un ticket o contactarse con Cristian Re (leizzer) en Github.
                -

                - -
                - - - - - - - - - - diff --git a/non-rack-legacy/public/images/background.png b/non-rack-legacy/public/images/background.png deleted file mode 100755 index 3a2dee031614731e46c00b5f8416d471908af982..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35315 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 b}X6WEoFQ zTj)?(QRpJ6?}oxuCL$~JFqv3KD?l_3Ypv8pgpn!f`%bz}_MqY-E{3#>?_FznUBj;G6)|DR8v(qBW>M*j2i4j7>CSiXF@^zw3=!i{IkZEyshF4uc_ zi;aj2#Y(i|=ZyW;`4&ddsxFKzjay;xEKCX$vwTIM=;mo^BD2;>4=m@9x(!1 z8GBremUDSJ^k#EW@?DTcW5N#3JZTsn6ooM*FP2**3u}*Ghig2cr=eYLR;`W>rN2Dj zEnjZ;P#xuCSL0*66h&mqbD+FDn5w%8j4K&!Wp_-1CNimiO zqRUi04V4riK1t<7rl!r}5?ai9F3A?H=kdqGzLCQ67;Q^!bI#;E+4zw6wC= zzNgf~hewRKHGTSY`n#ys$kRtmKYW;a8Csb-nht0XbdVGlBk(EUK~KX|QX!=g+U+Co zMpguZRvok&AwXn;azdpDFlUF35#rmyA=!anPx<*H1z!1^hpal}A$;1wQJElt5iK$4 zkXVF6&osUHd3!2>aVifq35ah88wpi95VEE$^A0w`$Q^9h@l;b9!Sy4aT%!&tAaNL> z;c}te@l*-OM@!!0r(Bnguy1;xX=0kC)w+Y@Wl5P!#Cq8w!j`RIVi?%6>5zI!lG=$K z$`AS&x_J5$*T~q(OO{NhF~XWvTUN7pnh-x7kt&Y;)bMF+))8tL#7{FrjYt>X2&8f9 z7?H(z+8f=|be7psP821R-P4pzo{q>Vou`=tJxwX%^D6PQCqXYMKh3W8!f%A@Kiya8 z9_rO4IHoU2HnMc`Vfc`NpEH(>z&p-BHhsyh!zfxZVmgQpFIh6;7UoD;jkppE=3ZEr{iq6x~ z8qDAecV)z3GQ)4#NQAc=cm6PHrXQw|w{oJ4Fo$^qP(vGrk|i)D6%&HO+`@8lk!4J$ zA|9roODGB+#N5Ywmn@;bweA~P2ZW(J1fkh<>N#A1Wcp!x3g`>F9!;i`DH@O+Ru-CQ z`Ym=J!7>7-iZKV+?Ilz~l+jah3qh9<+vx@gqFemj&;nqmFA;uNXbE|kNZ(TGd?BVF zo6dWViAZdwL+V?Ik6fo~w#*m{N>9WH0*0sNFoIzYOLCzMhXHjHmjOyA4A7K02?qwi zxWR@+w?xO^f|6W6LF=F;P~_Lg$QG?b;JBqN{Xww08mbmEbcy?gfTp+8Y=jl8F1uTUu| z2~`q${9-H}ylW-4e=I9mqE<^vOd=_kBm!tACF-Ram3TM@E&&5{iR-44Ky``Q>s2p` zADcxFM2WPzBdoR-cu6jlC0eLvN!Y$%s+`q&iF%X-BL&KivMZC-&QUBW3EN}vl4hV) zVh>NYl#S(*&>R6;gDtV}?#T%H63YNSQ|#Tl=g8hYd-vX?zw8|v8AN+a;&G%TDM>f( zu_=zdN7T_gk0kENdBC`r3Voy`>ygIg$ll&L+51Y(!=hGT1~ogq(Cz`uoA>s1L5JN0&ApN%T{j^bXzzijtE=Q5gn$7?hzRe!=ywFn zkkuY^xCiVYA_NCBcnT?0$vtq|1KO^VBS*j&W+i)$knzouJ>U#3H<8@lBR5f1f|N@3 z?70cXM6zAfXJfA3zKn1hid+Olpu~I81jy}0DKG`nUDy)vD#?K|fZfCn1Lm*>4!{=Bv5HU^+%hQKJ?KklK>+RI zO@b}LB0>!zk0Uq170=1-NPP^;*)EchR{Rv%bWK+7+C#raaVGXi0{K+7C@M*w83$ zSIBs1s5V&KKd&px%b&qwj-n~Y-CqN-U{a?Lz5Fr zAUDdvqASq^T|*O1lCJE@^54YEJ1HkJ3h{D9-ZHMZtD9X(&SNW+q>554uO#p?jw|u? zN{^AQTuH|}iFYM6NxNN16Z%SSl%Hpo2>$%SW=}a?kSovKo1Rk4mU3pyG*mML{0d&**$N_@kN|XufC7q-V6^k^Fkg%e;fGQJNN?*q00z+STtN>q z-TDrJfR>!zK?3ivmIEMH0E88&-l5#KG6B3?K}r}GVbJXz(Qc&>6aeL02`&f9L&@uk zRFJ_jgLly73RVYLQ82tK?<-s%Opf~w9EeEPl($me)Cs(MM1>lIw{RM_vfwIj&4n`8UiOPBbA>mE3&9RlQ|^^3R8tH9U++i;@37%kYQ}e{Ww&m{KL)=k zH1dn_V*G6m`lIlnkp~WZQIZ$qZ)ps~7ktrQTDL|X_@a?tjK8fW)EEG}$4BQ$p zWg?LA+{GNoGo22!CwgE=31gyq_ErZ%B*f72&w=u6v33xlN?iPbY-MFrD2*I;CkM)k zX^YwBW9S1JETp+r_K1bEEkF*G^&N;un=mjmg`!eRF{iECnv#%*(G116i_Q%=n8pkGyxmyR@ z9*o2}d#YU`e40#hquidEMtgf^*px-Kl-rYD z?J1$#pO-{x{=KH$-gD)=S9;7;x__jJZ{$Dy>D5>Nha$9>@0&^zS?c+%tfPAbUxeSYm9aYs><23eM)So(c0BY*(>u1(^<~W zfwH6OK%{8xfoXfYYqa)IvXDW0$T&O7v$ZPiQH^{a?Y7~DFgsMxa?OGAY`^iLcIsjg z+Gj_htQ(^(hbI0bw6N^Ln6ZDi?(eXX|AdW|3J#VOtZ5nLq_c%*Wr*x z{?n_&K{Q--!xQu2yn@?szOi0xhLe6cd#Np3vB~fxUOz4K;L$`lEn)7KN9@W`Fw7c}Z)eoiY>(uUxXItaBvneuJ9R)Sx+YsNPdfLz7C?Z2V%_=Hcm^u{lw2SY3}AdG*`FS7X6f zzYVw5bRXV~uVx_&3)VER23ruk4R^GDnYFWPq_vtZZ!_fE%?yu-!)Y(EE@(s-H5@DVT`7fxRSmohVR_eF6zi5^`vD>T%=?`sd zBmZf2%4l}?=CDjPh~~|yy44v)LFa>|L~PD%9}CijXzn?3#JxELPti9g0%uD(HDGh1 zZq2KEq~Gj3a-iIt9=Ey2T}rZQ?oDOWQ%)PFIW4g;ZSKv+#f>~_)M|Xe7hZU*Uad=- zjUqRikJ1S*M!D;1^^)1BpkXZuMvXE9HCk;VMUjveJuq6Ww9K6sx@2p8MbuQGu9fv!)z&LaMJQwz38Ydo4|14WQeb1LY89 zwFM7NXT=#6`pb%{I~^CB1phoLwUIgeYQOuV+%%f^AYSb!tG#4(Y#tc~Yo+0BlC;t@ zi?$|VwmJ@-R&3AM>QwL5qf*1?DY>NHv5T|FTXM-bkwZ%1^OD@^l!}IjH|d>d5;h{*dZ z4D%2}eRYYDVTMQm@({2Q0u_Kp05C=2L-M>tN^k-Ws3&J_r-uj%X5d8$fSwo-mrKGA zV^cV=d&nt`0t3tjtsXMhhhI@a&;(NhL+1Q2ugM`j4v81Q8RYSbuB0wn+Z&tDZ?FDeR+jE4Ni93Jxh;X|D` z<-^1<)j?gxhFrP;a!C-AK}@FvE;+kP!Qj%Rn5V_xcgZu}=MoWC0Vz0MGLTD`_FXdE zOL3ygYac20q}|KQzJJVfMJbHI-uDf-vEGbOdA%62f2e566%kY zqYIgc9o+Y^ngI5(7j80}^{0W0gS5at=x??JLzq}HfJ4{*v_~j^C_&lwAo=X$5V+=` z1W3$CfAFAK?c>`)GDGBj8kqBCyn~$aL3U@32SYOZtSkpPkGv+gk2A#MMBuUf{rj8O zzPu(!N7TN3k_1OHZwZ>u$|_);BrpZq7-X#qnAMRSD+isg1nc@6 z4Z{_?bDnYkV0+G}26B%5IVGDEnLLllof8PFXV9Muwas60{audzqgu<3pUZP{y0aQ0 zgq8cd!scE0Mga4M(W6}>_wSEQOyj-x-hJ=gb9jI69A033?mh5>3A8#)-^F=~AnvcZC^_Mj>&tr1u-cwh= ze-HQLT}+v^@3MP7lcW87S6H5V@0_G8Wu{erlf%_Hxl?QLj&cVwG99?stJu_|aZn@w z6EyO>iep4xj2GkQI^Olq3-7ybKU{LQqnU1(q*(~0~~*vNwhy*G%&gX}_+ zL4y(~Bp9S7=!P$`Q)5}gSnoL@PX_5a5i|j0_d#ha-%DDgvSr6XsTCpC5%odd%`Sr? zygVltV-9jzy!VqNmsAW2JO`O3kI97~aghhTHz*0l_s-qB`9#J>elUpp@jc&_g9cT- z_g)n&s;c1q9^R_Nq)L&hIDHUQNq%5TFO<9I#t%hgYul*drXpz z*_;8HHB-)CauzO}P?X3ZCZt*CFF9_eD(*6#GFBB^SLrb!;GH<6k^kwzARASbIOjho z><-DfR;m~jy#@^mwqZ3$mJB&atTlpIsocU#^>rmUG8?40Y-SKfWl*>puR&ViD)qs- zsIw;Ka?y-6DFJX4@|B!K)~7-*!f?=_s{AJBVP!GMk#Y9)okB<%=Y2u}UjX6FTU)I`;uWA>An z{g`e)&EDl@lDs8{%YHk_W~Vr57J*Ctk_!TC0V1Nl7hJ{jncRh)QMLQIl4_kb26S@V z$WRqFVT_=E-*5s(yyP`^t&Jw z?3tqC(?UWiLk`%_brLOjtAx^poqFHN5&P}5SpBHT{pfL(|ffl zzhyrx_J4%ekNWN340BxXZ`lkM&`)SUHZ3jKTws7rMm8;*!2)JW(Pb%k0`TVjn_HIl zLvKi8X$zWx{bsTUs&Mc35yWa~0U)@5K?{JO1E#$c{riCqmP4M@x}EZYmZUv)Y{JO6lx|)s z-To2EDO04hbg3N9AIayWiyJm<2#vfH48UUPQtZn8NJcOFb=`u4uh_t(kek@FsGk__ zS0QV}b$`o#!)P&J@dyAsZ!zuu7SBWCIXX(jkNx3GCoTJZ7P8tO0_}I)C3A=0;xO`+ zoHzzh7xX7cPMuU9IL37Hm)w4boPfg1QX1T^I5yzWM*hXpmd}^A;MWfuXOok&X|?$q zXMYN(ze;jve`3F%bezpfhm8#V3f~!U6ha>tN+bW`7fY9ZzV!2!r8jPn<5?JZL71}+ z>8xDNvJ`E+1ut4u(b5tyTFyq!&O;`w7kk4w>s;7c1FQ0^A(_xZDG7UthgZ9c1h6*c z(c+@0e_oSw`MBJ|4&*zz7W=Z@)gXa)UXyEyd_x2y4s8tW3fGp;_b-JuE-bVY`EwjM zKEH9}%dEp07#K5x6x za^nV=p1pCW-Xr|r(2vl!(Dl7!WlX94T% z**j-p0RH|~6X2X^7koiBmP=ZMnsIXHkF>GPZ1jc@J%0c-^9ftEWrzJWcz z1HrxlG=PUp^P3z1Kt64l&<%uZ0lPN5;qC$fto@D8+rIhyb9n9l{PV)X|1A7ZJCVPE zCcJ^84g2^`8^6&LFAH&ggD*6X#=;wIYTveSA+WqdlN$@sl*|{B`i5Armm%E{3!E$r z`s6t4aK>_LY6KJ{tUNJQeJ4%Hifr}8nn6?uZ51E$ayXk?P(>dnt8Sp zBSRZ^bXX&Q`1OZvAA;eQ4;Mc9df}F~g-@O={CW#`JweYWa0Ag6gxdldim_$k*C+)S zvH_DVblb9J3*Oqcz#35y1TP4M7BJs}Hn9E>B~N$`NMED>7PQ@hwr%Lfp|_AH2%ogI zksc#{h+&=}xh;r9rPzX=%((4qni2wq#xNh^?Zbs1K6&!wLsB9pGaw)`#>qg{Z*pJ5 zTs!Is74ylK4=L8yZCGna4*KisuiHNS`kN0wgimrE9sk)8PUNq@{_x4yUxN+35Fb40 zw($KePu@p3M0oQ46PavbqxTW^3Emg7=E?iWONv;hhAK_n8tB+9I1zRnBj6xWMN_f=DDvn~p3_ z{KKzde7I%HjSoNUz`>3Di(mYL?7y~6cwfg8WW_TCmIcj7MA3NmK6~=|$rE+gDO;M49OYAjtFna%q(t2V>2KB`3B}kA3QxUsmpz_31)XX9dc}Y&ASWGRptSwwV zlY656FNJ*-r}zDnnup}V&IY6>PkgsgtA33yII6d#Yvh;UO9H?2625Tp624!e^%K0{ z`h9-|ioy^Lqa!VHdK`PjXLQl8t{!GJQ!&O1U++JSC?d*ha(`JL;vE z1XuXvF}Wb*C{KJR{(tOQJ&R*!mJWnKOdyQ0n@RU4463YzGwBDcgm6Jc&ILD+15-&e z0)c{E6iJasg&GNz=w?a^SzA*e5X=uKRA6dx*dxqB&kU@SJ7lXf+t0rJ?6c6wG3NcNS1mVg-Mgh%=>S*bRjUPyd$nqL z&wKlDy``pHGrN{8+uD5r*N1O}N$WJcx4HLj_hxjj%l8(oaese?zOZj8T@}!O5A;9*D^f!bZlN$T*Q$PTCS|Eu=!%*z?NQOKoK7 z<9~Y{P=sIOzSU|-h8lv2Y+(MX)sT!yQW}y+F5im{Lf$iFE&4#RE?~y%9@h6Q{k`W< zJ`H^cB2Gg~Bk0Dfdx?Z-4M2c|nn*w-TMTUpPUNc4e9}%GTZXGFS}IEq9)sW0SmME~ z0iSy_ZE@mU5%3j|G#3W^QsP>kFr69-O+&Qq!|nFu8A}&^}b7 z5!p3jWGBjRHX8RaWFx+L&ocrVtwzc{;NQoR?=7*q zmlb!P(tb}%+57p=uYM>K&7jaR|GD!RgYxXbUIZ-xzVmF&ngV7xSL0-svNM(=QPEzr@yr{RK!n1R6Ri#RlTPX;MB~f z8pQ{jP94ve5~tLv)gn-}8X~{2xT%AiYDG27R6|u`Z7(1Wen}ap){9kNR&8W{X^_|R z=bwKWHL{jN<7=2IDe;<4@mtkj_IB8+PD48BJ2lfP=MXwIFM3zakz3WOX>OT$RUs^4 zQwxcV=#6o;h8ltenpTx=b?WdH%XllS>b9bzvyR*Or+ zuFZxzsp>{`Xldm-7Kb()p0KF8fUb)T!O$IaN_iM#NHqD;wV~thGzD%Ru&VnJ6TkP8 z;<~YvL_n&>Ppd)9S#i}f;#`G%$Zj!Trn4J2L{#CI6W1L^6>xg0)_qlPI6dFU_;b;n zIwll2j3Vmgcax>zFe{$ z{7N^W?3snIU61vG;-VafZZl&C_=4hmAlFYre^9$_?}f!hN`_I&yN-Q=EHY^reoqAFnUK>-54`G8TXy>RZqwA z=tC0K^?~hJJleeTx(RnQ*6)sKj?K0E&a@xn^lF&|>gZE+H2priN6pXC?+gP827MQR zb+-$LZd6B=%mf}oviz<~n^Sl^#vfbp?FcUIE4ourT6y|b?z($CVy ze+Z2XTJMg``K&UmFl2@3vm>v|;czyS-Abi0yF4B%GqD-YhL^+2P^Pks+l+~t&BTn& zdZ|d4aF_K_F)Q);pOboWu`)(BiP_^B*~#d&%k+gQkMXl$aH`SD4`nwvW&_ zR9RA}BZ_o6b0wGwDfv-Wvr5Gd(+nZC8HTD>V?pb&avWOdOOpc~VB0BR29iX)E5NmkMxZ(_t&X{GXRE!PesP7Do0R$S(m_b@0J|$PwRJY^!&P>=6+FuKS+3XHs*)% zkMFgaeZ(hvg`rQ6{7Z}P7-;19jm+~g`_*Lr>-yLAQWyV5%x3udCf}8PBcqT1YJcVb zb^Yu5|Iy3Z(DD_d`^hJN`s9q+v9h?i!Ky4)Zmyqh zaKBkp7K_SAK4MY9#!cnv=4tfw^fVe(uCIY1u8XI|O+`%MFMu!=Dd^^?uvUAY!8v5^2b3y@z3z0u8L1S44hizivSk)d#X zS}d+r)3wH5j4*({YYBV0yZ*3%moBj08`OAj26^TQIpZ=dL-<{3p_>CH3&g0Oh-32EDzmD z%bc0h5oL(27~I@2lT-zLtVx9-Ze;HowG{CHxUoXvAq0>}C4(*GSosQdL6-6_p3oS` z&;r#5PDOKyTnk&KjDfG8Fc*t!M7p5@%%8A@S|Nf^hOPyM)Qv(tMU9N>6I{NLUA1nm zrAi`wfnWbw@F}R+!X7t9>|~Bc@k96A=E7sdyNY0=(I^hXg^`OLMSxV#V|1;?3+HVv z>SIi8-h!mp>U0OyXpPe{^T)Z|m zF}Z8%3&Nbq$U=u08q}|Qwjmp%7~T~ynkJO7c^wgPHN0l(k$Wo!KyJK~^S|*q*E+d) zBVR_N6Q{y8#^`1g)Fzc0Ip(A%9sLx(|D%z=`Q)3Zk$D^!X-?BdeE&6C#GQI_3PvA> z`55}**KtoPc8=HRm!OXpg>;`w$mop2=!0mZUtjOf#27`dntu>|^r1ZbVnGFO{6XYj zYy0m>(#LTlKdJe8;qE$;$C|%7w4HTiv38cWuwF+K?|EXD7!?-QYjg2niOD*abvko_ zE#lfkodjDr>-7nfbupW3mx@JzS`>Mok+m)cjNRAokrD5m-&v=;7fDIZUumLzS=Z~6 ztypYQYVUIfEJ@Sa=iRr%Ix#J*7BaH-D%WR{pksU;x<(^^^G*ClzD6HEiqS?w9o7fm zOfp<-*6YX3RyPmZ^=e5Mz3Y^m03a%gui~ww?0i+*^AfBRSyM7k!>x}?E!b^B=4;wuMvc5%- zH4-6wH`~>AV}%2KP4{7g1c0-MUQ_j>7G(2$z|}hfqEWAjtG*tLRoVy3YjU%Cn7QXOwpP}JfMDZ6V+QQFH+2O zEDjqQ3O;s$BMiU{B?l>_c(Gcc)a=kLGPqek!+lFehsOmY(3yyDRtKs(0O)xG7jEKIY=t}0 zB-8-%jAd}xKmcw+SGrCD$!xV@a<{DBW+mrpg9J;o)d5;Jh$tTp-~ibN6az2WQ8WtBsZx16h3*rHd_P zp&)q0NK3E|kBGl!k=G1_g9pAW4E3Wad~2|hXrhh2aKMpgg~Va~3?C^dJ3tb#Itb1) zUMAWw;{M1gJTF#46$H^0NYCTpSvvOmQT|zZ+Q^&dXMygmHoX;V*Tb{dlNcLTl-Cv( zxaL9(q?DdfsbmF#?o2+ST*Et1TUgk{IP1JzL(W(}sC>tkrcJ(dxOqf*_tGQrLK#jpbz(ZaojC zae2pq?S+uNYBak2ZXL{4%Zas(&%?IY^X#m+8z0hf*%%q0 zza&3Bm;R6p7tim9?Vb^Fm0iU<;d++Wh@5czN3FDx<;~icKJEkJcGVkze{ay2dtauv zqVN_nd#iyA2CLhFDuew1<_L5vt^-SIpVqy>?d|PK00r+BSOeF{w~DtS_<)J&-wwFd z@Aov>vMJC5*sNB4MhCGzya%`100UM<>A~z4Mz@UJCoRSR&T23qM1MdFiHGI>3i`xu zK#GhE-YXS#YiE@(x3m}tl|i4YgFfT;sri;eF#NY@h|0Cw79|Zm}_7S#^s}VtRXP zGi<^J%edRmfcw1Lvv2ma(+~QETkyEmJ!LhZ4qUfAhpJpqG)3xj*7K|^Gb+ZBm8iFU zYGWa|$Byb#6u@q^uHB{1(1 zc9|H*g)9f`ak&^O4#AMF2g_07$M}o=wS2YNJog{J_{|sJ#f{v*#daB&@R1)Y(io#M zvQuW@F~^87My0eUYA|M3mDOSFD=K5mvCF<2(}=VN)ihDqKm(e+J6Sx}EPdJKSp(`DL^I1mjP;|L)+#G6J6B@|MD5J4b&=9g zCk?B$XA=-$>~b_FabFzO!|IJ)K`mVapRcl!87tNDz;b3?WDR7FF1v{NHQvh4^83Yi z-+lLmHS+I&-~W1SJy4Edyk6f~+!+{oiXBFg1v`2$xo9yLF1{~pY}TipL#gaoGf3&WjkHvb;S z59~IZANAQM0Q>T};n^_Fb2h(-chUG<#O5hTb6@^Nupi^p{58mrdG*oC-{I0m{=GD^ zy(pVhB0u}4Ui&ic*w{0Xb=j0_bQ2G>PoWSRH-hzO-5ttV6TbT8=Oj`iKe8fgzHVK z1b;}z8H+((+Y&Z){HWrx7NQIido@KCwG1wjoh&}S^v(oH#cfoN)nv>m&_le|^8c9iKFEbS#>6%dnOiy`g>0E~z(l z-?fa+!K%)cI@vl1E!N(=_WG&U(dEv>LYWnsbDv^BSluR$!k$M1Vr8a|b!`xct^4r% zC`y^87LEY=A-t)sbGmoL>(*iZVAq|4BKkAhWWB*isVIXzpJn5}*B$3vXH(Z*Zpu2; z^AwcV_a@dUbR}@3y$cBuGT|H;Lf-naub)YX;IC= zRMmsC)3(<%!`92$*CVcb^he$GN>HI?(I(Y@gnWI{$YVQvj#b2RpFWfRORjoxt8PE% zbl02BlSHHl_2$O{#_Udc|C(3*qYM8Kdc6R9`e@T~efyElrw%mRXoqxDs**X)~vFw?W=AoonMLzh^b&e*QD9wac zM=#$Hw56uW#4@UZttm>1NicG^2nNFLv{N;)K+1?d1T?Dlpq;H4R9e6d}&L1g6ZpM6Ko2J1^Wa=l@0uvoiOh412Vx2bCs+q8} zWnH2P)ZA$Ylq?-hH?u4#HNG?T3!DC;5-CKF%hs1cfNj@!EMQ>hs`q+nTc z_4Fta+9dG{ftt>0;*-cpyQEcjS=5}C(%@;s7DK-GYR1-+f{samnFRZG=_ED2%WeOZ zOKDO{MaPLMl}_ZePx!eFPjfN}q3EGUQ7oE)*u;EJDTKK_qbh{BlVY+gXfxFkjqNQr zDeRusqFrd0vqlNeiB+TR5>RhW>h|CD#-BFs>G6 z<#?4`qBI{Ny(Lx9E@dumoK=tG6Gvg0Pi9suyN1>@WR`qKLDNc!K9Z5m;?Bv!o{2Y) z%vYmS3LWNa7!|9nsmw~2OX<_ePxc>dq><(NZ~sQF^Ur`-xO#$5Ae4ngS)ZkeyrbD!E<1<3;$`Mu`}uwl_{ejcgW< zaprL{OO=86baWA#ZCjYLqbE`7y&v7 z#rCS*P8CG0nZ`9l{mM7;1YauJe`~kjWO;^Pame%hjZ0vzpl=Gr5feVL zxF?G1?vdK%MHij&k!Pug4stio6AJH}Bph;AfIR<8+G2UyYi9nJbnA^P$zSmNTkh%p zC8}2*1hymW+|rh3Nvnv;cA%H1=P^n^J7t!&3%RyD=7RAiPg9x*Y)1soZ@UENXHwdZ zW_j^&7A2gr^Rqne@{@C(7sBT4?2Mu}c;B|$=;TSgE{*)}U&W0qTW|DjljoW10Sxt) z*Kj}$7&V4cSECA=ZhtJ)5ZstlWM9p(Y%Mo-gdBP%67MSFo zsiH>Y^7BU{4}&ab8x=nHsqsN`hmiY-SrpJkj}qiX_$J9iA+i9K=OM+pXPqasBdJld z=8^m$!<*$HnR#C5WLpijNt(cQ&530QnFZ{?C#qEz`Yfh|1Ka*vCf_b_v5~)u8o7-w z&!m;*<&j@xyNB#y=Tdc{eUk4U9$XXemR!j5hYY{s5mL-`8(i$H$zknzRt zA`j#rY#=O_;7HC~xUkwwk_GZ%NzL9^{VrTOeFHJs;)O&#fF-PUS_RFbmhyqyp*G@V zBa~gD68Hj*z*bSQJ1eU&fQdEo1Bcm#iC#X4!VBFH{EOUT=b1GY6lThXLU#{2|2|4D z^PBRdK4ByOHfm(K#PkiIq%ov`JNckxrE`$FoIA*|wtQ>2Iy#q8RSY|>5LtvNK z1-&J@YKfx42y%DG<^?#xYsm&)qSqkc0--LJ*d;x%7i8uPU^@uA0IdgVUoJ1iWw+DN zASzH7#sOr-=K@hsL6l5-oy3i2&J5*DCNl7VU*uCdI^QvsVwDk_QBWS18^Rv6j5}73 ziQ1|32U?*Yke3T>6v$W-KWA`bjI!h`(ZvG`2oyPw6ux71b{CqE3-(P>RO zI!equxQ0?1&ODTR9(QCAog6+_Ft_XHQ8it|B?+Au-&pc_`}W5rzo4Lze=0Vzd`o$g zJ6z<+jxv#*+Se#;Mly<8TTzsMpvvusiPi$wp|;OQIr?b3Sq&fn%84DRso zOEQtAJ1lkX?sWCe?TcyWiu-pRb&^NNEIMi=!@2n&4?t<0a)7SQKQahfUCiu>ycjDZ5L3d^>Ux4wSiTIzBe@Gfx{?#g7 zKDQEINlmZFq;qwp$&#mG*E+Sknv82#wW}*G)p&KT?(S;hR+BB+mxk_$9k8z8UV|UX zcm?OHj%?COx<~F<6by~YtkpW~U6@_zzThG_P>}m8VhT77WTQi)JD7A}ht5w-fmN^`k$#&MYQc` zciyQ97=X|n+KX>3>XeG=OYBN>kF-G=<_zne^3r{H$ll0H`KKR#`^O(bBTIwxO9i;G z@HKWqr)FKi>xzVGC`--SMf%}N`w&*#!wNbIj(3W|z9K3+j!+=Y9-t!%i)4d4vGJhc zTtU^-yw$UVi*+Gq-dJ>Wqna4b+$7b4DrMn^l3Ei@4leqg`DnO18`ZAvj2w8ImkOk+ zJIhmtJXAc_J4W5~q2d~j>6_EYB74W0Wwh40GCe-1<>QV&mVu7r0xE2bj_Km7!{o3+ zuFgtR>+DL+GvS7i!-P9biZ?I_Wp&=ha;R@ zs{JCX&PlY+--Yvm>*@m-SARG0Uq$^t{p$QOgU$zb!}+QePB;l9rT`s;8%xlaiN}lc}etxVW;GlarH?k&}{;s;H=zlaaZ( zvbVRgm6Vc|l#`c~la`c}mz9*Mrl+c?r3Z#L}#;^N=1 zuCAn_qW1Ros;8*9xw4*|o2sd)nU|HTsHm5elBJ}etEs4|rl$Az_tVqQxwp5NmX*@b z(ACt`udc4Yzqz@%xTB$ZrlPX2uuC1=Esh5?KmzI^r#=*tJ#m~;p&(6&C_4L!x(U_H#+1J*Tk&=~?k*B4lm6MZ{ zk&%>=lK=nzl#-F4tk(qq02nAqL_t(|+U!~NyW=>Pjbl5p9ZnwAE3TR9?&l%&U>{p^X>ey-&gK>u`ONQd+xbMiqsh$e)#q)zvk;- z_1tqOcTP@D_US$wjrQqi&uipv`k1*VHl^+^-KjRUPt?(9AAh)qR2?{H zYKK7kx%27T#ZQ68Y@WHMImY>6`}tgk;60ts6L~6Jkj$rnw*;B_H*tx7DOyLFLy%}! z>XUSs<_s4=Dje6JI<4> zeUAI6G<#o_RH#lR4PT;>E1kdQE>GNxl)Qk3bR=~o^C+Vh#f?ejJ|9Jd71=2Gn$J}> zqbTo$C{xGYhz{m+hhd&NKVm)iDQELYg{WvDFA(aXOA^i$Bp`*y+bErbIA|GwiUc=? z9Wl!+O~H3!7=lq?%W4<{zD+_#GBd~UL>#9uO(C(2qyPv~MM5&2QG!t+lLRyXNS5k) zF_-Qn6>rpRip2pA_JzUVJxhgJXCxt=XRro$crCy`b)2$Dg;6nrSWuslcVv8LL$wA806Lo+t;UgoF~7Q_7f;dXz$IfD$FL&~U{) zdG4v_p1pbVwLkJZ@BWJqz562+^7p?2LVoI15c0{%6PRZxp~(!D2f~qDLRK9A+^L5MT&x9FkVPu21+nr;EY45B?K^1 zUBt&2qzO0Z1>0Z}<;{>;f|mp>8BiiV+^~L#g+HjGfb=mY;W}6B;cz};2Gk3DCYYI! z3uhElGnur3B;Y9uSRoIHAOWV-NWn7}7*at>h&M9qq=XAbOMp8A2$;;t3u=*oEmOD| zobu5ykAhzX0uTjFIW*;BL=UVDI09c#Bk34Pwh7CP$XFv#h7p5s83!OjgX&QYm}2r7 z{&5z7YP!n+8xLSg_~D!;`AEGWEY1r~VUzjExbeiyz$8=p=d`5=5)K%Nesvrr>|)c{ z4QGByR=6aX(_G>!5r&LVtinmgYz2Nx~qetO4D7!O$aCUV_qZ7BNI2 zx>|-vT4=2(@5x9L_j=GvA5u>i-wUrieEo2NmPPr6CvSfD%@5wcfBz%jK_UMgg#5}s zJrN;e6-ra@(3*uY3v0rwT*HQ%ErFwj`_tBiYg-&ym~$O0j_UB?EqY^XzT{OeV%zHm zEKGoL&2WsdeQNr_H@oQbiY&|{vDxF8i#SMZrQYi6^01FcZZO)9v}9_r9i+LSV{5OZ zucX!kMAz|gJ?e06yW??oIC61iq|c$ghMpK`ZKDcNV+(7Ju~=DPQ|^yM$WPwH_0#vC zxqtsBDdeAf1(f{9Cl8;v*k9snBuQmSwnL;AQLR0yhp)5seePCU*BsRDWyUhpa+j7) zDr)N}nvAKh5s8a#gOv`qAy0e6ta!m|C*bQrF8#fZqS(Gi6DC&otd{PMu5MuJLD*|> zT2G9o9DsVHT|8f$S!W}oDE(+k)qSW=huJPPbvnWh_;P-_;lvMteA2bmg4w`VJqR4* zvJQS12n|uKxl&1)gw`Bo7J0X3z*p zd~zpEAM${iCi-<_hHA804fzYyDsJmuqN3Y=NMvQb>ix~7Zr#ve?cbdMf<+{_-m^y% z)MERp2h64i>3f5B)8jBhs}Lt-)hE`oGiZop5s?#DH~0(s3f%P0ds1SOLSnX;gAKuk zvh7#@umXi~VOrT3ra8KY%sn@rWRE?{&-Phb8x_Y6Ru~(RZEVj=OsE|wy|;C{j)X@q zY=NIRxpVT-o6p|-qo;4Y|Hd;vMj;=*7fbR_TwHSR!4sTrVIsN7Oo$X{svx=w|8Q#( zU;H?Ws9_wW5tCtU!y7)}rBBW!Q}n6X-o0-U3{8+0o*VII8n16#RVJPoGOURvLhznc zy<{6_-S}}Hr?q`i4I@*l zzU_D8N%YN>xLu{aW|x|T^*I^1H1W65)@_}l;%hMLc2m*j$=StIT((s4H@4+y>0E^6 zU>k1*7Dt=H0d8xLcdT~NFD;9sJrDMFizunV#=$ynOt@b?0UWK)f#i4(RVY(ZuNO_Wz%S{?#Vn*Ymaw$i}+jL9`F79xAxYRW-;`eY==8L=TdWD zM3|F!{}CpJryc?op9@wJbZA+qf|S+)aKkS1W~=<_G@dyVdFfA3B%FXA+ESN z*E1o)_vzj3cyd4>ZpcJDwmv7Ga|W%qdZ5|X{=5dKc1u94;(~;!I%{#hKC4hH4ka9dgNz20BP7pWa-^x@!X2DyISeU$8L1`!bn2O~ww*hAAY*x_H-|&cL4q|LP$g!^<7=n#P5IhWEgjpj_4H>T4D=R>!-?X%s8hGzUAzJ~Zr`QlgXt8?A(>Ur_$dD=-S5qLd zq9QuB!U)q~RR}`T73)qwbjqpibEA<8p_2v7C|F&R#iPi;%F&)42t{b_#G4hDl6vQg zCBbUJBZKwGTMJFK#1lsO3r2x0R{G$QLcVzZFK^tsapTs19#qJOuf2Wyhn`O_(zGdL z$6GW|vrJ53vLmWmZj!GTSZ!QKt(76XPS{df{0A3Xt9&am(UGa8gKxr}r6NV)l5i&+ zN)++KCackzKk2Xnj&$O2{RbiQu_EC^kojvBCd1iMyI36MHrLCVmqFn%-G4bZdr@iat$qY+!~* zzUY7(!kR1in}Jz4)EUo86VBUBZ{7@!nErg$1aC!8L(!jdqa?5A2xqwCp5`jk;WP*x zm{=h3DY^f@Mp4)(wrQGX%+nqYd*6WN_{ObU|8@vM{^X}_|L*HAQW%VzNM&1_`^Q`! zH+(>I=-=i8^m%;C<=cDvD0SrM(iK%+yV!yAjz)ZJbMIuUZSvX)Bt^KzZn2LenC_~x zJh*lXi>v@!@9(Y+zPrIq!)r7hp64;P@RG-Yqi2Ps@#5Zl)_3rIyX^)s`>~x`+HDw5 zvwS;Xr+@2g@SBIskNh4ntWmn7`s9q_cz=s)b4a$^-cz1CcXzi0)k%M-sJ)uhHV`sE zbX6VqHqLO{**>Wrchg`+u6WkFc=KOB%?0_>FZV(|{Kuzmf8PV>+@uwy+(_9vakgPC z-om%Hz}rR%V)tglGO4KWANuUQt)~%h9P0`msddwnXx&?vYln_iD(Vk_R7iS zo^K-2<^4?SwA`DHBy^5fh8M)t98JV*i*!_Y^w?=$5Xx&sF6c$yuh|reD}#)6wwW<}QnPuXD?z47aRN?zw_@Qlphos-2FuaM+4XE}9zH&~%mxWb1{9SH;S8GhrvSXT9M5MZP0uqx{-^C?bNw|}VE>`&_Qh`sP^IuZRf*a&l*-jk0 zDK4WrapI;(C-b_qom+t%SGn8P3mLxLxi_#%o-RNVS2F4PG^KzWf0|*|otsNkb8{wo z#NXIfW5X@-1043g@o!&x@x_;Jed1>i10mzY_bb2f;K3NX6H++}+YCr;jwn8&DK2h&jhm|C(GA<**Nq>JzwMXS>z6+9^xJOz{`-!F ze0cl6|KNE1074$8R)1{sK=fBEw=<{2tD~A%?&z1upZ<==Gg&G|W9O>!+@Z6A8_pHi zTSk8IK+zb?Ykh(qHJUakv6#}OeizNvcJiowyz{cJd7wn^e2 zocf=Tt0MgH6@J$WzXVpp8a1vZH~_9D34-JJs!5`wqWksEqvq+g2sudtPwY` z9|4u-Vo=7!d#ifmn3S>Hs6&2q>edsY%xQKiu_Uj?~TK0HL! z3<#o|R4fYjd#ie^d`YMzC(v(w^LyX+wink=zqtOMUq4(C^5O99KmOrr%u7CZ_&cp^ zbbz?#Q1a;4ukgyhgrlz{Se}2SfpdHOX`|EPmyufje_$ZL?&W_^@Y-tRk3MyO6|Vft zDa%(^9l4tYV=qU&KK#MITD$8t?>k&4xl) z02w_ThxVOi*zxX+4)ZaZ5b5*`_T#f19?$T2R-M_MMJN6{13peY_}pRXz&Hd0EOfyA z=_%Y)MAS&&9T$3u3g@S1XF$OWE6s<06~O`iINzO;N-MZzedqAqsXfIzQ#d`d^mRtY zPYJvNJ@CmOOdkK`_`ay%4Ux|n83C}+fkC_DAnuu%4Kjrx*hRFnoe)j(c!L$N?<&c? zk@5(8SlD(1pYKQlJT{ebC>AVKBe8ap3>P(*pp=OP*_{!u6hmXdE%CsaBu-Cfw6As~ zm&@W9bXGg=BS;x=vSWPK5Y9NayB!``Dpn0FAsU9B=1rdOBqLT|gYjVpBvvu8O=2Mr z;6l!oRu{2R&&z*${`GJAy5E3;XXSdf{F`_7$~_YD;pNx7XSSTpCadLYJzK9=lgV<{ zuG%TyrnA{>)lO!3U(MQfTCVZDZsD?>w9{odTTd~vY%#W6w(Sf?(-y;4FfW%dSx=|s zbTV76SIgyOg5GI6Tdx=lJ+sxiEn9?Ht(VIcURS(L*OSS*Tq4SBvR*GIvvmoV>vp-G zO<)b9*<`XR5pB9&PuB>%BKqY7n3k*6x|}iGs$8`t0HWK`>ZGRmyUWtjZ}2OQa4YumVm7ff2)&!orMXucqaSlmk)Qma`?8 zLY_38fxPJw118f6YSFHzD-M7`xtuPSOOUlhMk~-kN=XVjTh+lSOW;sDwoV-f+y4reo+C`5r}8xs1!?h zUXo%k%=&^%^f3@TLoPth>>*BO1ktVD^O~0rj~4Rb@UG8(dWK9(XcZJqXCh=&i&}(W zAXLC@;SJ;<60&aBC0l?QRYK-VhGL8G3d1Ywa>n5Als`#J{;cgj?ewU7e9Z4lo0-O%2~+4trUME)FZ>` zL|UBPl!|Ia{$fKuR;-5L(PnpX02$Y*Qc~EQqS{qDQxK?9oK7VyxtyuZghm*`!Or8< z2bhYUo%;H4QX+uL$Nkc;*P;zf(X>4Tx0C)kNmUmQB*%pV-y*Itk5+Wca^cs2zAksTX z6$DXM^`x7XQc?|s+008spb1j2M!0f022SQPH-!CVp(%f$Br7!UytSOLJ{W@ZFO z_(THK{JlMynW#v{v-a*TfMmPdEWc1DbJqWVks>!kBnAKqMb$PuekK>?0+ds;#ThdH z1j_W4DKdsJG8Ul;qO2n0#IJ1jr{*iW$(WZWsE0n`c;fQ!l&-AnmjxZO1uWyz`0VP>&nP`#i ztsL#`S=Q!g`M=rU9)45(J;-|dRq-b5&z?byo>|{)?5r=n76A4nTALlSzLiw~v~31J z<>9PP?;rs31pu_(obw)rY+jPY;tVGXi|p)da{-@gE-UCa`=5eu%D;v=_nFJ?`&K)q z7e9d`Nfk3?MdhZarb|T3%nS~f&t(1g5dY)AIcd$w!z`Siz!&j_=v7hZlnI21XuE|x zfmo0(WD10T)!}~_HYW!eew}L+XmwuzeT6wtxJd`dZ#@7*BLgIEKY9Xv>st^p3dp{^ zXswa2bB{85{^$B13tWnB;Y>jyQ|9&zk7RNsqAVGs--K+z0uqo1bf5|}fi5rtEMN^B zfHQCd-XH*kfJhJnmIE$G0%<@5vOzxB0181d*a3EfYH$G5fqKvcPJ%XY23!PJzzuK< z41h;K3WmW;Fah3yX$XSw5EY_9s*o0>51B&N5F1(uc|$=^I1~fLLy3?Ol0f;;Ca4%H zgQ}rJP(Ab`bQ-z{U4#0d2hboi2K@njgb|nm(_szR0JebHusa+GN5aeCM0gdP2N%HG z;Yzp`J`T6S7vUT504#-H!jlL<$Or?`Mpy_N@kBz9SR?@vA#0H$qyni$nvf2p8@Y{0 zk#Xb$28W?xm>3qu8RLgpjNxKdVb)?wFx8l2m{v>|<~C*!GlBVnrDD~wrdTJeKXwT= z5u1%I#8zOBU|X=4u>;s)>^mF|$G{ol9B_WP7+f-LHLe7=57&&lfa}8z;U@8Tyei%l z?}87(bMRt(A-)QK9Dg3)j~~XrCy)tR1Z#p1A(kK{Y$Q|=8VKhI{e%(1G*N-5Pjn)N z5P8I0VkxnX*g?EW941ba6iJ387g8iCnY4jaNopcpCOsy-A(P2EWJhusSwLP-t|Xrz zUnLKcKTwn?CKOLf97RIePB}`sKzTrUL#0v;sBY9)s+hW+T2H-1eM)^VN0T#`^Oxhv zt&^*fYnAJldnHel*OzyfUoM{~Um<@={-*r60#U(0!Bc^wuvVc);k3d%g-J!4qLpHZ zVwz%!VuRu}#Ze`^l7W)95>Kf>>9Eozr6C$Z)1`URxU@~QI@)F0FdauXr2Es8>BaOP z=)Lp_WhG@>R;lZ?BJkMlIuMhw8Ap ziF&yDYW2hFJ?fJhni{?u85&g@mo&yT8JcdI$(rSw=QPK(Xj%)k1X|@<=e1rim6`6$ zRAwc!i#egKuI;BS(LSWzt39n_sIypSqfWEV6J3%nTQ@-4ii$R;gsG*9XzhRzXqv2yCs*$VFDx+GXJH|L;wsDH_KI2;^ zu!)^Xl1YupO;gy^-c(?^&$Q1BYvyPsG^;hc$D**@Sy`+`)}T4VJji^bd7Jqw3q6Zi zi=7tT7GEswEK@D(EFW1ZSp`^awCb?>!`j4}Yh7b~$A)U-W3$et-R8BesV(1jzwLcH znq9En7Q0Tn&-M=XBKs!$F$X<|c!#|X_tWYh)GZit(Q)Cp9CDE^WG;+fcyOWARoj*0TI>4EP1lX*cEoMO-Pk?Z z{kZ!p4@(b`M~lalr<3Oz&kJ6Nm#vN_+kA5 z{dW4@^Vjg_`q%qU1ULk&3Fr!>1V#i_2R;ij2@(Z$1jE4r!MlPVFVbHmT+|iPIq0wy5aS{>yK?9ZAjVh%SOwMWgFja zir&;wpi!{CU}&@N=Eg#~LQ&zpEzVmGY{hI9Z0+4-0x zS$$Xe-OToc?Y*V;rTcf_b_jRe-RZjXSeas3UfIyD;9afd%<`i0x4T#DzE)vdabOQ= zk7SRuGN`h>O0Q~1)u-yD>VX=Mn&!Rgd$;YK+Q-}1zu#?t(*cbG#Ronf6db&N$oEid ztwC+YVcg-Y!_VuY>bk#Ye_ww@?MU&F&qswvrN_dLb=5o6*Egs)ls3YRlE$&)amR1{ z;Ppd$6RYV^Go!iq1UMl%@#4q$AMc(FJlT1QeX8jv{h#)>&{~RGq1N2iiMFIRX?sk2 z-|2wUogK~{EkB$8eDsX=nVPf8XG_nK&J~=SIiGia@9y}|z3FhX{g&gc zj=lwb=lWgyFW&aLedUh-of`v-2Kw$UzI*>(+&$@i-u=-BsSjR1%z8NeX#HdC`Hh-Z(6xI-`hmHDqv!v)W&&nrf>M(RhcN6(D;jNN*% z^u_SYjF;2ng}*8Ow)d6MtDk;%`@Lsk$;9w$(d(H%O5UixIr`T2ZRcd@}9@pzr^FZ_ms= zd$0AaZB(&b~$*G9xSbv}_g6E|0t0C--ATca7)hPTbeCik^0xLpPBy=6&MvWK^ zz_36#;jXYEwKETXMbBung%k>h(Wa2(UI|dBk~!9hic-+9K*=j5st)CHK^^IxEK^df z5~H&L^I=WIr>LlxGVuwTO6PnN6Kr1cWHoqMTKVh&HqWBx);%a1aVQ#+dbUWWu>bmRc_w$4IflMI9Xi7e;&} z*G3RLlClWwHV>pZSTaWhFstHtyj)=+OGU@R3KMSWB@~XNu#+!fwH66w7ynnTv~XNM zl@xVkrC3fD5_NJ}J*K?a9~i2rd9A3FvA8r51v{-LI<#0h3gJ_3B&Q;TWb%Rn;HBeE zge)-LEW&Uf#BC8)jGcdBPu0vB(>XOEvs3^gqR;^-&6bw#ViS){Y(~OFsX@vT6GjyW za{Lq9SRp8Q`ubd4C{(&2KNIKOfmRV?Mz2g=lK%}$&-GA>PMoP~LnGPP?rrt6r%mqK zqZbqB+Oa08g)9id47K83XS# z2uVR`&nZwTq>C(QVjK;abw#I)DRQ3F8sWMzRJio6AWd?rP-Mqc;38otQ(!`Kmg?cq ziFWd0ONlA7BxiMV9Imo>92$rN5Nk^_rAaF_Ef}LxW7Jv`pn@WC2qGOu;$cOZvyuo; zd?19}93~+X8WjBDNYpaG(7S~S-=at-PSTSB%@jItpD-!w0M3MjDSl|fhM{=j#Rw_A zJ78jEq9X|zA`jBYv0^36&B4%zg2-TIq@Wl<&{0VtEg7#MT2F~wE|nsbjEgbQkY=U| zTuezq04ca|8l-|cZu%ny{|Lzkxit?o^oABr04A-_VF`gEa`_~Lg`>-cT7HNfwUpG+ zDZ$0SenPIe6uZR?HU2pGf4E#+O4bAiR{|wfCDm)SAxL#*t%N2BHemz<8xxool{ij} zp4@+7#RxTpDdyDq|1DawR%>u$uOy)*dh&MX+R?{DTlIX~qmqOR>!A>Khn8 zQOU7&Vm8`0xk!!nqE!-}vA4f}Y8%6wO7c0naBbnJd`ofuDuev9a*TvY;Wx*WqD%2n zmzI@K8`CVU6-&j5Yel_A|GuSHgpAD%M?V^&4mn8A`TJ2N&&ffWwogUR=y=( zS~x-O1eQ*wB$un{)2E7*U5_5UJpN247Fw9PMQv>h7c4|uv}nO1bZrpiEh#qVVdC67 z{yZ%PjIfw}+NcU$HC>!_304{cT{){Zuhv$~D<;XZU13tju?7=@8hMpnwYl-=(LSw$ zMCml8u0um!>uQIZR|_j^RHdz2)GDnatL)lESh#TE0%5Bm^XJZ)+d98QQw4}=mR8S8 zmP;7I3az~|E>@F0R?$|;eH#=rHB}`m*;d*4rW+4SC0Je%<6}5?)+d=s|pFu9&j=-fByUh3+69cxDf0G4a&w%5piiC=LsS$3=3qgi7JB#e8wh1nsXXUd`(*^Im$f1E@ zG_)}S&>jpbs`EYxN@0Pb95A*x#6(**GK)h6z?-jZMs*-d1Jk*O7Oj$|9f3&*j@U9Q z&D$XecjW+N!pf_0Z8ae&2`U&ljT=j-HLbuTh0Tjz^3;Vz9FlWulY=ZRM_Up!vs@{0bQVcG1|eW5>oOoMeQZ&~q3Nl1v;X7EBL$4RsCD zl8%4TA`H0j-GpcZAsDX}hk?S=j50JhLX>zgY|sRqu}N!;;x(E8m_%bLN`y+4lqyMu zNd6!zGP8%^FrINRd`6K1pe8_)6=Ncl6e4HQZ3Nqhz)^{iX*OuY5Wq*Bf5K8;fPzK~ zXqY%{q?j^&>QZ{P<{nXOlE=c~ zs;*t7jD%qlc1pK4w_`p>=B0;3cZKa?vL<@gW70h(IgaIYAGVK4#RW28b!|D|4 zjzvJ_uv2{Vh{C3w0R=0qEkO+TAf2V-qf8EcWz*WV}yf-9eJtl1?n9PMr)oJnLZ#gvw0P&4jt|nw!`lC!_Bjt&oPE zbOX|+Z)}bRZ1-y%pkp+?_$wn&$Yvw|*h#=URBjaHn`4T4!?KtURiqf#*w zsR8*?W1NH+4Adwy1pzJdqzklcu9>B-bJ);3#i#?9DRE&cIcY#gLTwlph#)>Dpt9P^ zUe$<5E@8lQ6ERd6+o9G$aj4eZPauZC-m%jdX)1^mG^Qs|(0Qash$KA92tFZ*z)TRa;_bvT2q~NQtBmW;HwmP$7=+EEIEEC=0qz*G42h}k=px{BXZLq-3wVuV~VkG zRC2X>r^p@vQaK!Fzzxfhe1t+arinaBq+~Rp38oeXUwy+O$=Ib`6)6Dmxo=~KN8eEd z#_(^sr66IhFe{6n|3yoWVq$k{vtTdq$Gct(QANQhuf0CACH=8xTlQaOt^NkYVJzxMG=Pgu2O&coRf0 zQBsC@f|yMSazBIDhd2B5d`?&d*hp$8vFI@hxw#Q zAI+UNH)4+HA+8%ZZ~y|CH@B2yQ{&Q0_wCTo!M7%d4K~2$&Yd@A%$RrIeYaPyUPD$N zvh>nRSqmi|+Et}oTNkrV6~Hb-04#rI(MBla|YH3 z1w?K0(xYfNUFg}fCts#h%DQb4_KAL+u(q0qIJfB3skwot&=qagteJV<($dXi-4wD| zgSm6(e(=FN820YHG}qQ!2)+KBQV~?%*hx4rPvxrh#OSj%nHX9cR@yFBK^T=w1SC); zXL)9G^})1c!WwObpkg97kSNUL6BY8EKnO|}rC~y|*nW)3yN7E`4ic3(Y^Xc6%Ixw9LayFjCPbrzLLR%xrMT&1mW z=1IGVc7-M5vc5ddkSbx-G{crW_*AQEfacZ0|0`Ejm1_%B1@N>6RwGDe?JBacc2L8g zA&HR>Hx+jlS&?mZVxgI=GX*TsV4Nj*)Uj2$&)Ouc5l~SjtePg%&w8vdf8vQJcHViH zY}(Y+w7~`&oOar2TW-09h0i_r{5IQc^YyQPZTRrv8MfPQyZ`ymf1WgHV&~4CPd)Xt zi!Qn-tH7}J)?1x*)>&Wp!WSUC>#n;FJn+lk{`R-dJ@?#Q-BB8FY2^cir{J6HYks{rBHD2~HZf-+sH_|Ni%$f*dYt`6qn% zLD!ZR%inqDojv#5YuvbTo^HPR<~QGbQ)Attdmnn_D_=Pj!Vx1zeEG`9f%TEw*2WpiE%RZ$y%cp=6c_f+8 zVGHjouCw0yyML*3OG^qnc0vSH+(IbG=ZtY;#K*><6yCJz*`(2xcLr;A+H(hBVXN0Y=UO_(+FQ=tM6{jdKpw+-fh5xbnS`T>0EkwBqy$ zCrRZk_YoA0l`NxTIGoav+=KusO_d3v(gdBKucKB;C?-z$Um>Kai7!p40R=crPBQqU z7{6|Lz-bv4dc~)+Em<=h28F-RdY}=H2BR}2H0cXX?Yomv=Mt-z&-Dg%I28Fb_#UD+BJ8)Vq(WNB|e23w|DaE zE+=`Z;4k1Q8QW*S+$NdQcSk^yH1*kEM3UzDSeVmN?swf~mjezQHhubx`|p3?!3Q7Q zV~;%^eDHw{H`stS5ubr}6jTslZv78_aPsP_tu}qejHgCF_4_~kVfWqlz)3^@{>$#Z z+iu%#yX`N3`Kxby;~RrkT+u<^ci;UZM~?jFH@`7t$m)@CCQdapEj;bCz=vM~~8uarEF2GsTl&Mp2(u1>#Y&&@6l}C)Y0^a}hr$60s#~nCNTKfxY zV*xug<1!2?P~X}*Z>ODho;-Q-RloYx1{usGdk7W;|oYA6~Z52IRzfbK&@E%ep$8W2NgBRB>(i;DKx4MXNrsnDF8IAAdAy zsiphkREsF`vS+8qmZ=jb{^pxU&wlgG`8v133o!7mQ-pyN9lT?N157dCeIO&kkGE1B z$W+lXzol|j0r>2b$A9CJc3vNU<4nAbNajCqUIX;Q{vkbKin5DD19 z&d-S=3-58Uv!fH=jtP_ng=kt6hoCUzk=%+xrow3DNRtLOcTa8;D=ORC4MU;U3oFkg z)xdEuOVr;J_u4J=6(J!7=mS9)ksj}e1W_2$OA`DdmNTjtLud)lMMAWq6hB62faek- z7CrFWzhg*V2|_4ojhu!d@Lr(4deX@!Uv%L`*I)k|M@Ej^ZoBPL3F{si`3N3acN{vDVWqqdKIk9^8RbvQz%c9TR$Vpcc<3dU zUV73=CtrvhfAbqCe|^ob@&Ek!!-sFX%{DI17dPJcJI5T8Qm(`EI|m(f5J*1!-~*gk zY`yh1U)nWY=F#@M`<{Dnwc|(UoO8ed!{Gfp$9@OTs$74=4P*GvKfSLsXwYB&@|Qo} zb=RJI>|qxWqOpbwk03M_oUh!F*musU*X;u^oLj)8xpNoY-H=RZZ#lEDk2_BbCQh6% zVZwNrb?MSwcTw=Ey2+GY>+45edwuJ;vE7>+dpCDls&l7)U7MF}>AYM^=Ko>d|$j9$i=N*@7P974h4>%ktg24CvOme@pW+T{|t^xl`}XO+A|%yLal?wW&jM zV~0-oj0HT^gX?^hIYd zST7bI>!My$?E#MT3q2MOV1WdXE%!=5s3HI@31OnC4rE8kNx-3gdElTRp#eo1C;GTI z<5=@jAFqS7O|mNShX?5SQX%e34%MU64h>4&2|}d?Nt$Q?7%j3s--CleA;DIhLip~; z1QNiU_bFuMZ^R()i4*3)5FOx*wvBjX4<2%XM8}AXQLqIMNi;74lRhQxXc>tC=o5o! zNF@t)$%>qWQAR^SId&|Z{y$%?RB+YGMb&=528cbNf_cmu8k5({gH&6uqYKRi^(cBA zxZJA0b>xc0k{n*JAX+tT)U;4qcP zFC504Dk-HNQ!bW;(Nn&{iYuVkr{mE3>O#x6l`st^4 z$BQ zko@7!J00H6yX=A|eTEM|Uqu#=$s8=%Eo2`>Ww?=m<3uvtNp)?l^XB5kF?`gLkHz+a({r0Wd>)WEZdTe^3bIx-Gb56$j$`Rq~?G;E00w=h~wQ% z8%AP_XlW~yUxtmTk$~dY)*7fbk-q#ahXHOQd_v1IB?BSlM%zT@+CU*?@XlPZiH9~y%AO$m z&y*|0pDGzic|TOtgb^xJlmz+Ou#~(~aK^$F*=b6(Dx*Q#0^&iZg$9|K2}ysh9R+5v zYs@gk4K%G(il0uyd5(Y0ZK(QWaP%sewSZb(%u~Mq%I`%MI-#N`6dupi;#Q2 zzI~@moqEKP|9$)kCmwj<0f&9{ur=3QQ#BzKer>IRgRgdBD)r&wm6u<}bmNUTwo|(d z0B@=kSco3J+~&-hg=bQxPMiAJqmTXk=NIBsV4r>VF%qy-Pd)YKTW&e|3gtPWtCNAM)TEI<7-FWfB%E^HlX(o4GkxraKaHs9{JEi4{g8w_6nME z1+0N4^cXWfFmS_o*Q(UG=jJ75-R$w?3tnk~28h-K_KbvTQRJnm`{d(~X3v=gb>}X6 z#a#HM0fzY@8E1lcAjd=fg1K`S;EgErS}~Z9-#K&U&z{{ndp5>+|7*AjXRHw){wsbJ z2kFVrf1F`8Z(grHJ$rO(>DsYlx2BH0IyLoa#uW}+=V)H8Yv+M2opI%3P`9pwx_4c< zN6X+IT?hAQSs8uLmSwu|*{0lBFBb@hT&j?9P9-}2u+veoVwUS_0Zfvy4En~zd zYpu2bU?Q1*uikUJxcPfQ8WH?M<`O|7^J;K}V?Gndb1E z2r{!I%MGK}ww0yJuqrL&g~}$W$hGpaZH1vsDmEVKol8w^TA(~k0>zsq`Iv&QjzQ>u zU>grwY0xvzJpI^Xj}9BQ|BW}^wDA|exXrfPUVGhjvu5*gBzuVg3)tQ*1xU2IHdx`c zmOuW_i}E$=C=`+iUN=m+jww$dEO@_VushJrQ_KVxK;}y`}*7 z>fH-32pu(gG|o0~P5!*|&chQKIlNC@`dxP3880v&`R6|y`N$&=!zZ31@s$1*#>#^S zue9>YgY=8R0eC@!3$6%}BCcUG$Gb~8%J#e8{cg8z-Om2u4_9Afjbpy^ojd<{C*B5v zuxppzj$njxu?VR|c$*9u{P<=}_a5D$|LCKS(6iO!QqaCDuDIfP!_Oli)y*WBq8c#{ z9h@@)-3M@p`yGmsAx;DEQCehH^J6IgX-h4xSm4WSKKUfQ?Wd`8JkS!99B4@9`g(i_ z=TfT=UUu!ZXHA}rkL2vsrKMB1E?t-E)7+yE^8Ms*W8WG5^yIhS?by^Q$C2DE=GfNO zu~Spel?M&leA5jMKKPE~P8|QjiyaypOShbALq`HBu8UyYp{eoXIjy+DQNl3^lnWxJ zD_HbWP*`fplXDoP^fjb;It?>E7)!<~JED~#h|`dCc26+0oTWe6J4M;in{4SYxNOFt z2(dh`Ud{lU7U{{Bvf^Zs-qA8pv!bJO5-SK003Gl3O8yyZO2OGBYiTe^2-Qe2CWMrZ zn{=@=og*iSp@bJ3qd`7J76HV;PD*tOA5Ow)63rdXnt%x%PqR~G)S6GdYff+kBq)he z+F?LRVT&0B@mDI0t-xk~Oa;Wb{)i-7v2?DE$jD_gqN$QnKDqJ=5gNTbmU+hER&2)0m-AtrS%T)|3*bEFHnIJ)+945Y`WCMguVeQZ7uATgyIh zMwPKr%2p%ngzQJI%^&84LyS^`4y`~a_1E8E{SD6j$+>smeK($H zIO^!5zxTcG?LTZ7UNnG@Rw}kJJykC~qpYjL+dA?)J9gP+m*<~*Zk1IABPyt}0S9Tl ze8h@m(ecL}x5}!kPMbOv5C8b@|G)qHYj`0fPBoH69i9#O)vtc_*kh0HyU)H`ZV_)e zq3>J@a;X~J-62KA0KpXtoa=yguRZqy=#fVr>EFNqI$u~Pf#P_{#TTU@x%A5{yR5@= z4DIE(iWhzG%7dSM=9!R*ffUyV zIKqo9@PQO~5+@ZofyEam7E`87@e4j-hif<_pskwA14iDlkQ2lUTU)#J>$}yl$Mjfk zd4Q&WF#hq&F2x0m)py!?vu}Q5&Xi9cyX2Cmueq+FV`Gpk@qo|Z>b6YZp{JZQXv=K? zHdYr)|gGGs0YoyfuxC6Wo0 zK81fcAm>B(%+>TT55(A5)l#VViz{oMIs5vM_v(mY%&Ve97b{^4(CF{ z#80H83Dc$&hHrg{c(KB$&?3{zhneniq(M;&MLbZneW$S<=g=8eZ3L}^p zkWAo{Sgt#7z#KCq7&0CH*_I+IQYgStMIhwbH#i4lRYfOj>Kqo+Nn=9PBr~2iXy~a_ zM9GykjFA4R)z-zBGjquh*=Z8JfR8@<_?~<2e)7pDUwi$v zRaPCWE$*m*q6Nd&EyZ+@x=I-AxYJHsZn-&vI{KKSUVi1(%{JYvTT2VhB*?Ft;>-Y- zD_(o;HC$Ygb1KNg9D|1S#h7?@>Z$JCyZ6Q$Z-ny+xSu&|_R~*4bMV0j=OT*%sJg=s zKZ15>jGE>(Iqrf>2>0Br9A86@s}K!vUEP3z124bq(n~JB_{EoAyy~i}Z@lrwgAY06 zsi&SAGGvGt84F9UhKb{rDa+fdckd~aCsXXY;+>l_`PmY^d-b-7`-2ZY2p5EYcHVin z-*&4dpp1>dr#vWA#kJZ|0ZIi^VKC;iBYZj>S8?Vqn9nzPP($CcRTTd37MC@qP5p!l z{GZr>lL4P?0H!+W4i!q@tpHZnp~IAS-+%bLpa1@tV;AcEC$HUg*OMcz9yQ{cYxh6! z(Vw5+xmTYZPd{_5J$J*Y2JxTP8aj6Pc--4}opRbde3ZvO)KqEa=7uy`4@oJhNde1b zw3nY-)|M<1CYvtAXDy2Bf9@?O*0)h3Ny1;58G<1PHkXJJ@HkcsyjPQz8Pbdf z++DQSs?obxXs7rhC(T7`EY$+iTtkMy>j6B5B@RYYA~Xg$L4au~u=VKijA2eW*(f9< z1Q&+fY$B9j(vi$fVQ`xMIAov%5yx@-@}RjBw2{CP%O>DFI398c&p~DgFBFkcM=8^j z*M-O!g0QPFAvI_0ZO-0RaxaBJG2|xHGnS%_-A5~NQfMzYSOOghct@u`xuz=#>7N5J za{`0^{7Z2WZAyfJr$%v_Tl#M-mkMdG=u;TnoQjHJCLzb3F^wW-%V2_mUW{d!D3qf( zB=ku42I4SxEKpj|Fz1b$oY)Tr2+RqkoFrZx^KFM3s&U{(iU)2`lMP(h_S|gg))>c3 z7UXhFH}>V}KfH}cJ@MqXzWr^y`v5O!z_a-H5QQGy^hNFBUxEunyupSW9Q&PP@ur4R zqecxHGzixlCVV)_;Wl>6pY~XFOR3Z45U{fn{7bi#wb%N>a?36E=SLrfOwOexP)PQF z_tN9THpY$}``-BXpM3HOd~FuqXe!4fv~v$I=Py@*ZkV-2MUFp;9KVJfCs12j`VJjC z;MxzaRSZAxJba?|t+(6)y(nYp<%LFSaYSDD1hAR2X6XZgAcX7sY18_!&CQKnI^(S5 z@yo9G;H4KJT>qeh@HHmd>%p{y0|;AZ&YnNVpI^2FVEd|+IkkvTzm7H@3^Yk8SR<&B z6qK8aqk6fRNms}*as}0Um{2~Z+qw4{WhBI30mc{;Em28YLBsz6OHFXCYGx@9%41m3 zSB*JBAPY%N&buMGfIJ9nlwF6~CW6vf;B;;wNR2Nhn1w6|3J~0+2~{|iD#o(n*yiYg z4Y;BWTq*^pR#TfYDkO5v&UWg9j)6d4QUu6~+^13oNv>51z+tFkXk{`@?k#n|^c(e0 zU`ZSghZf`D)I4Qh)Rw^zS8^V(peZSwspK+IA{bGk{~f|Ig_m{(OKmoq6%8}5Y$5U} z`NZ1EQI+0Y2?V7D8YB-{L|X|d`FqR7JsM2pD99l!YMA9hP{rROH8P+A5M;KJ35|%5 znT|y#d{&lLF(MIj+JTkXrMN|w{F*AlOcU6rp^m-5@Us!90p+g^f=;5P}Ip&QqV{X6gw%xw88y@hA|FSbZ2a9#l+^PAzpZ*k| zmHFeJ{MZ&xniA#3ToOvg^mDR3?%-&vXQ2&Ymazx4GFGz6Cak5HcGQTF7mNI{QQywAW-yG2p1 zT6Ba`gD4B~xN3l@C3z4`8COcOj46p@SYyGrz|;t9?G|S)+q5d?sbLF2UfLQ!c9(7w z5@dWJ*4FmMl>0JInZYh=wM8anmd`eBhb>hG zs#?23#$fE!gW zVu(W)+P$XivfRvhns;wG+^kLD3PE{N9@`5fwZgI}Ys<(iw8z}n%54>L9wg9Qqikwb z*>hR-cZ|hd;9q#*g&}LKfvf9yy(B)+Y0T@dpYnqrlt0O_3SU?*ezf@(TWq=Ime*Z( z9p32x)WCrQaSjphK2?UeVDR?aZ?C-4N;MqeZRDeme)!>s{z%QLrLQu{;eG1T<8wT5 z6$GahX!yX47JUX|6CrhI z`JxC!UOd1;5tKaXn>&Y>D`3lKLU56sX8sR|ryYV)q$daYdMhao7#)`mjvXIh_qtj7Vx|-&16$}*XmHyW--sKFV@P`8g zf>MHeQ=O}zNIo;cwV^Q9i08rrz>G%tOD!3SkM^SFjPz`hSWKx#iYX8#CfG>*3q@pN zl9&?@s7mVW9SKB(?z31}~&@n4r^&=Ix>l#B{a4 z2=$+{#*{h*rhrm}07Y2{w>081ngBG~*5mzyXP$ZHSHAKUyzex?3W{p6iYnPH)`bAz zqzOSMo_GR2m=gb0UwrY!IIB47sH5~Nt2-c9<< zv(MsVrtsAsx7~Idaz5phABc=~RxFH+4N1`n|2SqM=~A3>U}bUP>`CotnH zHV(xnWRp=0WQ>LrtW@ie9C^f%ef#wlGFd>QTgQnfoVdrHdoag~F23}VOCNpg(Zdcq z>vjX=UeB|&h<0(P?!UYTC<(s;|kqLNWF=zH{(D-siu;cUs#yE@M#Xm5i zvGcCPd5U%=rEYDD7UI387~^5SrSDR!?YPr|xpPL1xRP%$ZEI`l(!BMtM-SL=qprPs zk9%z7A5T2BbI%^z9CysX4L9u4XQ?sw+;iVqKgO9sBCEp*#9Djoy8eN~ntSw`IOg?d zue<((S6*9hzyDf#wN>X#oz@YbvC&pH`l@TY^<8THFCVaA-rNpNO|Ra5$J@`c)@N4dzwt9_2e5KdxF(%Ld2f=z0SjTJHlRQXTaN5kAPb%)9=qcsj{hmkxvTRBT% zGg7)@$U2fhb5}!ID+-FOgssMeIdqw*qb4`v6cLUjf;oFQ)Pyn6Gd(J(n+*cGW+M6A3zUMZyS#WLS`-MK63a9{LJ@P9|l9qf(1>7_dY| z?BZqcq|f418rM@K$pcm7uuocW;vh+r2#n;lE?Ru=#1rv7TR%AYO=;=P7`M#c)td&2YmO~?`*c|=8>K{c^;Jh4^YTrmLomQ8c_3^@t-5zv!ZiAyo~_cPy!9a-1UPKJu6;qn@PF zo?L{NaN=4E-l9RFYie)YO)otE6y6eo*UjR}0Q!N;4}zJWS>T;CxcI{kd*`Bq4}I^+ z(aU%5idSuP?%Dmn@42g6zhx)?ZQN^j{SjcamA2X%mlN(g^Q^x;F&Yo~cGKA0^yTZW zS#G@zpSkwxdrmpCu`@nwynf#imk-`%yJxPw=AKi|fCSW@ zzj$Zbtf{RF8tdyf8@BhM!+&PK?sd5)QsCO=rg3Q=3TB#W39XmLFpo2VmZp$ZVzOzV zI1iaUlxWg0*>DGX9~SHh13KL>BCtYS8kr|0qD@fJVz}4{SSR|_A%#sf>-bUSP% zQx8jm3c9kqc5E*d26<9ON5EMZ14C+ol@fxJM8{M(mzbiY&JGA^r>@o)Q71b|(xl`r z^A&>N3Xcel8Ng4K8UEqZm_=c^&aX_rz{DVxb*lUR$Okut3y^;VTGmo^kKARt{4{w=&Le< z1g|W4>#eu&G!VX?4ba)sr*`hn5A~|#lAw^1Gk7tIa|a9{U(wL99(Cof@G25~BDlgs zj|KGOG6WcBa?jvSB5IgrC4?M&z|axM92}o5m*^l+L2Dls?&o-Bu8<IKMKI3oV*H@J5b-lEh3f1v*TUU2)Ai+=-9l6s-rGxvo$J zDd!4E~W9JM#t&$BZ>+r!q=mvCECXqGD0!vZ=>}3l=IJXeA!m zi^Fnm3CQpw`Y4#KQ%z!RwMGK4*r{TG29B(x@nWjD)Zkh)^PnYSurlK;~#x_0e?Ps~g%989GP$mCa;sHVqDSo+&< zFJ6~mF#4PfKD2wQEw+lxBu^MXSfVubv2Y)wsHe&Z@Di6E7ZUjHP?(TctCKvE#tuEu zn$)_6q(}E2>#et*lUH!)7)xTZk;oNWVC>DnTshu!lc6e2F#jmbw+U*b)oq+=H=bPJ z+5?^kNs?mC;*RDyiu2?I)kY3or1xiVt3Vb>s!-?|H$6%dWj{_hpy)%l!|1 z@Z$6R*Ij?JZ+!jsV~%T^zi8k_>%a5V)3c{c>(r$S@5F+d>%zu9?h7kYK*4yA7cv}J zSewIyHAC^hrh9F`JTYq>g=l1tE$SA|R71r4fV*#X=)|V-*jBL?g4DFe(d3E)j_x zR2Ff?DNPS6_6GxI5^}JF9Yw`9P}GXuY0+Kck#l$CmOXhA03rsJauJJt2Z|cPQ{|{Y z$Olv`pUmY`qZFje!cY{GtvHO-QA*YTYMCVmNgzALsBGz$NQoJOho$ne%FvPrgbvMd zQmR1d%}pXzLJ)=F0vQUtN~u~a0dg<~`%uiB!$V3rlD%a-b+S zHEHofV(J+%k5*G4G1ZW3#v|tZ(``wPA_kIrs4^*HlA2xiRFj7?x)O&eIsaT-fK?lg zxzKZjZg-rfbXW|z-Bo( z|MvKkct>kv=PoeEMUf{*jM(=VR}9(pO9QUG?w!%k4BBkd=YMxIPC&$YNwU~XHKkS^g5VdxKK$JEu+O^_SHGOic`N>bQj zNHBiI#r;CK>`AA^u`$=jzRXP~ENIF^B1%KF`9v8VJ{YZPD=9g8QzVYaOi==d62$;b6poRj(SQYF zX<4+WjdbpeSJC#_|G2C;`>b!TF=R05$PwAH`flJ6ZJH56FtKuya;1UYCQ0HXbFc%U z;7Cb$l$wgLR1Or=9!JGaUD{KS8A>LF1+2WW{??L&-b-^Z#u|cG28Pg7SS~Fq z0Z(*FzZ_Dc%Gf#_8pjOTNJkDdS((FPhvKb42F4ai@v@?fiAQD~^YBk`tXK@5d+s^M#RO%*KvS|^ z@$DAM_J82gyPn)~Oqf98f@G;bWaI`@b`k2Nk|MsoI}i+GVSTBuG-~C zKUr$5b4p@Jq zO^-YR&%fZ4ygz*Pb)SfIP>qA%Wx<50AnJ+~6mI?0sWV1D#W(x@lT8bUC1QcRbW!D~ ziYh2I9C3+MN-q%w7N#Hs@Wd6D36qGFbWle=olTZ+78nJO$)l4X%T_g{3UD$(?Od%+_5H6eq zNHaiPAy~=M^yy1o&D14D7`LHW8C_u&{H6@8j!_+AVTQg6jLBj|wSZPTDl2IStB*>lkfh%r> zg_S|U5tDy&xfmWBiy!gl!cd~07!bmyqN@vSs*`TP1PF$XHDUQApbOtJ@+Pr92x+7> zlr(YZ7?XStK`P#>0L}saQrVnC+yJFa+oCjK9I`_XHT~rfopFR9dLxqqY3MWSG_XB~ zj7{1qK%&9XtuWynCZCfFF}udDg{v%|^vr-=5ar~shpfJuiK0IYx@cG(TuF#Cdnq+2WVWv| zv+<|(_<%G#Ju!5ruT7giQ*O5WlU_INh;QkHzd&&oGB1W3e&0p8AoCadwEN;@+5#%CAE&| zV(x=*F_b+!fs!6aMxX6UjDhtbhb9MkmJG9i_K4o}G_4>{VnU=!0s)K8VuI30v@uJ# z>_xDks$fjA5=$6Mf-WH_&QlJo$f7Js&I4gUiqlHSaO*9Fp14VhUv@fZ7^5WeYEWYo z)j3g#Qzs23*lrls-jk64O`UC$j}VtM)`vX6aZ9W+f|3&3vd>A>r5w)y03ZNKL_t*9 zEF_u;7G5fxC7F-xvpR`BKNs?VE?iblDYt^7NU6I1o*R(jG!(M`QA@83QW}v>j+6t0 zpR>z2h{7<7k}U+GvUO1;kF2yAPZ4zXhCNMf()nbDGG4JLUE!mMC<1&y9Gu{ELZ_P4 zgN!f4!Uss;of~?Bqwi{~0f84(;u6BVS+gJd=}!;5=GQGt_uKibGw(k6l!dJe@Sct- z@4nrCoplGSw|IQrsD8lX3>8}rs9RJ)i12)*G=YZwM{rR!{#*_Sl4X4gt=f*hIvZR~>bOQ%2 zbKJ3q0M%}La@33YKiYlv-eHC1mu(jYp~}Q6vDiL0WJxu)XDSLEud308tAWt+4?#xS zib3PtUbg5p^H!l${8~BrM3R(*M(F4^`QjJwWJg(&$FIEl<^vD%qs-jKyz#fgk39X> zn=hbe`c`}~2D5ThNvU*m$T@69fv8jsZea!Fz0AB>l&Z!u$QL;|OkU-J6N)T`DTj_E zCbH(3J~2sE5HF^r31(ZXhp@JpiXn1|l!HJF+tHIMP+GfG6u_J!=-l2iH z@ElOV=nRm~6=AJ}l|}}N3bu|oTnR;&s;Z0}Jh=!4P6Ey&Dh%lmjav4Y%ieN_^O?#8 zEBgTte@H}PdyiCDbxG(^2H})QC}<^&l#~H43v?Q48kZNy#mZ5mrJ%2%A&-p7$UpdV zcESJ^%LN^Y<=aQ}GN46lNo$EqNRRVW8qKu$u$R}wDzxef30*TZbpP6Q`M;%iz5j(v zuhrsq;O61&Ut2?qr>&sqekL$RtKi9oq-_5`E^?Ob^6`x}PS~x;% z3+Bvya>SMUU%AmMzyJO0DO2$}42M;5#X{+^=DcO9Ancg}=E|#Xz;gX?V&SBGo2OQH z1}4lW7Q^=6Y12*C;f>yOXuDX z5Dpcx;?>r$lABPQf)EDbNV$7#$+&gb$btoe(2Ax+7#^rd!9RMIfeU7-IGwjPsJsFu zxlLh%S;XZDYopj4IK7BY2M%*HGEJ2NOcfQWl%K8OgRwF1NbimRCt1^$B;T0eU9nsoL2U`cj0mR{r zQUQe&bLeCpF65Fp&e6LISE=ZfMh#Fig8aE&$A?1U@y z#0gSYk8e4_7nh%T)|tI}^`1C!!jFIS50{~3QE|hlrs+0iW7?@;Y&Tuir54e zC)FmPJAB^OQY)>9XE*LY>#W&RK3TM2e%Gb@_UJ$0{TKPFg^o>4Ph9aUeD!(1AwxdK zcegzEVuwzh-X8Vz4PQBQ&E0lu>AUpgci(&Znrm^+@$zlAPM`P@u12)Zn%&g33*J!r zmj@nM<4ZfQwAGgV*I8%Agb5G+mr=kY@Vi|5m zHYLiWS>1{jHL%z^CaV#RHL9`+f~+z+d6Bau@=}mTKcx29=n7&?5Jn-=$V6Fe83Qnt zLNRw3`VecI!w@cYk`^kZXBHm z+`<^zgv!scT#Pq`5@9e?-T6jP3Ni9^p{-CZV6?Pts-v9}mf?cu*-U6$bD zmRoPd_j{di-0?ko^_)6&>Qz@?waz;0;KZV+TwUFVA5OUVl1r|>>MDHI)}@zTdf1_d zBDBwTOJVJ<{`Id{=6 zcT6%(X2#&c3r<{f?S0Jh{`-?&eeKP))*PGx?ZyUSB^75liFLHuHe*au+m``0FH4qy zC#(dm8kVNyz_i#KiL^(LmNcxxn_}`fXJNxE_W)F8t8%e8aFu!OH1l|nrzOI&td<}o zRpyu?W%t>p3S+s2m1Ez1WV?0-*$M;v=5+@&tIB4z!p|ZpGkBb>Jjm0M-?FThAS49o zP7Z_E8`)oX}4<0=DuYdh3A3mfjo1}3% zX5+d#eAG9-(i5KaypY_-)^H{X2oDW{%_?>4*Sl1qU8)TPIX#Ump}9)9@Y+ika9 z|7DlG_rCi^j2Lm~p@-soL(=DJl$@1@4(0P(`jV^9G-R?-p6aEym;f;8Bvg_RK%^`z z)5&;pNRhT#lrhP1Z0E(Bd{71zu|C6*sZZrZ06ng1;EO!)Gz5Q}oAEK*_{fT?GXT8a z0xFy_z&)(d0015@%Mh}jU(nvvsYAy`UU-0$MQuC$9B|iU(~3i?%uuI&>c3(f>ERR;pk;#CdZ)a*H#vmO&~8@m8Ukz zhIvpn&t9s)z+~F83S*m82|X<{TT(@`=9+`sHLMj@87>ZBSh)uhQ~%alSzDIdwpMOT z6?0kWu~T-RomN>{Ue(*9k*3PzwZgKmG8kinO&zx;AMYW(;| zKiYr){g+v08JuL`BcyJ+`R183;|skFEBECpb?MRtPlB93eE6=r?h3<`PdW(pEi+UNFfBU*7!qSLGBZ@1t4fUmh5=c! zsVw}sD?N37ylwZy0=9(VM|=qhX;b0;P3XHW)wAco zWtv(#H+S#a+#~ti%Rbbsba@#FV-8jPfNdkc;9K&2V>wh z7DeqCyb8b~FpX$RL35v3P(!5v8I{nbqptI7PE_HjfSAG@bY9FAiGdtSp(4{Sejvz% z9t%PX48kB{G_RIkASP!DIS@X4+hZaTmAM=m)vAOB@- z9S2#&7o5ghN0>*J3M+UT=~#w{JfHnht=J<~XAnI@rPlFiOmAcpqAamJRh134VL~R_ z@fVmfR6@w|&A=w=wF)rescb==Y9&b-9mK8``U-FKlSnX**c6XChUFOGi$L_j5N2|v zaR|6l3F~o@8C22e)xQ*IWT3M0I$iwwT&Dz28dNxDGFIm z1EO*Yx_?CQNs3rfDtf^Zmlg?TA`D3-L3HwzUo=A|mI_7jHjpVKVMd4Ia9K5xmTdYH zt)IGa`Kgu=#~`8vLoFRBc%~ST0Mct|$SF<%89k+Di8#V5>7cDKq9?JJR4D<2)B1}6 zY+_eCrKXrFkTfvN;b!n!J6_SDjhgl zdli^9pqwa*Ibn0k9F)LCM1(`B00fX-PM&VylJS}_lVA#Iuxe2YPjJOTxmXNBBbX*{ zQpLm}DsDm*4xD-IU?>q8qh>x*P6*YoiKAzp%cops1W<`kND!cvQX`KLQjk3l>?&gZ zPn3)6z`CI+3e`a)SChqvXjOl&i7I0;GxfscTDowmqwAfhRTh|~a)qB_gIb_q^jMbW zIyyownX1N^V~2PSIRoJjX%aS#b-un>-T4mG97tdw~cJ5V$DYkwQR z`|f-G_Agr1v{Oz#8DIQ;(S;XYcG+cL{Nfk!?VWr7*MD{HtWPu2QmFQIctQc++E zlWDLn+N73pYoKs0&0>~5N+nxw4#7#_mZs@QX^hE@VRBJrz!MAZnu^9LOhStF;yeyk zE#g~xs~fH~;EF=a(tXz4{eTS*Ib^9~f7C6UHF?r=f1dp2m~P9j{@2@Xob~=EtyAYN zoHrj|EYfqxstfz|8T_fPMo8^cyw$ z<$LdYV$7Iv5Dpo#GT!sK%g$S1jFasd(`UZ+`dbEf@7{IIHCA>h5m@1z->krpYMJ5A z(Rx80HW-j%J4<3W>Y>d5gI$Ueq&zHQu^BS5+A)(%KM{baLE8=tX4IAl%YN$WUVCla zefK{(dUSj_ZMj?qmMvd;0 z=IO{iv+vfkOCj8Wv-L2_P1Lsc=u=yNNVZZkzBeld_kWv^UP zOr#{2 z9xc6Q_TvStTrxogrwJ`flhTadlMaZyV=OX!6aQ3V&{gz#NqfM6HcYx=VAkxe1DEeGaKKyd zyf^X5Q4FuX{-rzae)-P3SKD^$-Of3u?~oyPeg6lDyz0EC_LRa^;%hgVa*-z{6d`rp z=y2pzDG(&)TnqY-YICr-Rt59)=3DQ-@S^K&a@be*!udpgt15&TU-RofEVo?Wd+)g% zuV%n0$gl%XG#IZLeD&qq?Ux~y*2cm!&bmCmU*k`AUp}C&pJ71eNXpS>t;nJ)BQwDK z?t#1Sz9+H?-&?C@Lkuy4uMD=G7rUDwL9Q^T?sBg?`(w(D9zrt$!IBXfjiC<`Gm zPiAX(nq6mxEXlqkkt>QcpeGIBB<{YU(LG>7+dP3NrBTxASWL4o<1-TS4L02H!w)~i zAPbEtOIo^h!%H2}#*Q0z!won5?svcY)_uc1TZ~=#k0q9eVihez)Z@-+tu0pI3c* z8NIgG5GSJbN9Xf)q#KjMMHUq)NXWb}pi0eCj|B*Mm1M~5{VVNdt48gzG-7s5Y zjg@hdfj3`ZjE}q=J^JPRn3w%}Fn#)rd{zMy7{bH>WF#aWmn9IEn{#Y8a$DiMMaqxv zxDt@rJTOC<(_?7Mv{itzs$HJ5&lyo=lBcK-P7BUI?}UB#9cu4p*m3Bl`NRSzL*G62 zkg^w;8-~Hnx7?rEcHW7Xi`?3c*}?=Vj@fnDi-iE$SN53sv%OWetzyVlWlR-=RT&8e zlhm4IdD#nKtrnQFFuR7lJT_I8(10?mOqIc9Ko*+NDqEFp%i}VpY?Y}pKdfpE zZIb&8uvM8HDl|wus2baFaa!}(ge+=Vm;^j#9*oU~zG`3<(IvbMEkv(-yksa({%4xO z=Z6WQZHPWI2u|B_D^ESnhFO&vU|7bOC&N6zgZk;GpT76rdmnYwQO`gB{Jr@3> zT8yu_;)-AV;uj~Lc;a4r?PZB0sTyaY2d2v7Jg_hOH3RypLD@FrJupvsTqS|Z%`PxD z7=78w+AQ(50hp15B{vWOK5O8^DYhGa^h+SodX(kRt^F$&I-TIj2>5i(0AODpi2(de z2rg9M{UAe6J!$3h|7^B-2L|#ABzc-DlMnUigr8+OqP{L zMj1^8>}*NRv}rSsJN~=`sKdvMcI%G!VP+&X#8ovDFa&#TCjeOm&V&F}(O`<=;3|k; zJ&Gqp$`^a^B_?hG~#{j|xa|w1nd^ zkFz^~w6Ai(1^I`|mC_`O(nwLr4JV9&2PTDyJD4eK=_mq1V?sGlyu7nb|D#euqip2{rynxSvz~lN?zxq`M z`)MweCLN|Vav0GkS2!jr`?JEOs;|fSz`+L}{OmK&;A-~{JM7Tf+6sODW&6trhG@uC zKHRmp^!Ts}gpErtr=4~hu&8T!Wz8ZgbYvl8l#bJ+q7Hxm{L|vl7O}6N|9Y937r|NIWVxOGuC86&El#u~^jF z+O9v2?QkDr7~4!L^!@3&(#Yyq6R~{x1PVN6ACIphlism#T$81?honXVgjo$N96{?^1-Kkm z9iBNl?z;zf?}k$u*?;Gd(NDd6z?L_a!yv1| zuuqtn3Jf6;A*rMw*a)+0KPMYu!k)K$BI!U>nMYLFubEBDd=r;Ib{)#f+lcw)Or6UjAD?fza-=y>ICV72k$E^f%YAo|F^Z7&^pd4yNg)aKN;uU+ zTZl6G$S#~Di5* z;$5N(CFQawA27nN(`0G+_s2i}arEe?FxYmRZFd;DeS+#paNQPLY`(=7aoO@`Kl>RJ zYp%H_)zq>+f4nO*Y_r2q-`UDspnLyx-`BqOwY~P-^P-C`lnqxxo}p%y#Up&&SSWC8 zQl%o7SBF+YnIYhxdFh$AZImH94J_t;v=EeO1BBcr4lNl%mP|`W8$bn_5ptmqn<%!K z4bT%6F=5os12*5XkpPU2Co%dW4pomX>gw>=zx0sR_q^<~o&yFvc4<1 z`RUp?rGO6_5Z{I;N;)*uxAg1VZ-bqCt+^KH+U@%Q03ZNKL_t)I>*~7n>a*GoJOAnI zGe%u|1LEfATQqm#yHcB*np(PaYUxz9O&8n4VTQR9fI4d& zD^kFgKxE#ox%>=RcJ51l_`FZ3L>cVKNjlmBClEK?cpg7|$?~=~JZi2nM4!cENqrrj z7Rk?s;PLOhcPHSBOK9$G$F13h?*l7855m(Fnv25G=j~|6P#M5o#6@ts<<|Sl|GOtK zFI41*-Yh)x^l$P6D8g{K;WJ}mU`&<&xq$mvB_n(ugv*Djx{E^LE92|x_(8F3 z#iFzL5@}G#wNaocc7jmlj&`<1uRDmMN-4akt&kZ@D}`4f$=~cyM-x$HhN?j}aiW-hUgeTw-K-pwY7MWv$CXY& zN91{24&FM3NIW&^?!$BI-4~K}8DO4pxju2%FFBo*4M}I0axPUB#ymDEOw%Z|c>{yZ z_kb=&BBvKM+GVaKZR7RVTYv1EZ-y0vgBAKP@7}HZ0sminZvtl7Rh@_48oH~xdY)UY zRwH$5Yzc`$LJ~uS5dvd_W55m{vH)8NqcL&fFT}jq!2t|0<~`daFTshCA;u<&2LXnd z!OU17nZcS`t)Zn>x4PA1byszD&BObLwf5QfR<$H-hU9zfsyb)ywf^<5VefnIsdLV~ z_m!{21qj@diQ6_`b;Av3oRQzS^n_g~ka}^Zw-TTbU;5IQaq9+jOZxkHU}0?pg18(T z3xOL>Z@TFw+~jfjC6Ac3`_cPRwLbD-}Tk6ef8C^dG+(2_dL7>hF^RE zHu7ZzCGT+RI+qB@AV-pXFQ=YQ^o+9v!%@yM6{s6Ts$LU9`_$Jaij61bWd}{1z9`2f z1ZPv<4uFpqHQ{KX1B@fe)eZxuo9ONg0f)>L*O;__0^Eie(vix z-uO}iq|(0SPpPtfTnB*`pn$=F;Br*iQd&2hjVLE1YI#Q==PLf|@BdrhwwYlti4t}P z-WUPsk4_hOHl&eB>JFu9FMPq(*wbD+W+(KIzu=kWzzZ7G=bzsAQs|uh3t#xGay5k4 zO)zo!&MVUBo?IMGkyGuu>#h>3kKs#ltvHwyCWB-wb>BllsBnN7Dw2Y1IzrNg*IOo} z`h+xW&FR3>%Bu7aDN{3$)pc;B)^i(&?Gscc#Ws!iCSaFJE}HqOPA|&R5qN8=sET7? zNOn$T(hyE5mjasur_|%1;Gh=D;QL)J#DK6+OU8mf1;9A7l1wb)U6!^cPbPHux6k8=REt_uYcX^uDRy9xOt92G+GTJxW{q< z9PYCG!0+>BtUK@E8`D1X+0Pt0%(vjZ@eQwEzMO9ytsA@|0&k<3tvP(025uC^B^Z37 z#()062aX;+iq8cHDqdriOG85ArX4)=DBj6}Pl&$c;)`(yXej1d8#itI1zydGNeQPv zz^TWYVTl<5^F=2DS2`sLb*d*w8nI!g84-yqW`bggA$|CnEKIyBb>ol~0Fuv2bz9)T zqEXX%^$<(jxtZDJn>X*f?dzX=`@fwS9>FaUVh_7GwrI^Q8t7lVW);3C?EX)Da_ac; zsi6~>y!LgI#|{kNfA`er=)O<=>7o^@wk&Ned)3d}`WOF;--^Ddm#OHS$1EcMHI6CNV^cG# zCDeu~gP10cJ>BU=(?pWi9RANPS3~fw$Qys*rI zjzPsoI+?NR5K?)g4eNsg3u5H23pc66Eu6Sk^6Ah1%?n@fEb-D3Kl}C_EGJ`l9fa3e zR625p1G$M9aE=6uEGdPIvk4}#rNRnD#*Uj73P9xCXz0g|9(Hsa&jfrC(GrNFr7!P^ z6MZ_92OG$v%@H4+N^b8kWRvG8BQw&UCBNSW?CFteg%zAR+T8ggjR>7)x2;7IrYu#LBz>0(yZd4 zKR%O)P#x6l*)rT;rPWo` z4BakOZ7J~?S$NBumxlSVG}uR&G>_HE3gGL<22c1iI{%;F`JKuM zKYruqfBrQ;%&BL@dbLtmir*W}sGe(?9}E9jQ_mH^3C~p|R#lZeWKa!R3=jDNjn`+6 zxN!^frj838SakD6otCV*b~F=#3~`_4{@d^PtGE5??9>dtwcH2poL@OgZ(S3oCMI|9 z#m$>|&j;T0(Y<6~!{t{V`o>oeedEiUuYJj(yLQdCy75ix0~Ad)A~KK#VOUCy&N+U3{_6w)36`MU~oC+tm=9w0PkQaA&KTXJ>@RApO+FQY7+L$=u42F$4W7(*%#Un9+Q%Ala zARsI34pH%-B{DF!76ZJn8lvV#R2qelF~WO@5$Csi<6$e*X459bd+JcI7&wDv;Gme<8cuXEr$G4YT#fAWU2~tAX-5+JF8X7uL6)hN*P`G&CZ~r!aoubl?5FNl*zw(v6 zd-viz$F_5}uU)%_un1T^#r!@rGXy;|1nk0#E*KgbYBGWa0VV59P-!Kz2Bjw7uc@ym z&S7XmJ=vZJB+x{QJ_pJ@r(OdJ9l!D-&IwY>BDhTGgMgon$)i!JP>4WgO^9V%;J||S zSkx`oaI-qQx+cfQXO{Ki>q0;qA;6O&kO#uvx`@)TKnWnZh!x84eq*U z{j**$Iy#F_(}J&&!3X;e9KHOy>+ZZ`=bqc|?CRr@%FG-X=5SnuZwy(yWC@5L?@9=6 zu)x(A$Kp~j2Ng1liD8o&dI4_Kb=HsDCsjk&1~0X)0iKIuG>4lIoA-v`!iQcRgYYw- zxy3L1fb%+teHCx+#8A7&V_P5?;Hcu4-|}-E(zCW~`jvn6J_zCE-@W4l|M&ZTB_btR z@HQq32#rZ(<2@zCxTr!i4^Z5N#xusRT`e4ODW{mu&7oH1YRG3lcgx#<{q=R&_2**Y zItV?~>mt@fp;sp!hwc|o6~?l#O@Om2Iactho{>>1^WlVX?X=V(aq|VaoXwCt#e35! z6mXHDhAeIA-J;~laZ#{S$L_g68(}>m6Uu1$|@lsR;UaL|_ndI<@8q9A^Bo();sA+#{tE|n7 z+9j!Zh{(ktxAT^YI6{T~KWttic+-iwY`#}63L!gHwBpBo9%vOL*EU5$l(KMCNy@N6 zvez^Mei&2lAmKb}%U+R13X)+Ht>hR;rRhEk=2Z1CQ~fY@V!@mT5p+Xvj_FlEp4=h{ z+GCyw5P>O-4kI2b;0hz0i_nJ-P6hlLVvA!7zIjB$sfnqLS6Rr;mcwhY_5(yFS`!ps|x}--dYz2~#6W_CvJbE}aFKCc5h|!1X`b5Y@wg z(NMn&x(lt?P78q6q0YVhW!Lg1O*MQh#3TD~&C>kBm|;O4+Xxj4qj6mr3aIJ;)*vf6 zsca}f-gder!wV=eRh#405RY-#fzKx;i7@zF&T`W$uY)XWK0=r|5@x%0Lax(bs5+I$ z1&rG9W>ySoW)~ffoNu8k+U$@andkRum)iLq#*kXtsx91+7cig|z+}^;@0#!enO+LL;O0*$JVT3xMPa=;W~`NdigB_9j4P$ANeRFM(MIjh?HUzyeGY8)_HnKxR3G zXz9qKvTZOlNO5))N5dcB42%|uq^0|{M0^c~29M(c0OPqeI3;OGK;a~+aHcy0LN2W( zg@K)t1u3NYp-jD;mlWC}Zwpt0%!T1+{8VHL)LX8UoE8KXM$i!1l1evl>bycZ)@Tka zX7f3{z1%($=JA4m%;UF7fQ*i{XiI6!5US?bqPy#&pS$7UH~)6z=<&(PnWOjJ-@9_< z)D*6z%uUVCO}Dxxre^Q`*r(P`OD82BuC8w1lmavpF^vi(-`Yc!S zfBMs33uLQ>1B>KQ7H}r|488#2m%i;>0}PoF|1joO66-W%-076s$bhi?rA_p;Bg|AL zOFe`xkkCmAq&Xe4ZE5a@q{0&;H}d2Tt-=d~2McJmCyFXQ1<*iEJK|$ZA%?=ST=b3~ zk#a08H^!jjD21WAG=q%?{D)R92Bc`YWxNc`@k^qBrBY8R17ItgB7I$OsIq3h{w0*= zY`J5>Qf{>nw5MD!oo`OVv}IK*B6nGQ_R!b?3n?fnSTn~mROL1A)R%NMiF!o9-WU;T zZb@aCe8~Ys9?&0q+FM4j#gqpyA|%uX6ck!Y)uc}ok_gPS#AS8ahG!Q+Qg8JCu|1I$ zBzkRApNx@FMeFrT74h5&WN=jyr-lLwW<|jc z8RJKN4=91Md`xzEDaOlo^n=JrnLV9kqH!uh9`!Vb5=aMXy4Dacw&>&70&n-&bj9Uo zUj3ZipZ(1AT-Qvi`{;cSboKR5PV2w|#}+el({ruq?%oH!@YR`}_dWOJ|G0nE%8Bvu zE$5$)I!&G!!hr?ebn>{r&4C5NcH|6;5wTF*p_Pu}g8-9}Q^>u`SRE_Khy+xX)<#4~ zX=EdhpLc{~@zpX24REgjZVq6>zukA=^B^1`xSjXxF4sYR=4H>PJ*~LKpSjVah^E|1 z)pWY6>qa=}A%ID7rphnwj%+(=@yH?0djOOtY2}6;dCHAPq)Gra%(tykThGHh9-<>G zn#vp|2!jFCTo6$}KBb^fv%u95V{kQuj-)TAE1=@lCB}djsR5*UAzOVoNVy_Vp~%W1 z%a%QGs82FE@&JUJ`a^@m%$r#G;2p~iq^(oPmbEH3SVrVW7Y!<%k!7OrS+Ype4 zzcM4k_o7^mfnjJ_p(vKn5tCHna!QZxFlyFUP|6}E^dN2s$SN#lLCmrd9^~p1BPc2c zIr|MYBoM3K(osc;5XLGLa#n1nkb7-}7eEhr#@skEdyFa1Kjx@_B%{=$@FlxOW=chG z09A~WzijHzO|)8g*Im0Gd}zO1*o0GITcFW_XFng1jGjGoh(acse(X$!Mlu2~NxX&R z?%nt$1)4%cSIbp0`Q>XXi74hT`pTW9r-_Z#X}k$3u$VeMJobmZvqh+Zj( zj#Q3CykroIoUt1clP~UDjPH=cAGYDHz7*1&v5=*bA`zNM{ka$xP!wNNi3mMk>;#w{ zMTuhzz~*{;u6WBYj~^f0|E<5ng%2EC9NYWI*eTrGIXy8xIX*T%c4};NWOQs~6q1K- z{nq|ZeCD~=UAyt@v(A0`<>SYWP7a;Gt)Gv5y29G{ybBaV1&nP*)dbz18}BLMBaw|e z{KZHjq>$Q_H}>f%kZBJv0&M^&o@>oJX_01L9SJW!Oy+H;dxAw?g90kAsjOel8K)}|k;#BO zom{epkSb1=_T{7n?%y099)U5o<-kIpi-oT!E1c*gjfL~JR2yOy{P?#Zo48D@NMyub zWm^G_1V~)fxh=A$vaO%O!YA^Sf(Tu*wOQ9>gmN-%;%zl3ng~XKL~&1m955`pq9_3p zaf2qA^kwM9qhYAs=Qc=4U-hX7@~TJw`KYn22-tONOlkq8B5zZZ3<~9IMA}#pBbugy zp_EZdxyRYsW@s|JMLuQn9eS77n%H{o8vF3rOqPg15)sRnoG6&|l7V6@B=;GXG1`*E zMDi;us}VuqxWiv@h+Z-=%z*33Ec*s1AR=u@H{m-PF*P4Jduei>R8X< z#gKKBRCuS-Xz5ms5L)R6zVHhXrDb-cCyLPYP-$f=tr3C|Ij)-j008q(nlzEGmc ziK&RLCX6E2L>8`&X`6ytE&kC9Br< zE?L~w)3b8(maA_3XDc>rI`*A!&W?@s^e*y|N_+5aBOLiHD$z0$9Xw_s3`KMiGS!M% z3d%b}ZzEUfV?z$H@Q^b~&;jO=I3Uq{^<8;S`+wfm5 z3&SQh(#~sI8kBm$f}W-DlviNE=vpclxKgX@(7a_jOcFmkcRf^)Iy2#lDtQJ(#`309 zjB#v%BME#AYQ0CyH%A6pIf#;HP2>dvXkd#d6 z)32xzfwJJ3eQ-iyasfz#F;&h%SrI0ncvKPkq|QM}j-d5~>oDywN<@WAOp5?upYUW@cueam6LQ_~I?Qpl$e~rxFDFY&fT&5B^dt3Wi=} zqzH||*51g$gE4azWqYT$eaI25k+nYomd0Kw@MB_O_Dig!nR%)!WW~ z=CAO}JU3o?*^BWxCtb5Wi~F$5r^Zj=Hj3%V>9OI#iLr_CQ)5St9~;|$VC>ZBsi6}m zPn`ISk9yW>%aE;>u>l~%isB~-~Z@Geyb+n^Ay94hfiUZ4=FVJ z3I?psv7jW7DV()G@|!2{+eJHhC& z#6!zqBNzMHvd88%5)sIq9RbUyHO326nmQSp1y5uncWt~hQr6&Ha=AZx1V-M{;dEgM<@-aI#IfHXCv-rG%MyZD)#xN~#!MHj4Gw-%?( zPaW9L%N)(EARX~HL%`~f{$`{&tU@qqh`gkL4zw9&0I(xAvW{J&!$dGKm4ICO!Kgtr zJuz#TY&DF1jajf(>t!#!wtP|+{^7o7*B)7Nga63&Q6xy7lZ*xfJ^nnx=`43dq^Qg+ zY_oBcT#;}|drc9Y>r*bSd@?`3QvdYd@{QZ^rC(`@34~wS37m58O@|O7wD}N9aI%lf zwux)ma=lGM9Jk(j$5qd`Bp9NW!3I@vchN=LT`Re8@aS?q;^QuS?SuDk{?@-JH@)&Y z$nvFCNIb&Ma2drQ&Y{FQzh{b!R<6czOwhBly;<|;6mJAVGb@*ZVWepS| zOhZzcf0m&#lFbjLheWc$c{sSnNuBjlp2#UL=%cxbis2D@WzfG}jg+;E|dj=a@ z*=g=*qO7qaO7!|@P8HLFrpwaNLY0l8VxW?0PXolj7cBPN+!YH1dPbtHUo0{?&Yg^a zqZb=FMbZFI1;zT~h)qb&1Ue8g!lZ;2q6paVs$8rT2?(J@5>k{5B20z|i8g3Zb?HgM zLkT+Fky2E4PIpXOSy*IaEk}ouY~~}Jo)}$DYlN#HrHMzqoS{DWX{h7{8_5-mQ&X~{ zCYUy*`Z%h-C#rzoiSeYD!&YhjtsEgSz8Llg%_M{R&A9v z9h-zQ27@TA=7&YiM0kLRQHijd5IOY#vH~mWqAH{vpJRdViNTRhnzBThg?g~BETN+p zNaV@OQ0Z}TLO4A!@!Ws?*0cZ7wKJnbt(mDs{r!)8^Y&%yRzCeq{WorXn}Pq~KmN(p zSMg&g6}$q3g4N^qllhiX9EC8Pm>=%c001BWNkl?cYhm@v* z!E>J2#OfkSgfXPnsSa|eF`=MxK|~=2RtS2es;MET9;%WNAvFOqccLUw<4$(&(1?H3 z1q61=w}_}GKsb_ft*d$ANdv9pv9a--xr!QH&80npNP0=dp#We2M{In;qqQmk0E&T; zqm%*?iGT;$L1JOH-!zL5DMJ1 zvL&PFKnbKhk)7tsl-?weF5oJc4M{5&$K$dTStl@Dd&;W78G{JuivFU7YpZnnqUb$~ z4bCAWmRJoUbd}r%)HRT=nb{efU&PzIM^24FgAedMYs*Gf$@L0e?C^gg?@yT+pL+D* z5rEgMUa@xVioU)+6olBWuED_}@{EoF1|FPH#NBm%$UXG%qmW;8{@I5P4-TFfUN*1< zfHiAYC<|tQ%n-(-hmPUjRj9(PXt5a{I(huWNif(D-@1SgG2k3jL4pN86BASW_8%Od zm;@s(&YyMGM%>`18RSU_#&E&eM~@BRp2z;a#Ykbz8ou)aO|BTmsnM~A9y&0JELu1T z@gPXfKKl$P_8^5*W0zcvcli;9J_y&ZU%hd|Y8-{Y1oas`H3pN78`i8}y9)8(r2hU# zkDw-q4DL2v8mpIRzf3u_i>h;OAKAzgoX^7$g@o^^jY9 zfEE77GMusuN8B+D;MbHKtZC*C>X6{Y*dyTC5t?mP;4|}Ze$aZ0&$tC^5UYYs)9;o zKeAN`l(O7F%?S$kQ9lYO;;&|ukZ^}xXqu^OBvye2os6*bLWo_PRs$O*!h1)RJlH$8 z#+XbG?B4h2!J|;()f6A7zmIP*BSLX&87nC~j}Hx<{N}gs1{lbP_dfcazq=1N8%8X1 zb9m3l{sV_$irWvt^U$6Ha!)F}qMsZ-^^M!^gcV+W0mHT9!9jc`vz_oI9G4PCMn=Jm zXAhhcX8`zX%}q>9LS<$f9vvJ~ZAFia6du+e4tj3C^WH;;j=_vC>IV+rb=QMDuZ|Gs zx^O6ftMs^u;eiMCA_lx(H#>bBj1FZkPxR_>9BUQ;u1$ZvF4Bo-uk!m5e5&=>-Tuz8tro5mQIr5BH;inV~D^gy+C=Or{l(586(%9IAKlu~a{`zkm{L;tve(Iw~Z~xYjZ{IfZ;Lfd= zKMlMiM+f)avwLpE!1_zhU9_Yh2fQRA1KmzfPG0kxSMU7fXJ)3SaEv=Scnk-O_>79j z{ne!q9yTcwY`7XS15ig!Rn!@?(x4h}2cdrFCiqkrMjVaL%k3@PvR(>+_x`Fc82a#~ zFk*wNAtun22iJAa*QePVtjA^=B@2kqG)Y`0Qe%cJmM%6_#SeQtiK;!f3KAzR3LYmd z%*iiQTHZn**-*?K^}Qb=<2_js}cWOh{IRqvL3L4{h|{@TPZt;~O{y zVl^%P`t!HG^EdfLg>HE33WL71v50Rfr{U1?S16X&%Nqx zINO1kfAigcaMK@t3;@gvrv`Qmh(5WOggdqrDkRAQi=BV@e|;OUkc8MP%>%P?&5Dqv z3g_Mtm@z z9fu?oLh70@WxBPI_XI%86>g0uPIDovl!~1G(8%CTY&p&*Wuwhu*l?HR?CKYe)DH}# zWtJIV30WOj+p4#_XUC51S6sdWCtsiT)C<9I`0!u>10)jK_+@P4#3GlFjEy4rl@R8&2?xZf>aSpJ^t=b^)SAB-^%a0mHFl)42XGZ^Ft%thkVI-gVD^(Qm$Y&!2zr(BJ%ZtEU$Z zXQ!sR7kz!prO(8tfa8t{JbxbCy|-`W@^#zKT5|H#(S47y;@v&d(^Fe7d-9g^FZj&c z-g)&ud-e3G;i;2DJ@}+<`-tQg-T{IuE4&}UdhW2OAy%cU6c7&>t>>ee4H%}W^0GUx zSto$%VgUZP{)?MGk0bPghlFSNb@Rl_^(ho&(;S#p(dalwltAvd=E z3#T$GvlCgA$O{Y-EHEt^WQV4wYgA9^xI8!C{P}`M=cW&R{4F?wp~xoK8_0^O6y8!! zlu}{`4H7R}MT>r{AK6C$ z!Vs2tS@=Q0F0q-iQz*}=w2EYbQr`kOwkiPF0T9)ToFJhv7;J8toTeKm714U#$V^GF zS2871t|_w_nZzby3N1-MhQwMCDswtf;uJta9TU(cT7{(p46%tj5F5KN2_bY`ZYLVz$+0NyIN0w8V{b(R^I)rE2>Xy}`Dg|imx9BFcuu9qI@KW_CdNk%^rcynMsP zso^19bizFron>zeBnF59ACQHcHZbPPiVLHHBN0Ck9j5@zGXN`shIFGkVJc~EV&YUj zkh#9C7CuZGufz%B9|MY7M;esME zzs^ak#OAt=pBV1oQDRz%iY)WQKc~F!E&`vM!+jMPF6Z|%BU%L*yj)|OH?74<6dYK5 z>pQ#7+kO^cTC*)&Rl%z)O}e_yK6~@hC4D%9fL`li zNK#eG*es+fHT3q82HfrAVi7d+LTyxiIg zGQtHTjKwKps7u&(M0}q7X0d#vkeMxXTcn(Vy&(dJ;-<%J zd_xDnDoiK#q@5ZYyX+OOc+uP6@ptck&+fna4d|&&J{# zL!Q7dt})?Pt;*fwl&WaXkRlb4S#di2$1S?T$cjUEDD|&QQhU0+tb!;kV|qlCtT2D+ zPd~3F;dKz(sp7QF7#sk=5>o7GG9ZOD8Enl(q03XY!93T(cXR0c3Nbh^!fBY=%;Y%R z_KAS7c*~n#`N@yJKLy;|YXqkF(YF|nZ5&&`1csEgH@xb<_uv2WfBt{} z4PNh^9rTXb^MZ^#M3A7uAxI%W9}*0WEaqkibKRU#yY^>=HDyxIwv69Rp{pC-ln!0R zpL^OiRKglrVs-}@{)jewX>7T+G;TUxJQ&MGuvL9~@m82RSmI0--pTFM6ok4Z40nRW zNN+R320$m&6~6*nLK*(r0U<0V1yC8X>o{TWj)IqMJ~cTV%iSlZYbw7CQqkE(1R7-w zY>5Vj6zNx;cw|+XW+HM?qN=UfcZn)5Dvjx($0+&^k0SeJtW=d>$tiIR-WIJpwk5^9 z1^}A3>}1^}4o(BWY;p|Ki$c-RnDh%8QWo+@_VacJpSBzypX3>cAc;XfQHQ=`RJo*bNDXI%Pu|d%*`8c10!y>*t-{ZMbHXwh;WjO zDnC^)Bx0>;O5Xs`vrzH`m9_2^Bruf7SFy6NiB3I3EEH{{*V`$Ae@TB|I;x$>MVlbZ zLA7hw9^4Uvd4b5seCRl;;)6r|T20IG5zZeT=BRuu zWd4tVF3v*Xz(O+K@7tQ5diF2A>B<{kbIWi1>qFoERu4Yia|}24s-D{563MZ_6P zPr2`_U&Glc#-fP2db{ymWP9&l6P zc$v4ngk)_Q&hHd+bZ`Xlz`cK|{M&Nuuqs2_{?>c`IerUIht_h$`H}zjZakITd+(mR z@5aeUzOLijOyCiHn80sgu%sT=5*WIA`0xpSin-1=ZrQT&!V9;RYSb~*{la4*DppRn z)CU>R)V-E13D@5)X>vx^!yq=tlq@ z(j3mW>X3x_Li1>j4tx?f`vM56M)O_wT*g8O`|q~DpiBHieBi(loTA4ow*j~|I;`6c z3chw!gwd&Vc)iC5Ltpmf^ZBKdtrmI8RR*I4t}Hsqa7+V+4uFSvdEUBp)5eW!cHR3h zZpp+|3_JsDI|rW_(b@1C+`+JT@!|$l>7rXn3hcD14sZ_nLaWzOFr-Xmy!&!&Dc%Vp zIo{TSwcCvsxhK%TgC|wg5O<3BI~_5+3mSvK&Zcf8}gtDp0^UwYHgyLa~X^-YdXn3h}F z%}mYgzwO&+zw-L7UYwPPqY58e;GvFptvu_78-@=aJhA@(-V8F=HN9lT^0E8w?`h5A zw#_Hlx_fY7;lm(1g&#%EvP23b%Trl|`m~u2o&-`2o2MS@d0JTIWj*|=z#=Iz?o}Hw z1I<646k^DPQlf!eI1xKi-Q%$B3tzm=Dr|KfM58hhg#lvq8)k*dIf@RWGQU!8csj{E zE3zV|JB(S@wsSJfFgPimo5Qg`exLVaS2%hYNE`)WUv+OdMNj5n*Ip$B+cU1X7z3FfviA{wPp$Y~=JZ0o2BCo^tuLY6QTf&jW`LO!i{ zSd|p!gPkp1!zt_F1tp#g11cCYEizUZ0bDv7RCv%tJnXet)PUPPxM+Taw2t%L*5}>5D<(IiEnhHvs^ArW4*6iMt>4Ro1i=Qal|SSurr& zza=(wmMrPRE9lVBsSWEFA^cg~02o0q47{xa*J$7uhaGtP=&pPB96UU@eEEQ)h-Jxm zyLj&;-tK{1<7(8ILXe@t>3Sw^Mv4vxu#eKZPgDC^m zq6A@}KZJLPP{zh3(=~@97#v2hD>ut|m&pj;u;yD&@E#6mafB3iqQK0YdQjS_$h1*B zc!w<@;33vvBQ#(-j=-x;s~TmuswDM z6Y5JLpjFf$&)TUVG*>XPyS0fb^QL6!2FNOASO`g(E&BzG2U6@8R zH>~O?eIm>qfZ&(hwH9;onu$i}5fpwUFp*8$<|$W#jKT`L@a2v@P+9wGMomG4p~Fn7 z#1KyjO<^1b4NQ?J9%>X!S~^DRB9RiRBq^=-lE(u_ z;@|{h#7jhJa-3E+g5Q`Cf*-`&%HQ$^aM=&t`JtB3IjxEY+AQ_ z_r6{C?ZHQJz{~F4kAP>>#;%r=3=H(UlAdueJ3r@*A?m~mD1GglLpOu94Lbl9JgE}u21O=LU?u6o^^2}Wi?4az zYhU{(f7;*E^YPcb`q%?|a0Bi%?!DkK2S4aSeZDc(cY2;YHaKzY*rtmv;8ATJRp5Qh zYqoBA{%c?RsrUZ&(9vT9t5@N|N?(89lI1HV4j+7iUq9wMFmP@IZwzse*jCXZf%X)* zo~W-erSDD|%2)*IL0$t&zXM-}=#;)a)m6g9<~K7pi*LAuNU+_}ZjkIy&>IYDobXVR2D9 z1ygrAw8gx}pl^B6mQDw(9s=`3V8x_>OQ-lP77haI-HN`1W0#glXM zw2v1LnDIH*vf`@Aw5Dy;$v$5KO);rE`1B|I8-4G+5937<#{~X&93L}fJdlN|bka$) zhidDVjrivtB%s3UrEXfphfR$azYTgGCti1V?AV4wha*RhR*%HDC)BnDJJN zb?aB-=B+xg!n}U{s*Ri0j-DC^62Fk2yZtQQ*_|Gp!u&*vyr^(6fp@)*jgI4hz~)=e z+Jp#kz=Q}PLBD`8L|eOhIfOU{!Vw8nNNW4`EjUAln&83^|t^Fu682AQMCukzld*NWOzVPg_afdq|)j#c~ zIb%^nFfl$G!vjK*^Jv9A?eQ^ItF~@^<411Va>=Df?z;WsH~!O+gGYJ?mgplJfq|G4;n6!4EK@DHc}p2hqx8lK?hJ(uAFbmj~H0nQdQ<)=@sUcry5 zZ1K|}7sOb|PxY-DUa)HkhL=70JRFhWl@G6Z6_DLa{G}U}w6=v9=J-Vz__|JXDqssQ z#`py@P7-veYMA@yoV^)u^&cJOds~(c^p!VuVmLpB`I4IO-0gg0?Wm58(7`{+7hdor z{38wW1;fB+F#rIhi-`_vd-)E(-xWt}IMjg9tt0)@37tC_1_t_idwU&Ha+bEv-Ip{sJS}Itd-i|l_8m9Arh5^tc=4EJVq*Lyzw$4} zP8|RGfBzqg2L?t@p6pw;1ZN!vR;<7w#q^0meuzc*eEglySoqU5!n+bEM-}kMA~7Bw zIpL^GR{$6!+YZhy$V!y+aPU&g+Pt0>9rZB1n0wD!y7}!H28juc+Y2 zoONE|EL>&`wrU$u)I`zrZ21JXr!#4n$EXsbi&iEa{Yoj_yv^eR=2DLEp+k=>Y{7l zojpUaWm3o#sj6dv6Zdlt`H3LR&9*ses!}B1edjR`DLVXteL)H2U3~4FYhFITn?T6f zzj(1C>EP!O%=n0l(+~=uMtA|n>(6PBPe2?z-pzF!BsJvJr^|NMs+a_{KdsF(sRebv zaO(5XV^kJfBJrI{UK&2l!&L$mH~evjmw5DKpdp1#g9o?MGQ10V*& zaNICDcy#FQVxa-!PIx##sG5*w_`0?|eam63L;f?s-5S;Uw7#-_g z)Z4eHcL3iYH8D0j!cWIi_3id?wzyk%F^*@PX$Q6=1szKSB#Y+LG|-@f%yrR{IG*)D z5PW!w8p<%C0*xl|xYb$75;9qAlQ81=BPZN{=)e7CxkUiqV~*Nzra&w&er6zvuA$0W zKIJbCi!xq-jE4XeVM|wVq~!R5>H)UShSZKnff0*TqW}!w`7z0;3B6J;DEkbT7VOIx zFYDT?{G|btU|cd`KuO{N<%zUb088hLMmwq*g+pRJ@MW;?e$O9Rj_ohK`IU5vV2W2W zP)0M&P2^z~F=oshC{&e(PU)Sth=^vvfUxC;S(}&;8VfH&E*XVEQ?p{vWUvV{3N)={ zY6TV97;E5woU_CK*b&29A>O#*tXX!}!plr$CSjLrFPn7_iT>6Jn@( z1_j*V0*MZ{g2GA?W$TB7q9c>&R2@3N$l=RbmV%Bo^X3iTGIe3$iag%2W-&4z0aB)T zA_)=(T)j|}0}B1nHpb#rnm$nh`5ZpwN?#HZARuKxR-5I`oA}^MoTw2Kyx@QScyk5t zDvLCV&lr5N#Q4a_;I2C!yybyYhXz+{T7BU5yARy4bMf+JYqp-b{>eKwU48k)(LtQU z7~X#nXP|I+frAXVJ$39jF6nGK|NOhZ^p&lbUGl;=zTv;W^{rzgr+OCQ$_UcQo`PP5P0wjJ*Sh)RU&QB0J6@cwc=MZH;W$X#xR$=qn}v)e=;&~l+RlDNm9Epa z#8&j`RLmHcG=sc&F8(Yj>gbfDH5P_ssSWGq!HPOr$uwN*1|C)=0d(H|?>|^hSKuQt zaFbLxGARAT6Jq937?_ztY<7`qhN$PH0wbUPB1jKnD^wM&!No+=3D1>4hS>NgxpVL5 zBEltU3);&`HL^V8WdW16wlq!njv{9y1+S-Fc?+*{%uS(>@^ES5r!eHSQJvE!_nt?a zn6O6rV>mHo8ndTl?%X0(r1ZK zWD%|?%o7;m)Xlg&NK9i8)hl^NIb}waB5*{4CaWAI9fLw2uykuafg|?BYTs;V(l~GI z%_yx9(Q`UENKTJAQcDmQg@myh@UoeYi-17SpgBsTpm4IZ)_j=>*tSwMHqoQjJ|h^r zH>drupLW$6Fg~mTUyQkSXw{eoyi^^5m8$|_UEH_^ke>F057@x(W@bCH1WR^mbo}JO z!AE!AKQ=V7>g+QHRxFS_orVib4*IAc7`Qbb7e8oHd-DiLA_a43X{@(t$qBb`(Gd?~(ux#nl)oW)*hP$RF zyB9syMY{|z_B^oY>1y7Q0&%8MQYc9^I$9?#n6N8%y;c^dy=K{AK7S~}s-llPa^#Qx z_*3Nz)1iLfd;jI~<$S+#w1`+EOqY*?Qu$bWf}yX%o{w$_Yd6L%D8Yk7+QzURYVnpM zH9n%+UD~R{HXwlFSJAS(kd}T)q3{Rti(mTY@BZFL%25UGczw;Qf2zY}RsgoiQwLD@ z+bx?BFlZgfwqZtI*(e)$Y**o6{c&c{_+o`lN3+Dtj;a9C3I#;#aMTvC;wpCNILDZ> zQfDKQ)(p+o@&cCA;KVad<{o(Z2xUi2D6L6ynkfEWmumsn85G^kdwdni{EpLUa&k2) zHv57&Dj;a{peUBL$^3p+raUMLVH;L#+~hxCd3*qoUw2qm0Jtg=+^i6I$=nxQJoZI9 z+a{RujL?|a(o=Q|Si*4R*Cb&m0ZqOD+fIJkDBA|X~NIF$H?y!wv8n$WE zZ4mT!I_C3e92lb-bp-l2q^WS3yUZn5MwlG_s83Q_$-FqyD6;NqeeC03eCx0NuH454M-_kc;osyjSs}4s z579@5Y#F?}4%p;i;{SI1Un7u`gpDJyH&`+Dd<4}h184}nd9~$`{HeE(Bq?%Yg~t}c z2tH+$By-UkPkAAi6X(lrEf=}L0dQsP%j~9d-#N;P{62B*7&26eD?bX-QK6J2PKRfw z&WkqL3P~7#-^vxmD0An;vw8|I3WLxB>>z2Pg~~ESUS2SfggBjVoh-BsV}&7q7N1$m znURg7f>A-DI4oB2sgp{RFyYkOKR*>5Upa4WSEN) zbV{KyMP5v(R$xJBf~=L}bQrnS^IN*co{nT?a&9G{Dq+Q4U~}rJPmjjhoMJ`Q##ULu zDSn9&%#PUA5PJg1h%s}wU&<*A*nBw&)ohMQtY{)6=*gB9HVK6EB)JGY63hnBmLMbv z26>dGjsHzhY#+45T9?ca`PGZc+I7oH=Td=Grx4x zAAIG*AL(1lxBX<}ni&~7xoPF{fz@lK2an*(+P((`!d1d@+b9 z)bwkiiRl5dSbyP-63GL}hk#?IoFg54IBWs+n(7``Agzg1j$T%cQ}mkZ(#CM&K`l#z zT_GZ*f*CwgRXMJ0WgO&kLS_;w5{5N5hc9Q5AU61X@&EY#w=G{WP(m_)SUGWEJrv|1T76jf{q@KH+^$N+5Z7knZC9xnAvq|oEB zEQtXw1yN0L9K7`0SVcy&%S35aGABp0dO37_mMRtn=K0cOG&~BxPNOP}TMerVt{DiM z(#fb49)(hI#R&F&Ef?Z&G3+-dg~euLsBFm33z*YN8!BW-xfy68ymL)vX_bhKIMm2A zBuCTa+7(Gm2zj+8WpT;~#%c^RQ$OeK)qNfC*8 z8YLtu8q7GeXatkjxkSL$2;&%n-6pnTcoHiMQAuL95)VBv3$)C|Fey?^blIVy zb2or8m5!<2w0oN&4#ePTpGv!!FU zg%2!vR6;OsSl|*NS{9i-o;t=(jotdWFD>uJp#wj1Efqt4(@$q@W7)hf9fYb^)LTb_v&S9wwyV9^capm6c;zRClsGSy68zy>c@qZ zqYv_}rrlCP_XHYm-t6I;>1-V-2*CvkZuUd%B3r8T6%uj-h7j^%uPKop8+>Q1-MP{N z0^pztHoi7$b>Tx!aBP9?%U^o!4L7`a#fkxxTgxI0LCI&3QhJjoNturfhTe)${V0IL z2vW?FQqWN6J(-i90qDziQ59k$7dny7c~&K0A?Uc+8VadR)G?7H3Xv+=QOk(@VCUg) z^cxH1uVS(Qe5`g|eDS$-s;?+})eSGX>KPZ4Q01f4!7wj+bUaZd3g|fKvk!^Fp(!g) z7DYyJ+oVv1KiV@G`Cv>K6G}7ev=@vjK3=kp($+}VLuttrL{5bCR0f!F(O9n;5usG} z$qEL5G)$ewdIo5Z&9Ev|(&`UPQRj4;8Bqg%8hOvKm?iDd*j1ezgtt8FDy(Sy3A;wg7cn4Y^#z@+$Gp=<;S0|rD$+w!B3 ztZZVAS~Z5DGDZ;qX;(7R>L5Hx$W$J-9?&l%GONtEaSL#$9iub~mh(e*ObSvt(WGSv zq_#tMxMeLJj)`cXQwS=bwP{}i9T2zBs*dW>K+Q2~_wMfdGtGXAN&`m!vLCMa>HmvQr^PBy6 z<0-#lp1C`Zx^ELHqYKylIIzHv>qBucH)UYpd=8-|6Er)^6BV|dGj>M@7xzY`(L;U&BE1WcMMBH_?0a;`A1i20~r@Fb&-hUA*GwLle(0G zDyiv=Au-(y!dyy+T9GIS1tPYT%apbOvs_exBaNJ3ujJ?}TqhL}keI{nSbFyyry?ZG z6aaT&O<(hzr{25s=Jcuf6>M-ZT)Af*Wf%fQRO;G9MKAQqtQ0n5QW(lyDshuXa)TMF zLo-9nTs(0*4D%3~oThMG3XeXS3=A|KRDo7?iMfHCo`{q-cI@*HzqsEyS1Q>!q#Que zhIbj$iL4luqaspF1j};*$jZ7<+tGqdQfe7Awu}&4l2e9VbSe0um5X^X9Hhd+Fkv)^ zl(AyOSkWq6;@M#`(IgLu=R!mhN3nyA2CfD>E^0`Vwb6F~s6tHqghILTSY2AhgJ3`1t( zq=V>0*E1*?G$3_}=m0_v`G-=Fm^K)agJXxP5mW(S`OvuSn#HjJkM`y_MkQZTEpT8_ zoA@0fkT4dxKjXY}@Biv8{9r4-b;M-!i7`I!T{B01wb*%}ZP%@z{u1AT(%bvsgM0q& zrbqGJ9@7(3{M>FF%IIjMdwA?`Zu#b(6QezQ@9G+C^(~sg)eW47=t8c(DU# zCU6XaqY?bF7}|m#TD*(oj0?_(_pax!4oZ4a+{l;81Gr!Pw#5XG)kri281LgD=TXsBE-faDH<Bm^t%6>s)q zF=$997>h*x@M?_ATrowF45SWz$`!k;n_wh#P+HI|qlOU-`eb(s;8kYw=Q4UFDSB8i z9OoexKxpzkE*Bqhj50!XFb-SGAO-S^O&OQ4nP5{HXG$giik!L9g{-3TR1?Fklg2mY;ghRQoys*&{ zEs9qcNikYmY?IB8OnN}{G5ZE`&wr&(7-U!3SMPhW|uM zv}E0N&x1Sfy06vUi@P^)gbG$96h{&|w!jyH;9LfdHu&4!)z{O76BXDl>TV64dHzdY z{1YnT5ASTSr%&^Oit&dM{NyWO)X6jE=RJr#tm^6&i;4u03ojoJs+{HO#zAD60;%+< z5uxQ0wjp)oLErifSA@BQ+~R@b$C3tADI4IHX3@UcB zIylSF3g!}V>v>@*H9=lxG-okA4M3G;fGH*k|2##ixoj!*VW%HM^xilG9%q%S zJnuk7N!F zu~Ch&a$#3vYs;n=Zt1#JVUH)P&Tfk)656 zKIEce02-&E2ilU)N|@?7(9acV!f;?uEF5?xE^y#hOMccwPtWSL8#vD}@C6Zt6&ul@&L+_fK3>Z$(?$vts7-1GAFkV1G4bybnH0ds%_Is++g^77~%k{iN!sIl3f=u zsu_Nyb3cMQy#$(!m?Y7>z;dKDD3lhKo*ZE28mk1t1JN*~Z5w%^RY3#qYPYLsEjck( zX*)eJ*4vlwzb$h4(o#sT*cWXFe+4OB2N{lv)C{J=Hsg_ii^op}gjYyag)v)CZ5nb$ zxNf}gs6lfPD9<1y^`MQJJe4EUilf<(tt0WGEOJSHRIaG`yqQ9IJSnUbipFs@9UP~m zlr#aZf7I5@02dPDMZk@QUJ_m{ZEL2G1DX6`MFB&qS8RzHstlKpN6U+r3=(3?OW44+ zheu=;XHzA}X<4|nnDyj{wce1BK3l~@KxGR=gk(9kZl=nuomq!SV8cEN8_&xaN}2fJ zs2*ibhlRDFJH}}nkK#IjO3Q9WZYoNYNU2Pd*FtNFc(>%?s9qal3rxK;J_F;d`dPvf zrNlyzOixGdut*FoqRLt|PE9LE#kO&q?qFUjL)U2B%AqDgw|DVeh28ldxwzQ^AEv%? zRm0h8tz5Yh!?ptp1ih$t5e_V<&@A$sa5>;t;^wmyA*5kr9>Qe)dxs%+4$6_0_#P+z z%Fyeh$)-Ivjku}uDzcEbjWx(HO1(1Eb|_$VD=|Q5RqeE+Ut>&Sr^T=c-7)!mk40jB zA6OJ$b;mr|+EE8ThQ)=gJS_M+Ff(*W3WH6sEv*itSh-U$=oF9W7Z)X%g707}R>j0r z_0V35VF7f=3!rcUU>+k&3}z_W4onA69f_IEQ@qr)W-fq^j>GV_n0JH$lM=vuwqjMo zjIXVVBjXEr!C?WrQ^59)ZIKj5wa`|D*;X*An+>h1<@5U;z6>zA`yI>>7IOEooj5tv zzkH?TMO!+>q?SPFb~>vf2du;Zp@((HDb#YI8Y>KqFY+=h%r&M67xV(80fod83`-hVd1akh1Rf|r|#D#=zHi$&@WDw{VJP!2=7~NR17S7~-qXblAe%G!s2k6|GpiQJ(SeNy>{^19VSnlLD~cBdLjgN=f3covkHq-=rVFGFDSun|Zem_}Qy z8!OuuhO}z{CG5%(yVcO%EsQCs2+{pfxfUpw3y9))_EjX-$}NQ)#T3YZ^89Z{Nd5aG zl^2?6i#djvQwxFDP<9em!+?b^0vBjCtphgBR^FB{OkPEcZa8E}vc%4u=AoJ(jv7f5 zwvF0U9p(<2Jjqa~*b%9ji`-$?S^yyQZ;{)pX}z_i4nY6tnqGOpIOew*O4g*{p-DnT zc9Sp%^rWT8A%!j>uyPk$c8XjbkKDx;42Bd5=fX1Ao%Z40VB&>k-Qzkymk|$e~oj4`&6$L^AE)_P3w->^kXzD|*VT25fn-eVzB9BvfDf}UX z;qVlj14g)>k;jRDo?+Oe5XB!o|P_>lpa!b!vf z8)=Xl_EZyLB^8p8phS@offMT&?h+Ch#?!Enmc0I<4f*j)!;HZq3S~?Wb{*VdCI@6U zi#SQA1TtpY@{a_8WL;!}y}$}aIdK>x5-Buw#K}PMM@&@YN98(AxmYMJG}en%#*fC5 zu&yj6n`$Y5>z-3QhjX?xGcf9$M%sJA=m0ow#iovp>=Ii590mR-!t6<615T?gu}isy zUN%L2nj0x(l#aj=3l*U_EXD7fB0gvoxsfzwnvgOME!ApEmhy-p0h=D+UVs)*=HN}E zq%t#2LJauy7!L)8r=rl5ZlvPY(JC4yM2Ug}OezOTI5h^?JBu47pcm_DRhc*(iin0i zxLFV~5f+T{3IxC}qNqssSB)iXse)1E|CUCoO%eU$3-irE^JzG zFDiCa{+M45sq&N*zYMQYF-RFQ?9wrSCgCz%fGc^_fd$MXkt*Lp1p>P>QB+1ABUXi? zINN45%paADb&QI(mrIpzltdK~kfm>HO3G3!YfLbyNL00$LVDEvs6$SIiSwrEra-e6 zlg@Z($R;HB?3mqJZp*68PI(XkTVik@5K*Kf4&0&_9w3t-GSQF^ZLO&E(>#QOBP-Le z(y$&mp2$ZJRjOT|;?kY0Rj%`hA>wjng1hm+UNcJPEe#ZdVeV@YYlo&$tx`(sO@ILaF1IwM9!1&Y00000NkvXXu0mjf DW=Vhn diff --git a/non-rack-legacy/public/index.html b/non-rack-legacy/public/index.html deleted file mode 100644 index 566f947..0000000 --- a/non-rack-legacy/public/index.html +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - try ruby! (in your browser) - - - - - - - - - - - - - - - - - - -
                - -
                - -
                -
                - -

                A Popup Browser

                -

                [x]

                -
                - -
                -
                - -
                -
                -
                -
                -
                -
                -

                Got 15 minutes? Give Ruby a shot right now!

                -

                Ruby is a programming language from Japan - (available at ruby-lang.org) - which is revolutionizing the web. - The beauty of Ruby is found in its balance between simplicity and power.

                - -

                Try out Ruby code in the prompt above. In addition - to Ruby's builtin methods, the following commands are available:

                -
                  -
                • help - Start the 15 minute interactive tutorial. Trust me, it's very basic!
                • -
                • help 2 - Hop to chapter two.
                • - -
                • clear - Clear screen. Useful if your browser starts slowing down. - Your command history will be remembered. -
                • back - Go back one screen in the tutorial.
                • -
                • reset - Reset the interpreter if you get too deep. (or Ctrl-D!)
                • -
                • next -Allows you to skip to the next section of a lesson.
                • - -
                • time - A stopwatch. Prints the time your session has been open.
                • -
                -

                If you happen to leave or refresh the page, your session will still be here for - unless it is left inactive for ten minutes.

                -
                -
                -
                - -
                -
                Trapped in double dots? A quote or something was left open. Type: reset or hit Ctrl-D.
                -
                - -

                This place was sired by why the lucky stiff. - Please contact me using the email address at that link.is maintained by Andrew McElroy and David Miani. For support issues, please post a ticket or contact Sophrinix on github. -

                - -
                - - - - - - - - -Please Support
                Try Ruby!
                - - - diff --git a/non-rack-legacy/public/irb.cgi b/non-rack-legacy/public/irb.cgi deleted file mode 100755 index 9bf2d06..0000000 --- a/non-rack-legacy/public/irb.cgi +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/local/bin/ruby - -require './tryruby.rb' -require 'cgi' -require 'cgi/session' -require 'cgi/session/pstore' -require './popup.rb' - -class TryRubyCGISession# < TryRuby::Session - attr_accessor :cgi, :session - - def initialize - @session = CGI::Session.new @cgi = CGI.new, - 'database_manager' => CGI::Session::PStore, # use PStore - 'session_key' => 'trb_sess_id', # custom $session key - 'session_expires' => Time.now + 60 * 60, # 60 minute timeout - 'prefix' => 'pstore_sid_', #Pstore option - 'tmpdir' => 'tmp' # Temp Directory for sessions - - - @session['start_time'] ||= Time.now - @session['current_statement'] ||= '' - @session['past_commands'] ||= '' - end - - def header - @cgi.header 'text/plain' - end - - [:current_statement, :past_commands, :start_time].each do |accessor| - define_method(accessor) { @session[accessor.to_s] } - define_method(:"#{accessor.to_s}=") { |new_val| @session[accessor.to_s] = new_val } - end -end - -TryRuby.session = TryRubyCGISession.new - -print TryRuby.session.header + TryRuby.run_line(TryRuby.session.cgi['cmd']).format diff --git a/non-rack-legacy/public/javascripts/application.js b/non-rack-legacy/public/javascripts/application.js deleted file mode 100644 index fe45776..0000000 --- a/non-rack-legacy/public/javascripts/application.js +++ /dev/null @@ -1,2 +0,0 @@ -// Place your application-specific JavaScript functions and classes here -// This file is automatically included by javascript_include_tag :defaults diff --git a/non-rack-legacy/public/javascripts/console.js b/non-rack-legacy/public/javascripts/console.js deleted file mode 100644 index e7e8b79..0000000 --- a/non-rack-legacy/public/javascripts/console.js +++ /dev/null @@ -1,288 +0,0 @@ -jQuery.fn.debug = function() { - var msg = jqArray.args(arguments); - $("
                ").addClass("error").text(msg.join(", ")).prependTo(this); -} - -jQConsole = function(input, output) { - - var args = jqArray.args - - var input = input; - - // History - var command_history = []; - var command_selected = 0; - - var local_scope = safe_scope(); - - function hide_fn(fn) { return function() { return fn.apply(this, arguments); } } - hide_fn.desc = "A function that creates a wrapper that hides the implementation of another function"; - function queue_fn(fn, time) { if(!time) time = 0; return function() { setTimeout(fn, time); } } - queue_fn.desc = "Turns a function into a function that's called later"; - - var keys = function (o) { - var r = []; - if (typeof o != "object") return r; - for (var k in o) r.push(k); - return r; - } - var refocus = queue_fn(function() { input.blur().focus(); }); - var reset_input = queue_fn(function() { input.val("").blur().focus(); }); - function no_recurse(fn, max_depth) { - var count = 0; - if(!max_depth) max_depth = 1; - return function() { - count++; - if(count > max_depth) { - count--; return; - } else { - fn.apply(this, arguments); - } - } - } - - function hook_fn(fn, listener) { - fn.listener = function() { return listener; } - fn.apply = function(thisArg, argArray) { - if(fn == caller) return; - listener(); - return fn.apply(thisArg, argArray); - }; - } - - hook_fn(history, function() { print("Yo"); }); - - $(document).ready(page_onload); - - function page_onload() { - input = $(input); - output = $(output); - input.keypress(map_keyboard()); - $(document).click(refocus); - refocus(); - } - page_onload = hide_fn(page_onload); - - function clear() { output.html(""); } - - function history() { - return command_history.join("\n"); - } - - var keyLogging = false; - - function map_keyboard() { - var cmdKeys = keymap(); - with(cmdKeys) { - mapKeyCode(toggleKeyLogging, 120); - map(executeCommand, {keyCode:13, ctrlKey:true}); - //mapKeyCode(executeCommand, 13); - mapKeyCode(refocus, 9); - map(historyLast, {keyCode:38, ctrlKey:true}); - map(historyNext, {keyCode:40, ctrlKey:true}); - map(function() { return false; }, {keyCode:123}); - } - return function(e) { - if(keyLogging) - log("keyCode: " + e.keyCode, " shiftKey: " + e.shiftKey, " ctrlKey: " + e.ctrlKey); - resize_input(); - return cmdKeys.dispatch(e); - } - } - - function toggleKeyLogging() { keyLogging = !keyLogging; } - - function historyLast() { - command_selected = Math.max(0, command_selected - 1); - edit_command(command_history[command_selected]); - } - - function historyNext() { - command_selected = Math.min(command_history.length, command_selected + 1); - var cmd = (command_selected == command_history.length) ? "" : command_history[command_selected]; - edit_command(cmd); - } - - function tryComplete() { - - refocus(); - } - - function executeCommand(cmd) { - cmd = (!cmd) ? input.val() : cmd; - reset_input(); - var result = evalInScope(cmd, default_scope); - command_selected = command_history.length; - logCommand(cmd, result); - setTimeout(function() { input.attr("rows", 1); }, 2); - return false; - } - - function evalInScope(cmd, scope) { - try { - - //if(!scope) return eval.apply(our_scope, [cmd]); - with(scope) { - with(jQConsole.our_scope) { - return eval(cmd); - } - } - - //move_modified_scope(local_scope, global_scope); - } - catch(e) { - return e.message; - } - } - - function move_modified_scope(l, g) { - - for(var k in g) { - if(g[k] && typeof l[k] == 'undefined') { - l[k] = g[k]; - g[k] = null; - } - } - } - - function safe_scope() { - var s = {}, g = jQConsole.global_scope; - for(var k in g) { s[k] = null; } - s.global_scope = jQConsole.global_scope; - return s; - } - - var encoders = { - "object": function(o, l) { - if(o.constructor == Array) - return encode_array(o); - //return "[array]"; - return "{ " + encode_obj(o, l) + " }"; - }, - "function": function(v) { return v.toString(); }, - "string": function(v) { return "\"" + v + "\""; }, - "undefined": function() { return "undefined"; }, - _default: function(v) { return v.toString(); } - } - - function encode_array(a) { - var r = a.map(enc); - return "[" + r.join(",") + "]"; - } - - enc = function(v, l, root) { - root = root || true; - if(v == null) return (root) ? "" : "null" + l; - if(encoders[typeof v]) return encoders[typeof v](v); - //log("enc", v, l); - return encoders._default(v, l); - } - - function encode_obj(val, expand) { - if(expand <= 0) { return val.toString(); } - var r = []; - for(var i in val) { - r.push(i + ": " + enc(val[i], expand - 1, false)); - } - return r.join(",\n"); - } - - function encode_reg(s) { - return s.replace(/([\\/\t\n])/g, "\\$1"); - } - - function reg_lookup_fn(lookup) { - var re = new RegExp(encode_reg(keys(lookup).join("")), "ig"); - return re; - } - - function print(msg) { - var className = (typeof msg == "function") ? "cmd" : "print"; - msg = enc(msg, 3); - if(!msg) return; - var out = $($.PRE({"className":className}, msg)); - if(className == "cmd") { out.click(select_command); } - output.prepend(out); - } - - function logCommand(cmd, result) { - command_history.push(cmd); - if(result != undefined) { - output.prepend(jQuery.dump(result)); - } - $($.PRE({className:'cmd'}, cmd)).click(select_command).prependTo(output); - //print(result); - return cmd; - } - - function select_command() { - edit_command($(this).text()); - } - - function edit_command(cmd) { - input.val(cmd); - resize_input(); - input.get(0).select(); - } - - function log() { - var msg = args(arguments); - $("
                ").text(msg.join(", ")).prependTo(output); - } - - function resize_input() - { - setTimeout(do_resize, 0); - - function do_resize() { - var rows = input.val().split(/\n/).length - // + 1 // prevent scrollbar flickering in Mozilla - + (window.opera ? 1 : 0); // leave room for scrollbar in Opera - - // without this check, it is impossible to select text in Opera 7.60 or Opera 8.0. - if (input.attr("rows") != rows) - input.attr("rows", rows); - } - } - - var default_scope = { - "log": log, - "history": history, - alert: function(msg) { alert(msg); } - } - disable_functions(default_scope, "window,document,t1"); - - function disable_functions(obj, list) { - var list = list.split(","); - for(var i in list) { - obj[list[i]] = {}; - } - } - - return this; -}; - -jQuery.extend(jQuery.fn, { - "autoresize": function() - { - var thisp = this; - setTimeout(do_resize, 0); - - function do_resize() { - var s = thisp.val() || ""; - var rows = s.split(/\n/).length; - // + 1 // prevent scrollbar flickering in Mozilla - + (window.opera ? 1 : 0); // leave room for scrollbar in Opera - - // without this check, it is impossible to select text in Opera 7.60 or Opera 8.0. - if (thisp.attr("rows") != rows) - thisp.attr("rows", rows); - } - return this; - } -}) - - - -jQConsole.global_scope = this; -jQConsole.our_scope = {}; \ No newline at end of file diff --git a/non-rack-legacy/public/javascripts/controls.js b/non-rack-legacy/public/javascripts/controls.js deleted file mode 100644 index ca29aef..0000000 --- a/non-rack-legacy/public/javascripts/controls.js +++ /dev/null @@ -1,963 +0,0 @@ -// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// (c) 2005-2008 Ivan Krstic (http://blogs.law.harvard.edu/ivan) -// (c) 2005-2008 Jon Tirsen (http://www.tirsen.com) -// Contributors: -// Richard Livsey -// Rahul Bhargava -// Rob Wills -// -// script.aculo.us is freely distributable under the terms of an MIT-style license. -// For details, see the script.aculo.us web site: http://script.aculo.us/ - -// Autocompleter.Base handles all the autocompletion functionality -// that's independent of the data source for autocompletion. This -// includes drawing the autocompletion menu, observing keyboard -// and mouse events, and similar. -// -// Specific autocompleters need to provide, at the very least, -// a getUpdatedChoices function that will be invoked every time -// the text inside the monitored textbox changes. This method -// should get the text for which to provide autocompletion by -// invoking this.getToken(), NOT by directly accessing -// this.element.value. This is to allow incremental tokenized -// autocompletion. Specific auto-completion logic (AJAX, etc) -// belongs in getUpdatedChoices. -// -// Tokenized incremental autocompletion is enabled automatically -// when an autocompleter is instantiated with the 'tokens' option -// in the options parameter, e.g.: -// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' }); -// will incrementally autocomplete with a comma as the token. -// Additionally, ',' in the above example can be replaced with -// a token array, e.g. { tokens: [',', '\n'] } which -// enables autocompletion on multiple tokens. This is most -// useful when one of the tokens is \n (a newline), as it -// allows smart autocompletion after linebreaks. - -if(typeof Effect == 'undefined') - throw("controls.js requires including script.aculo.us' effects.js library"); - -var Autocompleter = { }; -Autocompleter.Base = Class.create({ - baseInitialize: function(element, update, options) { - element = $(element); - this.element = element; - this.update = $(update); - this.hasFocus = false; - this.changed = false; - this.active = false; - this.index = 0; - this.entryCount = 0; - this.oldElementValue = this.element.value; - - if(this.setOptions) - this.setOptions(options); - else - this.options = options || { }; - - this.options.paramName = this.options.paramName || this.element.name; - this.options.tokens = this.options.tokens || []; - this.options.frequency = this.options.frequency || 0.4; - this.options.minChars = this.options.minChars || 1; - this.options.onShow = this.options.onShow || - function(element, update){ - if(!update.style.position || update.style.position=='absolute') { - update.style.position = 'absolute'; - Position.clone(element, update, { - setHeight: false, - offsetTop: element.offsetHeight - }); - } - Effect.Appear(update,{duration:0.15}); - }; - this.options.onHide = this.options.onHide || - function(element, update){ new Effect.Fade(update,{duration:0.15}) }; - - if(typeof(this.options.tokens) == 'string') - this.options.tokens = new Array(this.options.tokens); - // Force carriage returns as token delimiters anyway - if (!this.options.tokens.include('\n')) - this.options.tokens.push('\n'); - - this.observer = null; - - this.element.setAttribute('autocomplete','off'); - - Element.hide(this.update); - - Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this)); - Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this)); - }, - - show: function() { - if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update); - if(!this.iefix && - (Prototype.Browser.IE) && - (Element.getStyle(this.update, 'position')=='absolute')) { - new Insertion.After(this.update, - ''); - this.iefix = $(this.update.id+'_iefix'); - } - if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50); - }, - - fixIEOverlapping: function() { - Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)}); - this.iefix.style.zIndex = 1; - this.update.style.zIndex = 2; - Element.show(this.iefix); - }, - - hide: function() { - this.stopIndicator(); - if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update); - if(this.iefix) Element.hide(this.iefix); - }, - - startIndicator: function() { - if(this.options.indicator) Element.show(this.options.indicator); - }, - - stopIndicator: function() { - if(this.options.indicator) Element.hide(this.options.indicator); - }, - - onKeyPress: function(event) { - if(this.active) - switch(event.keyCode) { - case Event.KEY_TAB: - case Event.KEY_RETURN: - this.selectEntry(); - Event.stop(event); - case Event.KEY_ESC: - this.hide(); - this.active = false; - Event.stop(event); - return; - case Event.KEY_LEFT: - case Event.KEY_RIGHT: - return; - case Event.KEY_UP: - this.markPrevious(); - this.render(); - Event.stop(event); - return; - case Event.KEY_DOWN: - this.markNext(); - this.render(); - Event.stop(event); - return; - } - else - if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || - (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return; - - this.changed = true; - this.hasFocus = true; - - if(this.observer) clearTimeout(this.observer); - this.observer = - setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); - }, - - activate: function() { - this.changed = false; - this.hasFocus = true; - this.getUpdatedChoices(); - }, - - onHover: function(event) { - var element = Event.findElement(event, 'LI'); - if(this.index != element.autocompleteIndex) - { - this.index = element.autocompleteIndex; - this.render(); - } - Event.stop(event); - }, - - onClick: function(event) { - var element = Event.findElement(event, 'LI'); - this.index = element.autocompleteIndex; - this.selectEntry(); - this.hide(); - }, - - onBlur: function(event) { - // needed to make click events working - setTimeout(this.hide.bind(this), 250); - this.hasFocus = false; - this.active = false; - }, - - render: function() { - if(this.entryCount > 0) { - for (var i = 0; i < this.entryCount; i++) - this.index==i ? - Element.addClassName(this.getEntry(i),"selected") : - Element.removeClassName(this.getEntry(i),"selected"); - if(this.hasFocus) { - this.show(); - this.active = true; - } - } else { - this.active = false; - this.hide(); - } - }, - - markPrevious: function() { - if(this.index > 0) this.index--; - else this.index = this.entryCount-1; - this.getEntry(this.index).scrollIntoView(true); - }, - - markNext: function() { - if(this.index < this.entryCount-1) this.index++; - else this.index = 0; - this.getEntry(this.index).scrollIntoView(false); - }, - - getEntry: function(index) { - return this.update.firstChild.childNodes[index]; - }, - - getCurrentEntry: function() { - return this.getEntry(this.index); - }, - - selectEntry: function() { - this.active = false; - this.updateElement(this.getCurrentEntry()); - }, - - updateElement: function(selectedElement) { - if (this.options.updateElement) { - this.options.updateElement(selectedElement); - return; - } - var value = ''; - if (this.options.select) { - var nodes = $(selectedElement).select('.' + this.options.select) || []; - if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); - } else - value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); - - var bounds = this.getTokenBounds(); - if (bounds[0] != -1) { - var newValue = this.element.value.substr(0, bounds[0]); - var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/); - if (whitespace) - newValue += whitespace[0]; - this.element.value = newValue + value + this.element.value.substr(bounds[1]); - } else { - this.element.value = value; - } - this.oldElementValue = this.element.value; - this.element.focus(); - - if (this.options.afterUpdateElement) - this.options.afterUpdateElement(this.element, selectedElement); - }, - - updateChoices: function(choices) { - if(!this.changed && this.hasFocus) { - this.update.innerHTML = choices; - Element.cleanWhitespace(this.update); - Element.cleanWhitespace(this.update.down()); - - if(this.update.firstChild && this.update.down().childNodes) { - this.entryCount = - this.update.down().childNodes.length; - for (var i = 0; i < this.entryCount; i++) { - var entry = this.getEntry(i); - entry.autocompleteIndex = i; - this.addObservers(entry); - } - } else { - this.entryCount = 0; - } - - this.stopIndicator(); - this.index = 0; - - if(this.entryCount==1 && this.options.autoSelect) { - this.selectEntry(); - this.hide(); - } else { - this.render(); - } - } - }, - - addObservers: function(element) { - Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this)); - Event.observe(element, "click", this.onClick.bindAsEventListener(this)); - }, - - onObserverEvent: function() { - this.changed = false; - this.tokenBounds = null; - if(this.getToken().length>=this.options.minChars) { - this.getUpdatedChoices(); - } else { - this.active = false; - this.hide(); - } - this.oldElementValue = this.element.value; - }, - - getToken: function() { - var bounds = this.getTokenBounds(); - return this.element.value.substring(bounds[0], bounds[1]).strip(); - }, - - getTokenBounds: function() { - if (null != this.tokenBounds) return this.tokenBounds; - var value = this.element.value; - if (value.strip().empty()) return [-1, 0]; - var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue); - var offset = (diff == this.oldElementValue.length ? 1 : 0); - var prevTokenPos = -1, nextTokenPos = value.length; - var tp; - for (var index = 0, l = this.options.tokens.length; index < l; ++index) { - tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1); - if (tp > prevTokenPos) prevTokenPos = tp; - tp = value.indexOf(this.options.tokens[index], diff + offset); - if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp; - } - return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]); - } -}); - -Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) { - var boundary = Math.min(newS.length, oldS.length); - for (var index = 0; index < boundary; ++index) - if (newS[index] != oldS[index]) - return index; - return boundary; -}; - -Ajax.Autocompleter = Class.create(Autocompleter.Base, { - initialize: function(element, update, url, options) { - this.baseInitialize(element, update, options); - this.options.asynchronous = true; - this.options.onComplete = this.onComplete.bind(this); - this.options.defaultParams = this.options.parameters || null; - this.url = url; - }, - - getUpdatedChoices: function() { - this.startIndicator(); - - var entry = encodeURIComponent(this.options.paramName) + '=' + - encodeURIComponent(this.getToken()); - - this.options.parameters = this.options.callback ? - this.options.callback(this.element, entry) : entry; - - if(this.options.defaultParams) - this.options.parameters += '&' + this.options.defaultParams; - - new Ajax.Request(this.url, this.options); - }, - - onComplete: function(request) { - this.updateChoices(request.responseText); - } -}); - -// The local array autocompleter. Used when you'd prefer to -// inject an array of autocompletion options into the page, rather -// than sending out Ajax queries, which can be quite slow sometimes. -// -// The constructor takes four parameters. The first two are, as usual, -// the id of the monitored textbox, and id of the autocompletion menu. -// The third is the array you want to autocomplete from, and the fourth -// is the options block. -// -// Extra local autocompletion options: -// - choices - How many autocompletion choices to offer -// -// - partialSearch - If false, the autocompleter will match entered -// text only at the beginning of strings in the -// autocomplete array. Defaults to true, which will -// match text at the beginning of any *word* in the -// strings in the autocomplete array. If you want to -// search anywhere in the string, additionally set -// the option fullSearch to true (default: off). -// -// - fullSsearch - Search anywhere in autocomplete array strings. -// -// - partialChars - How many characters to enter before triggering -// a partial match (unlike minChars, which defines -// how many characters are required to do any match -// at all). Defaults to 2. -// -// - ignoreCase - Whether to ignore case when autocompleting. -// Defaults to true. -// -// It's possible to pass in a custom function as the 'selector' -// option, if you prefer to write your own autocompletion logic. -// In that case, the other options above will not apply unless -// you support them. - -Autocompleter.Local = Class.create(Autocompleter.Base, { - initialize: function(element, update, array, options) { - this.baseInitialize(element, update, options); - this.options.array = array; - }, - - getUpdatedChoices: function() { - this.updateChoices(this.options.selector(this)); - }, - - setOptions: function(options) { - this.options = Object.extend({ - choices: 10, - partialSearch: true, - partialChars: 2, - ignoreCase: true, - fullSearch: false, - selector: function(instance) { - var ret = []; // Beginning matches - var partial = []; // Inside matches - var entry = instance.getToken(); - var count = 0; - - for (var i = 0; i < instance.options.array.length && - ret.length < instance.options.choices ; i++) { - - var elem = instance.options.array[i]; - var foundPos = instance.options.ignoreCase ? - elem.toLowerCase().indexOf(entry.toLowerCase()) : - elem.indexOf(entry); - - while (foundPos != -1) { - if (foundPos == 0 && elem.length != entry.length) { - ret.push("
              2. " + elem.substr(0, entry.length) + "" + - elem.substr(entry.length) + "
              3. "); - break; - } else if (entry.length >= instance.options.partialChars && - instance.options.partialSearch && foundPos != -1) { - if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) { - partial.push("
              4. " + elem.substr(0, foundPos) + "" + - elem.substr(foundPos, entry.length) + "" + elem.substr( - foundPos + entry.length) + "
              5. "); - break; - } - } - - foundPos = instance.options.ignoreCase ? - elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : - elem.indexOf(entry, foundPos + 1); - - } - } - if (partial.length) - ret = ret.concat(partial.slice(0, instance.options.choices - ret.length)); - return "
                  " + ret.join('') + "
                "; - } - }, options || { }); - } -}); - -// AJAX in-place editor and collection editor -// Full rewrite by Christophe Porteneuve (April 2007). - -// Use this if you notice weird scrolling problems on some browsers, -// the DOM might be a bit confused when this gets called so do this -// waits 1 ms (with setTimeout) until it does the activation -Field.scrollFreeActivate = function(field) { - setTimeout(function() { - Field.activate(field); - }, 1); -}; - -Ajax.InPlaceEditor = Class.create({ - initialize: function(element, url, options) { - this.url = url; - this.element = element = $(element); - this.prepareOptions(); - this._controls = { }; - arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!! - Object.extend(this.options, options || { }); - if (!this.options.formId && this.element.id) { - this.options.formId = this.element.id + '-inplaceeditor'; - if ($(this.options.formId)) - this.options.formId = ''; - } - if (this.options.externalControl) - this.options.externalControl = $(this.options.externalControl); - if (!this.options.externalControl) - this.options.externalControlOnly = false; - this._originalBackground = this.element.getStyle('background-color') || 'transparent'; - this.element.title = this.options.clickToEditText; - this._boundCancelHandler = this.handleFormCancellation.bind(this); - this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this); - this._boundFailureHandler = this.handleAJAXFailure.bind(this); - this._boundSubmitHandler = this.handleFormSubmission.bind(this); - this._boundWrapperHandler = this.wrapUp.bind(this); - this.registerListeners(); - }, - checkForEscapeOrReturn: function(e) { - if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return; - if (Event.KEY_ESC == e.keyCode) - this.handleFormCancellation(e); - else if (Event.KEY_RETURN == e.keyCode) - this.handleFormSubmission(e); - }, - createControl: function(mode, handler, extraClasses) { - var control = this.options[mode + 'Control']; - var text = this.options[mode + 'Text']; - if ('button' == control) { - var btn = document.createElement('input'); - btn.type = 'submit'; - btn.value = text; - btn.className = 'editor_' + mode + '_button'; - if ('cancel' == mode) - btn.onclick = this._boundCancelHandler; - this._form.appendChild(btn); - this._controls[mode] = btn; - } else if ('link' == control) { - var link = document.createElement('a'); - link.href = '#'; - link.appendChild(document.createTextNode(text)); - link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler; - link.className = 'editor_' + mode + '_link'; - if (extraClasses) - link.className += ' ' + extraClasses; - this._form.appendChild(link); - this._controls[mode] = link; - } - }, - createEditField: function() { - var text = (this.options.loadTextURL ? this.options.loadingText : this.getText()); - var fld; - if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) { - fld = document.createElement('input'); - fld.type = 'text'; - var size = this.options.size || this.options.cols || 0; - if (0 < size) fld.size = size; - } else { - fld = document.createElement('textarea'); - fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows); - fld.cols = this.options.cols || 40; - } - fld.name = this.options.paramName; - fld.value = text; // No HTML breaks conversion anymore - fld.className = 'editor_field'; - if (this.options.submitOnBlur) - fld.onblur = this._boundSubmitHandler; - this._controls.editor = fld; - if (this.options.loadTextURL) - this.loadExternalText(); - this._form.appendChild(this._controls.editor); - }, - createForm: function() { - var ipe = this; - function addText(mode, condition) { - var text = ipe.options['text' + mode + 'Controls']; - if (!text || condition === false) return; - ipe._form.appendChild(document.createTextNode(text)); - }; - this._form = $(document.createElement('form')); - this._form.id = this.options.formId; - this._form.addClassName(this.options.formClassName); - this._form.onsubmit = this._boundSubmitHandler; - this.createEditField(); - if ('textarea' == this._controls.editor.tagName.toLowerCase()) - this._form.appendChild(document.createElement('br')); - if (this.options.onFormCustomization) - this.options.onFormCustomization(this, this._form); - addText('Before', this.options.okControl || this.options.cancelControl); - this.createControl('ok', this._boundSubmitHandler); - addText('Between', this.options.okControl && this.options.cancelControl); - this.createControl('cancel', this._boundCancelHandler, 'editor_cancel'); - addText('After', this.options.okControl || this.options.cancelControl); - }, - destroy: function() { - if (this._oldInnerHTML) - this.element.innerHTML = this._oldInnerHTML; - this.leaveEditMode(); - this.unregisterListeners(); - }, - enterEditMode: function(e) { - if (this._saving || this._editing) return; - this._editing = true; - this.triggerCallback('onEnterEditMode'); - if (this.options.externalControl) - this.options.externalControl.hide(); - this.element.hide(); - this.createForm(); - this.element.parentNode.insertBefore(this._form, this.element); - if (!this.options.loadTextURL) - this.postProcessEditField(); - if (e) Event.stop(e); - }, - enterHover: function(e) { - if (this.options.hoverClassName) - this.element.addClassName(this.options.hoverClassName); - if (this._saving) return; - this.triggerCallback('onEnterHover'); - }, - getText: function() { - return this.element.innerHTML.unescapeHTML(); - }, - handleAJAXFailure: function(transport) { - this.triggerCallback('onFailure', transport); - if (this._oldInnerHTML) { - this.element.innerHTML = this._oldInnerHTML; - this._oldInnerHTML = null; - } - }, - handleFormCancellation: function(e) { - this.wrapUp(); - if (e) Event.stop(e); - }, - handleFormSubmission: function(e) { - var form = this._form; - var value = $F(this._controls.editor); - this.prepareSubmission(); - var params = this.options.callback(form, value) || ''; - if (Object.isString(params)) - params = params.toQueryParams(); - params.editorId = this.element.id; - if (this.options.htmlResponse) { - var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions); - Object.extend(options, { - parameters: params, - onComplete: this._boundWrapperHandler, - onFailure: this._boundFailureHandler - }); - new Ajax.Updater({ success: this.element }, this.url, options); - } else { - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: params, - onComplete: this._boundWrapperHandler, - onFailure: this._boundFailureHandler - }); - new Ajax.Request(this.url, options); - } - if (e) Event.stop(e); - }, - leaveEditMode: function() { - this.element.removeClassName(this.options.savingClassName); - this.removeForm(); - this.leaveHover(); - this.element.style.backgroundColor = this._originalBackground; - this.element.show(); - if (this.options.externalControl) - this.options.externalControl.show(); - this._saving = false; - this._editing = false; - this._oldInnerHTML = null; - this.triggerCallback('onLeaveEditMode'); - }, - leaveHover: function(e) { - if (this.options.hoverClassName) - this.element.removeClassName(this.options.hoverClassName); - if (this._saving) return; - this.triggerCallback('onLeaveHover'); - }, - loadExternalText: function() { - this._form.addClassName(this.options.loadingClassName); - this._controls.editor.disabled = true; - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: 'editorId=' + encodeURIComponent(this.element.id), - onComplete: Prototype.emptyFunction, - onSuccess: function(transport) { - this._form.removeClassName(this.options.loadingClassName); - var text = transport.responseText; - if (this.options.stripLoadedTextTags) - text = text.stripTags(); - this._controls.editor.value = text; - this._controls.editor.disabled = false; - this.postProcessEditField(); - }.bind(this), - onFailure: this._boundFailureHandler - }); - new Ajax.Request(this.options.loadTextURL, options); - }, - postProcessEditField: function() { - var fpc = this.options.fieldPostCreation; - if (fpc) - $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate'](); - }, - prepareOptions: function() { - this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions); - Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks); - [this._extraDefaultOptions].flatten().compact().each(function(defs) { - Object.extend(this.options, defs); - }.bind(this)); - }, - prepareSubmission: function() { - this._saving = true; - this.removeForm(); - this.leaveHover(); - this.showSaving(); - }, - registerListeners: function() { - this._listeners = { }; - var listener; - $H(Ajax.InPlaceEditor.Listeners).each(function(pair) { - listener = this[pair.value].bind(this); - this._listeners[pair.key] = listener; - if (!this.options.externalControlOnly) - this.element.observe(pair.key, listener); - if (this.options.externalControl) - this.options.externalControl.observe(pair.key, listener); - }.bind(this)); - }, - removeForm: function() { - if (!this._form) return; - this._form.remove(); - this._form = null; - this._controls = { }; - }, - showSaving: function() { - this._oldInnerHTML = this.element.innerHTML; - this.element.innerHTML = this.options.savingText; - this.element.addClassName(this.options.savingClassName); - this.element.style.backgroundColor = this._originalBackground; - this.element.show(); - }, - triggerCallback: function(cbName, arg) { - if ('function' == typeof this.options[cbName]) { - this.options[cbName](this, arg); - } - }, - unregisterListeners: function() { - $H(this._listeners).each(function(pair) { - if (!this.options.externalControlOnly) - this.element.stopObserving(pair.key, pair.value); - if (this.options.externalControl) - this.options.externalControl.stopObserving(pair.key, pair.value); - }.bind(this)); - }, - wrapUp: function(transport) { - this.leaveEditMode(); - // Can't use triggerCallback due to backward compatibility: requires - // binding + direct element - this._boundComplete(transport, this.element); - } -}); - -Object.extend(Ajax.InPlaceEditor.prototype, { - dispose: Ajax.InPlaceEditor.prototype.destroy -}); - -Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, { - initialize: function($super, element, url, options) { - this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions; - $super(element, url, options); - }, - - createEditField: function() { - var list = document.createElement('select'); - list.name = this.options.paramName; - list.size = 1; - this._controls.editor = list; - this._collection = this.options.collection || []; - if (this.options.loadCollectionURL) - this.loadCollection(); - else - this.checkForExternalText(); - this._form.appendChild(this._controls.editor); - }, - - loadCollection: function() { - this._form.addClassName(this.options.loadingClassName); - this.showLoadingText(this.options.loadingCollectionText); - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: 'editorId=' + encodeURIComponent(this.element.id), - onComplete: Prototype.emptyFunction, - onSuccess: function(transport) { - var js = transport.responseText.strip(); - if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check - throw('Server returned an invalid collection representation.'); - this._collection = eval(js); - this.checkForExternalText(); - }.bind(this), - onFailure: this.onFailure - }); - new Ajax.Request(this.options.loadCollectionURL, options); - }, - - showLoadingText: function(text) { - this._controls.editor.disabled = true; - var tempOption = this._controls.editor.firstChild; - if (!tempOption) { - tempOption = document.createElement('option'); - tempOption.value = ''; - this._controls.editor.appendChild(tempOption); - tempOption.selected = true; - } - tempOption.update((text || '').stripScripts().stripTags()); - }, - - checkForExternalText: function() { - this._text = this.getText(); - if (this.options.loadTextURL) - this.loadExternalText(); - else - this.buildOptionList(); - }, - - loadExternalText: function() { - this.showLoadingText(this.options.loadingText); - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: 'editorId=' + encodeURIComponent(this.element.id), - onComplete: Prototype.emptyFunction, - onSuccess: function(transport) { - this._text = transport.responseText.strip(); - this.buildOptionList(); - }.bind(this), - onFailure: this.onFailure - }); - new Ajax.Request(this.options.loadTextURL, options); - }, - - buildOptionList: function() { - this._form.removeClassName(this.options.loadingClassName); - this._collection = this._collection.map(function(entry) { - return 2 === entry.length ? entry : [entry, entry].flatten(); - }); - var marker = ('value' in this.options) ? this.options.value : this._text; - var textFound = this._collection.any(function(entry) { - return entry[0] == marker; - }.bind(this)); - this._controls.editor.update(''); - var option; - this._collection.each(function(entry, index) { - option = document.createElement('option'); - option.value = entry[0]; - option.selected = textFound ? entry[0] == marker : 0 == index; - option.appendChild(document.createTextNode(entry[1])); - this._controls.editor.appendChild(option); - }.bind(this)); - this._controls.editor.disabled = false; - Field.scrollFreeActivate(this._controls.editor); - } -}); - -//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! **** -//**** This only exists for a while, in order to let **** -//**** users adapt to the new API. Read up on the new **** -//**** API and convert your code to it ASAP! **** - -Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) { - if (!options) return; - function fallback(name, expr) { - if (name in options || expr === undefined) return; - options[name] = expr; - }; - fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' : - options.cancelLink == options.cancelButton == false ? false : undefined))); - fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' : - options.okLink == options.okButton == false ? false : undefined))); - fallback('highlightColor', options.highlightcolor); - fallback('highlightEndColor', options.highlightendcolor); -}; - -Object.extend(Ajax.InPlaceEditor, { - DefaultOptions: { - ajaxOptions: { }, - autoRows: 3, // Use when multi-line w/ rows == 1 - cancelControl: 'link', // 'link'|'button'|false - cancelText: 'cancel', - clickToEditText: 'Click to edit', - externalControl: null, // id|elt - externalControlOnly: false, - fieldPostCreation: 'activate', // 'activate'|'focus'|false - formClassName: 'inplaceeditor-form', - formId: null, // id|elt - highlightColor: '#ffff99', - highlightEndColor: '#ffffff', - hoverClassName: '', - htmlResponse: true, - loadingClassName: 'inplaceeditor-loading', - loadingText: 'Loading...', - okControl: 'button', // 'link'|'button'|false - okText: 'ok', - paramName: 'value', - rows: 1, // If 1 and multi-line, uses autoRows - savingClassName: 'inplaceeditor-saving', - savingText: 'Saving...', - size: 0, - stripLoadedTextTags: false, - submitOnBlur: false, - textAfterControls: '', - textBeforeControls: '', - textBetweenControls: '' - }, - DefaultCallbacks: { - callback: function(form) { - return Form.serialize(form); - }, - onComplete: function(transport, element) { - // For backward compatibility, this one is bound to the IPE, and passes - // the element directly. It was too often customized, so we don't break it. - new Effect.Highlight(element, { - startcolor: this.options.highlightColor, keepBackgroundImage: true }); - }, - onEnterEditMode: null, - onEnterHover: function(ipe) { - ipe.element.style.backgroundColor = ipe.options.highlightColor; - if (ipe._effect) - ipe._effect.cancel(); - }, - onFailure: function(transport, ipe) { - alert('Error communication with the server: ' + transport.responseText.stripTags()); - }, - onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls. - onLeaveEditMode: null, - onLeaveHover: function(ipe) { - ipe._effect = new Effect.Highlight(ipe.element, { - startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor, - restorecolor: ipe._originalBackground, keepBackgroundImage: true - }); - } - }, - Listeners: { - click: 'enterEditMode', - keydown: 'checkForEscapeOrReturn', - mouseover: 'enterHover', - mouseout: 'leaveHover' - } -}); - -Ajax.InPlaceCollectionEditor.DefaultOptions = { - loadingCollectionText: 'Loading options...' -}; - -// Delayed observer, like Form.Element.Observer, -// but waits for delay after last key input -// Ideal for live-search fields - -Form.Element.DelayedObserver = Class.create({ - initialize: function(element, delay, callback) { - this.delay = delay || 0.5; - this.element = $(element); - this.callback = callback; - this.timer = null; - this.lastValue = $F(this.element); - Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this)); - }, - delayedListener: function(event) { - if(this.lastValue == $F(this.element)) return; - if(this.timer) clearTimeout(this.timer); - this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000); - this.lastValue = $F(this.element); - }, - onTimerEvent: function() { - this.timer = null; - this.callback(this.element, $F(this.element)); - } -}); \ No newline at end of file diff --git a/non-rack-legacy/public/javascripts/dragdrop.js b/non-rack-legacy/public/javascripts/dragdrop.js deleted file mode 100644 index 07229f9..0000000 --- a/non-rack-legacy/public/javascripts/dragdrop.js +++ /dev/null @@ -1,973 +0,0 @@ -// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// (c) 2005-2008 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz) -// -// script.aculo.us is freely distributable under the terms of an MIT-style license. -// For details, see the script.aculo.us web site: http://script.aculo.us/ - -if(Object.isUndefined(Effect)) - throw("dragdrop.js requires including script.aculo.us' effects.js library"); - -var Droppables = { - drops: [], - - remove: function(element) { - this.drops = this.drops.reject(function(d) { return d.element==$(element) }); - }, - - add: function(element) { - element = $(element); - var options = Object.extend({ - greedy: true, - hoverclass: null, - tree: false - }, arguments[1] || { }); - - // cache containers - if(options.containment) { - options._containers = []; - var containment = options.containment; - if(Object.isArray(containment)) { - containment.each( function(c) { options._containers.push($(c)) }); - } else { - options._containers.push($(containment)); - } - } - - if(options.accept) options.accept = [options.accept].flatten(); - - Element.makePositioned(element); // fix IE - options.element = element; - - this.drops.push(options); - }, - - findDeepestChild: function(drops) { - deepest = drops[0]; - - for (i = 1; i < drops.length; ++i) - if (Element.isParent(drops[i].element, deepest.element)) - deepest = drops[i]; - - return deepest; - }, - - isContained: function(element, drop) { - var containmentNode; - if(drop.tree) { - containmentNode = element.treeNode; - } else { - containmentNode = element.parentNode; - } - return drop._containers.detect(function(c) { return containmentNode == c }); - }, - - isAffected: function(point, element, drop) { - return ( - (drop.element!=element) && - ((!drop._containers) || - this.isContained(element, drop)) && - ((!drop.accept) || - (Element.classNames(element).detect( - function(v) { return drop.accept.include(v) } ) )) && - Position.within(drop.element, point[0], point[1]) ); - }, - - deactivate: function(drop) { - if(drop.hoverclass) - Element.removeClassName(drop.element, drop.hoverclass); - this.last_active = null; - }, - - activate: function(drop) { - if(drop.hoverclass) - Element.addClassName(drop.element, drop.hoverclass); - this.last_active = drop; - }, - - show: function(point, element) { - if(!this.drops.length) return; - var drop, affected = []; - - this.drops.each( function(drop) { - if(Droppables.isAffected(point, element, drop)) - affected.push(drop); - }); - - if(affected.length>0) - drop = Droppables.findDeepestChild(affected); - - if(this.last_active && this.last_active != drop) this.deactivate(this.last_active); - if (drop) { - Position.within(drop.element, point[0], point[1]); - if(drop.onHover) - drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); - - if (drop != this.last_active) Droppables.activate(drop); - } - }, - - fire: function(event, element) { - if(!this.last_active) return; - Position.prepare(); - - if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active)) - if (this.last_active.onDrop) { - this.last_active.onDrop(element, this.last_active.element, event); - return true; - } - }, - - reset: function() { - if(this.last_active) - this.deactivate(this.last_active); - } -}; - -var Draggables = { - drags: [], - observers: [], - - register: function(draggable) { - if(this.drags.length == 0) { - this.eventMouseUp = this.endDrag.bindAsEventListener(this); - this.eventMouseMove = this.updateDrag.bindAsEventListener(this); - this.eventKeypress = this.keyPress.bindAsEventListener(this); - - Event.observe(document, "mouseup", this.eventMouseUp); - Event.observe(document, "mousemove", this.eventMouseMove); - Event.observe(document, "keypress", this.eventKeypress); - } - this.drags.push(draggable); - }, - - unregister: function(draggable) { - this.drags = this.drags.reject(function(d) { return d==draggable }); - if(this.drags.length == 0) { - Event.stopObserving(document, "mouseup", this.eventMouseUp); - Event.stopObserving(document, "mousemove", this.eventMouseMove); - Event.stopObserving(document, "keypress", this.eventKeypress); - } - }, - - activate: function(draggable) { - if(draggable.options.delay) { - this._timeout = setTimeout(function() { - Draggables._timeout = null; - window.focus(); - Draggables.activeDraggable = draggable; - }.bind(this), draggable.options.delay); - } else { - window.focus(); // allows keypress events if window isn't currently focused, fails for Safari - this.activeDraggable = draggable; - } - }, - - deactivate: function() { - this.activeDraggable = null; - }, - - updateDrag: function(event) { - if(!this.activeDraggable) return; - var pointer = [Event.pointerX(event), Event.pointerY(event)]; - // Mozilla-based browsers fire successive mousemove events with - // the same coordinates, prevent needless redrawing (moz bug?) - if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return; - this._lastPointer = pointer; - - this.activeDraggable.updateDrag(event, pointer); - }, - - endDrag: function(event) { - if(this._timeout) { - clearTimeout(this._timeout); - this._timeout = null; - } - if(!this.activeDraggable) return; - this._lastPointer = null; - this.activeDraggable.endDrag(event); - this.activeDraggable = null; - }, - - keyPress: function(event) { - if(this.activeDraggable) - this.activeDraggable.keyPress(event); - }, - - addObserver: function(observer) { - this.observers.push(observer); - this._cacheObserverCallbacks(); - }, - - removeObserver: function(element) { // element instead of observer fixes mem leaks - this.observers = this.observers.reject( function(o) { return o.element==element }); - this._cacheObserverCallbacks(); - }, - - notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag' - if(this[eventName+'Count'] > 0) - this.observers.each( function(o) { - if(o[eventName]) o[eventName](eventName, draggable, event); - }); - if(draggable.options[eventName]) draggable.options[eventName](draggable, event); - }, - - _cacheObserverCallbacks: function() { - ['onStart','onEnd','onDrag'].each( function(eventName) { - Draggables[eventName+'Count'] = Draggables.observers.select( - function(o) { return o[eventName]; } - ).length; - }); - } -}; - -/*--------------------------------------------------------------------------*/ - -var Draggable = Class.create({ - initialize: function(element) { - var defaults = { - handle: false, - reverteffect: function(element, top_offset, left_offset) { - var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02; - new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur, - queue: {scope:'_draggable', position:'end'} - }); - }, - endeffect: function(element) { - var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0; - new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity, - queue: {scope:'_draggable', position:'end'}, - afterFinish: function(){ - Draggable._dragging[element] = false - } - }); - }, - zindex: 1000, - revert: false, - quiet: false, - scroll: false, - scrollSensitivity: 20, - scrollSpeed: 15, - snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] } - delay: 0 - }; - - if(!arguments[1] || Object.isUndefined(arguments[1].endeffect)) - Object.extend(defaults, { - starteffect: function(element) { - element._opacity = Element.getOpacity(element); - Draggable._dragging[element] = true; - new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7}); - } - }); - - var options = Object.extend(defaults, arguments[1] || { }); - - this.element = $(element); - - if(options.handle && Object.isString(options.handle)) - this.handle = this.element.down('.'+options.handle, 0); - - if(!this.handle) this.handle = $(options.handle); - if(!this.handle) this.handle = this.element; - - if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) { - options.scroll = $(options.scroll); - this._isScrollChild = Element.childOf(this.element, options.scroll); - } - - Element.makePositioned(this.element); // fix IE - - this.options = options; - this.dragging = false; - - this.eventMouseDown = this.initDrag.bindAsEventListener(this); - Event.observe(this.handle, "mousedown", this.eventMouseDown); - - Draggables.register(this); - }, - - destroy: function() { - Event.stopObserving(this.handle, "mousedown", this.eventMouseDown); - Draggables.unregister(this); - }, - - currentDelta: function() { - return([ - parseInt(Element.getStyle(this.element,'left') || '0'), - parseInt(Element.getStyle(this.element,'top') || '0')]); - }, - - initDrag: function(event) { - if(!Object.isUndefined(Draggable._dragging[this.element]) && - Draggable._dragging[this.element]) return; - if(Event.isLeftClick(event)) { - // abort on form elements, fixes a Firefox issue - var src = Event.element(event); - if((tag_name = src.tagName.toUpperCase()) && ( - tag_name=='INPUT' || - tag_name=='SELECT' || - tag_name=='OPTION' || - tag_name=='BUTTON' || - tag_name=='TEXTAREA')) return; - - var pointer = [Event.pointerX(event), Event.pointerY(event)]; - var pos = Position.cumulativeOffset(this.element); - this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) }); - - Draggables.activate(this); - Event.stop(event); - } - }, - - startDrag: function(event) { - this.dragging = true; - if(!this.delta) - this.delta = this.currentDelta(); - - if(this.options.zindex) { - this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0); - this.element.style.zIndex = this.options.zindex; - } - - if(this.options.ghosting) { - this._clone = this.element.cloneNode(true); - this._originallyAbsolute = (this.element.getStyle('position') == 'absolute'); - if (!this._originallyAbsolute) - Position.absolutize(this.element); - this.element.parentNode.insertBefore(this._clone, this.element); - } - - if(this.options.scroll) { - if (this.options.scroll == window) { - var where = this._getWindowScroll(this.options.scroll); - this.originalScrollLeft = where.left; - this.originalScrollTop = where.top; - } else { - this.originalScrollLeft = this.options.scroll.scrollLeft; - this.originalScrollTop = this.options.scroll.scrollTop; - } - } - - Draggables.notify('onStart', this, event); - - if(this.options.starteffect) this.options.starteffect(this.element); - }, - - updateDrag: function(event, pointer) { - if(!this.dragging) this.startDrag(event); - - if(!this.options.quiet){ - Position.prepare(); - Droppables.show(pointer, this.element); - } - - Draggables.notify('onDrag', this, event); - - this.draw(pointer); - if(this.options.change) this.options.change(this); - - if(this.options.scroll) { - this.stopScrolling(); - - var p; - if (this.options.scroll == window) { - with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; } - } else { - p = Position.page(this.options.scroll); - p[0] += this.options.scroll.scrollLeft + Position.deltaX; - p[1] += this.options.scroll.scrollTop + Position.deltaY; - p.push(p[0]+this.options.scroll.offsetWidth); - p.push(p[1]+this.options.scroll.offsetHeight); - } - var speed = [0,0]; - if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity); - if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity); - if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity); - if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity); - this.startScrolling(speed); - } - - // fix AppleWebKit rendering - if(Prototype.Browser.WebKit) window.scrollBy(0,0); - - Event.stop(event); - }, - - finishDrag: function(event, success) { - this.dragging = false; - - if(this.options.quiet){ - Position.prepare(); - var pointer = [Event.pointerX(event), Event.pointerY(event)]; - Droppables.show(pointer, this.element); - } - - if(this.options.ghosting) { - if (!this._originallyAbsolute) - Position.relativize(this.element); - delete this._originallyAbsolute; - Element.remove(this._clone); - this._clone = null; - } - - var dropped = false; - if(success) { - dropped = Droppables.fire(event, this.element); - if (!dropped) dropped = false; - } - if(dropped && this.options.onDropped) this.options.onDropped(this.element); - Draggables.notify('onEnd', this, event); - - var revert = this.options.revert; - if(revert && Object.isFunction(revert)) revert = revert(this.element); - - var d = this.currentDelta(); - if(revert && this.options.reverteffect) { - if (dropped == 0 || revert != 'failure') - this.options.reverteffect(this.element, - d[1]-this.delta[1], d[0]-this.delta[0]); - } else { - this.delta = d; - } - - if(this.options.zindex) - this.element.style.zIndex = this.originalZ; - - if(this.options.endeffect) - this.options.endeffect(this.element); - - Draggables.deactivate(this); - Droppables.reset(); - }, - - keyPress: function(event) { - if(event.keyCode!=Event.KEY_ESC) return; - this.finishDrag(event, false); - Event.stop(event); - }, - - endDrag: function(event) { - if(!this.dragging) return; - this.stopScrolling(); - this.finishDrag(event, true); - Event.stop(event); - }, - - draw: function(point) { - var pos = Position.cumulativeOffset(this.element); - if(this.options.ghosting) { - var r = Position.realOffset(this.element); - pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY; - } - - var d = this.currentDelta(); - pos[0] -= d[0]; pos[1] -= d[1]; - - if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) { - pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft; - pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop; - } - - var p = [0,1].map(function(i){ - return (point[i]-pos[i]-this.offset[i]) - }.bind(this)); - - if(this.options.snap) { - if(Object.isFunction(this.options.snap)) { - p = this.options.snap(p[0],p[1],this); - } else { - if(Object.isArray(this.options.snap)) { - p = p.map( function(v, i) { - return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this)); - } else { - p = p.map( function(v) { - return (v/this.options.snap).round()*this.options.snap }.bind(this)); - } - }} - - var style = this.element.style; - if((!this.options.constraint) || (this.options.constraint=='horizontal')) - style.left = p[0] + "px"; - if((!this.options.constraint) || (this.options.constraint=='vertical')) - style.top = p[1] + "px"; - - if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering - }, - - stopScrolling: function() { - if(this.scrollInterval) { - clearInterval(this.scrollInterval); - this.scrollInterval = null; - Draggables._lastScrollPointer = null; - } - }, - - startScrolling: function(speed) { - if(!(speed[0] || speed[1])) return; - this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed]; - this.lastScrolled = new Date(); - this.scrollInterval = setInterval(this.scroll.bind(this), 10); - }, - - scroll: function() { - var current = new Date(); - var delta = current - this.lastScrolled; - this.lastScrolled = current; - if(this.options.scroll == window) { - with (this._getWindowScroll(this.options.scroll)) { - if (this.scrollSpeed[0] || this.scrollSpeed[1]) { - var d = delta / 1000; - this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] ); - } - } - } else { - this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; - this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000; - } - - Position.prepare(); - Droppables.show(Draggables._lastPointer, this.element); - Draggables.notify('onDrag', this); - if (this._isScrollChild) { - Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer); - Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000; - Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000; - if (Draggables._lastScrollPointer[0] < 0) - Draggables._lastScrollPointer[0] = 0; - if (Draggables._lastScrollPointer[1] < 0) - Draggables._lastScrollPointer[1] = 0; - this.draw(Draggables._lastScrollPointer); - } - - if(this.options.change) this.options.change(this); - }, - - _getWindowScroll: function(w) { - var T, L, W, H; - with (w.document) { - if (w.document.documentElement && documentElement.scrollTop) { - T = documentElement.scrollTop; - L = documentElement.scrollLeft; - } else if (w.document.body) { - T = body.scrollTop; - L = body.scrollLeft; - } - if (w.innerWidth) { - W = w.innerWidth; - H = w.innerHeight; - } else if (w.document.documentElement && documentElement.clientWidth) { - W = documentElement.clientWidth; - H = documentElement.clientHeight; - } else { - W = body.offsetWidth; - H = body.offsetHeight; - } - } - return { top: T, left: L, width: W, height: H }; - } -}); - -Draggable._dragging = { }; - -/*--------------------------------------------------------------------------*/ - -var SortableObserver = Class.create({ - initialize: function(element, observer) { - this.element = $(element); - this.observer = observer; - this.lastValue = Sortable.serialize(this.element); - }, - - onStart: function() { - this.lastValue = Sortable.serialize(this.element); - }, - - onEnd: function() { - Sortable.unmark(); - if(this.lastValue != Sortable.serialize(this.element)) - this.observer(this.element) - } -}); - -var Sortable = { - SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/, - - sortables: { }, - - _findRootElement: function(element) { - while (element.tagName.toUpperCase() != "BODY") { - if(element.id && Sortable.sortables[element.id]) return element; - element = element.parentNode; - } - }, - - options: function(element) { - element = Sortable._findRootElement($(element)); - if(!element) return; - return Sortable.sortables[element.id]; - }, - - destroy: function(element){ - element = $(element); - var s = Sortable.sortables[element.id]; - - if(s) { - Draggables.removeObserver(s.element); - s.droppables.each(function(d){ Droppables.remove(d) }); - s.draggables.invoke('destroy'); - - delete Sortable.sortables[s.element.id]; - } - }, - - create: function(element) { - element = $(element); - var options = Object.extend({ - element: element, - tag: 'li', // assumes li children, override with tag: 'tagname' - dropOnEmpty: false, - tree: false, - treeTag: 'ul', - overlap: 'vertical', // one of 'vertical', 'horizontal' - constraint: 'vertical', // one of 'vertical', 'horizontal', false - containment: element, // also takes array of elements (or id's); or false - handle: false, // or a CSS class - only: false, - delay: 0, - hoverclass: null, - ghosting: false, - quiet: false, - scroll: false, - scrollSensitivity: 20, - scrollSpeed: 15, - format: this.SERIALIZE_RULE, - - // these take arrays of elements or ids and can be - // used for better initialization performance - elements: false, - handles: false, - - onChange: Prototype.emptyFunction, - onUpdate: Prototype.emptyFunction - }, arguments[1] || { }); - - // clear any old sortable with same element - this.destroy(element); - - // build options for the draggables - var options_for_draggable = { - revert: true, - quiet: options.quiet, - scroll: options.scroll, - scrollSpeed: options.scrollSpeed, - scrollSensitivity: options.scrollSensitivity, - delay: options.delay, - ghosting: options.ghosting, - constraint: options.constraint, - handle: options.handle }; - - if(options.starteffect) - options_for_draggable.starteffect = options.starteffect; - - if(options.reverteffect) - options_for_draggable.reverteffect = options.reverteffect; - else - if(options.ghosting) options_for_draggable.reverteffect = function(element) { - element.style.top = 0; - element.style.left = 0; - }; - - if(options.endeffect) - options_for_draggable.endeffect = options.endeffect; - - if(options.zindex) - options_for_draggable.zindex = options.zindex; - - // build options for the droppables - var options_for_droppable = { - overlap: options.overlap, - containment: options.containment, - tree: options.tree, - hoverclass: options.hoverclass, - onHover: Sortable.onHover - }; - - var options_for_tree = { - onHover: Sortable.onEmptyHover, - overlap: options.overlap, - containment: options.containment, - hoverclass: options.hoverclass - }; - - // fix for gecko engine - Element.cleanWhitespace(element); - - options.draggables = []; - options.droppables = []; - - // drop on empty handling - if(options.dropOnEmpty || options.tree) { - Droppables.add(element, options_for_tree); - options.droppables.push(element); - } - - (options.elements || this.findElements(element, options) || []).each( function(e,i) { - var handle = options.handles ? $(options.handles[i]) : - (options.handle ? $(e).select('.' + options.handle)[0] : e); - options.draggables.push( - new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); - Droppables.add(e, options_for_droppable); - if(options.tree) e.treeNode = element; - options.droppables.push(e); - }); - - if(options.tree) { - (Sortable.findTreeElements(element, options) || []).each( function(e) { - Droppables.add(e, options_for_tree); - e.treeNode = element; - options.droppables.push(e); - }); - } - - // keep reference - this.sortables[element.id] = options; - - // for onupdate - Draggables.addObserver(new SortableObserver(element, options.onUpdate)); - - }, - - // return all suitable-for-sortable elements in a guaranteed order - findElements: function(element, options) { - return Element.findChildren( - element, options.only, options.tree ? true : false, options.tag); - }, - - findTreeElements: function(element, options) { - return Element.findChildren( - element, options.only, options.tree ? true : false, options.treeTag); - }, - - onHover: function(element, dropon, overlap) { - if(Element.isParent(dropon, element)) return; - - if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) { - return; - } else if(overlap>0.5) { - Sortable.mark(dropon, 'before'); - if(dropon.previousSibling != element) { - var oldParentNode = element.parentNode; - element.style.visibility = "hidden"; // fix gecko rendering - dropon.parentNode.insertBefore(element, dropon); - if(dropon.parentNode!=oldParentNode) - Sortable.options(oldParentNode).onChange(element); - Sortable.options(dropon.parentNode).onChange(element); - } - } else { - Sortable.mark(dropon, 'after'); - var nextElement = dropon.nextSibling || null; - if(nextElement != element) { - var oldParentNode = element.parentNode; - element.style.visibility = "hidden"; // fix gecko rendering - dropon.parentNode.insertBefore(element, nextElement); - if(dropon.parentNode!=oldParentNode) - Sortable.options(oldParentNode).onChange(element); - Sortable.options(dropon.parentNode).onChange(element); - } - } - }, - - onEmptyHover: function(element, dropon, overlap) { - var oldParentNode = element.parentNode; - var droponOptions = Sortable.options(dropon); - - if(!Element.isParent(dropon, element)) { - var index; - - var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only}); - var child = null; - - if(children) { - var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap); - - for (index = 0; index < children.length; index += 1) { - if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) { - offset -= Element.offsetSize (children[index], droponOptions.overlap); - } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) { - child = index + 1 < children.length ? children[index + 1] : null; - break; - } else { - child = children[index]; - break; - } - } - } - - dropon.insertBefore(element, child); - - Sortable.options(oldParentNode).onChange(element); - droponOptions.onChange(element); - } - }, - - unmark: function() { - if(Sortable._marker) Sortable._marker.hide(); - }, - - mark: function(dropon, position) { - // mark on ghosting only - var sortable = Sortable.options(dropon.parentNode); - if(sortable && !sortable.ghosting) return; - - if(!Sortable._marker) { - Sortable._marker = - ($('dropmarker') || Element.extend(document.createElement('DIV'))). - hide().addClassName('dropmarker').setStyle({position:'absolute'}); - document.getElementsByTagName("body").item(0).appendChild(Sortable._marker); - } - var offsets = Position.cumulativeOffset(dropon); - Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'}); - - if(position=='after') - if(sortable.overlap == 'horizontal') - Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'}); - else - Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'}); - - Sortable._marker.show(); - }, - - _tree: function(element, options, parent) { - var children = Sortable.findElements(element, options) || []; - - for (var i = 0; i < children.length; ++i) { - var match = children[i].id.match(options.format); - - if (!match) continue; - - var child = { - id: encodeURIComponent(match ? match[1] : null), - element: element, - parent: parent, - children: [], - position: parent.children.length, - container: $(children[i]).down(options.treeTag) - }; - - /* Get the element containing the children and recurse over it */ - if (child.container) - this._tree(child.container, options, child); - - parent.children.push (child); - } - - return parent; - }, - - tree: function(element) { - element = $(element); - var sortableOptions = this.options(element); - var options = Object.extend({ - tag: sortableOptions.tag, - treeTag: sortableOptions.treeTag, - only: sortableOptions.only, - name: element.id, - format: sortableOptions.format - }, arguments[1] || { }); - - var root = { - id: null, - parent: null, - children: [], - container: element, - position: 0 - }; - - return Sortable._tree(element, options, root); - }, - - /* Construct a [i] index for a particular node */ - _constructIndex: function(node) { - var index = ''; - do { - if (node.id) index = '[' + node.position + ']' + index; - } while ((node = node.parent) != null); - return index; - }, - - sequence: function(element) { - element = $(element); - var options = Object.extend(this.options(element), arguments[1] || { }); - - return $(this.findElements(element, options) || []).map( function(item) { - return item.id.match(options.format) ? item.id.match(options.format)[1] : ''; - }); - }, - - setSequence: function(element, new_sequence) { - element = $(element); - var options = Object.extend(this.options(element), arguments[2] || { }); - - var nodeMap = { }; - this.findElements(element, options).each( function(n) { - if (n.id.match(options.format)) - nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode]; - n.parentNode.removeChild(n); - }); - - new_sequence.each(function(ident) { - var n = nodeMap[ident]; - if (n) { - n[1].appendChild(n[0]); - delete nodeMap[ident]; - } - }); - }, - - serialize: function(element) { - element = $(element); - var options = Object.extend(Sortable.options(element), arguments[1] || { }); - var name = encodeURIComponent( - (arguments[1] && arguments[1].name) ? arguments[1].name : element.id); - - if (options.tree) { - return Sortable.tree(element, arguments[1]).children.map( function (item) { - return [name + Sortable._constructIndex(item) + "[id]=" + - encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)); - }).flatten().join('&'); - } else { - return Sortable.sequence(element, arguments[1]).map( function(item) { - return name + "[]=" + encodeURIComponent(item); - }).join('&'); - } - } -}; - -// Returns true if child is contained within element -Element.isParent = function(child, element) { - if (!child.parentNode || child == element) return false; - if (child.parentNode == element) return true; - return Element.isParent(child.parentNode, element); -}; - -Element.findChildren = function(element, only, recursive, tagName) { - if(!element.hasChildNodes()) return null; - tagName = tagName.toUpperCase(); - if(only) only = [only].flatten(); - var elements = []; - $A(element.childNodes).each( function(e) { - if(e.tagName && e.tagName.toUpperCase()==tagName && - (!only || (Element.classNames(e).detect(function(v) { return only.include(v) })))) - elements.push(e); - if(recursive) { - var grandchildren = Element.findChildren(e, only, recursive, tagName); - if(grandchildren) elements.push(grandchildren); - } - }); - - return (elements.length>0 ? elements.flatten() : []); -}; - -Element.offsetSize = function (element, type) { - return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')]; -}; \ No newline at end of file diff --git a/non-rack-legacy/public/javascripts/effects.js b/non-rack-legacy/public/javascripts/effects.js deleted file mode 100644 index 5a639d2..0000000 --- a/non-rack-legacy/public/javascripts/effects.js +++ /dev/null @@ -1,1128 +0,0 @@ -// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// Contributors: -// Justin Palmer (http://encytemedia.com/) -// Mark Pilgrim (http://diveintomark.org/) -// Martin Bialasinki -// -// script.aculo.us is freely distributable under the terms of an MIT-style license. -// For details, see the script.aculo.us web site: http://script.aculo.us/ - -// converts rgb() and #xxx to #xxxxxx format, -// returns self (or first argument) if not convertable -String.prototype.parseColor = function() { - var color = '#'; - if (this.slice(0,4) == 'rgb(') { - var cols = this.slice(4,this.length-1).split(','); - var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); - } else { - if (this.slice(0,1) == '#') { - if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); - if (this.length==7) color = this.toLowerCase(); - } - } - return (color.length==7 ? color : (arguments[0] || this)); -}; - -/*--------------------------------------------------------------------------*/ - -Element.collectTextNodes = function(element) { - return $A($(element).childNodes).collect( function(node) { - return (node.nodeType==3 ? node.nodeValue : - (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); - }).flatten().join(''); -}; - -Element.collectTextNodesIgnoreClass = function(element, className) { - return $A($(element).childNodes).collect( function(node) { - return (node.nodeType==3 ? node.nodeValue : - ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? - Element.collectTextNodesIgnoreClass(node, className) : '')); - }).flatten().join(''); -}; - -Element.setContentZoom = function(element, percent) { - element = $(element); - element.setStyle({fontSize: (percent/100) + 'em'}); - if (Prototype.Browser.WebKit) window.scrollBy(0,0); - return element; -}; - -Element.getInlineOpacity = function(element){ - return $(element).style.opacity || ''; -}; - -Element.forceRerendering = function(element) { - try { - element = $(element); - var n = document.createTextNode(' '); - element.appendChild(n); - element.removeChild(n); - } catch(e) { } -}; - -/*--------------------------------------------------------------------------*/ - -var Effect = { - _elementDoesNotExistError: { - name: 'ElementDoesNotExistError', - message: 'The specified DOM element does not exist, but is required for this effect to operate' - }, - Transitions: { - linear: Prototype.K, - sinoidal: function(pos) { - return (-Math.cos(pos*Math.PI)/2) + .5; - }, - reverse: function(pos) { - return 1-pos; - }, - flicker: function(pos) { - var pos = ((-Math.cos(pos*Math.PI)/4) + .75) + Math.random()/4; - return pos > 1 ? 1 : pos; - }, - wobble: function(pos) { - return (-Math.cos(pos*Math.PI*(9*pos))/2) + .5; - }, - pulse: function(pos, pulses) { - return (-Math.cos((pos*((pulses||5)-.5)*2)*Math.PI)/2) + .5; - }, - spring: function(pos) { - return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6)); - }, - none: function(pos) { - return 0; - }, - full: function(pos) { - return 1; - } - }, - DefaultOptions: { - duration: 1.0, // seconds - fps: 100, // 100= assume 66fps max. - sync: false, // true for combining - from: 0.0, - to: 1.0, - delay: 0.0, - queue: 'parallel' - }, - tagifyText: function(element) { - var tagifyStyle = 'position:relative'; - if (Prototype.Browser.IE) tagifyStyle += ';zoom:1'; - - element = $(element); - $A(element.childNodes).each( function(child) { - if (child.nodeType==3) { - child.nodeValue.toArray().each( function(character) { - element.insertBefore( - new Element('span', {style: tagifyStyle}).update( - character == ' ' ? String.fromCharCode(160) : character), - child); - }); - Element.remove(child); - } - }); - }, - multiple: function(element, effect) { - var elements; - if (((typeof element == 'object') || - Object.isFunction(element)) && - (element.length)) - elements = element; - else - elements = $(element).childNodes; - - var options = Object.extend({ - speed: 0.1, - delay: 0.0 - }, arguments[2] || { }); - var masterDelay = options.delay; - - $A(elements).each( function(element, index) { - new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); - }); - }, - PAIRS: { - 'slide': ['SlideDown','SlideUp'], - 'blind': ['BlindDown','BlindUp'], - 'appear': ['Appear','Fade'] - }, - toggle: function(element, effect) { - element = $(element); - effect = (effect || 'appear').toLowerCase(); - var options = Object.extend({ - queue: { position:'end', scope:(element.id || 'global'), limit: 1 } - }, arguments[2] || { }); - Effect[element.visible() ? - Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); - } -}; - -Effect.DefaultOptions.transition = Effect.Transitions.sinoidal; - -/* ------------- core effects ------------- */ - -Effect.ScopedQueue = Class.create(Enumerable, { - initialize: function() { - this.effects = []; - this.interval = null; - }, - _each: function(iterator) { - this.effects._each(iterator); - }, - add: function(effect) { - var timestamp = new Date().getTime(); - - var position = Object.isString(effect.options.queue) ? - effect.options.queue : effect.options.queue.position; - - switch(position) { - case 'front': - // move unstarted effects after this effect - this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { - e.startOn += effect.finishOn; - e.finishOn += effect.finishOn; - }); - break; - case 'with-last': - timestamp = this.effects.pluck('startOn').max() || timestamp; - break; - case 'end': - // start effect after last queued effect has finished - timestamp = this.effects.pluck('finishOn').max() || timestamp; - break; - } - - effect.startOn += timestamp; - effect.finishOn += timestamp; - - if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) - this.effects.push(effect); - - if (!this.interval) - this.interval = setInterval(this.loop.bind(this), 15); - }, - remove: function(effect) { - this.effects = this.effects.reject(function(e) { return e==effect }); - if (this.effects.length == 0) { - clearInterval(this.interval); - this.interval = null; - } - }, - loop: function() { - var timePos = new Date().getTime(); - for(var i=0, len=this.effects.length;i= this.startOn) { - if (timePos >= this.finishOn) { - this.render(1.0); - this.cancel(); - this.event('beforeFinish'); - if (this.finish) this.finish(); - this.event('afterFinish'); - return; - } - var pos = (timePos - this.startOn) / this.totalTime, - frame = (pos * this.totalFrames).round(); - if (frame > this.currentFrame) { - this.render(pos); - this.currentFrame = frame; - } - } - }, - cancel: function() { - if (!this.options.sync) - Effect.Queues.get(Object.isString(this.options.queue) ? - 'global' : this.options.queue.scope).remove(this); - this.state = 'finished'; - }, - event: function(eventName) { - if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); - if (this.options[eventName]) this.options[eventName](this); - }, - inspect: function() { - var data = $H(); - for(property in this) - if (!Object.isFunction(this[property])) data.set(property, this[property]); - return '#'; - } -}); - -Effect.Parallel = Class.create(Effect.Base, { - initialize: function(effects) { - this.effects = effects || []; - this.start(arguments[1]); - }, - update: function(position) { - this.effects.invoke('render', position); - }, - finish: function(position) { - this.effects.each( function(effect) { - effect.render(1.0); - effect.cancel(); - effect.event('beforeFinish'); - if (effect.finish) effect.finish(position); - effect.event('afterFinish'); - }); - } -}); - -Effect.Tween = Class.create(Effect.Base, { - initialize: function(object, from, to) { - object = Object.isString(object) ? $(object) : object; - var args = $A(arguments), method = args.last(), - options = args.length == 5 ? args[3] : null; - this.method = Object.isFunction(method) ? method.bind(object) : - Object.isFunction(object[method]) ? object[method].bind(object) : - function(value) { object[method] = value }; - this.start(Object.extend({ from: from, to: to }, options || { })); - }, - update: function(position) { - this.method(position); - } -}); - -Effect.Event = Class.create(Effect.Base, { - initialize: function() { - this.start(Object.extend({ duration: 0 }, arguments[0] || { })); - }, - update: Prototype.emptyFunction -}); - -Effect.Opacity = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - // make this work on IE on elements without 'layout' - if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) - this.element.setStyle({zoom: 1}); - var options = Object.extend({ - from: this.element.getOpacity() || 0.0, - to: 1.0 - }, arguments[1] || { }); - this.start(options); - }, - update: function(position) { - this.element.setOpacity(position); - } -}); - -Effect.Move = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ - x: 0, - y: 0, - mode: 'relative' - }, arguments[1] || { }); - this.start(options); - }, - setup: function() { - this.element.makePositioned(); - this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); - this.originalTop = parseFloat(this.element.getStyle('top') || '0'); - if (this.options.mode == 'absolute') { - this.options.x = this.options.x - this.originalLeft; - this.options.y = this.options.y - this.originalTop; - } - }, - update: function(position) { - this.element.setStyle({ - left: (this.options.x * position + this.originalLeft).round() + 'px', - top: (this.options.y * position + this.originalTop).round() + 'px' - }); - } -}); - -// for backwards compatibility -Effect.MoveBy = function(element, toTop, toLeft) { - return new Effect.Move(element, - Object.extend({ x: toLeft, y: toTop }, arguments[3] || { })); -}; - -Effect.Scale = Class.create(Effect.Base, { - initialize: function(element, percent) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ - scaleX: true, - scaleY: true, - scaleContent: true, - scaleFromCenter: false, - scaleMode: 'box', // 'box' or 'contents' or { } with provided values - scaleFrom: 100.0, - scaleTo: percent - }, arguments[2] || { }); - this.start(options); - }, - setup: function() { - this.restoreAfterFinish = this.options.restoreAfterFinish || false; - this.elementPositioning = this.element.getStyle('position'); - - this.originalStyle = { }; - ['top','left','width','height','fontSize'].each( function(k) { - this.originalStyle[k] = this.element.style[k]; - }.bind(this)); - - this.originalTop = this.element.offsetTop; - this.originalLeft = this.element.offsetLeft; - - var fontSize = this.element.getStyle('font-size') || '100%'; - ['em','px','%','pt'].each( function(fontSizeType) { - if (fontSize.indexOf(fontSizeType)>0) { - this.fontSize = parseFloat(fontSize); - this.fontSizeType = fontSizeType; - } - }.bind(this)); - - this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; - - this.dims = null; - if (this.options.scaleMode=='box') - this.dims = [this.element.offsetHeight, this.element.offsetWidth]; - if (/^content/.test(this.options.scaleMode)) - this.dims = [this.element.scrollHeight, this.element.scrollWidth]; - if (!this.dims) - this.dims = [this.options.scaleMode.originalHeight, - this.options.scaleMode.originalWidth]; - }, - update: function(position) { - var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); - if (this.options.scaleContent && this.fontSize) - this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); - this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); - }, - finish: function(position) { - if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); - }, - setDimensions: function(height, width) { - var d = { }; - if (this.options.scaleX) d.width = width.round() + 'px'; - if (this.options.scaleY) d.height = height.round() + 'px'; - if (this.options.scaleFromCenter) { - var topd = (height - this.dims[0])/2; - var leftd = (width - this.dims[1])/2; - if (this.elementPositioning == 'absolute') { - if (this.options.scaleY) d.top = this.originalTop-topd + 'px'; - if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; - } else { - if (this.options.scaleY) d.top = -topd + 'px'; - if (this.options.scaleX) d.left = -leftd + 'px'; - } - } - this.element.setStyle(d); - } -}); - -Effect.Highlight = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { }); - this.start(options); - }, - setup: function() { - // Prevent executing on elements not in the layout flow - if (this.element.getStyle('display')=='none') { this.cancel(); return; } - // Disable background image during the effect - this.oldStyle = { }; - if (!this.options.keepBackgroundImage) { - this.oldStyle.backgroundImage = this.element.getStyle('background-image'); - this.element.setStyle({backgroundImage: 'none'}); - } - if (!this.options.endcolor) - this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); - if (!this.options.restorecolor) - this.options.restorecolor = this.element.getStyle('background-color'); - // init color calculations - this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); - this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this)); - }, - update: function(position) { - this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ - return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) }); - }, - finish: function() { - this.element.setStyle(Object.extend(this.oldStyle, { - backgroundColor: this.options.restorecolor - })); - } -}); - -Effect.ScrollTo = function(element) { - var options = arguments[1] || { }, - scrollOffsets = document.viewport.getScrollOffsets(), - elementOffsets = $(element).cumulativeOffset(); - - if (options.offset) elementOffsets[1] += options.offset; - - return new Effect.Tween(null, - scrollOffsets.top, - elementOffsets[1], - options, - function(p){ scrollTo(scrollOffsets.left, p.round()); } - ); -}; - -/* ------------- combination effects ------------- */ - -Effect.Fade = function(element) { - element = $(element); - var oldOpacity = element.getInlineOpacity(); - var options = Object.extend({ - from: element.getOpacity() || 1.0, - to: 0.0, - afterFinishInternal: function(effect) { - if (effect.options.to!=0) return; - effect.element.hide().setStyle({opacity: oldOpacity}); - } - }, arguments[1] || { }); - return new Effect.Opacity(element,options); -}; - -Effect.Appear = function(element) { - element = $(element); - var options = Object.extend({ - from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), - to: 1.0, - // force Safari to render floated elements properly - afterFinishInternal: function(effect) { - effect.element.forceRerendering(); - }, - beforeSetup: function(effect) { - effect.element.setOpacity(effect.options.from).show(); - }}, arguments[1] || { }); - return new Effect.Opacity(element,options); -}; - -Effect.Puff = function(element) { - element = $(element); - var oldStyle = { - opacity: element.getInlineOpacity(), - position: element.getStyle('position'), - top: element.style.top, - left: element.style.left, - width: element.style.width, - height: element.style.height - }; - return new Effect.Parallel( - [ new Effect.Scale(element, 200, - { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), - new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], - Object.extend({ duration: 1.0, - beforeSetupInternal: function(effect) { - Position.absolutize(effect.effects[0].element); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.hide().setStyle(oldStyle); } - }, arguments[1] || { }) - ); -}; - -Effect.BlindUp = function(element) { - element = $(element); - element.makeClipping(); - return new Effect.Scale(element, 0, - Object.extend({ scaleContent: false, - scaleX: false, - restoreAfterFinish: true, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping(); - } - }, arguments[1] || { }) - ); -}; - -Effect.BlindDown = function(element) { - element = $(element); - var elementDimensions = element.getDimensions(); - return new Effect.Scale(element, 100, Object.extend({ - scaleContent: false, - scaleX: false, - scaleFrom: 0, - scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, - restoreAfterFinish: true, - afterSetup: function(effect) { - effect.element.makeClipping().setStyle({height: '0px'}).show(); - }, - afterFinishInternal: function(effect) { - effect.element.undoClipping(); - } - }, arguments[1] || { })); -}; - -Effect.SwitchOff = function(element) { - element = $(element); - var oldOpacity = element.getInlineOpacity(); - return new Effect.Appear(element, Object.extend({ - duration: 0.4, - from: 0, - transition: Effect.Transitions.flicker, - afterFinishInternal: function(effect) { - new Effect.Scale(effect.element, 1, { - duration: 0.3, scaleFromCenter: true, - scaleX: false, scaleContent: false, restoreAfterFinish: true, - beforeSetup: function(effect) { - effect.element.makePositioned().makeClipping(); - }, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity}); - } - }); - } - }, arguments[1] || { })); -}; - -Effect.DropOut = function(element) { - element = $(element); - var oldStyle = { - top: element.getStyle('top'), - left: element.getStyle('left'), - opacity: element.getInlineOpacity() }; - return new Effect.Parallel( - [ new Effect.Move(element, {x: 0, y: 100, sync: true }), - new Effect.Opacity(element, { sync: true, to: 0.0 }) ], - Object.extend( - { duration: 0.5, - beforeSetup: function(effect) { - effect.effects[0].element.makePositioned(); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle); - } - }, arguments[1] || { })); -}; - -Effect.Shake = function(element) { - element = $(element); - var options = Object.extend({ - distance: 20, - duration: 0.5 - }, arguments[1] || {}); - var distance = parseFloat(options.distance); - var split = parseFloat(options.duration) / 10.0; - var oldStyle = { - top: element.getStyle('top'), - left: element.getStyle('left') }; - return new Effect.Move(element, - { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) { - effect.element.undoPositioned().setStyle(oldStyle); - }}); }}); }}); }}); }}); }}); -}; - -Effect.SlideDown = function(element) { - element = $(element).cleanWhitespace(); - // SlideDown need to have the content of the element wrapped in a container element with fixed height! - var oldInnerBottom = element.down().getStyle('bottom'); - var elementDimensions = element.getDimensions(); - return new Effect.Scale(element, 100, Object.extend({ - scaleContent: false, - scaleX: false, - scaleFrom: window.opera ? 0 : 1, - scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, - restoreAfterFinish: true, - afterSetup: function(effect) { - effect.element.makePositioned(); - effect.element.down().makePositioned(); - if (window.opera) effect.element.setStyle({top: ''}); - effect.element.makeClipping().setStyle({height: '0px'}).show(); - }, - afterUpdateInternal: function(effect) { - effect.element.down().setStyle({bottom: - (effect.dims[0] - effect.element.clientHeight) + 'px' }); - }, - afterFinishInternal: function(effect) { - effect.element.undoClipping().undoPositioned(); - effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); } - }, arguments[1] || { }) - ); -}; - -Effect.SlideUp = function(element) { - element = $(element).cleanWhitespace(); - var oldInnerBottom = element.down().getStyle('bottom'); - var elementDimensions = element.getDimensions(); - return new Effect.Scale(element, window.opera ? 0 : 1, - Object.extend({ scaleContent: false, - scaleX: false, - scaleMode: 'box', - scaleFrom: 100, - scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, - restoreAfterFinish: true, - afterSetup: function(effect) { - effect.element.makePositioned(); - effect.element.down().makePositioned(); - if (window.opera) effect.element.setStyle({top: ''}); - effect.element.makeClipping().show(); - }, - afterUpdateInternal: function(effect) { - effect.element.down().setStyle({bottom: - (effect.dims[0] - effect.element.clientHeight) + 'px' }); - }, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping().undoPositioned(); - effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); - } - }, arguments[1] || { }) - ); -}; - -// Bug in opera makes the TD containing this element expand for a instance after finish -Effect.Squish = function(element) { - return new Effect.Scale(element, window.opera ? 1 : 0, { - restoreAfterFinish: true, - beforeSetup: function(effect) { - effect.element.makeClipping(); - }, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping(); - } - }); -}; - -Effect.Grow = function(element) { - element = $(element); - var options = Object.extend({ - direction: 'center', - moveTransition: Effect.Transitions.sinoidal, - scaleTransition: Effect.Transitions.sinoidal, - opacityTransition: Effect.Transitions.full - }, arguments[1] || { }); - var oldStyle = { - top: element.style.top, - left: element.style.left, - height: element.style.height, - width: element.style.width, - opacity: element.getInlineOpacity() }; - - var dims = element.getDimensions(); - var initialMoveX, initialMoveY; - var moveX, moveY; - - switch (options.direction) { - case 'top-left': - initialMoveX = initialMoveY = moveX = moveY = 0; - break; - case 'top-right': - initialMoveX = dims.width; - initialMoveY = moveY = 0; - moveX = -dims.width; - break; - case 'bottom-left': - initialMoveX = moveX = 0; - initialMoveY = dims.height; - moveY = -dims.height; - break; - case 'bottom-right': - initialMoveX = dims.width; - initialMoveY = dims.height; - moveX = -dims.width; - moveY = -dims.height; - break; - case 'center': - initialMoveX = dims.width / 2; - initialMoveY = dims.height / 2; - moveX = -dims.width / 2; - moveY = -dims.height / 2; - break; - } - - return new Effect.Move(element, { - x: initialMoveX, - y: initialMoveY, - duration: 0.01, - beforeSetup: function(effect) { - effect.element.hide().makeClipping().makePositioned(); - }, - afterFinishInternal: function(effect) { - new Effect.Parallel( - [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), - new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), - new Effect.Scale(effect.element, 100, { - scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, - sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) - ], Object.extend({ - beforeSetup: function(effect) { - effect.effects[0].element.setStyle({height: '0px'}).show(); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle); - } - }, options) - ); - } - }); -}; - -Effect.Shrink = function(element) { - element = $(element); - var options = Object.extend({ - direction: 'center', - moveTransition: Effect.Transitions.sinoidal, - scaleTransition: Effect.Transitions.sinoidal, - opacityTransition: Effect.Transitions.none - }, arguments[1] || { }); - var oldStyle = { - top: element.style.top, - left: element.style.left, - height: element.style.height, - width: element.style.width, - opacity: element.getInlineOpacity() }; - - var dims = element.getDimensions(); - var moveX, moveY; - - switch (options.direction) { - case 'top-left': - moveX = moveY = 0; - break; - case 'top-right': - moveX = dims.width; - moveY = 0; - break; - case 'bottom-left': - moveX = 0; - moveY = dims.height; - break; - case 'bottom-right': - moveX = dims.width; - moveY = dims.height; - break; - case 'center': - moveX = dims.width / 2; - moveY = dims.height / 2; - break; - } - - return new Effect.Parallel( - [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), - new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), - new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) - ], Object.extend({ - beforeStartInternal: function(effect) { - effect.effects[0].element.makePositioned().makeClipping(); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); } - }, options) - ); -}; - -Effect.Pulsate = function(element) { - element = $(element); - var options = arguments[1] || { }, - oldOpacity = element.getInlineOpacity(), - transition = options.transition || Effect.Transitions.linear, - reverser = function(pos){ - return 1 - transition((-Math.cos((pos*(options.pulses||5)*2)*Math.PI)/2) + .5); - }; - - return new Effect.Opacity(element, - Object.extend(Object.extend({ duration: 2.0, from: 0, - afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } - }, options), {transition: reverser})); -}; - -Effect.Fold = function(element) { - element = $(element); - var oldStyle = { - top: element.style.top, - left: element.style.left, - width: element.style.width, - height: element.style.height }; - element.makeClipping(); - return new Effect.Scale(element, 5, Object.extend({ - scaleContent: false, - scaleX: false, - afterFinishInternal: function(effect) { - new Effect.Scale(element, 1, { - scaleContent: false, - scaleY: false, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping().setStyle(oldStyle); - } }); - }}, arguments[1] || { })); -}; - -Effect.Morph = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ - style: { } - }, arguments[1] || { }); - - if (!Object.isString(options.style)) this.style = $H(options.style); - else { - if (options.style.include(':')) - this.style = options.style.parseStyle(); - else { - this.element.addClassName(options.style); - this.style = $H(this.element.getStyles()); - this.element.removeClassName(options.style); - var css = this.element.getStyles(); - this.style = this.style.reject(function(style) { - return style.value == css[style.key]; - }); - options.afterFinishInternal = function(effect) { - effect.element.addClassName(effect.options.style); - effect.transforms.each(function(transform) { - effect.element.style[transform.style] = ''; - }); - }; - } - } - this.start(options); - }, - - setup: function(){ - function parseColor(color){ - if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff'; - color = color.parseColor(); - return $R(0,2).map(function(i){ - return parseInt( color.slice(i*2+1,i*2+3), 16 ); - }); - } - this.transforms = this.style.map(function(pair){ - var property = pair[0], value = pair[1], unit = null; - - if (value.parseColor('#zzzzzz') != '#zzzzzz') { - value = value.parseColor(); - unit = 'color'; - } else if (property == 'opacity') { - value = parseFloat(value); - if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) - this.element.setStyle({zoom: 1}); - } else if (Element.CSS_LENGTH.test(value)) { - var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); - value = parseFloat(components[1]); - unit = (components.length == 3) ? components[2] : null; - } - - var originalValue = this.element.getStyle(property); - return { - style: property.camelize(), - originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), - targetValue: unit=='color' ? parseColor(value) : value, - unit: unit - }; - }.bind(this)).reject(function(transform){ - return ( - (transform.originalValue == transform.targetValue) || - ( - transform.unit != 'color' && - (isNaN(transform.originalValue) || isNaN(transform.targetValue)) - ) - ); - }); - }, - update: function(position) { - var style = { }, transform, i = this.transforms.length; - while(i--) - style[(transform = this.transforms[i]).style] = - transform.unit=='color' ? '#'+ - (Math.round(transform.originalValue[0]+ - (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() + - (Math.round(transform.originalValue[1]+ - (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() + - (Math.round(transform.originalValue[2]+ - (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() : - (transform.originalValue + - (transform.targetValue - transform.originalValue) * position).toFixed(3) + - (transform.unit === null ? '' : transform.unit); - this.element.setStyle(style, true); - } -}); - -Effect.Transform = Class.create({ - initialize: function(tracks){ - this.tracks = []; - this.options = arguments[1] || { }; - this.addTracks(tracks); - }, - addTracks: function(tracks){ - tracks.each(function(track){ - track = $H(track); - var data = track.values().first(); - this.tracks.push($H({ - ids: track.keys().first(), - effect: Effect.Morph, - options: { style: data } - })); - }.bind(this)); - return this; - }, - play: function(){ - return new Effect.Parallel( - this.tracks.map(function(track){ - var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options'); - var elements = [$(ids) || $$(ids)].flatten(); - return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) }); - }).flatten(), - this.options - ); - } -}); - -Element.CSS_PROPERTIES = $w( - 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + - 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' + - 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' + - 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' + - 'fontSize fontWeight height left letterSpacing lineHeight ' + - 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+ - 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' + - 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' + - 'right textIndent top width wordSpacing zIndex'); - -Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; - -String.__parseStyleElement = document.createElement('div'); -String.prototype.parseStyle = function(){ - var style, styleRules = $H(); - if (Prototype.Browser.WebKit) - style = new Element('div',{style:this}).style; - else { - String.__parseStyleElement.innerHTML = '
                '; - style = String.__parseStyleElement.childNodes[0].style; - } - - Element.CSS_PROPERTIES.each(function(property){ - if (style[property]) styleRules.set(property, style[property]); - }); - - if (Prototype.Browser.IE && this.include('opacity')) - styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]); - - return styleRules; -}; - -if (document.defaultView && document.defaultView.getComputedStyle) { - Element.getStyles = function(element) { - var css = document.defaultView.getComputedStyle($(element), null); - return Element.CSS_PROPERTIES.inject({ }, function(styles, property) { - styles[property] = css[property]; - return styles; - }); - }; -} else { - Element.getStyles = function(element) { - element = $(element); - var css = element.currentStyle, styles; - styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) { - results[property] = css[property]; - return results; - }); - if (!styles.opacity) styles.opacity = element.getOpacity(); - return styles; - }; -} - -Effect.Methods = { - morph: function(element, style) { - element = $(element); - new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { })); - return element; - }, - visualEffect: function(element, effect, options) { - element = $(element); - var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1); - new Effect[klass](element, options); - return element; - }, - highlight: function(element, options) { - element = $(element); - new Effect.Highlight(element, options); - return element; - } -}; - -$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+ - 'pulsate shake puff squish switchOff dropOut').each( - function(effect) { - Effect.Methods[effect] = function(element, options){ - element = $(element); - Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options); - return element; - }; - } -); - -$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each( - function(f) { Effect.Methods[f] = Element[f]; } -); - -Element.addMethods(Effect.Methods); \ No newline at end of file diff --git a/non-rack-legacy/public/javascripts/facebox.js b/non-rack-legacy/public/javascripts/facebox.js deleted file mode 100755 index 5ad90ed..0000000 --- a/non-rack-legacy/public/javascripts/facebox.js +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Facebox (for jQuery) - * version: 1.2 (05/05/2008) - * @requires jQuery v1.2 or later - * - * Examples at http://famspam.com/facebox/ - * - * Licensed under the MIT: - * http://www.opensource.org/licenses/mit-license.php - * - * Copyright 2007, 2008 Chris Wanstrath [ chris@ozmm.org ] - * - * Usage: - * - * jQuery(document).ready(function() { - * jQuery('a[rel*=facebox]').facebox() - * }) - * - * Terms - * Loads the #terms div in the box - * - * Terms - * Loads the terms.html page in the box - * - * Terms - * Loads the terms.png image in the box - * - * - * You can also use it programmatically: - * - * jQuery.facebox('some html') - * jQuery.facebox('some html', 'my-groovy-style') - * - * The above will open a facebox with "some html" as the content. - * - * jQuery.facebox(function($) { - * $.get('blah.html', function(data) { $.facebox(data) }) - * }) - * - * The above will show a loading screen before the passed function is called, - * allowing for a better ajaxy experience. - * - * The facebox function can also display an ajax page, an image, or the contents of a div: - * - * jQuery.facebox({ ajax: 'remote.html' }) - * jQuery.facebox({ ajax: 'remote.html' }, 'my-groovy-style') - * jQuery.facebox({ image: 'stairs.jpg' }) - * jQuery.facebox({ image: 'stairs.jpg' }, 'my-groovy-style') - * jQuery.facebox({ div: '#box' }) - * jQuery.facebox({ div: '#box' }, 'my-groovy-style') - * - * Want to close the facebox? Trigger the 'close.facebox' document event: - * - * jQuery(document).trigger('close.facebox') - * - * Facebox also has a bunch of other hooks: - * - * loading.facebox - * beforeReveal.facebox - * reveal.facebox (aliased as 'afterReveal.facebox') - * init.facebox - * afterClose.facebox - * - * Simply bind a function to any of these hooks: - * - * $(document).bind('reveal.facebox', function() { ...stuff to do after the facebox and contents are revealed... }) - * - */ -(function($) { - $.facebox = function(data, klass) { - $.facebox.loading() - - if (data.ajax) fillFaceboxFromAjax(data.ajax, klass) - else if (data.image) fillFaceboxFromImage(data.image, klass) - else if (data.div) fillFaceboxFromHref(data.div, klass) - else if ($.isFunction(data)) data.call($) - else $.facebox.reveal(data, klass) - } - - /* - * Public, $.facebox methods - */ - - $.extend($.facebox, { - settings: { - opacity : 0.2, - overlay : true, - loadingImage : '/facebox/loading.gif', - closeImage : '/facebox/closelabel.png', - imageTypes : [ 'png', 'jpg', 'jpeg', 'gif' ], - faceboxHtml : '\ - ' - }, - - loading: function() { - init() - if ($('#facebox .loading').length == 1) return true - showOverlay() - - $('#facebox .content').empty() - $('#facebox .body').children().hide().end(). - append('
                ') - - $('#facebox').css({ - top: getPageScroll()[1] + (getPageHeight() / 10), - left: $(window).width() / 2 - 205 - }).show() - - $(document).bind('keydown.facebox', function(e) { - if (e.keyCode == 27) $.facebox.close() - return true - }) - $(document).trigger('loading.facebox') - }, - - reveal: function(data, klass) { - $(document).trigger('beforeReveal.facebox') - if (klass) $('#facebox .content').addClass(klass) - $('#facebox .content').append(data) - $('#facebox .loading').remove() - $('#facebox .body').children().fadeIn('normal') - $('#facebox').css('left', $(window).width() / 2 - ($('#facebox .popup').width() / 2)) - $(document).trigger('reveal.facebox').trigger('afterReveal.facebox') - }, - - close: function() { - $(document).trigger('close.facebox') - return false - } - }) - - /* - * Public, $.fn methods - */ - - $.fn.facebox = function(settings) { - if ($(this).length == 0) return - - init(settings) - - function clickHandler() { - $.facebox.loading(true) - - // support for rel="facebox.inline_popup" syntax, to add a class - // also supports deprecated "facebox[.inline_popup]" syntax - var klass = this.rel.match(/facebox\[?\.(\w+)\]?/) - if (klass) klass = klass[1] - - fillFaceboxFromHref(this.href, klass) - return false - } - - return this.bind('click.facebox', clickHandler) - } - - /* - * Private methods - */ - - // called one time to setup facebox on this page - function init(settings) { - if ($.facebox.settings.inited) return true - else $.facebox.settings.inited = true - - $(document).trigger('init.facebox') - makeCompatible() - - var imageTypes = $.facebox.settings.imageTypes.join('|') - $.facebox.settings.imageTypesRegexp = new RegExp('\.(' + imageTypes + ')$', 'i') - - if (settings) $.extend($.facebox.settings, settings) - $('body').append($.facebox.settings.faceboxHtml) - - var preload = [ new Image(), new Image() ] - preload[0].src = $.facebox.settings.closeImage - preload[1].src = $.facebox.settings.loadingImage - - $('#facebox').find('.b:first, .bl').each(function() { - preload.push(new Image()) - preload.slice(-1).src = $(this).css('background-image').replace(/url\((.+)\)/, '$1') - }) - - $('#facebox .close').click($.facebox.close) - $('#facebox .close_image').attr('src', $.facebox.settings.closeImage) - } - - // getPageScroll() by quirksmode.com - function getPageScroll() { - var xScroll, yScroll; - if (self.pageYOffset) { - yScroll = self.pageYOffset; - xScroll = self.pageXOffset; - } else if (document.documentElement && document.documentElement.scrollTop) { // Explorer 6 Strict - yScroll = document.documentElement.scrollTop; - xScroll = document.documentElement.scrollLeft; - } else if (document.body) {// all other Explorers - yScroll = document.body.scrollTop; - xScroll = document.body.scrollLeft; - } - return new Array(xScroll,yScroll) - } - - // Adapted from getPageSize() by quirksmode.com - function getPageHeight() { - var windowHeight - if (self.innerHeight) { // all except Explorer - windowHeight = self.innerHeight; - } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode - windowHeight = document.documentElement.clientHeight; - } else if (document.body) { // other Explorers - windowHeight = document.body.clientHeight; - } - return windowHeight - } - - // Backwards compatibility - function makeCompatible() { - var $s = $.facebox.settings - - $s.loadingImage = $s.loading_image || $s.loadingImage - $s.closeImage = $s.close_image || $s.closeImage - $s.imageTypes = $s.image_types || $s.imageTypes - $s.faceboxHtml = $s.facebox_html || $s.faceboxHtml - } - - // Figures out what you want to display and displays it - // formats are: - // div: #id - // image: blah.extension - // ajax: anything else - function fillFaceboxFromHref(href, klass) { - // div - if (href.match(/#/)) { - var url = window.location.href.split('#')[0] - var target = href.replace(url,'') - if (target == '#') return - $.facebox.reveal($(target).html(), klass) - - // image - } else if (href.match($.facebox.settings.imageTypesRegexp)) { - fillFaceboxFromImage(href, klass) - // ajax - } else { - fillFaceboxFromAjax(href, klass) - } - } - - function fillFaceboxFromImage(href, klass) { - var image = new Image() - image.onload = function() { - $.facebox.reveal('
                ', klass) - } - image.src = href - } - - function fillFaceboxFromAjax(href, klass) { - $.get(href, function(data) { $.facebox.reveal(data, klass) }) - } - - function skipOverlay() { - return $.facebox.settings.overlay == false || $.facebox.settings.opacity === null - } - - function showOverlay() { - if (skipOverlay()) return - - if ($('#facebox_overlay').length == 0) - $("body").append('
                ') - - $('#facebox_overlay').hide().addClass("facebox_overlayBG") - .css('opacity', $.facebox.settings.opacity) - .click(function() { $(document).trigger('close.facebox') }) - .fadeIn(200) - return false - } - - function hideOverlay() { - if (skipOverlay()) return - - $('#facebox_overlay').fadeOut(200, function(){ - $("#facebox_overlay").removeClass("facebox_overlayBG") - $("#facebox_overlay").addClass("facebox_hide") - $("#facebox_overlay").remove() - }) - - return false - } - - /* - * Bindings - */ - - $(document).bind('close.facebox', function() { - $(document).unbind('keydown.facebox') - $('#facebox').fadeOut(function() { - $('#facebox .content').removeClass().addClass('content') - $('#facebox .loading').remove() - $(document).trigger('afterClose.facebox') - }) - hideOverlay() - }) - -})(jQuery); diff --git a/non-rack-legacy/public/javascripts/index.html b/non-rack-legacy/public/javascripts/index.html deleted file mode 100755 index e933af9..0000000 --- a/non-rack-legacy/public/javascripts/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -

                you shouldn't be here.. kicking you out!

                - - diff --git a/non-rack-legacy/public/javascripts/irb.js b/non-rack-legacy/public/javascripts/irb.js deleted file mode 100755 index b4cb354..0000000 --- a/non-rack-legacy/public/javascripts/irb.js +++ /dev/null @@ -1,110 +0,0 @@ -// -// Copyright (c) 2008 why the lucky stiff -// Copyright (c) 2010 Andrew McElroy -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, -// and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT -// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -var allStretch; -var helpPages; -var chapPages; -var defaultPage; -var toot = window.location.search.substr(1) - -//the main function, call to the effect object -function dumpAlert(obj) { - props = []; - for ( var i in obj ) { - props.push( "" + i + ": " + obj[i] ); - } - alert( props ); -} -window.onload = function() { - defaultPage = $('#helpstone .stretcher').html(); - - window.irb = new MouseApp.Irb('#irb', { - rows: 13, - name: 'IRB', - greeting: "%+r Interactive ruby ready. %-r", - ps: '\033[1;31m>>\033[m', - user: 'guest', - host: 'tryruby', - // original: irbUrl: '/irb', - irbUrl: '/tryruby/run', - init: function () { - helpPages = $(".stretcher"); - chapPages = new Array(); - for (var i = 0; i < helpPages.length; i++ ) { - var cls = helpPages[i].className.split(' '); - for (var j = 0; j < cls.length; j++) { - if (cls[j] == 'chapmark') { - chapPages.push([i, helpPages[i]]); - break; - } - } - } - }, - loadTutorial: function (id, instruct) { - $.ajax({ - url: '/tutorials/' + id , - type: 'GET', - complete: function (r) { - $('#helpstone').html("
                " + defaultPage + "
                " + r.responseText); - window.irb.init(); - window.irb.showHelp(0); - } - }); - }, - showChapter: function (n) { - if (n >= chapPages.length) return; - this.setHelpPage(chapPages[n][0], chapPages[n][1]); - }, - showHelp: function (n) { - if (n >= helpPages.length) return; - this.setHelpPage(n, helpPages[n]); - }, - popup_goto: function (u) { - $('#lilBrowser').show().css({left: '40px', top: '40px'}); - $('#lbIframe').attr('src', u); - }, - popup_make: function (s) { - $('#lilBrowser').show().css({left: '40px', top: '40px'}); - $('#lbIframe').get(0).onIframeLoad = function () { - alert($(this).html()); - alert("$(this).html()"); - return s; - }; - //$('#lbIframe').attr({src: '/blank.html'}); - src = s.replace(/\\/g, "\\\\").replace(/\"/g, "\\\""); - $('#lbIframe').attr({src: "javascript:\"" + src + "\""}); - // $('# - }, - popup_close: function () { - $('#lilBrowser').hide(); - } - }); - - if ( !toot ) { - toot = 'intro'; - } - try { - window.irb.options.loadTutorial( toot, true ); - } catch (e) {} -} diff --git a/non-rack-legacy/public/javascripts/jQuery.irb.js b/non-rack-legacy/public/javascripts/jQuery.irb.js deleted file mode 100644 index 765858d..0000000 --- a/non-rack-legacy/public/javascripts/jQuery.irb.js +++ /dev/null @@ -1,1641 +0,0 @@ -//Try Ruby 1.5 (defacto version Number) -// March 14 2011 - -// large parts of this file are lifted from Try Haskell ( which lifted parts from try ruby without copyright notice >:-/ ) - -// Thus it is fair to include the following banner if/until there is no try haskell code left/ only code that originally existed in try ruby in the -//first place. - - // Try Haskell 1.0.1 - // Tue Feb 23 18:34:48 GMT 2010 - // - // Copyright 2010 Chris Done. All rights reserved. - // - // Redistribution and use in source and binary forms, with or without - // modification, are permitted provided that the following conditions - // are met: - // - // 1. Redistributions of source code must retain the above - // copyright notice, this list of conditions and the following - // disclaimer. - // 2. Redistributions in binary form must reproduce the above - // copyright notice, this list of conditions and the following - // disclaimer in the documentation and/or other materials - // provided with the distribution. - // - // THIS SOFTWARE IS PROVIDED BY CHRIS DONE ``AS IS'' AND ANY EXPRESS - // OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - // ARE DISCLAIMED. IN NO EVENT SHALL CHRIS DONE OR CONTRIBUTORS BE - // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - // OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - // DAMAGE. - // The views and conclusions contained in the software and - // documentation are those of the authors and should not be - // interpreted as representing official policies, either expressed or - // implied, of Chris Done. - // - // TESTED ON - // Internet Explorer 6 - // Opera 10.01 - // Chromium 4.0.237.0 (Ubuntu build 31094) - // Firefox 3.5.8 - - //IOS 4.3 (all devices) - -// Temporary fix -function opera() { - return navigator.userAgent.indexOf("Opera") == 0; -} - -function encodeHex(str) { - var result = ""; - for (var i = 0; i < str.length; i++) { - result += "%" + pad(toHex(str.charCodeAt(i) & 0xff), 2, '0'); - } - return result; -} - -//var handleJSON = function(a){ alert('Unassigned JSONP: ' + a); } -var hexv = { - "00": 0, - "01": 1, - "02": 2, - "03": 3, - "04": 4, - "05": 5, - "06": 6, - "07": 7, - "08": 8, - "09": 9, - "0A": 10, - "0B": 11, - "0C": 12, - "0D": 13, - "0E": 14, - "0F": 15, - "10": 16, - "11": 17, - "12": 18, - "13": 19, - "14": 20, - "15": 21, - "16": 22, - "17": 23, - "18": 24, - "19": 25, - "1A": 26, - "1B": 27, - "1C": 28, - "1D": 29, - "1E": 30, - "1F": 31, - "20": 32, - "21": 33, - "22": 34, - "23": 35, - "24": 36, - "25": 37, - "26": 38, - "27": 39, - "28": 40, - "29": 41, - "2A": 42, - "2B": 43, - "2C": 44, - "2D": 45, - "2E": 46, - "2F": 47, - "30": 48, - "31": 49, - "32": 50, - "33": 51, - "34": 52, - "35": 53, - "36": 54, - "37": 55, - "38": 56, - "39": 57, - "3A": 58, - "3B": 59, - "3C": 60, - "3D": 61, - "3E": 62, - "3F": 63, - "40": 64, - "41": 65, - "42": 66, - "43": 67, - "44": 68, - "45": 69, - "46": 70, - "47": 71, - "48": 72, - "49": 73, - "4A": 74, - "4B": 75, - "4C": 76, - "4D": 77, - "4E": 78, - "4F": 79, - "50": 80, - "51": 81, - "52": 82, - "53": 83, - "54": 84, - "55": 85, - "56": 86, - "57": 87, - "58": 88, - "59": 89, - "5A": 90, - "5B": 91, - "5C": 92, - "5D": 93, - "5E": 94, - "5F": 95, - "60": 96, - "61": 97, - "62": 98, - "63": 99, - "64": 100, - "65": 101, - "66": 102, - "67": 103, - "68": 104, - "69": 105, - "6A": 106, - "6B": 107, - "6C": 108, - "6D": 109, - "6E": 110, - "6F": 111, - "70": 112, - "71": 113, - "72": 114, - "73": 115, - "74": 116, - "75": 117, - "76": 118, - "77": 119, - "78": 120, - "79": 121, - "7A": 122, - "7B": 123, - "7C": 124, - "7D": 125, - "7E": 126, - "7F": 127, - "80": 128, - "81": 129, - "82": 130, - "83": 131, - "84": 132, - "85": 133, - "86": 134, - "87": 135, - "88": 136, - "89": 137, - "8A": 138, - "8B": 139, - "8C": 140, - "8D": 141, - "8E": 142, - "8F": 143, - "90": 144, - "91": 145, - "92": 146, - "93": 147, - "94": 148, - "95": 149, - "96": 150, - "97": 151, - "98": 152, - "99": 153, - "9A": 154, - "9B": 155, - "9C": 156, - "9D": 157, - "9E": 158, - "9F": 159, - "A0": 160, - "A1": 161, - "A2": 162, - "A3": 163, - "A4": 164, - "A5": 165, - "A6": 166, - "A7": 167, - "A8": 168, - "A9": 169, - "AA": 170, - "AB": 171, - "AC": 172, - "AD": 173, - "AE": 174, - "AF": 175, - "B0": 176, - "B1": 177, - "B2": 178, - "B3": 179, - "B4": 180, - "B5": 181, - "B6": 182, - "B7": 183, - "B8": 184, - "B9": 185, - "BA": 186, - "BB": 187, - "BC": 188, - "BD": 189, - "BE": 190, - "BF": 191, - "C0": 192, - "C1": 193, - "C2": 194, - "C3": 195, - "C4": 196, - "C5": 197, - "C6": 198, - "C7": 199, - "C8": 200, - "C9": 201, - "CA": 202, - "CB": 203, - "CC": 204, - "CD": 205, - "CE": 206, - "CF": 207, - "D0": 208, - "D1": 209, - "D2": 210, - "D3": 211, - "D4": 212, - "D5": 213, - "D6": 214, - "D7": 215, - "D8": 216, - "D9": 217, - "DA": 218, - "DB": 219, - "DC": 220, - "DD": 221, - "DE": 222, - "DF": 223, - "E0": 224, - "E1": 225, - "E2": 226, - "E3": 227, - "E4": 228, - "E5": 229, - "E6": 230, - "E7": 231, - "E8": 232, - "E9": 233, - "EA": 234, - "EB": 235, - "EC": 236, - "ED": 237, - "EE": 238, - "EF": 239, - "F0": 240, - "F1": 241, - "F2": 242, - "F3": 243, - "F4": 244, - "F5": 245, - "F6": 246, - "F7": 247, - "F8": 248, - "F9": 249, - "FA": 250, - "FB": 251, - "FC": 252, - "FD": 253, - "FE": 254, - "FF": 255 -}; - -function pad(str, len, pad) { - var result = str; - for (var i = str.length; i < len; i++) { - result = pad + result; - } - return result; -} - -var digitArray = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'); - -function toHex(n) { - var result = '' - var start = true; - for (var i = 32; i > 0;) { - i -= 4; - var digit = (n >> i) & 0xf; - if (!start || digit != 0) { - start = false; - result += digitArray[digit]; - } - } - return (result == '' ? '0': result); -} - - (function($) { - var raphaelPaper; - var raphaelObjs; - var tutorialGuide; - - // I don't like this at all... I intend to make this pull via ajax from a key value data store. - var pages = - [ - //////////////////////////////////////////////////////////////////////// - // Lesson 1 - // Simple addition - { - lesson: 1, - title: 'Basics; numbers, strings, etc.', - guide: - '

                ' + rmsg(['Learning By Numbers', 'Music is Math', 'Back to Basics']) - + '

                ' - + "

                To kick off let's try some maths out. Up there you can" - + " type in Haskell expressions. Try this out: 5 + 7

                " - }, - { - guide: function(result) { - if (!result) result = { - expr: '5+7', - result: 12 - }; - var complied = result.expr.replace(/ /g, '') == "5+7"; - var who = complied ? 'we': 'you'; - return '

                ' + rmsg(['Your first Haskell expression', - "First Time's a Charm"]) + '

                ' - + '

                Well done, you typed it perfect! You got back the number' + - ' ' + result.result + '. Just what ' + who + ' wanted. ' - + "

                Let's try something completely different." + - " Type in your name like this:" + - ' "chris"

                ' - }, - trigger: function(result) { - return result.type == "(Num t) => t" || - result.type == "Integer" || - result.type == "Int"; - } - }, - // Strings & types - { - guide: function(result) { - if (!result) result = { - expr: '"chris"', - result: "\"chris\"" - }; - var n = unString(result.result); - if (n) n = ", " + n; - n += "!"; - return '

                ' + rmsg(['Types of values', "What's in a name?"]) + - '

                ' - + '

                Hi there' + htmlEncode(n) - + (n != "!" ? " That's a pretty name. Honest.": "") - + " You're getting the hang of this!

                " + - "

                Note: You can chat to Haskell programmers while learning here, enter chat to start it." + - " You will join the official IRC channel of the Haskell community!

                " - + "

                Each time, you're getting back the value of the expression. So " + - "far, just a number and a list of characters.

                " + - "

                You can have lists of other stuff, too. Let's see your " + - " lottery numbers: [42,13,22]

                " - }, - trigger: function(result) { - return result.type == "[Char]" - || result.type == "String"; - } - }, - // Overview of lesson 1 - { - guide: function(result) { - if (!result) result = { - result: "[42,13,22]" - }; - return '

                ' + rmsg(["Lesson 1 done already!"]) + - '

                ' + - "

                Great, you made a list of numbers! If you win we'll split" + - " the winnings, right?

                " + - "

                Let's see what you've learned so far:

                " + - "
                  " + - "
                1. How to write maths and lists of things.
                2. " + - "
                " + - "

                You can do stuff with lists. Maybe you want the lottery " + - "numbers sorted in the right order, try this: " + - "sort " + result.result + "

                " - }, - trigger: function(result) { - return result.expr.match(/^[ ]*\[[0-9, ]+\][ ]*$/) && - result.type == "(Num t) => [t]"; - } - }, - /////////////////////////////////////////////////////////////////////// - // Lesson 2 - Functions - // Functions on lists - { - lesson: 2, - title: 'Simple Functions', - guide: function(result) { - if (!result) result = { - result: "[13,23,30]" - }; - return '

                ' + rmsg(["We put the funk in function"]) + - '

                ' + - "

                Congratulations, you just used a function." + - " They're how you get things done in Haskell." + - "

                As you might've guessed, we got back " + - htmlEncode(result.result) - + ".

                Ever wanted an evil twin nemesis? Me too. " + - "Luckily, you can sort lists of characters, or " + - "strings" + - ", in the same way as numbers! sort \"chris\"

                " - }, - trigger: function(result) { - return result.expr.match(/sort/) && - result.type == "(Num t, Ord t) => [t]"; - } - }, - // Tuples - { - guide: function(result) { - if (!result) result = { - result: "\"chirs\"" - }; - nemesis = htmlEncode(unString(result.result)); - return '

                ' + - rmsg(["Tuples, because sometimes one value ain't enough!"]) + - '

                ' + - "

                Watch out for " + nemesis + "! You should keep their credentials for the police.

                " + - "

                My nemesis is 28 years of age: " + - "(28,\"chirs\")

                " - }, - trigger: function(result) { - return result.expr.match(/sort/) && - result.type == "[Char]"; - } - }, - // Functions on tuples - { - guide: function(result) { - if (!result) result = { - result: "(28,\"chirs\")" - }; - var age = result.result.match(/^\(([0-9]+)+/); - var villain = htmlEncode(result.result.replace(/\\"/g, '"')); - return '

                ' + - rmsg(["We'll keep them safe, don't worry about it."]) + - '

                ' + - "

                Is " + (age ? age[1] : "that") + " a normal age for a " + - "super-villain?

                " + - "

                You just wrote a tuple. It's a way to keep a bunch of values together in Haskell. " + - "You can put as many as you like in there:

                " + - "
                • (1,\"hats\",23/35)
                • (\"Shaggy\",\"Daphnie\",\"Velma\")
                " + - "

                Actually, let's say our villain is " + - "" + villain + "" + - ", how do you get their age?

                " + - "fst " + villain + "" - }, - trigger: function(result) { - return result.expr.match(/\([0-9]+,[ ]*"[^"]+"\)/) && - result.type == "(Num t) => (t, [Char])"; - } - }, - // Summary of lesson 2 - { - guide: function(result) { - return '

                ' + - rmsg(["Lesson 2 done! Wow, great job!", - "Lesson 2 completo!"]) + - '

                ' + - - "

                Good job! You got the age back from the tuple! Didn't " + - " even break a sweat, did you? The fst function " + - "just gets the first value. It's called \"fst\" because " + - "it's used a lot in Haskell so it really needs to be short!

                " + - - "

                Time to take a rest and see what you learned:

                " + - "
                  " + - "
                1. Functions can be used on lists of any type.
                2. " + - "
                3. We can stuff values into tuples.
                4. " + - "
                5. Getting the values back from tuples is easy.
                6. " + - "
                " + - - "

                Now let's say you want " + - " to use a value more than once, how would you do it? " + - "To make our lives easier, we can say:

                " + - - "let x = 4 in x * x" - }, - trigger: function(result) { - return result.expr.match(/fst/) && - result.type == "(Num t) => t"; - } - }, - { - guide: function(result) { - return "

                Let them eat cake

                " + - - "

                You just bound a variable. " + - "That is, you bound x to the expression 4, " + - " and then you can write x in some code (the body) and " + - " it will mean the same as if you'd written 4.

                " + - - "

                It's like this: let var = expression in body

                " + - - "The in part just separates the expression from the body.

                " + - - "

                For example try: " + - "let x = 8 * 10 in x + x

                " + - - "

                So if we wanted to get the age of our villain, we could do:

                " + - - "let villain = (28,\"chirs\") in fst villain" - - }, - trigger: function(result) { - return result.expr.match(/^[ ]*let[ ]+x[ ]*=[ ]*[0-9]+[ ]*in[ ]*x[ ]*\*[ ]*x/) && - result.type == "(Num t) => t"; - } - }, - { - guide: function(result) { - return "

                Basics over, let's go!

                " + - "

                Next, let's take a short detour to learn about " + - "syntactic sugar. " + - "Try typing this out:

                " + - "

                'a' : []

                " + - "

                Or skip to lesson4 to learn about functions," + - " the meat of Haskell!"; - }, - trigger: function(result) { - return result.expr.match(/^[ ]*let[ ]+villain[ ]*=[ ]*\([0-9]+,[ ]*"[^"]+"\)[ ]*in[ ]+fst[ ]+villain[ ]*/) && - result.type == "(Num t) => t"; - } - }, - // Lesson 3: Syntactic sugar - { - lesson: 3, - title: 'Syntactic Sugar', - guide: function(result) { - return '

                ' + - rmsg(["You constructed a list!"]) + - '

                ' + - "

                Well done, that was tricky syntax. You used the (:) " + - "function. It takes two values, some value and a list, and " + - " constructs a new list" + - " out of them. We call it 'cons' for short.

                " + - "

                'a' is " + - "the character 'a', [] is an empty list. So " + - "tacking 'a' at the start of an empty list just " + - "makes a list ['a']!

                " + - "

                But thankfully we don't have to type out " + - "'a' : 'b' : [] every time to we want to make a " + - "list of characters; we can use " + - "syntactic sugar and just write" + - " ['a','b']. Don't believe me, check this!

                " + - "'a' : 'b' : [] == ['a','b']" - }, - trigger: function(result) { - return result.expr.match(/^[ ]*'a'[ ]*:[ ]*\[\][ ]*/) && - result.type == "[Char]"; - } - }, - // Booleans and string syntactic sugar - { - guide: function(result) { - return '

                ' + - rmsg(["You're on fire!"]) + - '

                ' + - "

                You're handling this syntax really well, nice!

                " + - "

                You just got a boolean value back, and it said " + - "True. That means they're equal!

                " + - "

                One final demonstration on syntactic sugar for now:

                " + - "['a','b','c'] == \"abc\"" - }, - trigger: function(result) { - return result.type == "Bool" && - result.expr.replace(/[^':\[\]\=,]/g, '') == "'':'':[]==['','']"; - } - }, - // Summary of syntactic sugar section - { - guide: function(result) { - return '

                ' + - rmsg(["Lesson 3 over! Syntactic sugar is sweet"]) + - '

                ' + - "

                Let's have a gander at what you learned:

                " + - "
                  " + - "
                1. In 'a' : [], : is really just " + - " another function, just clever looking.
                2. " + - "
                3. Pretty functions like this are written like (:) when " + - " you talk about them.
                4. " + - "
                5. A list of characters ['a','b'] can just be written " + - "\"ab\". Much easier!
                6. " - + "
                " + - "

                Phew! You're getting pretty deep! Your arch nemesis, " + - nemesis + ", is gonna try to steal your " + rmsg(['mojo', - 'pizza']) + - "! Let's learn a bit more about functions and passing " + - "them around. Try this:

                map (+1) [1..5]

                "; - }, - trigger: function(result) { - return result.expr.replace(/[^\]\[',=\"]?/g, '') == "['','','']==\"\"" && - result.type == "Bool"; - } - }, - { - lesson: 4, - title: 'Functions, reloaded; passing, defining, etc.', - guide: function() { - var title = - rmsg(["Functions [of a Geisha]", - "Functions, functors, functoids, funky", - "Functions: Expanded fo' real"]); - return "

                " + title + "

                " + - - "

                Here's where the magic begins!

                " + - - "

                You just passed the (+1) " + - "function to the map function.

                " + - - "

                You can try other things like (remember: click to insert them):

                " + - - "
                  " + - "
                • map (*99) [1..10]
                • " + - "
                • map (/5) [13,24,52,42]
                • " + - "
                • filter (>5) [62,3,25,7,1,9]
                • " + - "
                " + - - "

                Note that a tuple is different to a list because you can do this:

                " + - "(1,\"George\")" - }, - trigger: function(result) { - return result.expr.match(/^[ ]*map[ ]+\(\+1\)[ ]*\[1..5\][ ]*$/) && - result.type == "(Num a, Enum a) => [a]"; - } - }, - { - guide: function(result) { - return "

                Lists and Tuples

                " + - - "

                You can only " + - " have a list of numbers or a list of characters, whereas in a tuple you can throw anything in!

                " + - - "

                We've also seen that you can make a new list with (:) that joins two values together, like:

                " + - "

                1 : [2,3]

                " + - - "

                But we can't do this with tuples! You can only write a tuple and then look at what's inside. You can't make new ones on the fly like a list." + - - "

                Let's write our own functions! It's really easy. How about something simple:

                " + - "let square x = x * x in square " + rmsg([52, 10, 3]) + "" - - }, - trigger: function(result) { - return result.expr.match(/^[ ]*\(1,"[^"]+"\)[ ]*$/) && - result.type == "(Num t) => (t, [Char])"; - } - }, - { - guide: function(result) { - return "

                Let there be functions

                " + - "

                Nice one! I think you're getting used to the let syntax.

                " + - "

                You defined a function. You can read it as, as for a given " + - "parameter called x, square of " + - "x is x * x." + - "

                Some others you can try are:

                " + - "
                • let add1 x = x + 1 in add1 5
                • " + - "
                • let second x = snd x in second (3,4)
                • " + - "
                " + - "

                Let's go crazy and use our square function with map:

                " + - "let square x = x * x in map square [1..10]" - }, - trigger: function(result) { - return result.expr.match(/^[ ]*let[ ]*square[ ]+x[ ]*=[ ]*x[ ]*\*[ ]*x[ ]*in[ ]*square[ ]+[0-9]+/) && - result.type == "(Num t) => t"; - } - }, - { - guide: function(result) { - if (!result || !result.value) result = { - value: "[1,4,9,16,25,36,49,64,81,100]" - }; - return "

                Let there be functions

                " + - - "

                That's so cool! You described a simple function square and then " + - "you just passed it to another function (map) and got back " + - htmlEncode(result.value) + ", exactly what you expected!

                " + - - "

                Haskell is pretty good at composing things together like this. " + - "Some other things you can try are:

                " + - - "
                  " + - "
                • let add1 x = x + 1 in map add1 [1,5,7]
                • " + - "
                • let take5s = filter (==5) in take5s [1,5,2,5,3,5]
                • " + - "
                • let take5s = filter (==5) in map take5s [[1,5],[5],[1,1]]
                • " + - "
                " + - - "

                Did you get back what you expected?

                " + - - "

                One more example for text; how do you upcase a letter?

                " + - - "

                toUpper 'a'

                " - }, - trigger: function(result) { - return result.expr.match(/^[ ]*let[ ]+square[ ]+x[ ]*=[ ]*x[ ]*\*[ ]*x[ ]*in[ ]+map[ ]+square[ ]*\[1..10\][ ]*$/) && - result.type == "(Num a, Enum a) => [a]"; - } - }, - { - guide: function(result) { - return "

                Exercise time!

                " + - - "

                Easy! Remember: characters are written like 'a' and " + - "strings (lists of characters) are written like \"a\"." + - - "

                I need you to use toUpper capitalise my whole name, " + - "\"Chris\". Give it a try." + - " You can do it, I believe in you!

                " + - - '

                Spoiler: map toUpper "Chris"

                ' - }, - trigger: function(result) { - return result.expr.match(/^toUpper 'a'$/) && - result.type == "Char"; - } - }, - { - guide: function(result) { - return "

                Lesson 4 complete!

                " + - - "

                Brilliant! You're making excellent progress! " + - "You just passed toUpper to map. No problem.

                " + - - "

                Let's go over what you've learned in this lesson:

                " + - - "
                  " + - "
                1. Functions like map take other functions as parameters.
                2. " + - "
                3. Functions like (+1), (>5) and " + - "square can be passed to other functions.
                4. " + - "
                5. Defining functions is just a case of writing what " + - "to do with the parameters.
                6. " + "
                " + - - "

                Let's check out pattern matching; a way to " + - "get values from other values using patterns. Try this:

                " + - "

                let (a,b) = (10,12) in a * 2

                " + - - "

                Or you can skip this section and go to straight to lesson6; types!

                " - }, - trigger: function(result) { - return result.type == "[Char]" && - result.expr.match(/^map[ ]+toUpper/); - } - }, - { - lesson: 5, - title: 'Pattern Matching', - guide: function(result) { - var title = - rmsg(["And therefore, patterns emerge in nature.", - "And Then Patterns", - "Pattern matching!"]) - return "

                " + title + "

                " + - - "

                Jolly good show!

                " + - "

                So you had a value (10,12) and matched " + - "it against a pattern (a,b), then you were able" + - " to do stuff with the a and b!" + - - "

                Note: Pattern matching (a,b) against " + - "(1,2) to get the a is the same as" + - " doing fst (1,2), like you did in step7!

                " + - - "

                A pattern always matches the way the " + - "value was originally constructed. Remember that \"abc\" is " + - "syntactic sugar for 'a' : 'b' : 'c' : [].

                " + - - "

                So you can get the characters from a string with patterns:

                " + - - "let (a:b:c:[]) = \"xyz\" in a" - }, - trigger: function(result) { - return result.expr.match(/^[ ]*let[ ]+\(a,b\)[ ]+=[ ]+\(10,12\)[ ]+in[ ]+a[ ]*\*[ ]*2[ ]*$/) && - result.type == "(Num t) => t"; - } - }, - { - guide: function(result) { - return "

                " + rmsg(["Ignorance is bliss", "Ignoring values"]) + "

                " + - - "

                You're getting into tricky syntax, huh? I know you can handle it!

                " + - - "

                If you just want some of the values, you can ignore the others with _ (underscore) like this:

                " + - - "

                let (a:_:_:_) = \"xyz\" in a

                " + - - "

                In fact, (a:b:c:d) is short-hand for " + - "(a:(b:(c:d))), so you can just ignore the rest in one go:

                " + - - "let (a:_) = \"xyz\" in a" - }, - trigger: function(result) { - return result.expr.match(/^[ ]*let[ ]+\(a:b:c:\[\]\)[ ]*=[ ]*\"xyz\"[ ]*in[ ]+a[ ]*$/) && - result.type == "Char"; - } - }, - { - guide: function(result) { - return "

                " + rmsg(["Exercise!", "Show me the money!"]) + "

                " + - - "

                Try to get the 'a' value from this value using pattern matching:

                " + - "

                (10,\"abc\")

                " + - - "

                Spoiler: let (_,(a:_)) = (10,\"abc\") in a

                " - }, - trigger: function(result) { - return result.expr.match(/^[ ]*let[ ]*\(a:_\)[ ]*=[ ]*"xyz"[ ]*in[ ]*a[ ]*$/) && - result.type == "Char"; - } - }, - { - guide: function(result) { - return "

                " + rmsg(["Well done!", "Brilliant!", "Perfetto!"]) + "

                " + - - "

                Wizard! I think you've got pattern-matching down.

                " + - - "

                If you're still a bit unsure, here are some other things you can try:

                " + - - "
                  " + - "
                • let _:_:c:_ = \"abcd\" in c
                • " + - "
                • let [a,b,c] = \"cat\" in (a,b,c)
                • " + - "
                " + - - "

                You can also grab a whole value and pattern match on it (have your cake and eat it too):

                " + - - "let abc@(a,b,c) = (10,20,30) in (abc,a,b,c)" - }, - trigger: function(result) { - return result.expr.match(/^[ ]*let[ ]*\(_,\(?a:_\)?\)[ ]*=[ ]*\(10,\"abc\"\)[ ]*in[ ]*a[ ]*$/) && - result.type == "Char"; - } - }, - { - guide: function(result) { - return "

                " + rmsg(["And that's the end of that chapter"]) + "

                " + - - "

                That was easy, right?

                " + - - "

                Let's go over what you've learned in this lesson:

                " + - - "
                  " + - "
                1. Values are pattern matched, or deconstructed, by writing however they were constructed.
                2. " + - "
                3. Patterns let you use the values that you match.
                4. " + - "
                5. You can ignore whichever values you want.
                6. " + - "
                7. You can pattern match and keep hold of the original value too.
                8. " + - "
                " + - - "

                Now we get to the Deep Ones. Types!

                " + - - "

                Consider the following value: 'a'

                " - - }, - trigger: function(result) { - return result.type == "(Num t, Num t1, Num t2) => ((t, t1, t2), t, t1, t2)"; - } - }, - { - lesson: 6, - title: 'Types', - guide: function(result) { - showTypes = true; - return "

                " + rmsg(["Types", "What's in a Type?", "Types & Values"]) + "

                " + - "

                What's this? Something new!

                " + - - "

                In Haskell there are types of values. Every value belongs to a type. To demonstrate this fact, I've sneakily enabled types to be " + - "shown of every value in the console from now on.

                " + - - "

                The type of the value 'a' is Char (short for 'character', but you guessed that, right?).

                " + - - "

                You've seen the type of a character, now what about" + - " a list of characters?

                " + - "\"Spartacus\"" - }, - trigger: function(result) { - return result.type == 'Char'; - } - }, - { - guide: function(result) { - showTypes = true; - return "

                " + rmsg(["Lists of stuff, types"]) + "

                " + - - "

                I'm Spartacus!

                " + - - "

                Okay, so a list of characters has type [Char].

                " + - - "

                Notice that when we write a :: X it means the value a has type X. It's just a short-hand called a signature.

                " + - - "

                If you just want the type of a value, without actually evaluating it, you can just type:

                " + - ":t toUpper" - }, - trigger: function(result) { - return result.expr.match(/"[^"]+"/) && - result.type == '[Char]'; - } - }, - { - guide: function(result) { - showTypes = true; - return "

                " + rmsg(["Function types"]) + "

                " + - - "

                Woah! Hold your blinkin' 'orses! The type of toUpper reads: Char -> Char

                " + - - "

                It's pretty easy; a -> b means function from a to b. " + - "So

                toUpper :: Char -> Char means: for a" + - " given character (Char value) a, toUpper a has type Char.

                " + - - "

                Some other things you can try are:

                " + - - "
                • :t words
                • " + - "
                • :t unwords
                • " + - "
                • :t True
                • " + - "
                • :t not
                • " - + "
                " + - - "

                The words function is pretty handy. Want to get a list of words from a sentence?

                " + - "words \"There's jam in my pants.\"" - }, - trigger: function(result) { - return result.type == 'Char -> Char'; - } - }, - { - guide: function(result) { - showTypes = true; - return "

                " + rmsg(["Mid-way review"]) + "

                " + - - "

                The type of words was String -> [String]. You got a list of strings back! Just what you expected, right?

                " + - - "

                Let's take a rest in the middle of this lesson and go over what we've learned:

                " + - - "
                  " + - "
                1. All values in Haskell have a type. We describe the types of values with signatures, like True :: Bool.
                2. " + - "
                3. Functions are values too, and they have types, notated a -> b.
                4. " + - "
                5. Functions can be defined for any type to any other type.
                6. " + - "
                7. Humble reader has a thing for jammy pants.
                8. " + - "
                " + - - "

                But what if you have a type that can contain values of any type, like a tuple?

                " + - ":t fst" - - }, - trigger: function(result) { - return result.expr.match(/^[ ]*words[ ]*\"[^"]+\"[ ]*$/) && - result.type == '[String]'; - } - }, - { - guide: function(result) { - showTypes = true; - return "

                " + rmsg(["Polymorphic functions"]) + "

                " + - - "

                Remember this one? I know you do! fst (1,2) is 1, right?

                " + - "

                We read its type

                " + - "

                fst :: (a, b) -> a

                " + - "

                as: for all types a and b, the fst has type (a,b) to a. So the fst " + - "function works on a pair of values of any types! We call such a function polymorphic." + - "

                " + - "

                Remember the drop function? Maybe you don't. I don't! Let's check out its type:

                " + - "

                :t drop

                " - }, - trigger: function(result) { - return result.type == '(a, b) -> a'; - } - }, - { - guide: function(result) { - showTypes = true; - return "

                " + rmsg(["Multi parameter functions"]) + "

                " + - - "

                So the drop function has type

                Int -> [a] -> [a].

                " + - - "

                This is something new. You've got two arrows! Relax. You can read

                " + - "

                a -> b -> c as a -> (b -> c)

                " + - - "

                In other words, drop is a function from integers (Int values) to functions of lists to lists ([a] -> [a] values). Drop is a function to another function.

                " + - - "

                Check for yourself! :t drop 3

                " - }, - trigger: function(result) { - return result.type == 'Int -> [a] -> [a]'; - } - }, - { - guide: function(result) { - showTypes = true; - return "

                " + rmsg(["Partial application"]) + "

                " + - - "

                You've got a function of type [a] -> [a]! The drop function is considered a multi-parameter function. Remember the map function? Its parameters were a function and a list. Just another multi-parameter function.

                " + - - "

                You can add another parameter and, hey presto, you get a list!

                " + - - "drop 3 \"hello!\"" - - }, - trigger: function(result) { - return result.type == '[a] -> [a]'; - } - }, - { - guide: function(result) { - showTypes = true; - return "

                " + rmsg(["Higher order functions"]) + "

                " + - - "

                'Lo bob! You've already used the map function loads. I wonder if you can guess its type?

                " + - - "

                map :: (a -> b) -> [a] -> [b] (spoiler)

                " + - - "

                It's okay to peek! Have a go at guessing these: filter, take

                " + - - "

                Tip: You can use parantheses to use more than one function. You want to double all the numbers over five? Psch!

                " + - "map (*2) (filter (>5) [10,2,16,9,4])" - }, - trigger: function(result) { - return result.expr.match(/^[ ]*drop[ ]*[0-9]+[ ]*"[^"]+"[ ]*$/) && - result.type == '[Char]'; - } - }, - { - guide: function(result) { - showTypes = true; - return "

                " + rmsg(["Phew! Rest time!"]) + "

                " + - - "

                Wow! You're doing so great! Have a look at what you know now!

                " + - - "
                  " + - "
                1. Function parameters can be polymorphic; any type!
                2. " + - "
                3. Functions can have multiple parameters by returning more functions.
                4. " + - "
                5. You can wrap expressions in parentheses and apply functions to them as a whole value.
                6. " + - "
                " + - - "

                You're really making great progress. Don't hesitate to sit and play in the console between chapters to get a good feel of it!

                " + - - "

                Stay tuned for more chapters on type classes and the meaning of :t 1, :t (*), etc.

                " + - learnMore - }, - trigger: function(result) { - return result.type == '(Num a, Ord a) => [a]'; - } - } - ]; - // - // var webchat; - // - // function runWebchat() { - // if (!webchat) { - // // Create webchat frame - // var webchat = - // $(''); - // webchat.attr('width', 635); - // webchat.attr('height', 500); - // webchat.css('float', 'left'); - // webchat.css('webkit-border-radius', '3px'); - // webchat.css('moz-border-radius', '3px'); - // webchat.css('border-radius', '3px'); - // webchat.css('border', '5px solid #eeeeee'); - // - // // Extend page wrap to fit console and chat - // $('.page-wrap').css({ - // width: '1250px' - // }); - // $('.primary-content').css('margin-left', 0); - // $('.page-wrap').append(webchat.css('margin-left', '5px')); - // } - // } - - var pageTrigger = -1; - var notices = []; - var controller; - // Console controller - var learnMore; - - //////////////////////////////////////////////////////////////////////// - // Unshow a string - function unString(str) { - return str.replace(/^"(.*)"$/, "$1").replace(/\\"/, '"'); - } - - //////////////////////////////////////////////////////////////////////// - // Random message from a list of messages - function rmsg(choices) { - return choices[Math.floor((Math.random() * 100) % choices.length)]; - } - - // Simple HTML encoding - // Simply replace '<', '>' and '&' - // TODO: Use jQuery's .html() trick, or grab a proper, fast - // HTML encoder. - function htmlEncode(text, shy) { - return ( - ('' + text).replace(/&/g, '&') - .replace(/'); - handleJSON = function(r) { - script.remove(); - func(r); - }; - script.attr('src', url); - $('body').append(script); - } - - - var console = $('.console'); - controller = console.console({ - promptLabel: '> ', - continuedPromptLabel: ' .. ', /*not quiet right but good enough*/ - cancelHandle: function() { - controller.commandRef.ignore = true; - controller.finishCommand(); - controller.report(); - }, - - commandHandle: function(line, report) { - - controller.ajaxloader = $('

                Loading...

                '); - var commandRef = {}; - controller.currentLine = line; - controller.commandRef = commandRef; - controller.report = report; - if (tellAboutRet) tellAboutRet.fadeOut(function() { - $(this).remove(); - }); - - if (libTrigger(line, report)) return; - controller.inner.append(controller.ajaxloader); - controller.scrollToBottom(); - - jsonp("http://localhost:3030/tryruby/run/?cmd=" + encodeHex(line), - function(resp) { - if (commandRef.ignore) { - return; - } - controller.finishCommand(); - var result = resp; - if (pageTrigger > -1 && result.expr) { - triggerTutorialPage(pageTrigger, result); - } - if (result.type) { - if (pageTrigger == 24) showTypes = false; - handleSuccess(report, result); - } else if (result.error) { - report( - [{ - msg: result.error, - className: "jquery-console-message-error jquery-console-message-compile-error" - }] - ); - notice('compile-error', - "A compile-time error! " + - "It just means the expression wasn't quite right. " + - "Try again.", - 'prompt'); - } else if (result.exception) { - var err = limitsError(result.exception); - report( - [{ - msg: err, - className: "jquery-console-message-error jquery-console-message-exception" - }] - ); - if (err == result.exception) { - notice('compile-error', - "A run-time error! The expression was right but the" + - " result didn't make sense. Check your expression and try again.", - 'prompt'); - } - } else if (result.internal) { - report( - [{ - msg: limitsError(result.internal), - className: "jquery-console-message-error jquery-console-message-internal" - }] - ); - } else if (result.bind) { - report(); - } else if (result.result) { - if (result.expr.match(/^:modules/)) { - report( - [{ - msg: result.result.replace(/[\["\]]/g, '') - .replace(/,/g, ', '), - className: "jquery-console-message-type" - }]); - } - } - }); - - }, - - charInsertTrigger: function() { - var t = notice('tellaboutreturn', - "Hit Return when you're " + - "finished typing your expression."); - if (t) tellAboutRet = t; - return true; - }, - autofocus: true, - promptHistory: true, - historyPreserveColumn: true, - welcomeMessage: 'Interactive ruby ready' - }); - - controller.finishCommand = function() { - controller.ajaxloader.remove(); - $('.jquery-console-prompt :last').each(function() { - lastLine = controller.currentLine; - if (!$(this).hasClass('prompt-done')) { - $(this).addClass('prompt-done'); - $(this).click(function() { - controller.promptText(controller.currentLine); - }); - } - }); - } - - makeGuidSamplesClickable(); - - var match = window.location.href.match(/#([0-9]+)$/); - if (match) { - pageTrigger = match[1] - 1; - setTutorialPage(undefined, match[1] - 1); - } - - var match = window.location.href.match(/\?input=([^&]+)/); - if (match) { - controller.promptText(urlDecode(match[1])); - controller.inner.click(); - controller.typer.consoleControl(13); - } - }); - - function urlDecode(encodedString) { - var output = encodedString; - var binVal, - thisString; - var myregexp = /(%[^%]{2})/; - while ((match = myregexp.exec(output)) != null - && match.length > 1 - && match[1] != '') { - binVal = parseInt(match[1].substr(1), 16); - thisString = String.fromCharCode(binVal); - output = output.replace(match[1], thisString); - } - return output; - } - - function makeGuidSamplesClickable() { - $('.chapmark code').each(function() { - $(this).css('cursor', 'pointer'); - $(this).attr('title', 'Click me to insert "' + - $(this).text() + '" into the console.'); - $(this).click(function() { - controller.promptText($(this).text()); - controller.inner.click(); - }); - }); - } - - String.prototype.trim = function() { - return this.replace(/^[\t ]*(.*)[\t ]*$/, '$1'); - }; - - //////////////////////////////////////////////////////////////////////// - // Trigger console commands - function libTrigger(line, report) { - switch (line.trim()) { - case 'help': - { - setTutorialPage(undefined, 0); - report(); - pageTrigger = 0; - return true; - } - case 'back': - { - if (pageTrigger > 0) { - setTutorialPage(undefined, pageTrigger - 1); - pageTrigger--; - report(); - return true; - } - break; - } - case 'lessons': - { - var lessons = $('
                  '); - for (var i = 0; i < pages.length; i++) { - if (pages[i].lesson) { - lessons.append($('
                1. '). - html('lesson' + pages[i].lesson + ' - ' + - pages[i].title)); - } - } - var lessonsList = '

                  Lessons

                  ' + lessons.html(); - tutorialGuide.animate({ - opacity: 0, - height: 0 - }, - 'fast', - function() { - tutorialGuide.html(lessonsList); - tutorialGuide.css({ - height: 'auto' - }); - tutorialGuide.animate({ - opacity: 1 - }, - 'fast'); - makeGuidSamplesClickable(); - }); - report(); - return true; - } - default: - { - if (line.trim() == 'chat') { - notice('irc', - 'Enter your nick on the right hand side and hit Connect!', - 'prompt'); - report(); - runWebchat(); - return true; - } - - var m = line.trim().match(/^link(.*)/); - if (m) { - var data; - if (m[1]) data = m[1].trim(); - else if (lastLine) data = lastLine; - if (data) { - var addr = '?input=' + encodeHex(data); - report([{ - msg: '', - className: 'latest-link' - }]); - var link = $(''). - text('link for ' + data).click(function() { - window.location.href = $(this).attr('href'); - return false; - }); - $('.latest-link').html(link).removeClass('latest-link'); - return true; - } - } - - var m = line.trim().match(/^step([0-9]+)/); - if (m) { - if ((m[1] * 1) <= pages.length) { - setTutorialPage(undefined, m[1] - 1); - report(); - pageTrigger = m[1] - 1; - return true; - } - } - var m = line.trim().match(/^help ([0-9]+)/); - if (m) { - for (var i = 0; i < pages.length; i++) { - if (pages[i].lesson == m[1] * 1) { - setTutorialPage(undefined, i); - report(); - pageTrigger = i; - return true; - } - } - } - } - }; - }; - - //////////////////////////////////////////////////////////////////////// - // Change the tutorial page - function setTutorialPage(result, n) { - if (pages[n]) { - window.location.href = '#' + (1 * n + 1); - tutorialGuide.find('#helpstone').remove(); - tutorialGuide.animate({ - opacity: 0, - height: 0 - }, - 'fast', - function() { - if (typeof(pages[n].guide) == 'function') - tutorialGuide.html(pages[n].guide(result)); - else - tutorialGuide.html(pages[n].guide); - var back = ''; - if (pageTrigger > 0) - back = 'You\'re at step' + (n + 1) - + '. Type back to go back.'; - else - back = 'You\'re at step' + (n + 1) + '. Type step' + (n + 1) - + ' to return here.'; - if (true) tutorialGuide - .append('
                  ' + back + '
                  ') - .append('
                  Lesson: ' + - searchLessonBack(n) + - '
                  '); - tutorialGuide.css({ - height: 'auto' - }); - tutorialGuide.animate({ - opacity: 1 - }, - 'fast'); - makeGuidSamplesClickable(); - }); - } - }; - - function searchLessonBack(page) { - for (var i = page; i >= 0; i--) { - if (pages[i].lesson) return pages[i].lesson; - } - return "1"; - } - - //////////////////////////////////////////////////////////////////////// - // Trigger a page according to a result - function triggerTutorialPage(n, result) { - n++; - if (pages[n] && (typeof(pages[n].trigger) == 'function') - && pages[n].trigger(result)) { - pageTrigger++; - setTutorialPage(result, n); - } - }; - - //////////////////////////////////////////////////////////////////////// - // Trigger various libraries after JSONRPC returned - function handleSuccess(report, result) { - if (result.type.match(/^Graphics\.Raphael\.Raphael[\r\n ]/)) { - runRaphael(result.result); - report(); - } - if (result.type.match(/standard/)) { - var hashrocket = ''; - var msg_value = ' => '; - if (result.result == null) { - hashrocket = ' => ' - msg_value = ''; - } - report( - [{ - msg: msg_value + result.output + hashrocket + result.result, - className: "jquery-console-message-value" - }]); - } - - if (result.type.match(/error/)) { - - report( - [{ - msg: result.error, - className: "jquery-console-message-value" - }]); - } - - if (result.type.match(/illegal/)) { - - report( - [{ - msg: 'You are not allowed to run that command!', - className: "jquery-console-message-value" - }]); - } - - - if (result.type.match(/line_continuation/)) { - report( - [{ - msg: '..', - className: "jquery-console-prompt-label" - }]); - } - - }; - - //////////////////////////////////////////////////////////////////////// - // Raphael support - function runRaphael(expr) { - raphaelPaper.clear(); - $('#raphael').parent().parent().slideDown(function() { - var exprs = expr.split(/\n/g); - for (var i = 0; i < exprs.length; i++) - raphaelRunExpr(exprs[i]); - }); - } - function raphaelRunExpr(expr) { - var expr = expr.split(/ /g); - switch (expr[0]) { - case 'new': - { - switch (expr[2]) { - case 'circle': - { - var x = expr[3], - y = expr[4], - radius = expr[5]; - var circle = raphaelPaper.circle(x * 1, y * 1, radius * 1); - circle.attr("fill", "#7360a4"); - break; - } - } - } - } - } - - function notice(name, msg, style) { - if (opera()) return; - if (!notices[name]) { - notices[name] = name; - return controller.notice(msg, style); - } - } - - function limitsError(str) { - if (str == "Terminated!") { - notice('terminated', - "This error means it took to long to work" + - " out on the server.", - 'fadeout'); - return "Terminated!"; - } else if (str == "Time limit exceeded.") { - notice('exceeded', - "This error means it took to long to work out on the server. " + - "Try again.", - 'fadeout'); - return "Terminated! Try again."; - } - return str; - } - -})(jQuery); diff --git a/non-rack-legacy/public/javascripts/jquery-1.3.2.min.js b/non-rack-legacy/public/javascripts/jquery-1.3.2.min.js deleted file mode 100644 index b1ae21d..0000000 --- a/non-rack-legacy/public/javascripts/jquery-1.3.2.min.js +++ /dev/null @@ -1,19 +0,0 @@ -/* - * jQuery JavaScript Library v1.3.2 - * http://jquery.com/ - * - * Copyright (c) 2009 John Resig - * Dual licensed under the MIT and GPL licenses. - * http://docs.jquery.com/License - * - * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) - * Revision: 6246 - */ -(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("",""]||!O.indexOf("",""]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
                  "]||!O.indexOf("",""]||(!O.indexOf("",""]||!O.indexOf("",""]||!o.support.htmlSerialize&&[1,"div
                  ","
                  "]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}}); -/* - * Sizzle CSS Selector Engine - v0.9.3 - * Copyright 2009, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * More information: http://sizzlejs.com/ - */ -(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return UT[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="

                  ";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="
                  ";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("
                  ").append(M.responseText.replace(//g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='
                  ';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})(); \ No newline at end of file diff --git a/non-rack-legacy/public/javascripts/jquery-1.4.2.min.js b/non-rack-legacy/public/javascripts/jquery-1.4.2.min.js deleted file mode 100644 index 7c24308..0000000 --- a/non-rack-legacy/public/javascripts/jquery-1.4.2.min.js +++ /dev/null @@ -1,154 +0,0 @@ -/*! - * jQuery JavaScript Library v1.4.2 - * http://jquery.com/ - * - * Copyright 2010, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2010, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Sat Feb 13 22:33:48 2010 -0500 - */ -(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, -Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& -(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, -a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== -"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, -function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
                  a"; -var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, -parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= -false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= -s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, -applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; -else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, -a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== -w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, -cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= -c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); -a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, -function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); -k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), -C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B=0){a.type= -e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& -f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; -if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", -e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, -"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, -d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, -e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); -t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| -g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, -CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, -g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, -text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, -setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= -h[3];l=0;for(m=h.length;l=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== -"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, -h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& -q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; -if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="

                  ";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); -(function(){var g=s.createElement("div");g.innerHTML="
                  ";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: -function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var j=d;j0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= -{},i;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== -"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", -d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? -a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== -1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"},F={option:[1,""],legend:[1,"
                  ","
                  "],thead:[1,"","
                  "],tr:[2,"","
                  "],td:[3,"","
                  "],col:[2,"","
                  "],area:[1,"",""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
                  ","
                  "];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= -c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, -wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, -prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, -this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); -return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, -""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); -return this}else{e=0;for(var j=d.length;e0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", -""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===""&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= -c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? -c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= -function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= -Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, -"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= -a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= -a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=//gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!== -"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("
                  ").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this}, -serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), -function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href, -global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&& -e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)? -"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache=== -false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B= -false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since", -c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E|| -d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x); -g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status=== -1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b=== -"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional; -if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration=== -"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]|| -c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start; -this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now= -this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem, -e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b
                  "; -a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b); -c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a, -d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top- -f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset": -"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in -e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window); diff --git a/non-rack-legacy/public/javascripts/jquery.console.js b/non-rack-legacy/public/javascripts/jquery.console.js deleted file mode 100644 index d45390d..0000000 --- a/non-rack-legacy/public/javascripts/jquery.console.js +++ /dev/null @@ -1,609 +0,0 @@ -// JQuery Console 1.0 -// Sun Feb 21 20:28:47 GMT 2010 -// -// Copyright 2010 Chris Done, Simon David Pratt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// 1. Redistributions of source code must retain the above -// copyright notice, this list of conditions and the following -// disclaimer. -// -// 2. Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// TESTED ON -// Internet Explorer 6 -// Opera 10.01 -// Chromium 4.0.237.0 (Ubuntu build 31094) -// Firefox 3.5.8, 3.6.2 (Mac) -// Safari 4.0.5 (6531.22.7) (Mac) -// Google Chrome 5.0.375.55 (Mac) - -(function($){ - $.fn.console = function(config){ - //////////////////////////////////////////////////////////////////////// - // Constants - // Some are enums, data types, others just for optimisation - var keyCodes = { - // left - 37: moveBackward, - // right - 39: moveForward, - // up - 38: previousHistory, - // down - 40: nextHistory, - // backspace - 8: backDelete, - // delete - 46: forwardDelete, - // end - 35: moveToEnd, - // start - 36: moveToStart, - // return - 13: commandTrigger, - // tab - 18: doNothing - }; - var ctrlCodes = { - // C-a - 65: moveToStart, - // C-e - 69: moveToEnd, - // C-d - 68: forwardDelete, - // C-n - 78: nextHistory, - // C-p - 80: previousHistory, - // C-b - 66: moveBackward, - // C-f - 70: moveForward, - // C-k - 75: deleteUntilEnd - }; - var altCodes = { - // M-f - 70: moveToNextWord, - // M-b - 66: moveToPreviousWord, - // M-d - 68: deleteNextWord - }; - var cursor = ' '; - // Opera only works with this character, not or ­, - // but IE6 displays this character, which is bad, so just use - // it on Opera. - var wbr = $.browser.opera? '​' : ''; - - //////////////////////////////////////////////////////////////////////// - // Globals - var container = $(this); - var inner = $('
                  '); - var typer = $(''); - // Prompt - var promptBox; - var prompt; - var promptLabel = config && config.promptLabel? config.promptLabel : "> "; - var column = 0; - var promptText = ''; - var restoreText = ''; - // Prompt history stack - var history = []; - var ringn = 0; - // For reasons unknown to The Sword of Michael himself, Opera - // triggers and sends a key character when you hit various - // keys like PgUp, End, etc. So there is no way of knowing - // when a user has typed '#' or End. My solution is in the - // typer.keydown and typer.keypress functions; I use the - // variable below to ignore the keypress event if the keydown - // event succeeds. - var cancelKeyPress = 0; - // When this value is false, the prompt will not respond to input - var acceptInput = true; - // When this value is true, the command has been canceled - var cancelCommand = false; - - // External exports object - var extern = {}; - - //////////////////////////////////////////////////////////////////////// - // Main entry point - (function(){ - container.append(inner); - inner.append(typer); - typer.css({position:'absolute',top:0,left:'-9999px'}); - if (config.welcomeMessage) - message(config.welcomeMessage,'jquery-console-welcome'); - newPromptBox(); - if (config.autofocus) { - inner.addClass('jquery-console-focus'); - typer.focus(); - setTimeout(function(){ - inner.addClass('jquery-console-focus'); - typer.focus(); - },100); - } - extern.inner = inner; - extern.typer = typer; - extern.scrollToBottom = scrollToBottom; - })(); - - //////////////////////////////////////////////////////////////////////// - // Reset terminal - extern.reset = function(){ - var welcome = true; - inner.parent().fadeOut(function(){ - inner.find('div').each(function(){ - if (!welcome) - $(this).remove(); - welcome = false; - }); - newPromptBox(); - inner.parent().fadeIn(function(){ - inner.addClass('jquery-console-focus'); - typer.focus(); - }); - }); - }; - - //////////////////////////////////////////////////////////////////////// - // Reset terminal - extern.notice = function(msg,style){ - var n = $('
                  ').append($('
                  ').text(msg)) - .css({visibility:'hidden'}); - container.append(n); - var focused = true; - if (style=='fadeout') - setTimeout(function(){ - n.fadeOut(function(){ - n.remove(); - }); - },4000); - else if (style=='prompt') { - var a = $('
                  '); - n.append(a); - focused = false; - a.click(function(){ n.fadeOut(function(){ n.remove();inner.css({opacity:1}) }); }); - } - var h = n.height(); - n.css({height:'0px',visibility:'visible'}) - .animate({height:h+'px'},function(){ - if (!focused) inner.css({opacity:0.5}); - }); - n.css('cursor','default'); - return n; - }; - - //////////////////////////////////////////////////////////////////////// - // Make a new prompt box - function newPromptBox() { - column = 0; - promptText = ''; - ringn = 0; // Reset the position of the history ring - enableInput(); - promptBox = $('
                  '); - var label = $(''); - promptBox.append(label.text(promptLabel).show()); - prompt = $(''); - promptBox.append(prompt); - inner.append(promptBox); - updatePromptDisplay(); - }; - - //////////////////////////////////////////////////////////////////////// - // Handle setting focus - container.click(function(){ - inner.addClass('jquery-console-focus'); - inner.removeClass('jquery-console-nofocus'); - typer.focus(); - scrollToBottom(); - return false; - }); - - //////////////////////////////////////////////////////////////////////// - // Handle losing focus - typer.blur(function(){ - inner.removeClass('jquery-console-focus'); - inner.addClass('jquery-console-nofocus'); - }); - - //////////////////////////////////////////////////////////////////////// - // Handle key hit before translation - // For picking up control characters like up/left/down/right - - typer.keydown(function(e){ - cancelKeyPress = 0; - var keyCode = e.keyCode; - // C-c: cancel the execution - if(e.ctrlKey && keyCode == 67) { - cancelKeyPress = keyCode; - cancelExecution(); - return false; - } - if (acceptInput) { - if (keyCode in keyCodes) { - cancelKeyPress = keyCode; - (keyCodes[keyCode])(); - return false; - } else if (e.ctrlKey && keyCode in ctrlCodes) { - cancelKeyPress = keyCode; - (ctrlCodes[keyCode])(); - return false; - } else if (e.altKey && keyCode in altCodes) { - cancelKeyPress = keyCode; - (altCodes[keyCode])(); - return false; - } - } - }); - - //////////////////////////////////////////////////////////////////////// - // Handle key press - typer.keypress(function(e){ - var keyCode = e.keyCode || e.which; - if (isIgnorableKey(e)) { - return false; - } - if (acceptInput && cancelKeyPress != keyCode && keyCode >= 32){ - if (cancelKeyPress) return false; - if (typeof config.charInsertTrigger == 'undefined' || - (typeof config.charInsertTrigger == 'function' && - config.charInsertTrigger(keyCode,promptText))) - typer.consoleInsert(keyCode); - } - if ($.browser.webkit) return false; - }); - - function isIgnorableKey(e) { - // for now just filter alt+tab that we receive on some platforms when - // user switches windows (goes away from the browser) - return ((e.keyCode == keyCodes.tab || e.keyCode == 192) && e.altKey); - }; - - //////////////////////////////////////////////////////////////////////// - // Rotate through the command history - function rotateHistory(n){ - if (history.length == 0) return; - ringn += n; - if (ringn < 0) ringn = history.length; - else if (ringn > history.length) ringn = 0; - var prevText = promptText; - if (ringn == 0) { - promptText = restoreText; - } else { - promptText = history[ringn - 1]; - } - if (config.historyPreserveColumn) { - if (promptText.length < column + 1) { - column = promptText.length; - } else if (column == 0) { - column = promptText.length; - } - } else if (config.historyColumnAtEnd) { - column = promptText.length; - } else { - column = 0; - } - updatePromptDisplay(); - }; - - function previousHistory() { - rotateHistory(-1); - }; - - function nextHistory() { - rotateHistory(1); - }; - - // Add something to the history ring - function addToHistory(line){ - history.push(line); - restoreText = ''; - }; - - // Delete the character at the current position - function deleteCharAtPos(){ - if (column < promptText.length){ - promptText = - promptText.substring(0,column) + - promptText.substring(column+1); - restoreText = promptText; - return true; - } else return false; - }; - - function backDelete() { - if (moveColumn(-1)){ - deleteCharAtPos(); - updatePromptDisplay(); - } - }; - - function forwardDelete() { - if (deleteCharAtPos()) - updatePromptDisplay(); - }; - - function deleteUntilEnd() { - while(deleteCharAtPos()) { - updatePromptDisplay(); - } - }; - - function deleteNextWord() { - // A word is defined within this context as a series of alphanumeric - // characters. - // Delete up to the next alphanumeric character - while(column < promptText.length && - !isCharAlphanumeric(promptText[column])) { - deleteCharAtPos(); - updatePromptDisplay(); - } - // Then, delete until the next non-alphanumeric character - while(column < promptText.length && - isCharAlphanumeric(promptText[column])) { - deleteCharAtPos(); - updatePromptDisplay(); - } - }; - - //////////////////////////////////////////////////////////////////////// - // Validate command and trigger it if valid, or show a validation error - function commandTrigger() { - var line = promptText; - if (typeof config.commandValidate == 'function') { - var ret = config.commandValidate(line); - if (ret == true || ret == false) { - if (ret) { - handleCommand(); - } - } else { - commandResult(ret,"jquery-console-message-error"); - } - } else { - handleCommand(); - } - }; - - // Scroll to the bottom of the view - function scrollToBottom() { - inner.attr({ scrollTop: inner.attr("scrollHeight") });; - }; - - function cancelExecution() { - if(typeof config.cancelHandle == 'function') { - config.cancelHandle(); - } - } - - //////////////////////////////////////////////////////////////////////// - // Handle a command - function handleCommand() { - if (typeof config.commandHandle == 'function') { - disableInput(); - addToHistory(promptText); - var ret = config.commandHandle(promptText,function(msgs){ - commandResult(msgs); - }); - if (typeof ret == 'boolean') { - if (ret) { - // Command succeeded without a result. - commandResult(); - } else { - commandResult('Command failed.', - "jquery-console-message-error"); - } - } else if (typeof ret == "string") { - commandResult(ret,"jquery-console-message-success"); - } else if (typeof ret == 'object' && ret.length) { - commandResult(ret); - } - } - }; - - //////////////////////////////////////////////////////////////////////// - // Disable input - function disableInput() { - acceptInput = false; - }; - - // Enable input - function enableInput() { - acceptInput = true; - } - - //////////////////////////////////////////////////////////////////////// - // Reset the prompt in invalid command - function commandResult(msg,className) { - column = -1; - updatePromptDisplay(); - if (typeof msg == 'string') { - message(msg,className); - } else { - for (var x in msg) { - var ret = msg[x]; - message(ret.msg,ret.className); - } - } - newPromptBox(); - }; - - //////////////////////////////////////////////////////////////////////// - // Display a message - function message(msg,className) { - var mesg = $('
                  '); - if (className) mesg.addClass(className); - mesg.filledText(msg).hide(); - inner.append(mesg); - mesg.show(); - }; - - //////////////////////////////////////////////////////////////////////// - // Handle normal character insertion - typer.consoleInsert = function(keyCode){ - // TODO: remove redundant indirection - var char = String.fromCharCode(keyCode); - var before = promptText.substring(0,column); - var after = promptText.substring(column); - promptText = before + char + after; - moveColumn(1); - restoreText = promptText; - updatePromptDisplay(); - }; - - //////////////////////////////////////////////////////////////////////// - // Move to another column relative to this one - // Negative means go back, positive means go forward. - function moveColumn(n){ - if (column + n >= 0 && column + n <= promptText.length){ - column += n; - return true; - } else return false; - }; - - function moveForward() { - if(moveColumn(1)) { - updatePromptDisplay(); - return true; - } - return false; - }; - - function moveBackward() { - if(moveColumn(-1)) { - updatePromptDisplay(); - return true; - } - return false; - }; - - function moveToStart() { - if (moveColumn(-column)) - updatePromptDisplay(); - }; - - function moveToEnd() { - if (moveColumn(promptText.length-column)) - updatePromptDisplay(); - }; - - function moveToNextWord() { - while(column < promptText.length && - !isCharAlphanumeric(promptText[column]) && - moveForward()) { - } - while(column < promptText.length && - isCharAlphanumeric(promptText[column]) && - moveForward()) { - } - }; - - function moveToPreviousWord() { - // Move backward until we find the first alphanumeric - while(column -1 >= 0 && - !isCharAlphanumeric(promptText[column-1]) && - moveBackward()) { - } - // Move until we find the first non-alphanumeric - while(column -1 >= 0 && - isCharAlphanumeric(promptText[column-1]) && - moveBackward()) { - } - }; - - function isCharAlphanumeric(charToTest) { - if(typeof charToTest == 'string') { - var code = charToTest.charCodeAt(); - return (code >= 'A'.charCodeAt() && code <= 'Z'.charCodeAt()) || - (code >= 'a'.charCodeAt() && code <= 'z'.charCodeAt()) || - (code >= '0'.charCodeAt() && code <= '9'.charCodeAt()); - } - return false; - }; - - function doNothing() {}; - - extern.promptText = function(text){ - if (text) { - promptText = text; - if (column > promptText.length) - column = promptText.length; - updatePromptDisplay(); - } - return promptText; - }; - - //////////////////////////////////////////////////////////////////////// - // Update the prompt display - function updatePromptDisplay(){ - var line = promptText; - var html = ''; - if (column > 0 && line == ''){ - // When we have an empty line just display a cursor. - html = cursor; - } else if (column == promptText.length){ - // We're at the end of the line, so we need to display - // the text *and* cursor. - html = htmlEncode(line) + cursor; - } else { - // Grab the current character, if there is one, and - // make it the current cursor. - var before = line.substring(0, column); - var current = line.substring(column,column+1); - if (current){ - current = - '' + - htmlEncode(current) + - ''; - } - var after = line.substring(column+1); - html = htmlEncode(before) + current + htmlEncode(after); - } - prompt.html(html); - scrollToBottom(); - }; - - // Simple HTML encoding - // Simply replace '<', '>' and '&' - // TODO: Use jQuery's .html() trick, or grab a proper, fast - // HTML encoder. - function htmlEncode(text){ - return ( - text.replace(/&/g,'&') - .replace(/&]{10})/g,'$1­' + wbr) - ); - }; - - return extern; - }; - // Simple utility for printing messages - $.fn.filledText = function(txt){ - $(this).text(txt); - $(this).html($(this).html().replace(/\n/g,'
                  ')); - return this; - }; -})(jQuery); diff --git a/non-rack-legacy/public/javascripts/jquery.console.min.js b/non-rack-legacy/public/javascripts/jquery.console.min.js deleted file mode 100644 index 7ae1e6b..0000000 --- a/non-rack-legacy/public/javascripts/jquery.console.min.js +++ /dev/null @@ -1 +0,0 @@ -(function($){$.fn.console=function(config){var keyCodes={left:37,right:39,up:38,down:40,back:8,del:46,end:35,start:36,ret:13};var cursor=' ';var wbr=$.browser.opera?'​':'';var container=$(this);var inner=$('
                  ');var typer=$('');var promptBox;var prompt;var promptLabel=config&&config.promptLabel?config.promptLabel:"> ";var column=0;var promptText='';var restoreText='';var history=[];var ringn=0;var cancelKeyPress=0;var extern={};(function(){container.append(inner);inner.append(typer);typer.css({position:'absolute',top:0,left:'-999px'});if(config.welcomeMessage)message(config.welcomeMessage,'jquery-console-welcome');newPromptBox();if(config.autofocus){inner.addClass('jquery-console-focus');typer.focus();setTimeout(function(){inner.addClass('jquery-console-focus');typer.focus()},100)}})();extern.reset=function(){var welcome=true;inner.parent().fadeOut(function(){inner.find('div').each(function(){if(!welcome)$(this).remove();welcome=false});newPromptBox();inner.parent().fadeIn(function(){inner.addClass('jquery-console-focus');typer.focus()})})};function newPromptBox(){column=0;promptText='';promptBox=$('
                  ');var label=$('');promptBox.append(label.text(promptLabel).show());prompt=$('');promptBox.append(prompt);inner.append(promptBox);updatePromptDisplay()};container.click(function(){inner.addClass('jquery-console-focus');inner.removeClass('jquery-console-nofocus');typer.focus();scrollToBottom();return false});typer.blur(function(){inner.removeClass('jquery-console-focus');inner.addClass('jquery-console-nofocus')});typer.keydown(function(e){cancelKeyPress=0;var keyCode=e.keyCode;if(isControlCharacter(keyCode)){cancelKeyPress=keyCode;if(!typer.consoleControl(keyCode)){return false}}});typer.keypress(function(e){var keyCode=e.keyCode||e.which;if(cancelKeyPress!=keyCode&&keyCode>=32){if(cancelKeyPress)return false;typer.consoleInsert(keyCode)}if($.browser.webkit)return false});function isControlCharacter(keyCode){return((keyCode>=keyCodes.left&&keyCode<=keyCodes.down)||keyCode==keyCodes.back||keyCode==keyCodes.del||keyCode==keyCodes.end||keyCode==keyCodes.start||keyCode==keyCodes.ret)};typer.consoleControl=function(keyCode){switch(keyCode){case keyCodes.left:{moveColumn(-1);updatePromptDisplay();return false;break}case keyCodes.right:{moveColumn(1);updatePromptDisplay();return false;break}case keyCodes.back:{if(moveColumn(-1)){deleteCharAtPos();updatePromptDisplay()}return false;break}case keyCodes.del:{if(deleteCharAtPos())updatePromptDisplay();return false;break}case keyCodes.end:{if(moveColumn(promptText.length-column))updatePromptDisplay();return false;break}case keyCodes.start:{if(moveColumn(-column))updatePromptDisplay();return false;break}case keyCodes.ret:{commandTrigger();return false}case keyCodes.up:{rotateHistory(-1);return false}case keyCodes.down:{rotateHistory(1);return false}default:}};function rotateHistory(n){if(history.length==0)return;ringn+=n;if(ringn<0)ringn=history.length;else if(ringn>history.length)ringn=0;var prevText=promptText;if(ringn==0){promptText=restoreText}else{promptText=history[ringn-1]}if(config.historyPreserveColumn){if(promptText.length
                  ');if(className)mesg.addClass(className);mesg.filledText(msg).hide();inner.append(mesg);mesg.show()};typer.consoleInsert=function(keyCode){var char=String.fromCharCode(keyCode);var before=promptText.substring(0,column);var after=promptText.substring(column);promptText=before+char+after;moveColumn(1);restoreText=promptText;updatePromptDisplay()};function moveColumn(n){if(column+n>=0&&column+n<=promptText.length){column+=n;return true}else return false};function updatePromptDisplay(){var line=promptText;var html='';if(column>0&&line==''){html=cursor}else if(column==promptText.length){html=htmlEncode(line)+cursor}else{var before=line.substring(0,column);var current=line.substring(column,column+1);if(current){current=''+htmlEncode(current)+''}var after=line.substring(column+1);html=htmlEncode(before)+current+htmlEncode(after)}prompt.html(html);scrollToBottom()};function htmlEncode(text){return(text.replace(/&/g,'&').replace(/&]{10})/g,'$1­'+wbr))};return extern};$.fn.filledText=function(txt){$(this).text(txt);$(this).html($(this).html().replace(/\n/g,'
                  '));return this}})(jQuery); \ No newline at end of file diff --git a/non-rack-legacy/public/javascripts/jquery.js b/non-rack-legacy/public/javascripts/jquery.js deleted file mode 100755 index 3747929..0000000 --- a/non-rack-legacy/public/javascripts/jquery.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * jQuery 1.2.3 - New Wave Javascript - * - * Copyright (c) 2008 John Resig (jquery.com) - * Dual licensed under the MIT (MIT-LICENSE.txt) - * and GPL (GPL-LICENSE.txt) licenses. - * - * $Date: 2008-02-06 00:21:25 -0500 (Wed, 06 Feb 2008) $ - * $Rev: 4663 $ - */ -(function(){if(window.jQuery)var _jQuery=window.jQuery;var jQuery=window.jQuery=function(selector,context){return new jQuery.prototype.init(selector,context);};if(window.$)var _$=window.$;window.$=jQuery;var quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;var isSimple=/^.[^:#\[\.]*$/;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;return this;}else if(typeof selector=="string"){var match=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1])selector=jQuery.clean([match[1]],context);else{var elem=document.getElementById(match[3]);if(elem)if(elem.id!=match[3])return jQuery().find(selector);else{this[0]=elem;this.length=1;return this;}else -selector=[];}}else -return new jQuery(context).find(selector);}else if(jQuery.isFunction(selector))return new jQuery(document)[jQuery.fn.ready?"ready":"load"](selector);return this.setArray(selector.constructor==Array&&selector||(selector.jquery||selector.length&&selector!=window&&!selector.nodeType&&selector[0]!=undefined&&selector[0].nodeType)&&jQuery.makeArray(selector)||[selector]);},jquery:"1.2.3",size:function(){return this.length;},length:0,get:function(num){return num==undefined?jQuery.makeArray(this):this[num];},pushStack:function(elems){var ret=jQuery(elems);ret.prevObject=this;return ret;},setArray:function(elems){this.length=0;Array.prototype.push.apply(this,elems);return this;},each:function(callback,args){return jQuery.each(this,callback,args);},index:function(elem){var ret=-1;this.each(function(i){if(this==elem)ret=i;});return ret;},attr:function(name,value,type){var options=name;if(name.constructor==String)if(value==undefined)return this.length&&jQuery[type||"attr"](this[0],name)||undefined;else{options={};options[name]=value;}return this.each(function(i){for(name in options)jQuery.attr(type?this.style:this,name,jQuery.prop(this,options[name],type,i,name));});},css:function(key,value){if((key=='width'||key=='height')&&parseFloat(value)<0)value=undefined;return this.attr(key,value,"curCSS");},text:function(text){if(typeof text!="object"&&text!=null)return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(text));var ret="";jQuery.each(text||this,function(){jQuery.each(this.childNodes,function(){if(this.nodeType!=8)ret+=this.nodeType!=1?this.nodeValue:jQuery.fn.text([this]);});});return ret;},wrapAll:function(html){if(this[0])jQuery(html,this[0].ownerDocument).clone().insertBefore(this[0]).map(function(){var elem=this;while(elem.firstChild)elem=elem.firstChild;return elem;}).append(this);return this;},wrapInner:function(html){return this.each(function(){jQuery(this).contents().wrapAll(html);});},wrap:function(html){return this.each(function(){jQuery(this).wrapAll(html);});},append:function(){return this.domManip(arguments,true,false,function(elem){if(this.nodeType==1)this.appendChild(elem);});},prepend:function(){return this.domManip(arguments,true,true,function(elem){if(this.nodeType==1)this.insertBefore(elem,this.firstChild);});},before:function(){return this.domManip(arguments,false,false,function(elem){this.parentNode.insertBefore(elem,this);});},after:function(){return this.domManip(arguments,false,true,function(elem){this.parentNode.insertBefore(elem,this.nextSibling);});},end:function(){return this.prevObject||jQuery([]);},find:function(selector){var elems=jQuery.map(this,function(elem){return jQuery.find(selector,elem);});return this.pushStack(/[^+>] [^+>]/.test(selector)||selector.indexOf("..")>-1?jQuery.unique(elems):elems);},clone:function(events){var ret=this.map(function(){if(jQuery.browser.msie&&!jQuery.isXMLDoc(this)){var clone=this.cloneNode(true),container=document.createElement("div");container.appendChild(clone);return jQuery.clean([container.innerHTML])[0];}else -return this.cloneNode(true);});var clone=ret.find("*").andSelf().each(function(){if(this[expando]!=undefined)this[expando]=null;});if(events===true)this.find("*").andSelf().each(function(i){if(this.nodeType==3)return;var events=jQuery.data(this,"events");for(var type in events)for(var handler in events[type])jQuery.event.add(clone[i],type,events[type][handler],events[type][handler].data);});return ret;},filter:function(selector){return this.pushStack(jQuery.isFunction(selector)&&jQuery.grep(this,function(elem,i){return selector.call(elem,i);})||jQuery.multiFilter(selector,this));},not:function(selector){if(selector.constructor==String)if(isSimple.test(selector))return this.pushStack(jQuery.multiFilter(selector,this,true));else -selector=jQuery.multiFilter(selector,this);var isArrayLike=selector.length&&selector[selector.length-1]!==undefined&&!selector.nodeType;return this.filter(function(){return isArrayLike?jQuery.inArray(this,selector)<0:this!=selector;});},add:function(selector){return!selector?this:this.pushStack(jQuery.merge(this.get(),selector.constructor==String?jQuery(selector).get():selector.length!=undefined&&(!selector.nodeName||jQuery.nodeName(selector,"form"))?selector:[selector]));},is:function(selector){return selector?jQuery.multiFilter(selector,this).length>0:false;},hasClass:function(selector){return this.is("."+selector);},val:function(value){if(value==undefined){if(this.length){var elem=this[0];if(jQuery.nodeName(elem,"select")){var index=elem.selectedIndex,values=[],options=elem.options,one=elem.type=="select-one";if(index<0)return null;for(var i=one?index:0,max=one?index+1:options.length;i=0||jQuery.inArray(this.name,value)>=0);else if(jQuery.nodeName(this,"select")){var values=value.constructor==Array?value:[value];jQuery("option",this).each(function(){this.selected=(jQuery.inArray(this.value,values)>=0||jQuery.inArray(this.text,values)>=0);});if(!values.length)this.selectedIndex=-1;}else -this.value=value;});},html:function(value){return value==undefined?(this.length?this[0].innerHTML:null):this.empty().append(value);},replaceWith:function(value){return this.after(value).remove();},eq:function(i){return this.slice(i,i+1);},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments));},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem);}));},andSelf:function(){return this.add(this.prevObject);},data:function(key,value){var parts=key.split(".");parts[1]=parts[1]?"."+parts[1]:"";if(value==null){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data==undefined&&this.length)data=jQuery.data(this[0],key);return data==null&&parts[1]?this.data(parts[0]):data;}else -return this.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){jQuery.data(this,key,value);});},removeData:function(key){return this.each(function(){jQuery.removeData(this,key);});},domManip:function(args,table,reverse,callback){var clone=this.length>1,elems;return this.each(function(){if(!elems){elems=jQuery.clean(args,this.ownerDocument);if(reverse)elems.reverse();}var obj=this;if(table&&jQuery.nodeName(this,"table")&&jQuery.nodeName(elems[0],"tr"))obj=this.getElementsByTagName("tbody")[0]||this.appendChild(this.ownerDocument.createElement("tbody"));var scripts=jQuery([]);jQuery.each(elems,function(){var elem=clone?jQuery(this).clone(true)[0]:this;if(jQuery.nodeName(elem,"script")){scripts=scripts.add(elem);}else{if(elem.nodeType==1)scripts=scripts.add(jQuery("script",elem).remove());callback.call(obj,elem);}});scripts.each(evalScript);});}};jQuery.prototype.init.prototype=jQuery.prototype;function evalScript(i,elem){if(elem.src)jQuery.ajax({url:elem.src,async:false,dataType:"script"});else -jQuery.globalEval(elem.text||elem.textContent||elem.innerHTML||"");if(elem.parentNode)elem.parentNode.removeChild(elem);}jQuery.extend=jQuery.fn.extend=function(){var target=arguments[0]||{},i=1,length=arguments.length,deep=false,options;if(target.constructor==Boolean){deep=target;target=arguments[1]||{};i=2;}if(typeof target!="object"&&typeof target!="function")target={};if(length==1){target=this;i=0;}for(;i-1;}},swap:function(elem,options,callback){var old={};for(var name in options){old[name]=elem.style[name];elem.style[name]=options[name];}callback.call(elem);for(var name in options)elem.style[name]=old[name];},css:function(elem,name,force){if(name=="width"||name=="height"){var val,props={position:"absolute",visibility:"hidden",display:"block"},which=name=="width"?["Left","Right"]:["Top","Bottom"];function getWH(){val=name=="width"?elem.offsetWidth:elem.offsetHeight;var padding=0,border=0;jQuery.each(which,function(){padding+=parseFloat(jQuery.curCSS(elem,"padding"+this,true))||0;border+=parseFloat(jQuery.curCSS(elem,"border"+this+"Width",true))||0;});val-=Math.round(padding+border);}if(jQuery(elem).is(":visible"))getWH();else -jQuery.swap(elem,props,getWH);return Math.max(0,val);}return jQuery.curCSS(elem,name,force);},curCSS:function(elem,name,force){var ret;function color(elem){if(!jQuery.browser.safari)return false;var ret=document.defaultView.getComputedStyle(elem,null);return!ret||ret.getPropertyValue("color")=="";}if(name=="opacity"&&jQuery.browser.msie){ret=jQuery.attr(elem.style,"opacity");return ret==""?"1":ret;}if(jQuery.browser.opera&&name=="display"){var save=elem.style.outline;elem.style.outline="0 solid black";elem.style.outline=save;}if(name.match(/float/i))name=styleFloat;if(!force&&elem.style&&elem.style[name])ret=elem.style[name];else if(document.defaultView&&document.defaultView.getComputedStyle){if(name.match(/float/i))name="float";name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var getComputedStyle=document.defaultView.getComputedStyle(elem,null);if(getComputedStyle&&!color(elem))ret=getComputedStyle.getPropertyValue(name);else{var swap=[],stack=[];for(var a=elem;a&&color(a);a=a.parentNode)stack.unshift(a);for(var i=0;i]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+">";});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("",""]||!tags.indexOf("",""]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
                  "]||!tags.indexOf("",""]||(!tags.indexOf("",""]||!tags.indexOf("",""]||jQuery.browser.msie&&[1,"div
                  ","
                  "]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--)div=div.lastChild;if(jQuery.browser.msie){var tbody=!tags.indexOf(""&&tags.indexOf("=0;--j)if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length)tbody[j].parentNode.removeChild(tbody[j]);if(/^\s/.test(elem))div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]),div.firstChild);}elem=jQuery.makeArray(div.childNodes);}if(elem.length===0&&(!jQuery.nodeName(elem,"form")&&!jQuery.nodeName(elem,"select")))return;if(elem[0]==undefined||jQuery.nodeName(elem,"form")||elem.options)ret.push(elem);else -ret=jQuery.merge(ret,elem);});return ret;},attr:function(elem,name,value){if(!elem||elem.nodeType==3||elem.nodeType==8)return undefined;var fix=jQuery.isXMLDoc(elem)?{}:jQuery.props;if(name=="selected"&&jQuery.browser.safari)elem.parentNode.selectedIndex;if(fix[name]){if(value!=undefined)elem[fix[name]]=value;return elem[fix[name]];}else if(jQuery.browser.msie&&name=="style")return jQuery.attr(elem.style,"cssText",value);else if(value==undefined&&jQuery.browser.msie&&jQuery.nodeName(elem,"form")&&(name=="action"||name=="method"))return elem.getAttributeNode(name).nodeValue;else if(elem.tagName){if(value!=undefined){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode)throw"type property can't be changed";elem.setAttribute(name,""+value);}if(jQuery.browser.msie&&/href|src/.test(name)&&!jQuery.isXMLDoc(elem))return elem.getAttribute(name,2);return elem.getAttribute(name);}else{if(name=="opacity"&&jQuery.browser.msie){if(value!=undefined){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+(parseFloat(value).toString()=="NaN"?"":"alpha(opacity="+value*100+")");}return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100).toString():"";}name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase();});if(value!=undefined)elem[name]=value;return elem[name];}},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"");},makeArray:function(array){var ret=[];if(typeof array!="array")for(var i=0,length=array.length;i*",this).remove();while(this.firstChild)this.removeChild(this.firstChild);}},function(name,fn){jQuery.fn[name]=function(){return this.each(fn,arguments);};});jQuery.each(["Height","Width"],function(i,name){var type=name.toLowerCase();jQuery.fn[type]=function(size){return this[0]==window?jQuery.browser.opera&&document.body["client"+name]||jQuery.browser.safari&&window["inner"+name]||document.compatMode=="CSS1Compat"&&document.documentElement["client"+name]||document.body["client"+name]:this[0]==document?Math.max(Math.max(document.body["scroll"+name],document.documentElement["scroll"+name]),Math.max(document.body["offset"+name],document.documentElement["offset"+name])):size==undefined?(this.length?jQuery.css(this[0],type):null):this.css(type,size.constructor==String?size:size+"px");};});var chars=jQuery.browser.safari&&parseInt(jQuery.browser.version)<417?"(?:[\\w*_-]|\\\\.)":"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",quickChild=new RegExp("^>\\s*("+chars+"+)"),quickID=new RegExp("^("+chars+"+)(#)("+chars+"+)"),quickClass=new RegExp("^([#.]?)("+chars+"*)");jQuery.extend({expr:{"":function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},"#":function(a,i,m){return a.getAttribute("id")==m[2];},":":{lt:function(a,i,m){return im[3]-0;},nth:function(a,i,m){return m[3]-0==i;},eq:function(a,i,m){return m[3]-0==i;},first:function(a,i){return i==0;},last:function(a,i,m,r){return i==r.length-1;},even:function(a,i){return i%2==0;},odd:function(a,i){return i%2;},"first-child":function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},"last-child":function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},"only-child":function(a){return!jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},parent:function(a){return a.firstChild;},empty:function(a){return!a.firstChild;},contains:function(a,i,m){return(a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},visible:function(a){return"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},hidden:function(a){return"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},enabled:function(a){return!a.disabled;},disabled:function(a){return a.disabled;},checked:function(a){return a.checked;},selected:function(a){return a.selected||jQuery.attr(a,"selected");},text:function(a){return"text"==a.type;},radio:function(a){return"radio"==a.type;},checkbox:function(a){return"checkbox"==a.type;},file:function(a){return"file"==a.type;},password:function(a){return"password"==a.type;},submit:function(a){return"submit"==a.type;},image:function(a){return"image"==a.type;},reset:function(a){return"reset"==a.type;},button:function(a){return"button"==a.type||jQuery.nodeName(a,"button");},input:function(a){return/input|select|textarea|button/i.test(a.nodeName);},has:function(a,i,m){return jQuery.find(m[3],a).length;},header:function(a){return/h\d/i.test(a.nodeName);},animated:function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}}},parse:[/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,new RegExp("^([:.#]*)("+chars+"+)")],multiFilter:function(expr,elems,not){var old,cur=[];while(expr&&expr!=old){old=expr;var f=jQuery.filter(expr,elems,not);expr=f.t.replace(/^\s*,\s*/,"");cur=not?elems=f.r:jQuery.merge(cur,f.r);}return cur;},find:function(t,context){if(typeof t!="string")return[t];if(context&&context.nodeType!=1&&context.nodeType!=9)return[];context=context||document;var ret=[context],done=[],last,nodeName;while(t&&last!=t){var r=[];last=t;t=jQuery.trim(t);var foundToken=false;var re=quickChild;var m=re.exec(t);if(m){nodeName=m[1].toUpperCase();for(var i=0;ret[i];i++)for(var c=ret[i].firstChild;c;c=c.nextSibling)if(c.nodeType==1&&(nodeName=="*"||c.nodeName.toUpperCase()==nodeName))r.push(c);ret=r;t=t.replace(re,"");if(t.indexOf(" ")==0)continue;foundToken=true;}else{re=/^([>+~])\s*(\w*)/i;if((m=re.exec(t))!=null){r=[];var merge={};nodeName=m[2].toUpperCase();m=m[1];for(var j=0,rl=ret.length;j=0;if(!not&&pass||not&&!pass)tmp.push(r[i]);}return tmp;},filter:function(t,r,not){var last;while(t&&t!=last){last=t;var p=jQuery.parse,m;for(var i=0;p[i];i++){m=p[i].exec(t);if(m){t=t.substring(m[0].length);m[2]=m[2].replace(/\\/g,"");break;}}if(!m)break;if(m[1]==":"&&m[2]=="not")r=isSimple.test(m[3])?jQuery.filter(m[3],r,true).r:jQuery(r).not(m[3]);else if(m[1]==".")r=jQuery.classFilter(r,m[2],not);else if(m[1]=="["){var tmp=[],type=m[3];for(var i=0,rl=r.length;i=0)^not)tmp.push(a);}r=tmp;}else if(m[1]==":"&&m[2]=="nth-child"){var merge={},tmp=[],test=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3]=="even"&&"2n"||m[3]=="odd"&&"2n+1"||!/\D/.test(m[3])&&"0n+"+m[3]||m[3]),first=(test[1]+(test[2]||1))-0,last=test[3]-0;for(var i=0,rl=r.length;i=0)add=true;if(add^not)tmp.push(node);}r=tmp;}else{var fn=jQuery.expr[m[1]];if(typeof fn=="object")fn=fn[m[2]];if(typeof fn=="string")fn=eval("false||function(a,i){return "+fn+";}");r=jQuery.grep(r,function(elem,i){return fn(elem,i,m,r);},not);}}return{r:r,t:t};},dir:function(elem,dir){var matched=[];var cur=elem[dir];while(cur&&cur!=document){if(cur.nodeType==1)matched.push(cur);cur=cur[dir];}return matched;},nth:function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir])if(cur.nodeType==1&&++num==result)break;return cur;},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType==1&&(!elem||n!=elem))r.push(n);}return r;}});jQuery.event={add:function(elem,types,handler,data){if(elem.nodeType==3||elem.nodeType==8)return;if(jQuery.browser.msie&&elem.setInterval!=undefined)elem=window;if(!handler.guid)handler.guid=this.guid++;if(data!=undefined){var fn=handler;handler=function(){return fn.apply(this,arguments);};handler.data=data;handler.guid=fn.guid;}var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){var val;if(typeof jQuery=="undefined"||jQuery.event.triggered)return val;val=jQuery.event.handle.apply(arguments.callee.elem,arguments);return val;});handle.elem=elem;jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];handler.type=parts[1];var handlers=events[type];if(!handlers){handlers=events[type]={};if(!jQuery.event.special[type]||jQuery.event.special[type].setup.call(elem)===false){if(elem.addEventListener)elem.addEventListener(type,handle,false);else if(elem.attachEvent)elem.attachEvent("on"+type,handle);}}handlers[handler.guid]=handler;jQuery.event.global[type]=true;});elem=null;},guid:1,global:{},remove:function(elem,types,handler){if(elem.nodeType==3||elem.nodeType==8)return;var events=jQuery.data(elem,"events"),ret,index;if(events){if(types==undefined||(typeof types=="string"&&types.charAt(0)=="."))for(var type in events)this.remove(elem,type+(types||""));else{if(types.type){handler=types.handler;types=types.type;}jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];if(events[type]){if(handler)delete events[type][handler.guid];else -for(handler in events[type])if(!parts[1]||events[type][handler].type==parts[1])delete events[type][handler];for(ret in events[type])break;if(!ret){if(!jQuery.event.special[type]||jQuery.event.special[type].teardown.call(elem)===false){if(elem.removeEventListener)elem.removeEventListener(type,jQuery.data(elem,"handle"),false);else if(elem.detachEvent)elem.detachEvent("on"+type,jQuery.data(elem,"handle"));}ret=null;delete events[type];}}});}for(ret in events)break;if(!ret){var handle=jQuery.data(elem,"handle");if(handle)handle.elem=null;jQuery.removeData(elem,"events");jQuery.removeData(elem,"handle");}}},trigger:function(type,data,elem,donative,extra){data=jQuery.makeArray(data||[]);if(type.indexOf("!")>=0){type=type.slice(0,-1);var exclusive=true;}if(!elem){if(this.global[type])jQuery("*").add([window,document]).trigger(type,data);}else{if(elem.nodeType==3||elem.nodeType==8)return undefined;var val,ret,fn=jQuery.isFunction(elem[type]||null),event=!data[0]||!data[0].preventDefault;if(event)data.unshift(this.fix({type:type,target:elem}));data[0].type=type;if(exclusive)data[0].exclusive=true;if(jQuery.isFunction(jQuery.data(elem,"handle")))val=jQuery.data(elem,"handle").apply(elem,data);if(!fn&&elem["on"+type]&&elem["on"+type].apply(elem,data)===false)val=false;if(event)data.shift();if(extra&&jQuery.isFunction(extra)){ret=extra.apply(elem,val==null?data:data.concat(val));if(ret!==undefined)val=ret;}if(fn&&donative!==false&&val!==false&&!(jQuery.nodeName(elem,'a')&&type=="click")){this.triggered=true;try{elem[type]();}catch(e){}}this.triggered=false;}return val;},handle:function(event){var val;event=jQuery.event.fix(event||window.event||{});var parts=event.type.split(".");event.type=parts[0];var handlers=jQuery.data(this,"events")&&jQuery.data(this,"events")[event.type],args=Array.prototype.slice.call(arguments,1);args.unshift(event);for(var j in handlers){var handler=handlers[j];args[0].handler=handler;args[0].data=handler.data;if(!parts[1]&&!event.exclusive||handler.type==parts[1]){var ret=handler.apply(this,args);if(val!==false)val=ret;if(ret===false){event.preventDefault();event.stopPropagation();}}}if(jQuery.browser.msie)event.target=event.preventDefault=event.stopPropagation=event.handler=event.data=null;return val;},fix:function(event){var originalEvent=event;event=jQuery.extend({},originalEvent);event.preventDefault=function(){if(originalEvent.preventDefault)originalEvent.preventDefault();originalEvent.returnValue=false;};event.stopPropagation=function(){if(originalEvent.stopPropagation)originalEvent.stopPropagation();originalEvent.cancelBubble=true;};if(!event.target)event.target=event.srcElement||document;if(event.target.nodeType==3)event.target=originalEvent.target.parentNode;if(!event.relatedTarget&&event.fromElement)event.relatedTarget=event.fromElement==event.target?event.toElement:event.fromElement;if(event.pageX==null&&event.clientX!=null){var doc=document.documentElement,body=document.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc.clientTop||0);}if(!event.which&&((event.charCode||event.charCode===0)?event.charCode:event.keyCode))event.which=event.charCode||event.keyCode;if(!event.metaKey&&event.ctrlKey)event.metaKey=event.ctrlKey;if(!event.which&&event.button)event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)));return event;},special:{ready:{setup:function(){bindReady();return;},teardown:function(){return;}},mouseenter:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseover",jQuery.event.special.mouseenter.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseover",jQuery.event.special.mouseenter.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseenter";return jQuery.event.handle.apply(this,arguments);}},mouseleave:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseout",jQuery.event.special.mouseleave.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseout",jQuery.event.special.mouseleave.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseleave";return jQuery.event.handle.apply(this,arguments);}}}};jQuery.fn.extend({bind:function(type,data,fn){return type=="unload"?this.one(type,data,fn):this.each(function(){jQuery.event.add(this,type,fn||data,fn&&data);});},one:function(type,data,fn){return this.each(function(){jQuery.event.add(this,type,function(event){jQuery(this).unbind(event);return(fn||data).apply(this,arguments);},fn&&data);});},unbind:function(type,fn){return this.each(function(){jQuery.event.remove(this,type,fn);});},trigger:function(type,data,fn){return this.each(function(){jQuery.event.trigger(type,data,this,true,fn);});},triggerHandler:function(type,data,fn){if(this[0])return jQuery.event.trigger(type,data,this[0],false,fn);return undefined;},toggle:function(){var args=arguments;return this.click(function(event){this.lastToggle=0==this.lastToggle?1:0;event.preventDefault();return args[this.lastToggle].apply(this,arguments)||false;});},hover:function(fnOver,fnOut){return this.bind('mouseenter',fnOver).bind('mouseleave',fnOut);},ready:function(fn){bindReady();if(jQuery.isReady)fn.call(document,jQuery);else -jQuery.readyList.push(function(){return fn.call(this,jQuery);});return this;}});jQuery.extend({isReady:false,readyList:[],ready:function(){if(!jQuery.isReady){jQuery.isReady=true;if(jQuery.readyList){jQuery.each(jQuery.readyList,function(){this.apply(document);});jQuery.readyList=null;}jQuery(document).triggerHandler("ready");}}});var readyBound=false;function bindReady(){if(readyBound)return;readyBound=true;if(document.addEventListener&&!jQuery.browser.opera)document.addEventListener("DOMContentLoaded",jQuery.ready,false);if(jQuery.browser.msie&&window==top)(function(){if(jQuery.isReady)return;try{document.documentElement.doScroll("left");}catch(error){setTimeout(arguments.callee,0);return;}jQuery.ready();})();if(jQuery.browser.opera)document.addEventListener("DOMContentLoaded",function(){if(jQuery.isReady)return;for(var i=0;i=0){var selector=url.slice(off,url.length);url=url.slice(0,off);}callback=callback||function(){};var type="GET";if(params)if(jQuery.isFunction(params)){callback=params;params=null;}else{params=jQuery.param(params);type="POST";}var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(res,status){if(status=="success"||status=="notmodified")self.html(selector?jQuery("
                  ").append(res.responseText.replace(//g,"")).find(selector):res.responseText);self.each(callback,[res.responseText,status,res]);}});return this;},serialize:function(){return jQuery.param(this.serializeArray());},serializeArray:function(){return this.map(function(){return jQuery.nodeName(this,"form")?jQuery.makeArray(this.elements):this;}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type));}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:val.constructor==Array?jQuery.map(val,function(val,i){return{name:elem.name,value:val};}):{name:elem.name,value:val};}).get();}});jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(i,o){jQuery.fn[o]=function(f){return this.bind(o,f);};});var jsc=(new Date).getTime();jQuery.extend({get:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data=null;}return jQuery.ajax({type:"GET",url:url,data:data,success:callback,dataType:type});},getScript:function(url,callback){return jQuery.get(url,null,callback,"script");},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},post:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data={};}return jQuery.ajax({type:"POST",url:url,data:data,success:callback,dataType:type});},ajaxSetup:function(settings){jQuery.extend(jQuery.ajaxSettings,settings);},ajaxSettings:{global:true,type:"GET",timeout:0,contentType:"application/x-www-form-urlencoded",processData:true,async:true,data:null,username:null,password:null,accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(s){var jsonp,jsre=/=\?(&|$)/g,status,data;s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));if(s.data&&s.processData&&typeof s.data!="string")s.data=jQuery.param(s.data);if(s.dataType=="jsonp"){if(s.type.toLowerCase()=="get"){if(!s.url.match(jsre))s.url+=(s.url.match(/\?/)?"&":"?")+(s.jsonp||"callback")+"=?";}else if(!s.data||!s.data.match(jsre))s.data=(s.data?s.data+"&":"")+(s.jsonp||"callback")+"=?";s.dataType="json";}if(s.dataType=="json"&&(s.data&&s.data.match(jsre)||s.url.match(jsre))){jsonp="jsonp"+jsc++;if(s.data)s.data=(s.data+"").replace(jsre,"="+jsonp+"$1");s.url=s.url.replace(jsre,"="+jsonp+"$1");s.dataType="script";window[jsonp]=function(tmp){data=tmp;success();complete();window[jsonp]=undefined;try{delete window[jsonp];}catch(e){}if(head)head.removeChild(script);};}if(s.dataType=="script"&&s.cache==null)s.cache=false;if(s.cache===false&&s.type.toLowerCase()=="get"){var ts=(new Date()).getTime();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"");}if(s.data&&s.type.toLowerCase()=="get"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null;}if(s.global&&!jQuery.active++)jQuery.event.trigger("ajaxStart");if((!s.url.indexOf("http")||!s.url.indexOf("//"))&&s.dataType=="script"&&s.type.toLowerCase()=="get"){var head=document.getElementsByTagName("head")[0];var script=document.createElement("script");script.src=s.url;if(s.scriptCharset)script.charset=s.scriptCharset;if(!jsonp){var done=false;script.onload=script.onreadystatechange=function(){if(!done&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){done=true;success();complete();head.removeChild(script);}};}head.appendChild(script);return undefined;}var requestDone=false;var xml=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();xml.open(s.type,s.url,s.async,s.username,s.password);try{if(s.data)xml.setRequestHeader("Content-Type",s.contentType);if(s.ifModified)xml.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT");xml.setRequestHeader("X-Requested-With","XMLHttpRequest");xml.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default);}catch(e){}if(s.beforeSend)s.beforeSend(xml);if(s.global)jQuery.event.trigger("ajaxSend",[xml,s]);var onreadystatechange=function(isTimeout){if(!requestDone&&xml&&(xml.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null;}status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xml)&&"error"||s.ifModified&&jQuery.httpNotModified(xml,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xml,s.dataType);}catch(e){status="parsererror";}}if(status=="success"){var modRes;try{modRes=xml.getResponseHeader("Last-Modified");}catch(e){}if(s.ifModified&&modRes)jQuery.lastModified[s.url]=modRes;if(!jsonp)success();}else -jQuery.handleError(s,xml,status);complete();if(s.async)xml=null;}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0)setTimeout(function(){if(xml){xml.abort();if(!requestDone)onreadystatechange("timeout");}},s.timeout);}try{xml.send(s.data);}catch(e){jQuery.handleError(s,xml,null,e);}if(!s.async)onreadystatechange();function success(){if(s.success)s.success(data,status);if(s.global)jQuery.event.trigger("ajaxSuccess",[xml,s]);}function complete(){if(s.complete)s.complete(xml,status);if(s.global)jQuery.event.trigger("ajaxComplete",[xml,s]);if(s.global&&!--jQuery.active)jQuery.event.trigger("ajaxStop");}return xml;},handleError:function(s,xml,status,e){if(s.error)s.error(xml,status,e);if(s.global)jQuery.event.trigger("ajaxError",[xml,s,e]);},active:0,httpSuccess:function(r){try{return!r.status&&location.protocol=="file:"||(r.status>=200&&r.status<300)||r.status==304||r.status==1223||jQuery.browser.safari&&r.status==undefined;}catch(e){}return false;},httpNotModified:function(xml,url){try{var xmlRes=xml.getResponseHeader("Last-Modified");return xml.status==304||xmlRes==jQuery.lastModified[url]||jQuery.browser.safari&&xml.status==undefined;}catch(e){}return false;},httpData:function(r,type){var ct=r.getResponseHeader("content-type");var xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0;var data=xml?r.responseXML:r.responseText;if(xml&&data.documentElement.tagName=="parsererror")throw"parsererror";if(type=="script")jQuery.globalEval(data);if(type=="json")data=eval("("+data+")");return data;},param:function(a){var s=[];if(a.constructor==Array||a.jquery)jQuery.each(a,function(){s.push(encodeURIComponent(this.name)+"="+encodeURIComponent(this.value));});else -for(var j in a)if(a[j]&&a[j].constructor==Array)jQuery.each(a[j],function(){s.push(encodeURIComponent(j)+"="+encodeURIComponent(this));});else -s.push(encodeURIComponent(j)+"="+encodeURIComponent(a[j]));return s.join("&").replace(/%20/g,"+");}});jQuery.fn.extend({show:function(speed,callback){return speed?this.animate({height:"show",width:"show",opacity:"show"},speed,callback):this.filter(":hidden").each(function(){this.style.display=this.oldblock||"";if(jQuery.css(this,"display")=="none"){var elem=jQuery("<"+this.tagName+" />").appendTo("body");this.style.display=elem.css("display");if(this.style.display=="none")this.style.display="block";elem.remove();}}).end();},hide:function(speed,callback){return speed?this.animate({height:"hide",width:"hide",opacity:"hide"},speed,callback):this.filter(":visible").each(function(){this.oldblock=this.oldblock||jQuery.css(this,"display");this.style.display="none";}).end();},_toggle:jQuery.fn.toggle,toggle:function(fn,fn2){return jQuery.isFunction(fn)&&jQuery.isFunction(fn2)?this._toggle(fn,fn2):fn?this.animate({height:"toggle",width:"toggle",opacity:"toggle"},fn,fn2):this.each(function(){jQuery(this)[jQuery(this).is(":hidden")?"show":"hide"]();});},slideDown:function(speed,callback){return this.animate({height:"show"},speed,callback);},slideUp:function(speed,callback){return this.animate({height:"hide"},speed,callback);},slideToggle:function(speed,callback){return this.animate({height:"toggle"},speed,callback);},fadeIn:function(speed,callback){return this.animate({opacity:"show"},speed,callback);},fadeOut:function(speed,callback){return this.animate({opacity:"hide"},speed,callback);},fadeTo:function(speed,to,callback){return this.animate({opacity:to},speed,callback);},animate:function(prop,speed,easing,callback){var optall=jQuery.speed(speed,easing,callback);return this[optall.queue===false?"each":"queue"](function(){if(this.nodeType!=1)return false;var opt=jQuery.extend({},optall);var hidden=jQuery(this).is(":hidden"),self=this;for(var p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden)return jQuery.isFunction(opt.complete)&&opt.complete.apply(this);if(p=="height"||p=="width"){opt.display=jQuery.css(this,"display");opt.overflow=this.style.overflow;}}if(opt.overflow!=null)this.style.overflow="hidden";opt.curAnim=jQuery.extend({},prop);jQuery.each(prop,function(name,val){var e=new jQuery.fx(self,opt,name);if(/toggle|show|hide/.test(val))e[val=="toggle"?hidden?"show":"hide":val](prop);else{var parts=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),start=e.cur(true)||0;if(parts){var end=parseFloat(parts[2]),unit=parts[3]||"px";if(unit!="px"){self.style[name]=(end||1)+unit;start=((end||1)/e.cur(true))*start;self.style[name]=start+unit;}if(parts[1])end=((parts[1]=="-="?-1:1)*end)+start;e.custom(start,end,unit);}else -e.custom(start,val,"");}});return true;});},queue:function(type,fn){if(jQuery.isFunction(type)||(type&&type.constructor==Array)){fn=type;type="fx";}if(!type||(typeof type=="string"&&!fn))return queue(this[0],type);return this.each(function(){if(fn.constructor==Array)queue(this,type,fn);else{queue(this,type).push(fn);if(queue(this,type).length==1)fn.apply(this);}});},stop:function(clearQueue,gotoEnd){var timers=jQuery.timers;if(clearQueue)this.queue([]);this.each(function(){for(var i=timers.length-1;i>=0;i--)if(timers[i].elem==this){if(gotoEnd)timers[i](true);timers.splice(i,1);}});if(!gotoEnd)this.dequeue();return this;}});var queue=function(elem,type,array){if(!elem)return undefined;type=type||"fx";var q=jQuery.data(elem,type+"queue");if(!q||array)q=jQuery.data(elem,type+"queue",array?jQuery.makeArray(array):[]);return q;};jQuery.fn.dequeue=function(type){type=type||"fx";return this.each(function(){var q=queue(this,type);q.shift();if(q.length)q[0].apply(this);});};jQuery.extend({speed:function(speed,easing,fn){var opt=speed&&speed.constructor==Object?speed:{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&easing.constructor!=Function&&easing};opt.duration=(opt.duration&&opt.duration.constructor==Number?opt.duration:{slow:600,fast:200}[opt.duration])||400;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false)jQuery(this).dequeue();if(jQuery.isFunction(opt.old))opt.old.apply(this);};return opt;},easing:{linear:function(p,n,firstNum,diff){return firstNum+diff*p;},swing:function(p,n,firstNum,diff){return((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum;}},timers:[],timerId:null,fx:function(elem,options,prop){this.options=options;this.elem=elem;this.prop=prop;if(!options.orig)options.orig={};}});jQuery.fx.prototype={update:function(){if(this.options.step)this.options.step.apply(this.elem,[this.now,this]);(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);if(this.prop=="height"||this.prop=="width")this.elem.style.display="block";},cur:function(force){if(this.elem[this.prop]!=null&&this.elem.style[this.prop]==null)return this.elem[this.prop];var r=parseFloat(jQuery.css(this.elem,this.prop,force));return r&&r>-10000?r:parseFloat(jQuery.curCSS(this.elem,this.prop))||0;},custom:function(from,to,unit){this.startTime=(new Date()).getTime();this.start=from;this.end=to;this.unit=unit||this.unit||"px";this.now=this.start;this.pos=this.state=0;this.update();var self=this;function t(gotoEnd){return self.step(gotoEnd);}t.elem=this.elem;jQuery.timers.push(t);if(jQuery.timerId==null){jQuery.timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;ithis.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var done=true;for(var i in this.options.curAnim)if(this.options.curAnim[i]!==true)done=false;if(done){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(jQuery.css(this.elem,"display")=="none")this.elem.style.display="block";}if(this.options.hide)this.elem.style.display="none";if(this.options.hide||this.options.show)for(var p in this.options.curAnim)jQuery.attr(this.elem.style,p,this.options.orig[p]);}if(done&&jQuery.isFunction(this.options.complete))this.options.complete.apply(this.elem);return false;}else{var n=t-this.startTime;this.state=n/this.options.duration;this.pos=jQuery.easing[this.options.easing||(jQuery.easing.swing?"swing":"linear")](this.state,n,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update();}return true;}};jQuery.fx.step={scrollLeft:function(fx){fx.elem.scrollLeft=fx.now;},scrollTop:function(fx){fx.elem.scrollTop=fx.now;},opacity:function(fx){jQuery.attr(fx.elem.style,"opacity",fx.now);},_default:function(fx){fx.elem.style[fx.prop]=fx.now+fx.unit;}};jQuery.fn.offset=function(){var left=0,top=0,elem=this[0],results;if(elem)with(jQuery.browser){var parent=elem.parentNode,offsetChild=elem,offsetParent=elem.offsetParent,doc=elem.ownerDocument,safari2=safari&&parseInt(version)<522&&!/adobeair/i.test(userAgent),fixed=jQuery.css(elem,"position")=="fixed";if(elem.getBoundingClientRect){var box=elem.getBoundingClientRect();add(box.left+Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),box.top+Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));add(-doc.documentElement.clientLeft,-doc.documentElement.clientTop);}else{add(elem.offsetLeft,elem.offsetTop);while(offsetParent){add(offsetParent.offsetLeft,offsetParent.offsetTop);if(mozilla&&!/^t(able|d|h)$/i.test(offsetParent.tagName)||safari&&!safari2)border(offsetParent);if(!fixed&&jQuery.css(offsetParent,"position")=="fixed")fixed=true;offsetChild=/^body$/i.test(offsetParent.tagName)?offsetChild:offsetParent;offsetParent=offsetParent.offsetParent;}while(parent&&parent.tagName&&!/^body|html$/i.test(parent.tagName)){if(!/^inline|table.*$/i.test(jQuery.css(parent,"display")))add(-parent.scrollLeft,-parent.scrollTop);if(mozilla&&jQuery.css(parent,"overflow")!="visible")border(parent);parent=parent.parentNode;}if((safari2&&(fixed||jQuery.css(offsetChild,"position")=="absolute"))||(mozilla&&jQuery.css(offsetChild,"position")!="absolute"))add(-doc.body.offsetLeft,-doc.body.offsetTop);if(fixed)add(Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));}results={top:top,left:left};}function border(elem){add(jQuery.curCSS(elem,"borderLeftWidth",true),jQuery.curCSS(elem,"borderTopWidth",true));}function add(l,t){left+=parseInt(l)||0;top+=parseInt(t)||0;}return results;};})(); \ No newline at end of file diff --git a/non-rack-legacy/public/javascripts/json2.js b/non-rack-legacy/public/javascripts/json2.js deleted file mode 100644 index d4f4541..0000000 --- a/non-rack-legacy/public/javascripts/json2.js +++ /dev/null @@ -1 +0,0 @@ -if(!this.JSON){this.JSON={}}(function(){function f(n){return n<10?'0'+n:n}if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+'-'+f(this.getUTCMonth()+1)+'-'+f(this.getUTCDate())+'T'+f(this.getUTCHours())+':'+f(this.getUTCMinutes())+':'+f(this.getUTCSeconds())+'Z':null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key)}if(typeof rep==='function'){value=rep.call(holder,key,value)}switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null'}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object Array]'){length=value.length;for(i=0;i)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, -Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& -(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, -a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== -"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, -function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
                  a"; -var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, -parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= -false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= -s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, -applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; -else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, -a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== -w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, -cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= -c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); -a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, -function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); -k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), -C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B=0){a.type= -e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& -f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; -if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", -e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, -"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, -d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, -e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); -t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| -g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, -CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, -g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, -text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, -setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= -h[3];l=0;for(m=h.length;l=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== -"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, -h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& -q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; -if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="

                  ";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); -(function(){var g=s.createElement("div");g.innerHTML="
                  ";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: -function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var j=d;j0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= -{},i;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== -"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", -d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? -a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== -1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"},F={option:[1,""],legend:[1,"
                  ","
                  "],thead:[1,"","
                  "],tr:[2,"","
                  "],td:[3,"","
                  "],col:[2,"","
                  "],area:[1,"",""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
                  ","
                  "];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= -c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, -wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, -prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, -this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); -return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, -""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); -return this}else{e=0;for(var j=d.length;e0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", -""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===""&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= -c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? -c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= -function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= -Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, -"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= -a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= -a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=//gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!== -"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("
                  ").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this}, -serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), -function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href, -global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&& -e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)? -"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache=== -false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B= -false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since", -c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E|| -d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x); -g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status=== -1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b=== -"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional; -if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration=== -"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]|| -c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start; -this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now= -this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem, -e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b
                  "; -a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b); -c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a, -d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top- -f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset": -"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in -e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window); -/*json2.js*/ -if(!this.JSON){this.JSON={}}(function(){function f(n){return n<10?'0'+n:n}if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+'-'+f(this.getUTCMonth()+1)+'-'+f(this.getUTCDate())+'T'+f(this.getUTCHours())+':'+f(this.getUTCMinutes())+':'+f(this.getUTCSeconds())+'Z':null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key)}if(typeof rep==='function'){value=rep.call(holder,key,value)}switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null'}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object Array]'){length=value.length;for(i=0;i
                  ');var typer=$('');var promptBox;var prompt;var promptLabel=config&&config.promptLabel?config.promptLabel:"> ";var column=0;var promptText='';var restoreText='';var history=[];var ringn=0;var cancelKeyPress=0;var extern={};(function(){container.append(inner);inner.append(typer);typer.css({position:'absolute',top:0,left:'-999px'});if(config.welcomeMessage)message(config.welcomeMessage,'jquery-console-welcome');newPromptBox();if(config.autofocus){inner.addClass('jquery-console-focus');typer.focus();setTimeout(function(){inner.addClass('jquery-console-focus');typer.focus()},100)}})();extern.reset=function(){var welcome=true;inner.parent().fadeOut(function(){inner.find('div').each(function(){if(!welcome)$(this).remove();welcome=false});newPromptBox();inner.parent().fadeIn(function(){inner.addClass('jquery-console-focus');typer.focus()})})};function newPromptBox(){column=0;promptText='';promptBox=$('
                  ');var label=$('');promptBox.append(label.text(promptLabel).show());prompt=$('');promptBox.append(prompt);inner.append(promptBox);updatePromptDisplay()};container.click(function(){inner.addClass('jquery-console-focus');inner.removeClass('jquery-console-nofocus');typer.focus();scrollToBottom();return false});typer.blur(function(){inner.removeClass('jquery-console-focus');inner.addClass('jquery-console-nofocus')});typer.keydown(function(e){cancelKeyPress=0;var keyCode=e.keyCode;if(isControlCharacter(keyCode)){cancelKeyPress=keyCode;if(!typer.consoleControl(keyCode)){return false}}});typer.keypress(function(e){var keyCode=e.keyCode||e.which;if(cancelKeyPress!=keyCode&&keyCode>=32){if(cancelKeyPress)return false;typer.consoleInsert(keyCode)}if($.browser.webkit)return false});function isControlCharacter(keyCode){return((keyCode>=keyCodes.left&&keyCode<=keyCodes.down)||keyCode==keyCodes.back||keyCode==keyCodes.del||keyCode==keyCodes.end||keyCode==keyCodes.start||keyCode==keyCodes.ret)};typer.consoleControl=function(keyCode){switch(keyCode){case keyCodes.left:{moveColumn(-1);updatePromptDisplay();return false;break}case keyCodes.right:{moveColumn(1);updatePromptDisplay();return false;break}case keyCodes.back:{if(moveColumn(-1)){deleteCharAtPos();updatePromptDisplay()}return false;break}case keyCodes.del:{if(deleteCharAtPos())updatePromptDisplay();return false;break}case keyCodes.end:{if(moveColumn(promptText.length-column))updatePromptDisplay();return false;break}case keyCodes.start:{if(moveColumn(-column))updatePromptDisplay();return false;break}case keyCodes.ret:{commandTrigger();return false}case keyCodes.up:{rotateHistory(-1);return false}case keyCodes.down:{rotateHistory(1);return false}default:}};function rotateHistory(n){if(history.length==0)return;ringn+=n;if(ringn<0)ringn=history.length;else if(ringn>history.length)ringn=0;var prevText=promptText;if(ringn==0){promptText=restoreText}else{promptText=history[ringn-1]}if(config.historyPreserveColumn){if(promptText.length
                  ');if(className)mesg.addClass(className);mesg.filledText(msg).hide();inner.append(mesg);mesg.show()};typer.consoleInsert=function(keyCode){var char=String.fromCharCode(keyCode);var before=promptText.substring(0,column);var after=promptText.substring(column);promptText=before+char+after;moveColumn(1);restoreText=promptText;updatePromptDisplay()};function moveColumn(n){if(column+n>=0&&column+n<=promptText.length){column+=n;return true}else return false};function updatePromptDisplay(){var line=promptText;var html='';if(column>0&&line==''){html=cursor}else if(column==promptText.length){html=htmlEncode(line)+cursor}else{var before=line.substring(0,column);var current=line.substring(column,column+1);if(current){current=''+htmlEncode(current)+''}var after=line.substring(column+1);html=htmlEncode(before)+current+htmlEncode(after)}prompt.html(html);scrollToBottom()};function htmlEncode(text){return(text.replace(/&/g,'&').replace(/&]{10})/g,'$1­'+wbr))};return extern};$.fn.filledText=function(txt){$(this).text(txt);$(this).html($(this).html().replace(/\n/g,'
                  '));return this}})(jQuery); diff --git a/non-rack-legacy/public/javascripts/mouseapp_2.js b/non-rack-legacy/public/javascripts/mouseapp_2.js deleted file mode 100755 index de5c777..0000000 --- a/non-rack-legacy/public/javascripts/mouseapp_2.js +++ /dev/null @@ -1,913 +0,0 @@ -// -// Copyright (c) 2008 why the lucky stiff -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, -// and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT -// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -var MouseApp = { - Version: '0.12', - CharCodes: { - 0: ' ', 1: ' ', 9: ' ', - 32: ' ', 34: '"', 38: '&', - 60: '<', 62: '>', 127: '◊', - 0x20AC: '€' - }, - KeyCodes: { - Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 33, PageDown: 34, - End: 35, Home: 36, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 45, - Delete: 46, F1: 112, F2: 113, F3: 114, F4: 115, F5: 116, F6: 117, - F7: 118, F8: 119, F10: 121 - }, - CodeKeys: {}, - Modes: { 1: 'b', 2: 'u', 4: 'i', 8: 'strike' }, - ModeIds: { r: 1, u: 2, i: 4, s: 8 }, - Colors: ['black', 'blue', 'green', - 'cyan', 'red', 'purple', 'brown', - 'gray', 'dark_gray', 'lt_blue', - 'lt_green', 'lt_cyan', 'lt_red', - 'lt_purple', 'yellow', 'white'] -} -//some of these are patently false, because I need to get on a real keyboard-- not a macbook. -if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1){ - MouseApp.KeyCodes = { - Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, - End: 63275, Home: 63273, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 632325, - Delete: 46, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, - F7: 63242, F8: 63243, F10: 63244 - } - -} - -//even though I am tempted to combine chrome and opera into the same if statment, I will refrain for now -// i dont have proper access to a proper keyboard and there might be a single difference between the two -if (navigator.userAgent.indexOf("Opera") > -1){ - MouseApp.KeyCodes = { - Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, - End: 63275, Home: 63273, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 632325, - Delete: 46, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, - F7: 63242, F8: 63243, F10: 63244 - } - -} - -// i am going to comment this out, since this seems un needed. if it past december 15 2009 and this -// is still commented it, please del me -//if ( navigator.appVersion.indexOf('AppleWebKit') > 0 ) { -// MouseApp.KeyCodes = { -// Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, -// End: 63275, Home: 63273, Left: 63234, Up: 63232, Right: 63235, Down: 63233, Insert: 632325, -// Delete: 63272, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, -// F7: 63242, F8: 63243, F10: 63244 -// };// -//} -for ( var k in MouseApp.KeyCodes ) { - MouseApp.CodeKeys[MouseApp.KeyCodes[k]] = k; -} - -MouseApp.isPrintable = function(ch) { - return (ch >= 32); -}; - -MouseApp.Base = function(){}; -MouseApp.Base.prototype = { - setOptions: function(options) { - this.options = { - columns: 72, rows: 24, indent: 2, - title: 'MouseApp', - blinkRate: 500, - ps: '>', - greeting:'%+r Terminal ready. %-r' - } - $.extend(this.options, options || {}); - } -} - -MouseApp.Manager = new Object(); -$.extend(MouseApp.Manager, { - observeTerm: function(term) { - this.activeTerm = term; - if ( this.observingKeyboard ) return; - var mgr = this; - if ( term.input ) { - term.input.keypress(function(e) { mgr.onKeyPress(e) }); - if (!window.opera) term.input.keydown(function(e) { mgr.onKeyDown(e) }); - else window.setInterval(function(){term.input.focus()},1); - } else { - if (!window.opera) $(document).keydown(function(e) { mgr.onKeyDown(e) }); - $(document).keypress(function(e) { mgr.onKeyPress(e) }); - } - this.observingKeyboard = true; - }, - - onKeyDown: function(e) { - e = (e) ? e : ((event) ? event : null); - if ( e && MouseApp.CodeKeys[e.keyCode] ) { - if ( window.event ) { - this.sendKeyPress(e); - } - this.blockEvent(e); - return false; - } - return true; - }, - - onKeyPress: function(e) { - if ( !window.opera && window.event && e.keyCode != 13 && e.keyCode != 8 ) { - e.charCode = e.keyCode; e.keyCode = null; - } - if ( e.keyCode == 191 ) { /* FF 1.0.x sends this upsy quizy -- ignore */ - return; - } - return this.sendKeyPress(e); - }, - - sendKeyPress: function(e) { - var term = MouseApp.Manager.activeTerm; - term.cursorOff(); - b = term.onKeyPress(e); - term.cursorOn(); - return b; - }, - - blockEvent: function (e) { - e.cancelBubble=true; - if (window.event && !window.opera) e.keyCode=0; - if (e.stopPropagation) e.stopPropagation(); - if (e.preventDefault) e.preventDefault(); - } -}); - -/* Basic text window functionality */ -MouseApp.Window = function(element, options) { - this.element = $(element); - this.setOptions(options); - this.initWindow(); -}; - -$.extend(MouseApp.Window.prototype, (new MouseApp.Base()), { - initWindow: function() { - var html = ''; - for ( var i = 0; i < this.options.rows; i++ ) { - html += "
                   
                  \n"; - } - this.element.html(html); - this.typingOn(); - if (this.options.input) { - this.input = $(this.options.input); - this.input.focus(); - } - MouseApp.Manager.observeTerm(this); - this.clear(); - this.cursorOn(); - this.painting = true; - this.element.css({visibility: 'visible'}); - }, - - text: function() { - var str = ""; - for (var i = 0; i < this.screen.length; i++ ) { - for (var j = 0; j < this.options.columns; j++ ) { - var ch = this.screen[i][j]; - if ( ch[0] != 0 ) { - str += String.fromCharCode(ch[0]); - } - } - } - return str; - }, - - clear: function() { - this.rpos = 0; - this.cpos = 0; - this.screen = []; - this.element.html(''); - this.screen[0] = this.fillRow(this.options.columns, 0); - this.paint(0); - }, - - typingOn: function() { this.typing = true; }, - typingOff: function() { this.typing = false; }, - - cursorOn: function() { - if ( this.blinker ) { - clearInterval( this.blinker ); - } - this.underblink = this.screen[this.rpos][this.cpos][1]; - MouseApp.Manager.activeTerm.blink(); - this.blinker = setInterval(function(){MouseApp.Manager.activeTerm.blink();}, this.options.blinkRate); - this.cursor = true; - }, - - cursorOff: function() { - if ( this.blinker ) { - clearInterval( this.blinker ); - } - if ( this.cursor ) { - this.screen[this.rpos][this.cpos][1] = this.underblink; - this.paint(this.rpos); - this.cursor = false; - } - }, - - blink: function() { - if ( this == MouseApp.Manager.activeTerm ) { - var mode = this.screen[this.rpos][this.cpos][1]; - this.screen[this.rpos][this.cpos][1] = ( mode & 1 ) ? mode & 4094 : mode | 1; - this.paint(this.rpos); - } - }, - - fillRow: function(len, ch, mode) { - ary = [] - for (var i = 0; i < len; i++) { - ary[i] = [ch, mode]; - } - return ary; - }, - - paint: function(start, end) { - if (!this.painting) return; - - if (!end) end = start; - for (var row = start; row <= end && row < this.screen.length; row++) { - var html = ''; - var mode = 0; - var fcolor = 0; - var bcolor = 0; - var spans = 0; - for (var i = 0; i < this.options.columns; i++ ) { - var c = this.screen[row][i][0]; - var m = this.screen[row][i][1] & 15; // 4 mode bits - var f = (this.screen[row][i][1] & (15 << 4)) >> 4; // 4 foreground bits - var b = (this.screen[row][i][1] & (15 << 8)) >> 8; // 4 background bits - if ( m != mode ) { - if ( MouseApp.Modes[mode] ) html += ""; - if ( MouseApp.Modes[m] ) html += "<" + MouseApp.Modes[m] + ">"; - mode = m; - } - if ( ( f != fcolor && f == 0 ) || ( b != bcolor && b == 0 ) ) { - for ( var s = 0; s < spans; s++ ) html += "
                  "; - fcolor = 0; bcolor = 0; - } - if ( f != fcolor ) { - if ( MouseApp.Colors[f] ) { - html += ""; - spans++; - } - fcolor = f; - } - if ( b != bcolor ) { - if ( MouseApp.Colors[b] ) html += ""; - spans++; bcolor = b; - } - html += MouseApp.CharCodes[c] ? MouseApp.CharCodes[c] : String.fromCharCode(c); - } - if ( MouseApp.Modes[mode] ) html += ""; - for ( var s = 0; s < spans; s++ ) html += ""; - var new_id = this.element.attr('id') + '_' + row; - if (!$('#' + new_id).get(0)) { - this.element.append("
                   
                  "); - this.scrollAllTheWayDown(); - } - $('#' + new_id).html(html); - } - }, - - onAfterKey: function() { - this.scrollAllTheWayDown(); - }, - - highlightLine: function(i) { - if (i >= 0 && i < this.screen.length) - { - $("#" + this.element.attr('id') + "_" + i); - } - }, - - scrollToLine: function(i) { - var p = this.element[0].parentNode; - if ( p.scrollHeight > p.clientHeight ) { - p.scrollTop = (p.scrollHeight - p.clientHeight); - } - }, - - scrollAllTheWayDown: function() { - var p = this.element[0].parentNode; - if ( p.scrollHeight > p.clientHeight ) { - p.scrollTop = (p.scrollHeight - p.clientHeight); - } - }, - - putc: function(ch, mode) { - if ( ch == 13 ) { - return; - } else if ( ch == 10 ) { - this.screen[this.rpos][this.cpos] = [ch, mode]; - this.advanceLine(); - } else { - this.screen[this.rpos][this.cpos] = [ch, mode]; - this.paint(this.rpos); - this.advance(); - } - }, - - zpad: function(n) { - if (n < 10) n = "0" + n; - return n; - }, - - puts: function(str, mode) { - if ( !str ) return; - var p = this.painting; - var r = this.rpos; - this.painting = false; - for ( var i = 0; i < str.length; i++ ) { - this.insertc(str.charCodeAt(i), mode); - } - this.painting = p; - this.paint(r, this.rpos); - }, - - advance: function() { - this.cpos++; - if ( this.cpos >= this.options.columns ) { - this.advanceLine(); - } - }, - - advanceLine: function() { - this.cpos = 0; - this.rpos++; - this.ensureRow(this.rpos); - this.paint(this.rpos, this.screen.length - 1); - }, - - fwdc: function() { - var r = this.rpos; - var c = this.cpos; - if ( c < this.options.columns - 1 ) { - c++; - } else if ( r < this.screen.length - 1 ) { - r++; - c = 0; - } - var ch = (c == 0 ? this.screen[r-1][this.options.columns-1] : this.screen[r][c-1]); - if ( MouseApp.isPrintable(ch[0]) ) { - this.rpos = r; - this.cpos = c; - } - }, - - fwdLine: function() { - if ( this.rpos >= this.screen.length - 1 ) return; - this.rpos++; - while ( this.cpos > 0 && !MouseApp.isPrintable(this.screen[this.rpos][this.cpos - 1][0]) ) { - this.cpos--; - } - }, - - backc: function() { - var r = this.rpos; - var c = this.cpos; - if ( c > 0 ) { - c--; - } else if ( r > 0 ) { - c = this.options.columns - 1; - r--; - } - if ( MouseApp.isPrintable(this.screen[r][c][0]) ) { - this.rpos = r; - this.cpos = c; - return true; - } - return false; - }, - - getTypingStart: function() { - var c = this.cpos; - if ( !MouseApp.isPrintable(this.screen[this.rpos][c][0]) ) { - c--; - } - var pos = null; - for ( var r = this.rpos; r >= 0; r-- ) { - while ( c >= 0 ) { - if ( !MouseApp.isPrintable(this.screen[r][c][0]) ) { - return pos; - } - pos = [r, c]; - c--; - } - c = this.options.columns - 1; - } - }, - - getTypingEnd: function(mod) { - var c = this.cpos; - if ( !MouseApp.isPrintable(this.screen[this.rpos][c][0]) ) { - c--; - } - var pos = null; - for ( var r = this.rpos; r < this.screen.length; r++ ) { - while ( c < this.options.columns ) { - if ( !this.screen[r] || !this.screen[r][c] || !MouseApp.isPrintable(this.screen[r][c][0]) ) { - if (!mod) return pos; - mod--; - } - pos = [r, c]; - c++; - } - c = 0; - } - }, - - getTypingAt: function(start, end) { - var r = start[0]; - var c = start[1]; - var str = ''; - while ( r < end[0] || c <= end[1] ) { - if ( c < this.options.columns ) { - str += String.fromCharCode(this.screen[r][c][0]); - c++; - } else { - c = 0; - r++; - } - } - return str; - }, - - ensureRow: function(r) { - if (!this.screen[r]) { - this.screen[r] = this.fillRow(this.options.columns, 0); - } - }, - - insertc: function(ch, mode) { - var r = this.rpos; var c = this.cpos; - var end = this.getTypingEnd(+1); - if (end) { - var thisc = null; - var lastc = this.screen[this.rpos][this.cpos]; - while ( r < end[0] || c <= end[1] ) { - if ( c < this.options.columns ) { - thisc = this.screen[r][c]; - this.screen[r][c] = lastc; - lastc = thisc; - c++; - } else { - c = 0; - r++; - this.ensureRow(r); - } - } - this.paint(this.rpos, end[0]); - } - this.putc(ch, mode); - }, - - delc: function() { - /* end of line */ - if ( MouseApp.isPrintable(this.screen[this.rpos][this.cpos][0]) ) { - var end = this.getTypingEnd(); - var thisc = null; - var lastc = [0, 0]; - while ( this.rpos < end[0] || this.cpos <= end[1] ) { - if ( end[1] >= 0 ) { - thisc = this.screen[end[0]][end[1]]; - this.screen[end[0]][end[1]] = lastc; - lastc = thisc; - end[1]--; - } else { - end[1] = this.options.columns - 1; - this.paint(end[0]); - end[0]--; - } - } - } - }, - - backspace: function() { - /* end of line */ - if ( !MouseApp.isPrintable(this.screen[this.rpos][this.cpos][0]) ) { - this.backc(); - this.screen[this.rpos][this.cpos] = [0, 0]; - } else { - if ( this.backc() ) this.delc(); - } - }, - - backLine: function() { - if ( this.rpos < 1 ) return; - this.rpos--; - while ( this.cpos > 0 && !MouseApp.isPrintable(this.screen[this.rpos][this.cpos - 1][0]) ) { - this.cpos--; - } - }, - - onKeyPress: function(e) { - var ch = e.keyCode; - var key_name = MouseApp.CodeKeys[ch]; - if (window.opera && !e.altKey && e.keyCode != 13 && e.keyCode != 8) key_name = null; - ch = (e.which || e.charCode || e.keyCode); - if (e.which) ch = e.which; - if (!key_name) { key_name = String.fromCharCode(ch); } - if (e.ctrlKey) { key_name = 'Ctrl' + key_name; } - - // alert([e.keyCode, e.which, key_name, this['onKey' + key_name]]); - if (this.typing && this.onAnyKey) this.onAnyKey(key_name); - if (key_name && this['onKey' + key_name]) { - if (this.typing) this['onKey' + key_name](); - MouseApp.Manager.blockEvent(e); - if (this.typing && this.onAfterKey) this.onAfterKey(key_name, true); - return false; - } - if (!e.ctrlKey) { - if (MouseApp.isPrintable(ch)) { - if (this.typing) this.insertc(ch, 0); - MouseApp.Manager.blockEvent(e); - if (this.typing && this.onAfterKey) this.onAfterKey(key_name, true); - return false; - } - } - if (this.typing && this.onAfterKey) this.onAfterKey(key_name, false); - return true; - }, - onKeyHome: function() { - var s = this.getTypingStart(); - this.rpos = s[0]; this.cpos = s[1]; - }, - onKeyEnd: function() { - var e = this.getTypingEnd(+1); - this.rpos = e[0]; this.cpos = e[1]; - }, - onKeyInsert: function() { }, - onKeyDelete: function() { this.delc(); }, - onKeyUp: function() { this.backLine(); }, - onKeyLeft: function() { this.backc(); }, - onKeyRight: function() { this.fwdc(); }, - onKeyDown: function() { this.fwdLine(); }, - onKeyBackspace: function() { this.backspace(); }, - onKeyEnter: function() { this.insertc(10, 0); }, - onKeyTab: function() { - this.insertc(32, 0); - while (this.cpos % this.options.indent != 0) this.insertc(32, 0); - } -}); - -/* Terminal running moush */ -MouseApp.Terminal = function(element, options) { - this.element = $(element); - this.setOptions(options); - this.initWindow(); - this.setup(); -}; - -$.extend(MouseApp.Terminal.prototype, MouseApp.Window.prototype, { - setup: function() { - this.history = []; - this.backupNum = this.historyNum = this.commandNum = 0; - if (this.onStart) { - this.onStart(); - } else { - this.write(this.options.greeting + "\n", true); - this.prompt(); - } - }, - - prompt: function(ps, pt) { - if (!ps) { - ps = this.options.ps; pt = true; - } - this.write(ps, pt); - this.putc(1, 0); - this.typingOn(); - }, - - getCommand: function() { - var s = this.getTypingStart(); - var e = this.getTypingEnd(); - if (!s || !e) return; - return this.getTypingAt(s, e); - }, - - clearCommand: function() { - var s = this.getTypingStart(); - var e = this.getTypingEnd(); - if (!s || !e) return; - var r = s[0]; - var c = s[1]; - this.rpos = r; this.cpos = c; - while ( r < e[0] || c <= e[1] ) { - if ( c < this.options.columns ) { - this.screen[r][c] = [0, 0]; - c++; - } else { - c = 0; - this.paint(r); - r++; - } - } - this.paint(r); - }, - - write: function(str, pcodes) { - var p = this.painting; - var r = this.rpos; - this.painting = false; - var mode = 0; - var today = new Date(); - for ( var i = 0; i < str.length; i++ ) { - if ( str.substr(i,1) == "\n" ) { - this.advanceLine(); - continue; - } else if ( str.substr(i,1) == "\033" ) { - if ( str.substr(i+1,2) == "[m" ) { - mode = 0; - i += 2; - continue; - } - if ( str.substr(i+1,5) == "[0;0m" ) { - mode = 0; - i += 5; - continue; - } - var colors = str.substr(i+1,7).match(/^\[(\d);(\d+)m/); - if ( colors ) { - var colCode = parseInt( colors[2] ); - var color = colCode % 10; - if ( colors[1] == '1' ) { - color += 8; - } - if ( colCode / 10 == 4 ) { - color = color << 4; - } - mode = (mode & 15) + color << 4; - i += colors[0].length; - continue; - } - } else if ( str.substr(i,1) == '%' && pcodes ) { - var s2 = str.substr(i,2); - switch ( s2 ) { - case '%h': - this.puts(this.options.host, mode); - i++; - continue; - case '%l': - this.puts(this.options.name, mode); - i++; - continue; - case '%n': - this.advanceLine(); - i++; - continue; - case '%s': - this.puts("moush", mode); - i++; - continue; - case '%t': - this.puts(this.zpad(today.getHours()) + ":" + this.zpad(today.getMinutes()) + ":" + - this.zpad(today.getSeconds()), mode); - i++; - continue; - case '%u': - this.puts(this.options.user, mode); - i++; - continue; - case '%v': - this.puts(MouseApp.Version, mode); - i++; - continue; - case '%!': - this.puts(this.historyNum.toString(), mode); - i++; - continue; - case '%#': - this.puts(this.commandNum.toString(), mode); - i++; - continue; - case '%+': - var kind = str.substr(i+2, 1); - if ( MouseApp.ModeIds[kind] ) { - mode = mode | MouseApp.ModeIds[kind]; - i += 2; - continue; - } - break; - case '%-': - var kind = str.substr(i+2, 1); - if ( MouseApp.ModeIds[kind] ) { - mode = mode & ( 4095 - MouseApp.ModeIds[kind] ); - i += 2; - continue; - } - break; - } - } - this.putc(str.charCodeAt(i), mode); - } - this.painting = p; - this.paint(r, this.rpos); - }, - - onKeyUp: function() { - if ( this.backupNum == 0 ) return; - if ( this.backupNum == this.historyNum ) { - this.history[this.historyNum] = this.getCommand(); - } - this.clearCommand(); - this.backupNum--; - this.puts(this.history[this.backupNum]); - }, - onKeyDown: function() { - if ( this.backupNum >= this.historyNum ) return; - this.clearCommand(); - this.backupNum++; - this.puts(this.history[this.backupNum]); - }, - onKeyEnter: function() { - var cmd = this.getCommand(); - if (cmd) { - this.history[this.historyNum] = cmd; - this.backupNum = ++this.historyNum; - } - this.commandNum++; - this.advanceLine(); - if (cmd) { - var str = this.onCommand(cmd); - if (str) { - if ( str.substr(str.length - 1, 1) != "\n" ) { - str += "\n"; - } - this.write(str); - } - } - this.prompt(); - }, - onCommand: function(line) { - // this.puts("Echoing: " + line + "\n"); - if ( line == "clear" ) { - this.clear(); - } else { - return "\033[1;37m\033[0;44mYou typed:\033[m " + line; - } - } -}); - -/* Notepad sort of editor */ -MouseApp.Notepad = function(element, options) { - this.element = $(element); - this.setOptions(options); - this.initWindow(); - this.history = []; - this.lineno = 0; -}; - -$.extend(MouseApp.Notepad.prototype, MouseApp.Window.prototype, { - csave: function() { - if ( this.cpos_save ) { - this.cpos = this.cpos_save; - } else { - this.cpos_save = this.cpos; - } - }, - onKeyUp: function() { if ( this.rpos < 1 ) { return; } this.csave(); this.backLine(); }, - onKeyDown: function() { if ( this.rpos < this.screen.length - 1 ) { this.csave(); this.fwdLine(); } }, - onAfterKey: function(key, st) { - if ( st && !(key == 'Up' || key == 'Down') ) { - this.cpos_save = null; - } - }, - insertc: function(ch, mode) { - if (ch == 10) { - this.element.append("
                   
                  "); - this.screen.splice(this.rpos + 1, 0, this.fillRow(this.options.columns, 0)); - var c = this.cpos; var c2 = 0; - while (c < this.options.columns) - { - if (this.screen[this.rpos][c] == 0) break; - this.screen[this.rpos + 1][c2] = this.screen[this.rpos][c]; - this.screen[this.rpos][c] = [0, 0]; - c++; c2++; - } - this.paint(this.rpos); - if (MouseApp.isPrintable(this.screen[this.rpos][c])) - { - var r = this.rpos; var c = this.cpos; - this.rpos += 1; this.cpos = c2; - this.delc(); - this.rpos = r; this.cpos = c; - } - this.putc(ch, mode); - if (this.rpos == this.screen.length - 1) - this.scrollAllTheWayDown(); - } else { - var c = this.cpos + 1; - var lastc = this.screen[this.rpos][this.cpos]; - this.putc(ch, mode); - for ( var r = this.rpos; r < this.screen.length; r++ ) { - while (c < this.options.columns) - { - var tmpc = this.screen[r][c]; - if (lastc[0] == 0) - break; - this.screen[r][c] = lastc; - lastc = tmpc; - c++; - } - if (c < this.options.columns) { - break; - } - c = 0; - } - } - }, - - backc: function() { - var r = this.rpos; - var c = this.cpos - 1; - for ( var r = this.rpos; r >= 0; r-- ) { - while ( c >= 0 ) { - this.rpos = r; - this.cpos = c; - if ( this.screen[r][c][0] != 0 ) { - this.paint(r); - return true; - } - this.screen[r][c] = [0, 0]; - c--; - } - c = this.options.columns - 1; - } - return false; - }, - delc: function() { - var c = this.cpos + 1; - for ( var r = this.rpos; r < this.screen.length; r++ ) { - while ( c < this.options.columns ) { - if ( this.screen[r][c][0] != 0 ) { - break; - } - c++; - } - if ( c < this.options.columns ) break; - c = 0; - } - - if (r >= this.screen.length) return; - - var r2 = this.rpos; - var c2 = this.cpos; - for ( var r2 = this.rpos; r2 < this.screen.length; r2++ ) { - while (c2 < this.options.columns) - { - if (this.screen[r][c][0] == 0) - break; - this.screen[r2][c2] = this.screen[r][c]; - c2++; - c++; - if (c >= this.options.columns) { - r++; - if (r >= this.options.rows) break; - c = 0; - } - } - if (c2 < this.options.columns) { - while (c2 < this.options.columns) { - this.screen[r2][c2] = [0, 0]; - c2++; - } - break; - } - c2 = 0; - } - - if (r != r2 && r < this.screen.length) - { - this.screen.splice(r, 1); - $("#" + this.element.attr('id') + "_" + this.screen.length).remove(); - } - this.paint(this.rpos, this.screen.length); - }, - onKeyBackspace: function() { - if (this.backc()) this.delc(); - } - -}); diff --git a/non-rack-legacy/public/javascripts/mouseirb_2.js b/non-rack-legacy/public/javascripts/mouseirb_2.js deleted file mode 100755 index 0fa5f12..0000000 --- a/non-rack-legacy/public/javascripts/mouseirb_2.js +++ /dev/null @@ -1,179 +0,0 @@ -// -// Copyright (c) 2008 why the lucky stiff -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, -// and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT -// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -/* Irb running moush */ -MouseApp.Irb = function(element, options) { - this.element = $(element); - this.setOptions(options); - this.showHelp = this.options.showHelp; - if ( this.options.showChapter ) { - this.showChapter = this.options.showChapter; - } - if ( this.options.init ) { - this.init = this.options.init; - } - this.initWindow(); - this.setup(); - this.helpPage = null; - this.irbInit = false; -}; - -$.extend(MouseApp.Irb.prototype, MouseApp.Terminal.prototype, { - cmdToQuery: function(cmd) { - return "cmd=" + escape(cmd.replace(/</g, '<').replace(/>/g, '>'). - replace(/&/g, '&').replace(/\r?\n/g, "\n")).replace(/\+/g, "%2B"); - }, - - fireOffCmd: function(cmd, func) { - var irb = this; - if (!this.irbInit) - { - $.ajax({url: this.options.irbUrl + "?" + this.cmdToQuery("!INIT!IRB!"), type: "GET", - complete: (function(r) { irb.irbInit = true; irb.fireOffCmd(cmd, func); })}); - } - else - { - $.ajax({url: this.options.irbUrl + "?" + this.cmdToQuery(cmd), type: "GET", - complete: func}); - } - }, - - reply: function(str) { - var raw = str.replace(/\033\[(\d);(\d+)m/g, ''); - this.checkAnswer(raw); - if (!str.match(/^(\.\.)+$/)) { - if ( str[str.length - 1] != "\n" ) { - str += "\n"; - } - js_payload = /\033\[1;JSm(.*)\033\[m/; - js_in = str.match(js_payload); - if (js_in) { - try { - js_in = eval(js_in[1]); - } catch (e) {} - str = str.replace(js_payload, ''); - } - var pr_re = new RegExp("(^|\\n)=>"); - if ( str.match( pr_re ) ) { - str = str.replace(new RegExp("(^|\\n)=>"), "$1\033[1;34m=>\033[m"); - } else { - str = str.replace(new RegExp("(^|\\n)= (.+?) ="), "$1\033[1;33m$2\033[m"); - } - this.write(str); - this.prompt(); - } else { - this.prompt("\033[1;32m" + ".." + "\033[m", true); - this.puts(str.replace(/\./g, ' '), 0); - } - }, - - setHelpPage: function(n, page) { - if (this.helpPage) - $(this.helpPage.ele).hide('fast'); - this.helpPage = {index: n, ele: page}; - match = this.scanHelpPageFor('load'); - if (match != -1) - { - this.fireOffCmd(match, (function(r) { - $(page).show('fast'); - })); - } - else - { - $(page).show('fast'); - } - }, - - scanHelpPageFor: function(eleClass) { - match = $("div." + eleClass, this.helpPage.ele); - if ( match[0] ) return match[0].innerHTML; - else return -1; - }, - - checkAnswer: function(str) { - if ( this.helpPage ) { - match = this.scanHelpPageFor('answer'); - if ( match != -1 ) { - if ( str.match( new RegExp('^\s*=> ' + match + '\s*$', 'm') ) ) { - this.showHelp(this.helpPage.index + 1); - } - } else { - match = this.scanHelpPageFor('stdout'); - if ( match != -1 ) { - if ( match == '' ) { - if ( str == '' || str == null ) this.showHelp(this.helpPage.index + 1); - } else if ( str.match( new RegExp('^\s*' + match + '$', 'm') ) ) { - this.showHelp(this.helpPage.index + 1); - } - } - } - } - }, - - onKeyCtrld: function() { - this.clearCommand(); - this.puts("reset"); - this.onKeyEnter(); - }, - - onKeyEnter: function() { - this.typingOff(); - var cmd = this.getCommand(); - if (cmd) { - this.history[this.historyNum] = cmd; - this.backupNum = ++this.historyNum; - } - this.commandNum++; - this.advanceLine(); - if (cmd) { - if ( cmd == "clear" ) { - this.clear(); - this.prompt(); - } else if ( cmd.match(/^(back)$/) ) { - if (this.helpPage && this.helpPage.index >= 1) { - this.showHelp(this.helpPage.index - 1); - } - this.prompt(); - } else if ( cmd.match(/^(next)$/) ) { - if (this.helpPage) { - this.showHelp(this.helpPage.index + 1); - } - this.prompt(); - } else if ( cmd.match(/^(help|wtf\?*)$/) ) { - this.showHelp(1); - this.prompt(); - } else if ( regs = cmd.match(/^(help|wtf\?*)\s+#?(\d+)\s*$/) ) { - this.showChapter(parseInt(regs[2])); - this.prompt(); - } else { - var term = this; - this.fireOffCmd(cmd, (function(r) { term.reply(r.responseText ? r.responseText : ''); })); - } - } else { - this.prompt(); - } - } -}); - diff --git a/non-rack-legacy/public/javascripts/raphael-min.js b/non-rack-legacy/public/javascripts/raphael-min.js deleted file mode 100644 index 4a99e3e..0000000 --- a/non-rack-legacy/public/javascripts/raphael-min.js +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Raphael 1.4.3 - JavaScript Vector Library - * - * Copyright (c) 2010 Dmitry Baranovskiy (http://raphaeljs.com) - * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. - */ -Raphael=function(){function m(){if(m.is(arguments[0],U)){for(var a=arguments[0],b=Aa[K](m,a.splice(0,3+m.is(a[0],O))),c=b.set(),d=0,f=a[o];d

                  ";if(ha.childNodes[o]!=2)return m.type=null;ha=null}m.svg=!(m.vml=m.type=="VML");G[p]=m[p];m._id=0;m._oid=0;m.fn={};m.is=function(a,b){b=ca.call(b);return b=="object"&&a===Object(a)||b=="undefined"&&typeof a==b||b=="null"&&a==null||ca.call(ob.call(a).slice(8,-1))==b};m.setWindow=function(a){X=a;C=X.document};function ra(a){if(m.vml){var b=/^\s+|\s+$/g;ra=T(function(d){var f;d=(d+s)[I](b, -s);try{var e=new X.ActiveXObject("htmlfile");e.write("");e.close();f=e.body}catch(g){f=X.createPopup().document.body}e=f.createTextRange();try{f.style.color=d;var h=e.queryCommandValue("ForeColor");h=(h&255)<<16|h&65280|(h&16711680)>>>16;return"#"+("000000"+h[N](16)).slice(-6)}catch(i){return"none"}})}else{var c=C.createElement("i");c.title="Rapha\u00ebl Colour Picker";c.style.display="none";C.body[y](c);ra=T(function(d){c.style.color=d;return C.defaultView.getComputedStyle(c,s).getPropertyValue("color")})}return ra(a)} -function qb(){return"hsb("+[this.h,this.s,this.b]+")"}function rb(){return this.hex}m.hsb2rgb=T(function(a,b,c){if(m.is(a,"object")&&"h"in a&&"s"in a&&"b"in a){c=a.b;b=a.s;a=a.h}var d;if(c==0)return{r:0,g:0,b:0,hex:"#000"};if(a>1||b>1||c>1){a/=255;b/=255;c/=255}d=~~(a*6);a=a*6-d;var f=c*(1-b),e=c*(1-b*a),g=c*(1-b*(1-a));a=[c,e,f,f,g,c,c][d];b=[g,c,c,e,f,f,g][d];d=[f,f,g,c,c,e,f][d];a*=255;b*=255;d*=255;c={r:a,g:b,b:d,toString:rb};a=(~~a)[N](16);b=(~~b)[N](16);d=(~~d)[N](16);a=a[I](ga,"0");b=b[I](ga, -"0");d=d[I](ga,"0");c.hex="#"+a+b+d;return c},m);m.rgb2hsb=T(function(a,b,c){if(m.is(a,"object")&&"r"in a&&"g"in a&&"b"in a){c=a.b;b=a.g;a=a.r}if(m.is(a,ea)){var d=m.getRGB(a);a=d.r;b=d.g;c=d.b}if(a>1||b>1||c>1){a/=255;b/=255;c/=255}var f=Y(a,b,c),e=$(a,b,c);d=f;if(e==f)return{h:0,s:0,b:f};else{var g=f-e;e=g/f;a=a==f?(b-c)/g:b==f?2+(c-a)/g:4+(a-b)/g;a/=6;a<0&&a++;a>1&&a--}return{h:a,s:e,b:d,toString:qb}},m);var sb=/,?([achlmqrstvxz]),?/gi,sa=/\s*,\s*/,tb={hs:1,rg:1};m._path2string=function(){return this.join(",")[I](sb, -"$1")};function T(a,b,c){function d(){var f=Array[p].slice.call(arguments,0),e=f[Q]("\u25ba"),g=d.cache=d.cache||{},h=d.count=d.count||[];if(g[z](e))return c?c(g[e]):g[e];h[o]>=1000&&delete g[h.shift()];h[E](e);g[e]=a[K](b,f);return c?c(g[e]):g[e]}return d}m.getRGB=T(function(a){if(!a||(a+=s).indexOf("-")+1)return{r:-1,g:-1,b:-1,hex:"none",error:1};if(a=="none")return{r:-1,g:-1,b:-1,hex:"none"};!(tb[z](a.substring(0,2))||a.charAt()=="#")&&(a=ra(a));var b,c,d,f,e;if(a=a.match(pb)){if(a[2]){d=da(a[2].substring(5), -16);c=da(a[2].substring(3,5),16);b=da(a[2].substring(1,3),16)}if(a[3]){d=da((e=a[3].charAt(3))+e,16);c=da((e=a[3].charAt(2))+e,16);b=da((e=a[3].charAt(1))+e,16)}if(a[4]){a=a[4][H](sa);b=A(a[0]);c=A(a[1]);d=A(a[2]);f=A(a[3])}if(a[5]){a=a[5][H](sa);b=A(a[0])*2.55;c=A(a[1])*2.55;d=A(a[2])*2.55;f=A(a[3])}if(a[6]){a=a[6][H](sa);b=A(a[0]);c=A(a[1]);d=A(a[2]);return m.hsb2rgb(b,c,d)}if(a[7]){a=a[7][H](sa);b=A(a[0])*2.55;c=A(a[1])*2.55;d=A(a[2])*2.55;return m.hsb2rgb(b,c,d)}a={r:b,g:c,b:d};b=(~~b)[N](16); -c=(~~c)[N](16);d=(~~d)[N](16);b=b[I](ga,"0");c=c[I](ga,"0");d=d[I](ga,"0");a.hex="#"+b+c+d;isFinite(A(f))&&(a.o=f);return a}return{r:-1,g:-1,b:-1,hex:"none",error:1}},m);m.getColor=function(a){a=this.getColor.start=this.getColor.start||{h:0,s:1,b:a||0.75};var b=this.hsb2rgb(a.h,a.s,a.b);a.h+=0.075;if(a.h>1){a.h=0;a.s-=0.2;a.s<=0&&(this.getColor.start={h:0,s:1,b:a.b})}return b.hex};m.getColor.reset=function(){delete this.start};var ub=/([achlmqstvz])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig, -vb=/(-?\d*\.?\d*(?:e[-+]?\d+)?)\s*,?\s*/ig;m.parsePathString=T(function(a){if(!a)return null;var b={a:7,c:6,h:1,l:2,m:2,q:4,s:4,t:2,v:1,z:0},c=[];if(m.is(a,U)&&m.is(a[0],U))c=ta(a);c[o]||(a+s)[I](ub,function(d,f,e){var g=[];d=ca.call(f);e[I](vb,function(h,i){i&&g[E](+i)});if(d=="m"&&g[o]>2){c[E]([f][M](g.splice(0,2)));d="l";f=f=="m"?"l":"L"}for(;g[o]>=b[d];){c[E]([f][M](g.splice(0,b[d])));if(!b[d])break}});c[N]=m._path2string;return c});m.findDotsAtSegment=function(a,b,c,d,f,e,g,h,i){var j=1-i,l= -D(j,3)*a+D(j,2)*3*i*c+j*3*i*i*f+D(i,3)*g;j=D(j,3)*b+D(j,2)*3*i*d+j*3*i*i*e+D(i,3)*h;var n=a+2*i*(c-a)+i*i*(f-2*c+a),r=b+2*i*(d-b)+i*i*(e-2*d+b),q=c+2*i*(f-c)+i*i*(g-2*f+c),k=d+2*i*(e-d)+i*i*(h-2*e+d);a=(1-i)*a+i*c;b=(1-i)*b+i*d;f=(1-i)*f+i*g;e=(1-i)*e+i*h;h=90-w.atan((n-q)/(r-k))*180/w.PI;(n>q||r1){B=w.sqrt(B);c=B*c;d=B*d}B=c*c;var L=d*d;B=(e==g?-1:1)*w.sqrt(w.abs((B*L-B*x*x-L*k*k)/(B*x*x+L*k*k)));e=B*c*x/d+(a+h)/2;var B= -B*-d*k/c+(b+i)/2,x=w.asin(((b-B)/d).toFixed(7));k=w.asin(((i-B)/d).toFixed(7));x=ak)x-=l*2;if(!g&&k>x)k-=l*2}l=k-x;if(w.abs(l)>n){q=k;l=h;L=i;k=x+n*(g&&k>x?1:-1);h=e+c*w.cos(k);i=B+d*w.sin(k);q=Qa(h,i,c,d,f,0,g,l,L,[k,q,e,B])}l=k-x;f=w.cos(x);e=w.sin(x);g=w.cos(k);k=w.sin(k);l=w.tan(l/4);c=4/3*c*l;l=4/3*d*l;d=[a,b];a=[a+c*e,b-l*f];b=[h+c*k,i-l*g];h=[h,i];a[0]=2*d[0]-a[0];a[1]=2*d[1]-a[1];if(j)return[a,b,h][M](q);else{q=[a,b,h][M](q)[Q]()[H](","); -j=[];h=0;for(i=q[o];h1000000000000&&(n=0.5);w.abs(i)>1000000000000&&(i=0.5);if(n>0&&n<1){n=la(a,b,c,d,f,e,g,h,n);q[E](n.x);r[E](n.y)}if(i> -0&&i<1){n=la(a,b,c,d,f,e,g,h,i);q[E](n.x);r[E](n.y)}i=e-2*d+b-(h-2*e+d);j=2*(d-b)-2*(e-d);l=b-d;n=(-j+w.sqrt(j*j-4*i*l))/2/i;i=(-j-w.sqrt(j*j-4*i*l))/2/i;w.abs(n)>1000000000000&&(n=0.5);w.abs(i)>1000000000000&&(i=0.5);if(n>0&&n<1){n=la(a,b,c,d,f,e,g,h,n);q[E](n.x);r[E](n.y)}if(i>0&&i<1){n=la(a,b,c,d,f,e,g,h,i);q[E](n.x);r[E](n.y)}return{min:{x:$[K](0,q),y:$[K](0,r)},max:{x:Y[K](0,q),y:Y[K](0,r)}}}),ua=T(function(a,b){var c=ka(a),d=b&&ka(b);a={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null};b={x:0,y:0, -bx:0,by:0,X:0,Y:0,qx:null,qy:null};function f(q,k){var t;if(!q)return["C",k.x,k.y,k.x,k.y,k.x,k.y];!(q[0]in{T:1,Q:1})&&(k.qx=k.qy=null);switch(q[0]){case "M":k.X=q[1];k.Y=q[2];break;case "A":q=["C"][M](Qa[K](0,[k.x,k.y][M](q.slice(1))));break;case "S":t=k.x+(k.x-(k.bx||k.x));k=k.y+(k.y-(k.by||k.y));q=["C",t,k][M](q.slice(1));break;case "T":k.qx=k.x+(k.x-(k.qx||k.x));k.qy=k.y+(k.y-(k.qy||k.y));q=["C"][M](Pa(k.x,k.y,k.qx,k.qy,q[1],q[2]));break;case "Q":k.qx=q[1];k.qy=q[2];q=["C"][M](Pa(k.x,k.y,q[1], -q[2],q[3],q[4]));break;case "L":q=["C"][M](wa(k.x,k.y,q[1],q[2]));break;case "H":q=["C"][M](wa(k.x,k.y,q[1],k.y));break;case "V":q=["C"][M](wa(k.x,k.y,k.x,q[1]));break;case "Z":q=["C"][M](wa(k.x,k.y,k.X,k.Y));break}return q}function e(q,k){if(q[k][o]>7){q[k].shift();for(var t=q[k];t[o];)q.splice(k++,0,["C"][M](t.splice(0,6)));q.splice(k,1);i=Y(c[o],d&&d[o]||0)}}function g(q,k,t,L,B){if(q&&k&&q[B][0]=="M"&&k[B][0]!="M"){k.splice(B,0,["M",L.x,L.y]);t.bx=0;t.by=0;t.x=q[B][1];t.y=q[B][2];i=Y(c[o],d&& -d[o]||0)}}for(var h=0,i=Y(c[o],d&&d[o]||0);h0.5)*2-1;D(f-0.5,2)+D(e-0.5,2)>0.25&&(e=w.sqrt(0.25-D(f-0.5,2))*l+0.5)&&e!=0.5&&(e=e.toFixed(5)-1.0E-5*l)}return s});b=b[H](/\s*\-\s*/);if(d=="linear"){var h=b.shift();h=-A(h);if(isNaN(h))return null;h=[0,0,w.cos(h*w.PI/180),w.sin(h*w.PI/180)];var i=1/(Y(w.abs(h[2]),w.abs(h[3]))||1);h[2]*=i;h[3]*=i;if(h[2]<0){h[0]=-h[2];h[2]=0}if(h[3]<0){h[1]=-h[3];h[3]=0}}b=Ra(b);if(!b)return null; -i=a.getAttribute(aa);(i=i.match(/^url\(#(.*)\)$/))&&c.defs.removeChild(C.getElementById(i[1]));i=v(d+"Gradient");i.id="r"+(m._id++)[N](36);v(i,d=="radial"?{fx:f,fy:e}:{x1:h[0],y1:h[1],x2:h[2],y2:h[3]});c.defs[y](i);c=0;for(h=b[o];cb.height&&(b.height=e.y+e.height-b.y);e.x+e.width-b.x>b.width&&(b.width=e.x+e.width-b.x)}}a&&this.hide();return b};u[p].attr=function(a,b){if(this.removed)return this;if(a==null){a={};for(var c in this.attrs)if(this.attrs[z](c))a[c]=this.attrs[c];this._.rt.deg&&(a.rotation=this.rotate());(this._.sx!=1||this._.sy!= -1)&&(a.scale=this.scale());a.gradient&&a.fill=="none"&&(a.fill=a.gradient)&&delete a.gradient;return a}if(b==null&&m.is(a,ea)){if(a=="translation")return ya.call(this);if(a=="rotation")return this.rotate();if(a=="scale")return this.scale();if(a==aa&&this.attrs.fill=="none"&&this.attrs.gradient)return this.attrs.gradient;return this.attrs[a]}if(b==null&&m.is(a,U)){b={};c=0;for(var d=a.length;c1&&(a=1);f.opacity=a}b.fill&&(f.on=true);if(f.on==null||b.fill=="none")f.on=false;if(f.on&&b.fill)if(a=b.fill.match(Na)){f.src=a[1];f.type="tile"}else{f.color=m.getRGB(b.fill).hex;f.src= -s;f.type="solid";if(m.getRGB(b.fill).error&&(g.type in{circle:1,ellipse:1}||(b.fill+s).charAt()!="r")&&ma(g,b.fill)){d.fill="none";d.gradient=b.fill}}e&&c[y](f);f=c.getElementsByTagName("stroke")&&c.getElementsByTagName("stroke")[0];e=false;!f&&(e=f=R("stroke"));if(b.stroke&&b.stroke!="none"||b["stroke-width"]||b["stroke-opacity"]!=null||b["stroke-dasharray"]||b["stroke-miterlimit"]||b["stroke-linejoin"]||b["stroke-linecap"])f.on=true;(b.stroke=="none"||f.on==null||b.stroke==0||b["stroke-width"]== -0)&&(f.on=false);a=m.getRGB(b.stroke);f.on&&b.stroke&&(f.color=a.hex);a=((+d["stroke-opacity"]+1||2)-1)*((+d.opacity+1||2)-1)*((+a.o+1||2)-1);h=(A(b["stroke-width"])||1)*0.75;a<0&&(a=0);a>1&&(a=1);b["stroke-width"]==null&&(h=d["stroke-width"]);b["stroke-width"]&&(f.weight=h);h&&h<1&&(a*=h)&&(f.weight=1);f.opacity=a;b["stroke-linejoin"]&&(f.joinstyle=b["stroke-linejoin"]||"miter");f.miterlimit=b["stroke-miterlimit"]||8;b["stroke-linecap"]&&(f.endcap=b["stroke-linecap"]=="butt"?"flat":b["stroke-linecap"]== -"square"?"square":"round");if(b["stroke-dasharray"]){a={"-":"shortdash",".":"shortdot","-.":"shortdashdot","-..":"shortdashdotdot",". ":"dot","- ":"dash","--":"longdash","- .":"dashdot","--.":"longdashdot","--..":"longdashdotdot"};f.dashstyle=a[z](b["stroke-dasharray"])?a[b["stroke-dasharray"]]:s}e&&c[y](f)}if(g.type=="text"){f=g.paper.span.style;d.font&&(f.font=d.font);d["font-family"]&&(f.fontFamily=d["font-family"]);d["font-size"]&&(f.fontSize=d["font-size"]);d["font-weight"]&&(f.fontWeight=d["font-weight"]); -d["font-style"]&&(f.fontStyle=d["font-style"]);g.node.string&&(g.paper.span.innerHTML=(g.node.string+s)[I](/"));g.W=d.w=g.paper.span.offsetWidth;g.H=d.h=g.paper.span.offsetHeight;g.X=d.x;g.Y=d.y+F(g.H/2);switch(d["text-anchor"]){case "start":g.node.style["v-text-align"]="left";g.bbx=F(g.W/2);break;case "end":g.node.style["v-text-align"]="right";g.bbx=-F(g.W/2);break;default:g.node.style["v-text-align"]="center";break}}};ma=function(a,b){a.attrs=a.attrs|| -{};var c="linear",d=".5 .5";a.attrs.gradient=b;b=(b+s)[I](Ya,function(i,j,l){c="radial";if(j&&l){j=A(j);l=A(l);D(j-0.5,2)+D(l-0.5,2)>0.25&&(l=w.sqrt(0.25-D(j-0.5,2))*((l>0.5)*2-1)+0.5);d=j+P+l}return s});b=b[H](/\s*\-\s*/);if(c=="linear"){var f=b.shift();f=-A(f);if(isNaN(f))return null}var e=Ra(b);if(!e)return null;a=a.shape||a.node;b=a.getElementsByTagName(aa)[0]||R(aa);!b.parentNode&&a.appendChild(b);if(e[o]){b.on=true;b.method="none";b.color=e[0].color;b.color2=e[e[o]-1].color;a=[];for(var g=0, -h=e[o];g')}}catch(Kb){R=function(a){return C.createElement("<"+a+' xmlns="urn:schemas-microsoft.com:vml" class="rvml">')}}Aa=function(){var a=Sa[K](0,arguments),b=a.container,c=a.height,d=a.width,f=a.x;a=a.y;if(!b)throw new Error("VML container not found.");var e=new G,g=e.canvas=C.createElement("div"),h=g.style;f=f||0;a=a||0;d=d||512; -c=c||342;d==+d&&(d+="px");c==+c&&(c+="px");e.width=1000;e.height=1000;e.coordsize=ja*1000+P+ja*1000;e.coordorigin="0 0";e.span=C.createElement("span");e.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";g[y](e.span);h.cssText=m.format("width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden",d,c);if(b==1){C.body[y](g);h.left=f+"px";h.top=a+"px";h.position="absolute"}else b.firstChild?b.insertBefore(g, -b.firstChild):b[y](g);Fa.call(e,e,m.fn);return e};G[p].clear=function(){this.canvas.innerHTML=s;this.span=C.createElement("span");this.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";this.canvas[y](this.span);this.bottom=this.top=null};G[p].remove=function(){this.canvas.parentNode.removeChild(this.canvas);for(var a in this)this[a]=Xa(a);return true}}G[p].safari=/^Apple|^Google/.test(X.navigator.vendor)&&(!(X.navigator.userAgent.indexOf("Version/4.0")+ -1)||X.navigator.platform.slice(0,2)=="iP")?function(){var a=this.rect(-99,-99,this.width+99,this.height+99);X.setTimeout(function(){a.remove()})}:function(){};function Db(){this.returnValue=false}function Eb(){return this.originalEvent.preventDefault()}function Fb(){this.cancelBubble=true}function Gb(){return this.originalEvent.stopPropagation()}var Hb=function(){if(C.addEventListener)return function(a,b,c,d){var f=Ba&&Ca[b]?Ca[b]:b;function e(g){if(Ba&&Ca[z](b))for(var h=0,i=g.targetTouches&&g.targetTouches.length;h< -i;h++)if(g.targetTouches[h].target==a){i=g;g=g.targetTouches[h];g.originalEvent=i;g.preventDefault=Eb;g.stopPropagation=Gb;break}return c.call(d,g)}a.addEventListener(f,e,false);return function(){a.removeEventListener(f,e,false);return true}};else if(C.attachEvent)return function(a,b,c,d){function f(g){g=g||X.event;g.preventDefault=g.preventDefault||Db;g.stopPropagation=g.stopPropagation||Fb;return c.call(d,g)}a.attachEvent("on"+b,f);function e(){a.detachEvent("on"+b,f);return true}return e}}();for(ha= -Ma[o];ha--;)(function(a){m[a]=u[p][a]=function(b){if(m.is(b,"function")){this.events=this.events||[];this.events.push({name:a,f:b,unbind:Hb(this.shape||this.node||C,a,b,this)})}return this};m["un"+a]=u[p]["un"+a]=function(b){for(var c=this.events,d=c[o];d--;)if(c[d].name==a&&c[d].f==b){c[d].unbind();c.splice(d,1);!c.length&&delete this.events;return this}return this}})(Ma[ha]);u[p].hover=function(a,b){return this.mouseover(a).mouseout(b)};u[p].unhover=function(a,b){return this.unmouseover(a).unmouseout(b)}; -u[p].drag=function(a,b,c){this._drag={};var d=this.mousedown(function(g){(g.originalEvent?g.originalEvent:g).preventDefault();this._drag.x=g.clientX;this._drag.y=g.clientY;this._drag.id=g.identifier;b&&b.call(this,g.clientX,g.clientY);Raphael.mousemove(f).mouseup(e)});function f(g){var h=g.clientX,i=g.clientY;if(Ba)for(var j=g.touches.length,l;j--;){l=g.touches[j];if(l.identifier==d._drag.id){h=l.clientX;i=l.clientY;(g.originalEvent?g.originalEvent:g).preventDefault();break}}else g.preventDefault(); -a&&a.call(d,h-d._drag.x,i-d._drag.y,h,i)}function e(){d._drag={};Raphael.unmousemove(f).unmouseup(e);c&&c.call(d)}return this};G[p].circle=function(a,b,c){return ab(this,a||0,b||0,c||0)};G[p].rect=function(a,b,c,d,f){return bb(this,a||0,b||0,c||0,d||0,f||0)};G[p].ellipse=function(a,b,c,d){return cb(this,a||0,b||0,c||0,d||0)};G[p].path=function(a){a&&!m.is(a,ea)&&!m.is(a[0],U)&&(a+=s);return Za(m.format[K](m,arguments),this)};G[p].image=function(a,b,c,d,f){return db(this,a||"about:blank",b||0,c||0, -d||0,f||0)};G[p].text=function(a,b,c){return eb(this,a||0,b||0,c||s)};G[p].set=function(a){arguments[o]>1&&(a=Array[p].splice.call(arguments,0,arguments[o]));return new Z(a)};G[p].setSize=fb;G[p].top=G[p].bottom=null;G[p].raphael=m;function ib(){return this.x+P+this.y}u[p].resetScale=function(){if(this.removed)return this;this._.sx=1;this._.sy=1;this.attrs.scale="1 1"};u[p].scale=function(a,b,c,d){if(this.removed)return this;if(a==null&&b==null)return{x:this._.sx,y:this._.sy,toString:ib};b=b||a;!+b&& -(b=a);var f,e,g=this.attrs;if(a!=0){var h=this.getBBox(),i=h.x+h.width/2,j=h.y+h.height/2;f=a/this._.sx;e=b/this._.sy;c=+c||c==0?c:i;d=+d||d==0?d:j;h=~~(a/w.abs(a));var l=~~(b/w.abs(b)),n=this.node.style,r=c+(i-c)*f;j=d+(j-d)*e;switch(this.type){case "rect":case "image":var q=g.width*h*f,k=g.height*l*e;this.attr({height:k,r:g.r*$(h*f,l*e),width:q,x:r-q/2,y:j-k/2});break;case "circle":case "ellipse":this.attr({rx:g.rx*h*f,ry:g.ry*l*e,r:g.r*$(h*f,l*e),cx:r,cy:j});break;case "text":this.attr({x:r,y:j}); -break;case "path":i=Oa(g.path);for(var t=true,L=0,B=i[o];L=i)return r;l=r}});function Ha(a,b){return function(c,d,f){c=ua(c); -for(var e,g,h,i,j="",l={},n=0,r=0,q=c.length;rd){if(b&&!l.start){e=jb(e,g,h[1],h[2],h[3],h[4],h[5],h[6],d-n);j+=["C",e.start.x,e.start.y,e.m.x,e.m.y,e.x,e.y];if(f)return j;l.start=j;j=["M",e.x,e.y+"C",e.n.x,e.n.y,e.end.x,e.end.y,h[5],h[6]][Q]();n+=i;e=+h[5];g=+h[6];continue}if(!a&&!b){e=jb(e,g,h[1],h[2],h[3],h[4],h[5],h[6],d-n);return{x:e.x,y:e.y,alpha:e.alpha}}}n+=i;e=+h[5];g=+h[6]}j+=h}l.end=j;e=a?n: -b?l:m.findDotsAtSegment(e,g,h[1],h[2],h[3],h[4],h[5],h[6],1);e.alpha&&(e={x:e.x,y:e.y,alpha:e.alpha});return e}}var Ib=T(function(a,b,c,d,f,e,g,h){for(var i={x:0,y:0},j=0,l=0;l<1.01;l+=0.01){var n=la(a,b,c,d,f,e,g,h,l);l&&(j+=D(D(i.x-n.x,2)+D(i.y-n.y,2),0.5));i=n}return j}),kb=Ha(1),za=Ha(),Ia=Ha(0,1);u[p].getTotalLength=function(){if(this.type=="path"){if(this.node.getTotalLength)return this.node.getTotalLength();return kb(this.attrs.path)}};u[p].getPointAtLength=function(a){if(this.type=="path")return za(this.attrs.path, -a)};u[p].getSubpath=function(a,b){if(this.type=="path"){if(w.abs(this.getTotalLength()-b)<1.0E-6)return Ia(this.attrs.path,a).end;b=Ia(this.attrs.path,b,1);return a?Ia(b,a).end:b}};m.easing_formulas={linear:function(a){return a},"<":function(a){return D(a,3)},">":function(a){return D(a-1,3)+1},"<>":function(a){a*=2;if(a<1)return D(a,3)/2;a-=2;return(D(a,3)+2)/2},backIn:function(a){var b=1.70158;return a*a*((b+1)*a-b)},backOut:function(a){a-=1;var b=1.70158;return a*a*((b+1)*a+b)+1},elastic:function(a){if(a== -0||a==1)return a;var b=0.3,c=b/4;return D(2,-10*a)*w.sin((a-c)*2*w.PI/b)+1},bounce:function(a){var b=7.5625,c=2.75;if(a<1/c)a=b*a*a;else if(a<2/c){a-=1.5/c;a=b*a*a+0.75}else if(a<2.5/c){a-=2.25/c;a=b*a*a+0.9375}else{a-=2.625/c;a=b*a*a+0.984375}return a}};var S={length:0};function lb(){var a=+new Date;for(var b in S)if(b!="length"&&S[z](b)){var c=S[b];if(c.stop||c.el.removed){delete S[b];S[o]--}else{var d=a-c.start,f=c.ms,e=c.easing,g=c.from,h=c.diff,i=c.to,j=c.t,l=c.prev||0,n=c.el,r=c.callback,q= -{},k;if(d - - - - -

                  you shouldn't be here.. kicking you out!

                  - - diff --git a/non-rack-legacy/public/js/irb.js b/non-rack-legacy/public/js/irb.js deleted file mode 100755 index 23d83df..0000000 --- a/non-rack-legacy/public/js/irb.js +++ /dev/null @@ -1,110 +0,0 @@ -// -// Copyright (c) 2008 why the lucky stiff -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, -// and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT -// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -var allStretch; -var helpPages; -var chapPages; -var defaultPage; -var toot = window.location.search.substr(1) - -//the main function, call to the effect object -function dumpAlert(obj) { - props = []; - for ( var i in obj ) { - props.push( "" + i + ": " + obj[i] ); - } - alert( props ); -} -window.onload = function() { - defaultPage = $('#helpstone .stretcher').html(); - - window.irb = new MouseApp.Irb('#irb', { - rows: 13, - name: 'IRB', - greeting: "%+r Interactive ruby ready. %-r", - ps: '\033[1;31m>>\033[m', - user: 'guest', - host: 'tryruby', - // original: irbUrl: '/irb', - irbUrl: '/irb.cgi', - init: function () { - helpPages = $(".stretcher"); - chapPages = new Array(); - for (var i = 0; i < helpPages.length; i++ ) { - var cls = helpPages[i].className.split(' '); - for (var j = 0; j < cls.length; j++) { - if (cls[j] == 'chapmark') { - chapPages.push([i, helpPages[i]]); - break; - } - } - } - }, - loadTutorial: function (id, instruct) { - $.ajax({ - url: '/tutorials/' + id + '.html', - type: 'GET', - complete: function (r) { - $('#helpstone').html("
                  " + defaultPage + "
                  " + r.responseText); - window.irb.init(); - window.irb.showHelp(0); - } - }); - }, - showChapter: function (n) { - if (n >= chapPages.length) return; - this.setHelpPage(chapPages[n][0], chapPages[n][1]); - }, - showHelp: function (n) { - if (n >= helpPages.length) return; - this.setHelpPage(n, helpPages[n]); - }, - popup_goto: function (u) { - $('#lilBrowser').show().css({left: '40px', top: '40px'}); - $('#lbIframe').attr('src', u); - }, - popup_make: function (s) { - $('#lilBrowser').show().css({left: '40px', top: '40px'}); - $('#lbIframe').get(0).onIframeLoad = function () { - alert($(this).html()); - alert("$(this).html()"); - return s; - }; - //$('#lbIframe').attr({src: '/blank.html'}); - src = s.replace(/\\/g, "\\\\").replace(/\"/g, "\\\""); - $('#lbIframe').attr({src: "javascript:\"" + src + "\""}); - // $('# - }, - popup_close: function () { - $('#lilBrowser').hide(); - } - }); - - if ( !toot ) { - toot = 'intro'; - } - try { - window.irb.options.loadTutorial( toot, true ); - } catch (e) {} -} diff --git a/non-rack-legacy/public/js/jquery-1.3.2.min.js b/non-rack-legacy/public/js/jquery-1.3.2.min.js deleted file mode 100644 index b1ae21d..0000000 --- a/non-rack-legacy/public/js/jquery-1.3.2.min.js +++ /dev/null @@ -1,19 +0,0 @@ -/* - * jQuery JavaScript Library v1.3.2 - * http://jquery.com/ - * - * Copyright (c) 2009 John Resig - * Dual licensed under the MIT and GPL licenses. - * http://docs.jquery.com/License - * - * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) - * Revision: 6246 - */ -(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("",""]||!O.indexOf("",""]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
                  "]||!O.indexOf("",""]||(!O.indexOf("",""]||!O.indexOf("",""]||!o.support.htmlSerialize&&[1,"div
                  ","
                  "]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}}); -/* - * Sizzle CSS Selector Engine - v0.9.3 - * Copyright 2009, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * More information: http://sizzlejs.com/ - */ -(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return UT[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="

                  ";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="
                  ";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("
                  ").append(M.responseText.replace(//g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='
                  ';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})(); \ No newline at end of file diff --git a/non-rack-legacy/public/js/jquery.js b/non-rack-legacy/public/js/jquery.js deleted file mode 100755 index 3747929..0000000 --- a/non-rack-legacy/public/js/jquery.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * jQuery 1.2.3 - New Wave Javascript - * - * Copyright (c) 2008 John Resig (jquery.com) - * Dual licensed under the MIT (MIT-LICENSE.txt) - * and GPL (GPL-LICENSE.txt) licenses. - * - * $Date: 2008-02-06 00:21:25 -0500 (Wed, 06 Feb 2008) $ - * $Rev: 4663 $ - */ -(function(){if(window.jQuery)var _jQuery=window.jQuery;var jQuery=window.jQuery=function(selector,context){return new jQuery.prototype.init(selector,context);};if(window.$)var _$=window.$;window.$=jQuery;var quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;var isSimple=/^.[^:#\[\.]*$/;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;return this;}else if(typeof selector=="string"){var match=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1])selector=jQuery.clean([match[1]],context);else{var elem=document.getElementById(match[3]);if(elem)if(elem.id!=match[3])return jQuery().find(selector);else{this[0]=elem;this.length=1;return this;}else -selector=[];}}else -return new jQuery(context).find(selector);}else if(jQuery.isFunction(selector))return new jQuery(document)[jQuery.fn.ready?"ready":"load"](selector);return this.setArray(selector.constructor==Array&&selector||(selector.jquery||selector.length&&selector!=window&&!selector.nodeType&&selector[0]!=undefined&&selector[0].nodeType)&&jQuery.makeArray(selector)||[selector]);},jquery:"1.2.3",size:function(){return this.length;},length:0,get:function(num){return num==undefined?jQuery.makeArray(this):this[num];},pushStack:function(elems){var ret=jQuery(elems);ret.prevObject=this;return ret;},setArray:function(elems){this.length=0;Array.prototype.push.apply(this,elems);return this;},each:function(callback,args){return jQuery.each(this,callback,args);},index:function(elem){var ret=-1;this.each(function(i){if(this==elem)ret=i;});return ret;},attr:function(name,value,type){var options=name;if(name.constructor==String)if(value==undefined)return this.length&&jQuery[type||"attr"](this[0],name)||undefined;else{options={};options[name]=value;}return this.each(function(i){for(name in options)jQuery.attr(type?this.style:this,name,jQuery.prop(this,options[name],type,i,name));});},css:function(key,value){if((key=='width'||key=='height')&&parseFloat(value)<0)value=undefined;return this.attr(key,value,"curCSS");},text:function(text){if(typeof text!="object"&&text!=null)return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(text));var ret="";jQuery.each(text||this,function(){jQuery.each(this.childNodes,function(){if(this.nodeType!=8)ret+=this.nodeType!=1?this.nodeValue:jQuery.fn.text([this]);});});return ret;},wrapAll:function(html){if(this[0])jQuery(html,this[0].ownerDocument).clone().insertBefore(this[0]).map(function(){var elem=this;while(elem.firstChild)elem=elem.firstChild;return elem;}).append(this);return this;},wrapInner:function(html){return this.each(function(){jQuery(this).contents().wrapAll(html);});},wrap:function(html){return this.each(function(){jQuery(this).wrapAll(html);});},append:function(){return this.domManip(arguments,true,false,function(elem){if(this.nodeType==1)this.appendChild(elem);});},prepend:function(){return this.domManip(arguments,true,true,function(elem){if(this.nodeType==1)this.insertBefore(elem,this.firstChild);});},before:function(){return this.domManip(arguments,false,false,function(elem){this.parentNode.insertBefore(elem,this);});},after:function(){return this.domManip(arguments,false,true,function(elem){this.parentNode.insertBefore(elem,this.nextSibling);});},end:function(){return this.prevObject||jQuery([]);},find:function(selector){var elems=jQuery.map(this,function(elem){return jQuery.find(selector,elem);});return this.pushStack(/[^+>] [^+>]/.test(selector)||selector.indexOf("..")>-1?jQuery.unique(elems):elems);},clone:function(events){var ret=this.map(function(){if(jQuery.browser.msie&&!jQuery.isXMLDoc(this)){var clone=this.cloneNode(true),container=document.createElement("div");container.appendChild(clone);return jQuery.clean([container.innerHTML])[0];}else -return this.cloneNode(true);});var clone=ret.find("*").andSelf().each(function(){if(this[expando]!=undefined)this[expando]=null;});if(events===true)this.find("*").andSelf().each(function(i){if(this.nodeType==3)return;var events=jQuery.data(this,"events");for(var type in events)for(var handler in events[type])jQuery.event.add(clone[i],type,events[type][handler],events[type][handler].data);});return ret;},filter:function(selector){return this.pushStack(jQuery.isFunction(selector)&&jQuery.grep(this,function(elem,i){return selector.call(elem,i);})||jQuery.multiFilter(selector,this));},not:function(selector){if(selector.constructor==String)if(isSimple.test(selector))return this.pushStack(jQuery.multiFilter(selector,this,true));else -selector=jQuery.multiFilter(selector,this);var isArrayLike=selector.length&&selector[selector.length-1]!==undefined&&!selector.nodeType;return this.filter(function(){return isArrayLike?jQuery.inArray(this,selector)<0:this!=selector;});},add:function(selector){return!selector?this:this.pushStack(jQuery.merge(this.get(),selector.constructor==String?jQuery(selector).get():selector.length!=undefined&&(!selector.nodeName||jQuery.nodeName(selector,"form"))?selector:[selector]));},is:function(selector){return selector?jQuery.multiFilter(selector,this).length>0:false;},hasClass:function(selector){return this.is("."+selector);},val:function(value){if(value==undefined){if(this.length){var elem=this[0];if(jQuery.nodeName(elem,"select")){var index=elem.selectedIndex,values=[],options=elem.options,one=elem.type=="select-one";if(index<0)return null;for(var i=one?index:0,max=one?index+1:options.length;i=0||jQuery.inArray(this.name,value)>=0);else if(jQuery.nodeName(this,"select")){var values=value.constructor==Array?value:[value];jQuery("option",this).each(function(){this.selected=(jQuery.inArray(this.value,values)>=0||jQuery.inArray(this.text,values)>=0);});if(!values.length)this.selectedIndex=-1;}else -this.value=value;});},html:function(value){return value==undefined?(this.length?this[0].innerHTML:null):this.empty().append(value);},replaceWith:function(value){return this.after(value).remove();},eq:function(i){return this.slice(i,i+1);},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments));},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem);}));},andSelf:function(){return this.add(this.prevObject);},data:function(key,value){var parts=key.split(".");parts[1]=parts[1]?"."+parts[1]:"";if(value==null){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data==undefined&&this.length)data=jQuery.data(this[0],key);return data==null&&parts[1]?this.data(parts[0]):data;}else -return this.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){jQuery.data(this,key,value);});},removeData:function(key){return this.each(function(){jQuery.removeData(this,key);});},domManip:function(args,table,reverse,callback){var clone=this.length>1,elems;return this.each(function(){if(!elems){elems=jQuery.clean(args,this.ownerDocument);if(reverse)elems.reverse();}var obj=this;if(table&&jQuery.nodeName(this,"table")&&jQuery.nodeName(elems[0],"tr"))obj=this.getElementsByTagName("tbody")[0]||this.appendChild(this.ownerDocument.createElement("tbody"));var scripts=jQuery([]);jQuery.each(elems,function(){var elem=clone?jQuery(this).clone(true)[0]:this;if(jQuery.nodeName(elem,"script")){scripts=scripts.add(elem);}else{if(elem.nodeType==1)scripts=scripts.add(jQuery("script",elem).remove());callback.call(obj,elem);}});scripts.each(evalScript);});}};jQuery.prototype.init.prototype=jQuery.prototype;function evalScript(i,elem){if(elem.src)jQuery.ajax({url:elem.src,async:false,dataType:"script"});else -jQuery.globalEval(elem.text||elem.textContent||elem.innerHTML||"");if(elem.parentNode)elem.parentNode.removeChild(elem);}jQuery.extend=jQuery.fn.extend=function(){var target=arguments[0]||{},i=1,length=arguments.length,deep=false,options;if(target.constructor==Boolean){deep=target;target=arguments[1]||{};i=2;}if(typeof target!="object"&&typeof target!="function")target={};if(length==1){target=this;i=0;}for(;i-1;}},swap:function(elem,options,callback){var old={};for(var name in options){old[name]=elem.style[name];elem.style[name]=options[name];}callback.call(elem);for(var name in options)elem.style[name]=old[name];},css:function(elem,name,force){if(name=="width"||name=="height"){var val,props={position:"absolute",visibility:"hidden",display:"block"},which=name=="width"?["Left","Right"]:["Top","Bottom"];function getWH(){val=name=="width"?elem.offsetWidth:elem.offsetHeight;var padding=0,border=0;jQuery.each(which,function(){padding+=parseFloat(jQuery.curCSS(elem,"padding"+this,true))||0;border+=parseFloat(jQuery.curCSS(elem,"border"+this+"Width",true))||0;});val-=Math.round(padding+border);}if(jQuery(elem).is(":visible"))getWH();else -jQuery.swap(elem,props,getWH);return Math.max(0,val);}return jQuery.curCSS(elem,name,force);},curCSS:function(elem,name,force){var ret;function color(elem){if(!jQuery.browser.safari)return false;var ret=document.defaultView.getComputedStyle(elem,null);return!ret||ret.getPropertyValue("color")=="";}if(name=="opacity"&&jQuery.browser.msie){ret=jQuery.attr(elem.style,"opacity");return ret==""?"1":ret;}if(jQuery.browser.opera&&name=="display"){var save=elem.style.outline;elem.style.outline="0 solid black";elem.style.outline=save;}if(name.match(/float/i))name=styleFloat;if(!force&&elem.style&&elem.style[name])ret=elem.style[name];else if(document.defaultView&&document.defaultView.getComputedStyle){if(name.match(/float/i))name="float";name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var getComputedStyle=document.defaultView.getComputedStyle(elem,null);if(getComputedStyle&&!color(elem))ret=getComputedStyle.getPropertyValue(name);else{var swap=[],stack=[];for(var a=elem;a&&color(a);a=a.parentNode)stack.unshift(a);for(var i=0;i]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+">";});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("",""]||!tags.indexOf("",""]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
                  "]||!tags.indexOf("",""]||(!tags.indexOf("",""]||!tags.indexOf("",""]||jQuery.browser.msie&&[1,"div
                  ","
                  "]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--)div=div.lastChild;if(jQuery.browser.msie){var tbody=!tags.indexOf(""&&tags.indexOf("=0;--j)if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length)tbody[j].parentNode.removeChild(tbody[j]);if(/^\s/.test(elem))div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]),div.firstChild);}elem=jQuery.makeArray(div.childNodes);}if(elem.length===0&&(!jQuery.nodeName(elem,"form")&&!jQuery.nodeName(elem,"select")))return;if(elem[0]==undefined||jQuery.nodeName(elem,"form")||elem.options)ret.push(elem);else -ret=jQuery.merge(ret,elem);});return ret;},attr:function(elem,name,value){if(!elem||elem.nodeType==3||elem.nodeType==8)return undefined;var fix=jQuery.isXMLDoc(elem)?{}:jQuery.props;if(name=="selected"&&jQuery.browser.safari)elem.parentNode.selectedIndex;if(fix[name]){if(value!=undefined)elem[fix[name]]=value;return elem[fix[name]];}else if(jQuery.browser.msie&&name=="style")return jQuery.attr(elem.style,"cssText",value);else if(value==undefined&&jQuery.browser.msie&&jQuery.nodeName(elem,"form")&&(name=="action"||name=="method"))return elem.getAttributeNode(name).nodeValue;else if(elem.tagName){if(value!=undefined){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode)throw"type property can't be changed";elem.setAttribute(name,""+value);}if(jQuery.browser.msie&&/href|src/.test(name)&&!jQuery.isXMLDoc(elem))return elem.getAttribute(name,2);return elem.getAttribute(name);}else{if(name=="opacity"&&jQuery.browser.msie){if(value!=undefined){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+(parseFloat(value).toString()=="NaN"?"":"alpha(opacity="+value*100+")");}return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100).toString():"";}name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase();});if(value!=undefined)elem[name]=value;return elem[name];}},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"");},makeArray:function(array){var ret=[];if(typeof array!="array")for(var i=0,length=array.length;i*",this).remove();while(this.firstChild)this.removeChild(this.firstChild);}},function(name,fn){jQuery.fn[name]=function(){return this.each(fn,arguments);};});jQuery.each(["Height","Width"],function(i,name){var type=name.toLowerCase();jQuery.fn[type]=function(size){return this[0]==window?jQuery.browser.opera&&document.body["client"+name]||jQuery.browser.safari&&window["inner"+name]||document.compatMode=="CSS1Compat"&&document.documentElement["client"+name]||document.body["client"+name]:this[0]==document?Math.max(Math.max(document.body["scroll"+name],document.documentElement["scroll"+name]),Math.max(document.body["offset"+name],document.documentElement["offset"+name])):size==undefined?(this.length?jQuery.css(this[0],type):null):this.css(type,size.constructor==String?size:size+"px");};});var chars=jQuery.browser.safari&&parseInt(jQuery.browser.version)<417?"(?:[\\w*_-]|\\\\.)":"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",quickChild=new RegExp("^>\\s*("+chars+"+)"),quickID=new RegExp("^("+chars+"+)(#)("+chars+"+)"),quickClass=new RegExp("^([#.]?)("+chars+"*)");jQuery.extend({expr:{"":function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},"#":function(a,i,m){return a.getAttribute("id")==m[2];},":":{lt:function(a,i,m){return im[3]-0;},nth:function(a,i,m){return m[3]-0==i;},eq:function(a,i,m){return m[3]-0==i;},first:function(a,i){return i==0;},last:function(a,i,m,r){return i==r.length-1;},even:function(a,i){return i%2==0;},odd:function(a,i){return i%2;},"first-child":function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},"last-child":function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},"only-child":function(a){return!jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},parent:function(a){return a.firstChild;},empty:function(a){return!a.firstChild;},contains:function(a,i,m){return(a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},visible:function(a){return"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},hidden:function(a){return"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},enabled:function(a){return!a.disabled;},disabled:function(a){return a.disabled;},checked:function(a){return a.checked;},selected:function(a){return a.selected||jQuery.attr(a,"selected");},text:function(a){return"text"==a.type;},radio:function(a){return"radio"==a.type;},checkbox:function(a){return"checkbox"==a.type;},file:function(a){return"file"==a.type;},password:function(a){return"password"==a.type;},submit:function(a){return"submit"==a.type;},image:function(a){return"image"==a.type;},reset:function(a){return"reset"==a.type;},button:function(a){return"button"==a.type||jQuery.nodeName(a,"button");},input:function(a){return/input|select|textarea|button/i.test(a.nodeName);},has:function(a,i,m){return jQuery.find(m[3],a).length;},header:function(a){return/h\d/i.test(a.nodeName);},animated:function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}}},parse:[/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,new RegExp("^([:.#]*)("+chars+"+)")],multiFilter:function(expr,elems,not){var old,cur=[];while(expr&&expr!=old){old=expr;var f=jQuery.filter(expr,elems,not);expr=f.t.replace(/^\s*,\s*/,"");cur=not?elems=f.r:jQuery.merge(cur,f.r);}return cur;},find:function(t,context){if(typeof t!="string")return[t];if(context&&context.nodeType!=1&&context.nodeType!=9)return[];context=context||document;var ret=[context],done=[],last,nodeName;while(t&&last!=t){var r=[];last=t;t=jQuery.trim(t);var foundToken=false;var re=quickChild;var m=re.exec(t);if(m){nodeName=m[1].toUpperCase();for(var i=0;ret[i];i++)for(var c=ret[i].firstChild;c;c=c.nextSibling)if(c.nodeType==1&&(nodeName=="*"||c.nodeName.toUpperCase()==nodeName))r.push(c);ret=r;t=t.replace(re,"");if(t.indexOf(" ")==0)continue;foundToken=true;}else{re=/^([>+~])\s*(\w*)/i;if((m=re.exec(t))!=null){r=[];var merge={};nodeName=m[2].toUpperCase();m=m[1];for(var j=0,rl=ret.length;j=0;if(!not&&pass||not&&!pass)tmp.push(r[i]);}return tmp;},filter:function(t,r,not){var last;while(t&&t!=last){last=t;var p=jQuery.parse,m;for(var i=0;p[i];i++){m=p[i].exec(t);if(m){t=t.substring(m[0].length);m[2]=m[2].replace(/\\/g,"");break;}}if(!m)break;if(m[1]==":"&&m[2]=="not")r=isSimple.test(m[3])?jQuery.filter(m[3],r,true).r:jQuery(r).not(m[3]);else if(m[1]==".")r=jQuery.classFilter(r,m[2],not);else if(m[1]=="["){var tmp=[],type=m[3];for(var i=0,rl=r.length;i=0)^not)tmp.push(a);}r=tmp;}else if(m[1]==":"&&m[2]=="nth-child"){var merge={},tmp=[],test=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3]=="even"&&"2n"||m[3]=="odd"&&"2n+1"||!/\D/.test(m[3])&&"0n+"+m[3]||m[3]),first=(test[1]+(test[2]||1))-0,last=test[3]-0;for(var i=0,rl=r.length;i=0)add=true;if(add^not)tmp.push(node);}r=tmp;}else{var fn=jQuery.expr[m[1]];if(typeof fn=="object")fn=fn[m[2]];if(typeof fn=="string")fn=eval("false||function(a,i){return "+fn+";}");r=jQuery.grep(r,function(elem,i){return fn(elem,i,m,r);},not);}}return{r:r,t:t};},dir:function(elem,dir){var matched=[];var cur=elem[dir];while(cur&&cur!=document){if(cur.nodeType==1)matched.push(cur);cur=cur[dir];}return matched;},nth:function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir])if(cur.nodeType==1&&++num==result)break;return cur;},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType==1&&(!elem||n!=elem))r.push(n);}return r;}});jQuery.event={add:function(elem,types,handler,data){if(elem.nodeType==3||elem.nodeType==8)return;if(jQuery.browser.msie&&elem.setInterval!=undefined)elem=window;if(!handler.guid)handler.guid=this.guid++;if(data!=undefined){var fn=handler;handler=function(){return fn.apply(this,arguments);};handler.data=data;handler.guid=fn.guid;}var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){var val;if(typeof jQuery=="undefined"||jQuery.event.triggered)return val;val=jQuery.event.handle.apply(arguments.callee.elem,arguments);return val;});handle.elem=elem;jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];handler.type=parts[1];var handlers=events[type];if(!handlers){handlers=events[type]={};if(!jQuery.event.special[type]||jQuery.event.special[type].setup.call(elem)===false){if(elem.addEventListener)elem.addEventListener(type,handle,false);else if(elem.attachEvent)elem.attachEvent("on"+type,handle);}}handlers[handler.guid]=handler;jQuery.event.global[type]=true;});elem=null;},guid:1,global:{},remove:function(elem,types,handler){if(elem.nodeType==3||elem.nodeType==8)return;var events=jQuery.data(elem,"events"),ret,index;if(events){if(types==undefined||(typeof types=="string"&&types.charAt(0)=="."))for(var type in events)this.remove(elem,type+(types||""));else{if(types.type){handler=types.handler;types=types.type;}jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];if(events[type]){if(handler)delete events[type][handler.guid];else -for(handler in events[type])if(!parts[1]||events[type][handler].type==parts[1])delete events[type][handler];for(ret in events[type])break;if(!ret){if(!jQuery.event.special[type]||jQuery.event.special[type].teardown.call(elem)===false){if(elem.removeEventListener)elem.removeEventListener(type,jQuery.data(elem,"handle"),false);else if(elem.detachEvent)elem.detachEvent("on"+type,jQuery.data(elem,"handle"));}ret=null;delete events[type];}}});}for(ret in events)break;if(!ret){var handle=jQuery.data(elem,"handle");if(handle)handle.elem=null;jQuery.removeData(elem,"events");jQuery.removeData(elem,"handle");}}},trigger:function(type,data,elem,donative,extra){data=jQuery.makeArray(data||[]);if(type.indexOf("!")>=0){type=type.slice(0,-1);var exclusive=true;}if(!elem){if(this.global[type])jQuery("*").add([window,document]).trigger(type,data);}else{if(elem.nodeType==3||elem.nodeType==8)return undefined;var val,ret,fn=jQuery.isFunction(elem[type]||null),event=!data[0]||!data[0].preventDefault;if(event)data.unshift(this.fix({type:type,target:elem}));data[0].type=type;if(exclusive)data[0].exclusive=true;if(jQuery.isFunction(jQuery.data(elem,"handle")))val=jQuery.data(elem,"handle").apply(elem,data);if(!fn&&elem["on"+type]&&elem["on"+type].apply(elem,data)===false)val=false;if(event)data.shift();if(extra&&jQuery.isFunction(extra)){ret=extra.apply(elem,val==null?data:data.concat(val));if(ret!==undefined)val=ret;}if(fn&&donative!==false&&val!==false&&!(jQuery.nodeName(elem,'a')&&type=="click")){this.triggered=true;try{elem[type]();}catch(e){}}this.triggered=false;}return val;},handle:function(event){var val;event=jQuery.event.fix(event||window.event||{});var parts=event.type.split(".");event.type=parts[0];var handlers=jQuery.data(this,"events")&&jQuery.data(this,"events")[event.type],args=Array.prototype.slice.call(arguments,1);args.unshift(event);for(var j in handlers){var handler=handlers[j];args[0].handler=handler;args[0].data=handler.data;if(!parts[1]&&!event.exclusive||handler.type==parts[1]){var ret=handler.apply(this,args);if(val!==false)val=ret;if(ret===false){event.preventDefault();event.stopPropagation();}}}if(jQuery.browser.msie)event.target=event.preventDefault=event.stopPropagation=event.handler=event.data=null;return val;},fix:function(event){var originalEvent=event;event=jQuery.extend({},originalEvent);event.preventDefault=function(){if(originalEvent.preventDefault)originalEvent.preventDefault();originalEvent.returnValue=false;};event.stopPropagation=function(){if(originalEvent.stopPropagation)originalEvent.stopPropagation();originalEvent.cancelBubble=true;};if(!event.target)event.target=event.srcElement||document;if(event.target.nodeType==3)event.target=originalEvent.target.parentNode;if(!event.relatedTarget&&event.fromElement)event.relatedTarget=event.fromElement==event.target?event.toElement:event.fromElement;if(event.pageX==null&&event.clientX!=null){var doc=document.documentElement,body=document.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc.clientTop||0);}if(!event.which&&((event.charCode||event.charCode===0)?event.charCode:event.keyCode))event.which=event.charCode||event.keyCode;if(!event.metaKey&&event.ctrlKey)event.metaKey=event.ctrlKey;if(!event.which&&event.button)event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)));return event;},special:{ready:{setup:function(){bindReady();return;},teardown:function(){return;}},mouseenter:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseover",jQuery.event.special.mouseenter.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseover",jQuery.event.special.mouseenter.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseenter";return jQuery.event.handle.apply(this,arguments);}},mouseleave:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseout",jQuery.event.special.mouseleave.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseout",jQuery.event.special.mouseleave.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseleave";return jQuery.event.handle.apply(this,arguments);}}}};jQuery.fn.extend({bind:function(type,data,fn){return type=="unload"?this.one(type,data,fn):this.each(function(){jQuery.event.add(this,type,fn||data,fn&&data);});},one:function(type,data,fn){return this.each(function(){jQuery.event.add(this,type,function(event){jQuery(this).unbind(event);return(fn||data).apply(this,arguments);},fn&&data);});},unbind:function(type,fn){return this.each(function(){jQuery.event.remove(this,type,fn);});},trigger:function(type,data,fn){return this.each(function(){jQuery.event.trigger(type,data,this,true,fn);});},triggerHandler:function(type,data,fn){if(this[0])return jQuery.event.trigger(type,data,this[0],false,fn);return undefined;},toggle:function(){var args=arguments;return this.click(function(event){this.lastToggle=0==this.lastToggle?1:0;event.preventDefault();return args[this.lastToggle].apply(this,arguments)||false;});},hover:function(fnOver,fnOut){return this.bind('mouseenter',fnOver).bind('mouseleave',fnOut);},ready:function(fn){bindReady();if(jQuery.isReady)fn.call(document,jQuery);else -jQuery.readyList.push(function(){return fn.call(this,jQuery);});return this;}});jQuery.extend({isReady:false,readyList:[],ready:function(){if(!jQuery.isReady){jQuery.isReady=true;if(jQuery.readyList){jQuery.each(jQuery.readyList,function(){this.apply(document);});jQuery.readyList=null;}jQuery(document).triggerHandler("ready");}}});var readyBound=false;function bindReady(){if(readyBound)return;readyBound=true;if(document.addEventListener&&!jQuery.browser.opera)document.addEventListener("DOMContentLoaded",jQuery.ready,false);if(jQuery.browser.msie&&window==top)(function(){if(jQuery.isReady)return;try{document.documentElement.doScroll("left");}catch(error){setTimeout(arguments.callee,0);return;}jQuery.ready();})();if(jQuery.browser.opera)document.addEventListener("DOMContentLoaded",function(){if(jQuery.isReady)return;for(var i=0;i=0){var selector=url.slice(off,url.length);url=url.slice(0,off);}callback=callback||function(){};var type="GET";if(params)if(jQuery.isFunction(params)){callback=params;params=null;}else{params=jQuery.param(params);type="POST";}var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(res,status){if(status=="success"||status=="notmodified")self.html(selector?jQuery("
                  ").append(res.responseText.replace(//g,"")).find(selector):res.responseText);self.each(callback,[res.responseText,status,res]);}});return this;},serialize:function(){return jQuery.param(this.serializeArray());},serializeArray:function(){return this.map(function(){return jQuery.nodeName(this,"form")?jQuery.makeArray(this.elements):this;}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type));}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:val.constructor==Array?jQuery.map(val,function(val,i){return{name:elem.name,value:val};}):{name:elem.name,value:val};}).get();}});jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(i,o){jQuery.fn[o]=function(f){return this.bind(o,f);};});var jsc=(new Date).getTime();jQuery.extend({get:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data=null;}return jQuery.ajax({type:"GET",url:url,data:data,success:callback,dataType:type});},getScript:function(url,callback){return jQuery.get(url,null,callback,"script");},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},post:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data={};}return jQuery.ajax({type:"POST",url:url,data:data,success:callback,dataType:type});},ajaxSetup:function(settings){jQuery.extend(jQuery.ajaxSettings,settings);},ajaxSettings:{global:true,type:"GET",timeout:0,contentType:"application/x-www-form-urlencoded",processData:true,async:true,data:null,username:null,password:null,accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(s){var jsonp,jsre=/=\?(&|$)/g,status,data;s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));if(s.data&&s.processData&&typeof s.data!="string")s.data=jQuery.param(s.data);if(s.dataType=="jsonp"){if(s.type.toLowerCase()=="get"){if(!s.url.match(jsre))s.url+=(s.url.match(/\?/)?"&":"?")+(s.jsonp||"callback")+"=?";}else if(!s.data||!s.data.match(jsre))s.data=(s.data?s.data+"&":"")+(s.jsonp||"callback")+"=?";s.dataType="json";}if(s.dataType=="json"&&(s.data&&s.data.match(jsre)||s.url.match(jsre))){jsonp="jsonp"+jsc++;if(s.data)s.data=(s.data+"").replace(jsre,"="+jsonp+"$1");s.url=s.url.replace(jsre,"="+jsonp+"$1");s.dataType="script";window[jsonp]=function(tmp){data=tmp;success();complete();window[jsonp]=undefined;try{delete window[jsonp];}catch(e){}if(head)head.removeChild(script);};}if(s.dataType=="script"&&s.cache==null)s.cache=false;if(s.cache===false&&s.type.toLowerCase()=="get"){var ts=(new Date()).getTime();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"");}if(s.data&&s.type.toLowerCase()=="get"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null;}if(s.global&&!jQuery.active++)jQuery.event.trigger("ajaxStart");if((!s.url.indexOf("http")||!s.url.indexOf("//"))&&s.dataType=="script"&&s.type.toLowerCase()=="get"){var head=document.getElementsByTagName("head")[0];var script=document.createElement("script");script.src=s.url;if(s.scriptCharset)script.charset=s.scriptCharset;if(!jsonp){var done=false;script.onload=script.onreadystatechange=function(){if(!done&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){done=true;success();complete();head.removeChild(script);}};}head.appendChild(script);return undefined;}var requestDone=false;var xml=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();xml.open(s.type,s.url,s.async,s.username,s.password);try{if(s.data)xml.setRequestHeader("Content-Type",s.contentType);if(s.ifModified)xml.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT");xml.setRequestHeader("X-Requested-With","XMLHttpRequest");xml.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default);}catch(e){}if(s.beforeSend)s.beforeSend(xml);if(s.global)jQuery.event.trigger("ajaxSend",[xml,s]);var onreadystatechange=function(isTimeout){if(!requestDone&&xml&&(xml.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null;}status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xml)&&"error"||s.ifModified&&jQuery.httpNotModified(xml,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xml,s.dataType);}catch(e){status="parsererror";}}if(status=="success"){var modRes;try{modRes=xml.getResponseHeader("Last-Modified");}catch(e){}if(s.ifModified&&modRes)jQuery.lastModified[s.url]=modRes;if(!jsonp)success();}else -jQuery.handleError(s,xml,status);complete();if(s.async)xml=null;}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0)setTimeout(function(){if(xml){xml.abort();if(!requestDone)onreadystatechange("timeout");}},s.timeout);}try{xml.send(s.data);}catch(e){jQuery.handleError(s,xml,null,e);}if(!s.async)onreadystatechange();function success(){if(s.success)s.success(data,status);if(s.global)jQuery.event.trigger("ajaxSuccess",[xml,s]);}function complete(){if(s.complete)s.complete(xml,status);if(s.global)jQuery.event.trigger("ajaxComplete",[xml,s]);if(s.global&&!--jQuery.active)jQuery.event.trigger("ajaxStop");}return xml;},handleError:function(s,xml,status,e){if(s.error)s.error(xml,status,e);if(s.global)jQuery.event.trigger("ajaxError",[xml,s,e]);},active:0,httpSuccess:function(r){try{return!r.status&&location.protocol=="file:"||(r.status>=200&&r.status<300)||r.status==304||r.status==1223||jQuery.browser.safari&&r.status==undefined;}catch(e){}return false;},httpNotModified:function(xml,url){try{var xmlRes=xml.getResponseHeader("Last-Modified");return xml.status==304||xmlRes==jQuery.lastModified[url]||jQuery.browser.safari&&xml.status==undefined;}catch(e){}return false;},httpData:function(r,type){var ct=r.getResponseHeader("content-type");var xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0;var data=xml?r.responseXML:r.responseText;if(xml&&data.documentElement.tagName=="parsererror")throw"parsererror";if(type=="script")jQuery.globalEval(data);if(type=="json")data=eval("("+data+")");return data;},param:function(a){var s=[];if(a.constructor==Array||a.jquery)jQuery.each(a,function(){s.push(encodeURIComponent(this.name)+"="+encodeURIComponent(this.value));});else -for(var j in a)if(a[j]&&a[j].constructor==Array)jQuery.each(a[j],function(){s.push(encodeURIComponent(j)+"="+encodeURIComponent(this));});else -s.push(encodeURIComponent(j)+"="+encodeURIComponent(a[j]));return s.join("&").replace(/%20/g,"+");}});jQuery.fn.extend({show:function(speed,callback){return speed?this.animate({height:"show",width:"show",opacity:"show"},speed,callback):this.filter(":hidden").each(function(){this.style.display=this.oldblock||"";if(jQuery.css(this,"display")=="none"){var elem=jQuery("<"+this.tagName+" />").appendTo("body");this.style.display=elem.css("display");if(this.style.display=="none")this.style.display="block";elem.remove();}}).end();},hide:function(speed,callback){return speed?this.animate({height:"hide",width:"hide",opacity:"hide"},speed,callback):this.filter(":visible").each(function(){this.oldblock=this.oldblock||jQuery.css(this,"display");this.style.display="none";}).end();},_toggle:jQuery.fn.toggle,toggle:function(fn,fn2){return jQuery.isFunction(fn)&&jQuery.isFunction(fn2)?this._toggle(fn,fn2):fn?this.animate({height:"toggle",width:"toggle",opacity:"toggle"},fn,fn2):this.each(function(){jQuery(this)[jQuery(this).is(":hidden")?"show":"hide"]();});},slideDown:function(speed,callback){return this.animate({height:"show"},speed,callback);},slideUp:function(speed,callback){return this.animate({height:"hide"},speed,callback);},slideToggle:function(speed,callback){return this.animate({height:"toggle"},speed,callback);},fadeIn:function(speed,callback){return this.animate({opacity:"show"},speed,callback);},fadeOut:function(speed,callback){return this.animate({opacity:"hide"},speed,callback);},fadeTo:function(speed,to,callback){return this.animate({opacity:to},speed,callback);},animate:function(prop,speed,easing,callback){var optall=jQuery.speed(speed,easing,callback);return this[optall.queue===false?"each":"queue"](function(){if(this.nodeType!=1)return false;var opt=jQuery.extend({},optall);var hidden=jQuery(this).is(":hidden"),self=this;for(var p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden)return jQuery.isFunction(opt.complete)&&opt.complete.apply(this);if(p=="height"||p=="width"){opt.display=jQuery.css(this,"display");opt.overflow=this.style.overflow;}}if(opt.overflow!=null)this.style.overflow="hidden";opt.curAnim=jQuery.extend({},prop);jQuery.each(prop,function(name,val){var e=new jQuery.fx(self,opt,name);if(/toggle|show|hide/.test(val))e[val=="toggle"?hidden?"show":"hide":val](prop);else{var parts=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),start=e.cur(true)||0;if(parts){var end=parseFloat(parts[2]),unit=parts[3]||"px";if(unit!="px"){self.style[name]=(end||1)+unit;start=((end||1)/e.cur(true))*start;self.style[name]=start+unit;}if(parts[1])end=((parts[1]=="-="?-1:1)*end)+start;e.custom(start,end,unit);}else -e.custom(start,val,"");}});return true;});},queue:function(type,fn){if(jQuery.isFunction(type)||(type&&type.constructor==Array)){fn=type;type="fx";}if(!type||(typeof type=="string"&&!fn))return queue(this[0],type);return this.each(function(){if(fn.constructor==Array)queue(this,type,fn);else{queue(this,type).push(fn);if(queue(this,type).length==1)fn.apply(this);}});},stop:function(clearQueue,gotoEnd){var timers=jQuery.timers;if(clearQueue)this.queue([]);this.each(function(){for(var i=timers.length-1;i>=0;i--)if(timers[i].elem==this){if(gotoEnd)timers[i](true);timers.splice(i,1);}});if(!gotoEnd)this.dequeue();return this;}});var queue=function(elem,type,array){if(!elem)return undefined;type=type||"fx";var q=jQuery.data(elem,type+"queue");if(!q||array)q=jQuery.data(elem,type+"queue",array?jQuery.makeArray(array):[]);return q;};jQuery.fn.dequeue=function(type){type=type||"fx";return this.each(function(){var q=queue(this,type);q.shift();if(q.length)q[0].apply(this);});};jQuery.extend({speed:function(speed,easing,fn){var opt=speed&&speed.constructor==Object?speed:{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&easing.constructor!=Function&&easing};opt.duration=(opt.duration&&opt.duration.constructor==Number?opt.duration:{slow:600,fast:200}[opt.duration])||400;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false)jQuery(this).dequeue();if(jQuery.isFunction(opt.old))opt.old.apply(this);};return opt;},easing:{linear:function(p,n,firstNum,diff){return firstNum+diff*p;},swing:function(p,n,firstNum,diff){return((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum;}},timers:[],timerId:null,fx:function(elem,options,prop){this.options=options;this.elem=elem;this.prop=prop;if(!options.orig)options.orig={};}});jQuery.fx.prototype={update:function(){if(this.options.step)this.options.step.apply(this.elem,[this.now,this]);(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);if(this.prop=="height"||this.prop=="width")this.elem.style.display="block";},cur:function(force){if(this.elem[this.prop]!=null&&this.elem.style[this.prop]==null)return this.elem[this.prop];var r=parseFloat(jQuery.css(this.elem,this.prop,force));return r&&r>-10000?r:parseFloat(jQuery.curCSS(this.elem,this.prop))||0;},custom:function(from,to,unit){this.startTime=(new Date()).getTime();this.start=from;this.end=to;this.unit=unit||this.unit||"px";this.now=this.start;this.pos=this.state=0;this.update();var self=this;function t(gotoEnd){return self.step(gotoEnd);}t.elem=this.elem;jQuery.timers.push(t);if(jQuery.timerId==null){jQuery.timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;ithis.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var done=true;for(var i in this.options.curAnim)if(this.options.curAnim[i]!==true)done=false;if(done){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(jQuery.css(this.elem,"display")=="none")this.elem.style.display="block";}if(this.options.hide)this.elem.style.display="none";if(this.options.hide||this.options.show)for(var p in this.options.curAnim)jQuery.attr(this.elem.style,p,this.options.orig[p]);}if(done&&jQuery.isFunction(this.options.complete))this.options.complete.apply(this.elem);return false;}else{var n=t-this.startTime;this.state=n/this.options.duration;this.pos=jQuery.easing[this.options.easing||(jQuery.easing.swing?"swing":"linear")](this.state,n,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update();}return true;}};jQuery.fx.step={scrollLeft:function(fx){fx.elem.scrollLeft=fx.now;},scrollTop:function(fx){fx.elem.scrollTop=fx.now;},opacity:function(fx){jQuery.attr(fx.elem.style,"opacity",fx.now);},_default:function(fx){fx.elem.style[fx.prop]=fx.now+fx.unit;}};jQuery.fn.offset=function(){var left=0,top=0,elem=this[0],results;if(elem)with(jQuery.browser){var parent=elem.parentNode,offsetChild=elem,offsetParent=elem.offsetParent,doc=elem.ownerDocument,safari2=safari&&parseInt(version)<522&&!/adobeair/i.test(userAgent),fixed=jQuery.css(elem,"position")=="fixed";if(elem.getBoundingClientRect){var box=elem.getBoundingClientRect();add(box.left+Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),box.top+Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));add(-doc.documentElement.clientLeft,-doc.documentElement.clientTop);}else{add(elem.offsetLeft,elem.offsetTop);while(offsetParent){add(offsetParent.offsetLeft,offsetParent.offsetTop);if(mozilla&&!/^t(able|d|h)$/i.test(offsetParent.tagName)||safari&&!safari2)border(offsetParent);if(!fixed&&jQuery.css(offsetParent,"position")=="fixed")fixed=true;offsetChild=/^body$/i.test(offsetParent.tagName)?offsetChild:offsetParent;offsetParent=offsetParent.offsetParent;}while(parent&&parent.tagName&&!/^body|html$/i.test(parent.tagName)){if(!/^inline|table.*$/i.test(jQuery.css(parent,"display")))add(-parent.scrollLeft,-parent.scrollTop);if(mozilla&&jQuery.css(parent,"overflow")!="visible")border(parent);parent=parent.parentNode;}if((safari2&&(fixed||jQuery.css(offsetChild,"position")=="absolute"))||(mozilla&&jQuery.css(offsetChild,"position")!="absolute"))add(-doc.body.offsetLeft,-doc.body.offsetTop);if(fixed)add(Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));}results={top:top,left:left};}function border(elem){add(jQuery.curCSS(elem,"borderLeftWidth",true),jQuery.curCSS(elem,"borderTopWidth",true));}function add(l,t){left+=parseInt(l)||0;top+=parseInt(t)||0;}return results;};})(); \ No newline at end of file diff --git a/non-rack-legacy/public/js/mouseapp_2.js b/non-rack-legacy/public/js/mouseapp_2.js deleted file mode 100755 index 6ea09a4..0000000 --- a/non-rack-legacy/public/js/mouseapp_2.js +++ /dev/null @@ -1,913 +0,0 @@ -// -// Copyright (c) 2008 why the lucky stiff -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, -// and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT -// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -var MouseApp = { - Version: '0.12', - CharCodes: { - 0: ' ', 1: ' ', 9: ' ', - 32: ' ', 34: '"', 38: '&', - 60: '<', 62: '>', 127: '◊', - 0x20AC: '€' - }, - KeyCodes: { - Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 33, PageDown: 34, - End: 35, Home: 36, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 45, - Delete: 46, F1: 112, F2: 113, F3: 114, F4: 115, F5: 116, F6: 117, - F7: 118, F8: 119, F10: 121 - }, - CodeKeys: {}, - Modes: { 1: 'b', 2: 'u', 4: 'i', 8: 'strike' }, - ModeIds: { r: 1, u: 2, i: 4, s: 8 }, - Colors: ['black', 'blue', 'green', - 'cyan', 'red', 'purple', 'brown', - 'gray', 'dark_gray', 'lt_blue', - 'lt_green', 'lt_cyan', 'lt_red', - 'lt_purple', 'yellow', 'white'] -} -//some of these are patently false, because I need to get on a real keyboard-- not a macbook. -if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1){ - MouseApp.KeyCodes = { - Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, - End: 63275, Home: 63273, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 632325, - Delete: 8, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, - F7: 63242, F8: 63243, F10: 63244 - } - -} - -//even though I am tempted to combine chrome and opera into the same if statment, I will refrain for now -// i dont have proper access to a proper keyboard and there might be a single difference between the two -if (navigator.userAgent.indexOf("Opera") > -1){ - MouseApp.KeyCodes = { - Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, - End: 63275, Home: 63273, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 632325, - Delete: 8, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, - F7: 63242, F8: 63243, F10: 63244 - } - -} - -// i am going to comment this out, since this seems un needed. if it past december 15 2009 and this -// is still commented it, please del me -//if ( navigator.appVersion.indexOf('AppleWebKit') > 0 ) { -// MouseApp.KeyCodes = { -// Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277, -// End: 63275, Home: 63273, Left: 63234, Up: 63232, Right: 63235, Down: 63233, Insert: 632325, -// Delete: 63272, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241, -// F7: 63242, F8: 63243, F10: 63244 -// };// -//} -for ( var k in MouseApp.KeyCodes ) { - MouseApp.CodeKeys[MouseApp.KeyCodes[k]] = k; -} - -MouseApp.isPrintable = function(ch) { - return (ch >= 32); -}; - -MouseApp.Base = function(){}; -MouseApp.Base.prototype = { - setOptions: function(options) { - this.options = { - columns: 72, rows: 24, indent: 2, - title: 'MouseApp', - blinkRate: 500, - ps: '>', - greeting:'%+r Terminal ready. %-r' - } - $.extend(this.options, options || {}); - } -} - -MouseApp.Manager = new Object(); -$.extend(MouseApp.Manager, { - observeTerm: function(term) { - this.activeTerm = term; - if ( this.observingKeyboard ) return; - var mgr = this; - if ( term.input ) { - term.input.keypress(function(e) { mgr.onKeyPress(e) }); - if (!window.opera) term.input.keydown(function(e) { mgr.onKeyDown(e) }); - else window.setInterval(function(){term.input.focus()},1); - } else { - if (!window.opera) $(document).keydown(function(e) { mgr.onKeyDown(e) }); - $(document).keypress(function(e) { mgr.onKeyPress(e) }); - } - this.observingKeyboard = true; - }, - - onKeyDown: function(e) { - e = (e) ? e : ((event) ? event : null); - if ( e && MouseApp.CodeKeys[e.keyCode] ) { - if ( window.event ) { - this.sendKeyPress(e); - } - this.blockEvent(e); - return false; - } - return true; - }, - - onKeyPress: function(e) { - if ( !window.opera && window.event && e.keyCode != 13 && e.keyCode != 8 ) { - e.charCode = e.keyCode; e.keyCode = null; - } - if ( e.keyCode == 191 ) { /* FF 1.0.x sends this upsy quizy -- ignore */ - return; - } - return this.sendKeyPress(e); - }, - - sendKeyPress: function(e) { - var term = MouseApp.Manager.activeTerm; - term.cursorOff(); - b = term.onKeyPress(e); - term.cursorOn(); - return b; - }, - - blockEvent: function (e) { - e.cancelBubble=true; - if (window.event && !window.opera) e.keyCode=0; - if (e.stopPropagation) e.stopPropagation(); - if (e.preventDefault) e.preventDefault(); - } -}); - -/* Basic text window functionality */ -MouseApp.Window = function(element, options) { - this.element = $(element); - this.setOptions(options); - this.initWindow(); -}; - -$.extend(MouseApp.Window.prototype, (new MouseApp.Base()), { - initWindow: function() { - var html = ''; - for ( var i = 0; i < this.options.rows; i++ ) { - html += "
                   
                  \n"; - } - this.element.html(html); - this.typingOn(); - if (this.options.input) { - this.input = $(this.options.input); - this.input.focus(); - } - MouseApp.Manager.observeTerm(this); - this.clear(); - this.cursorOn(); - this.painting = true; - this.element.css({visibility: 'visible'}); - }, - - text: function() { - var str = ""; - for (var i = 0; i < this.screen.length; i++ ) { - for (var j = 0; j < this.options.columns; j++ ) { - var ch = this.screen[i][j]; - if ( ch[0] != 0 ) { - str += String.fromCharCode(ch[0]); - } - } - } - return str; - }, - - clear: function() { - this.rpos = 0; - this.cpos = 0; - this.screen = []; - this.element.html(''); - this.screen[0] = this.fillRow(this.options.columns, 0); - this.paint(0); - }, - - typingOn: function() { this.typing = true; }, - typingOff: function() { this.typing = false; }, - - cursorOn: function() { - if ( this.blinker ) { - clearInterval( this.blinker ); - } - this.underblink = this.screen[this.rpos][this.cpos][1]; - MouseApp.Manager.activeTerm.blink(); - this.blinker = setInterval(function(){MouseApp.Manager.activeTerm.blink();}, this.options.blinkRate); - this.cursor = true; - }, - - cursorOff: function() { - if ( this.blinker ) { - clearInterval( this.blinker ); - } - if ( this.cursor ) { - this.screen[this.rpos][this.cpos][1] = this.underblink; - this.paint(this.rpos); - this.cursor = false; - } - }, - - blink: function() { - if ( this == MouseApp.Manager.activeTerm ) { - var mode = this.screen[this.rpos][this.cpos][1]; - this.screen[this.rpos][this.cpos][1] = ( mode & 1 ) ? mode & 4094 : mode | 1; - this.paint(this.rpos); - } - }, - - fillRow: function(len, ch, mode) { - ary = [] - for (var i = 0; i < len; i++) { - ary[i] = [ch, mode]; - } - return ary; - }, - - paint: function(start, end) { - if (!this.painting) return; - - if (!end) end = start; - for (var row = start; row <= end && row < this.screen.length; row++) { - var html = ''; - var mode = 0; - var fcolor = 0; - var bcolor = 0; - var spans = 0; - for (var i = 0; i < this.options.columns; i++ ) { - var c = this.screen[row][i][0]; - var m = this.screen[row][i][1] & 15; // 4 mode bits - var f = (this.screen[row][i][1] & (15 << 4)) >> 4; // 4 foreground bits - var b = (this.screen[row][i][1] & (15 << 8)) >> 8; // 4 background bits - if ( m != mode ) { - if ( MouseApp.Modes[mode] ) html += ""; - if ( MouseApp.Modes[m] ) html += "<" + MouseApp.Modes[m] + ">"; - mode = m; - } - if ( ( f != fcolor && f == 0 ) || ( b != bcolor && b == 0 ) ) { - for ( var s = 0; s < spans; s++ ) html += ""; - fcolor = 0; bcolor = 0; - } - if ( f != fcolor ) { - if ( MouseApp.Colors[f] ) { - html += ""; - spans++; - } - fcolor = f; - } - if ( b != bcolor ) { - if ( MouseApp.Colors[b] ) html += ""; - spans++; bcolor = b; - } - html += MouseApp.CharCodes[c] ? MouseApp.CharCodes[c] : String.fromCharCode(c); - } - if ( MouseApp.Modes[mode] ) html += ""; - for ( var s = 0; s < spans; s++ ) html += ""; - var new_id = this.element.attr('id') + '_' + row; - if (!$('#' + new_id).get(0)) { - this.element.append("
                   
                  "); - this.scrollAllTheWayDown(); - } - $('#' + new_id).html(html); - } - }, - - onAfterKey: function() { - this.scrollAllTheWayDown(); - }, - - highlightLine: function(i) { - if (i >= 0 && i < this.screen.length) - { - $("#" + this.element.attr('id') + "_" + i); - } - }, - - scrollToLine: function(i) { - var p = this.element[0].parentNode; - if ( p.scrollHeight > p.clientHeight ) { - p.scrollTop = (p.scrollHeight - p.clientHeight); - } - }, - - scrollAllTheWayDown: function() { - var p = this.element[0].parentNode; - if ( p.scrollHeight > p.clientHeight ) { - p.scrollTop = (p.scrollHeight - p.clientHeight); - } - }, - - putc: function(ch, mode) { - if ( ch == 13 ) { - return; - } else if ( ch == 10 ) { - this.screen[this.rpos][this.cpos] = [ch, mode]; - this.advanceLine(); - } else { - this.screen[this.rpos][this.cpos] = [ch, mode]; - this.paint(this.rpos); - this.advance(); - } - }, - - zpad: function(n) { - if (n < 10) n = "0" + n; - return n; - }, - - puts: function(str, mode) { - if ( !str ) return; - var p = this.painting; - var r = this.rpos; - this.painting = false; - for ( var i = 0; i < str.length; i++ ) { - this.insertc(str.charCodeAt(i), mode); - } - this.painting = p; - this.paint(r, this.rpos); - }, - - advance: function() { - this.cpos++; - if ( this.cpos >= this.options.columns ) { - this.advanceLine(); - } - }, - - advanceLine: function() { - this.cpos = 0; - this.rpos++; - this.ensureRow(this.rpos); - this.paint(this.rpos, this.screen.length - 1); - }, - - fwdc: function() { - var r = this.rpos; - var c = this.cpos; - if ( c < this.options.columns - 1 ) { - c++; - } else if ( r < this.screen.length - 1 ) { - r++; - c = 0; - } - var ch = (c == 0 ? this.screen[r-1][this.options.columns-1] : this.screen[r][c-1]); - if ( MouseApp.isPrintable(ch[0]) ) { - this.rpos = r; - this.cpos = c; - } - }, - - fwdLine: function() { - if ( this.rpos >= this.screen.length - 1 ) return; - this.rpos++; - while ( this.cpos > 0 && !MouseApp.isPrintable(this.screen[this.rpos][this.cpos - 1][0]) ) { - this.cpos--; - } - }, - - backc: function() { - var r = this.rpos; - var c = this.cpos; - if ( c > 0 ) { - c--; - } else if ( r > 0 ) { - c = this.options.columns - 1; - r--; - } - if ( MouseApp.isPrintable(this.screen[r][c][0]) ) { - this.rpos = r; - this.cpos = c; - return true; - } - return false; - }, - - getTypingStart: function() { - var c = this.cpos; - if ( !MouseApp.isPrintable(this.screen[this.rpos][c][0]) ) { - c--; - } - var pos = null; - for ( var r = this.rpos; r >= 0; r-- ) { - while ( c >= 0 ) { - if ( !MouseApp.isPrintable(this.screen[r][c][0]) ) { - return pos; - } - pos = [r, c]; - c--; - } - c = this.options.columns - 1; - } - }, - - getTypingEnd: function(mod) { - var c = this.cpos; - if ( !MouseApp.isPrintable(this.screen[this.rpos][c][0]) ) { - c--; - } - var pos = null; - for ( var r = this.rpos; r < this.screen.length; r++ ) { - while ( c < this.options.columns ) { - if ( !this.screen[r] || !this.screen[r][c] || !MouseApp.isPrintable(this.screen[r][c][0]) ) { - if (!mod) return pos; - mod--; - } - pos = [r, c]; - c++; - } - c = 0; - } - }, - - getTypingAt: function(start, end) { - var r = start[0]; - var c = start[1]; - var str = ''; - while ( r < end[0] || c <= end[1] ) { - if ( c < this.options.columns ) { - str += String.fromCharCode(this.screen[r][c][0]); - c++; - } else { - c = 0; - r++; - } - } - return str; - }, - - ensureRow: function(r) { - if (!this.screen[r]) { - this.screen[r] = this.fillRow(this.options.columns, 0); - } - }, - - insertc: function(ch, mode) { - var r = this.rpos; var c = this.cpos; - var end = this.getTypingEnd(+1); - if (end) { - var thisc = null; - var lastc = this.screen[this.rpos][this.cpos]; - while ( r < end[0] || c <= end[1] ) { - if ( c < this.options.columns ) { - thisc = this.screen[r][c]; - this.screen[r][c] = lastc; - lastc = thisc; - c++; - } else { - c = 0; - r++; - this.ensureRow(r); - } - } - this.paint(this.rpos, end[0]); - } - this.putc(ch, mode); - }, - - delc: function() { - /* end of line */ - if ( MouseApp.isPrintable(this.screen[this.rpos][this.cpos][0]) ) { - var end = this.getTypingEnd(); - var thisc = null; - var lastc = [0, 0]; - while ( this.rpos < end[0] || this.cpos <= end[1] ) { - if ( end[1] >= 0 ) { - thisc = this.screen[end[0]][end[1]]; - this.screen[end[0]][end[1]] = lastc; - lastc = thisc; - end[1]--; - } else { - end[1] = this.options.columns - 1; - this.paint(end[0]); - end[0]--; - } - } - } - }, - - backspace: function() { - /* end of line */ - if ( !MouseApp.isPrintable(this.screen[this.rpos][this.cpos][0]) ) { - this.backc(); - this.screen[this.rpos][this.cpos] = [0, 0]; - } else { - if ( this.backc() ) this.delc(); - } - }, - - backLine: function() { - if ( this.rpos < 1 ) return; - this.rpos--; - while ( this.cpos > 0 && !MouseApp.isPrintable(this.screen[this.rpos][this.cpos - 1][0]) ) { - this.cpos--; - } - }, - - onKeyPress: function(e) { - var ch = e.keyCode; - var key_name = MouseApp.CodeKeys[ch]; - if (window.opera && !e.altKey && e.keyCode != 13 && e.keyCode != 8) key_name = null; - ch = (e.which || e.charCode || e.keyCode); - if (e.which) ch = e.which; - if (!key_name) { key_name = String.fromCharCode(ch); } - if (e.ctrlKey) { key_name = 'Ctrl' + key_name; } - - // alert([e.keyCode, e.which, key_name, this['onKey' + key_name]]); - if (this.typing && this.onAnyKey) this.onAnyKey(key_name); - if (key_name && this['onKey' + key_name]) { - if (this.typing) this['onKey' + key_name](); - MouseApp.Manager.blockEvent(e); - if (this.typing && this.onAfterKey) this.onAfterKey(key_name, true); - return false; - } - if (!e.ctrlKey) { - if (MouseApp.isPrintable(ch)) { - if (this.typing) this.insertc(ch, 0); - MouseApp.Manager.blockEvent(e); - if (this.typing && this.onAfterKey) this.onAfterKey(key_name, true); - return false; - } - } - if (this.typing && this.onAfterKey) this.onAfterKey(key_name, false); - return true; - }, - onKeyHome: function() { - var s = this.getTypingStart(); - this.rpos = s[0]; this.cpos = s[1]; - }, - onKeyEnd: function() { - var e = this.getTypingEnd(+1); - this.rpos = e[0]; this.cpos = e[1]; - }, - onKeyInsert: function() { }, - onKeyDelete: function() { this.delc(); }, - onKeyUp: function() { this.backLine(); }, - onKeyLeft: function() { this.backc(); }, - onKeyRight: function() { this.fwdc(); }, - onKeyDown: function() { this.fwdLine(); }, - onKeyBackspace: function() { this.backspace(); }, - onKeyEnter: function() { this.insertc(10, 0); }, - onKeyTab: function() { - this.insertc(32, 0); - while (this.cpos % this.options.indent != 0) this.insertc(32, 0); - } -}); - -/* Terminal running moush */ -MouseApp.Terminal = function(element, options) { - this.element = $(element); - this.setOptions(options); - this.initWindow(); - this.setup(); -}; - -$.extend(MouseApp.Terminal.prototype, MouseApp.Window.prototype, { - setup: function() { - this.history = []; - this.backupNum = this.historyNum = this.commandNum = 0; - if (this.onStart) { - this.onStart(); - } else { - this.write(this.options.greeting + "\n", true); - this.prompt(); - } - }, - - prompt: function(ps, pt) { - if (!ps) { - ps = this.options.ps; pt = true; - } - this.write(ps, pt); - this.putc(1, 0); - this.typingOn(); - }, - - getCommand: function() { - var s = this.getTypingStart(); - var e = this.getTypingEnd(); - if (!s || !e) return; - return this.getTypingAt(s, e); - }, - - clearCommand: function() { - var s = this.getTypingStart(); - var e = this.getTypingEnd(); - if (!s || !e) return; - var r = s[0]; - var c = s[1]; - this.rpos = r; this.cpos = c; - while ( r < e[0] || c <= e[1] ) { - if ( c < this.options.columns ) { - this.screen[r][c] = [0, 0]; - c++; - } else { - c = 0; - this.paint(r); - r++; - } - } - this.paint(r); - }, - - write: function(str, pcodes) { - var p = this.painting; - var r = this.rpos; - this.painting = false; - var mode = 0; - var today = new Date(); - for ( var i = 0; i < str.length; i++ ) { - if ( str.substr(i,1) == "\n" ) { - this.advanceLine(); - continue; - } else if ( str.substr(i,1) == "\033" ) { - if ( str.substr(i+1,2) == "[m" ) { - mode = 0; - i += 2; - continue; - } - if ( str.substr(i+1,5) == "[0;0m" ) { - mode = 0; - i += 5; - continue; - } - var colors = str.substr(i+1,7).match(/^\[(\d);(\d+)m/); - if ( colors ) { - var colCode = parseInt( colors[2] ); - var color = colCode % 10; - if ( colors[1] == '1' ) { - color += 8; - } - if ( colCode / 10 == 4 ) { - color = color << 4; - } - mode = (mode & 15) + color << 4; - i += colors[0].length; - continue; - } - } else if ( str.substr(i,1) == '%' && pcodes ) { - var s2 = str.substr(i,2); - switch ( s2 ) { - case '%h': - this.puts(this.options.host, mode); - i++; - continue; - case '%l': - this.puts(this.options.name, mode); - i++; - continue; - case '%n': - this.advanceLine(); - i++; - continue; - case '%s': - this.puts("moush", mode); - i++; - continue; - case '%t': - this.puts(this.zpad(today.getHours()) + ":" + this.zpad(today.getMinutes()) + ":" + - this.zpad(today.getSeconds()), mode); - i++; - continue; - case '%u': - this.puts(this.options.user, mode); - i++; - continue; - case '%v': - this.puts(MouseApp.Version, mode); - i++; - continue; - case '%!': - this.puts(this.historyNum.toString(), mode); - i++; - continue; - case '%#': - this.puts(this.commandNum.toString(), mode); - i++; - continue; - case '%+': - var kind = str.substr(i+2, 1); - if ( MouseApp.ModeIds[kind] ) { - mode = mode | MouseApp.ModeIds[kind]; - i += 2; - continue; - } - break; - case '%-': - var kind = str.substr(i+2, 1); - if ( MouseApp.ModeIds[kind] ) { - mode = mode & ( 4095 - MouseApp.ModeIds[kind] ); - i += 2; - continue; - } - break; - } - } - this.putc(str.charCodeAt(i), mode); - } - this.painting = p; - this.paint(r, this.rpos); - }, - - onKeyUp: function() { - if ( this.backupNum == 0 ) return; - if ( this.backupNum == this.historyNum ) { - this.history[this.historyNum] = this.getCommand(); - } - this.clearCommand(); - this.backupNum--; - this.puts(this.history[this.backupNum]); - }, - onKeyDown: function() { - if ( this.backupNum >= this.historyNum ) return; - this.clearCommand(); - this.backupNum++; - this.puts(this.history[this.backupNum]); - }, - onKeyEnter: function() { - var cmd = this.getCommand(); - if (cmd) { - this.history[this.historyNum] = cmd; - this.backupNum = ++this.historyNum; - } - this.commandNum++; - this.advanceLine(); - if (cmd) { - var str = this.onCommand(cmd); - if (str) { - if ( str.substr(str.length - 1, 1) != "\n" ) { - str += "\n"; - } - this.write(str); - } - } - this.prompt(); - }, - onCommand: function(line) { - // this.puts("Echoing: " + line + "\n"); - if ( line == "clear" ) { - this.clear(); - } else { - return "\033[1;37m\033[0;44mYou typed:\033[m " + line; - } - } -}); - -/* Notepad sort of editor */ -MouseApp.Notepad = function(element, options) { - this.element = $(element); - this.setOptions(options); - this.initWindow(); - this.history = []; - this.lineno = 0; -}; - -$.extend(MouseApp.Notepad.prototype, MouseApp.Window.prototype, { - csave: function() { - if ( this.cpos_save ) { - this.cpos = this.cpos_save; - } else { - this.cpos_save = this.cpos; - } - }, - onKeyUp: function() { if ( this.rpos < 1 ) { return; } this.csave(); this.backLine(); }, - onKeyDown: function() { if ( this.rpos < this.screen.length - 1 ) { this.csave(); this.fwdLine(); } }, - onAfterKey: function(key, st) { - if ( st && !(key == 'Up' || key == 'Down') ) { - this.cpos_save = null; - } - }, - insertc: function(ch, mode) { - if (ch == 10) { - this.element.append("
                   
                  "); - this.screen.splice(this.rpos + 1, 0, this.fillRow(this.options.columns, 0)); - var c = this.cpos; var c2 = 0; - while (c < this.options.columns) - { - if (this.screen[this.rpos][c] == 0) break; - this.screen[this.rpos + 1][c2] = this.screen[this.rpos][c]; - this.screen[this.rpos][c] = [0, 0]; - c++; c2++; - } - this.paint(this.rpos); - if (MouseApp.isPrintable(this.screen[this.rpos][c])) - { - var r = this.rpos; var c = this.cpos; - this.rpos += 1; this.cpos = c2; - this.delc(); - this.rpos = r; this.cpos = c; - } - this.putc(ch, mode); - if (this.rpos == this.screen.length - 1) - this.scrollAllTheWayDown(); - } else { - var c = this.cpos + 1; - var lastc = this.screen[this.rpos][this.cpos]; - this.putc(ch, mode); - for ( var r = this.rpos; r < this.screen.length; r++ ) { - while (c < this.options.columns) - { - var tmpc = this.screen[r][c]; - if (lastc[0] == 0) - break; - this.screen[r][c] = lastc; - lastc = tmpc; - c++; - } - if (c < this.options.columns) { - break; - } - c = 0; - } - } - }, - - backc: function() { - var r = this.rpos; - var c = this.cpos - 1; - for ( var r = this.rpos; r >= 0; r-- ) { - while ( c >= 0 ) { - this.rpos = r; - this.cpos = c; - if ( this.screen[r][c][0] != 0 ) { - this.paint(r); - return true; - } - this.screen[r][c] = [0, 0]; - c--; - } - c = this.options.columns - 1; - } - return false; - }, - delc: function() { - var c = this.cpos + 1; - for ( var r = this.rpos; r < this.screen.length; r++ ) { - while ( c < this.options.columns ) { - if ( this.screen[r][c][0] != 0 ) { - break; - } - c++; - } - if ( c < this.options.columns ) break; - c = 0; - } - - if (r >= this.screen.length) return; - - var r2 = this.rpos; - var c2 = this.cpos; - for ( var r2 = this.rpos; r2 < this.screen.length; r2++ ) { - while (c2 < this.options.columns) - { - if (this.screen[r][c][0] == 0) - break; - this.screen[r2][c2] = this.screen[r][c]; - c2++; - c++; - if (c >= this.options.columns) { - r++; - if (r >= this.options.rows) break; - c = 0; - } - } - if (c2 < this.options.columns) { - while (c2 < this.options.columns) { - this.screen[r2][c2] = [0, 0]; - c2++; - } - break; - } - c2 = 0; - } - - if (r != r2 && r < this.screen.length) - { - this.screen.splice(r, 1); - $("#" + this.element.attr('id') + "_" + this.screen.length).remove(); - } - this.paint(this.rpos, this.screen.length); - }, - onKeyBackspace: function() { - if (this.backc()) this.delc(); - } - -}); diff --git a/non-rack-legacy/public/js/mouseirb_2.js b/non-rack-legacy/public/js/mouseirb_2.js deleted file mode 100755 index 0fa5f12..0000000 --- a/non-rack-legacy/public/js/mouseirb_2.js +++ /dev/null @@ -1,179 +0,0 @@ -// -// Copyright (c) 2008 why the lucky stiff -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, -// and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -// SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT -// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -/* Irb running moush */ -MouseApp.Irb = function(element, options) { - this.element = $(element); - this.setOptions(options); - this.showHelp = this.options.showHelp; - if ( this.options.showChapter ) { - this.showChapter = this.options.showChapter; - } - if ( this.options.init ) { - this.init = this.options.init; - } - this.initWindow(); - this.setup(); - this.helpPage = null; - this.irbInit = false; -}; - -$.extend(MouseApp.Irb.prototype, MouseApp.Terminal.prototype, { - cmdToQuery: function(cmd) { - return "cmd=" + escape(cmd.replace(/</g, '<').replace(/>/g, '>'). - replace(/&/g, '&').replace(/\r?\n/g, "\n")).replace(/\+/g, "%2B"); - }, - - fireOffCmd: function(cmd, func) { - var irb = this; - if (!this.irbInit) - { - $.ajax({url: this.options.irbUrl + "?" + this.cmdToQuery("!INIT!IRB!"), type: "GET", - complete: (function(r) { irb.irbInit = true; irb.fireOffCmd(cmd, func); })}); - } - else - { - $.ajax({url: this.options.irbUrl + "?" + this.cmdToQuery(cmd), type: "GET", - complete: func}); - } - }, - - reply: function(str) { - var raw = str.replace(/\033\[(\d);(\d+)m/g, ''); - this.checkAnswer(raw); - if (!str.match(/^(\.\.)+$/)) { - if ( str[str.length - 1] != "\n" ) { - str += "\n"; - } - js_payload = /\033\[1;JSm(.*)\033\[m/; - js_in = str.match(js_payload); - if (js_in) { - try { - js_in = eval(js_in[1]); - } catch (e) {} - str = str.replace(js_payload, ''); - } - var pr_re = new RegExp("(^|\\n)=>"); - if ( str.match( pr_re ) ) { - str = str.replace(new RegExp("(^|\\n)=>"), "$1\033[1;34m=>\033[m"); - } else { - str = str.replace(new RegExp("(^|\\n)= (.+?) ="), "$1\033[1;33m$2\033[m"); - } - this.write(str); - this.prompt(); - } else { - this.prompt("\033[1;32m" + ".." + "\033[m", true); - this.puts(str.replace(/\./g, ' '), 0); - } - }, - - setHelpPage: function(n, page) { - if (this.helpPage) - $(this.helpPage.ele).hide('fast'); - this.helpPage = {index: n, ele: page}; - match = this.scanHelpPageFor('load'); - if (match != -1) - { - this.fireOffCmd(match, (function(r) { - $(page).show('fast'); - })); - } - else - { - $(page).show('fast'); - } - }, - - scanHelpPageFor: function(eleClass) { - match = $("div." + eleClass, this.helpPage.ele); - if ( match[0] ) return match[0].innerHTML; - else return -1; - }, - - checkAnswer: function(str) { - if ( this.helpPage ) { - match = this.scanHelpPageFor('answer'); - if ( match != -1 ) { - if ( str.match( new RegExp('^\s*=> ' + match + '\s*$', 'm') ) ) { - this.showHelp(this.helpPage.index + 1); - } - } else { - match = this.scanHelpPageFor('stdout'); - if ( match != -1 ) { - if ( match == '' ) { - if ( str == '' || str == null ) this.showHelp(this.helpPage.index + 1); - } else if ( str.match( new RegExp('^\s*' + match + '$', 'm') ) ) { - this.showHelp(this.helpPage.index + 1); - } - } - } - } - }, - - onKeyCtrld: function() { - this.clearCommand(); - this.puts("reset"); - this.onKeyEnter(); - }, - - onKeyEnter: function() { - this.typingOff(); - var cmd = this.getCommand(); - if (cmd) { - this.history[this.historyNum] = cmd; - this.backupNum = ++this.historyNum; - } - this.commandNum++; - this.advanceLine(); - if (cmd) { - if ( cmd == "clear" ) { - this.clear(); - this.prompt(); - } else if ( cmd.match(/^(back)$/) ) { - if (this.helpPage && this.helpPage.index >= 1) { - this.showHelp(this.helpPage.index - 1); - } - this.prompt(); - } else if ( cmd.match(/^(next)$/) ) { - if (this.helpPage) { - this.showHelp(this.helpPage.index + 1); - } - this.prompt(); - } else if ( cmd.match(/^(help|wtf\?*)$/) ) { - this.showHelp(1); - this.prompt(); - } else if ( regs = cmd.match(/^(help|wtf\?*)\s+#?(\d+)\s*$/) ) { - this.showChapter(parseInt(regs[2])); - this.prompt(); - } else { - var term = this; - this.fireOffCmd(cmd, (function(r) { term.reply(r.responseText ? r.responseText : ''); })); - } - } else { - this.prompt(); - } - } -}); - diff --git a/non-rack-legacy/public/keypress_test.html b/non-rack-legacy/public/keypress_test.html deleted file mode 100644 index 7297c4d..0000000 --- a/non-rack-legacy/public/keypress_test.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - -

                  Press a key, the details will be displayed below

                  -
                  - - - diff --git a/non-rack-legacy/public/moods/index.html b/non-rack-legacy/public/moods/index.html deleted file mode 100755 index e933af9..0000000 --- a/non-rack-legacy/public/moods/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -

                  you shouldn't be here.. kicking you out!

                  - - diff --git a/non-rack-legacy/public/moods/sick.gif b/non-rack-legacy/public/moods/sick.gif deleted file mode 100755 index 217a67cbae60740fdc90b92e06b977cf7fc56699..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 94 zcmZ?wbhEHb|6B#{self.text}" - end - - end - - class Link - attr_accessor :text, :target - def initialize(text, target) - self.text, self.target = text, target - end - def generate_html - "#{text}" - end - - - end - - class List - attr_accessor :elements - def initialize(elements) - self.elements = elements - end - - def generate_html - items = elements.map do |elem| - text = elem.instance_of?(Paragraph) ? elem.text : elem.generate_html - "
                2. #{text}
                3. " - end.join(" ") - - "
                    #{items}
                  " - end - end - - - class Paragraph - attr_accessor :text - def initialize(text) - self.text = text - end - - def generate_html - "

                  #{self.text}

                  " - end - end - - - class ComplexPopup - attr_reader :elements - def initialize - @elements = [] - end - - (1..6).each do |n| - define_method "h#{n}".to_sym do |text| - @elements << Header.new(n, text) - end - end - - - # def h1 text - # @elements << Header.new(1, text) - # end - - def link(text, target) - @elements << Link.new(text, target) - end - - def p(text) - @elements << Paragraph.new(text) - end - - def list(&block) - lst = ComplexPopup.new - lst.instance_eval(&block) - @elements << List.new(lst.elements) - end - - def generate_html() - @elements.map(&:generate_html).join(" ") - end - - - - end - - - def self.make(&block) - result = ComplexPopup.new - result.instance_eval(&block) - - html = result.generate_html.gsub('\\', '\\\\').gsub('"', '\"') - command = "window.irb.options.popup_make(\"#{html}\")" - TryRuby::Output.javascript command - end - -end diff --git a/non-rack-legacy/public/setup.rb b/non-rack-legacy/public/setup.rb deleted file mode 100644 index 10c1a39..0000000 --- a/non-rack-legacy/public/setup.rb +++ /dev/null @@ -1,67 +0,0 @@ -module TryRuby -SetupCode = < p:first-child{ - margin-top:0; -} -#facebox .content > p:last-child{ - margin-bottom:0; -} - -#facebox .close{ - position:absolute; - top:5px; - right:5px; - padding:2px; - background:#fff; -} -#facebox .close img{ - opacity:0.3; -} -#facebox .close:hover img{ - opacity:1.0; -} - -#facebox .loading { - text-align: center; -} - -#facebox .image { - text-align: center; -} - -#facebox img { - border: 0; - margin: 0; -} - -#facebox_overlay { - position: fixed; - top: 0px; - left: 0px; - height:100%; - width:100%; -} - -.facebox_hide { - z-index:-100; -} - -.facebox_overlayBG { - background-color: #000; - z-index: 99; -} -.facebox-footnote{ - margin-top:40px; -} \ No newline at end of file diff --git a/non-rack-legacy/public/stylesheets/reset.css b/non-rack-legacy/public/stylesheets/reset.css deleted file mode 100644 index d709810..0000000 --- a/non-rack-legacy/public/stylesheets/reset.css +++ /dev/null @@ -1,46 +0,0 @@ -html, body, div, span, applet, object, iframe, -h1, h2, h3, h4, h5, h6, p, blockquote, pre, -a, abbr, acronym, address, big, cite, code, -del, dfn, em, font, img, ins, kbd, q, s, samp, -small, strike, strong, sub, sup, tt, var, -dl, dt, dd, ol, ul, li, -fieldset, form, label, legend, -table, caption, tbody, tfoot, thead, tr, th, td { - margin: 0; - padding: 0; - border: 0; - outline: 0; - font-weight: inherit; - font-style: inherit; - font-size: 100%; - font-family: inherit; - vertical-align: baseline; -} -/* remember to define focus styles! */ -:focus { - outline: 0; -} -body { - line-height: 1; - color: black; - background: white; -} -ol, ul { - list-style: none; -} -/* tables still need 'cellspacing="0"' in the markup */ -table { - border-collapse: separate; - border-spacing: 0; -} -caption, th, td { - text-align: left; - font-weight: normal; -} -blockquote:before, blockquote:after, -q:before, q:after { - content: ""; -} -blockquote, q { - quotes: "" ""; -} diff --git a/non-rack-legacy/public/stylesheets/scaffold.css b/non-rack-legacy/public/stylesheets/scaffold.css deleted file mode 100644 index 1ae7000..0000000 --- a/non-rack-legacy/public/stylesheets/scaffold.css +++ /dev/null @@ -1,56 +0,0 @@ -body { background-color: #fff; color: #333; } - -body, p, ol, ul, td { - font-family: verdana, arial, helvetica, sans-serif; - font-size: 13px; - line-height: 18px; -} - -pre { - background-color: #eee; - padding: 10px; - font-size: 11px; -} - -a { color: #000; } -a:visited { color: #666; } -a:hover { color: #fff; background-color:#000; } - -div.field, div.actions { - margin-bottom: 10px; -} - -#notice { - color: green; -} - -.field_with_errors { - padding: 2px; - background-color: red; - display: table; -} - -#error_explanation { - width: 450px; - border: 2px solid red; - padding: 7px; - padding-bottom: 0; - margin-bottom: 20px; - background-color: #f0f0f0; -} - -#error_explanation h2 { - text-align: left; - font-weight: bold; - padding: 5px 5px 5px 15px; - font-size: 12px; - margin: -7px; - margin-bottom: 0px; - background-color: #c00; - color: #fff; -} - -#error_explanation ul li { - font-size: 12px; - list-style: square; -} diff --git a/non-rack-legacy/public/stylesheets/site.css b/non-rack-legacy/public/stylesheets/site.css deleted file mode 100755 index 62b1526..0000000 --- a/non-rack-legacy/public/stylesheets/site.css +++ /dev/null @@ -1,378 +0,0 @@ -body { - font-family: verdana, arial, sans-serif; - font-size: 14px; - text-align: center; -} -h1, h2, h3, h4 { - font-family: georgia, serif; - margin: 10px 45px; padding: 0; -} -h1 { - color: #333; - font-size: 48px; - font-weight: normal; - margin: 10px 0px; -} -h3 { - color: white; - font-size: 21px; - font-weight: normal; -} -a,a:link,a:visited { - text-decoration: none; - color: #57ad11; -} -a:hover { - text-decoration: underline; - color: #57ad11; -} -a:active { - text-decoration: underline; - color: #dddddd; -} -input.keyboard-selector-input { - position: fixed; - top: 0; - _position: absolute; - _top: expression(eval(document.body.scrollTop)); - left: -300px; -} -.container { - width: 678px; - margin: 0 auto; - text-align: left; -} -.content { - width: 712px; - background: url(/images/tile.png) repeat-y; -} -#lilBrowser { - position: absolute; - background-color: white; - top: -540px; - left: -440px; - width: 510px; - height: 430px; - padding: 5px; - border: solid 1px #444; - z-index: 100; -} -h3#lbTitle { - color: #444; - font-family: verdana, arial, sans-serif; - font-size: small; - float:left; - line-height: 90%; - margin: 0; padding: 3px; -} -p#lbClose { - font-size: small; - float: right; - margin: 0; padding: 3px; -} -p#lbClose a { - display: inline; -} -.shellwin { - width: 712px; - padding-left: 12px; - background: url(/images/background.png) no-repeat; -} - -/* tutorial panes */ -.stretcher { - color: #f1f1ff; - display: none; - margin: 0; - padding: 0; - padding-left: 12px; - background: url(/images/tile.png) repeat-y; -} -.stretcher a, .stretcher a:link, .stretcher a:visited, .stretcher a:active { - text-decoration: none; - color: #a7ed91; -} -.stretcher a:hover { - text-decoration: underline; - color: #b7fd91; -} -.stretcher p { - margin: 10px 16px; -} -.stretcher dl, .stretcher ul { - background-color: white; - color: #333; - padding: 4px 8px; - font-size: 12px; - margin-left: 16px; - list-style: none; -} -.stretcher li { - margin: 6px; -} -.stretcher p code { - background-color: #874a20; - color: #fedeec; - padding: 1px 4px; -} -.stretcher p code.cmd { - background-color: #eeeeec; - color: #204a87; -} -.stretcher dt { - font-weight: bold; -} - -.chapmark { - padding: 6px 0; - margin-left: 12px; - margin-right: 22px; - color: #553; - background: #efefe1; -} -.chapmark h3 { - color: #335; -} -.chapmark a, .chapmark a:link, .chapmark a:visited, .chapmark a:active { - text-decoration: none; - color: #372d61; -} -.chapmark a:hover { - text-decoration: underline; - color: #477d51; -} -.note { color: #ddc; text-align: center; font-size: xx-small; } -ul li strong { color: #286; border-bottom: solid 2px #cca; } -ul li code { background-color: #f1f1f1; padding: 1px 3px; border-bottom: solid 2px #ddd; } -ul li code.faded { color: #899; } -code strong { background-color: #dcffb9; padding: 1px 3px; } -ul.commands li strong { display: block; float: left; width: 60px; border: none; } - -/* irb terminal */ -.terminal { - background-color: #ffffff; - border: solid 1px #204a87; - width: 678px; - height: 240px; - overflow: auto; -} -.console { - padding: 4px; margin-left: -50px; - font-family: "Andale Mono", courier, fixed, monospace; - font-size: 14px; - line-height: 16px; - color: #204a87; - text-align: left; - width: 664px; - height:220px; -} - -.console div b { - background-color: #874a20; - color: #fedeac; -} -div.answer, div.stdout, div.no_answer, div.load { - display: none; -} - -/* terminal escape colors */ -span.fore_black { color: #2e3436; } -span.fore_dark_gray { color: #888a85; } -span.fore_gray { color: #babdb6; } -span.fore_white { color: #eeeeec; } -span.fore_blue { color: #204a87; } -span.fore_lt_blue { color: #729fcf; } -span.fore_green { color: #788600; font-weight: bold; } -span.fore_lt_green { color: #cbe134; } -span.fore_cyan { color: #c4a000; } /* using cyan for yellows */ -span.fore_lt_cyan { color: #fc994f; } -span.fore_red { color: #a40000; } -span.fore_lt_red { color: #ef2929; font-weight: bold; } -span.fore_purple { color: #5c3566; } -span.fore_lt_purple { color: #ad7fa8; } -span.fore_brown { color: #8f5972; } -span.fore_lt_brown { color: #b9b9de; } -span.back_black { background-color: #2e3436; } -span.back_dark_gray { background-color: #888a85; } -span.back_gray { background-color: #babdb6; } -span.back_white { background-color: #eeeeec; } -span.back_blue { background-color: #204a87; } -span.back_lt_blue { background-color: #729fcf; } -span.back_green { background-color: #788600; } -span.back_lt_green { background-color: #cbe134; } -span.back_cyan { background-color: #c4a000; } /* using cyan for yellows */ -span.back_lt_cyan { background-color: #fce94f; } -span.back_red { background-color: #a40000; } -span.back_lt_red { background-color: #ef2929; } -span.back_purple { background-color: #5c3566; } -span.back_lt_purple { background-color: #ad7fa8; } -span.back_brown { background-color: #8f5902; } -span.back_lt_brown { background-color: #b9b96e; } - -/** no ways***/ - -div.main-wrapper-bottom { - height:4px;background-position: 0px -80px; background-repeat: no-repeat; - font-size:0 /* IE6, go figure */ -} -div.main-wrapper-borders { - background-position: -1731px 0; padding:15px; - background-repeat:repeat-y; -} -div.console-wrapper { - margin:0px auto ;width:566px; - cursor:text; - font-family:monospace; -} -div.console-wrapper-top { - height:3px;background-position: -50px -48px; background-repeat: no-repeat; - font-size:0 /* IE6, go figure */ -} -div.console-wrapper-bottom { - height:3px;background-position: -50px -51px; background-repeat: no-repeat; - font-size:0 /* IE6, go figure */ -} -div.console-wrapper-borders { - background-position: 0px 0px; padding:1px; - background-repeat:repeat-y; -} -div.guide-wrapper { - color:#fff; width:566px;margin-left:2px -} -div.guide-wrapper-top { - height:4px;background-position: 0 -65px; - font-size:0 /* IE6, go figure */ -} -div.guide-wrapper-bottom { - height:4px;background-position: 0 -70px; - font-size:0 /* IE6, go figure */ -} -div.guide-wrapper-borders { - background-position: -1166px 0px;padding:15px; - background-repeat:repeat-y; -} - -div.footer-wrapper-borders { - background-position: -566px 0px; padding:10px; - background-repeat:repeat-y; - font-size:12px -} -h1.main-header { - text-indent:-9999px; background-position: -49px 0px; - background-repeat: no-repeat; - width:318px; height:48px; margin-bottom:20px; - float:left -} - -div.footer { - line-height: 1.3em; -} - div.console div.jquery-console-inner -{ height:100%; overflow:auto; background:white} -div.console div.jquery-console-prompt-box -{ color:#437375; font-family:monospace; margin-top:0.5em; } -div.console div.jquery-console-prompt-box .prompt-done -{ cursor: pointer } -div.console div.jquery-console-prompt-box .prompt-done:hover -{ background:#453D5B; color: white; } -div.console div.jquery-console-focus span.jquery-console-cursor -{ background:#666; color:#fff; } -div.console div.jquery-console-message-error { - color:#ef0505; font-family:sans-serif; font-weight:bold; - padding-top:0.25em -} -div.console div.jquery-console-message-value -{ color:#000; font-family:monospace;padding-top:0.25em; font-weight: bold; } -div.console div.jquery-console-message-type -{ color:#382567; font-family:monospace;padding-left:0em;padding-top:0.25em; font-size:.9em } -div.console span.jquery-console-prompt-label { font-weight:bold } -div.console div.jquery-console-welcome { font-family:"DejaVu Sans",sans-serif; } - -div.share-wrapper { font-size:12px;padding:10px 0em 0em 10px } -div.share-wrapper strong { font-weight: bold } - -.clearfix:after { content:"."; display:block; height:0; clear:both; visibility:hidden } -div.menu { - float:right; - margin-right:2px; - margin-top:40px; - margin-bottom:5px -} -a.reset-btn { - float:left; - display:block; - width:59px; - height:24px; - background-position: -427px -18px; background-repeat: no-repeat; -} -a.reset-btn span { display:none } - -div.clear { clear:both } - - -div.console-wrapper .notice { - position:absolute; - bottom:0;right:0; - margin:1px; - background:#eee; - color:black; - padding:10px; - font-size:12px; - font-family:sans-serif; - font-weight:bold; -} -p.ajax-loader { background:url(../images/ajax-loader.gif); width:16px; height:16px;text-indent:-9999px } - -.notice a { padding:3px;background:#333;color:white} -.notice .action { text-align: right } - -/* Support Try Ruby! */ - - -a.trigger{ -position: absolute; -text-decoration: none; -top: 80px; right: 0; -font-size: 14px; -letter-spacing:-1px; -font-family: verdana, helvetica, arial, sans-serif; -color:#fff; -padding: 10px 10px 10px 10px; -font-weight: 500; -background:#333333 url(images/plus.png) 15% 55% no-repeat; -border:1px solid #444444; --moz-border-radius-topleft: 20px; --webkit-border-top-left-radius: 20px; --moz-border-radius-bottomleft: 20px; --webkit-border-bottom-left-radius: 20px; --moz-border-radius-bottomright: 0px; --webkit-border-bottom-right-radius: 0px; -display: block; -} - -a.trigger:hover{ -position: absolute; -text-decoration: none; -top: 80px; right: 0; -font-size: 14px; -letter-spacing:-1px; -font-family: verdana, helvetica, arial, sans-serif; -color:#fff; -padding: 10px 10px 10px 10px; -font-weight: 500; -background: green; -border:1px solid #444444; --moz-border-radius-topleft: 20px; --webkit-border-top-left-radius: 20px; --moz-border-radius-bottomleft: 20px; --webkit-border-bottom-left-radius: 20px; --moz-border-radius-bottomright: 0px; --webkit-border-bottom-right-radius: 0px; -display: block; -} - -a.active.trigger { -background:#222222 url(images/minus.png) 15% 55% no-repeat; -} - - \ No newline at end of file diff --git a/non-rack-legacy/public/test.rb b/non-rack-legacy/public/test.rb deleted file mode 100755 index 8810c18..0000000 --- a/non-rack-legacy/public/test.rb +++ /dev/null @@ -1,633 +0,0 @@ -#!/usr/bin/env ruby -require 'test/unit' -require 'rexml/document' -require 'hpricot' -load 'tryruby_runner.rb' - -class Integer - def weeks - self * 7*24*60*60 - end -end - - -def run_script(session,line) - session << line -end - -class TryRubyTestSession < TryRubyBaseSession - def initialize - reset - @current_includes = [] - end - - attr_accessor :start_time, :current_statement - attr_accessor :nesting_level, :past_commands, :current_includes -end - -$session = nil - -# This tests the TryRubyBaseSession#calculate_nesting_level function -class NestingLevelTest < Test::Unit::TestCase - def test_finished_statement_should_return_0 - t = TryRubyBaseSession.new - assert_equal(0, t.calculate_nesting_level("42")) - end - - def test_missing_end_should_return_1 - t = TryRubyBaseSession.new - assert_equal(1, t.calculate_nesting_level("3.times do")) - end - - def test_missing_close_brace_should_return_1 - t = TryRubyBaseSession.new - assert_equal(1, t.calculate_nesting_level("3.times {")) - end - - def test_open_class_should_return_1 - t = TryRubyBaseSession.new - assert_equal(1, t.calculate_nesting_level("class BlogEntry")) - end - - def test_closed_class_should_return_0 - t = TryRubyBaseSession.new - assert_equal(0, t.calculate_nesting_level("class BlogEntry\nend")) - end - - def test_2_unclosed_dos_should_return_2 - t = TryRubyBaseSession.new - assert_equal(2, t.calculate_nesting_level("3.times do\n4.times do")) - end - - def test_mix_of_opened_statements - t = TryRubyBaseSession.new - test_str = <<-EOF - class MyClass - def mymethod - 3.times do - 8.times { - EOF - assert_equal(4, t.calculate_nesting_level(test_str)) - end - - def test_open_and_close_on_same_line_should_return_0 - t = TryRubyBaseSession.new - assert_equal(0, t.calculate_nesting_level("3.times { puts 'lol' }")) - assert_equal(0, t.calculate_nesting_level("3.times do |v| puts 'lol'; end")) - end - - def test_half_statement - t = TryRubyBaseSession.new - assert_equal(1, t.calculate_nesting_level('true and')) - assert_equal(1, t.calculate_nesting_level('amethod(')) - end - -end - - -class TryRubyTest < Test::Unit::TestCase - # a test helper that simplifies testing the tryruby interpretor. - # It takes one optional argument session, which is the session to use for - # the test. - # It then takes a block. In the block a method input is available which is used - # to send a line to the interpretor and test the output. - # - # input takes one mandatory argument, the line, and some optional args: - # - output: The output of line should match this (defaults to "") - # - javascript: The line generated a javascript function, and should match this - # - error: The line generated an error and should match this - # - result: The line didn't generate an error or javascript, and should match this - # (defaults to nil if not supplied) - # - line_continuation: The line didn't complete, the current indent level - # should be equal to this (use true if you aren't interested in testing this) - # output, error, javascript and result can take either a: - # - Class: Tests if is the given type - # - Proc: Proc should take one param (the ) and run assertions with that value - # - Regexp: Tests (a string) against the regexp - # - : should equal - def tryruby_session(session = TryRubyTestSession.new, &block) - input_o = TryRubySession_Input.new - input_o.session = session - input_o.test = self - input_o.instance_eval(&block) - - end - - - def test_lesson1 - tryruby_session do - input '2 + 6' , result: 8 - input '"Jimmy"' , result: "Jimmy" - input '"Jimmy".reverse' , result: "ymmiJ" - input '"Jimmy".length' , result: 5 - input '"Jimmy" * 5' , result: "JimmyJimmyJimmyJimmyJimmy" - end - end - - # tests statements that should end with a line continuation - def test_line_continuations - tryruby_session do - input '3.times do |v|' , line_continuation: 1 - input '3.times { |v|', line_continuation: 2 - input '}; end', result: Proc.new {true} - input 'class MyClass', line_continuation: 1 - input "def mymethod", line_continuation: 2 - input "end; end", result: Proc.new{true} - end - end - - def test_lines_with_semicolons - tryruby_session do - input '3; 4', result: 4 - input 'puts "hello"; a = 4; 5', output: "hello\n", result: 5 - input 'a', result: 4 - input '; 42', result: 42 - end - end - - - def test_errors - tryruby_session do - input 'asdf', error: NameError, output: "" - input 'print "hello"; asdf', error: NameError, output: "hello" - end - end - - # tests statements that shouldn't end with a line continuation - def test_shouldnt_have_line_continuation - tryruby_session do - input "'helloclassend'", result: "helloclassend" - input "3.class", result: Class - end - end - - def test_illegal_ops - $session = TryRubyTestSession.new - tryruby_session $session do - input '`cat /etc/passwd`', illegal: true - input 'require "popup"', result: Proc.new{} - input '%x(cat /etc/passwd)', illegal: true - end - end - - - def test_lesson2 - tryruby_session do - input '40.reverse', error: NoMethodError - input '40.to_s.reverse', result: "04" - input '[]', result: [] - input '[12,47,35]', result: [12,47,35] - input '[12,47,35].max', result: 47 - input 'ticket = [12,47,35]', result: [12,47,35] - input 'ticket', result: [12,47,35] - input 'ticket.sort!', result: [12,35,47] - end - end - - def test_lesson3 - poem = <<-EOF -My toast has flown from my hand -And my toast has gone to the -moon. -But when I saw it on television, -Planting our flag on Halley's -comet, -More still did I want to eat it. -EOF - - tryruby_session do - # the below line should be done automatically by the interpretor - # when help 3 is loaded - # input "poem = #{poem.inspect}", result: Proc.new{} - - input 'print poem', output: poem - input "poem['toast'] = 'honeydew'", result: "honeydew" - input 'print poem', output: (poem['toast'] = 'honeydew'; poem) - input 'poem.reverse', result: poem.reverse - input 'poem.lines.to_a.reverse', result: poem.lines.to_a.reverse - input 'print poem.lines.to_a.reverse.join', output: poem.lines.to_a.reverse.join - end - end - - def test_lesson4 - tryruby_session do - input 'books = {}', result: {} - - input 'books["Gravity\'s Rainbow"] = :splendid', - result: :splendid - - input 'books["a"] = :mediocre', result: :mediocre - input 'books["b"] = :mediocre', result: :mediocre - input 'books["c"] = :mediocre', result: :mediocre - input 'books.length', result: 4 - input 'books["Gravity\'s Rainbow"]', result: :splendid - input 'books.keys', result: ["Gravity's Rainbow", "a", "b", "c"] - input 'ratings = Hash.new {0}', result: {} - - input 'books.values.each { |rate| ratings[rate] += 1 }', - result: [:splendid, :mediocre, :mediocre, :mediocre] - - input '5.times {print "Odelay!" }', - result: 5, - output: 'Odelay!Odelay!Odelay!Odelay!Odelay!' - - end - end - - def test_lesson5 - tryruby_session do - input 'Dir.entries "/"', - result: [".", "..", "Home", "Libraries", "MouseHole", "Programs", "Tutorials", - "comics.txt"] - input 'Dir["/*.txt"]', result: ["/comics.txt"] - comics_txt_text = <", value.inspect - } - input 'File.mtime("/Home/comics.txt")', result: Time - input 'File.mtime("/Home/comics.txt").hour', result: Fixnum - end - - end - - def test_lesson6 - $session = TryRubyTestSession.new - tryruby_session $session do - input 'def load_comics( path )', line_continuation: 1 - input 'comics = {}', line_continuation: 1 - input 'File.foreach(path) do |line|', line_continuation: 2 - input "name, url = line.split(': ')", line_continuation: 2 - input 'comics[name] = url.strip', line_continuation: 2 - input 'end', line_continuation: 1 - input 'comics', line_continuation: 1 - input 'end', result: nil - - input "comics = load_comics('/comics.txt')", result: - {"Achewood"=>"http://achewood.com/", - "Dinosaur Comics"=>"http://qwantz.com/", - "Perry Bible Fellowship"=>"http://cheston.com/pbf/archive.html" , - "Get Your War On"=>"http://mnftiu.cc/"} - - input "require 'popup'", result: Proc.new {} - input 'Popup.goto "http://google.com/"', - javascript: "window.irb.options.popup_goto(\"http://google.com/\")" - - input 'Popup.make {', line_continuation: 1 - input 'h1 "My Links"', line_continuation: 1 - input 'link "Go to Google", "http://google.com/"', line_continuation: 1 - input '}', javascript: - "window.irb.options.popup_make" + - "(\"

                  My Links

                  " + - "Go to Google\")" - - input 'Popup.make do', line_continuation: 1 - input 'h1 "Things To Do"', line_continuation: 1 - input 'list do', line_continuation: 2 - input 'p "Try out Ruby"', line_continuation: 2 - input 'p "Ride a tiger"', line_continuation: 2 - input 'p "(down River Euphrates)"', line_continuation: 2 - input 'end', line_continuation: 1 - expected = <Things To Do -
                  • Try out Ruby
                  • -
                  • Ride a tiger
                  • -
                  • (down River Euphrates) -
                  ") -EOF - input 'end', javascript: expected.gsub("\n", "") - -input 'Popup.make do', line_continuation: 1 -input 'h1 "Comics on the Web"', line_continuation: 1 -input 'list do', line_continuation: 2 -input 'comics.each do |name, url|', line_continuation: 3 -input 'link name, url', line_continuation: 3 -input 'end', line_continuation: 2 -input 'end', line_continuation: 1 -input 'end', javascript: Proc.new { |v| - matches = v.match(/^window.irb.options.popup_make\("(.*)"\)/) - assert_not_nil(matches) - html = matches[1].gsub(/\\(.)/, '\1') - doc = Hpricot(html) - assert_equal("Comics on the Web", (doc/:h1).inner_html) - list_items = (doc/:li/:a).map do |elem| - {href: elem.attributes['href'], title: elem.inner_html} - end - assert_equal({href: "http://achewood.com/", title: "Achewood"}, - list_items[0]) - assert_equal({href: "http://qwantz.com/", title: "Dinosaur Comics"}, - list_items[1]) - assert_equal({href: "http://cheston.com/pbf/archive.html", - title: "Perry Bible Fellowship"}, - list_items[2]) - assert_equal({href: "http://mnftiu.cc/", title: "Get Your War On"}, - list_items[3]) - - #assert_equal("", html) - } - - - - - end - - end - - - - - def test_lesson7_and_8 - $session = TryRubyTestSession.new - tryruby_session $session do - input 'Hash.new', result: {} - input 'class BlogEntry', line_continuation: 1 - input 'attr_accessor :title, :time, :fulltext, :mood', line_continuation: 1 - input 'end', result: nil - - # can't test for BlogEntry directly, as it isn't defined in this scope - input 'entry = BlogEntry.new', result: Proc.new {|v| - assert_equal("BlogEntry", v.class.name, - "line should result in a BlogEntry") - } - - input 'entry.title = "Today Mt. Hood Was Stolen!"', result: "Today Mt. Hood Was Stolen!" - - input 'entry.time = Time.now', result: Time - - input 'entry.mood = :sick', result: :sick - - str = <

                  My Blog

                  -
                    -
                  • Today Mt. Hood Was Stolen!

                  • -
                  • I can't believe Mt. Hood was stolen! I am speechless! - It was stolen by a giraffe who drove away in his - Cadillac Seville very nonchalant!!
                  • -
                  • I Left my Hoodie on the Mountain!

                  • -
                  • I am never going back to that mountain and - I hope a giraffe steals it.
                  • -
                  - EOF - - expected_xml = REXML::Document.new(expected_str.strip) - assert_match(/^window.irb.options.popup_make\(".*"\)?/m, - v, - "testing that Popup calls the correct javascript function") - actual_str = v.match(/^window.irb.options.popup_make\("(.*)"\);?/m)[1] - actual_str = "#{actual_str}" - actual_xml = REXML::Document.new(actual_str.strip) - assert_equal(expected_xml.write(StringIO.new).to_s, - actual_xml.write(StringIO.new).to_s, - "testing that html used with the javascript popup " + - "function is correct") - } - - input 'Time.now - 2.weeks', result: Time - - input 'File.read("/MouseHole/flickrpedia.user.rb")', result: String - - end # tryruby_session - - end # lesson6_and_7 - - - - - # class that performs the tests with the input sections of the - # tryrubysession test helper - class TryRubySession_Input - attr_accessor :session, :test - - # performs an assertion - # actual is the value being tested - # expected should either be a - # - Class: the class of actual should be expected - # - Regexp: actual (a string) should match the expected Regexp - # - Proc: A proc that takes one argument, actual. Assertions can - # be used inside that proc, eg assert_equal, assert. - # - : actual should equal expected - # name is the name of the input (result, output, javascript, error), - # used in messages - # line is the line being tested - def do_assert(actual, expected, name, line) - case expected - when Class - @test.assert_kind_of(expected, actual, - "Testing line `#{line}': #{name} should be a #{expected}") - when Regexp - @test.assert_match(expected, actual, - "Testing line `#{line}': #{name} should match #{expected}") - when Proc - @backtrace_pos = 0 - @test.instance_exec(actual, &expected) - - # @test.assert(expected.call(actual), - # "Testing line `#{line}': #{message} \n[#{actual}]") - else - @test.assert_equal(expected,actual, - "Testing line `#{line}' for correct #{name}") - end - end - - # runs the line using this objects session. - def do_test(line) - o = Object.new - # store the initial constants of Object - initial_constants = Object.constants - session = @session - - thread = Thread.new do - o.instance_eval do - run_script(session, line) - end - end - - result = thread.value - # restores require to its old functionality - #def Object.require(str) - # old_require(str) - #end - - # next 4 lines will revert Object to the way it was before - # run_script - diff_constants = Object.constants - initial_constants - diff_constants.each do |constant| - Object.send(:remove_const, constant) - end - result - end - - - # The input function, used with the tryruby_session test helper - # see tryruby_session for more details - def input(line, params = {}) - @backtrace_pos = 2 - params[:output] ||= "" - params[:result] ||= nil - params[:error] ||= nil - - result = do_test(line) - begin - if params[:illegal] then - @test.assert_equal(:illegal, result.type, - "Testing if line `#{line}' resulted in an illegal operation") - elsif params[:error] then - @test.assert_equal(:error, result.type, - "Testing if line `#{line}` resulted in an error") - do_assert(result.error, params[:error], "error", line) - do_assert(result.output, params[:output], "output", line) - elsif params[:javascript] then - @test.assert_nil(result.error, - "Testing line `#{line}' to ensure there was no error") - do_assert(result.javascript, params[:javascript], "javascript", line) - do_assert(result.output, params[:output], "output", line) - elsif params[:line_continuation] - @test.assert_equal(:line_continuation, result.type, - "Testing if line `#{line}' resulted in a line continuation") - if params[:line_continuation] != true then - @test.assert_equal(result.indent_level, params[:line_continuation], - "Testing if line `#{line}' triggered enough autoindent") - end - else - @test.assert_nil(result.error, - "Testing line `#{line}' to ensure there was no error") - do_assert(result.result, params[:result], "result" , line) - do_assert(result.output, params[:output], "output", line) - end - - rescue Test::Unit::AssertionFailedError => e - p e - - new_bt = Test::Unit::Util::BacktraceFilter.filter_backtrace(e.backtrace) - new_bt = new_bt[@backtrace_pos..@backtrace_pos] - e.set_backtrace(new_bt) - raise e - - end - end - end -end - -# tests if the TryRubyOutput translation, for use with mouseapp_2.js and similar -# is working correctly -class TryRubyOutputTest < Test::Unit::TestCase - def test_simple_result - t = TryRubyOutput.standard(result: [12,24]) - assert_equal("=> \033[1;20m[12, 24]", t.format_output) - end - - def test_result_and_output - t = TryRubyOutput.standard(result: 333, output: "hello") - assert_equal("hello=> \033[1;20m333", t.format_output) - end - - def test_error - begin - 40.reverse - rescue Exception => e - t = TryRubyOutput.error(error: e) - end - assert_equal("\033[1;33mNoMethodError: undefined method `reverse' for 40:Fixnum", - t.format_output) - end - - def test_error_with_output - begin - 40.reverse - rescue Exception => e - t = TryRubyOutput.error(error: e, output: "hello\nworld") - end - assert_equal("hello\nworld\033[1;33mNoMethodError: undefined method `reverse' for 40:Fixnum", - t.format_output) - end - - def test_illegal - t = TryRubyOutput.illegal - assert_equal("\033[1;33mYou aren't allowed to run that command!", - t.format_output) - end - - - - def test_line_continuation - t = TryRubyOutput.line_continuation(3) - assert_equal(".." * 3, t.format_output) - end - - def test_javascript - t = TryRubyOutput.javascript(javascript: 'alert("hello")') - # expected ends in a space to stop a visual problem in mouseapp - assert_equal("\033[1;JSmalert(\"hello\")\033[m ", t.format_output) - end - -end diff --git a/non-rack-legacy/public/images/index.html b/non-rack-legacy/public/tmp/index.html similarity index 100% rename from non-rack-legacy/public/images/index.html rename to non-rack-legacy/public/tmp/index.html diff --git a/non-rack-legacy/public/tryruby.rb b/non-rack-legacy/public/tryruby.rb deleted file mode 100644 index 4b9bbcb..0000000 --- a/non-rack-legacy/public/tryruby.rb +++ /dev/null @@ -1,174 +0,0 @@ -#$LOAD_PATH.unshift File.join(File.dirname(__FILE__), 'submodules', 'fakefs', 'lib') -require './setup.rb' -require 'ruby_parser' -require './fakefs/safe' -require 'stringio' - -module TryRuby - extend self - - class Session - attr_accessor :past_commands, :current_statement, :start_time - def initialize - @past_commands = '' - @current_statement = '' - @start_time = Time.now - end - end - - class Output - attr_reader :type, :result, :output, :error, :indent_level, :javascript - - def self.standard(params = {}) - Output.new type: :standard, result: params[:result], - output: params[:output] || '' - end - - def self.illegal - Output.new type: :illegal - end - - def self.javascript(js) - Output.new type: :javascript, javascript: js - end - - def self.no_output - Output.standard result: nil - end - - def self.line_continuation(level) - Output.new type: :line_continuation, indent_level: level - end - - def self.error(params = {}) - params[:error] ||= StandardError.new('TryRuby Error') - params[:error].message.gsub! /\(eval\):\d*/, '(TryRuby):1' - Output.new type: :error, error: params[:error], - output: params[:output] || '' - end - - def format - case @type - when :line_continuation - ".." * @indent_level - when :error - @output + "\033[1;33m#{@error.class}: #{@error.message}" - when :illegal - "\033[1;33mYou aren't allowed to run that command!" - when :javascript - "\033[1;JSm#{@javascript}\033[m " - else - @output + "=> \033[1;20m#{@result.inspect}" - end - end - - protected - def initialize(values = {}) - values.each do |variable, value| - instance_variable_set("@#{variable}", value) - end - end - end - - - class << self - attr_accessor :session - TryRuby.session = TryRuby::Session.new - end - - def calculate_nesting_level(statement) - begin - RubyParser.new.parse(statement) - 0 - rescue Racc::ParseError => e - case e.message - when /parse error on value \"\$end\" \(\$end\)/ then - new_statement = statement + "\n end" - begin - RubyParser.new.parse(new_statement) - return 1 - rescue Racc::ParseError => e - if e.message =~ /parse error on value \"end\" \(kEND\)/ then - new_statement = statement + "\n }" - end - end - begin - 1 + calculate_nesting_level(new_statement) - rescue Racc::ParseError => e - return 1 - end - else - raise e - end - end - end - - def run_line(code) - case code.strip - when '!INIT!IRB!' - return Output.no_output - when 'reset' - TryRuby.session.current_statement = '' - return Output.no_output - when 'time' - seconds = (Time.now - session.start_time).ceil - return Output.standard result: - if seconds < 60; "#{seconds} seconds" - elsif seconds < 120; "1 minute" - else; "#{seconds / 60} minutes" - end - end - - # nesting level - level = begin - calculate_nesting_level(session.current_statement + "\n" + code) - rescue Racc::ParseError, SyntaxError - 0 - end - if level > 0 - session.current_statement += "\n" + code - return Output.line_continuation(level) - end - - # run something - FakeFS.activate! - stdout_id = $stdout.to_i - $stdout = StringIO.new - cmd = <<-EOF - #{SetupCode} - $SAFE = 3 - #{session.past_commands} - $stdout = StringIO.new - begin - #{session.current_statement} - #{code} - end - EOF - begin - result = Thread.new { eval cmd, TOPLEVEL_BINDING }.value - rescue SecurityError - return Output.illegal - rescue Exception => e - return Output.error :error => e, :output => get_stdout - ensure - output = get_stdout - $stdout = IO.new(stdout_id) - FakeFS.deactivate! - end - - session.current_statement += "\n" + code - session.past_commands += "\n" + session.current_statement.strip - session.current_statement = '' - - return result if result.is_a? Output and result.type == :javascript - Output.standard result: result, output: output - end - - private - def get_stdout - raise TypeError, "$stdout is a #{$stdout.class}" unless $stdout.is_a? StringIO - $stdout.rewind - $stdout.read - end - -end diff --git a/non-rack-legacy/public/tutorials/es_intro.html b/non-rack-legacy/public/tutorials/es_intro.html deleted file mode 100644 index 256de2f..0000000 --- a/non-rack-legacy/public/tutorials/es_intro.html +++ /dev/null @@ -1,666 +0,0 @@ - -
                  -

                  Usando El Prompt

                  -

                  La ventana azul de arriba es el prompt de Ruby. ¡Escribe una línea de código Ruby, aprieta Enter - y velo correr!

                  -

                  Por ejemplo, trata de escribir algo matemático. Como: 2 + 6

                  -
                  \d+
                  -
                  -
                  -

                  Números & Matemática

                  -

                  ¡Bien! Hiciste algo de matemática. ¿Ves como la respuesta salta a la vista?

                  -

                  Ruby reconoce números y símbolos matemáticos. Puedes probar otras cosas como:

                  -
                  • 4 * 10
                  • -
                  • 5 - 12
                  • -
                  • 40 / 4
                  -

                  Seguro, las computadoras son habilidosas y rápidas con las matemáticas. Sigamos... ¿Quieres ver tu nombre al revés? - Escribe tu primer nombre entre comillas así: "Jimmy"

                  -
                  "(\w+)"
                  -
                  -
                  -

                  Decir Tu Nombre Al Revés

                  -

                  Perfecto, has formado un string de las letras de tu nombre. Un string - es un juego de caracteres que la computadora puede procesar.

                  -

                  Imagina que las letras están en una cuerda donde - se cuelga la ropa y las comillas son los broches que sostienen los bordes. Las comillas marcan el comienzo y el final.

                  -

                  Para invertir tu nombre, escribe: "Jimmy".reverse (¡No olvides el punto!)

                  -
                  "(\w+)"
                  -
                  -
                  -

                  Contando Las Letras

                  -

                  ¡Has usado el método reverse sobre tu nombre! Poniendo tu nombre entre comillas, - hiciste un string. Luego llamaste al método reverse, que funciona sobre un string cambiando - todas las letras de atrás para adelante.

                  -

                  Ahora, vamos a ver cuantas letras tiene tu nombre: "Jimmy".length

                  -
                  \d+
                  -
                  -
                  -

                  Repitiendo

                  -

                  Ahora, estoy seguro que te estarás preguntando para que sirve todo esto. Bueno, estoy seguro que habrás estado en alguna - pagina web donde te gritaron, ¡Hey, tu password es muy corto! Ves, algunos programas - usan este código tan simple.

                  -

                  Mira esto. Vamos a multiplicar tu nombre por 5. "Jimmy" * 5

                  -
                  "(\w+)"
                  -
                  -
                  -

                  Hey, Sumario #1 Listo

                  -

                  Vamos a ver que es lo que has aprendido en el primer minuto.

                  -
                    -
                  • El prompt. Escribiendo código en el prompt verde obtienes - una respuesta del prompt rojo. Todo código te da una respuesta.
                  • -
                  • Números y strings son objetos matemáticos y de texto de Ruby.
                  • -
                  • Métodos Has usado métodos en Ingles como reverse - y métodos simbólicos como * (el método de multiplicación.) ¡Los métodos son acciones!
                  • -
                  -

                  Esta es la esencia del aprendizaje. Tomar cosas simples, jugar con ellas - y trasformarlas en cosas nuevas. ¿Te sientes cómodo con todo? Te aseguro que lo estas.

                  -

                  Bien, vamos a hacer algo incomodo. Trata de invertir un número: 40.reverse

                  -
                  NoMethodError: undefined method `reverse' for (\d+):Fixnum
                  -
                  -
                  -

                  ¡Basta, Te Volviste Loco!

                  -

                  No puedes invertir el numero cuarenta. Supongo que puedes poner tu monitor en - frente de un espejo, pero invertir un numero no tiene sentido. Ruby lanza un - mensaje de error. Ruby te dice que no hay un método reverse para los números.

                  -

                  Tal vez si lo conviertes en un string: 40.to_s.reverse.

                  -
                  \"(\d+)\"
                  -
                  -
                  -

                  Los Chicos Son Diferentes De Las Chicas

                  -

                  Y los números son diferentes de los strings. Aunque puedes usar métodos en cualquier objeto - en Ruby, algunos métodos solo funcionan en cierto tipo de cosas. Pero siempre puedes - convertir entre diferentes tipos usando el método "to" de Ruby.

                  -
                  • to_s convierte cosas a strings.
                  • -
                  • to_i convierte cosas a integers (números.)
                  • -
                  • to_a convierte cosas a arrays.
                  • -
                  -

                  ¿Que son los arrays?! Son listas. Escribe entre un par de corchetes: [].

                  -
                  \[\]
                  -
                  -
                  -

                  Mantenerse en Cola

                  -

                  Genial, eso es una lista vacía. Las listas guardan cosas en orden. - Como esperando en la cola para palomitas de maíz. Estas atrás de alguien y jamás - pensarías en empujarlo a un costado, ¿no es así? Y con respecto al tipo detrás de ti, - mantienes un ojo sobre el, ¿correcto?

                  -

                  Acá hay una lista para ti. Números de la lotería: [12, 47, 35].

                  -
                  \[(\d+(, )?){2,}\]
                  -
                  -
                  -

                  Uno Levanta La Mano

                  -

                  Una lista de números de la lotería. ¿Cual es el mayor?

                  -

                  Prueba: [12, 47, 35].max.

                  -
                  (\d+)
                  -
                  -
                  -

                  Manteniendo la Lista

                  -

                  Bien, bien. Pero es un fastidio el tener que reescribir esa lista, ¿no es así?

                  -

                  Guardemos nuestros números en un ticket de esta manera: ticket = [12, 47, 35]

                  -
                  \[(\d+(, )?){2,}\]
                  -
                  -
                  -

                  Ahora Escribe Ticket

                  -

                  Ahora, escribe: ticket

                  -
                  \[(\d+(, )?){2,}\]
                  -
                  -
                  -

                  Guardado, Escondido

                  -

                  ¡Fantástico! Te has aferrado a tus números de la lotería, escondiéndolos dentro de una - variable llamada ticket.

                  -

                  Vamos a poner tus números en orden, que te parece? Usa: ticket.sort!

                  -
                  \[(\d+(, )?){2,}\]
                  -
                  -
                  -

                  Sumario #2 Está Sobre Nosotros

                  -

                  Tenías una lista. Ordenaste la lista. La variable ticket ahora esta cambiada.

                  -

                  ¿Te diste cuenta que el método sort! tiene un claro y llamativo signo de exclamación al final? - Muchas veces los métodos de Ruby gritan así si es que alteran la variable para bien. No es nada - especial, solo una marca.

                  -

                  Ahora, mira como te fue en tu segundo minuto:

                  -
                    -
                  • Errors. Si tratas de invertir un número o hacer algo sospechoso, - Ruby salteara el prompt para avisarte.
                  • -
                  • Arrays son listas para ordenar cosas en orden.
                  • -
                  • Variables guardan cosas y le dan un nombre. Usaste el - signo igual para hacerlo.
                    Like: ticket = [14, 37, 18].
                  • -
                  -

                  En total hay ocho lecciones. Estás a dos octavos de camino! - Esto es cosa simple, no te parece? Las cosas buenas están mas adelante.

                  -

                  Cambiemos de dirección por un momento. Rellené con un poco de poesía cierta - variable para ti. Hecha un vistazo. Escribe print poem

                  -
                  poem = "My toast has flown from my hand\nAnd my toast has gone to the -moon.\nBut when I saw it on television,\nPlanting our flag on Halley's -comet,\nMore still did I want to eat it.\n"
                  -
                  My toast (.+)
                  -
                  -
                  -

                  Desgraciadamente, Tú Odias la poesía de Tostadas

                  -

                  Mira, esta bien. No tiene que gustarte. Hackéalo, yo invito.

                  -

                  En vez de tostada, ve por un melón o algo. Prueba esto: poem['toast'] = 'honeydew'

                  -

                  Y luego escribe print poem para ver el nuevo poema.

                  -
                  My honey(.+)
                  -
                  -
                  -

                  Listo, Apuntado

                  -

                  Los corchetes que acabas de usar son muy comunes en Ruby. Recuerda, escribiste: poem['toast'] = 'honeydew'. Esa casilla con la palabra toast tiene corchetes a ambos lados, ¿ves?

                  -

                  Los -corchetes son como una mira para alinear un objetivo. Exacto. Estos -corchetes significan, "Estoy buscando ____." Listo, apuntado. Aquí estas buscando -una costada e intercambiándola por una fruta.

                  -

                  Aquí hay una pregunta: ¿Que pasa si volteamos el poema entero? poem.reverse -

                  "\\n.ti tae ot (.+)"
                  -
                  -
                  -

                  Demasiado Invertido

                  -

                  Está bien, seguro. Entonces todo el poema fue puesto al revés. Letra por letra. Sin embargo, yo realmente solo quería - invertir las líneas. Mover la última línea a la primera y la primera hacia abajo a la ultima. Al revés, pero no - ése revés.

                  -

                  Aquí esta como lograrlo: poem.lines.to_a.reverse

                  -
                  \["More still did I(.+)"\]
                  -
                  -
                  -

                  Rizos de Metodos Concatenados

                  -

                  Dime, que es lo que ves? Que paso acá? Escribiste poem.lines.to_a.reverse y ¿que pasó?

                  -

                  Dos cosas pasaron. Convertiste poem en una lista usando -lines.to_a. lines decide la forma en que -el string se divide, luego to_a lo -convierte en un Array. (To array.) Diferentes métodos, como -bytes y chars pueden ser usadas en lugar de -lines. Usando lines, Ruby retornará cada línea de poem.

                  -

                  Luego, tu revertiste, reversed, esa lista. Tenías cada línea. Las revertiste. Eso es todo.

                  -

                  Vamos a hilar un método más al final de todo esto: print poem.lines.to_a.reverse.join -

                  More still did I(.+)
                  -
                  -
                  -

                  De Todos los Sumarios, el #3 esta aquí

                  -

                  Buen espectáculo, mi amigo! El método join toma la lista de líneas revertidas y las pone juntas en un string. - (Seguro, también podrías haber usado to_s.)

                  -

                  Tiempo de Revisión.

                  -
                    -
                  • Exclamaciones. Métodos pueden tener signos de exclamación (y también de interrogación) en - sus nombres. No es la gran cosa. Prueba: poem.include? "my hand"
                  • -
                  • Corchetes. Establece objetivos y busca cosas. Busca y reemplaza.
                  • -
                  • Concatenar métodos te permite hacer mas cosas juntas. Partir poem, revertirlo, - reensamblarlo: poem.lines.to_a.reverse.join
                  • -
                  -

                  En este punto, querras manosear un poco más el poema. Una lista completa de métodos - String estan - - acá. - No temas y prueba algunos (como poem.downcase o poem.delete.)

                  -

                  Cuando estés listo para seguir adelante, escribe: books = {}

                  -
                  \{\}
                  -
                  -
                  -

                  Un Pequeñín Libro en Blanco

                  -

                  Has hecho un hash vacío. (también conocido como: un diccionario vacío.)

                  -

                  Vamos a rellenar con un libro de críticas en miniatura. Acá esta nuestro sistema de calificación:

                  -
                    -
                  • :splendid → una obra maestra.
                  • -
                  • :quite_good → disfrutable, por supuesto que sí.
                  • -
                  • :mediocre → partes iguales de bueno y malo.
                  • -
                  • :quite_not_good → notablemente malo.
                  • -
                  • :abyssmal → una perdida de tiempo.
                  • -
                  -

                  Para calificar un libro, pon el título entre corchetes y la calificación luego del signo igual.

                  -

                  Por ejemplo: books["Gravity's Rainbow"] = :splendid

                  -
                  :\w+
                  -
                  -
                  -

                  Mas Críticas Tamaño Bocadillo

                  -

                  Tú sigue, agrega mas críticas. Y, si quieres ver toda la lista, - implemente escribe: books

                  -

                  De nuevo, las calificaciones son: :splendid, :quite_good, :mediocre, - :quite_not_good, and :abyssmal.

                  -

                  Estas calificaciones no son strings. Cuando colocas dos puntos frente a una palabra simple, obtienes un - symbol. Los símbolos son más baratos que los strings (en términos de memoria de la computadora.) Si usas - una palabra una y otra vez en un programa, usa un símbolo. En vez de tener miles de - copias de una palabra en memoria, la computadora guardara el símbolo solamente una vez.

                  -

                  Una vez que tengas tres o cuatro libros allí - dentro, escribe: books.length.

                  -
                  [3-9]
                  -
                  -
                  -

                  Espera, ¿Me gustó Gravity's Rainbow?

                  -

                  Ves, el método length funciona sobre strings, list y hashes. Una gran cosa acerca de - Ruby es que los nombres usualmente se reutilizan, lo que significa menos nombres para recordar.

                  -

                  Si quisieras ver una de tus críticas hechas, vuelve a poner el título entre corchetes. Pero deja de lado el - signo igual.

                  -

                  Al igual que aquí: books["Gravity's Rainbow"]

                  -
                  :\w+
                  -
                  -
                  -

                  Hashes como Pares

                  -

                  Ten en mente que los hashes no mantienen las cosas en orden. Ese no es su trabajo. Solo emparejará dos - cosas: una key (llave) y un valor. En tus críticas, la key es el - titulo del libro y el valor es la calificación.

                  -

                  Si simplemente quieres ver los títulos de los libros que calificaste: books.keys

                  -
                  \[".*"\]
                  -
                  -
                  -

                  ¿Eres Duro?

                  -

                  ¿Estás dando duras injustas críticas? Sigamos puntuando con rigurosidad:
                  ratings = Hash.new {0}

                  -

                  Entonces, bien, ahora vamos a contar tus críticas. Trata de seguirme. Escribe:
                  - books.values.each { |rate| ratings[rate] += 1 }

                  -

                  (La línea vertical es el signo de tubería, probablemente lo logres con AltGr+1 con tu teclado.)

                  -
                  \[:.+\]
                  -
                  -
                  -

                  Un Recuento

                  -

                  Genial, wow! Has hecho un recuento de tus calificaciones. Escribe ratings para ver las cuenta. Este nuevo - hash muestra las calificaciones y luego el numero de veces que has dado esa calificación.

                  -

                  Una de las asombrosas cosas nuevas que acabamos de usar es un bloque, block. Vamos a explorar - explore these more in the next summary. más esto en el próximo sumario. Pero, básicamente, un bloque es un pedazo de código Ruby - rodeado por llaves.

                  -

                  Probemos otro bloque: 5.times { print "Odelay!" }

                  -
                  Odelay!Od.*
                  -
                  -
                  -

                  Ahora Arribamos al Sumario #4

                  -

                  Los bloques están siempre apegados a métodos. Como el método times, que toma el bloque y lo corre - repetidas veces. (En este caso: cinco veces.)

                  -

                  Esta última lección fue algo mas larga. Probablemente usaste unos tres minutos aprendiendo sobre:

                  -
                    -
                  • Hashes. El pequeño diccionario con páginas arrugadas: {}.
                  • -
                  • Symbols. Pequeñas, eficientes palabras con dos puntos: :splendid.
                  • -
                  • Blocks. Pedazos de código que pueden ser clavados a muchos métodos de Ruby. Aquí - esta el código que usaste para crear el recuento:
                    books.values.each { |rate| ratings[rate] += 1 }.
                  • -
                  -

                  En tu computadora, probablemente tienes muchos archivos diferentes. Archivos con fotos en ellos, - archivos con programas dentro. Y los archivos usualmente se organizan en carpetas, también llamadas: - directorios.

                  -

                  He preparado algunos directorios para ti. Echa un vistazo: - Dir.entries "/"

                  -
                  \["\.", .+\]
                  -
                  -
                  -

                  La Privada Colección de Dr. Dir

                  -

                  Acabas de listar todo lo existente en el directorio superior. El directorio raíz, indicado - por la barra en diagonal. Conteniendo algunos programas y otros tutoriales y semejantes.

                  -

                  Entonces, ¿que es el método Dir.entries? Bueno, es solo un método ¿si?, - entries es el método llamado sobre la variable Dir. - Y Dir tiene una colección de métodos para chequear los archivos de los directorios.

                  -

                  Otra pequeña cosa de la que no hemos hablado abiertamente. Argumentos de los métodos, resaltados en verde.

                  -
                    -
                  • Dir.entries "/": Cualquier cosa listada luego de un método - es considerado acoplamiento.
                  • -
                  • print poem: Ves, print es un método ordinario. - Y el poema esta acoplado. Para ser impreso.
                  • -
                  • print "pre", "event", "ual", "ism" posee varios argumentos, - con comas entre ellos.
                  • -
                  -

                  Para listar solamente archivos de texto en el directorio: Dir["/*.txt"]

                  -
                  \["\/comics\.txt"\]
                  -
                  -
                  -

                  Ven, Lee Historietas Conmigo

                  -

                  El método Dir[] hace como entries pero tu buscas por archivos - archivos con carácteres de comodín. ¡Aquí, vemos esos corchetes otra vez! Te das - cuenta como todavía significan, "Estoy buscando _____.".

                  -

                  Mas específicamente: "Estoy buscando archivos que terminen con .txt."

                  -

                  Abramos este archivo con historietas de una vez. Aquí esta la manera:
                  - print File.read("/comics.txt")

                  -
                  Achewood.+
                  -
                  -
                  -

                  Mi Comicas, Tu Comicas

                  -

                  ¡De acuerdo! Podemos comenzar a usar archivos para guardar cosas. Esto es excelente - porque normalmente cuando salimos de Ruby, todas nuestras variables desaparecerán. - Ruby, por si mismo, olvida estas cosas. Pero si salvamos cosas en archivos, - podemos leer esos archivos en futuras escapadas a Ruby.

                  -

                  Hey, y ¿adivina que? ¡El directorio /Home es tuyo! ¡Te lo entrego a ti! ¡Soy generoso! Hagamos una copia del archivo de la historieta.

                  -

                  Querrás hacer lo siguiente: FileUtils.copy('/comics.txt', '/Home/comics.txt') -

                  Si ya has creado el archivo, usa File.delete('/Home/comics.txt') para arrojarlo a la basura.

                  -
                  nil
                  -
                  -
                  -

                  Tu Propio Territorio

                  -

                  Ok, tienes una copia. Chequéala: Dir["/Home/*.txt"]

                  -

                  Para agregar tu propia historieta a la lista, abramos el archivo en modo append.

                  -

                  Empieza asi: File.open("/Home/comics.txt", "a") do |f|.

                  -
                  ..
                  -
                  -
                  -

                  Y Ahora, para la Sorprendente Conclusión

                  -

                  Asi que tu prompt ha cambiado. ¿Lo notas? Tu prompt es doble punto ahora.

                  -

                  En este tutorial, este prompt significa que Ruby espera que escribas más. A - medida que vayas completando con líneas de código, los doble puntos se mantendrán - hasta que hallas finalizado.

                  -

                  Hot tip: si quieres parar de trabajar en el código y salirte de los doble puntos, usa el comando reset. - Si quieres volver a la pagina previa del tutorial, usa el comando back.

                  -

                  Aquí esta tu código. Ya has escrito la primera línea, asi que simplemente ingresa la segunda. (El \n - es el carácter de Enter.

                  -
                  • File.open("/Home/comics.txt", "a") do |f|
                  • -
                  •   f << "Cat and Girl: http://catandgirl.com/\n"
                  • -
                  • end
                  • -
                  -

                  Y, como te has vuelto avanzado y capaz aquí, otro tip: puedes usar las flechas hacia - arriba y hacia abajo para editar tus viejos comandos o correrlos otra vez.

                  -
                  ..
                  -
                  -
                  -

                  Ruby se Sienta y Espera

                  -

                  Esa ultima línea agrega la historieta Cat and Girl a la lista, pero Ruby seguirá esperando - hasta que hallas terminado por completo para tomar acción.

                  -

                  Ahora, para finalizar el código que has empezado. Empezaste un nuevo bloque cuando escribiste do. - Hasta ahora los bloques que hemos visto usaban llaves. Esta vez usaremos do y end en lugar - de las llaves. Muchos Rubyistas usan do...end cuando el bloque ocupa varias líneas.

                  -

                  Terminemos ese bloque ahora mismo, con: end

                  -
                  • File.open("/Home/comics.txt", "a") do |f|
                  • -
                  •   f << "Cat and Girl: http://catandgirl.com/\n"
                  • -
                  • end
                  • -
                  -
                  #.File:/Home/comics\.txt \(closed\).
                  -
                  -
                  -

                  El Reloj Clavado en el Archivo

                  -

                  ¡Bien, bien! Has añadido esa historieta al archivo. Puedes verlo por ti mismo: print File.read("/Home/comics.txt")

                  -

                  ¿Qué hora era cuando cambiaste el archivo? Veamos. Escribe: File.mtime("/Home/comics.txt")

                  -
                  \w+ \w+ \d+ \d{2}:\d{2}:\d{2} [+-]\d{4} \d{4}
                  -
                  -
                  -

                  Sólo la Manecilla de la Hora

                  -

                  Estupendo, allí esta la hora. La hora exacta en la que agregaste la historieta al archivo. El mtime te devuelve un objeto Time de Ruby.

                  -

                  Si sólo quieres ver la hora que era, aprieta la flecha para arriba y cambia la línea a: File.mtime("/Home/comics.txt").hour

                  -
                  \d+
                  -
                  -
                  -

                  Hola, ¿Quién Anda Ahí? Y el Sumario #5 Agita su Sombrero!

                  -

                  Bien hecho, bien hecho, bien hecho, ¡bien hecho! Realmente, realmente, realmente, realmente, ¡reaaaaaaaaalllmente!

                  -

                  Aquí esta tu último minuto de tu vida en retrospectiva:

                  -
                    -
                  • Archivos. ¿Que más se puede decir? Muchos métodos para editar archivos y revisar directorios.
                  • -
                  • Argumentos. Los argumentos son listas de cosas mandadas en un método. Separadas con comas.
                  • -
                  • También hablamos sobre do y end que es otra manera de hacer un bloque.
                  • -
                  -

                  Ahora ya sabes como usar Ruby por completo. Me refiero a que tienes lo esencial. Solo necesitas seguir - aprendiendo métodos y probar bloques más complejos.

                  -

                  Pero existe un lado de Ruby que no hemos hablado. Hacer tus propios métodos y clases.

                  -

                  Ahem! Acabemos con ello de una vez.

                  -

                  Empieza con: def load_comics( path )

                  -
                  ..
                  -
                  -
                  -

                  En Ruby, Def Leppard Significa ¡Define Leppard (un Método)!

                  -

                  Hey, bueno, lo hiciste. Estas haciendo tu propio método. Comenzaste con def, seguido por el nombre del método. - Y una lista de argumentos que va a necesitar el método. ¡Esto no da tanto miedo ni es peligroso!

                  -

                  Todo lo que debemos hacer es rellenar con Ruby y terminarlo con end.

                  -

                  Aquí esta el código:

                  -
                  • def load_comics( path )
                  • -
                  •   comics = {}
                  • -
                  •   File.foreach(path) do |line|
                  • -
                  •     url, name = line.split(': ')
                  • -
                  •     comics[url] = name.strip
                  • -
                  •   end
                  • -
                  •   comics
                  • -
                  • end
                  • -
                  -

                  No necesitas indentar, si no quieres. Lo hice solo para que sea más legible.

                  -
                  nil
                  -
                  -
                  -

                  La Madura Fruta de tu Propia Creación

                  -

                  Un nuevo método ha nacido. Vamos a usarlo: comics = load_comics('/comics.txt')

                  -

                  Si tienes un problema, puedes haberlo escrito mal. Usa el comando back y prueba otra vez.

                  -
                  \{.*"Achewood"=."http://achewood.com/".*\}
                  -
                  -
                  -

                  Hey, Cool, Una Cosa de Historietas

                  -

                  En tu ventana de Ruby arriba, mira el código que has escrito para el método load_comics. ¿Qué esta pasando? Tu estas - pasando en la variable path y estas recibiendo la variable comics. Ruby permite filtrar el hash comics - que es devuelto al final del método.

                  -

                  Una cantidad de métodos se usaron para realizar el trabajo. Fíjate si puedes hallarlos.

                  -
                  • File.foreach es el método que abre un archivo y manda cada línea al bloque. La variable line - dentro del bloque do...end va turnando con cada línea del archivo.
                  • -
                  • split es un método para strings, que rompe los string en colocándolo en un array. Un hacha es arrojada sobre las comas - y las líneas se cortan en dos, dándonos la url y el nombre, name, de las historietas.
                  • -
                  • strip remueve los espacios extra alrededor de name. Por si acaso.
                  • -
                  -

                  Justo allí. Bravo. Tienes las historietas en un hash de Ruby. ¿Pero ahora qué? ¿Qué tan bueno es en verdad?

                  -

                  Hagamos una página de links. ¿Qué te parece? Vamos a necesitar una pequeña librería que hice para ti.

                  -

                  Escribe: require 'popup'

                  -
                  true
                  -
                  -
                  -

                  El Navegador de Títere

                  -

                  Excelente, has cargado la librería popup. Está guardada en un archivo en el directorio Libraries. Mira: Dir["/Libraries/*"]

                  -

                  La librería popup contiene un puñado de métodos que he escrito y te dejaran controlar ventanas emergentes aquí en Try Ruby.

                  -

                  Mira, prueba esto: Popup.goto "http://google.com/"

                  -
                  \033\[1;JSm.*popup_goto\(.*\)\033\[m.*
                  -
                  -
                  -

                  Haciendo Links e Hilando Redes

                  -

                  Nuestro propio adorable, pequeño popup para manipular. también puedes rellenarlo con tus cositas. Empecemos por algo pequeño:

                  -
                  • Popup.make {
                  • -
                  •   h1 "My Links"
                  • -
                  •   link "Go to Google", "http://google.com/"
                  • -
                  • }
                  • -
                  -

                  El termino h1 (h-uno) significa encabezado de nivel uno. En HTML, es el encabezado más grande.

                  -
                  \033\[1;JSm.*popup_make\(.*h1.*a href.*\)\033\[m.*
                  -
                  -
                  -

                  Los Popups son tan fáciles, es una Locura

                  -

                  Se ve bien, lo hiciste perfecto, tal como se te pidió. Hagamos una lista entonces.

                  -

                  Aquí esta como haces una lista con la librería de popup:

                  -
                  • Popup.make do
                  • -
                  •   h1 "Things To Do"
                  • -
                  •   list do
                  • -
                  •     p "Try out Ruby"
                  • -
                  •     p "Ride a tiger"
                  • -
                  •     p "(down River Euphrates)"
                  • -
                  •   end
                  • -
                  • end
                  • -
                  -

                  El método p es la manera corta para "párrafo".

                  -
                  \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*li.*\)\033\[m.*
                  -
                  -
                  -

                  Expandiendo las Historietas en la Tabla

                  -

                  Bien, esto esta yendo maravilloso. Esto es algo simple, pero mantén en mente que no sabias nada sobre Ruby hace quince minutos atrás!<

                  -

                  Ultimo paso. Vamos a juntar todo, ¿sabes? ¡Juntémoslo como esos juegos de - campanillas hermosas que tintinean en los pórticos bajo la hermosa luz del sol - en la playa!

                  -

                  Asegúrate de que las historietas están cargadas: comics = load_comics( '/comics.txt' )

                  -

                  Ahora, hagamos una lista de links para cada historieta:

                  -
                  • Popup.make do
                  • -
                  •   h1 "Comics on the Web"
                  • -
                  •   list do
                  • -
                  •     comics.each do |name, url|
                  • -
                  •       link name, url
                  • -
                  •     end
                  • -
                  •   end
                  • -
                  • end
                  • -
                  -

                  Puedes clickear en los links y leer las historietas ¡inclusive en la ventana principal! ¡Bárbaro!

                  -
                  \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*a href.*li.*a href.*\)\033\[m.*
                  -
                  -
                  -

                  Sumario #6 lo que Significa que has Llegado Muy Lejos

                  -

                  Eres un clérigo nivel 6 de Ruby. Quiero decir que buen trabajo has hecho. Vamos a revisar:

                  -
                    -
                  • Agregaste tu propio método con def y usaste ese método load_comics varias veces.
                  • -
                  • Librerias. Tú usaste el método require para cargar la librería popup.
                    Escribiendo: require 'popup'
                  • -
                  • Y como si no fuera suficiente, hiciste tu propia página web para listar los archivos de historietas. ¡Hiciste un programa real!
                  • -
                  -

                  Entonces ¿Qué podrá venir luego? ¿Qué deberías aprender posiblemente ahora? - Ja, esta es la mejor parte. Has recorrido un largo camino y ahora descubrirás - las clases. En dos lecciones mas y ya estarás hecho.

                  -

                  Tempranamente, creamos un hash como este: Hash.new pruébalo.

                  -
                  \{\}
                  -
                  -
                  -

                  No una Clase de Escuela, Una Clase Trabajadora

                  -

                  Ves, las llaves vacías {} son abreviaciones para Hash.new. El método new - es usado para hacer objetos de cierta clase. (Piensa "clase" como en "clase - trabajadora" — un grupo especifico de objetos similares, tienen el - mismo trabajo, la misma camisa.)

                  -

                  Pregúntate esto: ¿Cómo haría mi blog en Ruby? ¿Dónde deberías - comenzar? Bien, deberías guardar tus entradas del blog en un archivo, ¿cierto? - Pero ¿cómo seguirías los títulos de las entradas y el momento en que fue creado? - Y cuando cargas el archivo, ¿cómo se vería en Ruby? ¿Sería un Hash? ¿O un Array? ¿O - un Array de Arrys? ¿O alguna otra cosa?

                  Yo realmente creo que querrás usar una clase. Ya estas familiarizado con varias clases: Hash, Array, String.

                  -

                  Hagamos una clase nueva: class BlogEntry.

                  -
                  ..
                  -
                  -
                  -

                  El Relleno del Blog esta Hecho de

                  -

                  Has abierto una nueva clase BlogEntry. ¿De que están hechas las entradas de tu blog? Un titulo, seguro. también, - la fecha en la que fue creada. El texto entero de la entrada.

                  -

                  Vamos a poner el estado de ánimo, también, tal como LiveJournal. La internet ha traído de vuelta las personas de palitos y emoticones - fuera de la bancarrota.¡Que emoción!

                  -

                  Bueno, ya tienes la primera línea de la clase, aquí esta el resto:/p> -

                  • class BlogEntry
                  • -
                  •   attr_accessor :title, :time, :fulltext, :mood
                  • -
                  • end
                  • -
                  -
                  nil
                  -
                  -
                  -

                  Accessors Son las Extremidades Colgantes

                  -

                  Hey, buena clase, colega. Tienes una nueva clase BlogEntry. Para comenzar una entrada:
                  entry = BlogEntry.new.

                  -

                  En la definición de la clase, usaste un método llamado attr_accessor. Existen varios métodos attribute - atributo, como este que agregan pequeñas configuraciones a la clase. Estos atributos son simplemente variables adosadas a la clase.

                  -

                  Piénsalo de este modo. Una clase es como una persona. Esa forma de estrella - del humano. Y los atributos son las extremidades, las diferentes partes que - hacen un cuerpo.

                  -

                  Para crear el titulo de tu entrada: entry.title = "Today Mt. Hood Was Stolen!"

                  -
                  ".+"
                  -
                  -
                  -

                  Un Objeto, Ese Estupendo Paquete Pequeño

                  -

                  Sigue adelante y pon la hora: entry.time = Time.now

                  -

                  Y el estado de animo: entry.mood = :sick

                  -

                  Y el anuncio en si: entry.fulltext = "I can't believe Mt. Hood was stolen! I am speechless! It was stolen by a giraffe who drove away - in his Cadillac Seville very nonchalant!!"

                  -

                  Para ver toda la configuración, simplemente escribe en el prompt: entry.

                  -
                  #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
                  -
                  -
                  -

                  Agilizando

                  -

                  Genial, tu blog es impresionante. Hey, hagamos las cosas algo mas fácil. No querrás - poner la hora asi todas las veces que postees. Solo quieres escribir el titulo, - el contenido y el emoticon rápido, ¿verdad?

                  -

                  Vamos a agregar un método initialize.

                  -
                  • class BlogEntry
                  • -
                  •   def initialize( title, mood, fulltext )
                  • -
                  •     @time = Time.now
                  • -
                  •     @title, @mood, @fulltext = title, mood, fulltext
                  • -
                  •   end
                  • -
                  • end
                  • -
                  -

                  Una vez que lo hallas escrito, prueba hacer una nueva entrada: BlogEntry.new

                  -
                  ArgumentError: wrong number of arguments \(0 for 3\).*
                  -
                  -
                  -

                  Tu le Has Enseñado al Blog a Rechazar lo Malo

                  -

                  ¿Viste como usamos dentro de la clase el símbolo arroba? De este modo: @time = Time.now

                  -

                  Fuera de la clase, usamos accesos (accessors): entry.time = Time.now Pero dentro variables de instancia: @time = Time.now - Son exactamente lo mismo, pero expresado en dos partes diferentes de tu programa.

                  -

                  tu blog ahora necesita un titulo, estado de ánimo y el post para funcionar. Cuando un nuevo BlogEntry es creado, el método initialize - es usado para chequear cualquier argumento para new. ¡Uh, necesitamos tres argumentos!

                  -

                  Prueba de nuevo con los tres.

                  -

                  entry2 -= BlogEntry.new( "I Left my Hoodie on the Mountain!", :confused, "I am -never going back to that mountain and I hope a giraffe steals it." )

                  -
                  #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
                  -
                  -
                  -

                  Una Jirafa No Ha Robado el Sumario #7

                  -

                  Aha, estas aquí. Y todo en una pieza. Todavía vamos a hacer tu blog realidad, pero hasta entonces, vamos a revisar, ¿bien?

                  -
                    -
                  • Clases. Todo en Ruby es algún tipo de objeto. Las clases explican los objetos. Como ciertos objetos - trabajan. Por ejemplo, haces algunas entradas de blog y estos objetos están explicados en la clase BlogEntry. - En otras palabras: los llamas objetos del tipo BlogEntry.
                  • -
                  • Accessors son variables adosadas a un objeto que pueden ser usadas fuera del objeto. (entry.time = Time.now)
                  • -
                  • Variables de instancia son las mismas variables para accesos dentro del objeto. - Como en la definición de un método. (@time = Time.now)
                  • -
                  -

                  Bueno, vamos a envolver las cosas, niño. Aquí esta el ultimo capitulo de la FASCINANTE épica - historia de Try Ruby! Ahora que ya has probado como todo funciona, ¿cómo vas a - usar eso alrededor de la casa y en tu tienda de comestibles? Eres una - gran persona (una de mis favoritas), pero necesitas dirección.

                  -

                  Vamos a terminar tu blog. Tienes entradas de blog, pero no un blog.

                  -

                  Pon las entradas en un array: blog = [entry, entry2]

                  -
                  \[#.BlogEntry:0x[0-9a-f]+.*, #.BlogEntry:0x[0-9a-f]+.*\]
                  -
                  -
                  -

                  Todo Se Trata de Combinar Cosas

                  -

                  Cosas hermosas pueden hacerse de partes simples de Ruby, especialmente - cuando las combinas entre ellas para formar algo nuevo. Aquí tenemos un blog - hecho de un array de clases. Y, en realidad, Ruby realmente hace buenas cosas - con este tipo de criaturas.

                  -

                  Aquí hay un puñado de cosas que puedes hacer con tu blog array:

                  -
                  • Querrás ordenar tus entradas de mas reciente a viejas. Puedes hacerlo con:
                    - blog.sort_by { |entry| entry.time }.reverse
                    Ve sort_by para más explicación.
                  • -
                  • Si quieres buscar en el blog por cualquier cosa relacionada con "cadillac":
                    - blog.find_all { |entry| entry.fulltext.match(/cadillac/i) }
                    - Lee mas en find_all - y match - para descubrir como funciona. También: /giraffe/i es un objeto Regexp, usado para concordar palabras.
                  • -
                  • Y agregar nuevas entradas con blog << new_entry
                    - Y aquí la documentación del método <<.
                  • -
                  -

                  Puedes buscar entre la lista de los métodos con los que viene Ruby en ruby-doc.org's core. - Otra buena lista hay en online pickaxe.

                  -

                  Un método realmente útil (probablemente yo uso esto mas que otra cosa) es map. Escribe: blog.map { |entry| entry.mood }

                  -
                  \[(:\w+, )+:\w+\]
                  -
                  -
                  -

                  Mira Su Cara — La Transformación Ha Comenzado

                  -

                  El método map recorre un array y reemplaza cada ítem con algo nuevo. ¿Dices que quieres reemplazar cada entrada de tu blog - con el nombre de Bruce Willis?. Hazlo entonces: blog.map { "Bruce Willis" }

                  -

                  Como el bloque siempre devuelve el string "Bruce Willis", eso es lo que obtienes. En el código que acabas de usar, la entrada entry wfue reemplazada - por solo el entry.mood.

                  -

                  Ahora, quiero que hagas un popup con las entradas de tu blog. Yo no te voy a - dar todo el código. Solo te voy a dar una parte.

                  -
                  • blog.each do |entry|
                  • -
                  •   h2 entry.title
                  • -
                  •   p entry.fulltext
                  • -
                  • end
                  • -
                  -

                  Ahora, yo espero que pongas el código del popup alrededor y agregues un titulo con el nombre de tu blog usando h1. Como extra, tienes la hora de cada entrada para mostrar.

                  -
                  \033\[1;JSm.*popup_make\(.*h1.*h2.*li.*h2.*li.*\)\033\[m.*
                  -
                  -
                  -

                  Eres Una Especie de Gurú Web, Tengo Estrellas en Mis Ojos

                  -

                  Bien, ¡eso es! Este es exactamente el código que puedes usar para escribir tu - propio blog real en Ruby. Si te sientes aventurero, yo chequearía el video de - Rails videos donde muestran a un joven compañero creando un blog en 15 minutos. Solo sientete cómodo y mira.

                  -

                  Debo mencionar a Rails. Tú has estado aprendiendo el lenguaje Ruby, como - hablarlo. Pero Rails es grupo de librerías (algo asi como la librería de popup - que hemos estado usando.) Es un poderoso conjunto de herramientas para crear - sitios web. Si estas interesado en aprender sobre Rails, yo miraría head - por aquí directamente. ¡Empieza a usar tus habilidades en Ruby apropiadamente!

                  -

                  Algo que tiene Rails son métodos para manejar fechas fácilmente. Como, prueba: Time.now - 2.weeks

                  -
                  class Integer; def weeks; self * 7*24*60*60; end; end
                  -
                  \w+ \w+ \d+ \d{2}:\d{2}:\d{2} .*
                  -
                  -
                  -

                  Si Quieres Empezar Poco a Poco

                  -

                  Si quieres comenzar escribiendo pequeños programas en Ruby para practicar, tengo un proyecto llamado MouseHole - que es una pequeña caja de herramientas en la web para escribir programas cortos en Ruby. Puedes ver aquí algunos - scripts para ver que quiero decir.

                  -

                  MouseHole no es para escribir sitios web en realidad. Es para escribir - pequeños programas y correrlos dentro del navegador. Como hay un programa block - de notas para MouseHole y un programa que agrega una imagen de un ratón a los - links de la web que linkean a programas de MouseHole.

                  -

                  Tengo un script de MouseHole dentro de un archivo aquí mismo:
                  - print File.read("/MouseHole/flickrpedia.user.rb")

                  -
                  .*Inserts Wikipedia links for Flickr tags.*
                  -
                  -
                  -

                  Sumario #8, El Sumario Hey-Relájate-Lo-Hiciste-Bien

                  -

                  Esta ultima sección se tomó un momento para relajarse, para darte algunos consejos de como - puedes usar Ruby. Si lo has disfrutado, descarga Ruby e instálalo.

                  - -

                  Una vez que tengas Ruby instalado, puedes usar Ruby Interactivo ejecutando el comando irb en el prompt de tu sistema. Para mas sobre Irb, esta - The Tiger's Vest para ayudarte.

                  -

                  Tú realmente mereces una torta doble-capa con doble-doble azúcar glaseado y - un tipo tocando una de esas guitarras que son doble-guitarra. Quiero decir - terminaste, ¡lo hiciste! No hay dudas de eso, ¡eres un gran ser certificado!

                  -
                  -
                  - \ No newline at end of file diff --git a/non-rack-legacy/public/tutorials/intro.html b/non-rack-legacy/public/tutorials/intro.html deleted file mode 100644 index 56c1d1c..0000000 --- a/non-rack-legacy/public/tutorials/intro.html +++ /dev/null @@ -1,680 +0,0 @@ - -
                  -

                  Using the Prompt

                  -

                  The blue window above is a Ruby prompt. Type a line of Ruby code, hit Enter - and watch it run!

                  -

                  For example, try typing some math. Like: 2 + 6

                  -
                  \d+
                  -
                  -
                  -

                  Numbers & Math

                  -

                  Good! You did a bit of math. See how the answer popped out?

                  -

                  Ruby recognizes numbers and mathematic symbols. You could try some other math like:

                  -
                  • 4 * 10
                  • -
                  • 5 - 12
                  • -
                  • 40 / 4
                  -

                  Sure, computers are handy and fast for math. Let's move on. Want to see your name reversed? - Type your first name in quotes like this: "Jimmy"

                  -
                  "(\w+)"
                  -
                  -
                  -

                  Say Your Name Backwards

                  -

                  Perfect, you've formed a string from the letters of your name. A string - is a set of characters the computer can process.

                  -

                  Imagine the letters are on a string of - laundry line and the quotes are clothespins holding the ends. The quotes mark the beginning and end.

                  -

                  To reverse your name, type: "Jimmy".reverse (Don't forget the dot!)

                  -
                  "(\w+)"
                  -
                  -
                  -

                  Counting the Letters

                  -

                  You have used the reverse method on your name! By enclosing your name in - quotes, you made a string. Then you called the reverse method, which works on strings to flip - all the letters backwards.

                  -

                  Now, let's see how many letters are in your name: "Jimmy".length

                  -
                  \d+
                  -
                  -
                  -

                  On Repeat

                  -

                  Now, I'm sure by now you're wondering what any of this is good for. Well, I'm sure you've been to - a website that screamed, Hey, your password is too short! See, some programs - use this simple code.

                  -

                  Watch this. Let's multiply your name by 5. "Jimmy" * 5

                  -
                  "(\w+)"
                  -
                  -
                  -

                  Hey, Summary #1 Already

                  -

                  Let's look at what you've learned in the first minute.

                  -
                    -
                  • The prompt. Typing code into the green prompt gives you - an answer from a red prompt. All code gives an answer.
                  • -
                  • Numbers and strings are Ruby's math and text objects.
                  • -
                  • Methods. You've used English-language methods like reverse - and symbolic methods like * (the multiplication method.) Methods are action!
                  • -
                  -

                  This is the essence of your learning. Taking simple things, toying with - them and turning them into new things. Feeling comfortable yet? I promise you are.

                  -

                  Okay, let's do something uncomfortable. Try reversing a number: 40.reverse

                  -
                  NoMethodError: undefined method `reverse' for (\d+):Fixnum
                  -
                  -
                  -

                  Stop, You're Barking Mad!

                  -

                  You can't reverse the number forty. I guess you can hold your monitor up to the - mirror, but reversing a number just doesn't make sense. Ruby has tossed an error - message. Ruby is telling you there is no method reverse for numbers.

                  -

                  Maybe if you turn it into a string: 40.to_s.reverse.

                  -
                  \"(\d+)\"
                  -
                  -
                  -

                  Boys are Different From Girls

                  -

                  And numbers are different from strings. While you can use methods on any object - in Ruby, some methods only work on certain types of things. But you can always - convert between different types using Ruby's "to" methods.

                  -
                  • to_s converts things to strings.
                  • -
                  • to_i converts things to integers (numbers.)
                  • -
                  • to_a converts things to arrays.
                  • -
                  -

                  What are arrays?! They are lists. Type in a pair of brackets: [].

                  -
                  \[\]
                  -
                  -
                  -

                  Standing in Line

                  -

                  Great, that's an empty list. Lists store things in order. - Like standing in line for popcorn. You are behind someone and you wouldn't - dream of pushing them aside, right? And the guy behind you, you've got a - close eye on him, right?

                  -

                  Here's a list for you. Lottery numbers: [12, 47, 35].

                  -
                  \[(\d+(, )?){2,}\]
                  -
                  -
                  -

                  One Raises Its Hand

                  -

                  A list of lottery numbers. Which one is the highest?

                  -

                  Try: [12, 47, 35].max.

                  -
                  (\d+)
                  -
                  -
                  -

                  Tucking a List Away

                  -

                  Good, good. But it's annoying to have to retype that list, isn't it?

                  -

                  Let's save our numbers inside a ticket like so: ticket = [12, 47, 35]

                  -
                  \[(\d+(, )?){2,}\]
                  -
                  -
                  -

                  Now Type Ticket

                  -

                  Now, type: ticket

                  -
                  \[(\d+(, )?){2,}\]
                  -
                  -
                  -

                  Saved, Tucked Away

                  -

                  Fantastic! You've hung on to your lotto numbers, tucking them away inside a - variable called ticket.

                  -

                  Let's put your lotto numbers in order, how about? Use: ticket.sort!

                  -
                  \[(\d+(, )?){2,}\]
                  -
                  -
                  -

                  Summary #2 is Upon Us

                  -

                  You had a list. You sorted the list. The ticket variable is now changed.

                  -

                  Did you notice that the sort! method has a big, bright exclamation at the end? - A lot of times Ruby methods shout like that if they alter the variable for good. It's nothin - special, just a mark.

                  -

                  Now, look how your second minute went:

                  -
                    -
                  • Errors. If you try to reverse a number or do anything fishy, - Ruby will skip the prompt and tell you so.
                  • -
                  • Arrays are lists for storing things in order.
                  • -
                  • Variables save a thing and give it a name. You used the - equals sign to do this.
                    Like: ticket = [14, 37, 18].
                  • -
                  -

                  In all there are eight lessons. You are two-eighths of the way there! - This is simple stuff, don't you think? Good stuff up ahead.

                  -

                  Let's change directions for a moment. I've stuffed a bit of poetry for you in - a certain variable. Take a look. Type print poem

                  -
                  poem = "My toast has flown from my hand\nAnd my toast has gone to the -moon.\nBut when I saw it on television,\nPlanting our flag on Halley's -comet,\nMore still did I want to eat it.\n"
                  -
                  My toast (.+)
                  -
                  -
                  -

                  Sadly, You Hate Toast Poetry

                  -

                  Look, it's okay. You don't have to like it. Hack it up, be my guest.

                  -

                  Instead of toast, go for a melon or something. Try this: poem['toast'] = 'honeydew'

                  -

                  And then type print poem by itself to see the new poem.

                  -
                  My honey(.+)
                  -
                  -
                  -

                  Ready, Aim

                  -

                  The square brackets you just used are very common in Ruby. Remember, you typed: poem['toast'] = 'honeydew'. That box with the word toast has a square bracket on each side, see?

                  -

                  The -two brackets are like sights used to line up a target. Exactly. These -brackets mean, "I am looking for ____." Ready, aim. Here you're looking -for toast and swapping it out with fruit.

                  -

                  Here's a question: what happens when we reverse this whole poem? poem.reverse -

                  "\\n.ti tae ot (.+)"
                  -
                  -
                  -

                  Too Much Reversal

                  -

                  Okay, sure. So the whole poem's been turned backwards, letter-by-letter. I really want to just - reverse the lines, though. Move the last line up to first and the first line down to last. Backwards, but not - that backwards.

                  -

                  Here's how: poem.lines.to_a.reverse

                  -
                  \["More still did I(.+)"\]
                  -
                  -
                  -

                  Ringlets of Chained Methods

                  -

                  So what do you see? What happened there? You typed poem.lines.to_a.reverse and what happened?

                  -

                  Two things happened. You turned the poem into a -list using lines.to_a. lines decides the way -the string is split up, then to_a converted it into an -Array. (To array.) Different methods, such -as bytes and chars can be used in place -of lines. By using lines, ruby will return each line of the poem.

                  -

                  Then, you reversed that list. You had each line. You reversed them. That's it.

                  -

                  Let's tack one more method on the end there: print poem.lines.to_a.reverse.join -

                  More still did I(.+)
                  -
                  -
                  -

                  Of All the Summaries, #3 is Here Now

                  -

                  Good show, my friend! The join method took that list of reversed lines and put them - together into a string. (Sure, you could have also just used to_s.)

                  -

                  Review time.

                  -
                    -
                  • Exclamations. Methods may have exclamations (and also question marks) - in their name. No big deal. Try: poem.include? "my hand"
                  • -
                  • Square brackets. Target and find things. Search and replace.
                  • -
                  • Chaining methods lets you get a lot more done. Break up a poem, - reverse it, reassemble it: poem.lines.to_a.reverse.join
                  • -
                  -

                  At this point, you may want to tinker with the poem a bit more. A complete list of all - the String methods is - - here. - Go ahead and try a few (such as poem.downcase or poem.delete.)

                  -

                  When you're ready to move on, type: books = {}

                  -
                  \{\}
                  -
                  -
                  -

                  A Wee Blank Book

                  -

                  You've made an empty hash. (Also known as: an empty dictionary.)

                  -

                  We're going to stuff some miniature book reviews in this hash. Here's our rating system:

                  -
                    -
                  • :splendid → a masterpiece.
                  • -
                  • :quite_good → enjoyed, sure, yes.
                  • -
                  • :mediocre → equal parts great and terrible.
                  • -
                  • :quite_not_good → notably bad.
                  • -
                  • :abyssmal → steaming wreck.
                  • -
                  -

                  To rate a book, put the title in square brackets and put the rating after the equals.

                  -

                  For example: books["Gravity's Rainbow"] = :splendid

                  -
                  :\w+
                  -
                  -
                  -

                  More Bite-Size Reviews

                  -

                  Keep going, fill it up with reviews. And, if you want to see the whole list, - just type: books

                  -

                  Again, the ratings are: :splendid, :quite_good, :mediocre, - :quite_not_good, and :abyssmal.

                  -

                  These ratings are not strings. When you place a colon in front of a simple word, you get a - symbol. Symbols are cheaper than strings (in terms of computer memory.) If - you use a word over and over in your program, use a symbol. Rather than having thousands of - copies of that word in memory, the computer will store the symbol only once.

                  -

                  Once you've got three or four books in - there, type: books.length.

                  -
                  [3-9]
                  -
                  -
                  -

                  Wait, Did I Like Gravity's Rainbow?

                  -

                  See, the length method works on strings, list and hashes. One great thing about - Ruby is that names are often reused, which means fewer names you need to remember.

                  -

                  If you'd like to look up one of your old reviews, again put the title in the square. But leave off - the equals.

                  -

                  Just like this: books["Gravity's Rainbow"]

                  -
                  :\w+
                  -
                  -
                  -

                  Hashes as Pairs

                  -

                  Keep in mind that hashes won't keep things in order. That's not their job. It'll just pair up two - things: a key and a value. In your reviews, the key is the book's - title and the value is the rating.

                  -

                  If you want to just see the titles of the books you've reviewed: books.keys

                  -
                  \[".*"\]
                  -
                  -
                  -

                  Are You Harsh?

                  -

                  So are you giving out harsh, unfair reviews? Let's keep score with this hash:
                  ratings = Hash.new {0}

                  -

                  Then, okay, now let's count up your reviews. Just stay with me. Type:
                  - books.values.each { |rate| ratings[rate] += 1 }

                  -

                  (The straight line in the code is the pipe character, probably located right above the - Enter key on your keyboard.)

                  -
                  \[:.+\]
                  -
                  -
                  -

                  A Tally

                  -

                  Great, wow! You've made a scorecard of your ratings. Type ratings to see the count. - This new hash shows a rating and then the number of times you've given that rating.

                  -

                  One of the amazing new things we've just used is a block. We're going to - explore these more in the next summary. But, basically, a block is a bit of Ruby code surrounded - by curly braces.

                  -

                  Let's try another block: 5.times { print "Odelay!" }

                  -
                  Odelay!Od.*
                  -
                  -
                  -

                  Now Arriving at Summary #4

                  -

                  Blocks are always attached to methods. Like the times method, which takes the - block and runs the code over and over. (In this case: five times.)

                  -

                  This last lesson was a bit longer. You've probably used up three minutes learning about:

                  -
                    -
                  • Hashes. The little dictionary with the curly pages: {}.
                  • -
                  • Symbols. Tiny, efficient code words with a colon: :splendid.
                  • -
                  • Blocks. Chunks of code which can be tacked on to many of Ruby's methods. Here's the - code you used to build a scorecard:
                    books.values.each { |rate| ratings[rate] += 1 }.
                  • -
                  -

                  On your computer, you probably have a lot of different files. Files with pictures in them, - files with programs in them. And files are often organized into folders, also called: - directories.

                  -

                  I've prepared a few directories for you. Take a look: - Dir.entries "/"

                  -
                  \["\.", .+\]
                  -
                  -
                  -

                  The Private Collection of Dr. Dir

                  -

                  You've just listed out everything in the top directory. The root directory, indicated - by a single slash. Containing some programs and other tutorials and such.

                  -

                  So, what is the Dir.entries method? Well, it's just a method, right? - entries is a method called on the Dir variable. - And Dir has a collection of methods for checking out file directories.

                  -

                  One other little thing we haven't really talked about openly. Method arguments, highlighted in green.

                  -
                    -
                  • Dir.entries "/": Anything listed after a method - is considered an attachment.
                  • -
                  • print poem: See, print is an ordinary method. And the - poem is attached. To be printed.
                  • -
                  • print "pre", "event", "ual", "ism" has several arguments, with commas - between them.
                  • -
                  -

                  To list just the text files in that directory: Dir["/*.txt"]

                  -
                  \["\/comics\.txt"\]
                  -
                  -
                  -

                  Come, Read Comics With Me

                  -

                  The Dir[] method is like entries but you search for files - with wildcard characters. Here, we see those square brackets again! Notice how - they still mean, "I am looking for _____?"

                  -

                  More specifically: "I am looking for files which end with .txt."

                  -

                  Let's crack open this comics file, then. Here's the way:
                  - print File.read("/comics.txt")

                  -
                  Achewood.+
                  -
                  -
                  -

                  Mi Comicas, Tu Comicas

                  -

                  All right! We can start to use files to store things. This is great because normally when - we exit Ruby, all our variables will be gone. Ruby, by itself, forgets these things. - But if we save things in files, we can read those files in future Ruby escapades.

                  -

                  Hey, and guess what? The /Home directory is yours! I gave it to you! I am generous! Let's make a copy of the comics file.

                  -

                  You'll want to: FileUtils.copy('/comics.txt', '/Home/comics.txt') -

                  If you've already created the file, use File.delete('/Home/comics.txt') to trash it.

                  -
                  nil
                  -
                  -
                  -

                  Your Own Turf

                  -

                  Okay, you've got a copy. Check it: Dir["/Home/*.txt"]

                  -

                  To add your own comic to the list, let's open the file in append mode.

                  -

                  Start like this: File.open("/Home/comics.txt", "a") do |f|.

                  -
                  ..
                  -
                  -
                  -

                  And Now For the Startling Conclusion

                  -

                  So your prompt has changed. See that? Your prompt is a double dot now.

                  -

                  In this tutorial, this prompt means that Ruby is expecting you to type more. - As you type in the lines of Ruby code, the double dots will continue until you - are completely finished.

                  -

                  Hot tip: If you want to stop working on the code and break out of the double dots, use the reset - command. If you want to go the previous page of the tutorial, use the back command.

                  -

                  Here's your code. You've already typed the first line, so just enter the second line. (The \n - is an Enter character.

                  -
                  • File.open("/Home/comics.txt", "a") do |f|
                  • -
                  •   f << "Cat and Girl: http://catandgirl.com/\n"
                  • -
                  • end
                  • -
                  -

                  And, since you're getting so advanced and capable here, one other tip: you can use the up and down arrow keys to - edit your old commands or run them again.

                  -
                  ..
                  -
                  -
                  -

                  Ruby Sits Still

                  -

                  That last line adds the Cat and Girl comic to the list, but Ruby's going to wait until you're totally finished to - take action.

                  -

                  Now, to finish the code you've started. You opened a new block when you typed do. - So far the blocks we've seen have used curly braces. This time we'll be using do and end instead - of curly braces. A lot of Rubyists will use do...end when the block goes on for many lines.

                  -

                  Let's get that block finished now, with: end

                  -
                  • File.open("/Home/comics.txt", "a") do |f|
                  • -
                  •   f << "Cat and Girl: http://catandgirl.com/\n"
                  • -
                  • end
                  • -
                  -
                  #.File:/Home/comics\.txt \(closed\).
                  -
                  -
                  -

                  The Clock Nailed To the File

                  -

                  Good, good! You've added that new comic to the file. You can see for yourself: print File.read("/Home/comics.txt")

                  -

                  What time was it when you changed the file? Let's check. Type: File.mtime("/Home/comics.txt")

                  -
                  \d{4}-\d+-\d+ \d{2}:\d{2}:\d{2} [+-]\d{4}
                  -
                  -
                  -

                  Just the Hour Hand

                  -

                  Great, there's the time. The precise time exactly when you added to the file. The mtime gives you a Ruby Time object.

                  -

                  If you want to check just what hour it was, hit the up arrow key and change the line to: File.mtime("/Home/comics.txt").hour

                  -
                  \d+
                  -
                  -
                  -

                  Hallo, Who's There? And Summary #5 Waves Its Hat!

                  -

                  Well done, well done, well done, well done! Truly, truly, truly, truly, truuuuuuuuly!

                  -

                  Here's the last few minutes of your life in review:

                  -
                    -
                  • Files. What more can be said? Lots of methods for editing files and lookin around in directories.
                  • -
                  • Arguments. Arguments are a list of things sent into a method. With commas between.
                  • -
                  • We also spoke about do and end which are another way to make a block.
                  • -
                  -

                  You totally know how to use Ruby now. I mean you've got down the essentials. You just need to keep learning more methods and - try out more complex blocks.

                  -

                  But there's one side of Ruby we haven't settled. Making your own methods and classes.

                  -

                  Ahem! Let's get it over with then.

                  -

                  Start with: def load_comics( path )

                  -
                  ..
                  -
                  -
                  -

                  In Ruby, Def Leppard Means Define Leppard (a Method)!

                  -

                  Hey, okay, you done it. You're making your own method. You started with def, followed by the name of the method. - And a list of arguments which the method will need. This isn't too scary and dangerous!

                  -

                  All we have to do is fill it up with Ruby and finish it up with end.

                  -

                  Here's the code:

                  -
                  • def load_comics( path )
                  • -
                  •   comics = {}
                  • -
                  •   File.foreach(path) do |line|
                  • -
                  •     name, url = line.split(': ')
                  • -
                  •     comics[name] = url.strip
                  • -
                  •   end
                  • -
                  •   comics
                  • -
                  • end
                  • -
                  -

                  No need to indent, if you don't want. I just do that to make it read easier.

                  -
                  nil
                  -
                  -
                  -

                  The Ripened Fruit of Your Own Creation

                  -

                  A new method is born. Let us use it: comics = load_comics('/comics.txt')

                  -

                  If you have a problem, you might have mistyped. Use the back command and try again.

                  -
                  \{.*"Achewood"=."http://achewood.com/".*\}
                  -
                  -
                  -

                  Hey, Cool, a Comics Thing

                  -

                  In your Ruby window above, look at the code you've typed for the load_comics method. What is happening? You're - passing in the path variable and you're getting back the comics variable. Ruby lets the comics - hash trickle out the end of the method.

                  -

                  A number of methods were used to get the job done. See if you can spot them.

                  -
                  • File.foreach is a method which opens a file and hands each line to the block. The line - variable inside the do...end block took turns with each line in the file.
                  • -
                  • split is a method for strings, which breaks the string up into an array. An axe is laid on the colon - and the line is chopped in half, giving us the url and name for each comic.
                  • -
                  • strip removes extra spaces around the name. Just in case.
                  • -
                  -

                  Right on. Bravo. You've got the comics in a Ruby hash. But what now? What good is this really?

                  -

                  Let's make a page of links. How about that? I went ahead and loaded a little library I've made for you.

                  -

                  Type: next. This is temporary as I updates new lessons.

                  -
                  true
                  -
                  -
                  -

                  Browser Puppetry

                  -

                  Excellent, you've loaded the popup library. It's saved in a file in the Libraries folder. See: Dir["/Libraries/*"]

                  -

                  The popup library contains a bunch of methods I've written which let you control a popup here on the Try Ruby site.

                  -

                  Here, try this: Popup.goto "http://google.com/"

                  -
                  \033\[1;JSm.*popup_goto\(.*\)\033\[m.*
                  -
                  -
                  -

                  Making Links and Spinning Webs

                  -

                  Our own lovely, little popup to manipulate. You can also fill it with your own goodies. We'll start small:

                  -
                  • Popup.make {
                  • -
                  •   h1 "My Links"
                  • -
                  •   link "Go to Google", "http://google.com/"
                  • -
                  • }
                  • -
                  -

                  The term h1 (h-one) means a level-one header. In HTML, this is the largest size of header.

                  -
                  \033\[1;JSm.*popup_make\(.*h1.*a href.*\)\033\[m.*
                  -
                  -
                  -

                  Popups Are So Easy, It's Crazy

                  -

                  Looks good, you did it perfectly, just as you were asked. Let's make a list then.

                  -

                  Here's how you make a list with the popup library:

                  -
                  • Popup.make do
                  • -
                  •   h1 "Things To Do"
                  • -
                  •   list do
                  • -
                  •     p "Try out Ruby"
                  • -
                  •     p "Ride a tiger"
                  • -
                  •     p "(down River Euphrates)"
                  • -
                  •   end
                  • -
                  • end
                  • -
                  -

                  The p method is short for "paragraph".

                  -
                  \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*li.*\)\033\[m.*
                  -
                  -
                  -

                  Spread the Comics on the Table

                  -

                  Okay, this is coming along wonderfully. This is simple stuff, but keep in mind that you didn't know any Ruby whatsoever just fifteen minutes ago!

                  -

                  Last -step. Let's tie it all together, you know? Let's make it chime together -like a very nice set of glistening chimes on the beach in the -maginificent sunlight!

                  -

                  Make sure the comics are loaded: comics = load_comics( '/comics.txt' )

                  -

                  Now, let's make a list of the links to each comic:

                  -
                  • Popup.make do
                  • -
                  •   h1 "Comics on the Web"
                  • -
                  •   list do
                  • -
                  •     comics.each do |name, url|
                  • -
                  •       link name, url
                  • -
                  •     end
                  • -
                  •   end
                  • -
                  • end
                  • -
                  -

                  You can click on the links and read the comics in the little window even! Smashing!

                  -
                  \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*a href.*li.*a href.*\)\033\[m.*
                  -
                  -
                  -

                  Summary #6 Which Means You've Come So Far

                  -

                  You're a level six Ruby cleric. I mean what a great job you've done. Let's review:

                  -
                    -
                  • You added your own method with def and you used that load_comics method several times.
                  • -
                  • Libraries. You used the require method to load the popup library.
                    By typing: require 'popup'
                  • -
                  • And if that wasn't enough, you made your own web page from a list of comics in a file. You made a real program!
                  • -
                  -

                  So -what could possibly be next? What could you possibly have to learn now? -Ha, this is the best part. You've come such a long way that we're going -to uncover classes. For two more short lessons and you're done.

                  -

                  Earlier, we created a hash like this: Hash.new Try it.

                  -
                  \{\}
                  -
                  -
                  -

                  Not a School Class, a Working Class

                  -

                  You see, the empty curly braces {} is a shortcut for Hash.new. The new -method is used to make objects of a certain class. (Think "class" as in -"working class" — a specific group of objects which are similar, have -the same jobs, the same shirts.)

                  -

                  Ask yourself this: How would I make a blog in Ruby? -Where would you start? Well, you might store your blog entries in a -file, right? But how would you keep track of the title of the entry and -the time it was posted? And when you loaded the file, how would it look -in Ruby? Would it be a Hash? Or an Array? Or an Array of Arrays? Or -something else?

                  I really think you'll want to use a class. You are already familiar with many classes: Hash, Array, String.

                  -

                  Let's make a new class: class BlogEntry.

                  -
                  ..
                  -
                  -
                  -

                  The Stuff Blogs are Made of

                  -

                  You've opened up a new BlogEntry class. What is your blog entry made of? A title, sure. Also, a time when the entry was posted. The - full text of the entry.

                  -

                  We'll do a mood setting, too, just like LiveJournal. The Internet has really brought back stick people and smileys - out of bankruptcy. Emote!

                  -

                  Okay, so you've got the first line of the class, here's the rest:

                  -
                  • class BlogEntry
                  • -
                  •   attr_accessor :title, :time, :fulltext, :mood
                  • -
                  • end
                  • -
                  -
                  nil
                  -
                  -
                  -

                  Accessors Are the Dangling Limbs

                  -

                  Hey, good class, man. You've got a new BlogEntry class. To start an entry:
                  entry = BlogEntry.new.

                  -

                  In the class definition, you used a method called attr_accessor. There are many attribute methods like - this which add little settings to classes. These attributes are just variables attached to a class.

                  -

                  Think -of it this way. A class is like a person. That star-shaped human thing -out there. And the attributes are the dangling limbs, the different -parts that make up a body.

                  -

                  To set the title of your entry: entry.title = "Today Mt. Hood Was Stolen!"

                  -
                  ".+"
                  -
                  -
                  -

                  An Object, That Neat Little Package

                  -

                  Go ahead and set the post time: entry.time = Time.now

                  -

                  And the mood: entry.mood = :sick

                  -

                  And the post itself: entry.fulltext = "I can't believe Mt. Hood was stolen! I am speechless! It was stolen by a giraffe who drove away - in his Cadillac Seville very nonchalant!!"

                  -

                  To see all your settings, just type at the prompt: entry.

                  -
                  #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
                  -
                  -
                  -

                  Quickening it Up

                  -

                  Cool, -you're blog is awesome. Hey, let's make things a bit easier on you. -You're not going to want to set the time like that every time you post. -You just want to type in the title and the entry and the mood quickly, -right?

                  -

                  Let's add an initialize method.

                  -
                  • class BlogEntry
                  • -
                  •   def initialize( title, mood, fulltext )
                  • -
                  •     @time = Time.now
                  • -
                  •     @title, @mood, @fulltext = title, mood, fulltext
                  • -
                  •   end
                  • -
                  • end
                  • -
                  -

                  Once you've got that typed in, try making a new entry: BlogEntry.new

                  -
                  ArgumentError: wrong number of arguments \(0 for 3\).*
                  -
                  -
                  -

                  You've Taught Your Blog to Reject Worthless Things

                  -

                  Did you see how inside the class we used the at-symbols? Like this: @time = Time.now

                  -

                  Outside the class, we use accessors: entry.time = Time.now But inside we use instance variables: @time = Time.now - They're the exact same thing, but expressed in two different places of your program.

                  -

                  Your blog now needs a title, a mood and a post in order to work. When a new BlogEntry is created, the initialize method - is used to check for any arguments to new. Uh, we need three arguments!

                  -

                  Try it again with all three.

                  -

                  entry2 -= BlogEntry.new( "I Left my Hoodie on the Mountain!", :confused, "I am -never going back to that mountain and I hope a giraffe steals it." )

                  -
                  #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
                  -
                  -
                  -

                  A Giraffe Has Not Stolen Summary #7

                  -

                  Aha, you're here. And all in one piece. We're still going to make your blog real, but until then, let's review, okay?

                  -
                    -
                  • Classes. Everything in Ruby is some kind of object. Classes explain objects. How a certain object works. - For example, you made a few blog entry objects and these objects are explained in the BlogEntry class. - In other words: you call them BlogEntry objects.
                  • -
                  • Accessors are variables attached to an object which can be used outside the object. (entry.time = Time.now)
                  • -
                  • Instance variables are the same variables you're using for accessors when inside the object. - Like in a method definition. (@time = Time.now)
                  • -
                  -

                  Okay, -let's wrap things up, kid. Here's the last chapter of the GRIPPING epic -story of Try Ruby! Now that you've got a taste of how it all works, how -are you going to use it around the house and in your grocer's freezer? -You're a great person (one of my favorites), but you need guidance.

                  -

                  Let's finish your blog. You have blog entries, but no actual blog.

                  -

                  Put the entries into an array: blog = [entry, entry2]

                  -
                  \[#.BlogEntry:0x[0-9a-f]+.*, #.BlogEntry:0x[0-9a-f]+.*\]
                  -
                  -
                  -

                  It's All About Combining Things

                  -

                  Some -beautiful things can be done with the simple parts of Ruby, especially -when you combine them together into new things. Here we've got a blog -made of an array of classes. And, actually, Ruby really does good with -this kind of creature.

                  -

                  Here's a few things you can do with your array blog:

                  -
                  • You'll want to sort your entries from newest to oldest. You can do this with:
                    - blog.sort_by { |entry| entry.time }.reverse
                    See the sort_by explanation for more.
                  • -
                  • If you want to search your blog for anything related to "cadillac":
                    - blog.find_all { |entry| entry.fulltext.match(/cadillac/i) }
                    - Read all about find_all - and match - to figure out how that works. Also: the slashy /giraffe/i is a Regexp object, used for matching words.
                  • -
                  • Add new entries with blog << new_entry
                    - And check out the << method documentation.
                  • -
                  -

                  You can browse a list of all Ruby's built-in methods at ruby-doc.org's core list. - Another good list is at the online pickaxe.

                  -

                  One really useful method (I probably use this more than anything else) is map. Type: blog.map { |entry| entry.mood }

                  -
                  \[(:\w+, )+:\w+\]
                  -
                  -
                  -

                  Look at His Face — The Transformation Has Begun

                  -

                  The map method cycles through an array and replaces each item with something new. Say you wanted to replace each of your blog entries - with the name Bruce Willis. Do it so: blog.map { "Bruce Willis" }

                  -

                  Since the block always returns the string "Bruce Willis", that's what you get. In the code you just used, the entry was swapped out - for only the entry.mood.

                  -

                  Now, -I want you to make a popup with your blog entries. I'm not going to -give you all of the code. I'm just going to give you part of it.

                  -
                  • blog.each do |entry|
                  • -
                  •   h2 entry.title
                  • -
                  •   p entry.fulltext
                  • -
                  • end
                  • -
                  -

                  Now, I expect you to put the popup code around it and add an h1 title with the name of your blog. For extra haroompf, have the time of each entry display.

                  -
                  \033\[1;JSm.*popup_make\(.*h1.*h2.*li.*h2.*li.*\)\033\[m.*
                  -
                  -
                  -

                  You are Some Kind of Web Guru, I Have Stars in My Eyes

                  -

                  Good, -that's it! This is exactly the code you can use to write your own real -Ruby blog. If you're feeling adventurous, I'd check out the Rails videos which show a swift young fellow creating a blog in 15 minutes. You just sit back and watch.

                  -

                  I -should mention Rails. You have been learning the Ruby language, how to -speak it. But Rails is a bunch of libraries (sort of like the popup -library we've been using.) It's a very powerful toolkit for building -websites. If you're interested in learning about Rails, I would head - over there right away. Start using your Ruby skills proper!

                  -

                  One thing Rails has is easy methods for dates. Like, try: Time.now - 2.weeks

                  -
                  class Integer; def weeks; self * 7*24*60*60; end; end
                  -
                  \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-+]\d{4}
                  -
                  -
                  -

                  If You Want to Start Small

                  -

                  If you'd like to start writing little Ruby programs just to practice, I have a project called MouseHole - which is a little web toolkit for writing short Ruby programs. You can look over a few - scripts to see what I mean.

                  -

                  MouseHole -isn't for writing web sites really. It's just for writing little -programs you run inside your browser. Like there's a notepad program -for MouseHole and a program which adds a mouse picture next to links on -the web which link to MouseHole programs.

                  -

                  I've got a MouseHole script inside a file here:
                  - print File.read("/MouseHole/flickrpedia.user.rb")

                  -
                  .*Inserts Wikipedia links for Flickr tags.*
                  -
                  -
                  -

                  Summary #8, The Hey-Relax-You-Did-Good Summary

                  -

                  This last section took a moment to wind down, to give you some pointers as to how you can use Ruby. If you enjoyed yourself, - download Ruby and install it.

                  - -

                  Once you have Ruby installed, you can use Interactive Ruby by running irb on your system's prompt. For more on Irb, - there's The Tiger's Vest to help you.

                  -

                  You -really deserve a double-layer cake with double-double frosting and a -guy playing one of those guitars that's a double guitar. I mean you -finished, you really did! No doubt about it, you're a certified -red-blooded smartiac!

                  -
                  -
                  - - diff --git a/non-rack-legacy/public/tutorials/intro.html.broken b/non-rack-legacy/public/tutorials/intro.html.broken deleted file mode 100755 index 5a6c27c..0000000 --- a/non-rack-legacy/public/tutorials/intro.html.broken +++ /dev/null @@ -1,638 +0,0 @@ - -
                  -

                  Using the Prompt

                  -

                  The blue window above is a Ruby prompt. Type a line of Ruby code, hit Enter - and watch it run!

                  -

                  For example, try typing some math. Like: 2 + 6

                  -
                  \d+
                  -
                  -
                  -

                  Numbers & Math

                  -

                  Good! You did a bit of math. See how the answer popped out?

                  -

                  Ruby recognizes numbers and mathematic symbols. You could try some other math like:

                  -
                  • 4 * 10
                  • -
                  • 5 - 12
                  • -
                  • 40 / 4
                  -

                  Sure, computers are handy and fast for math. Let's move on. Want to see your name reversed? - Type your first name in quotes like this: "Jimmy"

                  -
                  "(\w+)"
                  -
                  -
                  -

                  Say Your Name Backwards

                  -

                  Perfect, you've formed a string from the letters of your name. A string - is a set of characters the computer can process.

                  -

                  Imagine the letters are on a string of - laundry line and the quotes are clothespins holding the ends. The quotes mark the beginning and end.

                  -

                  To reverse your name, type: "Jimmy".reverse (Don't forget the dot!)

                  -
                  "(\w+)"
                  -
                  -
                  -

                  Counting the Letters

                  -

                  You have used the reverse method on your name! By enclosing your name in - quotes, you made a string. Then you called the reverse method, which works on strings to flip - all the letters backwards.

                  -

                  Now, let's see how many letters are in your name: "Jimmy".length

                  -
                  \d+
                  -
                  -
                  -

                  On Repeat

                  -

                  Now, I'm sure by now you're wondering what any of this is good for. Well, I'm sure you've been to - a website that screamed, Hey, your password is too short! See, some programs - use this simple code.

                  -

                  Watch this. Let's multiply your name by 5. "Jimmy" * 5

                  -
                  "(\w+)"
                  -
                  -
                  -

                  Hey, Summary #1 Already

                  -

                  Let's look at what you've learned in the first minute.

                  -
                    -
                  • The prompt. Typing code into the green prompt gives you - an answer from a red prompt. All code gives an answer.
                  • -
                  • Numbers and strings are Ruby's math and text objects.
                  • -
                  • Methods. You've used English-language methods like reverse - and symbolic methods like * (the multiplication method.) Methods are action!
                  • -
                  -

                  This is the essence of your learning. Taking simple things, toying with - them and turning them into new things. Feeling comfortable yet? I promise you are.

                  -

                  Okay, let's do something uncomfortable. Try reversing a number: 40.reverse

                  -
                  NoMethodError: undefined method `reverse' for (\d+):Fixnum
                  -
                  -
                  -

                  Stop, You're Barking Mad!

                  -

                  You can't reverse the number forty. I guess you can hold your monitor up to the - mirror, but reversing a number just doesn't make sense. Ruby has tossed an error - message. Ruby is telling you there is no method reverse for numbers.

                  -

                  Maybe if you turn it into a string: 40.to_s.reverse.

                  -
                  \"(\d+)\"
                  -
                  -
                  -

                  Boys are Different From Girls

                  -

                  And numbers are different from strings. While you can use methods on any object - in Ruby, some methods only work on certain types of things. But you can always - convert between different types using Ruby's "to" methods.

                  -
                  • to_s converts things to strings.
                  • -
                  • to_i converts things to integers (numbers.)
                  • -
                  • to_a converts things to arrays.
                  • -
                  -

                  What are arrays?! They are lists. Type in a pair of brackets: [].

                  -
                  \[\]
                  -
                  -
                  -

                  Standing in Line

                  -

                  Great, that's an empty list. Lists store things in order. - Like standing in line for popcorn. You are behind someone and you wouldn't - dream of pushing them aside, right? And the guy behind you, you've got a - close eye on him, right?

                  -

                  Here's a list for you. Lottery numbers: [12, 47, 35].

                  -
                  \[(\d+(, )?){2,}\]
                  -
                  -
                  -

                  One Raises Its Hand

                  -

                  A list of lottery numbers. Which one is the highest?

                  -

                  Try: [12, 47, 35].max.

                  -
                  (\d+)
                  -
                  -
                  -

                  Tucking a List Away

                  -

                  Good, good. But it's annoying to have to retype that list, isn't it?

                  -

                  Let's save our numbers inside a ticket like so: ticket = [12, 47, 35]

                  -
                  \[(\d+(, )?){2,}\]
                  -
                  -
                  -

                  Now Type Ticket

                  -

                  Now, type: ticket

                  -
                  \[(\d+(, )?){2,}\]
                  -
                  -
                  -

                  Saved, Tucked Away

                  -

                  Fantastic! You've hung on to your lotto numbers, tucking them away inside a - variable called ticket.

                  -

                  Let's put your lotto numbers in order, how about? Use: ticket.sort!

                  -
                  \[(\d+(, )?){2,}\]
                  -
                  -
                  -

                  Summary #2 is Upon Us

                  -

                  You had a list. You sorted the list. The ticket variable is now changed.

                  -

                  Did you notice that the sort! method has a big, bright exclamation at the end? - A lot of times Ruby methods shout like that if they alter the variable for good. It's nothin - special, just a mark.

                  -

                  Now, look how your second minute went:

                  -
                    -
                  • Errors. If you try to reverse a number or do anything fishy, - Ruby will skip the prompt and tell you so.
                  • -
                  • Arrays are lists for storing things in order.
                  • -
                  • Variables save a thing and give it a name. You used the - equals sign to do this.
                    Like: ticket = [14, 37, 18].
                  • -
                  -

                  In all there are eight lessons. You are two-eighths of the way there! - This is simple stuff, don't you think? Good stuff up ahead.

                  -

                  Let's change directions for a moment. I've stuffed a bit of poetry for you in - a certain variable. Take a look. Type print poem

                  -
                  poem = "My toast has flown from my hand\nAnd my toast has gone to the -moon.\nBut when I saw it on television,\nPlanting our flag on Halley's -comet,\nMore still did I want to eat it.\n"
                  -
                  My toast (.+)
                  -
                  -
                  -

                  Sadly, You Hate Toast Poetry

                  -

                  Look, it's okay. You don't have to like it. Hack it up, be my guest.

                  -

                  Instead of toast, go for a melon or something. Try this: poem['toast'] = 'honeydew'

                  -

                  And then type print poem by itself to see the new poem.

                  -
                  My honey(.+)
                  -
                  -
                  -

                  Ready, Aim

                  -

                  The square brackets you just used are very common in Ruby. Remember, you typed: poem['toast'] = 'honeydew'. That box with the word toast has a square bracket on each side, see?

                  -

                  The -two brackets are like sights used to line up a target. Exactly. These -brackets mean, "I am looking for ____." Ready, aim. Here you're looking -for toast and swapping it out with fruit.

                  -

                  Here's a question: what happens when we reverse this whole poem? poem.reverse -

                  "\\n.ti tae ot (.+)"
                  -
                  -
                  -

                  Too Much Reversal

                  -

                  Okay, sure. So the whole poem's been turned backwards, letter-by-letter. I really want to just - reverse the lines, though. Move the last line up to first and the first line down to last. Backwards, but not - that backwards.

                  -

                  Here's how: poem.lines.to_a.reverse

                  -
                  \["More still did I(.+)"\]
                  -
                  -
                  -

                  Ringlets of Chained Methods

                  -

                  So what do you see? What happened there? You typed poem.lines.to_a.reverse and what happened?

                  -

                  Two things happened. You turned the poem into a -list using lines.to_a. lines decides the way -the string is split up, then to_a converted it into an -Array. (To array.) Different methods, such -as bytes and chars can be used in place -of lines. By using lines, ruby will return each line of the poem.

                  -

                  Then, you reversed that list. You had each line. You reversed them. That's it.

                  -

                  Let's tack one more method on the end there: print poem.lines.to_a.reverse.join -

                  More still did I(.+)
                  -
                  -
                  -

                  Of All the Summaries, #3 is Here Now

                  -

                  Good show, my friend! The join method took that list of reversed lines and put them - together into a string. (Sure, you could have also just used to_s.)

                  -

                  Review time.

                  -
                    -
                  • Exclamations. Methods may have exclamations (and also question marks) - in their name. No big deal. Try: poem.include? "my hand"
                  • -
                  • Square brackets. Target and find things. Search and replace.
                  • -
                  • Chaining methods lets you get a lot more done. Break up a poem, - reverse it, reassemble it: poem.lines.to_a.reverse.join
                  • -
                  -

                  At this point, you may want to tinker with the poem a bit more. A complete list of all - the String methods is - - here. - Go ahead and try a few (such as poem.downcase or poem.delete.)

                  -

                  When you're ready to move on, type: books = {}

                  -
                  \{\}
                  -
                  -
                  -

                  A Wee Blank Book

                  -

                  You've made an empty hash. (Also known as: an empty dictionary.)

                  -

                  We're going to stuff some miniature book reviews in this hash. Here's our rating system:

                  -
                    -
                  • :splendid → a masterpiece.
                  • -
                  • :quite_good → enjoyed, sure, yes.
                  • -
                  • :mediocre → equal parts great and terrible.
                  • -
                  • :quite_not_good → notably bad.
                  • -
                  • :abyssmal → steaming wreck.
                  • -
                  -

                  To rate a book, put the title in square brackets and put the rating after the equals.

                  -

                  For example: books["Gravity's Rainbow"] = :splendid

                  -
                  :\w+
                  -
                  -
                  -

                  More Bite-Size Reviews

                  -

                  Keep going, fill it up with reviews. And, if you want to see the whole list, - just type: books

                  -

                  Again, the ratings are: :splendid, :quite_good, :mediocre, - :quite_not_good, and :abyssmal.

                  -

                  These ratings are not strings. When you place a colon in front of a simple word, you get a - symbol. Symbols are cheaper than strings (in terms of computer memory.) If - you use a word over and over in your program, use a symbol. Rather than having thousands of - copies of that word in memory, the computer will store the symbol only once.

                  -

                  Once you've got three or four books in - there, type: books.length.

                  -
                  [3-9]
                  -
                  -
                  -

                  Wait, Did I Like Gravity's Rainbow?

                  -

                  See, the length method works on strings, list and hashes. One great thing about - Ruby is that names are often reused, which means fewer names you need to remember.

                  -

                  If you'd like to look up one of your old reviews, again put the title in the square. But leave off - the equals.

                  -

                  Just like this: books["Gravity's Rainbow"]

                  -
                  :\w+
                  -
                  -
                  -

                  Hashes as Pairs

                  -

                  Keep in mind that hashes won't keep things in order. That's not their job. It'll just pair up two - things: a key and a value. In your reviews, the key is the book's - title and the value is the rating.

                  -

                  If you want to just see the titles of the books you've reviewed: books.keys

                  -
                  \[".*"\]
                  -
                  -
                  -

                  Are You Harsh?

                  -

                  So are you giving out harsh, unfair reviews? Let's keep score with this hash:
                  ratings = Hash.new {0}

                  -

                  Then, okay, now let's count up your reviews. Just stay with me. Type:
                  - books.values.each { |rate| ratings[rate] += 1 }

                  -

                  (The straight line in the code is the pipe character, probably located right above the - Enter key on your keyboard.)

                  -
                  \[:.+\]
                  -
                  -
                  -

                  A Tally

                  -

                  Great, wow! You've made a scorecard of your ratings. Type ratings to see the count. - This new hash shows a rating and then the number of times you've given that rating.

                  -

                  One of the amazing new things we've just used is a block. We're going to - explore these more in the next summary. But, basically, a block is a bit of Ruby code surrounded - by curly braces.

                  -

                  Let's try another block: 5.times { print "Odelay!" }

                  -
                  Odelay!Od.*
                  -
                  -
                  -

                  Now Arriving at Summary #4

                  -

                  Blocks are always attached to methods. Like the times method, which takes the - block and runs the code over and over. (In this case: five times.)

                  -

                  This last lesson was a bit longer. You've probably used up three minutes learning about:

                  -
                    -
                  • Hashes. The little dictionary with the curly pages: {}.
                  • -
                  • Symbols. Tiny, efficient code words with a colon: :splendid.
                  • -
                  • Blocks. Chunks of code which can be tacked on to many of Ruby's methods. Here's the - code you used to build a scorecard:
                    books.values.each { |rate| ratings[rate] += 1 }.
                  • -
                  -<<<<<<< HEAD - - -======= -

                  On your computer, you probably have a lot of different files. Files with pictures in them, - files with programs in them. And files are often organized into folders, also called: - directories.

                  -

                  I've prepared a few directories for you. Take a look: - Dir.entries "/"

                  -
                  \["\.", .+\]
                  -
                  -
                  -

                  The Private Collection of Dr. Dir

                  -

                  You've just listed out everything in the top directory. The root directory, indicated - by a single slash. Containing some programs and other tutorials and such.

                  -

                  So, what is the Dir.entries method? Well, it's just a method, right? - entries is a method called on the Dir variable. - And Dir has a collection of methods for checking out file directories.

                  -

                  One other little thing we haven't really talked about openly. Method arguments, highlighted in green.

                  -
                    -
                  • Dir.entries "/": Anything listed after a method - is considered an attachment.
                  • -
                  • print poem: See, print is an ordinary method. And the - poem is attached. To be printed.
                  • -
                  • print "pre", "event", "ual", "ism" has several arguments, with commas - between them.
                  • -
                  -

                  To list just the text files in that directory: Dir["/*.txt"]

                  -
                  \["\/comics\.txt"\]
                  -
                  -
                  -

                  Come, Read Comics With Me

                  -

                  The Dir[] method is like entries but you search for files - with wildcard characters. Here, we see those square brackets again! Notice how - they still mean, "I am looking for _____?"

                  -

                  More specifically: "I am looking for files which end with .txt."

                  -

                  Let's crack open this comics file, then. Here's the way:
                  - print File.read("/comics.txt")

                  -
                  Achewood.+
                  -
                  -
                  -

                  Mi Comicas, Tu Comicas

                  -

                  All right! We can start to use files to store things. This is great because normally when - we exit Ruby, all our variables will be gone. Ruby, by itself, forgets these things. - But if we save things in files, we can read those files in future Ruby escapades.

                  -

                  Hey, and guess what? The /Home directory is yours! I gave it to you! I am generous! Let's make a copy of the comics file.

                  -

                  You'll want to: FileUtils.copy('/comics.txt', '/Home/comics.txt') -

                  If you've already created the file, use File.delete('/Home/comics.txt') to trash it.

                  -
                  nil
                  -
                  -
                  -

                  Your Own Turf

                  -

                  Okay, you've got a copy. Check it: Dir["/Home/*.txt"]

                  -

                  To add your own comic to the list, let's open the file in append mode.

                  -

                  Start like this: File.open("/Home/comics.txt", "a") do |f|.

                  -
                  ..
                  -
                  -
                  -

                  And Now For the Startling Conclusion

                  -

                  So your prompt has changed. See that? Your prompt is a double dot now.

                  -

                  In this tutorial, this prompt means that Ruby is expecting you to type more. - As you type in the lines of Ruby code, the double dots will continue until you - are completely finished.

                  -

                  Hot tip: If you want to stop working on the code and break out of the double dots, use the reset - command. If you want to go the previous page of the tutorial, use the back command.

                  -

                  Here's your code. You've already typed the first line, so just enter the second line. (The \n - is an Enter character.

                  -
                  • File.open("/Home/comics.txt", "a") do |f|
                  • -
                  •   f << "Cat and Girl: http://catandgirl.com/\n"
                  • -
                  • end
                  • -
                  -

                  And, since you're getting so advanced and capable here, one other tip: you can use the up and down arrow keys to - edit your old commands or run them again.

                  -
                  ..
                  -
                  -
                  -

                  Ruby Sits Still

                  -

                  That last line adds the Cat and Girl comic to the list, but Ruby's going to wait until you're totally finished to - take action.

                  -

                  Now, to finish the code you've started. You opened a new block when you typed do. - So far the blocks we've seen have used curly braces. This time we'll be using do and end instead - of curly braces. A lot of Rubyists will use do...end when the block goes on for many lines.

                  -

                  Let's get that block finished now, with: end

                  -
                  • File.open("/Home/comics.txt", "a") do |f|
                  • -
                  •   f << "Cat and Girl: http://catandgirl.com/\n"
                  • -
                  • end
                  • -
                  -
                  #.File:/Home/comics\.txt \(closed\).
                  -
                  -
                  -

                  The Clock Nailed To the File

                  -

                  Good, good! You've added that new comic to the file. You can see for yourself: print File.read("/Home/comics.txt")

                  -

                  What time was it when you changed the file? Let's check. Type: File.mtime("/Home/comics.txt")

                  -
                  \d{4}-\d+-\d+ \d{2}:\d{2}:\d{2} [+-]\d{4}
                  -
                  -
                  -

                  Just the Hour Hand

                  -

                  Great, there's the time. The precise time exactly when you added to the file. The mtime gives you a Ruby Time object.

                  -

                  If you want to check just what hour it was, hit the up arrow key and change the line to: File.mtime("/Home/comics.txt").hour

                  -
                  \d+
                  ->>>>>>> nanothief/master -
                  - -
                  -

                  Hallo, Who's There? And Summary #5 Waves Its Hat!

                  -

                  Well done, well done, well done, well done! Truly, truly, truly, truly, truuuuuuuuly!

                  -

                  Here's the last few minutes of your life in review:

                  -
                    -
                  • Arguments. Arguments are a list of things sent into a method. With commas between.
                  • -
                  • We also spoke about do and end which are another way to make a block.
                  • -
                  -

                  You totally know how to use Ruby now. I mean you've got down the essentials. You just need to keep learning more methods and - try out more complex blocks.

                  -

                  But there's one side of Ruby we haven't settled. Making your own methods and classes.

                  -

                  Ahem! Let's get it over with then.

                  -
                  -
                  -

                  In Ruby, Def Leppard Means Define Leppard (a Method)!

                  -

                  Hey, okay, you done it. You're making your own method. You started with def, followed by the name of the method. - And a list of arguments which the method will need. This isn't too scary and dangerous!

                  -

                  All we have to do is fill it up with Ruby and finish it up with end.

                  -
                  -
                  -

                  Hey, Cool, a Popup

                  -

                  Let's make a page of links. How about that? We'll need to load a little library I've made for you.

                  -

                  Type: require 'popup'

                  -
                  true
                  -
                  -
                  -

                  Browser Puppetry

                  -

                  Excellent, you've loaded the popup library.

                  -

                  The popup library contains a bunch of methods I've written which let you control a popup here on the Try Ruby site.

                  -

                  Here, try this: Popup.goto "http://google.com/"

                  -
                  \033\[1;JSm.*popup_goto\(.*\)\033\[m.*
                  -
                  -
                  -

                  Making Links and Spinning Webs

                  -

                  Our own lovely, little popup to manipulate. You can also fill it with your own goodies. We'll start small:

                  -
                  • Popup.make {
                  • -
                  •   h1 "My Links"
                  • -
                  •   link "Go to Google", "http://google.com/"
                  • -
                  • }
                  • -
                  -

                  The term h1 (h-one) means a level-one header. In HTML, this is the largest size of header.

                  -
                  \033\[1;JSm.*popup_make\(.*h1.*a href.*\)\033\[m.*
                  -
                  -
                  -

                  Popups Are So Easy, It's Crazy

                  -

                  Looks good, you did it perfectly, just as you were asked. Let's make a list then.

                  -

                  Here's how you make a list with the popup library:

                  -
                  • Popup.make do
                  • -
                  •   h1 "Things To Do"
                  • -
                  •   list do
                  • -
                  •     p "Try out Ruby"
                  • -
                  •     p "Ride a tiger"
                  • -
                  •     p "(down River Euphrates)"
                  • -
                  •   end
                  • -
                  • end
                  • -
                  -

                  The p method is short for "paragraph".

                  -
                  \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*li.*\)\033\[m.*
                  -
                  -
                  -

                  Spread the Comics on the Table

                  -

                  Okay, this is coming along wonderfully. This is simple stuff, but keep in mind that you didn't know any Ruby whatsoever just fifteen minutes ago!

                  -

                  Last -step. Let's tie it all together, you know? Let's make it chime together -like a very nice set of glistening chimes on the beach in the -maginificent sunlight!

                  -

                  Now, let's make a list of the links to each comic:

                  -
                  • Popup.make do
                  • -
                  •   h1 "Comics on the Web"
                  • -
                  •   list do
                  • -
                  •     comics.each do |name, url|
                  • -
                  •       link name, url
                  • -
                  •     end
                  • -
                  •   end
                  • -
                  • end
                  • -
                  -

                  You can click on the links and read the comics in the little window even! Smashing!

                  -
                  \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*a href.*li.*a href.*\)\033\[m.*
                  -
                  -
                  -

                  Summary #6 Which Means You've Come So Far

                  -

                  You're a level six Ruby cleric. I mean what a great job you've done. Let's review:

                  -
                    -
                  • You added your own method with def and you used that [coming soon]
                  • -
                  • You used the require method to load the popup library.
                    By typing: require 'popup'
                  • -
                  • And if that wasn't enough, you made your own web page from a list of comics in a file no you havent. You made a real program!
                  • -
                  -

                  So -what could possibly be next? What could you possibly have to learn now? -Ha, this is the best part. You've come such a long way that we're going -to uncover classes. For two more short lessons and you're done.

                  -

                  Earlier, we created a hash like this: Hash.new Try it.

                  -
                  \{\}
                  -
                  -
                  -

                  Not a School Class, a Working Class

                  -

                  You see, the empty curly braces {} is a shortcut for Hash.new. The new -method is used to make objects of a certain class. (Think "class" as in -"working class" — a specific group of objects which are similar, have -the same jobs, the same shirts.)

                  -

                  Ask yourself this: How would I make a blog in Ruby? -Where would you start? Well, you might store your blog entries in a -file, right? But how would you keep track of the title of the entry and -the time it was posted? And when you loaded the file, how would it look -in Ruby? Would it be a Hash? Or an Array? Or an Array of Arrays? Or -something else?

                  I really think you'll want to use a class. You are already familiar with many classes: Hash, Array, String.

                  -

                  Let's make a new class: class BlogEntry.

                  -
                  ..
                  -
                  -
                  -

                  The Stuff Blogs are Made of

                  -

                  You've opened up a new BlogEntry class. What is your blog entry made of? A title, sure. Also, a time when the entry was posted. The - full text of the entry.

                  -

                  We'll do a mood setting, too, just like LiveJournal. The Internet has really brought back stick people and smileys - out of bankruptcy. Emote!

                  -

                  Okay, so you've got the first line of the class, here's the rest:

                  -
                  • class BlogEntry
                  • -
                  •   attr_accessor :title, :time, :fulltext, :mood
                  • -
                  • end
                  • -
                  -
                  nil
                  -
                  -
                  -

                  Accessors Are the Dangling Limbs

                  -

                  Hey, good class, man. You've got a new BlogEntry class. To start an entry:
                  entry = BlogEntry.new.

                  -

                  In the class definition, you used a method called attr_accessor. There are many attribute methods like - this which add little settings to classes. These attributes are just variables attached to a class.

                  -

                  Think -of it this way. A class is like a person. That star-shaped human thing -out there. And the attributes are the dangling limbs, the different -parts that make up a body.

                  -

                  To set the title of your entry: entry.title = "Today Mt. Hood Was Stolen!"

                  -
                  ".+"
                  -
                  -
                  -

                  An Object, That Neat Little Package

                  -

                  Go ahead and set the post time: entry.time = Time.now

                  -

                  And the mood: entry.mood = :sick

                  -

                  And the post itself: entry.fulltext = "I can't believe Mt. Hood was stolen! I am speechless! It was stolen by a giraffe who drove away - in his Cadillac Seville very nonchalant!!"

                  -

                  To see all your settings, just type at the prompt: entry.

                  -
                  #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
                  -
                  -
                  -

                  Quickening it Up

                  -

                  Cool, -you're blog is awesome. Hey, let's make things a bit easier on you. -You're not going to want to set the time like that every time you post. -You just want to type in the title and the entry and the mood quickly, -right?

                  -

                  Let's add an initialize method.

                  -
                  • class BlogEntry
                  • -
                  •   def initialize( title, mood, fulltext )
                  • -
                  •     @time = Time.now
                  • -
                  •     @title, @mood, @fulltext = title, mood, fulltext
                  • -
                  •   end
                  • -
                  • end
                  • -
                  -

                  Once you've got that typed in, try making a new entry: BlogEntry.new

                  -
                  ArgumentError: wrong number of arguments \(0 for 3\).*
                  -
                  -
                  -

                  You've Taught Your Blog to Reject Worthless Things

                  -

                  Did you see how inside the class we used the at-symbols? Like this: @time = Time.now

                  -

                  Outside the class, we use accessors: entry.time = Time.now But inside we use instance variables: @time = Time.now - They're the exact same thing, but expressed in two different places of your program.

                  -

                  Your blog now needs a title, a mood and a post in order to work. When a new BlogEntry is created, the initialize method - is used to check for any arguments to new. Uh, we need three arguments!

                  -

                  Try it again with all three.

                  -

                  entry2 -= BlogEntry.new( "I Left my Hoodie on the Mountain!", :confused, "I am -never going back to that mountain and I hope a giraffe steals it." )

                  -
                  #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
                  -
                  -
                  -

                  A Giraffe Has Not Stolen Summary #7

                  -

                  Aha, you're here. And all in one piece. We're still going to make your blog real, but until then, let's review, okay?

                  -
                    -
                  • Classes. Everything in Ruby is some kind of object. Classes explain objects. How a certain object works. - For example, you made a few blog entry objects and these objects are explained in the BlogEntry class. - In other words: you call them BlogEntry objects.
                  • -
                  • Accessors are variables attached to an object which can be used outside the object. (entry.time = Time.now)
                  • -
                  • Instance variables are the same variables you're using for accessors when inside the object. - Like in a method definition. (@time = Time.now)
                  • -
                  -

                  Okay, -let's wrap things up, kid. Here's the last chapter of the GRIPPING epic -story of Try Ruby! Now that you've got a taste of how it all works, how -are you going to use it around the house and in your grocer's freezer? -You're a great person (one of my favorites), but you need guidance.

                  -

                  Let's finish your blog. You have blog entries, but no actual blog.

                  -

                  Put the entries into an array: blog = [entry, entry2]

                  -
                  \[#.BlogEntry:0x[0-9a-f]+.*, #.BlogEntry:0x[0-9a-f]+.*\]
                  -
                  -
                  -

                  It's All About Combining Things

                  -

                  Some -beautiful things can be done with the simple parts of Ruby, especially -when you combine them together into new things. Here we've got a blog -made of an array of classes. And, actually, Ruby really does good with -this kind of creature.

                  -

                  Here's a few things you can do with your array blog:

                  -
                  • You'll want to sort your entries from newest to oldest. You can do this with:
                    - blog.sort_by { |entry| entry.time }.reverse
                    See the sort_by explanation for more.
                  • -
                  • If you want to search your blog for anything related to "cadillac":
                    - blog.find_all { |entry| entry.fulltext.match(/cadillac/i) }
                    - Read all about find_all - and match - to figure out how that works. Also: the slashy /giraffe/i is a Regexp object, used for matching words.
                  • -
                  • Add new entries with blog << new_entry
                    - And check out the << method documentation.
                  • -
                  -

                  You can browse a list of all Ruby's built-in methods at ruby-doc.org's core list. - Another good list is at the online pickaxe.

                  -

                  One really useful method (I probably use this more than anything else) is map. Type: blog.map { |entry| entry.mood }

                  -
                  \[(:\w+, )+:\w+\]
                  -
                  -
                  -

                  Look at His Face — The Transformation Has Begun

                  -

                  The map method cycles through an array and replaces each item with something new. Say you wanted to replace each of your blog entries - with the name Bruce Willis. Do it so: blog.map { "Bruce Willis" }

                  -

                  Since the block always returns the string "Bruce Willis", that's what you get. In the code you just used, the entry was swapped out - for only the entry.mood.

                  -

                  Now, -I want you to make a popup with your blog entries. I'm not going to -give you all of the code. I'm just going to give you part of it.

                  -
                  • blog.each do |entry|
                  • -
                  •   h2 entry.title
                  • -
                  •   p entry.fulltext
                  • -
                  • end
                  • -
                  -

                  Now, I expect you to put the popup code around it and add an h1 title with the name of your blog. For extra haroompf, have the time of each entry display.

                  -
                  \033\[1;JSm.*popup_make\(.*h1.*h2.*li.*h2.*li.*\)\033\[m.*
                  -
                  -
                  -

                  You are Some Kind of Web Guru, I Have Stars in My Eyes

                  -

                  Good, -that's it! This is exactly the code you can use to write your own real -Ruby blog. If you're feeling adventurous, I'd check out the Rails videos which show a swift young fellow creating a blog in 15 minutes. You just sit back and watch.

                  -

                  I -should mention Rails. You have been learning the Ruby language, how to -speak it. But Rails is a bunch of libraries (sort of like the popup -library we've been using.) It's a very powerful toolkit for building -websites. If you're interested in learning about Rails, I would head - over there right away. Start using your Ruby skills proper!

                  -

                  One thing Rails has is easy methods for dates. Like, try: Time.now - 2.weeks

                  -
                  class Integer; def weeks; self * 7*24*60*60; end; end
                  -
                  \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-+]\d{4}
                  -
                  -
                  -

                  Summary #8, The Hey-Relax-You-Did-Good Summary

                  -

                  This last section took a moment to wind down, to give you some pointers as to how you can use Ruby. If you enjoyed yourself, - download Ruby and install it.

                  - -

                  Once you have Ruby installed, you can use Interactive Ruby by running irb on your system's prompt. For more on Irb, - there's The Tiger's Vest to help you.

                  -

                  You -really deserve a double-layer cake with double-double frosting and a -guy playing one of those guitars that's a double guitar. I mean you -finished, you really did! No doubt about it, you're a certified -red-blooded smartiac!

                  -
                  -
                  - diff --git a/non-rack-legacy/public/tutorials/intro_files/sick.gif b/non-rack-legacy/public/tutorials/intro_files/sick.gif deleted file mode 100755 index 217a67cbae60740fdc90b92e06b977cf7fc56699..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 94 zcmZ?wbhEHb|6B Date: Fri, 8 Jul 2011 18:20:50 -0500 Subject: [PATCH 11/16] sorry for such wild unwiedlyness on master I promise to keep things stable again after today. its for the good of the project. promise --- tryruby/Gemfile => Gemfile | 0 README | 299 ++++++-- tryruby/Rakefile => Rakefile | 0 .../controllers/application_controller.rb | 0 .../controllers/index_controller.rb | 0 .../controllers/tutorials_controller.rb | 0 .../app => app}/helpers/application_helper.rb | 0 {tryruby/app => app}/helpers/index_helper.rb | 0 .../app => app}/helpers/tutorials_helper.rb | 0 .../app => app}/views/index/index.html.erb | 0 .../app => app}/views/index/terminal.html.erb | 0 .../views/layouts/application.html.erb | 0 .../app => app}/views/layouts/blank.html.erb | 0 .../views/tutorials/intro.html.erb | 0 tryruby/config.ru => config.ru | 0 {tryruby/config => config}/application.rb | 0 {tryruby/config => config}/boot.rb | 0 {tryruby/config => config}/database.yml | 0 {tryruby/config => config}/environment.rb | 0 .../environments/development.rb | 0 .../environments/production.rb | 0 .../config => config}/environments/test.rb | 0 .../initializers/backtrace_silencers.rb | 0 .../initializers/inflections.rb | 0 .../initializers/mime_types.rb | 0 .../initializers/secret_token.rb | 0 .../initializers/session_store.rb | 0 {tryruby/config => config}/locales/en.yml | 0 {tryruby/config => config}/routes.rb | 0 {tryruby/db => db}/seeds.rb | 0 {tryruby/doc => doc}/README_FOR_APP | 0 {tryruby/lib => lib}/tasks/.gitkeep | 0 log/development.log | 673 ++++++++++++++++++ .../public/favicon.ico => log/production.log | 0 .../stylesheets/.gitkeep => log/server.log | 0 .../vendor/plugins/.gitkeep => log/test.log | 0 {tryruby/public => public}/404.html | 0 {tryruby/public => public}/422.html | 0 {tryruby/public => public}/500.html | 0 public/favicon.ico | 0 .../public => public}/images/background.png | Bin {tryruby/public => public}/images/footer.png | Bin {tryruby/public => public}/images/header.png | Bin {tryruby/public => public}/images/index.html | 0 {tryruby/public => public}/images/rails.png | Bin {tryruby/public => public}/images/tile.png | Bin .../javascripts/application.js | 0 .../public => public}/javascripts/console.js | 0 .../public => public}/javascripts/controls.js | 0 .../public => public}/javascripts/dragdrop.js | 0 .../public => public}/javascripts/effects.js | 0 .../public => public}/javascripts/facebox.js | 0 .../public => public}/javascripts/index.html | 0 {tryruby/public => public}/javascripts/irb.js | 0 .../javascripts/jQuery.irb.js | 0 .../javascripts/jquery-1.3.2.min.js | 0 .../javascripts/jquery-1.4.2.min.js | 0 .../javascripts/jquery.console.js | 0 .../javascripts/jquery.console.min.js | 0 .../public => public}/javascripts/jquery.js | 0 .../public => public}/javascripts/json2.js | 0 .../public => public}/javascripts/lib.min.js | 0 .../javascripts/mouseapp_2.js | 0 .../javascripts/mouseirb_2.js | 0 .../javascripts/prototype.js | 0 .../public => public}/javascripts/rails.js | 0 .../javascripts/raphael-min.js | 0 {tryruby/public => public}/robots.txt | 0 public/stylesheets/.gitkeep | 0 .../public => public}/stylesheets/facebox.css | 0 .../public => public}/stylesheets/reset.css | 0 .../stylesheets/scaffold.css | 0 .../public => public}/stylesheets/site.css | 0 {tryruby/script => script}/rails | 0 .../functional/index_controller_test.rb | 0 .../functional/tutorials_controller_test.rb | 0 .../performance/browsing_test.rb | 0 {tryruby/test => test}/test_helper.rb | 0 .../unit/helpers/index_helper_test.rb | 0 .../unit/helpers/tutorials_helper_test.rb | 0 tryruby/.gitignore | 4 - tryruby/README | 256 ------- vendor/plugins/.gitkeep | 0 83 files changed, 902 insertions(+), 330 deletions(-) rename tryruby/Gemfile => Gemfile (100%) rename tryruby/Rakefile => Rakefile (100%) rename {tryruby/app => app}/controllers/application_controller.rb (100%) rename {tryruby/app => app}/controllers/index_controller.rb (100%) rename {tryruby/app => app}/controllers/tutorials_controller.rb (100%) rename {tryruby/app => app}/helpers/application_helper.rb (100%) rename {tryruby/app => app}/helpers/index_helper.rb (100%) rename {tryruby/app => app}/helpers/tutorials_helper.rb (100%) rename {tryruby/app => app}/views/index/index.html.erb (100%) rename {tryruby/app => app}/views/index/terminal.html.erb (100%) rename {tryruby/app => app}/views/layouts/application.html.erb (100%) rename {tryruby/app => app}/views/layouts/blank.html.erb (100%) rename {tryruby/app => app}/views/tutorials/intro.html.erb (100%) rename tryruby/config.ru => config.ru (100%) rename {tryruby/config => config}/application.rb (100%) rename {tryruby/config => config}/boot.rb (100%) rename {tryruby/config => config}/database.yml (100%) rename {tryruby/config => config}/environment.rb (100%) rename {tryruby/config => config}/environments/development.rb (100%) rename {tryruby/config => config}/environments/production.rb (100%) rename {tryruby/config => config}/environments/test.rb (100%) rename {tryruby/config => config}/initializers/backtrace_silencers.rb (100%) rename {tryruby/config => config}/initializers/inflections.rb (100%) rename {tryruby/config => config}/initializers/mime_types.rb (100%) rename {tryruby/config => config}/initializers/secret_token.rb (100%) rename {tryruby/config => config}/initializers/session_store.rb (100%) rename {tryruby/config => config}/locales/en.yml (100%) rename {tryruby/config => config}/routes.rb (100%) rename {tryruby/db => db}/seeds.rb (100%) rename {tryruby/doc => doc}/README_FOR_APP (100%) rename {tryruby/lib => lib}/tasks/.gitkeep (100%) create mode 100644 log/development.log rename tryruby/public/favicon.ico => log/production.log (100%) rename tryruby/public/stylesheets/.gitkeep => log/server.log (100%) rename tryruby/vendor/plugins/.gitkeep => log/test.log (100%) rename {tryruby/public => public}/404.html (100%) rename {tryruby/public => public}/422.html (100%) rename {tryruby/public => public}/500.html (100%) create mode 100644 public/favicon.ico rename {tryruby/public => public}/images/background.png (100%) rename {tryruby/public => public}/images/footer.png (100%) rename {tryruby/public => public}/images/header.png (100%) rename {tryruby/public => public}/images/index.html (100%) rename {tryruby/public => public}/images/rails.png (100%) rename {tryruby/public => public}/images/tile.png (100%) rename {tryruby/public => public}/javascripts/application.js (100%) rename {tryruby/public => public}/javascripts/console.js (100%) rename {tryruby/public => public}/javascripts/controls.js (100%) rename {tryruby/public => public}/javascripts/dragdrop.js (100%) rename {tryruby/public => public}/javascripts/effects.js (100%) rename {tryruby/public => public}/javascripts/facebox.js (100%) rename {tryruby/public => public}/javascripts/index.html (100%) rename {tryruby/public => public}/javascripts/irb.js (100%) rename {tryruby/public => public}/javascripts/jQuery.irb.js (100%) rename {tryruby/public => public}/javascripts/jquery-1.3.2.min.js (100%) rename {tryruby/public => public}/javascripts/jquery-1.4.2.min.js (100%) rename {tryruby/public => public}/javascripts/jquery.console.js (100%) rename {tryruby/public => public}/javascripts/jquery.console.min.js (100%) rename {tryruby/public => public}/javascripts/jquery.js (100%) rename {tryruby/public => public}/javascripts/json2.js (100%) rename {tryruby/public => public}/javascripts/lib.min.js (100%) rename {tryruby/public => public}/javascripts/mouseapp_2.js (100%) rename {tryruby/public => public}/javascripts/mouseirb_2.js (100%) rename {tryruby/public => public}/javascripts/prototype.js (100%) rename {tryruby/public => public}/javascripts/rails.js (100%) rename {tryruby/public => public}/javascripts/raphael-min.js (100%) rename {tryruby/public => public}/robots.txt (100%) create mode 100644 public/stylesheets/.gitkeep rename {tryruby/public => public}/stylesheets/facebox.css (100%) rename {tryruby/public => public}/stylesheets/reset.css (100%) rename {tryruby/public => public}/stylesheets/scaffold.css (100%) rename {tryruby/public => public}/stylesheets/site.css (100%) rename {tryruby/script => script}/rails (100%) rename {tryruby/test => test}/functional/index_controller_test.rb (100%) rename {tryruby/test => test}/functional/tutorials_controller_test.rb (100%) rename {tryruby/test => test}/performance/browsing_test.rb (100%) rename {tryruby/test => test}/test_helper.rb (100%) rename {tryruby/test => test}/unit/helpers/index_helper_test.rb (100%) rename {tryruby/test => test}/unit/helpers/tutorials_helper_test.rb (100%) delete mode 100644 tryruby/.gitignore delete mode 100644 tryruby/README create mode 100644 vendor/plugins/.gitkeep diff --git a/tryruby/Gemfile b/Gemfile similarity index 100% rename from tryruby/Gemfile rename to Gemfile diff --git a/README b/README index 1139d90..fe7013d 100644 --- a/README +++ b/README @@ -1,97 +1,256 @@ -TRYRUBY! is now 1.9 ready and hosted using 1.9. Please note this is beta software. +== Welcome to Rails -Copyright (c) 2009 Andrew McElroy +Rails is a web-application framework that includes everything needed to create +database-backed web applications according to the Model-View-Control pattern. -index.html is Copyright (c) 2009 _why -test.rb, tryruby_runner.rb Copyright (c) 2009 David Miani +This pattern splits the view (also called the presentation) into "dumb" +templates that are primarily responsible for inserting pre-built data in between +HTML tags. The model contains the "smart" domain objects (such as Account, +Product, Person, Post) that holds all the business logic and knows how to +persist themselves to a database. The controller handles the incoming requests +(such as Save New Account, Update Product, Show Post) by manipulating the model +and directing data to the view. +In Rails, the model is handled by what's called an object-relational mapping +layer entitled Active Record. This layer allows you to present the data from +database rows as objects and embellish these data objects with business logic +methods. You can read more about Active Record in +link:files/vendor/rails/activerecord/README.html. -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: +The controller and view are handled by the Action Pack, which handles both +layers by its two parts: Action View and Action Controller. These two layers +are bundled in a single package due to their heavy interdependence. This is +unlike the relationship between the Active Record and Action Pack that is much +more separate. Each of these packages can be used independently outside of +Rails. You can read more about Action Pack in +link:files/vendor/rails/actionpack/README.html. -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. +== Getting Started -What is TryRuby? --------------------------------------------------------------------------------------- -Try Ruby is a interactive shell that quickly and whimsically teaches the Ruby programming language. Originally _why's idea, it has been recreated from the ground up by Rubists who have a passion for Ruby and for teaching their fellow (wo)man how to program. +1. At the command prompt, create a new Rails application: + rails new myapp (where myapp is the application name) -Please note that If you feel like you are stuck in the middle of a lesson try typing: +2. Change directory to myapp and start the web server: + cd myapp; rails server (run with --help for options) -next +3. Go to http://localhost:3000/ and you'll see: + "Welcome aboard: You're riding Ruby on Rails!" -Doing so will skip to to the next part of the less/next lesson +4. Follow the guidelines to start developing your application. You can find +the following resources handy: -UPDATE: -EXPECT TO SEE THIS CHANGE IN THE NEXT FEW DAYS. I AM LOOKING INTO A SQLITE STORE OPTION. -The sessions are now stored in a tmp folder. -For the time being it is within the htdoc path. I know this is bad. -I have included an index.html that redirects you back to the home page in the mean time. -Ideally, I need to put this some place like /var/logs/tryruby. +* The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html +* Ruby on Rails Tutorial Book: http://www.railstutorial.org/ +== Debugging Rails -from there I will see about the viability of making this use the r bridge so you -can have ruby to R lessons. :-) +Sometimes your application goes wrong. Fortunately there are a lot of tools that +will help you debug it and get it back on the rails. -Explaination of /irb.cgi -======================== -The only part of the TryRuby implementation that wasn't able to be recovered from archive.org is the /irb file (or /irb.cgi currently, you can change the name of the file used in js/irb.js). This script should: - - Take one GET param "cmd", which will contain a single line of ruby to run. It can also be "!INIT!IRB", which is called at the start of the session. The current implementation of irb.cgi ignores this. "reset" should also do something special (but doesn't atm). - - Return the output, optionally formatted using normal shell escapes (eg "\033[1;33mThis appears orange") +First area to check is the application log files. Have "tail -f" commands +running on the server.log and development.log. Rails will automatically display +debugging and runtime information to these files. Debugging info will also be +shown in the browser on requests from 127.0.0.1. -The output has four main formats for returning a result, error output, javascript function and line continuation. This is used by the help system so that it can detect when a user has entered the next step for the tutorial. +You can also log your own messages directly into the log file from your code +using the Ruby logger class from inside your controllers. Example: -Output results should be formatted with a "=> " at the front of the output. For example: /irb.cgi?cmd=3*4 should output "=> 12". Shell escape codes can be used to give the output different colors, for example "=> \033[1;20m12". This will automatically be removed when used with the help system. Note that you don't and shouldn't terminate these shell escapes with \033[m (like with a normal shell). + class WeblogController < ActionController::Base + def destroy + @weblog = Weblog.find(params[:id]) + @weblog.destroy + logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!") + end + end -Standard output should not be prefixed by =>, so /irb.cgi?cmd=puts(44) should output "44\n=> nil". Here 44 is output, and nil is returned. Again shell escapes can be used. +The result will be a message in your log file along the lines of: -Errors should be formated just like standard output, however it should have no return. For example, /irb.cgi?cmd=non_existant_function should output something like "\033[1;33mNameError: undefined local variable or method `non_existant_function' for main:Object". - -Javascript functions (such as Popup.goto) should use the format "\033[1;JsmJAVASCRIPT CODE\033[m". The javascript cod will then be run. For example, /irb.cgi?cmd=Popup.goto("http://www.google.com") should output \033[1;JSmwindow.irb.options.popup_goto("http://www.google.com")\033[m. - -Finally, if the command isn't finished (eg "def myfunc"), then ".." should be returned. Eg /irb.cgi?cmd=def%20myfunc should return "..". - - -How this works with the help system: -==================================== -The help system works with the file /tutorials/intro.html . There is a
                  section for each part of the tutorial. Most of it is just the text for that part of the tutorial. However, there is also a
                  regex
                  section. If this matches against the output for a command, then the tutorial will go to the next step. - -When the class is "answer", then it will match against lines beginning with "=>". So
                  \d+
                  will match any code that returns a number. Other output can be shown as well, eg "someoutput\n=> 42" will match this. The exact regexp is '^\s*=> match_regex_from_help\s*$'. So the line must be an exact match, other than spaces and the initial => - -When the class is "stdout", the match must work on a complete line. Eg
                  hello
                  will match "hello", or "start\n hello\ngoodbye" (leading spaces are ignored, and multiple lines are searched. The exact regex is '^\s*match_regex_from_help$' - -As a special case, if the tutorial expects that a command isn't finished (such as with def myfunc), then it
                  ..
                  will be used. This is changed from the original implementation _why used, which was
                  as I couldn't get it to work like that. - -Another special case, if the return should some javascript code, then something like '
                  \033\[1;JSm.*popup_goto\(.*\)\033\[m.*
                  ' will be used - - - -Current Implementation -====================== -The current implementation doesn't use persistent processes like irb. What it does is it stores all previous successfully run commands in session['previous_commands'], and runs them all first (disabling stdout). Then it will finally run the command. It uses a primitive method of detecting incomplete statements (with the function unfinished_statement?) and when a incomplete statement is finished (finished_statement?). The current nesting level (eg "class X" then "def myfunc" will having a nesting level of 2) is stored in $session['nesting_level']. All the lines of the current incomplete statement are stored in $session['current_statement']. - -To work with javascript functions, a special class JavascriptResult was written, with one accessor :js. If the result of an eval returns this object, then the output will be formatted in the javascript method. + Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1! +More information on how to use the logger is at http://www.ruby-doc.org/core/ +Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are +several books available online as well: +* Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe) +* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide) +These two books will bring you up to speed on the Ruby language and also on +programming in general. +== Debugger +Debugger support is available through the debugger command when you start your +Mongrel or WEBrick server with --debugger. This means that you can break out of +execution at any point in the code, investigate and change the model, and then, +resume execution! You need to install ruby-debug to run the server in debugging +mode. With gems, use sudo gem install ruby-debug. Example: + + class WeblogController < ActionController::Base + def index + @posts = Post.find(:all) + debugger + end + end + +So the controller will accept the action, run the first line, then present you +with a IRB prompt in the server window. Here you can do things like: + + >> @posts.inspect + => "[#nil, "body"=>nil, "id"=>"1"}>, + #"Rails", "body"=>"Only ten..", "id"=>"2"}>]" + >> @posts.first.title = "hello from a debugger" + => "hello from a debugger" + +...and even better, you can examine how your runtime objects actually work: + + >> f = @posts.first + => #nil, "body"=>nil, "id"=>"1"}> + >> f. + Display all 152 possibilities? (y or n) + +Finally, when you're ready to resume execution, you can enter "cont". + + +== Console + +The console is a Ruby shell, which allows you to interact with your +application's domain model. Here you'll have all parts of the application +configured, just like it is when the application is running. You can inspect +domain models, change values, and save to the database. Starting the script +without arguments will launch it in the development environment. +To start the console, run rails console from the application +directory. + +Options: + +* Passing the -s, --sandbox argument will rollback any modifications + made to the database. +* Passing an environment name as an argument will load the corresponding + environment. Example: rails console production. + +To reload your controllers and models after launching the console run +reload! + +More information about irb can be found at: +link:http://www.rubycentral.com/pickaxe/irb.html + + +== dbconsole + +You can go to the command line of your database directly through rails +dbconsole. You would be connected to the database with the credentials +defined in database.yml. Starting the script without arguments will connect you +to the development database. Passing an argument will connect you to a different +database, like rails dbconsole production. Currently works for MySQL, +PostgreSQL and SQLite 3. + +== Description of Contents + +The default directory structure of a generated Ruby on Rails application: + + |-- app + | |-- controllers + | |-- helpers + | |-- mailers + | |-- models + | `-- views + | `-- layouts + |-- config + | |-- environments + | |-- initializers + | `-- locales + |-- db + |-- doc + |-- lib + | `-- tasks + |-- log + |-- public + | |-- images + | |-- javascripts + | `-- stylesheets + |-- script + |-- test + | |-- fixtures + | |-- functional + | |-- integration + | |-- performance + | `-- unit + |-- tmp + | |-- cache + | |-- pids + | |-- sessions + | `-- sockets + `-- vendor + `-- plugins + +app + Holds all the code that's specific to this particular application. + +app/controllers + Holds controllers that should be named like weblogs_controller.rb for + automated URL mapping. All controllers should descend from + ApplicationController which itself descends from ActionController::Base. + +app/models + Holds models that should be named like post.rb. Models descend from + ActiveRecord::Base by default. + +app/views + Holds the template files for the view that should be named like + weblogs/index.html.erb for the WeblogsController#index action. All views use + eRuby syntax by default. + +app/views/layouts + Holds the template files for layouts to be used with views. This models the + common header/footer method of wrapping views. In your views, define a layout + using the layout :default and create a file named default.html.erb. + Inside default.html.erb, call <% yield %> to render the view using this + layout. + +app/helpers + Holds view helpers that should be named like weblogs_helper.rb. These are + generated for you automatically when using generators for controllers. + Helpers can be used to wrap functionality for your views into methods. + +config + Configuration files for the Rails environment, the routing map, the database, + and other dependencies. + +db + Contains the database schema in schema.rb. db/migrate contains all the + sequence of Migrations for your schema. + +doc + This directory is where your application documentation will be stored when + generated using rake doc:app + +lib + Application specific libraries. Basically, any kind of custom code that + doesn't belong under controllers, models, or helpers. This directory is in + the load path. + +public + The directory available for the web server. Contains subdirectories for + images, stylesheets, and javascripts. Also contains the dispatchers and the + default HTML files. This should be set as the DOCUMENT_ROOT of your web + server. + +script + Helper scripts for automation and generation. + +test + Unit and functional tests along with fixtures. When using the rails generate + command, template test files will be generated for you and placed in this + directory. + +vendor + External libraries that the application depends on. Also includes the plugins + subdirectory. If the app has frozen rails, those gems also go here, under + vendor/rails/. This directory is in the load path. diff --git a/tryruby/Rakefile b/Rakefile similarity index 100% rename from tryruby/Rakefile rename to Rakefile diff --git a/tryruby/app/controllers/application_controller.rb b/app/controllers/application_controller.rb similarity index 100% rename from tryruby/app/controllers/application_controller.rb rename to app/controllers/application_controller.rb diff --git a/tryruby/app/controllers/index_controller.rb b/app/controllers/index_controller.rb similarity index 100% rename from tryruby/app/controllers/index_controller.rb rename to app/controllers/index_controller.rb diff --git a/tryruby/app/controllers/tutorials_controller.rb b/app/controllers/tutorials_controller.rb similarity index 100% rename from tryruby/app/controllers/tutorials_controller.rb rename to app/controllers/tutorials_controller.rb diff --git a/tryruby/app/helpers/application_helper.rb b/app/helpers/application_helper.rb similarity index 100% rename from tryruby/app/helpers/application_helper.rb rename to app/helpers/application_helper.rb diff --git a/tryruby/app/helpers/index_helper.rb b/app/helpers/index_helper.rb similarity index 100% rename from tryruby/app/helpers/index_helper.rb rename to app/helpers/index_helper.rb diff --git a/tryruby/app/helpers/tutorials_helper.rb b/app/helpers/tutorials_helper.rb similarity index 100% rename from tryruby/app/helpers/tutorials_helper.rb rename to app/helpers/tutorials_helper.rb diff --git a/tryruby/app/views/index/index.html.erb b/app/views/index/index.html.erb similarity index 100% rename from tryruby/app/views/index/index.html.erb rename to app/views/index/index.html.erb diff --git a/tryruby/app/views/index/terminal.html.erb b/app/views/index/terminal.html.erb similarity index 100% rename from tryruby/app/views/index/terminal.html.erb rename to app/views/index/terminal.html.erb diff --git a/tryruby/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb similarity index 100% rename from tryruby/app/views/layouts/application.html.erb rename to app/views/layouts/application.html.erb diff --git a/tryruby/app/views/layouts/blank.html.erb b/app/views/layouts/blank.html.erb similarity index 100% rename from tryruby/app/views/layouts/blank.html.erb rename to app/views/layouts/blank.html.erb diff --git a/tryruby/app/views/tutorials/intro.html.erb b/app/views/tutorials/intro.html.erb similarity index 100% rename from tryruby/app/views/tutorials/intro.html.erb rename to app/views/tutorials/intro.html.erb diff --git a/tryruby/config.ru b/config.ru similarity index 100% rename from tryruby/config.ru rename to config.ru diff --git a/tryruby/config/application.rb b/config/application.rb similarity index 100% rename from tryruby/config/application.rb rename to config/application.rb diff --git a/tryruby/config/boot.rb b/config/boot.rb similarity index 100% rename from tryruby/config/boot.rb rename to config/boot.rb diff --git a/tryruby/config/database.yml b/config/database.yml similarity index 100% rename from tryruby/config/database.yml rename to config/database.yml diff --git a/tryruby/config/environment.rb b/config/environment.rb similarity index 100% rename from tryruby/config/environment.rb rename to config/environment.rb diff --git a/tryruby/config/environments/development.rb b/config/environments/development.rb similarity index 100% rename from tryruby/config/environments/development.rb rename to config/environments/development.rb diff --git a/tryruby/config/environments/production.rb b/config/environments/production.rb similarity index 100% rename from tryruby/config/environments/production.rb rename to config/environments/production.rb diff --git a/tryruby/config/environments/test.rb b/config/environments/test.rb similarity index 100% rename from tryruby/config/environments/test.rb rename to config/environments/test.rb diff --git a/tryruby/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb similarity index 100% rename from tryruby/config/initializers/backtrace_silencers.rb rename to config/initializers/backtrace_silencers.rb diff --git a/tryruby/config/initializers/inflections.rb b/config/initializers/inflections.rb similarity index 100% rename from tryruby/config/initializers/inflections.rb rename to config/initializers/inflections.rb diff --git a/tryruby/config/initializers/mime_types.rb b/config/initializers/mime_types.rb similarity index 100% rename from tryruby/config/initializers/mime_types.rb rename to config/initializers/mime_types.rb diff --git a/tryruby/config/initializers/secret_token.rb b/config/initializers/secret_token.rb similarity index 100% rename from tryruby/config/initializers/secret_token.rb rename to config/initializers/secret_token.rb diff --git a/tryruby/config/initializers/session_store.rb b/config/initializers/session_store.rb similarity index 100% rename from tryruby/config/initializers/session_store.rb rename to config/initializers/session_store.rb diff --git a/tryruby/config/locales/en.yml b/config/locales/en.yml similarity index 100% rename from tryruby/config/locales/en.yml rename to config/locales/en.yml diff --git a/tryruby/config/routes.rb b/config/routes.rb similarity index 100% rename from tryruby/config/routes.rb rename to config/routes.rb diff --git a/tryruby/db/seeds.rb b/db/seeds.rb similarity index 100% rename from tryruby/db/seeds.rb rename to db/seeds.rb diff --git a/tryruby/doc/README_FOR_APP b/doc/README_FOR_APP similarity index 100% rename from tryruby/doc/README_FOR_APP rename to doc/README_FOR_APP diff --git a/tryruby/lib/tasks/.gitkeep b/lib/tasks/.gitkeep similarity index 100% rename from tryruby/lib/tasks/.gitkeep rename to lib/tasks/.gitkeep diff --git a/log/development.log b/log/development.log new file mode 100644 index 0000000..6a63a43 --- /dev/null +++ b/log/development.log @@ -0,0 +1,673 @@ +DEPRECATION WARNING: config.action_view.debug_rjs will be removed in 3.1, from 3.1 onwards you will need to install prototype-rails to continue to use RJS templates . (called from service at /Users/sophrinix/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/webrick/httpserver.rb:111) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 17:52:45 -0500 + +ActionController::RoutingError (No route matches "/"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.5ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 17:54:39 -0500 + +ActionController::RoutingError (No route matches "/"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.4ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 17:54:44 -0500 + +ActionController::RoutingError (No route matches "/"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (100.8ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 17:54:57 -0500 + +NoMethodError (undefined method `reverse_merge' for #): + config/routes.rb:2:in `block in ' + config/routes.rb:1:in `' + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (3.0ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (19.8ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (46.8ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 17:55:29 -0500 + +ArgumentError (missing :action): + config/routes.rb:2:in `block in ' + config/routes.rb:1:in `' + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (4.2ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (2.8ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (26.6ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 17:55:42 -0500 + Processing by IndexController#index as HTML +Completed 500 Internal Server Error in 73ms + +ActionView::MissingTemplate (Missing template index/index with {:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=>[:html], :locale=>[:en, :en]} in view paths "/Users/sophrinix/Desktop/herokutr/TryRuby/tryruby/app/views"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/missing_template.erb within rescues/layout (2.7ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 17:55:56 -0500 + Processing by IndexController#index as HTML +Rendered index/index.html.erb within layouts/application (2.0ms) +Completed 200 OK in 13ms (Views: 12.0ms | ActiveRecord: 0.0ms) + + +Started GET "/images/footer.png" for 127.0.0.1 at 2011-07-08 17:55:57 -0500 + +ActionController::RoutingError (No route matches "/images/footer.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) + + +Started GET "/images/header.png" for 127.0.0.1 at 2011-07-08 17:55:57 -0500 + +ActionController::RoutingError (No route matches "/images/header.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) + + +Started GET "/images/header.png" for 127.0.0.1 at 2011-07-08 17:55:57 -0500 + +ActionController::RoutingError (No route matches "/images/header.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.3ms) + + +Started GET "/images/footer.png" for 127.0.0.1 at 2011-07-08 17:55:57 -0500 + +ActionController::RoutingError (No route matches "/images/footer.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) + + +Started GET "/stylesheets/images/plus.png" for 127.0.0.1 at 2011-07-08 17:55:57 -0500 + +ActionController::RoutingError (No route matches "/stylesheets/images/plus.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.3ms) + + +Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 17:55:57 -0500 + +ActionController::RoutingError (No route matches "/images/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) + + +Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 17:55:58 -0500 + +ActionController::RoutingError (No route matches "/images/loading.gif"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) + + +Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 17:55:58 -0500 + +ActionController::RoutingError (No route matches "/facebox/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 17:57:25 -0500 + Processing by IndexController#index as HTML +Rendered index/index.html.erb within layouts/application (2.3ms) +Completed 200 OK in 14ms (Views: 13.3ms | ActiveRecord: 0.0ms) + + +Started GET "/images/footer.png" for 127.0.0.1 at 2011-07-08 17:57:25 -0500 + +ActionController::RoutingError (No route matches "/images/footer.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (3.7ms) + + +Started GET "/images/header.png" for 127.0.0.1 at 2011-07-08 17:57:25 -0500 + +ActionController::RoutingError (No route matches "/images/header.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (3.0ms) + + +Started GET "/images/footer.png" for 127.0.0.1 at 2011-07-08 17:57:25 -0500 + +ActionController::RoutingError (No route matches "/images/footer.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (3.6ms) + + +Started GET "/images/header.png" for 127.0.0.1 at 2011-07-08 17:57:25 -0500 + +ActionController::RoutingError (No route matches "/images/header.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) + + +Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 17:57:26 -0500 + +ActionController::RoutingError (No route matches "/facebox/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) + + +Started GET "/stylesheets/images/plus.png" for 127.0.0.1 at 2011-07-08 17:57:26 -0500 + +ActionController::RoutingError (No route matches "/stylesheets/images/plus.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) + + +Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 17:57:26 -0500 + +ActionController::RoutingError (No route matches "/images/loading.gif"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (9.0ms) + + +Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 17:57:26 -0500 + +ActionController::RoutingError (No route matches "/images/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 17:57:31 -0500 + Processing by IndexController#index as HTML +Rendered index/index.html.erb within layouts/application (2.1ms) +Completed 200 OK in 17ms (Views: 16.6ms | ActiveRecord: 0.0ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 17:58:24 -0500 + Processing by IndexController#index as HTML +Rendered index/index.html.erb within layouts/application (4.8ms) +Completed 200 OK in 30ms (Views: 29.1ms | ActiveRecord: 0.0ms) + + +Started GET "/stylesheets/images/plus.png" for 127.0.0.1 at 2011-07-08 17:58:24 -0500 + +ActionController::RoutingError (No route matches "/stylesheets/images/plus.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.3ms) + + +Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 17:58:24 -0500 + +ActionController::RoutingError (No route matches "/facebox/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) + + +Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 17:58:24 -0500 + +ActionController::RoutingError (No route matches "/images/loading.gif"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.8ms) + + +Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 17:58:25 -0500 + +ActionController::RoutingError (No route matches "/images/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.4ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 17:59:08 -0500 + Processing by IndexController#index as HTML +Rendered index/index.html.erb within layouts/application (2.4ms) +Completed 200 OK in 22ms (Views: 21.5ms | ActiveRecord: 0.0ms) + + +Started GET "/stylesheets/images/plus.png" for 127.0.0.1 at 2011-07-08 17:59:09 -0500 + +ActionController::RoutingError (No route matches "/stylesheets/images/plus.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) + + +Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 17:59:09 -0500 + +ActionController::RoutingError (No route matches "/facebox/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) + + +Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 17:59:09 -0500 + +ActionController::RoutingError (No route matches "/images/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) + + +Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 17:59:09 -0500 + +ActionController::RoutingError (No route matches "/images/loading.gif"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.5ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:07:42 -0500 + Processing by IndexController#index as HTML +Rendered index/index.html.erb within layouts/application (2.2ms) +Completed 200 OK in 19ms (Views: 17.9ms | ActiveRecord: 0.0ms) + + +Started GET "/stylesheets/images/plus.png" for 127.0.0.1 at 2011-07-08 18:07:43 -0500 + +ActionController::RoutingError (No route matches "/stylesheets/images/plus.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.8ms) + + +Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 18:07:43 -0500 + +ActionController::RoutingError (No route matches "/facebox/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.3ms) + + +Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 18:07:43 -0500 + +ActionController::RoutingError (No route matches "/images/loading.gif"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.0ms) + + +Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 18:07:43 -0500 + +ActionController::RoutingError (No route matches "/images/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:08:38 -0500 + Processing by IndexController#index as HTML +Rendered index/index.html.erb within layouts/application (1.3ms) +Completed 200 OK in 7ms (Views: 6.4ms | ActiveRecord: 0.0ms) + + +Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 18:08:38 -0500 + +ActionController::RoutingError (No route matches "/facebox/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.1ms) + + +Started GET "/stylesheets/images/plus.png" for 127.0.0.1 at 2011-07-08 18:08:38 -0500 + +ActionController::RoutingError (No route matches "/stylesheets/images/plus.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.1ms) + + +Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 18:08:38 -0500 + +ActionController::RoutingError (No route matches "/images/loading.gif"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.1ms) + + +Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 18:08:38 -0500 + +ActionController::RoutingError (No route matches "/images/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.4ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:09:04 -0500 + Processing by IndexController#index as HTML +Rendered index/index.html.erb within layouts/application (1.3ms) +Completed 200 OK in 18ms (Views: 17.0ms | ActiveRecord: 0.0ms) + + +Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 18:09:05 -0500 + +ActionController::RoutingError (No route matches "/facebox/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.1ms) + + +Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 18:09:05 -0500 + +ActionController::RoutingError (No route matches "/images/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.1ms) + + +Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 18:09:05 -0500 + +ActionController::RoutingError (No route matches "/images/loading.gif"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.1ms) + + +Started GET "/stylesheets/images/plus.png" for 127.0.0.1 at 2011-07-08 18:09:05 -0500 + +ActionController::RoutingError (No route matches "/stylesheets/images/plus.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.8ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:09:30 -0500 + Processing by IndexController#index as HTML +Rendered index/index.html.erb within layouts/application (1.3ms) +Completed 200 OK in 8ms (Views: 7.0ms | ActiveRecord: 0.0ms) + + +Started GET "/stylesheets/images/plus.png" for 127.0.0.1 at 2011-07-08 18:09:30 -0500 + +ActionController::RoutingError (No route matches "/stylesheets/images/plus.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.1ms) + + +Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 18:09:30 -0500 + +ActionController::RoutingError (No route matches "/facebox/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.8ms) + + +Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 18:09:30 -0500 + +ActionController::RoutingError (No route matches "/images/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.1ms) + + +Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 18:09:30 -0500 + +ActionController::RoutingError (No route matches "/images/loading.gif"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.3ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:10:21 -0500 + Processing by IndexController#index as HTML +Rendered index/index.html.erb within layouts/application (2.2ms) +Completed 200 OK in 15ms (Views: 14.5ms | ActiveRecord: 0.0ms) + + +Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 18:10:22 -0500 + +ActionController::RoutingError (No route matches "/images/loading.gif"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) + + +Started GET "/stylesheets/images/plus.png" for 127.0.0.1 at 2011-07-08 18:10:22 -0500 + +ActionController::RoutingError (No route matches "/stylesheets/images/plus.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) + + +Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 18:10:22 -0500 + +ActionController::RoutingError (No route matches "/facebox/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.3ms) + + +Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 18:10:22 -0500 + +ActionController::RoutingError (No route matches "/images/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) + + +Started GET "/tutorials/intro" for 127.0.0.1 at 2011-07-08 18:10:22 -0500 + +ActionController::RoutingError (No route matches "/tutorials/intro"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:11:20 -0500 + Processing by IndexController#index as HTML +Rendered index/index.html.erb within layouts/application (2.0ms) +Completed 200 OK in 14ms (Views: 13.4ms | ActiveRecord: 0.0ms) + + +Started GET "/stylesheets/images/plus.png" for 127.0.0.1 at 2011-07-08 18:11:20 -0500 + +ActionController::RoutingError (No route matches "/stylesheets/images/plus.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.3ms) + + +Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 18:11:20 -0500 + +ActionController::RoutingError (No route matches "/images/loading.gif"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) + + +Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 18:11:20 -0500 + +ActionController::RoutingError (No route matches "/images/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) + + +Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 18:11:21 -0500 + +ActionController::RoutingError (No route matches "/facebox/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.0ms) + + +Started GET "/tutorials/intro" for 127.0.0.1 at 2011-07-08 18:11:21 -0500 + Processing by TutorialsController#intro as +Rendered tutorials/intro.html.erb within layouts/application (2.2ms) +Completed 200 OK in 41ms (Views: 40.5ms | ActiveRecord: 0.0ms) + + +Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 18:11:23 -0500 + +ActionController::RoutingError (No route matches "/facebox/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) + + +Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 18:11:23 -0500 + +ActionController::RoutingError (No route matches "/images/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (3.8ms) + + +Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 18:11:23 -0500 + +ActionController::RoutingError (No route matches "/images/loading.gif"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.3ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:11:39 -0500 + Processing by IndexController#index as HTML +Rendered index/index.html.erb within layouts/application (2.0ms) +Completed 200 OK in 13ms (Views: 12.0ms | ActiveRecord: 0.0ms) + + +Started GET "/stylesheets/images/plus.png" for 127.0.0.1 at 2011-07-08 18:11:40 -0500 + +ActionController::RoutingError (No route matches "/stylesheets/images/plus.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (5.1ms) + + +Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 18:11:40 -0500 + +ActionController::RoutingError (No route matches "/images/loading.gif"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) + + +Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 18:11:40 -0500 + +ActionController::RoutingError (No route matches "/images/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) + + +Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 18:11:40 -0500 + +ActionController::RoutingError (No route matches "/facebox/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.3ms) + + +Started GET "/tutorials/intro" for 127.0.0.1 at 2011-07-08 18:11:41 -0500 + Processing by TutorialsController#intro as +Rendered tutorials/intro.html.erb within layouts/application (2.1ms) +Completed 200 OK in 47ms (Views: 45.8ms | ActiveRecord: 0.0ms) + + +Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 18:11:42 -0500 + +ActionController::RoutingError (No route matches "/facebox/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) + + +Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 18:11:42 -0500 + +ActionController::RoutingError (No route matches "/images/loading.gif"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) + + +Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 18:11:42 -0500 + +ActionController::RoutingError (No route matches "/images/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (3.7ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:13:34 -0500 + Processing by IndexController#index as HTML +Rendered index/index.html.erb within layouts/application (2.2ms) +Completed 200 OK in 14ms (Views: 13.2ms | ActiveRecord: 0.0ms) + + +Started GET "/stylesheets/images/plus.png" for 127.0.0.1 at 2011-07-08 18:13:35 -0500 + +ActionController::RoutingError (No route matches "/stylesheets/images/plus.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.9ms) + + +Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 18:13:35 -0500 + +ActionController::RoutingError (No route matches "/images/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) + + +Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 18:13:35 -0500 + +ActionController::RoutingError (No route matches "/facebox/closelabel.png"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (6.7ms) + + +Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 18:13:35 -0500 + +ActionController::RoutingError (No route matches "/images/loading.gif"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) + + +Started GET "/tutorials/intro" for 127.0.0.1 at 2011-07-08 18:13:36 -0500 + Processing by TutorialsController#intro as +Rendered tutorials/intro.html.erb within layouts/blank (14.9ms) +Completed 200 OK in 51ms (Views: 50.6ms | ActiveRecord: 0.0ms) + + +Started GET "/tryruby/run?cmd=%21INIT%21IRB%21" for 127.0.0.1 at 2011-07-08 18:13:41 -0500 + +ActionController::RoutingError (No route matches "/tryruby/run"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.0ms) + + +Started GET "/tryruby/run?cmd=1" for 127.0.0.1 at 2011-07-08 18:13:42 -0500 + +ActionController::RoutingError (No route matches "/tryruby/run"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.4ms) diff --git a/tryruby/public/favicon.ico b/log/production.log similarity index 100% rename from tryruby/public/favicon.ico rename to log/production.log diff --git a/tryruby/public/stylesheets/.gitkeep b/log/server.log similarity index 100% rename from tryruby/public/stylesheets/.gitkeep rename to log/server.log diff --git a/tryruby/vendor/plugins/.gitkeep b/log/test.log similarity index 100% rename from tryruby/vendor/plugins/.gitkeep rename to log/test.log diff --git a/tryruby/public/404.html b/public/404.html similarity index 100% rename from tryruby/public/404.html rename to public/404.html diff --git a/tryruby/public/422.html b/public/422.html similarity index 100% rename from tryruby/public/422.html rename to public/422.html diff --git a/tryruby/public/500.html b/public/500.html similarity index 100% rename from tryruby/public/500.html rename to public/500.html diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..e69de29 diff --git a/tryruby/public/images/background.png b/public/images/background.png similarity index 100% rename from tryruby/public/images/background.png rename to public/images/background.png diff --git a/tryruby/public/images/footer.png b/public/images/footer.png similarity index 100% rename from tryruby/public/images/footer.png rename to public/images/footer.png diff --git a/tryruby/public/images/header.png b/public/images/header.png similarity index 100% rename from tryruby/public/images/header.png rename to public/images/header.png diff --git a/tryruby/public/images/index.html b/public/images/index.html similarity index 100% rename from tryruby/public/images/index.html rename to public/images/index.html diff --git a/tryruby/public/images/rails.png b/public/images/rails.png similarity index 100% rename from tryruby/public/images/rails.png rename to public/images/rails.png diff --git a/tryruby/public/images/tile.png b/public/images/tile.png similarity index 100% rename from tryruby/public/images/tile.png rename to public/images/tile.png diff --git a/tryruby/public/javascripts/application.js b/public/javascripts/application.js similarity index 100% rename from tryruby/public/javascripts/application.js rename to public/javascripts/application.js diff --git a/tryruby/public/javascripts/console.js b/public/javascripts/console.js similarity index 100% rename from tryruby/public/javascripts/console.js rename to public/javascripts/console.js diff --git a/tryruby/public/javascripts/controls.js b/public/javascripts/controls.js similarity index 100% rename from tryruby/public/javascripts/controls.js rename to public/javascripts/controls.js diff --git a/tryruby/public/javascripts/dragdrop.js b/public/javascripts/dragdrop.js similarity index 100% rename from tryruby/public/javascripts/dragdrop.js rename to public/javascripts/dragdrop.js diff --git a/tryruby/public/javascripts/effects.js b/public/javascripts/effects.js similarity index 100% rename from tryruby/public/javascripts/effects.js rename to public/javascripts/effects.js diff --git a/tryruby/public/javascripts/facebox.js b/public/javascripts/facebox.js similarity index 100% rename from tryruby/public/javascripts/facebox.js rename to public/javascripts/facebox.js diff --git a/tryruby/public/javascripts/index.html b/public/javascripts/index.html similarity index 100% rename from tryruby/public/javascripts/index.html rename to public/javascripts/index.html diff --git a/tryruby/public/javascripts/irb.js b/public/javascripts/irb.js similarity index 100% rename from tryruby/public/javascripts/irb.js rename to public/javascripts/irb.js diff --git a/tryruby/public/javascripts/jQuery.irb.js b/public/javascripts/jQuery.irb.js similarity index 100% rename from tryruby/public/javascripts/jQuery.irb.js rename to public/javascripts/jQuery.irb.js diff --git a/tryruby/public/javascripts/jquery-1.3.2.min.js b/public/javascripts/jquery-1.3.2.min.js similarity index 100% rename from tryruby/public/javascripts/jquery-1.3.2.min.js rename to public/javascripts/jquery-1.3.2.min.js diff --git a/tryruby/public/javascripts/jquery-1.4.2.min.js b/public/javascripts/jquery-1.4.2.min.js similarity index 100% rename from tryruby/public/javascripts/jquery-1.4.2.min.js rename to public/javascripts/jquery-1.4.2.min.js diff --git a/tryruby/public/javascripts/jquery.console.js b/public/javascripts/jquery.console.js similarity index 100% rename from tryruby/public/javascripts/jquery.console.js rename to public/javascripts/jquery.console.js diff --git a/tryruby/public/javascripts/jquery.console.min.js b/public/javascripts/jquery.console.min.js similarity index 100% rename from tryruby/public/javascripts/jquery.console.min.js rename to public/javascripts/jquery.console.min.js diff --git a/tryruby/public/javascripts/jquery.js b/public/javascripts/jquery.js similarity index 100% rename from tryruby/public/javascripts/jquery.js rename to public/javascripts/jquery.js diff --git a/tryruby/public/javascripts/json2.js b/public/javascripts/json2.js similarity index 100% rename from tryruby/public/javascripts/json2.js rename to public/javascripts/json2.js diff --git a/tryruby/public/javascripts/lib.min.js b/public/javascripts/lib.min.js similarity index 100% rename from tryruby/public/javascripts/lib.min.js rename to public/javascripts/lib.min.js diff --git a/tryruby/public/javascripts/mouseapp_2.js b/public/javascripts/mouseapp_2.js similarity index 100% rename from tryruby/public/javascripts/mouseapp_2.js rename to public/javascripts/mouseapp_2.js diff --git a/tryruby/public/javascripts/mouseirb_2.js b/public/javascripts/mouseirb_2.js similarity index 100% rename from tryruby/public/javascripts/mouseirb_2.js rename to public/javascripts/mouseirb_2.js diff --git a/tryruby/public/javascripts/prototype.js b/public/javascripts/prototype.js similarity index 100% rename from tryruby/public/javascripts/prototype.js rename to public/javascripts/prototype.js diff --git a/tryruby/public/javascripts/rails.js b/public/javascripts/rails.js similarity index 100% rename from tryruby/public/javascripts/rails.js rename to public/javascripts/rails.js diff --git a/tryruby/public/javascripts/raphael-min.js b/public/javascripts/raphael-min.js similarity index 100% rename from tryruby/public/javascripts/raphael-min.js rename to public/javascripts/raphael-min.js diff --git a/tryruby/public/robots.txt b/public/robots.txt similarity index 100% rename from tryruby/public/robots.txt rename to public/robots.txt diff --git a/public/stylesheets/.gitkeep b/public/stylesheets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tryruby/public/stylesheets/facebox.css b/public/stylesheets/facebox.css similarity index 100% rename from tryruby/public/stylesheets/facebox.css rename to public/stylesheets/facebox.css diff --git a/tryruby/public/stylesheets/reset.css b/public/stylesheets/reset.css similarity index 100% rename from tryruby/public/stylesheets/reset.css rename to public/stylesheets/reset.css diff --git a/tryruby/public/stylesheets/scaffold.css b/public/stylesheets/scaffold.css similarity index 100% rename from tryruby/public/stylesheets/scaffold.css rename to public/stylesheets/scaffold.css diff --git a/tryruby/public/stylesheets/site.css b/public/stylesheets/site.css similarity index 100% rename from tryruby/public/stylesheets/site.css rename to public/stylesheets/site.css diff --git a/tryruby/script/rails b/script/rails similarity index 100% rename from tryruby/script/rails rename to script/rails diff --git a/tryruby/test/functional/index_controller_test.rb b/test/functional/index_controller_test.rb similarity index 100% rename from tryruby/test/functional/index_controller_test.rb rename to test/functional/index_controller_test.rb diff --git a/tryruby/test/functional/tutorials_controller_test.rb b/test/functional/tutorials_controller_test.rb similarity index 100% rename from tryruby/test/functional/tutorials_controller_test.rb rename to test/functional/tutorials_controller_test.rb diff --git a/tryruby/test/performance/browsing_test.rb b/test/performance/browsing_test.rb similarity index 100% rename from tryruby/test/performance/browsing_test.rb rename to test/performance/browsing_test.rb diff --git a/tryruby/test/test_helper.rb b/test/test_helper.rb similarity index 100% rename from tryruby/test/test_helper.rb rename to test/test_helper.rb diff --git a/tryruby/test/unit/helpers/index_helper_test.rb b/test/unit/helpers/index_helper_test.rb similarity index 100% rename from tryruby/test/unit/helpers/index_helper_test.rb rename to test/unit/helpers/index_helper_test.rb diff --git a/tryruby/test/unit/helpers/tutorials_helper_test.rb b/test/unit/helpers/tutorials_helper_test.rb similarity index 100% rename from tryruby/test/unit/helpers/tutorials_helper_test.rb rename to test/unit/helpers/tutorials_helper_test.rb diff --git a/tryruby/.gitignore b/tryruby/.gitignore deleted file mode 100644 index f0fa30c..0000000 --- a/tryruby/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -.bundle -db/*.sqlite3 -log/*.log -tmp/ diff --git a/tryruby/README b/tryruby/README deleted file mode 100644 index fe7013d..0000000 --- a/tryruby/README +++ /dev/null @@ -1,256 +0,0 @@ -== Welcome to Rails - -Rails is a web-application framework that includes everything needed to create -database-backed web applications according to the Model-View-Control pattern. - -This pattern splits the view (also called the presentation) into "dumb" -templates that are primarily responsible for inserting pre-built data in between -HTML tags. The model contains the "smart" domain objects (such as Account, -Product, Person, Post) that holds all the business logic and knows how to -persist themselves to a database. The controller handles the incoming requests -(such as Save New Account, Update Product, Show Post) by manipulating the model -and directing data to the view. - -In Rails, the model is handled by what's called an object-relational mapping -layer entitled Active Record. This layer allows you to present the data from -database rows as objects and embellish these data objects with business logic -methods. You can read more about Active Record in -link:files/vendor/rails/activerecord/README.html. - -The controller and view are handled by the Action Pack, which handles both -layers by its two parts: Action View and Action Controller. These two layers -are bundled in a single package due to their heavy interdependence. This is -unlike the relationship between the Active Record and Action Pack that is much -more separate. Each of these packages can be used independently outside of -Rails. You can read more about Action Pack in -link:files/vendor/rails/actionpack/README.html. - - -== Getting Started - -1. At the command prompt, create a new Rails application: - rails new myapp (where myapp is the application name) - -2. Change directory to myapp and start the web server: - cd myapp; rails server (run with --help for options) - -3. Go to http://localhost:3000/ and you'll see: - "Welcome aboard: You're riding Ruby on Rails!" - -4. Follow the guidelines to start developing your application. You can find -the following resources handy: - -* The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html -* Ruby on Rails Tutorial Book: http://www.railstutorial.org/ - - -== Debugging Rails - -Sometimes your application goes wrong. Fortunately there are a lot of tools that -will help you debug it and get it back on the rails. - -First area to check is the application log files. Have "tail -f" commands -running on the server.log and development.log. Rails will automatically display -debugging and runtime information to these files. Debugging info will also be -shown in the browser on requests from 127.0.0.1. - -You can also log your own messages directly into the log file from your code -using the Ruby logger class from inside your controllers. Example: - - class WeblogController < ActionController::Base - def destroy - @weblog = Weblog.find(params[:id]) - @weblog.destroy - logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!") - end - end - -The result will be a message in your log file along the lines of: - - Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1! - -More information on how to use the logger is at http://www.ruby-doc.org/core/ - -Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are -several books available online as well: - -* Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe) -* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide) - -These two books will bring you up to speed on the Ruby language and also on -programming in general. - - -== Debugger - -Debugger support is available through the debugger command when you start your -Mongrel or WEBrick server with --debugger. This means that you can break out of -execution at any point in the code, investigate and change the model, and then, -resume execution! You need to install ruby-debug to run the server in debugging -mode. With gems, use sudo gem install ruby-debug. Example: - - class WeblogController < ActionController::Base - def index - @posts = Post.find(:all) - debugger - end - end - -So the controller will accept the action, run the first line, then present you -with a IRB prompt in the server window. Here you can do things like: - - >> @posts.inspect - => "[#nil, "body"=>nil, "id"=>"1"}>, - #"Rails", "body"=>"Only ten..", "id"=>"2"}>]" - >> @posts.first.title = "hello from a debugger" - => "hello from a debugger" - -...and even better, you can examine how your runtime objects actually work: - - >> f = @posts.first - => #nil, "body"=>nil, "id"=>"1"}> - >> f. - Display all 152 possibilities? (y or n) - -Finally, when you're ready to resume execution, you can enter "cont". - - -== Console - -The console is a Ruby shell, which allows you to interact with your -application's domain model. Here you'll have all parts of the application -configured, just like it is when the application is running. You can inspect -domain models, change values, and save to the database. Starting the script -without arguments will launch it in the development environment. - -To start the console, run rails console from the application -directory. - -Options: - -* Passing the -s, --sandbox argument will rollback any modifications - made to the database. -* Passing an environment name as an argument will load the corresponding - environment. Example: rails console production. - -To reload your controllers and models after launching the console run -reload! - -More information about irb can be found at: -link:http://www.rubycentral.com/pickaxe/irb.html - - -== dbconsole - -You can go to the command line of your database directly through rails -dbconsole. You would be connected to the database with the credentials -defined in database.yml. Starting the script without arguments will connect you -to the development database. Passing an argument will connect you to a different -database, like rails dbconsole production. Currently works for MySQL, -PostgreSQL and SQLite 3. - -== Description of Contents - -The default directory structure of a generated Ruby on Rails application: - - |-- app - | |-- controllers - | |-- helpers - | |-- mailers - | |-- models - | `-- views - | `-- layouts - |-- config - | |-- environments - | |-- initializers - | `-- locales - |-- db - |-- doc - |-- lib - | `-- tasks - |-- log - |-- public - | |-- images - | |-- javascripts - | `-- stylesheets - |-- script - |-- test - | |-- fixtures - | |-- functional - | |-- integration - | |-- performance - | `-- unit - |-- tmp - | |-- cache - | |-- pids - | |-- sessions - | `-- sockets - `-- vendor - `-- plugins - -app - Holds all the code that's specific to this particular application. - -app/controllers - Holds controllers that should be named like weblogs_controller.rb for - automated URL mapping. All controllers should descend from - ApplicationController which itself descends from ActionController::Base. - -app/models - Holds models that should be named like post.rb. Models descend from - ActiveRecord::Base by default. - -app/views - Holds the template files for the view that should be named like - weblogs/index.html.erb for the WeblogsController#index action. All views use - eRuby syntax by default. - -app/views/layouts - Holds the template files for layouts to be used with views. This models the - common header/footer method of wrapping views. In your views, define a layout - using the layout :default and create a file named default.html.erb. - Inside default.html.erb, call <% yield %> to render the view using this - layout. - -app/helpers - Holds view helpers that should be named like weblogs_helper.rb. These are - generated for you automatically when using generators for controllers. - Helpers can be used to wrap functionality for your views into methods. - -config - Configuration files for the Rails environment, the routing map, the database, - and other dependencies. - -db - Contains the database schema in schema.rb. db/migrate contains all the - sequence of Migrations for your schema. - -doc - This directory is where your application documentation will be stored when - generated using rake doc:app - -lib - Application specific libraries. Basically, any kind of custom code that - doesn't belong under controllers, models, or helpers. This directory is in - the load path. - -public - The directory available for the web server. Contains subdirectories for - images, stylesheets, and javascripts. Also contains the dispatchers and the - default HTML files. This should be set as the DOCUMENT_ROOT of your web - server. - -script - Helper scripts for automation and generation. - -test - Unit and functional tests along with fixtures. When using the rails generate - command, template test files will be generated for you and placed in this - directory. - -vendor - External libraries that the application depends on. Also includes the plugins - subdirectory. If the app has frozen rails, those gems also go here, under - vendor/rails/. This directory is in the load path. diff --git a/vendor/plugins/.gitkeep b/vendor/plugins/.gitkeep new file mode 100644 index 0000000..e69de29 From a695e9972aecff5c52969781c737e83007847e19 Mon Sep 17 00:00:00 2001 From: Andrew McElroy Date: Fri, 8 Jul 2011 19:19:29 -0500 Subject: [PATCH 12/16] on branch experi --- Gemfile | 32 +- app/controllers/application_controller.rb | 37 +- app/controllers/classic_controller.rb | 2 + app/controllers/irb_controller.rb | 85 +++ app/controllers/public_controller.rb | 2 + app/controllers/tryruby_controller.rb | 42 ++ app/controllers/tutorials_controller.rb | 4 +- app/helpers/application_helper.rb | 16 + app/helpers/classic_helper.rb | 2 + app/helpers/irb_helper.rb | 2 + app/helpers/public_helper.rb | 2 + app/views/irb/_form.html.erb | 17 + app/views/irb/edit.html.erb | 6 + app/views/irb/index.html.erb | 21 + app/views/irb/new.html.erb | 5 + app/views/irb/show.html.erb | 5 + app/views/layouts/tryruby.rhtml | 96 +++ app/views/layouts/tryruby_2.html.erb | 147 +++++ app/views/tryruby/_donate.html.erb | 41 ++ app/views/tryruby/index.html.erb | 0 app/views/tryruby/run.html.erb | 0 app/views/tutorials/es_intro.html | 666 +++++++++++++++++++++ app/views/tutorials/intro.rhtml | 680 ++++++++++++++++++++++ config/database.yml | 38 +- config/routes.rb | 128 ++-- db/development.sqlite3 | 0 lib/popup.rb | 115 ++++ lib/setup.rb | 68 +++ lib/tasks/cucumber.rake | 53 ++ lib/tryruby.rb | 206 +++++++ log/development.log | 653 +++++++++++++++++++++ tmp/pids/server.pid | 1 + 32 files changed, 3082 insertions(+), 90 deletions(-) create mode 100644 app/controllers/classic_controller.rb create mode 100644 app/controllers/irb_controller.rb create mode 100644 app/controllers/public_controller.rb create mode 100644 app/controllers/tryruby_controller.rb create mode 100644 app/helpers/classic_helper.rb create mode 100644 app/helpers/irb_helper.rb create mode 100644 app/helpers/public_helper.rb create mode 100644 app/views/irb/_form.html.erb create mode 100644 app/views/irb/edit.html.erb create mode 100644 app/views/irb/index.html.erb create mode 100644 app/views/irb/new.html.erb create mode 100644 app/views/irb/show.html.erb create mode 100644 app/views/layouts/tryruby.rhtml create mode 100644 app/views/layouts/tryruby_2.html.erb create mode 100644 app/views/tryruby/_donate.html.erb create mode 100644 app/views/tryruby/index.html.erb create mode 100644 app/views/tryruby/run.html.erb create mode 100644 app/views/tutorials/es_intro.html create mode 100644 app/views/tutorials/intro.rhtml create mode 100644 db/development.sqlite3 create mode 100755 lib/popup.rb create mode 100644 lib/setup.rb create mode 100644 lib/tasks/cucumber.rake create mode 100644 lib/tryruby.rb create mode 100644 tmp/pids/server.pid diff --git a/Gemfile b/Gemfile index b55f320..35a352e 100644 --- a/Gemfile +++ b/Gemfile @@ -2,26 +2,32 @@ source 'http://rubygems.org' gem 'rails', '3.0.9' -# Bundle edge Rails instead: -# gem 'rails', :git => 'git://github.com/rails/rails.git' - -gem 'sqlite3' - +gem 'mysql2', '< 0.3' +gem 'fakefs', '0.2.1', :git => "http://github.com/defunkt/fakefs.git", :ref => "aa0cb96b8ebc81287a2e", :require => 'fakefs/safe' # Use unicorn as the web server # gem 'unicorn' - +gem 'i18n' # Deploy with Capistrano # gem 'capistrano' -gem "fakefs", :require => "fakefs/safe" - gem 'chronic' - + +gem 'devise' + # To use debugger (ruby-debug for Ruby 1.8.7+, ruby-debug19 for Ruby 1.9.2+) # gem 'ruby-debug' # gem 'ruby-debug19', :require => 'ruby-debug' +gem 'jquery-rails' +gem 'ruby_parser' +gem 'racc' +#gem 'ruby2ruby' +#gem 'newrelic_rpm' +#gem 'madmimi' +#gem 'delayed_job' +#gem 'dalli' # Bundle the extra gems: # gem 'bj' -# gem 'nokogiri' + +gem 'nokogiri' # gem 'sqlite3-ruby', :require => 'sqlite3' # gem 'aws-s3', :require => 'aws/s3' @@ -29,5 +35,7 @@ gem "fakefs", :require => "fakefs/safe" # put test-only gems in this group so their generators # and rake tasks are available in development mode: # group :development, :test do -# gem 'webrat' -# end + gem 'capybara' + gem 'rspec-rails' + gem 'cucumber-rails' + #gem 'factory-girl' diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index e8065d9..c0bea36 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,3 +1,38 @@ +# Filters added to this controller apply to all controllers in the application. +# Likewise, all the methods added will be available for all controllers. +#require File.dirname(__FILE__) + '/../../lib/tryruby' + class ApplicationController < ActionController::Base - protect_from_forgery + + + + + layout 'tryruby' + +# attr_accessor :past_commands, :current_statement, :start_time + + +# attr_accessor :past_commands, :current_statement, :start_time + + + + + +=begin + #attr_accessor :session + TryRuby.session = session + + TryRuby.session['start_time'] ||= Time.now + TryRuby.session['current_statement'] ||= '' + TryRuby.session['past_commands'] ||= '' + + helper :all # include all helpers, all the time + protect_from_forgery # See ActionController::RequestForgeryProtection for details + + # Scrub sensitive parameters from your log + # filter_parameter_logging :password + #class << self +=end +# not needed + #end end diff --git a/app/controllers/classic_controller.rb b/app/controllers/classic_controller.rb new file mode 100644 index 0000000..019e234 --- /dev/null +++ b/app/controllers/classic_controller.rb @@ -0,0 +1,2 @@ +class ClassicController < ApplicationController +end diff --git a/app/controllers/irb_controller.rb b/app/controllers/irb_controller.rb new file mode 100644 index 0000000..f296b07 --- /dev/null +++ b/app/controllers/irb_controller.rb @@ -0,0 +1,85 @@ +class IrbController < ApplicationController + # GET /irb + # GET /irb.xml + def index + + @irb = [] + + respond_to do |format| + format.html # index.html.erb + format.to_json + format.xml { render :xml => @irb } + end + end + + # GET /irb/1 + # GET /irb/1.xml + def show + @irb = Irb.find(params[:id]) + + respond_to do |format| + format.html # show.html.erb + format.xml { render :xml => @irb } + end + end + + # GET /irb/new + # GET /irb/new.xml + def new + @irb = Irb.new + + respond_to do |format| + format.html # new.html.erb + format.xml { render :xml => @irb } + end + end + + # GET /irb/1/edit + def edit + @irb = Irb.find(params[:id]) + end + + # POST /irb + # POST /irb.xml + def create + @irb = Irb.new(params[:irb]) + + respond_to do |format| + if @irb.save + format.html { redirect_to(@irb, :notice => 'Irb was successfully created.') } + format.xml { render :xml => @irb, :status => :created, :location => @irb } + else + format.html { render :action => "new" } + format.xml { render :xml => @irb.errors, :status => :unprocessable_entity } + end + end + end + + # PUT /irb/1 + # PUT /irb/1.xml + def update + @irb = Irb.find(params[:id]) + + respond_to do |format| + if @irb.update_attributes(params[:irb]) + format.html { redirect_to(@irb, :notice => 'Irb was successfully updated.') } + format.xml { head :ok } + else + format.html { render :action => "edit" } + format.xml { render :xml => @irb.errors, :status => :unprocessable_entity } + end + end + end + + # DELETE /irb/1 + # DELETE /irb/1.xml + def destroy + @irb = Irb.find(params[:id]) + @irb.destroy + + respond_to do |format| + format.html { redirect_to(irb_url) } + format.xml { head :ok } + end + end +end diff --git a/app/controllers/public_controller.rb b/app/controllers/public_controller.rb new file mode 100644 index 0000000..2857026 --- /dev/null +++ b/app/controllers/public_controller.rb @@ -0,0 +1,2 @@ +class PublicController < ApplicationController +end diff --git a/app/controllers/tryruby_controller.rb b/app/controllers/tryruby_controller.rb new file mode 100644 index 0000000..ec763b7 --- /dev/null +++ b/app/controllers/tryruby_controller.rb @@ -0,0 +1,42 @@ + +class TryrubyController < ApplicationController + + layout 'tryruby' + def index + end + + def run + eval(params[:cmd]) + + #@cmd=params[:cmd] + # @a= run_script(@cmd) + # @b = "handleJSON({\"type\": #{@a.type.to_json}, \"output\":#{@a.output.to_json},\"result\":#{@a.result.inspect.to_json}, \"error\": #{@a.error.inspect.to_json}})" + +begin + render :json => @b + rescue + end + end + + + def run_script(command) + #output = begin + eval(command) + # rescue StandardError => e + # e.message + ". On the " + begin + # Tryrubyengine.session ||= TRSession.new + #TryRuby.run_line(TryRuby.session.cgi['cmd']).format + #Tryrubyengine.new + # @c= Tryrubyengine.session + # @c.inspect + # Tryrubyengine.run_line(command) + rescue + + end + # end + + # return "=> #{output}" + ", says yoda" + end + +end diff --git a/app/controllers/tutorials_controller.rb b/app/controllers/tutorials_controller.rb index 662119f..662aa01 100644 --- a/app/controllers/tutorials_controller.rb +++ b/app/controllers/tutorials_controller.rb @@ -1,6 +1,6 @@ class TutorialsController < ApplicationController -layout 'blank' + def intro + end - end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index de6be79..d995b05 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,2 +1,18 @@ module ApplicationHelper + + def google_analytics_js + ua_code = "UA-2365371-3" + '' + + end + end diff --git a/app/helpers/classic_helper.rb b/app/helpers/classic_helper.rb new file mode 100644 index 0000000..e85110a --- /dev/null +++ b/app/helpers/classic_helper.rb @@ -0,0 +1,2 @@ +module ClassicHelper +end diff --git a/app/helpers/irb_helper.rb b/app/helpers/irb_helper.rb new file mode 100644 index 0000000..6c9f3c9 --- /dev/null +++ b/app/helpers/irb_helper.rb @@ -0,0 +1,2 @@ +module IrbHelper +end diff --git a/app/helpers/public_helper.rb b/app/helpers/public_helper.rb new file mode 100644 index 0000000..0d8e188 --- /dev/null +++ b/app/helpers/public_helper.rb @@ -0,0 +1,2 @@ +module PublicHelper +end diff --git a/app/views/irb/_form.html.erb b/app/views/irb/_form.html.erb new file mode 100644 index 0000000..4e3cdae --- /dev/null +++ b/app/views/irb/_form.html.erb @@ -0,0 +1,17 @@ +<%= form_for(@irb) do |f| %> + <% if @irb.errors.any? %> +
                  +

                  <%= pluralize(@irb.errors.count, "error") %> prohibited this irb from being saved:

                  + +
                    + <% @irb.errors.full_messages.each do |msg| %> +
                  • <%= msg %>
                  • + <% end %> +
                  +
                  + <% end %> + +
                  + <%= f.submit %> +
                  +<% end %> diff --git a/app/views/irb/edit.html.erb b/app/views/irb/edit.html.erb new file mode 100644 index 0000000..9e50dc3 --- /dev/null +++ b/app/views/irb/edit.html.erb @@ -0,0 +1,6 @@ +

                  Editing irb

                  + +<%= render 'form' %> + +<%= link_to 'Show', @irb %> | +<%= link_to 'Back', irb_path %> diff --git a/app/views/irb/index.html.erb b/app/views/irb/index.html.erb new file mode 100644 index 0000000..90b773b --- /dev/null +++ b/app/views/irb/index.html.erb @@ -0,0 +1,21 @@ +

                  Listing irb

                  + + + + + + + + +<% @irb.each do |irb| %> + + + + + +<% end %> +
                  <%= link_to 'Show', irb %><%= link_to 'Edit', edit_irb_path(irb) %><%= link_to 'Destroy', irb, :confirm => 'Are you sure?', :method => :delete %>
                  + +
                  + +<%= link_to 'New Irb', new_irb_path %> diff --git a/app/views/irb/new.html.erb b/app/views/irb/new.html.erb new file mode 100644 index 0000000..9a7b635 --- /dev/null +++ b/app/views/irb/new.html.erb @@ -0,0 +1,5 @@ +

                  New irb

                  + +<%= render 'form' %> + +<%= link_to 'Back', irb_path %> diff --git a/app/views/irb/show.html.erb b/app/views/irb/show.html.erb new file mode 100644 index 0000000..c271c01 --- /dev/null +++ b/app/views/irb/show.html.erb @@ -0,0 +1,5 @@ +

                  <%= notice %>

                  + + +<%= link_to 'Edit', edit_irb_path(@irb) %> | +<%= link_to 'Back', irb_path %> diff --git a/app/views/layouts/tryruby.rhtml b/app/views/layouts/tryruby.rhtml new file mode 100644 index 0000000..9ab71c1 --- /dev/null +++ b/app/views/layouts/tryruby.rhtml @@ -0,0 +1,96 @@ + + + + + try ruby! (en tu navegador) + + + + + + + + + +
                  + +
                  +
                  +
                  + +

                  A Popup Browser

                  +

                  [x]

                  +
                  + +
                  +
                  + +
                  +
                  +
                  +
                  +
                  +
                  +

                  ¿Tienes 15 minutos? ¡Prueba Ruby ahora mismo!

                  +

                  Ruby es un lenguaje de programación de Japón + (disponible en ruby-lang.org) + que está revolucionando la web. + La belleza de Ruby se encuentra en su balance entre la simplicidad y el poder.

                  + +

                  Prueba código Ruby en el prompt de arriba. Además de los métodos + originales de Ruby, los siguientes comandos están disponibles:

                  +
                    +
                  • help + Empieza el tutorial interactivo de 15 minutos. ¡Creeme, es muy básico!
                  • +
                  • help 2 + Salta al capítulo 2.
                  • + +
                  • clear + Limpia la pantalla. Útil si tu navegador empieza a alerdarce. + Tu historial de comandos será recordado. +
                  • back + Retrocede una pantalla en el tutorial.
                  • +
                  • reset + Resetea el interprete. (o Ctrl-D!)
                  • +
                  • next + Te permite saltear la siguiente lección
                  • + +
                  • time + Detiene el reloj. Imprime cuanto tiempo tu sesión estuvo abierta.
                  • +
                  +

                  Si te pasa de dejar o refrescar la página, tu sesión seguirá aquí a menos que + se deje inactiva por diez minutos.

                  +
                  +
                  +
                  + +
                  +
                  ¿Atrapado en los dos puntos? Unas comillas o algo fue dejado abierto. Escribe: reset o aprieta Ctrl-D.
                  +
                  + +

                  This place was sired by why the lucky stiff. + Please contact me using the email address at that link.is maintained by Andrew McElroy and David Miani. For support issues, please post a ticket or contact Sophrinix on github.
                  Por asuntos de traducción, mandar un ticket o contactarse con Cristian Re (leizzer) en Github.
                  +

                  + +
                  + + + + + + + + + + diff --git a/app/views/layouts/tryruby_2.html.erb b/app/views/layouts/tryruby_2.html.erb new file mode 100644 index 0000000..fbdd73e --- /dev/null +++ b/app/views/layouts/tryruby_2.html.erb @@ -0,0 +1,147 @@ + + + + Try Haskell! An interactive tutorial in your browser + + + + + + + + + + + + +
                  +
                  +
                  +
                  +
                  +

                  Try Haskell! An interactive tutorial in your + browser

                  + +
                  + +
                  +
                  +
                  + +

                  A Popup Browser

                  +

                  [x]

                  +
                  + <%= yield %> + + +
                  +
                  + +
                  +
                  +
                  +
                  +
                  +
                  + +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +

                  + Welcome to your first taste of Haskell! Let's try Haskell right now! +

                  +

                  Beginners

                  +
                  +

                  Type help to start the + tutorial. Type lessons to see the + list of lessons.

                  +

                  Or try typing these out and see what happens + (click to insert):

                  +
                    +
                  • + 23*36 +
                  • +
                  • + reverse "hello" +
                  • +
                  +
                  +
                  +

                  Learn More

                  +
                  +

                  + Real World Haskell! + Get stuck into a book with + Real + World Haskell + (readable online!), published by O'Reilly Media. + Checkout + Haskell.org + for more information about Haskell.

                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  + +
                  +
                  + + diff --git a/app/views/tryruby/_donate.html.erb b/app/views/tryruby/_donate.html.erb new file mode 100644 index 0000000..f7095b1 --- /dev/null +++ b/app/views/tryruby/_donate.html.erb @@ -0,0 +1,41 @@ + \ No newline at end of file diff --git a/app/views/tryruby/index.html.erb b/app/views/tryruby/index.html.erb new file mode 100644 index 0000000..e69de29 diff --git a/app/views/tryruby/run.html.erb b/app/views/tryruby/run.html.erb new file mode 100644 index 0000000..e69de29 diff --git a/app/views/tutorials/es_intro.html b/app/views/tutorials/es_intro.html new file mode 100644 index 0000000..6a8e773 --- /dev/null +++ b/app/views/tutorials/es_intro.html @@ -0,0 +1,666 @@ + +
                  +

                  Usando El Prompt

                  +

                  La ventana azul de arriba es el prompt de Ruby. ¡Escribe una línea de código Ruby, aprieta Enter + y velo correr!

                  +

                  Por ejemplo, trata de escribir algo matemático. Como: 2 + 6

                  +
                  \d+
                  +
                  +
                  +

                  Números & Matemática

                  +

                  ¡Bien! Hiciste algo de matemática. ¿Ves como la respuesta salta a la vista?

                  +

                  Ruby reconoce números y símbolos matemáticos. Puedes probar otras cosas como:

                  +
                  • 4 * 10
                  • +
                  • 5 - 12
                  • +
                  • 40 / 4
                  +

                  Seguro, las computadoras son habilidosas y rápidas con las matemáticas. Sigamos... ¿Quieres ver tu nombre al revés? + Escribe tu primer nombre entre comillas así: "Jimmy"

                  +
                  "(\w+)"
                  +
                  +
                  +

                  Decir Tu Nombre Al Revés

                  +

                  Perfecto, has formado un string de las letras de tu nombre. Un string + es un juego de caracteres que la computadora puede procesar.

                  +

                  Imagina que las letras están en una cuerda donde + se cuelga la ropa y las comillas son los broches que sostienen los bordes. Las comillas marcan el comienzo y el final.

                  +

                  Para invertir tu nombre, escribe: "Jimmy".reverse (¡No olvides el punto!)

                  +
                  "(\w+)"
                  +
                  +
                  +

                  Contando Las Letras

                  +

                  ¡Has usado el método reverse sobre tu nombre! Poniendo tu nombre entre comillas, + hiciste un string. Luego llamaste al método reverse, que funciona sobre un string cambiando + todas las letras de atrás para adelante.

                  +

                  Ahora, vamos a ver cuantas letras tiene tu nombre: "Jimmy".length

                  +
                  \d+
                  +
                  +
                  +

                  Repitiendo

                  +

                  Ahora, estoy seguro que te estarás preguntando para que sirve todo esto. Bueno, estoy seguro que habrás estado en alguna + pagina web donde te gritaron, ¡Hey, tu password es muy corto! Ves, algunos programas + usan este código tan simple.

                  +

                  Mira esto. Vamos a multiplicar tu nombre por 5. "Jimmy" * 5

                  +
                  "(\w+)"
                  +
                  +
                  +

                  Hey, Sumario #1 Listo

                  +

                  Vamos a ver que es lo que has aprendido en el primer minuto.

                  +
                    +
                  • El prompt. Escribiendo código en el prompt verde obtienes + una respuesta del prompt rojo. Todo código te da una respuesta.
                  • +
                  • Números y strings son objetos matemáticos y de texto de Ruby.
                  • +
                  • Métodos Has usado métodos en Ingles como reverse + y métodos simbólicos como * (el método de multiplicación.) ¡Los métodos son acciones!
                  • +
                  +

                  Esta es la esencia del aprendizaje. Tomar cosas simples, jugar con ellas + y trasformarlas en cosas nuevas. ¿Te sientes cómodo con todo? Te aseguro que lo estas.

                  +

                  Bien, vamos a hacer algo incomodo. Trata de invertir un número: 40.reverse

                  +
                  NoMethodError: undefined method `reverse' for (\d+):Fixnum
                  +
                  +
                  +

                  ¡Basta, Te Volviste Loco!

                  +

                  No puedes invertir el numero cuarenta. Supongo que puedes poner tu monitor en + frente de un espejo, pero invertir un numero no tiene sentido. Ruby lanza un + mensaje de error. Ruby te dice que no hay un método reverse para los números.

                  +

                  Tal vez si lo conviertes en un string: 40.to_s.reverse.

                  +
                  \"(\d+)\"
                  +
                  +
                  +

                  Los Chicos Son Diferentes De Las Chicas

                  +

                  Y los números son diferentes de los strings. Aunque puedes usar métodos en cualquier objeto + en Ruby, algunos métodos solo funcionan en cierto tipo de cosas. Pero siempre puedes + convertir entre diferentes tipos usando el método "to" de Ruby.

                  +
                  • to_s convierte cosas a strings.
                  • +
                  • to_i convierte cosas a integers (números.)
                  • +
                  • to_a convierte cosas a arrays.
                  • +
                  +

                  ¿Que son los arrays?! Son listas. Escribe entre un par de corchetes: [].

                  +
                  \[\]
                  +
                  +
                  +

                  Mantenerse en Cola

                  +

                  Genial, eso es una lista vacía. Las listas guardan cosas en orden. + Como esperando en la cola para palomitas de maíz. Estas atrás de alguien y jamás + pensarías en empujarlo a un costado, ¿no es así? Y con respecto al tipo detrás de ti, + mantienes un ojo sobre el, ¿correcto?

                  +

                  Acá hay una lista para ti. Números de la lotería: [12, 47, 35].

                  +
                  \[(\d+(, )?){2,}\]
                  +
                  +
                  +

                  Uno Levanta La Mano

                  +

                  Una lista de números de la lotería. ¿Cual es el mayor?

                  +

                  Prueba: [12, 47, 35].max.

                  +
                  (\d+)
                  +
                  +
                  +

                  Manteniendo la Lista

                  +

                  Bien, bien. Pero es un fastidio el tener que reescribir esa lista, ¿no es así?

                  +

                  Guardemos nuestros números en un ticket de esta manera: ticket = [12, 47, 35]

                  +
                  \[(\d+(, )?){2,}\]
                  +
                  +
                  +

                  Ahora Escribe Ticket

                  +

                  Ahora, escribe: ticket

                  +
                  \[(\d+(, )?){2,}\]
                  +
                  +
                  +

                  Guardado, Escondido

                  +

                  ¡Fantástico! Te has aferrado a tus números de la lotería, escondiéndolos dentro de una + variable llamada ticket.

                  +

                  Vamos a poner tus números en orden, que te parece? Usa: ticket.sort!

                  +
                  \[(\d+(, )?){2,}\]
                  +
                  +
                  +

                  Sumario #2 Está Sobre Nosotros

                  +

                  Tenías una lista. Ordenaste la lista. La variable ticket ahora esta cambiada.

                  +

                  ¿Te diste cuenta que el método sort! tiene un claro y llamativo signo de exclamación al final? + Muchas veces los métodos de Ruby gritan así si es que alteran la variable para bien. No es nada + especial, solo una marca.

                  +

                  Ahora, mira como te fue en tu segundo minuto:

                  +
                    +
                  • Errors. Si tratas de invertir un número o hacer algo sospechoso, + Ruby salteara el prompt para avisarte.
                  • +
                  • Arrays son listas para ordenar cosas en orden.
                  • +
                  • Variables guardan cosas y le dan un nombre. Usaste el + signo igual para hacerlo.
                    Like: ticket = [14, 37, 18].
                  • +
                  +

                  En total hay ocho lecciones. Estás a dos octavos de camino! + Esto es cosa simple, no te parece? Las cosas buenas están mas adelante.

                  +

                  Cambiemos de dirección por un momento. Rellené con un poco de poesía cierta + variable para ti. Hecha un vistazo. Escribe print poem

                  +
                  poem = "My toast has flown from my hand\nAnd my toast has gone to the +moon.\nBut when I saw it on television,\nPlanting our flag on Halley's +comet,\nMore still did I want to eat it.\n"
                  +
                  My toast (.+)
                  +
                  +
                  +

                  Desgraciadamente, Tú Odias la poesía de Tostadas

                  +

                  Mira, esta bien. No tiene que gustarte. Hackéalo, yo invito.

                  +

                  En vez de tostada, ve por un melón o algo. Prueba esto: poem['toast'] = 'honeydew'

                  +

                  Y luego escribe print poem para ver el nuevo poema.

                  +
                  My honey(.+)
                  +
                  +
                  +

                  Listo, Apuntado

                  +

                  Los corchetes que acabas de usar son muy comunes en Ruby. Recuerda, escribiste: poem['toast'] = 'honeydew'. Esa casilla con la palabra toast tiene corchetes a ambos lados, ¿ves?

                  +

                  Los +corchetes son como una mira para alinear un objetivo. Exacto. Estos +corchetes significan, "Estoy buscando ____." Listo, apuntado. Aquí estas buscando +una costada e intercambiándola por una fruta.

                  +

                  Aquí hay una pregunta: ¿Que pasa si volteamos el poema entero? poem.reverse +

                  "\\n.ti tae ot (.+)"
                  +
                  +
                  +

                  Demasiado Invertido

                  +

                  Está bien, seguro. Entonces todo el poema fue puesto al revés. Letra por letra. Sin embargo, yo realmente solo quería + invertir las líneas. Mover la última línea a la primera y la primera hacia abajo a la ultima. Al revés, pero no + ése revés.

                  +

                  Aquí esta como lograrlo: poem.lines.to_a.reverse

                  +
                  \["More still did I(.+)"\]
                  +
                  +
                  +

                  Rizos de Metodos Concatenados

                  +

                  Dime, que es lo que ves? Que paso acá? Escribiste poem.lines.to_a.reverse y ¿que pasó?

                  +

                  Dos cosas pasaron. Convertiste poem en una lista usando +lines.to_a. lines decide la forma en que +el string se divide, luego to_a lo +convierte en un Array. (To array.) Diferentes métodos, como +bytes y chars pueden ser usadas en lugar de +lines. Usando lines, Ruby retornará cada línea de poem.

                  +

                  Luego, tu revertiste, reversed, esa lista. Tenías cada línea. Las revertiste. Eso es todo.

                  +

                  Vamos a hilar un método más al final de todo esto: print poem.lines.to_a.reverse.join +

                  More still did I(.+)
                  +
                  +
                  +

                  De Todos los Sumarios, el #3 esta aquí

                  +

                  Buen espectáculo, mi amigo! El método join toma la lista de líneas revertidas y las pone juntas en un string. + (Seguro, también podrías haber usado to_s.)

                  +

                  Tiempo de Revisión.

                  +
                    +
                  • Exclamaciones. Métodos pueden tener signos de exclamación (y también de interrogación) en + sus nombres. No es la gran cosa. Prueba: poem.include? "my hand"
                  • +
                  • Corchetes. Establece objetivos y busca cosas. Busca y reemplaza.
                  • +
                  • Concatenar métodos te permite hacer mas cosas juntas. Partir poem, revertirlo, + reensamblarlo: poem.lines.to_a.reverse.join
                  • +
                  +

                  En este punto, querras manosear un poco más el poema. Una lista completa de métodos + String estan + + acá. + No temas y prueba algunos (como poem.downcase o poem.delete.)

                  +

                  Cuando estés listo para seguir adelante, escribe: books = {}

                  +
                  \{\}
                  +
                  +
                  +

                  Un Pequeñín Libro en Blanco

                  +

                  Has hecho un hash vacío. (también conocido como: un diccionario vacío.)

                  +

                  Vamos a rellenar con un libro de críticas en miniatura. Acá esta nuestro sistema de calificación:

                  +
                    +
                  • :splendid → una obra maestra.
                  • +
                  • :quite_good → disfrutable, por supuesto que sí.
                  • +
                  • :mediocre → partes iguales de bueno y malo.
                  • +
                  • :quite_not_good → notablemente malo.
                  • +
                  • :abyssmal → una perdida de tiempo.
                  • +
                  +

                  Para calificar un libro, pon el título entre corchetes y la calificación luego del signo igual.

                  +

                  Por ejemplo: books["Gravity's Rainbow"] = :splendid

                  +
                  :\w+
                  +
                  +
                  +

                  Mas Críticas Tamaño Bocadillo

                  +

                  Tú sigue, agrega mas críticas. Y, si quieres ver toda la lista, + implemente escribe: books

                  +

                  De nuevo, las calificaciones son: :splendid, :quite_good, :mediocre, + :quite_not_good, and :abyssmal.

                  +

                  Estas calificaciones no son strings. Cuando colocas dos puntos frente a una palabra simple, obtienes un + symbol. Los símbolos son más baratos que los strings (en términos de memoria de la computadora.) Si usas + una palabra una y otra vez en un programa, usa un símbolo. En vez de tener miles de + copias de una palabra en memoria, la computadora guardara el símbolo solamente una vez.

                  +

                  Una vez que tengas tres o cuatro libros allí + dentro, escribe: books.length.

                  +
                  [3-9]
                  +
                  +
                  +

                  Espera, ¿Me gustó Gravity's Rainbow?

                  +

                  Ves, el método length funciona sobre strings, list y hashes. Una gran cosa acerca de + Ruby es que los nombres usualmente se reutilizan, lo que significa menos nombres para recordar.

                  +

                  Si quisieras ver una de tus críticas hechas, vuelve a poner el título entre corchetes. Pero deja de lado el + signo igual.

                  +

                  Al igual que aquí: books["Gravity's Rainbow"]

                  +
                  :\w+
                  +
                  +
                  +

                  Hashes como Pares

                  +

                  Ten en mente que los hashes no mantienen las cosas en orden. Ese no es su trabajo. Solo emparejará dos + cosas: una key (llave) y un valor. En tus críticas, la key es el + titulo del libro y el valor es la calificación.

                  +

                  Si simplemente quieres ver los títulos de los libros que calificaste: books.keys

                  +
                  \[".*"\]
                  +
                  +
                  +

                  ¿Eres Duro?

                  +

                  ¿Estás dando duras injustas críticas? Sigamos puntuando con rigurosidad:
                  ratings = Hash.new {0}

                  +

                  Entonces, bien, ahora vamos a contar tus críticas. Trata de seguirme. Escribe:
                  + books.values.each { |rate| ratings[rate] += 1 }

                  +

                  (La línea vertical es el signo de tubería, probablemente lo logres con AltGr+1 con tu teclado.)

                  +
                  \[:.+\]
                  +
                  +
                  +

                  Un Recuento

                  +

                  Genial, wow! Has hecho un recuento de tus calificaciones. Escribe ratings para ver las cuenta. Este nuevo + hash muestra las calificaciones y luego el numero de veces que has dado esa calificación.

                  +

                  Una de las asombrosas cosas nuevas que acabamos de usar es un bloque, block. Vamos a explorar + explore these more in the next summary. más esto en el próximo sumario. Pero, básicamente, un bloque es un pedazo de código Ruby + rodeado por llaves.

                  +

                  Probemos otro bloque: 5.times { print "Odelay!" }

                  +
                  Odelay!Od.*
                  +
                  +
                  +

                  Ahora Arribamos al Sumario #4

                  +

                  Los bloques están siempre apegados a métodos. Como el método times, que toma el bloque y lo corre + repetidas veces. (En este caso: cinco veces.)

                  +

                  Esta última lección fue algo mas larga. Probablemente usaste unos tres minutos aprendiendo sobre:

                  +
                    +
                  • Hashes. El pequeño diccionario con páginas arrugadas: {}.
                  • +
                  • Symbols. Pequeñas, eficientes palabras con dos puntos: :splendid.
                  • +
                  • Blocks. Pedazos de código que pueden ser clavados a muchos métodos de Ruby. Aquí + esta el código que usaste para crear el recuento:
                    books.values.each { |rate| ratings[rate] += 1 }.
                  • +
                  +

                  En tu computadora, probablemente tienes muchos archivos diferentes. Archivos con fotos en ellos, + archivos con programas dentro. Y los archivos usualmente se organizan en carpetas, también llamadas: + directorios.

                  +

                  He preparado algunos directorios para ti. Echa un vistazo: + Dir.entries "/"

                  +
                  \["\.", .+\]
                  +
                  +
                  +

                  La Privada Colección de Dr. Dir

                  +

                  Acabas de listar todo lo existente en el directorio superior. El directorio raíz, indicado + por la barra en diagonal. Conteniendo algunos programas y otros tutoriales y semejantes.

                  +

                  Entonces, ¿que es el método Dir.entries? Bueno, es solo un método ¿si?, + entries es el método llamado sobre la variable Dir. + Y Dir tiene una colección de métodos para chequear los archivos de los directorios.

                  +

                  Otra pequeña cosa de la que no hemos hablado abiertamente. Argumentos de los métodos, resaltados en verde.

                  +
                    +
                  • Dir.entries "/": Cualquier cosa listada luego de un método + es considerado acoplamiento.
                  • +
                  • print poem: Ves, print es un método ordinario. + Y el poema esta acoplado. Para ser impreso.
                  • +
                  • print "pre", "event", "ual", "ism" posee varios argumentos, + con comas entre ellos.
                  • +
                  +

                  Para listar solamente archivos de texto en el directorio: Dir["/*.txt"]

                  +
                  \["\/comics\.txt"\]
                  +
                  +
                  +

                  Ven, Lee Historietas Conmigo

                  +

                  El método Dir[] hace como entries pero tu buscas por archivos + archivos con carácteres de comodín. ¡Aquí, vemos esos corchetes otra vez! Te das + cuenta como todavía significan, "Estoy buscando _____.".

                  +

                  Mas específicamente: "Estoy buscando archivos que terminen con .txt."

                  +

                  Abramos este archivo con historietas de una vez. Aquí esta la manera:
                  + print File.read("/comics.txt")

                  +
                  Achewood.+
                  +
                  +
                  +

                  Mi Comicas, Tu Comicas

                  +

                  ¡De acuerdo! Podemos comenzar a usar archivos para guardar cosas. Esto es excelente + porque normalmente cuando salimos de Ruby, todas nuestras variables desaparecerán. + Ruby, por si mismo, olvida estas cosas. Pero si salvamos cosas en archivos, + podemos leer esos archivos en futuras escapadas a Ruby.

                  +

                  Hey, y ¿adivina que? ¡El directorio /Home es tuyo! ¡Te lo entrego a ti! ¡Soy generoso! Hagamos una copia del archivo de la historieta.

                  +

                  Querrás hacer lo siguiente: FileUtils.copy('/comics.txt', '/Home/comics.txt') +

                  Si ya has creado el archivo, usa File.delete('/Home/comics.txt') para arrojarlo a la basura.

                  +
                  nil
                  +
                  +
                  +

                  Tu Propio Territorio

                  +

                  Ok, tienes una copia. Chequéala: Dir["/Home/*.txt"]

                  +

                  Para agregar tu propia historieta a la lista, abramos el archivo en modo append.

                  +

                  Empieza asi: File.open("/Home/comics.txt", "a") do |f|.

                  +
                  ..
                  +
                  +
                  +

                  Y Ahora, para la Sorprendente Conclusión

                  +

                  Asi que tu prompt ha cambiado. ¿Lo notas? Tu prompt es doble punto ahora.

                  +

                  En este tutorial, este prompt significa que Ruby espera que escribas más. A + medida que vayas completando con líneas de código, los doble puntos se mantendrán + hasta que hallas finalizado.

                  +

                  Hot tip: si quieres parar de trabajar en el código y salirte de los doble puntos, usa el comando reset. + Si quieres volver a la pagina previa del tutorial, usa el comando back.

                  +

                  Aquí esta tu código. Ya has escrito la primera línea, asi que simplemente ingresa la segunda. (El \n + es el carácter de Enter.

                  +
                  • File.open("/Home/comics.txt", "a") do |f|
                  • +
                  •   f << "Cat and Girl: http://catandgirl.com/\n"
                  • +
                  • end
                  • +
                  +

                  Y, como te has vuelto avanzado y capaz aquí, otro tip: puedes usar las flechas hacia + arriba y hacia abajo para editar tus viejos comandos o correrlos otra vez.

                  +
                  ..
                  +
                  +
                  +

                  Ruby se Sienta y Espera

                  +

                  Esa ultima línea agrega la historieta Cat and Girl a la lista, pero Ruby seguirá esperando + hasta que hallas terminado por completo para tomar acción.

                  +

                  Ahora, para finalizar el código que has empezado. Empezaste un nuevo bloque cuando escribiste do. + Hasta ahora los bloques que hemos visto usaban llaves. Esta vez usaremos do y end en lugar + de las llaves. Muchos Rubyistas usan do...end cuando el bloque ocupa varias líneas.

                  +

                  Terminemos ese bloque ahora mismo, con: end

                  +
                  • File.open("/Home/comics.txt", "a") do |f|
                  • +
                  •   f << "Cat and Girl: http://catandgirl.com/\n"
                  • +
                  • end
                  • +
                  +
                  #.File:/Home/comics\.txt.
                  +
                  +
                  +

                  El Reloj Clavado en el Archivo

                  +

                  ¡Bien, bien! Has añadido esa historieta al archivo. Puedes verlo por ti mismo: print File.read("/Home/comics.txt")

                  +

                  ¿Qué hora era cuando cambiaste el archivo? Veamos. Escribe: File.mtime("/Home/comics.txt")

                  +
                  \w+ \w+ \d+ \d{2}:\d{2}:\d{2} [+-]\d{4} \d{4}
                  +
                  +
                  +

                  Sólo la Manecilla de la Hora

                  +

                  Estupendo, allí esta la hora. La hora exacta en la que agregaste la historieta al archivo. El mtime te devuelve un objeto Time de Ruby.

                  +

                  Si sólo quieres ver la hora que era, aprieta la flecha para arriba y cambia la línea a: File.mtime("/Home/comics.txt").hour

                  +
                  \d+
                  +
                  +
                  +

                  Hola, ¿Quién Anda Ahí? Y el Sumario #5 Agita su Sombrero!

                  +

                  Bien hecho, bien hecho, bien hecho, ¡bien hecho! Realmente, realmente, realmente, realmente, ¡reaaaaaaaaalllmente!

                  +

                  Aquí esta tu último minuto de tu vida en retrospectiva:

                  +
                    +
                  • Archivos. ¿Que más se puede decir? Muchos métodos para editar archivos y revisar directorios.
                  • +
                  • Argumentos. Los argumentos son listas de cosas mandadas en un método. Separadas con comas.
                  • +
                  • También hablamos sobre do y end que es otra manera de hacer un bloque.
                  • +
                  +

                  Ahora ya sabes como usar Ruby por completo. Me refiero a que tienes lo esencial. Solo necesitas seguir + aprendiendo métodos y probar bloques más complejos.

                  +

                  Pero existe un lado de Ruby que no hemos hablado. Hacer tus propios métodos y clases.

                  +

                  Ahem! Acabemos con ello de una vez.

                  +

                  Empieza con: def load_comics( path )

                  +
                  ..
                  +
                  +
                  +

                  En Ruby, Def Leppard Significa ¡Define Leppard (un Método)!

                  +

                  Hey, bueno, lo hiciste. Estas haciendo tu propio método. Comenzaste con def, seguido por el nombre del método. + Y una lista de argumentos que va a necesitar el método. ¡Esto no da tanto miedo ni es peligroso!

                  +

                  Todo lo que debemos hacer es rellenar con Ruby y terminarlo con end.

                  +

                  Aquí esta el código:

                  +
                  • def load_comics( path )
                  • +
                  •   comics = {}
                  • +
                  •   File.foreach(path) do |line|
                  • +
                  •     url, name = line.split(': ')
                  • +
                  •     comics[url] = name.strip
                  • +
                  •   end
                  • +
                  •   comics
                  • +
                  • end
                  • +
                  +

                  No necesitas indentar, si no quieres. Lo hice solo para que sea más legible.

                  +
                  nil
                  +
                  +
                  +

                  La Madura Fruta de tu Propia Creación

                  +

                  Un nuevo método ha nacido. Vamos a usarlo: comics = load_comics('/comics.txt')

                  +

                  Si tienes un problema, puedes haberlo escrito mal. Usa el comando back y prueba otra vez.

                  +
                  \{.*"Achewood"=."http://achewood.com/".*\}
                  +
                  +
                  +

                  Hey, Cool, Una Cosa de Historietas

                  +

                  En tu ventana de Ruby arriba, mira el código que has escrito para el método load_comics. ¿Qué esta pasando? Tu estas + pasando en la variable path y estas recibiendo la variable comics. Ruby permite filtrar el hash comics + que es devuelto al final del método.

                  +

                  Una cantidad de métodos se usaron para realizar el trabajo. Fíjate si puedes hallarlos.

                  +
                  • File.foreach es el método que abre un archivo y manda cada línea al bloque. La variable line + dentro del bloque do...end va turnando con cada línea del archivo.
                  • +
                  • split es un método para strings, que rompe los string en colocándolo en un array. Un hacha es arrojada sobre las comas + y las líneas se cortan en dos, dándonos la url y el nombre, name, de las historietas.
                  • +
                  • strip remueve los espacios extra alrededor de name. Por si acaso.
                  • +
                  +

                  Justo allí. Bravo. Tienes las historietas en un hash de Ruby. ¿Pero ahora qué? ¿Qué tan bueno es en verdad?

                  +

                  Hagamos una página de links. ¿Qué te parece? Vamos a necesitar una pequeña librería que hice para ti.

                  +

                  Escribe: require 'popup'

                  +
                  true
                  +
                  +
                  +

                  El Navegador de Títere

                  +

                  Excelente, has cargado la librería popup. Está guardada en un archivo en el directorio Libraries. Mira: Dir["/Libraries/*"]

                  +

                  La librería popup contiene un puñado de métodos que he escrito y te dejaran controlar ventanas emergentes aquí en Try Ruby.

                  +

                  Mira, prueba esto: Popup.goto "http://google.com/"

                  +
                  \033\[1;JSm.*popup_goto\(.*\)\033\[m.*
                  +
                  +
                  +

                  Haciendo Links e Hilando Redes

                  +

                  Nuestro propio adorable, pequeño popup para manipular. también puedes rellenarlo con tus cositas. Empecemos por algo pequeño:

                  +
                  • Popup.make {
                  • +
                  •   h1 "My Links"
                  • +
                  •   link "Go to Google", "http://google.com/"
                  • +
                  • }
                  • +
                  +

                  El termino h1 (h-uno) significa encabezado de nivel uno. En HTML, es el encabezado más grande.

                  +
                  \033\[1;JSm.*popup_make\(.*h1.*a href.*\)\033\[m.*
                  +
                  +
                  +

                  Los Popups son tan fáciles, es una Locura

                  +

                  Se ve bien, lo hiciste perfecto, tal como se te pidió. Hagamos una lista entonces.

                  +

                  Aquí esta como haces una lista con la librería de popup:

                  +
                  • Popup.make do
                  • +
                  •   h1 "Things To Do"
                  • +
                  •   list do
                  • +
                  •     p "Try out Ruby"
                  • +
                  •     p "Ride a tiger"
                  • +
                  •     p "(down River Euphrates)"
                  • +
                  •   end
                  • +
                  • end
                  • +
                  +

                  El método p es la manera corta para "párrafo".

                  +
                  \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*li.*\)\033\[m.*
                  +
                  +
                  +

                  Expandiendo las Historietas en la Tabla

                  +

                  Bien, esto esta yendo maravilloso. Esto es algo simple, pero mantén en mente que no sabias nada sobre Ruby hace quince minutos atrás!<

                  +

                  Ultimo paso. Vamos a juntar todo, ¿sabes? ¡Juntémoslo como esos juegos de + campanillas hermosas que tintinean en los pórticos bajo la hermosa luz del sol + en la playa!

                  +

                  Asegúrate de que las historietas están cargadas: comics = load_comics( '/comics.txt' )

                  +

                  Ahora, hagamos una lista de links para cada historieta:

                  +
                  • Popup.make do
                  • +
                  •   h1 "Comics on the Web"
                  • +
                  •   list do
                  • +
                  •     comics.each do |name, url|
                  • +
                  •       link name, url
                  • +
                  •     end
                  • +
                  •   end
                  • +
                  • end
                  • +
                  +

                  Puedes clickear en los links y leer las historietas ¡inclusive en la ventana principal! ¡Bárbaro!

                  +
                  \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*a href.*li.*a href.*\)\033\[m.*
                  +
                  +
                  +

                  Sumario #6 lo que Significa que has Llegado Muy Lejos

                  +

                  Eres un clérigo nivel 6 de Ruby. Quiero decir que buen trabajo has hecho. Vamos a revisar:

                  +
                    +
                  • Agregaste tu propio método con def y usaste ese método load_comics varias veces.
                  • +
                  • Librerias. Tú usaste el método require para cargar la librería popup.
                    Escribiendo: require 'popup'
                  • +
                  • Y como si no fuera suficiente, hiciste tu propia página web para listar los archivos de historietas. ¡Hiciste un programa real!
                  • +
                  +

                  Entonces ¿Qué podrá venir luego? ¿Qué deberías aprender posiblemente ahora? + Ja, esta es la mejor parte. Has recorrido un largo camino y ahora descubrirás + las clases. En dos lecciones mas y ya estarás hecho.

                  +

                  Tempranamente, creamos un hash como este: Hash.new pruébalo.

                  +
                  \{\}
                  +
                  +
                  +

                  No una Clase de Escuela, Una Clase Trabajadora

                  +

                  Ves, las llaves vacías {} son abreviaciones para Hash.new. El método new + es usado para hacer objetos de cierta clase. (Piensa "clase" como en "clase + trabajadora" — un grupo especifico de objetos similares, tienen el + mismo trabajo, la misma camisa.)

                  +

                  Pregúntate esto: ¿Cómo haría mi blog en Ruby? ¿Dónde deberías + comenzar? Bien, deberías guardar tus entradas del blog en un archivo, ¿cierto? + Pero ¿cómo seguirías los títulos de las entradas y el momento en que fue creado? + Y cuando cargas el archivo, ¿cómo se vería en Ruby? ¿Sería un Hash? ¿O un Array? ¿O + un Array de Arrys? ¿O alguna otra cosa?

                  Yo realmente creo que querrás usar una clase. Ya estas familiarizado con varias clases: Hash, Array, String.

                  +

                  Hagamos una clase nueva: class BlogEntry.

                  +
                  ..
                  +
                  +
                  +

                  El Relleno del Blog esta Hecho de

                  +

                  Has abierto una nueva clase BlogEntry. ¿De que están hechas las entradas de tu blog? Un titulo, seguro. también, + la fecha en la que fue creada. El texto entero de la entrada.

                  +

                  Vamos a poner el estado de ánimo, también, tal como LiveJournal. La internet ha traído de vuelta las personas de palitos y emoticones + fuera de la bancarrota.¡Que emoción!

                  +

                  Bueno, ya tienes la primera línea de la clase, aquí esta el resto:/p> +

                  • class BlogEntry
                  • +
                  •   attr_accessor :title, :time, :fulltext, :mood
                  • +
                  • end
                  • +
                  +
                  nil
                  +
                  +
                  +

                  Accessors Son las Extremidades Colgantes

                  +

                  Hey, buena clase, colega. Tienes una nueva clase BlogEntry. Para comenzar una entrada:
                  entry = BlogEntry.new.

                  +

                  En la definición de la clase, usaste un método llamado attr_accessor. Existen varios métodos attribute + atributo, como este que agregan pequeñas configuraciones a la clase. Estos atributos son simplemente variables adosadas a la clase.

                  +

                  Piénsalo de este modo. Una clase es como una persona. Esa forma de estrella + del humano. Y los atributos son las extremidades, las diferentes partes que + hacen un cuerpo.

                  +

                  Para crear el titulo de tu entrada: entry.title = "Today Mt. Hood Was Stolen!"

                  +
                  ".+"
                  +
                  +
                  +

                  Un Objeto, Ese Estupendo Paquete Pequeño

                  +

                  Sigue adelante y pon la hora: entry.time = Time.now

                  +

                  Y el estado de animo: entry.mood = :sick

                  +

                  Y el anuncio en si: entry.fulltext = "I can't believe Mt. Hood was stolen! I am speechless! It was stolen by a giraffe who drove away + in his Cadillac Seville very nonchalant!!"

                  +

                  Para ver toda la configuración, simplemente escribe en el prompt: entry.

                  +
                  #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
                  +
                  +
                  +

                  Agilizando

                  +

                  Genial, tu blog es impresionante. Hey, hagamos las cosas algo mas fácil. No querrás + poner la hora asi todas las veces que postees. Solo quieres escribir el titulo, + el contenido y el emoticon rápido, ¿verdad?

                  +

                  Vamos a agregar un método initialize.

                  +
                  • class BlogEntry
                  • +
                  •   def initialize( title, mood, fulltext )
                  • +
                  •     @time = Time.now
                  • +
                  •     @title, @mood, @fulltext = title, mood, fulltext
                  • +
                  •   end
                  • +
                  • end
                  • +
                  +

                  Una vez que lo hallas escrito, prueba hacer una nueva entrada: BlogEntry.new

                  +
                  ArgumentError: wrong number of arguments \(0 for 3\).*
                  +
                  +
                  +

                  Tu le Has Enseñado al Blog a Rechazar lo Malo

                  +

                  ¿Viste como usamos dentro de la clase el símbolo arroba? De este modo: @time = Time.now

                  +

                  Fuera de la clase, usamos accesos (accessors): entry.time = Time.now Pero dentro variables de instancia: @time = Time.now + Son exactamente lo mismo, pero expresado en dos partes diferentes de tu programa.

                  +

                  tu blog ahora necesita un titulo, estado de ánimo y el post para funcionar. Cuando un nuevo BlogEntry es creado, el método initialize + es usado para chequear cualquier argumento para new. ¡Uh, necesitamos tres argumentos!

                  +

                  Prueba de nuevo con los tres.

                  +

                  entry2 += BlogEntry.new( "I Left my Hoodie on the Mountain!", :confused, "I am +never going back to that mountain and I hope a giraffe steals it." )

                  +
                  #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
                  +
                  +
                  +

                  Una Jirafa No Ha Robado el Sumario #7

                  +

                  Aha, estas aquí. Y todo en una pieza. Todavía vamos a hacer tu blog realidad, pero hasta entonces, vamos a revisar, ¿bien?

                  +
                    +
                  • Clases. Todo en Ruby es algún tipo de objeto. Las clases explican los objetos. Como ciertos objetos + trabajan. Por ejemplo, haces algunas entradas de blog y estos objetos están explicados en la clase BlogEntry. + En otras palabras: los llamas objetos del tipo BlogEntry.
                  • +
                  • Accessors son variables adosadas a un objeto que pueden ser usadas fuera del objeto. (entry.time = Time.now)
                  • +
                  • Variables de instancia son las mismas variables para accesos dentro del objeto. + Como en la definición de un método. (@time = Time.now)
                  • +
                  +

                  Bueno, vamos a envolver las cosas, niño. Aquí esta el ultimo capitulo de la FASCINANTE épica + historia de Try Ruby! Ahora que ya has probado como todo funciona, ¿cómo vas a + usar eso alrededor de la casa y en tu tienda de comestibles? Eres una + gran persona (una de mis favoritas), pero necesitas dirección.

                  +

                  Vamos a terminar tu blog. Tienes entradas de blog, pero no un blog.

                  +

                  Pon las entradas en un array: blog = [entry, entry2]

                  +
                  \[#.BlogEntry:0x[0-9a-f]+.*, #.BlogEntry:0x[0-9a-f]+.*\]
                  +
                  +
                  +

                  Todo Se Trata de Combinar Cosas

                  +

                  Cosas hermosas pueden hacerse de partes simples de Ruby, especialmente + cuando las combinas entre ellas para formar algo nuevo. Aquí tenemos un blog + hecho de un array de clases. Y, en realidad, Ruby realmente hace buenas cosas + con este tipo de criaturas.

                  +

                  Aquí hay un puñado de cosas que puedes hacer con tu blog array:

                  +
                  • Querrás ordenar tus entradas de mas reciente a viejas. Puedes hacerlo con:
                    + blog.sort_by { |entry| entry.time }.reverse
                    Ve sort_by para más explicación.
                  • +
                  • Si quieres buscar en el blog por cualquier cosa relacionada con "cadillac":
                    + blog.find_all { |entry| entry.fulltext.match(/cadillac/i) }
                    + Lee mas en find_all + y match + para descubrir como funciona. También: /giraffe/i es un objeto Regexp, usado para concordar palabras.
                  • +
                  • Y agregar nuevas entradas con blog << new_entry
                    + Y aquí la documentación del método <<.
                  • +
                  +

                  Puedes buscar entre la lista de los métodos con los que viene Ruby en ruby-doc.org's core. + Otra buena lista hay en online pickaxe.

                  +

                  Un método realmente útil (probablemente yo uso esto mas que otra cosa) es map. Escribe: blog.map { |entry| entry.mood }

                  +
                  \[(:\w+, )+:\w+\]
                  +
                  +
                  +

                  Mira Su Cara — La Transformación Ha Comenzado

                  +

                  El método map recorre un array y reemplaza cada ítem con algo nuevo. ¿Dices que quieres reemplazar cada entrada de tu blog + con el nombre de Bruce Willis?. Hazlo entonces: blog.map { "Bruce Willis" }

                  +

                  Como el bloque siempre devuelve el string "Bruce Willis", eso es lo que obtienes. En el código que acabas de usar, la entrada entry wfue reemplazada + por solo el entry.mood.

                  +

                  Ahora, quiero que hagas un popup con las entradas de tu blog. Yo no te voy a + dar todo el código. Solo te voy a dar una parte.

                  +
                  • blog.each do |entry|
                  • +
                  •   h2 entry.title
                  • +
                  •   p entry.fulltext
                  • +
                  • end
                  • +
                  +

                  Ahora, yo espero que pongas el código del popup alrededor y agregues un titulo con el nombre de tu blog usando h1. Como extra, tienes la hora de cada entrada para mostrar.

                  +
                  \033\[1;JSm.*popup_make\(.*h1.*h2.*li.*h2.*li.*\)\033\[m.*
                  +
                  +
                  +

                  Eres Una Especie de Gurú Web, Tengo Estrellas en Mis Ojos

                  +

                  Bien, ¡eso es! Este es exactamente el código que puedes usar para escribir tu + propio blog real en Ruby. Si te sientes aventurero, yo chequearía el video de + Rails videos donde muestran a un joven compañero creando un blog en 15 minutos. Solo sientete cómodo y mira.

                  +

                  Debo mencionar a Rails. Tú has estado aprendiendo el lenguaje Ruby, como + hablarlo. Pero Rails es grupo de librerías (algo asi como la librería de popup + que hemos estado usando.) Es un poderoso conjunto de herramientas para crear + sitios web. Si estas interesado en aprender sobre Rails, yo miraría head + por aquí directamente. ¡Empieza a usar tus habilidades en Ruby apropiadamente!

                  +

                  Algo que tiene Rails son métodos para manejar fechas fácilmente. Como, prueba: Time.now - 2.weeks

                  +
                  class Integer; def weeks; self * 7*24*60*60; end; end
                  +
                  \w+ \w+ \d+ \d{2}:\d{2}:\d{2} .*
                  +
                  +
                  +

                  Si Quieres Empezar Poco a Poco

                  +

                  Si quieres comenzar escribiendo pequeños programas en Ruby para practicar, tengo un proyecto llamado MouseHole + que es una pequeña caja de herramientas en la web para escribir programas cortos en Ruby. Puedes ver aquí algunos + scripts para ver que quiero decir.

                  +

                  MouseHole no es para escribir sitios web en realidad. Es para escribir + pequeños programas y correrlos dentro del navegador. Como hay un programa block + de notas para MouseHole y un programa que agrega una imagen de un ratón a los + links de la web que linkean a programas de MouseHole.

                  +

                  Tengo un script de MouseHole dentro de un archivo aquí mismo:
                  + print File.read("/MouseHole/flickrpedia.user.rb")

                  +
                  .*Inserts Wikipedia links for Flickr tags.*
                  +
                  +
                  +

                  Sumario #8, El Sumario Hey-Relájate-Lo-Hiciste-Bien

                  +

                  Esta ultima sección se tomó un momento para relajarse, para darte algunos consejos de como + puedes usar Ruby. Si lo has disfrutado, descarga Ruby e instálalo.

                  + +

                  Una vez que tengas Ruby instalado, puedes usar Ruby Interactivo ejecutando el comando irb en el prompt de tu sistema. Para mas sobre Irb, esta + The Tiger's Vest para ayudarte.

                  +

                  Tú realmente mereces una torta doble-capa con doble-doble azúcar glaseado y + un tipo tocando una de esas guitarras que son doble-guitarra. Quiero decir + terminaste, ¡lo hiciste! No hay dudas de eso, ¡eres un gran ser certificado!

                  +
                  +
                  + \ No newline at end of file diff --git a/app/views/tutorials/intro.rhtml b/app/views/tutorials/intro.rhtml new file mode 100644 index 0000000..7443c46 --- /dev/null +++ b/app/views/tutorials/intro.rhtml @@ -0,0 +1,680 @@ + +
                  +

                  Using the Prompt

                  +

                  The blue window above is a Ruby prompt. Type a line of Ruby code, hit Enter + and watch it run!

                  +

                  For example, try typing some math. Like: 2 + 6

                  +
                  \d+
                  +
                  +
                  +

                  Numbers & Math

                  +

                  Good! You did a bit of math. See how the answer popped out?

                  +

                  Ruby recognizes numbers and mathematic symbols. You could try some other math like:

                  +
                  • 4 * 10
                  • +
                  • 5 - 12
                  • +
                  • 40 / 4
                  +

                  Sure, computers are handy and fast for math. Let's move on. Want to see your name reversed? + Type your first name in quotes like this: "Jimmy"

                  +
                  "(\w+)"
                  +
                  +
                  +

                  Say Your Name Backwards

                  +

                  Perfect, you've formed a string from the letters of your name. A string + is a set of characters the computer can process.

                  +

                  Imagine the letters are on a string of + laundry line and the quotes are clothespins holding the ends. The quotes mark the beginning and end.

                  +

                  To reverse your name, type: "Jimmy".reverse (Don't forget the dot!)

                  +
                  "(\w+)"
                  +
                  +
                  +

                  Counting the Letters

                  +

                  You have used the reverse method on your name! By enclosing your name in + quotes, you made a string. Then you called the reverse method, which works on strings to flip + all the letters backwards.

                  +

                  Now, let's see how many letters are in your name: "Jimmy".length

                  +
                  \d+
                  +
                  +
                  +

                  On Repeat

                  +

                  Now, I'm sure by now you're wondering what any of this is good for. Well, I'm sure you've been to + a website that screamed, Hey, your password is too short! See, some programs + use this simple code.

                  +

                  Watch this. Let's multiply your name by 5. "Jimmy" * 5

                  +
                  "(\w+)"
                  +
                  +
                  +

                  Hey, Summary #1 Already

                  +

                  Let's look at what you've learned in the first minute.

                  +
                    +
                  • The prompt. Typing code into the green prompt gives you + an answer from a red prompt. All code gives an answer.
                  • +
                  • Numbers and strings are Ruby's math and text objects.
                  • +
                  • Methods. You've used English-language methods like reverse + and symbolic methods like * (the multiplication method.) Methods are action!
                  • +
                  +

                  This is the essence of your learning. Taking simple things, toying with + them and turning them into new things. Feeling comfortable yet? I promise you are.

                  +

                  Okay, let's do something uncomfortable. Try reversing a number: 40.reverse

                  +
                  NoMethodError: undefined method `reverse' for (\d+):Fixnum
                  +
                  +
                  +

                  Stop, You're Barking Mad!

                  +

                  You can't reverse the number forty. I guess you can hold your monitor up to the + mirror, but reversing a number just doesn't make sense. Ruby has tossed an error + message. Ruby is telling you there is no method reverse for numbers.

                  +

                  Maybe if you turn it into a string: 40.to_s.reverse.

                  +
                  \"(\d+)\"
                  +
                  +
                  +

                  Boys are Different From Girls

                  +

                  And numbers are different from strings. While you can use methods on any object + in Ruby, some methods only work on certain types of things. But you can always + convert between different types using Ruby's "to" methods.

                  +
                  • to_s converts things to strings.
                  • +
                  • to_i converts things to integers (numbers.)
                  • +
                  • to_a converts things to arrays.
                  • +
                  +

                  What are arrays?! They are lists. Type in a pair of brackets: [].

                  +
                  \[\]
                  +
                  +
                  +

                  Standing in Line

                  +

                  Great, that's an empty list. Lists store things in order. + Like standing in line for popcorn. You are behind someone and you wouldn't + dream of pushing them aside, right? And the guy behind you, you've got a + close eye on him, right?

                  +

                  Here's a list for you. Lottery numbers: [12, 47, 35].

                  +
                  \[(\d+(, )?){2,}\]
                  +
                  +
                  +

                  One Raises Its Hand

                  +

                  A list of lottery numbers. Which one is the highest?

                  +

                  Try: [12, 47, 35].max.

                  +
                  (\d+)
                  +
                  +
                  +

                  Tucking a List Away

                  +

                  Good, good. But it's annoying to have to retype that list, isn't it?

                  +

                  Let's save our numbers inside a ticket like so: ticket = [12, 47, 35]

                  +
                  \[(\d+(, )?){2,}\]
                  +
                  +
                  +

                  Now Type Ticket

                  +

                  Now, type: ticket

                  +
                  \[(\d+(, )?){2,}\]
                  +
                  +
                  +

                  Saved, Tucked Away

                  +

                  Fantastic! You've hung on to your lotto numbers, tucking them away inside a + variable called ticket.

                  +

                  Let's put your lotto numbers in order, how about? Use: ticket.sort!

                  +
                  \[(\d+(, )?){2,}\]
                  +
                  +
                  +

                  Summary #2 is Upon Us

                  +

                  You had a list. You sorted the list. The ticket variable is now changed.

                  +

                  Did you notice that the sort! method has a big, bright exclamation at the end? + A lot of times Ruby methods shout like that if they alter the variable for good. It's nothin + special, just a mark.

                  +

                  Now, look how your second minute went:

                  +
                    +
                  • Errors. If you try to reverse a number or do anything fishy, + Ruby will skip the prompt and tell you so.
                  • +
                  • Arrays are lists for storing things in order.
                  • +
                  • Variables save a thing and give it a name. You used the + equals sign to do this.
                    Like: ticket = [14, 37, 18].
                  • +
                  +

                  In all there are eight lessons. You are two-eighths of the way there! + This is simple stuff, don't you think? Good stuff up ahead.

                  +

                  Let's change directions for a moment. I've stuffed a bit of poetry for you in + a certain variable. Take a look. Type print poem

                  +
                  poem = "My toast has flown from my hand\nAnd my toast has gone to the +moon.\nBut when I saw it on television,\nPlanting our flag on Halley's +comet,\nMore still did I want to eat it.\n"
                  +
                  My toast (.+)
                  +
                  +
                  +

                  Sadly, You Hate Toast Poetry

                  +

                  Look, it's okay. You don't have to like it. Hack it up, be my guest.

                  +

                  Instead of toast, go for a melon or something. Try this: poem['toast'] = 'honeydew'

                  +

                  And then type print poem by itself to see the new poem.

                  +
                  My honey(.+)
                  +
                  +
                  +

                  Ready, Aim

                  +

                  The square brackets you just used are very common in Ruby. Remember, you typed: poem['toast'] = 'honeydew'. That box with the word toast has a square bracket on each side, see?

                  +

                  The +two brackets are like sights used to line up a target. Exactly. These +brackets mean, "I am looking for ____." Ready, aim. Here you're looking +for toast and swapping it out with fruit.

                  +

                  Here's a question: what happens when we reverse this whole poem? poem.reverse +

                  "\\n.ti tae ot (.+)"
                  +
                  +
                  +

                  Too Much Reversal

                  +

                  Okay, sure. So the whole poem's been turned backwards, letter-by-letter. I really want to just + reverse the lines, though. Move the last line up to first and the first line down to last. Backwards, but not + that backwards.

                  +

                  Here's how: poem.lines.to_a.reverse

                  +
                  \["More still did I(.+)"\]
                  +
                  +
                  +

                  Ringlets of Chained Methods

                  +

                  So what do you see? What happened there? You typed poem.lines.to_a.reverse and what happened?

                  +

                  Two things happened. You turned the poem into a +list using lines.to_a. lines decides the way +the string is split up, then to_a converted it into an +Array. (To array.) Different methods, such +as bytes and chars can be used in place +of lines. By using lines, ruby will return each line of the poem.

                  +

                  Then, you reversed that list. You had each line. You reversed them. That's it.

                  +

                  Let's tack one more method on the end there: print poem.lines.to_a.reverse.join +

                  More still did I(.+)
                  +
                  +
                  +

                  Of All the Summaries, #3 is Here Now

                  +

                  Good show, my friend! The join method took that list of reversed lines and put them + together into a string. (Sure, you could have also just used to_s.)

                  +

                  Review time.

                  +
                    +
                  • Exclamations. Methods may have exclamations (and also question marks) + in their name. No big deal. Try: poem.include? "my hand"
                  • +
                  • Square brackets. Target and find things. Search and replace.
                  • +
                  • Chaining methods lets you get a lot more done. Break up a poem, + reverse it, reassemble it: poem.lines.to_a.reverse.join
                  • +
                  +

                  At this point, you may want to tinker with the poem a bit more. A complete list of all + the String methods is + + here. + Go ahead and try a few (such as poem.downcase or poem.delete.)

                  +

                  When you're ready to move on, type: books = {}

                  +
                  \{\}
                  +
                  +
                  +

                  A Wee Blank Book

                  +

                  You've made an empty hash. (Also known as: an empty dictionary.)

                  +

                  We're going to stuff some miniature book reviews in this hash. Here's our rating system:

                  +
                    +
                  • :splendid → a masterpiece.
                  • +
                  • :quite_good → enjoyed, sure, yes.
                  • +
                  • :mediocre → equal parts great and terrible.
                  • +
                  • :quite_not_good → notably bad.
                  • +
                  • :abyssmal → steaming wreck.
                  • +
                  +

                  To rate a book, put the title in square brackets and put the rating after the equals.

                  +

                  For example: books["Gravity's Rainbow"] = :splendid

                  +
                  :\w+
                  +
                  +
                  +

                  More Bite-Size Reviews

                  +

                  Keep going, fill it up with reviews. And, if you want to see the whole list, + just type: books

                  +

                  Again, the ratings are: :splendid, :quite_good, :mediocre, + :quite_not_good, and :abyssmal.

                  +

                  These ratings are not strings. When you place a colon in front of a simple word, you get a + symbol. Symbols are cheaper than strings (in terms of computer memory.) If + you use a word over and over in your program, use a symbol. Rather than having thousands of + copies of that word in memory, the computer will store the symbol only once.

                  +

                  Once you've got three or four books in + there, type: books.length.

                  +
                  [3-9]
                  +
                  +
                  +

                  Wait, Did I Like Gravity's Rainbow?

                  +

                  See, the length method works on strings, list and hashes. One great thing about + Ruby is that names are often reused, which means fewer names you need to remember.

                  +

                  If you'd like to look up one of your old reviews, again put the title in the square. But leave off + the equals.

                  +

                  Just like this: books["Gravity's Rainbow"]

                  +
                  :\w+
                  +
                  +
                  +

                  Hashes as Pairs

                  +

                  Keep in mind that hashes won't keep things in order. That's not their job. It'll just pair up two + things: a key and a value. In your reviews, the key is the book's + title and the value is the rating.

                  +

                  If you want to just see the titles of the books you've reviewed: books.keys

                  +
                  \[".*"\]
                  +
                  +
                  +

                  Are You Harsh?

                  +

                  So are you giving out harsh, unfair reviews? Let's keep score with this hash:
                  ratings = Hash.new {0}

                  +

                  Then, okay, now let's count up your reviews. Just stay with me. Type:
                  + books.values.each { |rate| ratings[rate] += 1 }

                  +

                  (The straight line in the code is the pipe character, probably located right above the + Enter key on your keyboard.)

                  +
                  \[:.+\]
                  +
                  +
                  +

                  A Tally

                  +

                  Great, wow! You've made a scorecard of your ratings. Type ratings to see the count. + This new hash shows a rating and then the number of times you've given that rating.

                  +

                  One of the amazing new things we've just used is a block. We're going to + explore these more in the next summary. But, basically, a block is a bit of Ruby code surrounded + by curly braces.

                  +

                  Let's try another block: 5.times { print "Odelay!" }

                  +
                  Odelay!Od.*
                  +
                  +
                  +

                  Now Arriving at Summary #4

                  +

                  Blocks are always attached to methods. Like the times method, which takes the + block and runs the code over and over. (In this case: five times.)

                  +

                  This last lesson was a bit longer. You've probably used up three minutes learning about:

                  +
                    +
                  • Hashes. The little dictionary with the curly pages: {}.
                  • +
                  • Symbols. Tiny, efficient code words with a colon: :splendid.
                  • +
                  • Blocks. Chunks of code which can be tacked on to many of Ruby's methods. Here's the + code you used to build a scorecard:
                    books.values.each { |rate| ratings[rate] += 1 }.
                  • +
                  +

                  On your computer, you probably have a lot of different files. Files with pictures in them, + files with programs in them. And files are often organized into folders, also called: + directories.

                  +

                  I've prepared a few directories for you. Take a look: + Dir.entries "/"

                  +
                  \["\.", .+\]
                  +
                  +
                  +

                  The Private Collection of Dr. Dir

                  +

                  You've just listed out everything in the top directory. The root directory, indicated + by a single slash. Containing some programs and other tutorials and such.

                  +

                  So, what is the Dir.entries method? Well, it's just a method, right? + entries is a method called on the Dir variable. + And Dir has a collection of methods for checking out file directories.

                  +

                  One other little thing we haven't really talked about openly. Method arguments, highlighted in green.

                  +
                    +
                  • Dir.entries "/": Anything listed after a method + is considered an attachment.
                  • +
                  • print poem: See, print is an ordinary method. And the + poem is attached. To be printed.
                  • +
                  • print "pre", "event", "ual", "ism" has several arguments, with commas + between them.
                  • +
                  +

                  To list just the text files in that directory: Dir["/*.txt"]

                  +
                  \["\/comics\.txt"\]
                  +
                  +
                  +

                  Come, Read Comics With Me

                  +

                  The Dir[] method is like entries but you search for files + with wildcard characters. Here, we see those square brackets again! Notice how + they still mean, "I am looking for _____?"

                  +

                  More specifically: "I am looking for files which end with .txt."

                  +

                  Let's crack open this comics file, then. Here's the way:
                  + print File.read("/comics.txt")

                  +
                  Achewood.+
                  +
                  +
                  +

                  Mi Comicas, Tu Comicas

                  +

                  All right! We can start to use files to store things. This is great because normally when + we exit Ruby, all our variables will be gone. Ruby, by itself, forgets these things. + But if we save things in files, we can read those files in future Ruby escapades.

                  +

                  Hey, and guess what? The /Home directory is yours! I gave it to you! I am generous! Let's make a copy of the comics file.

                  +

                  You'll want to: FileUtils.copy('/comics.txt', '/Home/comics.txt') +

                  If you've already created the file, use File.delete('/Home/comics.txt') to trash it.

                  +
                  nil
                  +
                  +
                  +

                  Your Own Turf

                  +

                  Okay, you've got a copy. Check it: Dir["/Home/*.txt"]

                  +

                  To add your own comic to the list, let's open the file in append mode.

                  +

                  Start like this: File.open("/Home/comics.txt", "a") do |f|.

                  +
                  ..
                  +
                  +
                  +

                  And Now For the Startling Conclusion

                  +

                  So your prompt has changed. See that? Your prompt is a double dot now.

                  +

                  In this tutorial, this prompt means that Ruby is expecting you to type more. + As you type in the lines of Ruby code, the double dots will continue until you + are completely finished.

                  +

                  Hot tip: If you want to stop working on the code and break out of the double dots, use the reset + command. If you want to go the previous page of the tutorial, use the back command.

                  +

                  Here's your code. You've already typed the first line, so just enter the second line. (The \n + is an Enter character.

                  +
                  • File.open("/Home/comics.txt", "a") do |f|
                  • +
                  •   f << "Cat and Girl: http://catandgirl.com/\n"
                  • +
                  • end
                  • +
                  +

                  And, since you're getting so advanced and capable here, one other tip: you can use the up and down arrow keys to + edit your old commands or run them again.

                  +
                  ..
                  +
                  +
                  +

                  Ruby Sits Still

                  +

                  That last line adds the Cat and Girl comic to the list, but Ruby's going to wait until you're totally finished to + take action.

                  +

                  Now, to finish the code you've started. You opened a new block when you typed do. + So far the blocks we've seen have used curly braces. This time we'll be using do and end instead + of curly braces. A lot of Rubyists will use do...end when the block goes on for many lines.

                  +

                  Let's get that block finished now, with: end

                  +
                  • File.open("/Home/comics.txt", "a") do |f|
                  • +
                  •   f << "Cat and Girl: http://catandgirl.com/\n"
                  • +
                  • end
                  • +
                  +
                  #.File:/Home/comics\.txt.
                  +
                  +
                  +

                  The Clock Nailed To the File

                  +

                  Good, good! You've added that new comic to the file. You can see for yourself: print File.read("/Home/comics.txt")

                  +

                  What time was it when you changed the file? Let's check. Type: File.mtime("/Home/comics.txt")

                  +
                  \d{4}-\d+-\d+ \d{2}:\d{2}:\d{2} [+-]\d{4}
                  +
                  +
                  +

                  Just the Hour Hand

                  +

                  Great, there's the time. The precise time exactly when you added to the file. The mtime gives you a Ruby Time object.

                  +

                  If you want to check just what hour it was, hit the up arrow key and change the line to: File.mtime("/Home/comics.txt").hour

                  +
                  \d+
                  +
                  +
                  +

                  Hallo, Who's There? And Summary #5 Waves Its Hat!

                  +

                  Well done, well done, well done, well done! Truly, truly, truly, truly, truuuuuuuuly!

                  +

                  Here's the last few minutes of your life in review:

                  +
                    +
                  • Files. What more can be said? Lots of methods for editing files and lookin around in directories.
                  • +
                  • Arguments. Arguments are a list of things sent into a method. With commas between.
                  • +
                  • We also spoke about do and end which are another way to make a block.
                  • +
                  +

                  You totally know how to use Ruby now. I mean you've got down the essentials. You just need to keep learning more methods and + try out more complex blocks.

                  +

                  But there's one side of Ruby we haven't settled. Making your own methods and classes.

                  +

                  Ahem! Let's get it over with then.

                  +

                  Start with: def load_comics( path )

                  +
                  ..
                  +
                  +
                  +

                  In Ruby, Def Leppard Means Define Leppard (a Method)!

                  +

                  Hey, okay, you done it. You're making your own method. You started with def, followed by the name of the method. + And a list of arguments which the method will need. This isn't too scary and dangerous!

                  +

                  All we have to do is fill it up with Ruby and finish it up with end.

                  +

                  Here's the code:

                  +
                  • def load_comics( path )
                  • +
                  •   comics = {}
                  • +
                  •   File.foreach(path) do |line|
                  • +
                  •     name, url = line.split(': ')
                  • +
                  •     comics[name] = url.strip
                  • +
                  •   end
                  • +
                  •   comics
                  • +
                  • end
                  • +
                  +

                  No need to indent, if you don't want. I just do that to make it read easier.

                  +
                  nil
                  +
                  +
                  +

                  The Ripened Fruit of Your Own Creation

                  +

                  A new method is born. Let us use it: comics = load_comics('/comics.txt')

                  +

                  If you have a problem, you might have mistyped. Use the back command and try again.

                  +
                  \{.*"Achewood"=."http://achewood.com/".*\}
                  +
                  +
                  +

                  Hey, Cool, a Comics Thing

                  +

                  In your Ruby window above, look at the code you've typed for the load_comics method. What is happening? You're + passing in the path variable and you're getting back the comics variable. Ruby lets the comics + hash trickle out the end of the method.

                  +

                  A number of methods were used to get the job done. See if you can spot them.

                  +
                  • File.foreach is a method which opens a file and hands each line to the block. The line + variable inside the do...end block took turns with each line in the file.
                  • +
                  • split is a method for strings, which breaks the string up into an array. An axe is laid on the colon + and the line is chopped in half, giving us the url and name for each comic.
                  • +
                  • strip removes extra spaces around the name. Just in case.
                  • +
                  +

                  Right on. Bravo. You've got the comics in a Ruby hash. But what now? What good is this really?

                  +

                  Let's make a page of links. How about that? We'll need to load a little library I've made for you.

                  +

                  Type: require 'popup'

                  +
                  true
                  +
                  +
                  +

                  Browser Puppetry

                  +

                  Excellent, you've loaded the popup library. It's saved in a file in the Libraries folder. See: Dir["/Libraries/*"]

                  +

                  The popup library contains a bunch of methods I've written which let you control a popup here on the Try Ruby site.

                  +

                  Here, try this: Popup.goto "http://google.com/"

                  +
                  \033\[1;JSm.*popup_goto\(.*\)\033\[m.*
                  +
                  +
                  +

                  Making Links and Spinning Webs

                  +

                  Our own lovely, little popup to manipulate. You can also fill it with your own goodies. We'll start small:

                  +
                  • Popup.make {
                  • +
                  •   h1 "My Links"
                  • +
                  •   link "Go to Google", "http://google.com/"
                  • +
                  • }
                  • +
                  +

                  The term h1 (h-one) means a level-one header. In HTML, this is the largest size of header.

                  +
                  \033\[1;JSm.*popup_make\(.*h1.*a href.*\)\033\[m.*
                  +
                  +
                  +

                  Popups Are So Easy, It's Crazy

                  +

                  Looks good, you did it perfectly, just as you were asked. Let's make a list then.

                  +

                  Here's how you make a list with the popup library:

                  +
                  • Popup.make do
                  • +
                  •   h1 "Things To Do"
                  • +
                  •   list do
                  • +
                  •     p "Try out Ruby"
                  • +
                  •     p "Ride a tiger"
                  • +
                  •     p "(down River Euphrates)"
                  • +
                  •   end
                  • +
                  • end
                  • +
                  +

                  The p method is short for "paragraph".

                  +
                  \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*li.*\)\033\[m.*
                  +
                  +
                  +

                  Spread the Comics on the Table

                  +

                  Okay, this is coming along wonderfully. This is simple stuff, but keep in mind that you didn't know any Ruby whatsoever just fifteen minutes ago!

                  +

                  Last +step. Let's tie it all together, you know? Let's make it chime together +like a very nice set of glistening chimes on the beach in the +maginificent sunlight!

                  +

                  Make sure the comics are loaded: comics = load_comics( '/comics.txt' )

                  +

                  Now, let's make a list of the links to each comic:

                  +
                  • Popup.make do
                  • +
                  •   h1 "Comics on the Web"
                  • +
                  •   list do
                  • +
                  •     comics.each do |name, url|
                  • +
                  •       link name, url
                  • +
                  •     end
                  • +
                  •   end
                  • +
                  • end
                  • +
                  +

                  You can click on the links and read the comics in the little window even! Smashing!

                  +
                  \033\[1;JSm.*popup_make\(.*h1.*ul.*li.*a href.*li.*a href.*\)\033\[m.*
                  +
                  +
                  +

                  Summary #6 Which Means You've Come So Far

                  +

                  You're a level six Ruby cleric. I mean what a great job you've done. Let's review:

                  +
                    +
                  • You added your own method with def and you used that load_comics method several times.
                  • +
                  • Libraries. You used the require method to load the popup library.
                    By typing: require 'popup'
                  • +
                  • And if that wasn't enough, you made your own web page from a list of comics in a file. You made a real program!
                  • +
                  +

                  So +what could possibly be next? What could you possibly have to learn now? +Ha, this is the best part. You've come such a long way that we're going +to uncover classes. For two more short lessons and you're done.

                  +

                  Earlier, we created a hash like this: Hash.new Try it.

                  +
                  \{\}
                  +
                  +
                  +

                  Not a School Class, a Working Class

                  +

                  You see, the empty curly braces {} is a shortcut for Hash.new. The new +method is used to make objects of a certain class. (Think "class" as in +"working class" — a specific group of objects which are similar, have +the same jobs, the same shirts.)

                  +

                  Ask yourself this: How would I make a blog in Ruby? +Where would you start? Well, you might store your blog entries in a +file, right? But how would you keep track of the title of the entry and +the time it was posted? And when you loaded the file, how would it look +in Ruby? Would it be a Hash? Or an Array? Or an Array of Arrays? Or +something else?

                  I really think you'll want to use a class. You are already familiar with many classes: Hash, Array, String.

                  +

                  Let's make a new class: class BlogEntry.

                  +
                  ..
                  +
                  +
                  +

                  The Stuff Blogs are Made of

                  +

                  You've opened up a new BlogEntry class. What is your blog entry made of? A title, sure. Also, a time when the entry was posted. The + full text of the entry.

                  +

                  We'll do a mood setting, too, just like LiveJournal. The Internet has really brought back stick people and smileys + out of bankruptcy. Emote!

                  +

                  Okay, so you've got the first line of the class, here's the rest:

                  +
                  • class BlogEntry
                  • +
                  •   attr_accessor :title, :time, :fulltext, :mood
                  • +
                  • end
                  • +
                  +
                  nil
                  +
                  +
                  +

                  Accessors Are the Dangling Limbs

                  +

                  Hey, good class, man. You've got a new BlogEntry class. To start an entry:
                  entry = BlogEntry.new.

                  +

                  In the class definition, you used a method called attr_accessor. There are many attribute methods like + this which add little settings to classes. These attributes are just variables attached to a class.

                  +

                  Think +of it this way. A class is like a person. That star-shaped human thing +out there. And the attributes are the dangling limbs, the different +parts that make up a body.

                  +

                  To set the title of your entry: entry.title = "Today Mt. Hood Was Stolen!"

                  +
                  ".+"
                  +
                  +
                  +

                  An Object, That Neat Little Package

                  +

                  Go ahead and set the post time: entry.time = Time.now

                  +

                  And the mood: entry.mood = :sick

                  +

                  And the post itself: entry.fulltext = "I can't believe Mt. Hood was stolen! I am speechless! It was stolen by a giraffe who drove away + in his Cadillac Seville very nonchalant!!"

                  +

                  To see all your settings, just type at the prompt: entry.

                  +
                  #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
                  +
                  +
                  +

                  Quickening it Up

                  +

                  Cool, +your blog is awesome. Hey, let's make things a bit easier on you. +You're not going to want to set the time like that every time you post. +You just want to type in the title and the entry and the mood quickly, +right?

                  +

                  Let's add an initialize method.

                  +
                  • class BlogEntry
                  • +
                  •   def initialize( title, mood, fulltext )
                  • +
                  •     @time = Time.now
                  • +
                  •     @title, @mood, @fulltext = title, mood, fulltext
                  • +
                  •   end
                  • +
                  • end
                  • +
                  +

                  Once you've got that typed in, try making a new entry: BlogEntry.new

                  +
                  ArgumentError: wrong number of arguments \(0 for 3\).*
                  +
                  +
                  +

                  You've Taught Your Blog to Reject Worthless Things

                  +

                  Did you see how inside the class we used the at-symbols? Like this: @time = Time.now

                  +

                  Outside the class, we use accessors: entry.time = Time.now But inside we use instance variables: @time = Time.now + They're the exact same thing, but expressed in two different places of your program.

                  +

                  Your blog now needs a title, a mood and a post in order to work. When a new BlogEntry is created, the initialize method + is used to check for any arguments to new. Uh, we need three arguments!

                  +

                  Try it again with all three.

                  +

                  entry2 += BlogEntry.new( "I Left my Hoodie on the Mountain!", :confused, "I am +never going back to that mountain and I hope a giraffe steals it." )

                  +
                  #.BlogEntry:0x[0-9a-f]+ ((@title|@mood|@time|@fulltext)=.*?, ){3}.*
                  +
                  +
                  +

                  A Giraffe Has Not Stolen Summary #7

                  +

                  Aha, you're here. And all in one piece. We're still going to make your blog real, but until then, let's review, okay?

                  +
                    +
                  • Classes. Everything in Ruby is some kind of object. Classes explain objects. How a certain object works. + For example, you made a few blog entry objects and these objects are explained in the BlogEntry class. + In other words: you call them BlogEntry objects.
                  • +
                  • Accessors are variables attached to an object which can be used outside the object. (entry.time = Time.now)
                  • +
                  • Instance variables are the same variables you're using for accessors when inside the object. + Like in a method definition. (@time = Time.now)
                  • +
                  +

                  Okay, +let's wrap things up, kid. Here's the last chapter of the GRIPPING epic +story of Try Ruby! Now that you've got a taste of how it all works, how +are you going to use it around the house and in your grocer's freezer? +You're a great person (one of my favorites), but you need guidance.

                  +

                  Let's finish your blog. You have blog entries, but no actual blog.

                  +

                  Put the entries into an array: blog = [entry, entry2]

                  +
                  \[#.BlogEntry:0x[0-9a-f]+.*, #.BlogEntry:0x[0-9a-f]+.*\]
                  +
                  +
                  +

                  It's All About Combining Things

                  +

                  Some +beautiful things can be done with the simple parts of Ruby, especially +when you combine them together into new things. Here we've got a blog +made of an array of classes. And, actually, Ruby really does good with +this kind of creature.

                  +

                  Here's a few things you can do with your array blog:

                  +
                  • You'll want to sort your entries from newest to oldest. You can do this with:
                    + blog.sort_by { |entry| entry.time }.reverse
                    See the sort_by explanation for more.
                  • +
                  • If you want to search your blog for anything related to "cadillac":
                    + blog.find_all { |entry| entry.fulltext.match(/cadillac/i) }
                    + Read all about find_all + and match + to figure out how that works. Also: the slashy /giraffe/i is a Regexp object, used for matching words.
                  • +
                  • Add new entries with blog << new_entry
                    + And check out the << method documentation.
                  • +
                  +

                  You can browse a list of all Ruby's built-in methods at ruby-doc.org's core list. + Another good list is at the online pickaxe.

                  +

                  One really useful method (I probably use this more than anything else) is map. Type: blog.map { |entry| entry.mood }

                  +
                  \[(:\w+, )+:\w+\]
                  +
                  +
                  +

                  Look at His Face — The Transformation Has Begun

                  +

                  The map method cycles through an array and replaces each item with something new. Say you wanted to replace each of your blog entries + with the name Bruce Willis. Do it so: blog.map { "Bruce Willis" }

                  +

                  Since the block always returns the string "Bruce Willis", that's what you get. In the code you just used, the entry was swapped out + for only the entry.mood.

                  +

                  Now, +I want you to make a popup with your blog entries. I'm not going to +give you all of the code. I'm just going to give you part of it.

                  +
                  • blog.each do |entry|
                  • +
                  •   h2 entry.title
                  • +
                  •   p entry.fulltext
                  • +
                  • end
                  • +
                  +

                  Now, I expect you to put the popup code around it and add an h1 title with the name of your blog. For extra haroompf, have the time of each entry display.

                  +
                  \033\[1;JSm.*popup_make\(.*h1.*h2.*li.*h2.*li.*\)\033\[m.*
                  +
                  +
                  +

                  You are Some Kind of Web Guru, I Have Stars in My Eyes

                  +

                  Good, +that's it! This is exactly the code you can use to write your own real +Ruby blog. If you're feeling adventurous, I'd check out the Rails videos which show a swift young fellow creating a blog in 15 minutes. You just sit back and watch.

                  +

                  I +should mention Rails. You have been learning the Ruby language, how to +speak it. But Rails is a bunch of libraries (sort of like the popup +library we've been using.) It's a very powerful toolkit for building +websites. If you're interested in learning about Rails, I would head + over there right away. Start using your Ruby skills proper!

                  +

                  One thing Rails has is easy methods for dates. Like, try: Time.now - 2.weeks

                  +
                  class Integer; def weeks; self * 7*24*60*60; end; end
                  +
                  \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-+]\d{4}
                  +
                  +
                  +

                  If You Want to Start Small

                  +

                  If you'd like to start writing little Ruby programs just to practice, I have a project called MouseHole + which is a little web toolkit for writing short Ruby programs. You can look over a few + scripts to see what I mean.

                  +

                  MouseHole +isn't for writing web sites really. It's just for writing little +programs you run inside your browser. Like there's a notepad program +for MouseHole and a program which adds a mouse picture next to links on +the web which link to MouseHole programs.

                  +

                  I've got a MouseHole script inside a file here:
                  + print File.read("/MouseHole/flickrpedia.user.rb")

                  +
                  .*Inserts Wikipedia links for Flickr tags.*
                  +
                  +
                  +

                  Summary #8, The Hey-Relax-You-Did-Good Summary

                  +

                  This last section took a moment to wind down, to give you some pointers as to how you can use Ruby. If you enjoyed yourself, + download Ruby and install it.

                  + +

                  Once you have Ruby installed, you can use Interactive Ruby by running irb on your system's prompt. For more on Irb, + there's The Tiger's Vest to help you.

                  +

                  You +really deserve a double-layer cake with double-double frosting and a +guy playing one of those guitars that's a double guitar. I mean you +finished, you really did! No doubt about it, you're a certified +red-blooded smartiac!

                  +
                  +
                  + + diff --git a/config/database.yml b/config/database.yml index 90d87cc..d36560a 100644 --- a/config/database.yml +++ b/config/database.yml @@ -1,22 +1,32 @@ -# SQLite version 3.x -# gem install sqlite3 + development: - adapter: sqlite3 - database: db/development.sqlite3 - pool: 5 - timeout: 5000 + adapter: mysql2 + database: tryruby_development + username: root + password: + pool: 5 + timeout: 5000 + host: 127.0.0.1 # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: - adapter: sqlite3 - database: db/test.sqlite3 - pool: 5 - timeout: 5000 + adapter: mysql2 + database: tryruby_test + username: root + password: + pool: 5 + timeout: 5000 + host: 127.0.0.1 production: - adapter: sqlite3 - database: db/production.sqlite3 - pool: 5 - timeout: 5000 + adapter: mysql2 + database: tryruby_production + username: root + password: + pool: 5 + timeout: 5000 + host: localhost +cucumber: + <<: *test diff --git a/config/routes.rb b/config/routes.rb index c11e155..b0cd5a4 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,62 +1,68 @@ Tryruby::Application.routes.draw do - get "tutorials/intro" - - root :to => "index#index" - - # The priority is based upon order of creation: - # first created -> highest priority. - - # Sample of regular route: - # match 'products/:id' => 'catalog#view' - # Keep in mind you can assign values other than :controller and :action - - # Sample of named route: - # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase - # This route can be invoked with purchase_url(:id => product.id) - - # Sample resource route (maps HTTP verbs to controller actions automatically): - # resources :products - - # Sample resource route with options: - # resources :products do - # member do - # get 'short' - # post 'toggle' - # end - # - # collection do - # get 'sold' - # end - # end - - # Sample resource route with sub-resources: - # resources :products do - # resources :comments, :sales - # resource :seller - # end - - # Sample resource route with more complex sub-resources - # resources :products do - # resources :comments - # resources :sales do - # get 'recent', :on => :collection - # end - # end - - # Sample resource route within a namespace: - # namespace :admin do - # # Directs /admin/products/* to Admin::ProductsController - # # (app/controllers/admin/products_controller.rb) - # resources :products - # end - - # You can have the root of your site routed with "root" - # just remember to delete public/index.html. - # root :to => "welcome#index" - - # See how all your routes lay out with "rake routes" - - # This is a legacy wild controller route that's not recommended for RESTful applications. - # Note: This route will make all actions in every controller accessible via GET requests. - # match ':controller(/:action(/:id(.:format)))' -end + + resources :irb + + # The priority is based upon order of creation: + # first created -> highest priority. + root :to => "tryruby#index" + match '/tryruby/run' => 'tryruby#run' + # connect ':controller/:action/:id' + # connect ':controller/:action/:id.:format' + + # Sample of regular route: + # match 'products/:id' => 'catalog#view' + # Keep in mind you can assign values other than :controller and :action + + # Sample of named route: + # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase + # This route can be invoked with purchase_url(:id => product.id) + + # Sample resource route (maps HTTP verbs to controller actions automatically): + # resources :products + + # Sample resource route with options: + # resources :products do + # member do + # get 'short' + # post 'toggle' + # end + # + # collection do + # get 'sold' + # end + # end + + # Sample resource route with sub-resources: + # resources :products do + # resources :comments, :sales + # resource :seller + # end + + # Sample resource route with more complex sub-resources + # resources :products do + # resources :comments + # resources :sales do + # get 'recent', :on => :collection + # end + # end + + # Sample resource route within a namespace: + # namespace :admin do + # # Directs /admin/products/* to Admin::ProductsController + # # (app/controllers/admin/products_controller.rb) + # resources :products + # end + + # You can have the root of your site routed with "root" + # just remember to delete public/index.html. + # root :to => "welcome#index" + + # See how all your routes lay out with "rake routes" + + # This is a legacy wild controller route that's not recommended for RESTful applications. + # Note: This route will make all actions in every controller accessible via GET requests. + # match ':controller(/:action(/:id(.:format)))' + end + + + \ No newline at end of file diff --git a/db/development.sqlite3 b/db/development.sqlite3 new file mode 100644 index 0000000..e69de29 diff --git a/lib/popup.rb b/lib/popup.rb new file mode 100755 index 0000000..87edf38 --- /dev/null +++ b/lib/popup.rb @@ -0,0 +1,115 @@ +class Symbol + def to_proc + Proc.new { |obj, *args| obj.send(self, *args) } + end +end +module LoadPopup +module Popup + def self.goto(url) + url = url.gsub '"', '\"' + Output.javascript "window.irb.options.popup_goto(\"#{url}\")" + end + + class Header + attr_accessor :level, :text + def initialize(level, text) + self.level, self.text = level, text + end + def generate_html + "#{self.text}" + end + + end + + class Link + attr_accessor :text, :target + def initialize(text, target) + self.text, self.target = text, target + end + def generate_html + "#{text}" + end + + + end + + class List + attr_accessor :elements + def initialize(elements) + self.elements = elements + end + + def generate_html + items = elements.map do |elem| + text = elem.instance_of?(Paragraph) ? elem.text : elem.generate_html + "
                4. #{text}
                5. " + end.join(" ") + + "
                    #{items}
                  " + end + end + + + class Paragraph + attr_accessor :text + def initialize(text) + self.text = text + end + + def generate_html + "

                  #{self.text}

                  " + end + end + + + class ComplexPopup + attr_reader :elements + def initialize + @elements = [] + end + + (1..6).each do |n| + define_method "h#{n}".to_sym do |text| + @elements << Header.new(n, text) + end + end + + + # def h1 text + # @elements << Header.new(1, text) + # end + + def link(text, target) + @elements << Link.new(text, target) + end + + def p(text) + @elements << Paragraph.new(text) + end + + def list(&block) + lst = ComplexPopup.new + lst.instance_eval(&block) + @elements << List.new(lst.elements) + end + + def generate_html() + @elements.map(&:generate_html).join(" ") + end + + + + end + + + def self.make(&block) + result = ComplexPopup.new + result.instance_eval(&block) + + html = result.generate_html.gsub('\\', '\\\\').gsub('"', '\"') + command = "window.irb.options.popup_make(\"#{html}\")" + Tryrubyengine::Output.javascript command + end + +end +end \ No newline at end of file diff --git a/lib/setup.rb b/lib/setup.rb new file mode 100644 index 0000000..20fad62 --- /dev/null +++ b/lib/setup.rb @@ -0,0 +1,68 @@ +module Tryrubyengine +SetupCode = < 'db:test:prepare'}, 'Run features that should pass') do |t| + t.binary = vendored_cucumber_bin # If nil, the gem's binary is used. + t.fork = true # You may get faster startup if you set this to false + t.profile = 'default' + end + + Cucumber::Rake::Task.new({:wip => 'db:test:prepare'}, 'Run features that are being worked on') do |t| + t.binary = vendored_cucumber_bin + t.fork = true # You may get faster startup if you set this to false + t.profile = 'wip' + end + + Cucumber::Rake::Task.new({:rerun => 'db:test:prepare'}, 'Record failing features and run only them if any exist') do |t| + t.binary = vendored_cucumber_bin + t.fork = true # You may get faster startup if you set this to false + t.profile = 'rerun' + end + + desc 'Run all features' + task :all => [:ok, :wip] + end + desc 'Alias for cucumber:ok' + task :cucumber => 'cucumber:ok' + + task :default => :cucumber + + task :features => :cucumber do + STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***" + end +rescue LoadError + desc 'cucumber rake task not available (cucumber not installed)' + task :cucumber do + abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin' + end +end + +end diff --git a/lib/tryruby.rb b/lib/tryruby.rb new file mode 100644 index 0000000..7fe0912 --- /dev/null +++ b/lib/tryruby.rb @@ -0,0 +1,206 @@ +#require 'ruby_parser' +require 'ruby_parser' + +require 'stringio' +require 'popup.rb' +require 'setup.rb' +require 'fakefs/safe' +require 'cgi' +require 'cgi/session' +require 'cgi/session/pstore' + + + + + + + module Tryrubyengine + extend self + class TRSession + #include ActionDispatch::Session + # < TryRuby::Session + attr_accessor :cgi, :session + + def initialize + + @session = CGI::Session.new @cgi = CGI.new, + 'database_manager' => CGI::Session::PStore, # use PStore + 'session_key' => 'trb_sess_id', # custom $session key + 'session_expires' => Time.now + 60 * 60, # 60 minute timeout + 'prefix' => 'pstore_sid_', #Pstore option + 'tmpdir' => 'tmp' # Temp Directory for sessions + + @session['start_time'] ||= Time.now + #ActionController::Base.session + @session['current_statement'] ||= '' + @session['past_commands'] ||= '' + end + + def header + @cgi.header 'text/plain' + end + + [:current_statement, :past_commands, :start_time].each do |accessor| + define_method(accessor) { @session[accessor.to_s] } + define_method(:"#{accessor.to_s}=") { |new_val| @session[accessor.to_s] = new_val } + end + end + + + + class Output + attr_reader :type, :result, :output, :error, :indent_level, :javascript + + def self.standard(params = {}) + Output.new type: :standard, result: params[:result], + output: params[:output] || '' + end + + def self.illegal + Output.new type: :illegal + end + + def self.javascript(js) + Output.new type: :javascript, javascript: js + end + + def self.no_output + Output.standard result: nil + end + + def self.line_continuation(level) + Output.new type: :line_continuation, indent_level: level + end + + def self.error(params = {}) + params[:error] ||= StandardError.new('TryRuby Error') + params[:error].message.gsub! /\(eval\):\d*/, '(TryRuby):1' + Output.new type: :error, error: params[:error], + output: params[:output] || '' + end + + def format + case @type + when :line_continuation + ".." * @indent_level + when :error + @output + "\033[1;33m#{@error.class}: #{@error.message}" + when :illegal + "\033[1;33mYou aren't allowed to run that command!" + when :javascript + "\033[1;JSm#{@javascript}\033[m " + else + @output + "=> \033[1;20m#{@result.inspect}" + end + end + + protected + def initialize(values = {}) + values.each do |variable, value| + instance_variable_set("@#{variable}", value) + end + end + end + + + class << self + attr_accessor :session + Tryrubyengine.session = Tryrubyengine::TRSession.new + end + + def calculate_nesting_level(statement) + begin + RubyParser.new.parse(statement) + 0 + rescue Racc::ParseError => e + case e.message + when /parse error on value \"\$end\" \(\$end\)/ then + new_statement = statement + "\n end" + begin + RubyParser.new.parse(new_statement) + return 1 + rescue Racc::ParseError => e + if e.message =~ /parse error on value \"end\" \(kEND\)/ then + new_statement = statement + "\n }" + end + end + begin + 1 + calculate_nesting_level(new_statement) + rescue Racc::ParseError => e + return 1 + end + else + raise e + end + end + end + + def run_line(code,session) + case code.strip + when '!INIT!IRB!' + return Output.no_output + when 'reset' + session.current_statement = '' + return Output.no_output + when 'time' + seconds = (Time.now - session.start_time).ceil + return Output.standard result: + if seconds < 60; "#{seconds} seconds" + elsif seconds < 120; "1 minute" + else; "#{seconds / 60} minutes" + end + end + + # nesting level + level = begin + calculate_nesting_level(session.current_statement + "\n" + code) + rescue Racc::ParseError, SyntaxError + 0 + end + if level > 0 + session.current_statement += "\n" + code + return Output.line_continuation(level) + end + + # run something + FakeFS.activate! + stdout_id = $stdout.to_i + $stdout = StringIO.new + cmd = <<-EOF + #{SetupCode} + $SAFE = 3 + #{session.past_commands} + $stdout = StringIO.new + begin + #{session.current_statement} + #{code} + end + EOF + begin + result = Thread.new { eval cmd, TOPLEVEL_BINDING }.value + rescue SecurityError + return Output.illegal + rescue Exception => e + return Output.error :error => e, :output => get_stdout + ensure + output = get_stdout + $stdout = IO.new(stdout_id) + FakeFS.deactivate! + end + + session.current_statement += "\n" + code + session.past_commands += "\n" + session.current_statement.strip + session.current_statement = '' + + return result if result.is_a? Output and result.type == :javascript + Output.standard result: result, output: output + end + + private + def get_stdout + raise TypeError, "$stdout is a #{$stdout.class}" unless $stdout.is_a? StringIO + $stdout.rewind + $stdout.read + end + + end diff --git a/log/development.log b/log/development.log index 6a63a43..74ec939 100644 --- a/log/development.log +++ b/log/development.log @@ -671,3 +671,656 @@ ActionController::RoutingError (No route matches "/tryruby/run"): Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.4ms) + + +Started GET "/tryruby/run?cmd=tt" for 127.0.0.1 at 2011-07-08 18:25:11 -0500 + +Errno::ENOENT (No such file or directory - /Users/sophrinix/Desktop/herokutr/TryRuby/tryruby/config/locales/en.yml): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.6ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (3.5ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (16.2ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:28:50 -0500 + +Errno::ENOENT (No such file or directory - /Users/sophrinix/Desktop/herokutr/TryRuby/tryruby/config/locales/en.yml): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.9ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (3.8ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (26.2ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:28:51 -0500 + +Errno::ENOENT (No such file or directory - /Users/sophrinix/Desktop/herokutr/TryRuby/tryruby/config/locales/en.yml): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (29.5ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (2.8ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (41.8ms) +DEPRECATION WARNING: config.action_view.debug_rjs will be removed in 3.1, from 3.1 onwards you will need to install prototype-rails to continue to use RJS templates . (called from service at /Users/sophrinix/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/webrick/httpserver.rb:111) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:31:29 -0500 + +ActionController::RoutingError (uninitialized constant IndexController): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (3.1ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:31:47 -0500 + +NameError (uninitialized constant TryRuby): + config/routes.rb:1:in `' + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.9ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (62.0ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (76.9ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:32:26 -0500 + +LoadError (no such file to load -- ruby_parser): + lib/tryruby.rb:2:in `' + app/controllers/application_controller.rb:3:in `' + app/controllers/tryruby_controller.rb:2:in `' + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (8.2ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (3.0ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (20.8ms) +DEPRECATION WARNING: config.action_view.debug_rjs will be removed in 3.1, from 3.1 onwards you will need to install prototype-rails to continue to use RJS templates . (called from service at /Users/sophrinix/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/webrick/httpserver.rb:111) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:38:53 -0500 + +LoadError (no such file to load -- sqlite3): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.9ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (25.8ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (41.4ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:39:53 -0500 + +LoadError (no such file to load -- sqlite3): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.8ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (3.2ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (14.7ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:39:55 -0500 + +LoadError (no such file to load -- sqlite3): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.7ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (2.8ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (15.1ms) +DEPRECATION WARNING: config.action_view.debug_rjs will be removed in 3.1, from 3.1 onwards you will need to install prototype-rails to continue to use RJS templates . (called from service at /Users/sophrinix/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/webrick/httpserver.rb:111) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:54:33 -0500 + +Mysql2::Error (Access denied for user 'root'@'localhost' (using password: YES)): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.8ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (19.3ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (32.2ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:54:50 -0500 + +Mysql2::Error (Access denied for user 'root'@'localhost' (using password: YES)): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.7ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (2.6ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (13.5ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:54:51 -0500 + +Mysql2::Error (Access denied for user 'root'@'localhost' (using password: YES)): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.8ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (2.6ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (13.5ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:54:52 -0500 + +Mysql2::Error (Access denied for user 'root'@'localhost' (using password: YES)): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.8ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (2.7ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (14.1ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:55:19 -0500 + +Mysql2::Error (Access denied for user 'root'@'localhost' (using password: YES)): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.6ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (2.6ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (13.3ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:55:20 -0500 + +Mysql2::Error (Access denied for user 'root'@'localhost' (using password: YES)): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.7ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (2.7ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (13.7ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:55:20 -0500 + +Mysql2::Error (Access denied for user 'root'@'localhost' (using password: YES)): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.8ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (2.6ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (14.0ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:55:21 -0500 + +Mysql2::Error (Access denied for user 'root'@'localhost' (using password: YES)): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.7ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (2.6ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (13.5ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:55:35 -0500 + +Mysql2::Error (Access denied for user 'root'@'localhost' (using password: YES)): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.7ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (2.8ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (14.9ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:55:36 -0500 + +Mysql2::Error (Access denied for user 'root'@'localhost' (using password: YES)): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (3.9ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (4.2ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (18.0ms) +DEPRECATION WARNING: config.action_view.debug_rjs will be removed in 3.1, from 3.1 onwards you will need to install prototype-rails to continue to use RJS templates . (called from service at /Users/sophrinix/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/webrick/httpserver.rb:111) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:56:14 -0500 +DEPRECATION WARNING: config.action_view.debug_rjs will be removed in 3.1, from 3.1 onwards you will need to install prototype-rails to continue to use RJS templates . (called from service at /Users/sophrinix/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/webrick/httpserver.rb:111) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:59:08 -0500 + Processing by TryrubyController#index as HTML +Completed 500 Internal Server Error in 80ms + +ActionView::MissingTemplate (Missing template tryruby/index with {:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=>[:html], :locale=>[:en, :en]} in view paths "/Users/sophrinix/Desktop/herokutr/TryRuby/app/views", "/Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/devise-1.4.2/app/views"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/missing_template.erb within rescues/layout (2.6ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 18:59:37 -0500 + Processing by TryrubyController#index as HTML +Rendered tryruby/index.html.erb within layouts/tryruby (1.9ms) +Completed 200 OK in 9ms (Views: 8.8ms | ActiveRecord: 0.0ms) + + +Started GET "/javascript/jquery.console.js" for 127.0.0.1 at 2011-07-08 18:59:37 -0500 + +ActionController::RoutingError (No route matches "/javascript/jquery.console.js"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (3.2ms) + + +Started GET "/css/reset.css" for 127.0.0.1 at 2011-07-08 18:59:37 -0500 + +ActionController::RoutingError (No route matches "/css/reset.css"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) + + +Started GET "/javascript/lib.min.js" for 127.0.0.1 at 2011-07-08 18:59:37 -0500 + +ActionController::RoutingError (No route matches "/javascript/lib.min.js"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) + + +Started GET "/javascript/tryhaskell.js" for 127.0.0.1 at 2011-07-08 18:59:37 -0500 + +ActionController::RoutingError (No route matches "/javascript/tryhaskell.js"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) + + +Started GET "/javascript/raphael-min.js" for 127.0.0.1 at 2011-07-08 18:59:38 -0500 + +ActionController::RoutingError (No route matches "/javascript/raphael-min.js"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.3ms) + + +Started GET "/css/tryhaskell.css" for 127.0.0.1 at 2011-07-08 18:59:38 -0500 + +ActionController::RoutingError (No route matches "/css/tryhaskell.css"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 19:00:04 -0500 + Processing by TryrubyController#index as HTML +Rendered tryruby/index.html.erb within layouts/tryruby (1.6ms) +Completed 200 OK in 8ms (Views: 7.8ms | ActiveRecord: 0.0ms) + + +Started GET "/tutorials/intro" for 127.0.0.1 at 2011-07-08 19:00:05 -0500 + +ActionController::RoutingError (No route matches "/tutorials/intro"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.0ms) + + +Started GET "/tryruby/run?cmd=%21INIT%21IRB%21" for 127.0.0.1 at 2011-07-08 19:00:08 -0500 + Processing by TryrubyController#run as + Parameters: {"cmd"=>"!INIT!IRB!"} +Completed 500 Internal Server Error in 12ms + +NoMethodError (undefined method `type' for nil:NilClass): + app/controllers/tryruby_controller.rb:11:in `run' + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (3.5ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (11.3ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (28.2ms) + + +Started GET "/tryruby/run?cmd=2" for 127.0.0.1 at 2011-07-08 19:00:08 -0500 + Processing by TryrubyController#run as + Parameters: {"cmd"=>"2"} +Completed 500 Internal Server Error in 11ms + +NoMethodError (undefined method `type' for nil:NilClass): + app/controllers/tryruby_controller.rb:11:in `run' + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.8ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (7.3ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (18.8ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 19:00:25 -0500 +DEPRECATION WARNING: config.action_view.debug_rjs will be removed in 3.1, from 3.1 onwards you will need to install prototype-rails to continue to use RJS templates . (called from service at /Users/sophrinix/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/webrick/httpserver.rb:111) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 19:03:47 -0500 + Processing by TryrubyController#index as HTML +Rendered tryruby/index.html.erb within layouts/tryruby (1.0ms) +Completed 200 OK in 5ms (Views: 4.8ms | ActiveRecord: 0.0ms) + + +Started GET "/tutorials/intro" for 127.0.0.1 at 2011-07-08 19:03:47 -0500 + +ActionController::RoutingError (No route matches "/tutorials/intro"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.2ms) + + +Started GET "/tryruby/run?cmd=%21INIT%21IRB%21" for 127.0.0.1 at 2011-07-08 19:03:52 -0500 + Processing by TryrubyController#run as + Parameters: {"cmd"=>"!INIT!IRB!"} +Completed 500 Internal Server Error in 2ms + +NoMethodError (undefined method `IRB!' for #): + app/controllers/tryruby_controller.rb:22:in `eval' + app/controllers/tryruby_controller.rb:22:in `eval' + app/controllers/tryruby_controller.rb:22:in `run_script' + app/controllers/tryruby_controller.rb:10:in `run' + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (1.4ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (3.8ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (10.3ms) + + +Started GET "/tryruby/run?cmd=2" for 127.0.0.1 at 2011-07-08 19:03:52 -0500 + Processing by TryrubyController#run as + Parameters: {"cmd"=>"2"} +Completed 500 Internal Server Error in 1ms + +NoMethodError (undefined method `type' for nil:NilClass): + app/controllers/tryruby_controller.rb:11:in `run' + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (1.5ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (3.5ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (10.8ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 19:04:56 -0500 + Processing by TryrubyController#index as HTML +Rendered tryruby/index.html.erb within layouts/tryruby (0.9ms) +Completed 200 OK in 4ms (Views: 3.9ms | ActiveRecord: 0.0ms) + + +Started GET "/tutorials/intro" for 127.0.0.1 at 2011-07-08 19:04:56 -0500 + +ActionController::RoutingError (No route matches "/tutorials/intro"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.2ms) + + +Started GET "/tryruby/run?cmd=%21INIT%21IRB%21" for 127.0.0.1 at 2011-07-08 19:04:58 -0500 + Processing by TryrubyController#run as + Parameters: {"cmd"=>"!INIT!IRB!"} +Completed 500 Internal Server Error in 1ms + +NoMethodError (undefined method `IRB!' for #): + app/controllers/tryruby_controller.rb:9:in `eval' + app/controllers/tryruby_controller.rb:9:in `eval' + app/controllers/tryruby_controller.rb:9:in `run' + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (1.4ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (3.5ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (9.2ms) + + +Started GET "/tryruby/run?cmd=2" for 127.0.0.1 at 2011-07-08 19:04:58 -0500 + Processing by TryrubyController#run as + Parameters: {"cmd"=>"2"} +Completed 200 OK in 1ms (Views: 0.2ms | ActiveRecord: 0.0ms) + + +Started GET "/tryruby/run?cmd=time" for 127.0.0.1 at 2011-07-08 19:05:00 -0500 + Processing by TryrubyController#run as + Parameters: {"cmd"=>"time"} +Completed 500 Internal Server Error in 1ms + +NameError (undefined local variable or method `time' for #): + app/controllers/tryruby_controller.rb:9:in `eval' + app/controllers/tryruby_controller.rb:9:in `eval' + app/controllers/tryruby_controller.rb:9:in `run' + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.7ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (3.4ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (10.6ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 19:05:07 -0500 + Processing by TryrubyController#index as HTML +Rendered tryruby/index.html.erb within layouts/tryruby (0.9ms) +Completed 200 OK in 5ms (Views: 4.2ms | ActiveRecord: 0.0ms) + + +Started GET "/tutorials/intro" for 127.0.0.1 at 2011-07-08 19:05:08 -0500 + +ActionController::RoutingError (No route matches "/tutorials/intro"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.1ms) + + +Started GET "/tryruby/run?cmd=%21INIT%21IRB%21" for 127.0.0.1 at 2011-07-08 19:05:09 -0500 + Processing by TryrubyController#run as + Parameters: {"cmd"=>"!INIT!IRB!"} +Completed 500 Internal Server Error in 1ms + +NoMethodError (undefined method `IRB!' for #): + app/controllers/tryruby_controller.rb:9:in `eval' + app/controllers/tryruby_controller.rb:9:in `eval' + app/controllers/tryruby_controller.rb:9:in `run' + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (1.4ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (4.6ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (10.4ms) + + +Started GET "/tryruby/run?cmd=1" for 127.0.0.1 at 2011-07-08 19:05:09 -0500 + Processing by TryrubyController#run as + Parameters: {"cmd"=>"1"} +Completed 200 OK in 1ms (Views: 0.3ms | ActiveRecord: 0.0ms) + + +Started GET "/tryruby/run?cmd=1%20%2B%206" for 127.0.0.1 at 2011-07-08 19:05:11 -0500 + Processing by TryrubyController#run as + Parameters: {"cmd"=>"1 + 6"} +Completed 200 OK in 1ms (Views: 0.2ms | ActiveRecord: 0.0ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 19:05:24 -0500 + Processing by TryrubyController#index as HTML +Rendered tryruby/index.html.erb within layouts/tryruby (1.9ms) +Completed 200 OK in 8ms (Views: 7.8ms | ActiveRecord: 0.0ms) + + +Started GET "/tutorials/intro" for 127.0.0.1 at 2011-07-08 19:05:24 -0500 + +ActionController::RoutingError (No route matches "/tutorials/intro"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) + + +Started GET "/tryruby/run?cmd=%21INIT%21IRB%21" for 127.0.0.1 at 2011-07-08 19:05:26 -0500 + Processing by TryrubyController#run as + Parameters: {"cmd"=>"!INIT!IRB!"} +Completed 500 Internal Server Error in 3ms + +NoMethodError (undefined method `IRB!' for #): + app/controllers/tryruby_controller.rb:9:in `eval' + app/controllers/tryruby_controller.rb:9:in `eval' + app/controllers/tryruby_controller.rb:9:in `run' + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.7ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (7.1ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (18.1ms) + + +Started GET "/tryruby/run?cmd=1" for 127.0.0.1 at 2011-07-08 19:05:26 -0500 + Processing by TryrubyController#run as + Parameters: {"cmd"=>"1"} +Completed 500 Internal Server Error in 78ms + +ActionView::MissingTemplate (Missing template tryruby/run with {:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=>[:html, :text, :js, :css, :ics, :csv, :xml, :rss, :atom, :yaml, :multipart_form, :url_encoded_form, :json], :locale=>[:en, :en]} in view paths "/Users/sophrinix/Desktop/herokutr/TryRuby/app/views", "/Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/devise-1.4.2/app/views"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/missing_template.erb within rescues/layout (1.7ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 19:05:47 -0500 + Processing by TryrubyController#index as HTML +Rendered tryruby/index.html.erb within layouts/tryruby (1.5ms) +Completed 200 OK in 8ms (Views: 7.5ms | ActiveRecord: 0.0ms) + + +Started GET "/tutorials/intro" for 127.0.0.1 at 2011-07-08 19:05:48 -0500 + +ActionController::RoutingError (No route matches "/tutorials/intro"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.5ms) + + +Started GET "/tryruby/run?cmd=%21INIT%21IRB%21" for 127.0.0.1 at 2011-07-08 19:05:49 -0500 + Processing by TryrubyController#run as + Parameters: {"cmd"=>"!INIT!IRB!"} +Completed 500 Internal Server Error in 3ms + +NoMethodError (undefined method `IRB!' for #): + app/controllers/tryruby_controller.rb:9:in `eval' + app/controllers/tryruby_controller.rb:9:in `eval' + app/controllers/tryruby_controller.rb:9:in `run' + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.8ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (6.7ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (17.7ms) + + +Started GET "/tryruby/run?cmd=2" for 127.0.0.1 at 2011-07-08 19:05:49 -0500 + Processing by TryrubyController#run as + Parameters: {"cmd"=>"2"} +Completed 500 Internal Server Error in 2ms + +NoMethodError (undefined method `model_name' for Fixnum:Class): + app/controllers/tryruby_controller.rb:9:in `run' + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.8ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (7.3ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (18.3ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 19:06:06 -0500 + Processing by TryrubyController#index as HTML +Rendered tryruby/index.html.erb within layouts/tryruby (1.5ms) +Completed 200 OK in 8ms (Views: 7.2ms | ActiveRecord: 0.0ms) + + +Started GET "/tutorials/intro" for 127.0.0.1 at 2011-07-08 19:06:06 -0500 + +ActionController::RoutingError (No route matches "/tutorials/intro"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.9ms) + + +Started GET "/tryruby/run?cmd=%21INIT%21IRB%21" for 127.0.0.1 at 2011-07-08 19:06:07 -0500 + Processing by TryrubyController#run as + Parameters: {"cmd"=>"!INIT!IRB!"} +Completed 500 Internal Server Error in 3ms + +NoMethodError (undefined method `IRB!' for #): + app/controllers/tryruby_controller.rb:9:in `eval' + app/controllers/tryruby_controller.rb:9:in `eval' + app/controllers/tryruby_controller.rb:9:in `run' + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (90.0ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (6.7ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (105.1ms) + + +Started GET "/tryruby/run?cmd=1" for 127.0.0.1 at 2011-07-08 19:06:07 -0500 + Processing by TryrubyController#run as + Parameters: {"cmd"=>"1"} +Completed 500 Internal Server Error in 17ms + +ActionView::MissingTemplate (Missing template tryruby/run with {:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=>[:html, :text, :js, :css, :ics, :csv, :xml, :rss, :atom, :yaml, :multipart_form, :url_encoded_form, :json], :locale=>[:en, :en]} in view paths "/Users/sophrinix/Desktop/herokutr/TryRuby/app/views", "/Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/devise-1.4.2/app/views"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/missing_template.erb within rescues/layout (1.7ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 19:17:57 -0500 + Processing by TryrubyController#index as HTML +Rendered tryruby/index.html.erb within layouts/tryruby (1.5ms) +Completed 200 OK in 8ms (Views: 7.3ms | ActiveRecord: 0.0ms) + + +Started GET "/tutorials/intro" for 127.0.0.1 at 2011-07-08 19:17:58 -0500 + +ActionController::RoutingError (No route matches "/tutorials/intro"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) + + +Started GET "/tryruby/run?cmd=%21INIT%21IRB%21" for 127.0.0.1 at 2011-07-08 19:18:00 -0500 + Processing by TryrubyController#run as + Parameters: {"cmd"=>"!INIT!IRB!"} +Completed 500 Internal Server Error in 3ms + +NoMethodError (undefined method `IRB!' for #): + app/controllers/tryruby_controller.rb:9:in `eval' + app/controllers/tryruby_controller.rb:9:in `eval' + app/controllers/tryruby_controller.rb:9:in `run' + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.8ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (8.8ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (20.3ms) + + +Started GET "/tryruby/run?cmd=1" for 127.0.0.1 at 2011-07-08 19:18:00 -0500 + Processing by TryrubyController#run as + Parameters: {"cmd"=>"1"} +Completed 500 Internal Server Error in 17ms + +ActionView::MissingTemplate (Missing template tryruby/run with {:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=>[:html, :text, :js, :css, :ics, :csv, :xml, :rss, :atom, :yaml, :multipart_form, :url_encoded_form, :json], :locale=>[:en, :en]} in view paths "/Users/sophrinix/Desktop/herokutr/TryRuby/app/views", "/Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/devise-1.4.2/app/views"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/missing_template.erb within rescues/layout (1.6ms) + + +Started GET "/" for 127.0.0.1 at 2011-07-08 19:18:23 -0500 + Processing by TryrubyController#index as HTML +Rendered tryruby/index.html.erb within layouts/tryruby (1.5ms) +Completed 200 OK in 9ms (Views: 8.2ms | ActiveRecord: 0.0ms) + + +Started GET "/tutorials/intro" for 127.0.0.1 at 2011-07-08 19:18:23 -0500 + +ActionController::RoutingError (No route matches "/tutorials/intro"): + + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) + + +Started GET "/tryruby/run?cmd=%21INIT%21IRB%21" for 127.0.0.1 at 2011-07-08 19:18:25 -0500 + Processing by TryrubyController#run as + Parameters: {"cmd"=>"!INIT!IRB!"} +Completed 500 Internal Server Error in 3ms + +NoMethodError (undefined method `IRB!' for #): + app/controllers/tryruby_controller.rb:9:in `eval' + app/controllers/tryruby_controller.rb:9:in `eval' + app/controllers/tryruby_controller.rb:9:in `run' + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (3.4ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (6.8ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (18.9ms) + + +Started GET "/tryruby/run?cmd=1" for 127.0.0.1 at 2011-07-08 19:18:25 -0500 + Processing by TryrubyController#run as + Parameters: {"cmd"=>"1"} +Rendered tryruby/run.html.erb within layouts/tryruby (1.6ms) +Completed 200 OK in 18ms (Views: 16.9ms | ActiveRecord: 0.0ms) + + +Started GET "/tryruby/run?cmd=hi" for 127.0.0.1 at 2011-07-08 19:18:34 -0500 + Processing by TryrubyController#run as + Parameters: {"cmd"=>"hi"} +Completed 500 Internal Server Error in 3ms + +NameError (undefined local variable or method `hi' for #): + app/controllers/tryruby_controller.rb:9:in `eval' + app/controllers/tryruby_controller.rb:9:in `eval' + app/controllers/tryruby_controller.rb:9:in `run' + +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.9ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (7.1ms) +Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (18.5ms) diff --git a/tmp/pids/server.pid b/tmp/pids/server.pid new file mode 100644 index 0000000..9738fa5 --- /dev/null +++ b/tmp/pids/server.pid @@ -0,0 +1 @@ +47518 \ No newline at end of file From f51c07138dab17cd9e7026fbe53528dc08c65f52 Mon Sep 17 00:00:00 2001 From: Andrew McElroy Date: Fri, 8 Jul 2011 19:59:52 -0500 Subject: [PATCH 13/16] absolutely ensuring that master is cleaned up... ill tweet when it is safe to use. --- .gitignore | 2 + log/development.log | 1326 ------------------------- log/production.log | 0 log/server.log | 0 log/test.log | 0 non-rack-legacy/public/tmp/index.html | 8 - 6 files changed, 2 insertions(+), 1334 deletions(-) delete mode 100644 log/development.log delete mode 100644 log/production.log delete mode 100644 log/server.log delete mode 100644 log/test.log delete mode 100755 non-rack-legacy/public/tmp/index.html diff --git a/.gitignore b/.gitignore index 1c58a2b..fd50413 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ .bundle *.lock tryruby/log/* +tmp/* +tmp/* diff --git a/log/development.log b/log/development.log deleted file mode 100644 index 74ec939..0000000 --- a/log/development.log +++ /dev/null @@ -1,1326 +0,0 @@ -DEPRECATION WARNING: config.action_view.debug_rjs will be removed in 3.1, from 3.1 onwards you will need to install prototype-rails to continue to use RJS templates . (called from service at /Users/sophrinix/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/webrick/httpserver.rb:111) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 17:52:45 -0500 - -ActionController::RoutingError (No route matches "/"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.5ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 17:54:39 -0500 - -ActionController::RoutingError (No route matches "/"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.4ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 17:54:44 -0500 - -ActionController::RoutingError (No route matches "/"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (100.8ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 17:54:57 -0500 - -NoMethodError (undefined method `reverse_merge' for #): - config/routes.rb:2:in `block in ' - config/routes.rb:1:in `' - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (3.0ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (19.8ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (46.8ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 17:55:29 -0500 - -ArgumentError (missing :action): - config/routes.rb:2:in `block in ' - config/routes.rb:1:in `' - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (4.2ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (2.8ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (26.6ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 17:55:42 -0500 - Processing by IndexController#index as HTML -Completed 500 Internal Server Error in 73ms - -ActionView::MissingTemplate (Missing template index/index with {:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=>[:html], :locale=>[:en, :en]} in view paths "/Users/sophrinix/Desktop/herokutr/TryRuby/tryruby/app/views"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/missing_template.erb within rescues/layout (2.7ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 17:55:56 -0500 - Processing by IndexController#index as HTML -Rendered index/index.html.erb within layouts/application (2.0ms) -Completed 200 OK in 13ms (Views: 12.0ms | ActiveRecord: 0.0ms) - - -Started GET "/images/footer.png" for 127.0.0.1 at 2011-07-08 17:55:57 -0500 - -ActionController::RoutingError (No route matches "/images/footer.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) - - -Started GET "/images/header.png" for 127.0.0.1 at 2011-07-08 17:55:57 -0500 - -ActionController::RoutingError (No route matches "/images/header.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) - - -Started GET "/images/header.png" for 127.0.0.1 at 2011-07-08 17:55:57 -0500 - -ActionController::RoutingError (No route matches "/images/header.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.3ms) - - -Started GET "/images/footer.png" for 127.0.0.1 at 2011-07-08 17:55:57 -0500 - -ActionController::RoutingError (No route matches "/images/footer.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) - - -Started GET "/stylesheets/images/plus.png" for 127.0.0.1 at 2011-07-08 17:55:57 -0500 - -ActionController::RoutingError (No route matches "/stylesheets/images/plus.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.3ms) - - -Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 17:55:57 -0500 - -ActionController::RoutingError (No route matches "/images/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) - - -Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 17:55:58 -0500 - -ActionController::RoutingError (No route matches "/images/loading.gif"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) - - -Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 17:55:58 -0500 - -ActionController::RoutingError (No route matches "/facebox/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 17:57:25 -0500 - Processing by IndexController#index as HTML -Rendered index/index.html.erb within layouts/application (2.3ms) -Completed 200 OK in 14ms (Views: 13.3ms | ActiveRecord: 0.0ms) - - -Started GET "/images/footer.png" for 127.0.0.1 at 2011-07-08 17:57:25 -0500 - -ActionController::RoutingError (No route matches "/images/footer.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (3.7ms) - - -Started GET "/images/header.png" for 127.0.0.1 at 2011-07-08 17:57:25 -0500 - -ActionController::RoutingError (No route matches "/images/header.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (3.0ms) - - -Started GET "/images/footer.png" for 127.0.0.1 at 2011-07-08 17:57:25 -0500 - -ActionController::RoutingError (No route matches "/images/footer.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (3.6ms) - - -Started GET "/images/header.png" for 127.0.0.1 at 2011-07-08 17:57:25 -0500 - -ActionController::RoutingError (No route matches "/images/header.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) - - -Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 17:57:26 -0500 - -ActionController::RoutingError (No route matches "/facebox/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) - - -Started GET "/stylesheets/images/plus.png" for 127.0.0.1 at 2011-07-08 17:57:26 -0500 - -ActionController::RoutingError (No route matches "/stylesheets/images/plus.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) - - -Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 17:57:26 -0500 - -ActionController::RoutingError (No route matches "/images/loading.gif"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (9.0ms) - - -Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 17:57:26 -0500 - -ActionController::RoutingError (No route matches "/images/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 17:57:31 -0500 - Processing by IndexController#index as HTML -Rendered index/index.html.erb within layouts/application (2.1ms) -Completed 200 OK in 17ms (Views: 16.6ms | ActiveRecord: 0.0ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 17:58:24 -0500 - Processing by IndexController#index as HTML -Rendered index/index.html.erb within layouts/application (4.8ms) -Completed 200 OK in 30ms (Views: 29.1ms | ActiveRecord: 0.0ms) - - -Started GET "/stylesheets/images/plus.png" for 127.0.0.1 at 2011-07-08 17:58:24 -0500 - -ActionController::RoutingError (No route matches "/stylesheets/images/plus.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.3ms) - - -Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 17:58:24 -0500 - -ActionController::RoutingError (No route matches "/facebox/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) - - -Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 17:58:24 -0500 - -ActionController::RoutingError (No route matches "/images/loading.gif"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.8ms) - - -Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 17:58:25 -0500 - -ActionController::RoutingError (No route matches "/images/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.4ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 17:59:08 -0500 - Processing by IndexController#index as HTML -Rendered index/index.html.erb within layouts/application (2.4ms) -Completed 200 OK in 22ms (Views: 21.5ms | ActiveRecord: 0.0ms) - - -Started GET "/stylesheets/images/plus.png" for 127.0.0.1 at 2011-07-08 17:59:09 -0500 - -ActionController::RoutingError (No route matches "/stylesheets/images/plus.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) - - -Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 17:59:09 -0500 - -ActionController::RoutingError (No route matches "/facebox/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) - - -Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 17:59:09 -0500 - -ActionController::RoutingError (No route matches "/images/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) - - -Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 17:59:09 -0500 - -ActionController::RoutingError (No route matches "/images/loading.gif"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.5ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:07:42 -0500 - Processing by IndexController#index as HTML -Rendered index/index.html.erb within layouts/application (2.2ms) -Completed 200 OK in 19ms (Views: 17.9ms | ActiveRecord: 0.0ms) - - -Started GET "/stylesheets/images/plus.png" for 127.0.0.1 at 2011-07-08 18:07:43 -0500 - -ActionController::RoutingError (No route matches "/stylesheets/images/plus.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.8ms) - - -Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 18:07:43 -0500 - -ActionController::RoutingError (No route matches "/facebox/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.3ms) - - -Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 18:07:43 -0500 - -ActionController::RoutingError (No route matches "/images/loading.gif"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.0ms) - - -Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 18:07:43 -0500 - -ActionController::RoutingError (No route matches "/images/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:08:38 -0500 - Processing by IndexController#index as HTML -Rendered index/index.html.erb within layouts/application (1.3ms) -Completed 200 OK in 7ms (Views: 6.4ms | ActiveRecord: 0.0ms) - - -Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 18:08:38 -0500 - -ActionController::RoutingError (No route matches "/facebox/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.1ms) - - -Started GET "/stylesheets/images/plus.png" for 127.0.0.1 at 2011-07-08 18:08:38 -0500 - -ActionController::RoutingError (No route matches "/stylesheets/images/plus.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.1ms) - - -Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 18:08:38 -0500 - -ActionController::RoutingError (No route matches "/images/loading.gif"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.1ms) - - -Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 18:08:38 -0500 - -ActionController::RoutingError (No route matches "/images/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.4ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:09:04 -0500 - Processing by IndexController#index as HTML -Rendered index/index.html.erb within layouts/application (1.3ms) -Completed 200 OK in 18ms (Views: 17.0ms | ActiveRecord: 0.0ms) - - -Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 18:09:05 -0500 - -ActionController::RoutingError (No route matches "/facebox/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.1ms) - - -Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 18:09:05 -0500 - -ActionController::RoutingError (No route matches "/images/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.1ms) - - -Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 18:09:05 -0500 - -ActionController::RoutingError (No route matches "/images/loading.gif"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.1ms) - - -Started GET "/stylesheets/images/plus.png" for 127.0.0.1 at 2011-07-08 18:09:05 -0500 - -ActionController::RoutingError (No route matches "/stylesheets/images/plus.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.8ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:09:30 -0500 - Processing by IndexController#index as HTML -Rendered index/index.html.erb within layouts/application (1.3ms) -Completed 200 OK in 8ms (Views: 7.0ms | ActiveRecord: 0.0ms) - - -Started GET "/stylesheets/images/plus.png" for 127.0.0.1 at 2011-07-08 18:09:30 -0500 - -ActionController::RoutingError (No route matches "/stylesheets/images/plus.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.1ms) - - -Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 18:09:30 -0500 - -ActionController::RoutingError (No route matches "/facebox/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.8ms) - - -Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 18:09:30 -0500 - -ActionController::RoutingError (No route matches "/images/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.1ms) - - -Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 18:09:30 -0500 - -ActionController::RoutingError (No route matches "/images/loading.gif"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.3ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:10:21 -0500 - Processing by IndexController#index as HTML -Rendered index/index.html.erb within layouts/application (2.2ms) -Completed 200 OK in 15ms (Views: 14.5ms | ActiveRecord: 0.0ms) - - -Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 18:10:22 -0500 - -ActionController::RoutingError (No route matches "/images/loading.gif"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) - - -Started GET "/stylesheets/images/plus.png" for 127.0.0.1 at 2011-07-08 18:10:22 -0500 - -ActionController::RoutingError (No route matches "/stylesheets/images/plus.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) - - -Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 18:10:22 -0500 - -ActionController::RoutingError (No route matches "/facebox/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.3ms) - - -Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 18:10:22 -0500 - -ActionController::RoutingError (No route matches "/images/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) - - -Started GET "/tutorials/intro" for 127.0.0.1 at 2011-07-08 18:10:22 -0500 - -ActionController::RoutingError (No route matches "/tutorials/intro"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:11:20 -0500 - Processing by IndexController#index as HTML -Rendered index/index.html.erb within layouts/application (2.0ms) -Completed 200 OK in 14ms (Views: 13.4ms | ActiveRecord: 0.0ms) - - -Started GET "/stylesheets/images/plus.png" for 127.0.0.1 at 2011-07-08 18:11:20 -0500 - -ActionController::RoutingError (No route matches "/stylesheets/images/plus.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.3ms) - - -Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 18:11:20 -0500 - -ActionController::RoutingError (No route matches "/images/loading.gif"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) - - -Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 18:11:20 -0500 - -ActionController::RoutingError (No route matches "/images/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) - - -Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 18:11:21 -0500 - -ActionController::RoutingError (No route matches "/facebox/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.0ms) - - -Started GET "/tutorials/intro" for 127.0.0.1 at 2011-07-08 18:11:21 -0500 - Processing by TutorialsController#intro as -Rendered tutorials/intro.html.erb within layouts/application (2.2ms) -Completed 200 OK in 41ms (Views: 40.5ms | ActiveRecord: 0.0ms) - - -Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 18:11:23 -0500 - -ActionController::RoutingError (No route matches "/facebox/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) - - -Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 18:11:23 -0500 - -ActionController::RoutingError (No route matches "/images/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (3.8ms) - - -Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 18:11:23 -0500 - -ActionController::RoutingError (No route matches "/images/loading.gif"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.3ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:11:39 -0500 - Processing by IndexController#index as HTML -Rendered index/index.html.erb within layouts/application (2.0ms) -Completed 200 OK in 13ms (Views: 12.0ms | ActiveRecord: 0.0ms) - - -Started GET "/stylesheets/images/plus.png" for 127.0.0.1 at 2011-07-08 18:11:40 -0500 - -ActionController::RoutingError (No route matches "/stylesheets/images/plus.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (5.1ms) - - -Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 18:11:40 -0500 - -ActionController::RoutingError (No route matches "/images/loading.gif"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) - - -Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 18:11:40 -0500 - -ActionController::RoutingError (No route matches "/images/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) - - -Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 18:11:40 -0500 - -ActionController::RoutingError (No route matches "/facebox/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.3ms) - - -Started GET "/tutorials/intro" for 127.0.0.1 at 2011-07-08 18:11:41 -0500 - Processing by TutorialsController#intro as -Rendered tutorials/intro.html.erb within layouts/application (2.1ms) -Completed 200 OK in 47ms (Views: 45.8ms | ActiveRecord: 0.0ms) - - -Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 18:11:42 -0500 - -ActionController::RoutingError (No route matches "/facebox/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) - - -Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 18:11:42 -0500 - -ActionController::RoutingError (No route matches "/images/loading.gif"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) - - -Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 18:11:42 -0500 - -ActionController::RoutingError (No route matches "/images/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (3.7ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:13:34 -0500 - Processing by IndexController#index as HTML -Rendered index/index.html.erb within layouts/application (2.2ms) -Completed 200 OK in 14ms (Views: 13.2ms | ActiveRecord: 0.0ms) - - -Started GET "/stylesheets/images/plus.png" for 127.0.0.1 at 2011-07-08 18:13:35 -0500 - -ActionController::RoutingError (No route matches "/stylesheets/images/plus.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.9ms) - - -Started GET "/images/closelabel.png" for 127.0.0.1 at 2011-07-08 18:13:35 -0500 - -ActionController::RoutingError (No route matches "/images/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) - - -Started GET "/facebox/closelabel.png" for 127.0.0.1 at 2011-07-08 18:13:35 -0500 - -ActionController::RoutingError (No route matches "/facebox/closelabel.png"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (6.7ms) - - -Started GET "/images/loading.gif" for 127.0.0.1 at 2011-07-08 18:13:35 -0500 - -ActionController::RoutingError (No route matches "/images/loading.gif"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) - - -Started GET "/tutorials/intro" for 127.0.0.1 at 2011-07-08 18:13:36 -0500 - Processing by TutorialsController#intro as -Rendered tutorials/intro.html.erb within layouts/blank (14.9ms) -Completed 200 OK in 51ms (Views: 50.6ms | ActiveRecord: 0.0ms) - - -Started GET "/tryruby/run?cmd=%21INIT%21IRB%21" for 127.0.0.1 at 2011-07-08 18:13:41 -0500 - -ActionController::RoutingError (No route matches "/tryruby/run"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.0ms) - - -Started GET "/tryruby/run?cmd=1" for 127.0.0.1 at 2011-07-08 18:13:42 -0500 - -ActionController::RoutingError (No route matches "/tryruby/run"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.4ms) - - -Started GET "/tryruby/run?cmd=tt" for 127.0.0.1 at 2011-07-08 18:25:11 -0500 - -Errno::ENOENT (No such file or directory - /Users/sophrinix/Desktop/herokutr/TryRuby/tryruby/config/locales/en.yml): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.6ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (3.5ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (16.2ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:28:50 -0500 - -Errno::ENOENT (No such file or directory - /Users/sophrinix/Desktop/herokutr/TryRuby/tryruby/config/locales/en.yml): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.9ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (3.8ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (26.2ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:28:51 -0500 - -Errno::ENOENT (No such file or directory - /Users/sophrinix/Desktop/herokutr/TryRuby/tryruby/config/locales/en.yml): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (29.5ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (2.8ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (41.8ms) -DEPRECATION WARNING: config.action_view.debug_rjs will be removed in 3.1, from 3.1 onwards you will need to install prototype-rails to continue to use RJS templates . (called from service at /Users/sophrinix/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/webrick/httpserver.rb:111) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:31:29 -0500 - -ActionController::RoutingError (uninitialized constant IndexController): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (3.1ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:31:47 -0500 - -NameError (uninitialized constant TryRuby): - config/routes.rb:1:in `' - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.9ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (62.0ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (76.9ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:32:26 -0500 - -LoadError (no such file to load -- ruby_parser): - lib/tryruby.rb:2:in `' - app/controllers/application_controller.rb:3:in `' - app/controllers/tryruby_controller.rb:2:in `' - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (8.2ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (3.0ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (20.8ms) -DEPRECATION WARNING: config.action_view.debug_rjs will be removed in 3.1, from 3.1 onwards you will need to install prototype-rails to continue to use RJS templates . (called from service at /Users/sophrinix/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/webrick/httpserver.rb:111) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:38:53 -0500 - -LoadError (no such file to load -- sqlite3): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.9ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (25.8ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (41.4ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:39:53 -0500 - -LoadError (no such file to load -- sqlite3): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.8ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (3.2ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (14.7ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:39:55 -0500 - -LoadError (no such file to load -- sqlite3): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.7ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (2.8ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (15.1ms) -DEPRECATION WARNING: config.action_view.debug_rjs will be removed in 3.1, from 3.1 onwards you will need to install prototype-rails to continue to use RJS templates . (called from service at /Users/sophrinix/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/webrick/httpserver.rb:111) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:54:33 -0500 - -Mysql2::Error (Access denied for user 'root'@'localhost' (using password: YES)): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.8ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (19.3ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (32.2ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:54:50 -0500 - -Mysql2::Error (Access denied for user 'root'@'localhost' (using password: YES)): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.7ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (2.6ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (13.5ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:54:51 -0500 - -Mysql2::Error (Access denied for user 'root'@'localhost' (using password: YES)): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.8ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (2.6ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (13.5ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:54:52 -0500 - -Mysql2::Error (Access denied for user 'root'@'localhost' (using password: YES)): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.8ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (2.7ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (14.1ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:55:19 -0500 - -Mysql2::Error (Access denied for user 'root'@'localhost' (using password: YES)): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.6ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (2.6ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (13.3ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:55:20 -0500 - -Mysql2::Error (Access denied for user 'root'@'localhost' (using password: YES)): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.7ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (2.7ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (13.7ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:55:20 -0500 - -Mysql2::Error (Access denied for user 'root'@'localhost' (using password: YES)): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.8ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (2.6ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (14.0ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:55:21 -0500 - -Mysql2::Error (Access denied for user 'root'@'localhost' (using password: YES)): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.7ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (2.6ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (13.5ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:55:35 -0500 - -Mysql2::Error (Access denied for user 'root'@'localhost' (using password: YES)): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.7ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (2.8ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (14.9ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:55:36 -0500 - -Mysql2::Error (Access denied for user 'root'@'localhost' (using password: YES)): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (3.9ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (4.2ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (18.0ms) -DEPRECATION WARNING: config.action_view.debug_rjs will be removed in 3.1, from 3.1 onwards you will need to install prototype-rails to continue to use RJS templates . (called from service at /Users/sophrinix/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/webrick/httpserver.rb:111) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:56:14 -0500 -DEPRECATION WARNING: config.action_view.debug_rjs will be removed in 3.1, from 3.1 onwards you will need to install prototype-rails to continue to use RJS templates . (called from service at /Users/sophrinix/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/webrick/httpserver.rb:111) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:59:08 -0500 - Processing by TryrubyController#index as HTML -Completed 500 Internal Server Error in 80ms - -ActionView::MissingTemplate (Missing template tryruby/index with {:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=>[:html], :locale=>[:en, :en]} in view paths "/Users/sophrinix/Desktop/herokutr/TryRuby/app/views", "/Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/devise-1.4.2/app/views"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/missing_template.erb within rescues/layout (2.6ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 18:59:37 -0500 - Processing by TryrubyController#index as HTML -Rendered tryruby/index.html.erb within layouts/tryruby (1.9ms) -Completed 200 OK in 9ms (Views: 8.8ms | ActiveRecord: 0.0ms) - - -Started GET "/javascript/jquery.console.js" for 127.0.0.1 at 2011-07-08 18:59:37 -0500 - -ActionController::RoutingError (No route matches "/javascript/jquery.console.js"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (3.2ms) - - -Started GET "/css/reset.css" for 127.0.0.1 at 2011-07-08 18:59:37 -0500 - -ActionController::RoutingError (No route matches "/css/reset.css"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) - - -Started GET "/javascript/lib.min.js" for 127.0.0.1 at 2011-07-08 18:59:37 -0500 - -ActionController::RoutingError (No route matches "/javascript/lib.min.js"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) - - -Started GET "/javascript/tryhaskell.js" for 127.0.0.1 at 2011-07-08 18:59:37 -0500 - -ActionController::RoutingError (No route matches "/javascript/tryhaskell.js"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) - - -Started GET "/javascript/raphael-min.js" for 127.0.0.1 at 2011-07-08 18:59:38 -0500 - -ActionController::RoutingError (No route matches "/javascript/raphael-min.js"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.3ms) - - -Started GET "/css/tryhaskell.css" for 127.0.0.1 at 2011-07-08 18:59:38 -0500 - -ActionController::RoutingError (No route matches "/css/tryhaskell.css"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 19:00:04 -0500 - Processing by TryrubyController#index as HTML -Rendered tryruby/index.html.erb within layouts/tryruby (1.6ms) -Completed 200 OK in 8ms (Views: 7.8ms | ActiveRecord: 0.0ms) - - -Started GET "/tutorials/intro" for 127.0.0.1 at 2011-07-08 19:00:05 -0500 - -ActionController::RoutingError (No route matches "/tutorials/intro"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.0ms) - - -Started GET "/tryruby/run?cmd=%21INIT%21IRB%21" for 127.0.0.1 at 2011-07-08 19:00:08 -0500 - Processing by TryrubyController#run as - Parameters: {"cmd"=>"!INIT!IRB!"} -Completed 500 Internal Server Error in 12ms - -NoMethodError (undefined method `type' for nil:NilClass): - app/controllers/tryruby_controller.rb:11:in `run' - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (3.5ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (11.3ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (28.2ms) - - -Started GET "/tryruby/run?cmd=2" for 127.0.0.1 at 2011-07-08 19:00:08 -0500 - Processing by TryrubyController#run as - Parameters: {"cmd"=>"2"} -Completed 500 Internal Server Error in 11ms - -NoMethodError (undefined method `type' for nil:NilClass): - app/controllers/tryruby_controller.rb:11:in `run' - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.8ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (7.3ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (18.8ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 19:00:25 -0500 -DEPRECATION WARNING: config.action_view.debug_rjs will be removed in 3.1, from 3.1 onwards you will need to install prototype-rails to continue to use RJS templates . (called from service at /Users/sophrinix/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/webrick/httpserver.rb:111) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 19:03:47 -0500 - Processing by TryrubyController#index as HTML -Rendered tryruby/index.html.erb within layouts/tryruby (1.0ms) -Completed 200 OK in 5ms (Views: 4.8ms | ActiveRecord: 0.0ms) - - -Started GET "/tutorials/intro" for 127.0.0.1 at 2011-07-08 19:03:47 -0500 - -ActionController::RoutingError (No route matches "/tutorials/intro"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.2ms) - - -Started GET "/tryruby/run?cmd=%21INIT%21IRB%21" for 127.0.0.1 at 2011-07-08 19:03:52 -0500 - Processing by TryrubyController#run as - Parameters: {"cmd"=>"!INIT!IRB!"} -Completed 500 Internal Server Error in 2ms - -NoMethodError (undefined method `IRB!' for #): - app/controllers/tryruby_controller.rb:22:in `eval' - app/controllers/tryruby_controller.rb:22:in `eval' - app/controllers/tryruby_controller.rb:22:in `run_script' - app/controllers/tryruby_controller.rb:10:in `run' - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (1.4ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (3.8ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (10.3ms) - - -Started GET "/tryruby/run?cmd=2" for 127.0.0.1 at 2011-07-08 19:03:52 -0500 - Processing by TryrubyController#run as - Parameters: {"cmd"=>"2"} -Completed 500 Internal Server Error in 1ms - -NoMethodError (undefined method `type' for nil:NilClass): - app/controllers/tryruby_controller.rb:11:in `run' - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (1.5ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (3.5ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (10.8ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 19:04:56 -0500 - Processing by TryrubyController#index as HTML -Rendered tryruby/index.html.erb within layouts/tryruby (0.9ms) -Completed 200 OK in 4ms (Views: 3.9ms | ActiveRecord: 0.0ms) - - -Started GET "/tutorials/intro" for 127.0.0.1 at 2011-07-08 19:04:56 -0500 - -ActionController::RoutingError (No route matches "/tutorials/intro"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.2ms) - - -Started GET "/tryruby/run?cmd=%21INIT%21IRB%21" for 127.0.0.1 at 2011-07-08 19:04:58 -0500 - Processing by TryrubyController#run as - Parameters: {"cmd"=>"!INIT!IRB!"} -Completed 500 Internal Server Error in 1ms - -NoMethodError (undefined method `IRB!' for #): - app/controllers/tryruby_controller.rb:9:in `eval' - app/controllers/tryruby_controller.rb:9:in `eval' - app/controllers/tryruby_controller.rb:9:in `run' - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (1.4ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (3.5ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (9.2ms) - - -Started GET "/tryruby/run?cmd=2" for 127.0.0.1 at 2011-07-08 19:04:58 -0500 - Processing by TryrubyController#run as - Parameters: {"cmd"=>"2"} -Completed 200 OK in 1ms (Views: 0.2ms | ActiveRecord: 0.0ms) - - -Started GET "/tryruby/run?cmd=time" for 127.0.0.1 at 2011-07-08 19:05:00 -0500 - Processing by TryrubyController#run as - Parameters: {"cmd"=>"time"} -Completed 500 Internal Server Error in 1ms - -NameError (undefined local variable or method `time' for #): - app/controllers/tryruby_controller.rb:9:in `eval' - app/controllers/tryruby_controller.rb:9:in `eval' - app/controllers/tryruby_controller.rb:9:in `run' - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.7ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (3.4ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (10.6ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 19:05:07 -0500 - Processing by TryrubyController#index as HTML -Rendered tryruby/index.html.erb within layouts/tryruby (0.9ms) -Completed 200 OK in 5ms (Views: 4.2ms | ActiveRecord: 0.0ms) - - -Started GET "/tutorials/intro" for 127.0.0.1 at 2011-07-08 19:05:08 -0500 - -ActionController::RoutingError (No route matches "/tutorials/intro"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.1ms) - - -Started GET "/tryruby/run?cmd=%21INIT%21IRB%21" for 127.0.0.1 at 2011-07-08 19:05:09 -0500 - Processing by TryrubyController#run as - Parameters: {"cmd"=>"!INIT!IRB!"} -Completed 500 Internal Server Error in 1ms - -NoMethodError (undefined method `IRB!' for #): - app/controllers/tryruby_controller.rb:9:in `eval' - app/controllers/tryruby_controller.rb:9:in `eval' - app/controllers/tryruby_controller.rb:9:in `run' - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (1.4ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (4.6ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (10.4ms) - - -Started GET "/tryruby/run?cmd=1" for 127.0.0.1 at 2011-07-08 19:05:09 -0500 - Processing by TryrubyController#run as - Parameters: {"cmd"=>"1"} -Completed 200 OK in 1ms (Views: 0.3ms | ActiveRecord: 0.0ms) - - -Started GET "/tryruby/run?cmd=1%20%2B%206" for 127.0.0.1 at 2011-07-08 19:05:11 -0500 - Processing by TryrubyController#run as - Parameters: {"cmd"=>"1 + 6"} -Completed 200 OK in 1ms (Views: 0.2ms | ActiveRecord: 0.0ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 19:05:24 -0500 - Processing by TryrubyController#index as HTML -Rendered tryruby/index.html.erb within layouts/tryruby (1.9ms) -Completed 200 OK in 8ms (Views: 7.8ms | ActiveRecord: 0.0ms) - - -Started GET "/tutorials/intro" for 127.0.0.1 at 2011-07-08 19:05:24 -0500 - -ActionController::RoutingError (No route matches "/tutorials/intro"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.2ms) - - -Started GET "/tryruby/run?cmd=%21INIT%21IRB%21" for 127.0.0.1 at 2011-07-08 19:05:26 -0500 - Processing by TryrubyController#run as - Parameters: {"cmd"=>"!INIT!IRB!"} -Completed 500 Internal Server Error in 3ms - -NoMethodError (undefined method `IRB!' for #): - app/controllers/tryruby_controller.rb:9:in `eval' - app/controllers/tryruby_controller.rb:9:in `eval' - app/controllers/tryruby_controller.rb:9:in `run' - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.7ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (7.1ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (18.1ms) - - -Started GET "/tryruby/run?cmd=1" for 127.0.0.1 at 2011-07-08 19:05:26 -0500 - Processing by TryrubyController#run as - Parameters: {"cmd"=>"1"} -Completed 500 Internal Server Error in 78ms - -ActionView::MissingTemplate (Missing template tryruby/run with {:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=>[:html, :text, :js, :css, :ics, :csv, :xml, :rss, :atom, :yaml, :multipart_form, :url_encoded_form, :json], :locale=>[:en, :en]} in view paths "/Users/sophrinix/Desktop/herokutr/TryRuby/app/views", "/Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/devise-1.4.2/app/views"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/missing_template.erb within rescues/layout (1.7ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 19:05:47 -0500 - Processing by TryrubyController#index as HTML -Rendered tryruby/index.html.erb within layouts/tryruby (1.5ms) -Completed 200 OK in 8ms (Views: 7.5ms | ActiveRecord: 0.0ms) - - -Started GET "/tutorials/intro" for 127.0.0.1 at 2011-07-08 19:05:48 -0500 - -ActionController::RoutingError (No route matches "/tutorials/intro"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.5ms) - - -Started GET "/tryruby/run?cmd=%21INIT%21IRB%21" for 127.0.0.1 at 2011-07-08 19:05:49 -0500 - Processing by TryrubyController#run as - Parameters: {"cmd"=>"!INIT!IRB!"} -Completed 500 Internal Server Error in 3ms - -NoMethodError (undefined method `IRB!' for #): - app/controllers/tryruby_controller.rb:9:in `eval' - app/controllers/tryruby_controller.rb:9:in `eval' - app/controllers/tryruby_controller.rb:9:in `run' - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.8ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (6.7ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (17.7ms) - - -Started GET "/tryruby/run?cmd=2" for 127.0.0.1 at 2011-07-08 19:05:49 -0500 - Processing by TryrubyController#run as - Parameters: {"cmd"=>"2"} -Completed 500 Internal Server Error in 2ms - -NoMethodError (undefined method `model_name' for Fixnum:Class): - app/controllers/tryruby_controller.rb:9:in `run' - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.8ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (7.3ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (18.3ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 19:06:06 -0500 - Processing by TryrubyController#index as HTML -Rendered tryruby/index.html.erb within layouts/tryruby (1.5ms) -Completed 200 OK in 8ms (Views: 7.2ms | ActiveRecord: 0.0ms) - - -Started GET "/tutorials/intro" for 127.0.0.1 at 2011-07-08 19:06:06 -0500 - -ActionController::RoutingError (No route matches "/tutorials/intro"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.9ms) - - -Started GET "/tryruby/run?cmd=%21INIT%21IRB%21" for 127.0.0.1 at 2011-07-08 19:06:07 -0500 - Processing by TryrubyController#run as - Parameters: {"cmd"=>"!INIT!IRB!"} -Completed 500 Internal Server Error in 3ms - -NoMethodError (undefined method `IRB!' for #): - app/controllers/tryruby_controller.rb:9:in `eval' - app/controllers/tryruby_controller.rb:9:in `eval' - app/controllers/tryruby_controller.rb:9:in `run' - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (90.0ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (6.7ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (105.1ms) - - -Started GET "/tryruby/run?cmd=1" for 127.0.0.1 at 2011-07-08 19:06:07 -0500 - Processing by TryrubyController#run as - Parameters: {"cmd"=>"1"} -Completed 500 Internal Server Error in 17ms - -ActionView::MissingTemplate (Missing template tryruby/run with {:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=>[:html, :text, :js, :css, :ics, :csv, :xml, :rss, :atom, :yaml, :multipart_form, :url_encoded_form, :json], :locale=>[:en, :en]} in view paths "/Users/sophrinix/Desktop/herokutr/TryRuby/app/views", "/Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/devise-1.4.2/app/views"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/missing_template.erb within rescues/layout (1.7ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 19:17:57 -0500 - Processing by TryrubyController#index as HTML -Rendered tryruby/index.html.erb within layouts/tryruby (1.5ms) -Completed 200 OK in 8ms (Views: 7.3ms | ActiveRecord: 0.0ms) - - -Started GET "/tutorials/intro" for 127.0.0.1 at 2011-07-08 19:17:58 -0500 - -ActionController::RoutingError (No route matches "/tutorials/intro"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) - - -Started GET "/tryruby/run?cmd=%21INIT%21IRB%21" for 127.0.0.1 at 2011-07-08 19:18:00 -0500 - Processing by TryrubyController#run as - Parameters: {"cmd"=>"!INIT!IRB!"} -Completed 500 Internal Server Error in 3ms - -NoMethodError (undefined method `IRB!' for #): - app/controllers/tryruby_controller.rb:9:in `eval' - app/controllers/tryruby_controller.rb:9:in `eval' - app/controllers/tryruby_controller.rb:9:in `run' - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.8ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (8.8ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (20.3ms) - - -Started GET "/tryruby/run?cmd=1" for 127.0.0.1 at 2011-07-08 19:18:00 -0500 - Processing by TryrubyController#run as - Parameters: {"cmd"=>"1"} -Completed 500 Internal Server Error in 17ms - -ActionView::MissingTemplate (Missing template tryruby/run with {:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=>[:html, :text, :js, :css, :ics, :csv, :xml, :rss, :atom, :yaml, :multipart_form, :url_encoded_form, :json], :locale=>[:en, :en]} in view paths "/Users/sophrinix/Desktop/herokutr/TryRuby/app/views", "/Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/devise-1.4.2/app/views"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/missing_template.erb within rescues/layout (1.6ms) - - -Started GET "/" for 127.0.0.1 at 2011-07-08 19:18:23 -0500 - Processing by TryrubyController#index as HTML -Rendered tryruby/index.html.erb within layouts/tryruby (1.5ms) -Completed 200 OK in 9ms (Views: 8.2ms | ActiveRecord: 0.0ms) - - -Started GET "/tutorials/intro" for 127.0.0.1 at 2011-07-08 19:18:23 -0500 - -ActionController::RoutingError (No route matches "/tutorials/intro"): - - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (2.1ms) - - -Started GET "/tryruby/run?cmd=%21INIT%21IRB%21" for 127.0.0.1 at 2011-07-08 19:18:25 -0500 - Processing by TryrubyController#run as - Parameters: {"cmd"=>"!INIT!IRB!"} -Completed 500 Internal Server Error in 3ms - -NoMethodError (undefined method `IRB!' for #): - app/controllers/tryruby_controller.rb:9:in `eval' - app/controllers/tryruby_controller.rb:9:in `eval' - app/controllers/tryruby_controller.rb:9:in `run' - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (3.4ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (6.8ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (18.9ms) - - -Started GET "/tryruby/run?cmd=1" for 127.0.0.1 at 2011-07-08 19:18:25 -0500 - Processing by TryrubyController#run as - Parameters: {"cmd"=>"1"} -Rendered tryruby/run.html.erb within layouts/tryruby (1.6ms) -Completed 200 OK in 18ms (Views: 16.9ms | ActiveRecord: 0.0ms) - - -Started GET "/tryruby/run?cmd=hi" for 127.0.0.1 at 2011-07-08 19:18:34 -0500 - Processing by TryrubyController#run as - Parameters: {"cmd"=>"hi"} -Completed 500 Internal Server Error in 3ms - -NameError (undefined local variable or method `hi' for #): - app/controllers/tryruby_controller.rb:9:in `eval' - app/controllers/tryruby_controller.rb:9:in `eval' - app/controllers/tryruby_controller.rb:9:in `run' - -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.9ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (7.1ms) -Rendered /Users/sophrinix/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (18.5ms) diff --git a/log/production.log b/log/production.log deleted file mode 100644 index e69de29..0000000 diff --git a/log/server.log b/log/server.log deleted file mode 100644 index e69de29..0000000 diff --git a/log/test.log b/log/test.log deleted file mode 100644 index e69de29..0000000 diff --git a/non-rack-legacy/public/tmp/index.html b/non-rack-legacy/public/tmp/index.html deleted file mode 100755 index e933af9..0000000 --- a/non-rack-legacy/public/tmp/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -

                  you shouldn't be here.. kicking you out!

                  - - From 1700a47cb7bed320ad0780be8c26239eb28d5664 Mon Sep 17 00:00:00 2001 From: zhangnan Date: Wed, 26 Oct 2011 10:08:00 +0800 Subject: [PATCH 14/16] =?UTF-8?q?=E6=9B=B4=E6=8D=A2tryruby=E7=9A=84google?= =?UTF-8?q?=20analytics=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/layouts/application.html.erb | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 6de65d3..73383b4 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -159,8 +159,15 @@ putting my code though that. Expect This to become it's own .js file in the futu Replace the UA code if your hosting your own copy -->