Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

reorganized directory structure

  • Loading branch information...
commit f9304707fe84188f607cfbc45c76b5d19d75c174 1 parent 6c472da
@georgi authored
Showing with 516 additions and 848 deletions.
  1. +76 −0 assets/print.css
  2. +91 −0 assets/styles.css
  3. +14 −8 bin/shinmun
  4. +16 −0 config.ru
  5. +0 −41 example/Rakefile
  6. BIN  example/assets/images/favicon.ico
  7. BIN  example/assets/images/loading.gif
  8. +0 −32 example/assets/javascripts/1-jquery.min.js
  9. +0 −5 example/assets/javascripts/2-jquery-form.min.js
  10. +0 −45 example/assets/javascripts/3-comments.js
  11. +0 −13 example/assets/javascripts/4-coderay.js
  12. +0 −76 example/assets/print.css
  13. +0 −23 example/assets/stylesheets/1-reset.css
  14. +0 −40 example/assets/stylesheets/2-typo.css
  15. +0 −23 example/assets/stylesheets/3-table.css
  16. +0 −15 example/assets/stylesheets/4-article.css
  17. +0 −20 example/assets/stylesheets/5-comments.css
  18. +0 −25 example/assets/stylesheets/6-diff.css
  19. +0 −33 example/assets/stylesheets/7-blog.css
  20. +0 −6 example/config.ru
  21. +0 −10 example/config/blog.yml
  22. +0 −7 example/pages/about.md
  23. +0 −90 example/templates/_comment_form.rhtml
  24. +0 −10 example/templates/_pagination.rhtml
  25. +0 −1  example/templates/comments.rhtml
  26. +0 −82 example/templates/layout.rhtml
  27. +102 −97 lib/shinmun/blog.rb
  28. +1 −1  lib/shinmun/comment.rb
  29. +1 −1  lib/shinmun/helpers.rb
  30. +4 −7 lib/shinmun/post_handler.rb
  31. +22 −36 lib/shinmun/routes.rb
  32. +4 −0 templates/404.rhtml
  33. +19 −0 templates/_comment_form.rhtml
  34. +1 −1  {example → }/templates/_comments.rhtml
  35. +0 −1  {example → }/templates/archive.rhtml
  36. +1 −2  {example → }/templates/category.rhtml
  37. 0  {example → }/templates/category.rxml
  38. +0 −1  {example → }/templates/index.rhtml
  39. 0  {example → }/templates/index.rxml
  40. +44 −0 templates/layout.rhtml
  41. +0 −2  {example → }/templates/page.rhtml
  42. +6 −21 {example → }/templates/post.rhtml
  43. +32 −73 test/blog_spec.rb
  44. +11 −0 test/templates/templates/_comments.rhtml
  45. +6 −0 test/templates/templates/archive.rhtml
  46. +6 −0 test/templates/templates/category.rhtml
  47. +20 −0 test/templates/templates/category.rxml
  48. +4 −0 test/templates/templates/index.rhtml
  49. +21 −0 test/templates/templates/index.rxml
  50. +9 −0 test/templates/templates/layout.rhtml
  51. +2 −0  test/templates/templates/page.rhtml
  52. +3 −0  test/templates/templates/post.rhtml
View
76 assets/print.css
@@ -0,0 +1,76 @@
+body {
+ line-height:1.5;
+ font-family:"Helvetica Neue", "Lucida Grande", Arial, Verdana, sans-serif;
+ color:#000;
+ background:none;
+ font-size:10pt;
+}
+
+.container {
+ background:none;
+}
+
+h1,h2,h3,h4,h5,h6 {
+ font-family:"Helvetica Neue", Arial, "Lucida Grande", sans-serif;
+}
+
+code {
+ font:.9em "Courier New", Monaco, Courier, monospace;
+}
+
+img {
+ float:left;
+ margin:1.5em 1.5em 1.5em 0;
+}
+
+a img {
+ border:none;
+}
+
+p img.top {
+ margin-top:0;
+}
+
+hr {
+ background:#ccc;
+ color:#ccc;
+ width:100%;
+ height:2px;
+ border:none;
+ margin:2em 0;
+ padding:0;
+}
+
+blockquote {
+ font-style:italic;
+ font-size:.9em;
+ margin:1.5em;
+ padding:1em;
+}
+
+.small {
+ font-size:.9em;
+}
+
+.large {
+ font-size:1.1em;
+}
+
+.quiet {
+ color:#999;
+}
+
+.hide {
+ display:none;
+}
+
+a:link,a:visited {
+ background:transparent;
+ font-weight:700;
+ text-decoration:underline;
+}
+
+a:link:after,a:visited:after {
+ content:" (" attr(href) ") ";
+ font-size:90%;
+}
View
91 assets/styles.css
@@ -0,0 +1,91 @@
+html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p,
+blockquote, pre, a, abbr, acronym, address, del, dfn, img,
+q, fieldset, form, label, legend, table,
+caption, tbody, tfoot, thead, tr, th, td {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font-weight: inherit;
+ font-style: inherit;
+ font-size: 100%;
+ font-family: inherit;
+ vertical-align: baseline;
+}
+
+body {
+ line-height: 1.5;
+ background: #fff;
+ margin:0.5em 0;
+ font-size: 80%;
+ color: #222;
+ font-family: Arial, sans-serif;
+}
+
+p {
+ margin-bottom: 1em;
+}
+
+a {
+ color: #444;
+}
+
+a:visited {
+ color: #444;
+}
+
+h1 a, h2 a, h3 a, h4 a, h5 a, h6 a {
+ text-decoration: none;
+}
+
+h1 { font-size: 2em; line-height: 1; margin-top: 1em; margin-bottom: 1em; }
+h2 { font-size: 1.5em; margin-top: 0.75em; margin-bottom: 0.75em; }
+h3 { font-size: 1.3em; line-height: 1; margin-top: 1.7em; margin-bottom: 1em; }
+h4 { font-size: 1.2em; line-height: 1.25; margin-top: 1.25em; margin-bottom: 1.25em; }
+h5 { font-size: 1em; font-weight: bold; margin-bottom: 1.5em; }
+h6 { font-size: 1em; font-weight: bold; }
+
+hr {
+ height: 1px;
+ color: #ccc;
+}
+
+.container {
+ width: 600px;
+ margin: 0 auto;
+}
+
+.article {
+}
+
+.article h2 {
+ margin-top:0px;
+}
+
+.article .date {
+ color: #666;
+}
+
+.article .tags a {
+ color: #69c;
+ text-decoration: none;
+}
+
+.comments {
+ margin-bottom: 2em;
+}
+
+.comments .comment, .preview .comment {
+ margin-top: 2em;
+ border: 1px solid #ccc;
+}
+
+.comments .comment .top, .preview .comment .top {
+ background: #F0F0F0;
+ color: #333;
+ padding: 3px 5px;
+}
+
+.comments .comment .body, .preview .comment .body {
+ background: #F8F8F8;
+ padding: 3px 5px;
+}
View
22 bin/shinmun
@@ -7,16 +7,22 @@ when 'init'
Shinmun::Blog.init ARGV[1]
when 'post'
- post = Shinmun::Post.new(:title => ARGV[1], :date => Date.today)
- FileUtils.mkpath(File.dirname(post.path))
- open(post.path, 'w') { |io| io.write post.dump }
- puts "created #{post.path}"
+ blog = Shinmun::Blog.new('.')
+ post = blog.create_post(:title => ARGV[1], :date => Date.today)
+ path = blog.post_file(post)
+
+ `git checkout #{path}`
+
+ exec "#{ENV['EDITOR']} #{path}"
when 'page'
- post = Shinmun::Post.new(:title => ARGV[1])
- FileUtils.mkpath(File.dirname(post.path))
- open(post.path, 'w') { |io| io.write post.dump }
- puts "created #{post.path}"
+ blog = Shinmun::Blog.new('.')
+ post = blog.create_page(:title => ARGV[1])
+ path = blog.post_file(post)
+
+ `git checkout #{path}`
+
+ exec "#{ENV['EDITOR']} #{path}"
else
puts "Usage:"
View
16 config.ru
@@ -0,0 +1,16 @@
+require 'shinmun'
+
+use Rack::Session::Cookie
+use Rack::Reloader
+
+blog = Shinmun::Blog.new(File.dirname(__FILE__))
+
+blog.config = {
+ :language => 'en',
+ :title => "Blog Title",
+ :author => "The Author",
+ :categories => ["Ruby", "Javascript"],
+ :description => "Blog description"
+}
+
+run blog
View
41 example/Rakefile
@@ -1,41 +0,0 @@
-require 'shinmun'
-
-blog = Shinmun::Blog.new
-
-task :index do
- blog.write "index.html", "index.rhtml"
- blog.write "index.rss", "index.rxml"
-end
-
-blog.pages.each do |page|
- task page.path do
- blog.write page.path, "page.rhtml", :page => page
- end
-end
-
-blog.posts.each do |post|
- task "#{post.path}.html" do
- blog.write "#{post.path}.html", "post.rhtml", :post => post
- end
-end
-
-blog.archives.each do |year, month|
- task "#{year}/#{month}" do
- blog.write "#{year}/#{month}/index.html", "archive.rhtml", :year => year, :month => month
- end
-end
-
-blog.categories.each do |name|
- category = blog.find_category(name)
- task "categories/#{category[:permalink]}" do
- blog.write "categories/#{category[:permalink]}.html", "category.rhtml", category
- blog.write "categories/#{category[:permalink]}.rss", "category.rxml", category
- end
-end
-
-task :pages => blog.pages.map { |p| p.path }
-task :posts => blog.posts.map { |p| p.path }
-task :archives => blog.archives.map { |y,m| "#{y}/#{m}" }
-task :categories => blog.categories.map { |name| "categories/#{blog.urlify name}" }
-
-task :default => [:index, :pages, :posts, :archives, :categories]
View
BIN  example/assets/images/favicon.ico
Binary file not shown
View
BIN  example/assets/images/loading.gif
Deleted file not rendered
View
32 example/assets/javascripts/1-jquery.min.js
@@ -1,32 +0,0 @@
-/*
- * jQuery 1.2.6 - 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-05-24 14:22:17 -0400 (Sat, 24 May 2008) $
- * $Rev: 5685 $
- */
-(function(){var _jQuery=window.jQuery,_$=window.$;var jQuery=window.jQuery=window.$=function(selector,context){return new jQuery.fn.init(selector,context);};var quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/,isSimple=/^.[^:#\[\.]*$/,undefined;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;return this;}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);return jQuery(elem);}selector=[];}}else
-return jQuery(context).find(selector);}else if(jQuery.isFunction(selector))return jQuery(document)[jQuery.fn.ready?"ready":"load"](selector);return this.setArray(jQuery.makeArray(selector));},jquery:"1.2.6",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;return jQuery.inArray(elem&&elem.jquery?elem[0]:elem,this);},attr:function(name,value,type){var options=name;if(name.constructor==String)if(value===undefined)return this[0]&&jQuery[type||"attr"](this[0],name);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 this.pushStack(jQuery.unique(jQuery.merge(this.get(),typeof selector=='string'?jQuery(selector):jQuery.makeArray(selector))));},is:function(selector){return!!selector&&jQuery.multiFilter(selector,this).length>0;},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<max;i++){var option=options[i];if(option.selected){value=jQuery.browser.msie&&!option.attributes.value.specified?option.text:option.value;if(one)return value;values.push(value);}}return values;}else
-return(this[0].value||"").replace(/\r/g,"");}return undefined;}if(value.constructor==Number)value+='';return this.each(function(){if(this.nodeType!=1)return;if(value.constructor==Array&&/radio|checkbox/.test(this.type))this.checked=(jQuery.inArray(this.value,value)>=0||jQuery.inArray(this.name,value)>=0);else if(jQuery.nodeName(this,"select")){var values=jQuery.makeArray(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[0]?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===undefined){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data===undefined&&this.length)data=jQuery.data(this[0],key);return data===undefined&&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.fn.init.prototype=jQuery.fn;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);}function now(){return+new Date;}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==i){target=this;--i;}for(;i<length;i++)if((options=arguments[i])!=null)for(var name in options){var src=target[name],copy=options[name];if(target===copy)continue;if(deep&&copy&&typeof copy=="object"&&!copy.nodeType)target[name]=jQuery.extend(deep,src||(copy.length!=null?[]:{}),copy);else if(copy!==undefined)target[name]=copy;}return target;};var expando="jQuery"+now(),uuid=0,windowData={},exclude=/z-?index|font-?weight|opacity|zoom|line-?height/i,defaultView=document.defaultView||{};jQuery.extend({noConflict:function(deep){window.$=_$;if(deep)window.jQuery=_jQuery;return jQuery;},isFunction:function(fn){return!!fn&&typeof fn!="string"&&!fn.nodeName&&fn.constructor!=Array&&/^[\s[]?function/.test(fn+"");},isXMLDoc:function(elem){return elem.documentElement&&!elem.body||elem.tagName&&elem.ownerDocument&&!elem.ownerDocument.body;},globalEval:function(data){data=jQuery.trim(data);if(data){var head=document.getElementsByTagName("head")[0]||document.documentElement,script=document.createElement("script");script.type="text/javascript";if(jQuery.browser.msie)script.text=data;else
-script.appendChild(document.createTextNode(data));head.insertBefore(script,head.firstChild);head.removeChild(script);}},nodeName:function(elem,name){return elem.nodeName&&elem.nodeName.toUpperCase()==name.toUpperCase();},cache:{},data:function(elem,name,data){elem=elem==window?windowData:elem;var id=elem[expando];if(!id)id=elem[expando]=++uuid;if(name&&!jQuery.cache[id])jQuery.cache[id]={};if(data!==undefined)jQuery.cache[id][name]=data;return name?jQuery.cache[id][name]:id;},removeData:function(elem,name){elem=elem==window?windowData:elem;var id=elem[expando];if(name){if(jQuery.cache[id]){delete jQuery.cache[id][name];name="";for(name in jQuery.cache[id])break;if(!name)jQuery.removeData(elem);}}else{try{delete elem[expando];}catch(e){if(elem.removeAttribute)elem.removeAttribute(expando);}delete jQuery.cache[id];}},each:function(object,callback,args){var name,i=0,length=object.length;if(args){if(length==undefined){for(name in object)if(callback.apply(object[name],args)===false)break;}else
-for(;i<length;)if(callback.apply(object[i++],args)===false)break;}else{if(length==undefined){for(name in object)if(callback.call(object[name],name,object[name])===false)break;}else
-for(var value=object[0];i<length&&callback.call(value,i,value)!==false;value=object[++i]){}}return object;},prop:function(elem,value,type,i,name){if(jQuery.isFunction(value))value=value.call(elem,i);return value&&value.constructor==Number&&type=="curCSS"&&!exclude.test(name)?value+"px":value;},className:{add:function(elem,classNames){jQuery.each((classNames||"").split(/\s+/),function(i,className){if(elem.nodeType==1&&!jQuery.className.has(elem.className,className))elem.className+=(elem.className?" ":"")+className;});},remove:function(elem,classNames){if(elem.nodeType==1)elem.className=classNames!=undefined?jQuery.grep(elem.className.split(/\s+/),function(className){return!jQuery.className.has(classNames,className);}).join(" "):"";},has:function(elem,className){return jQuery.inArray(className,(elem.className||elem).toString().split(/\s+/))>-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,style=elem.style;function color(elem){if(!jQuery.browser.safari)return false;var ret=defaultView.getComputedStyle(elem,null);return!ret||ret.getPropertyValue("color")=="";}if(name=="opacity"&&jQuery.browser.msie){ret=jQuery.attr(style,"opacity");return ret==""?"1":ret;}if(jQuery.browser.opera&&name=="display"){var save=style.outline;style.outline="0 solid black";style.outline=save;}if(name.match(/float/i))name=styleFloat;if(!force&&style&&style[name])ret=style[name];else if(defaultView.getComputedStyle){if(name.match(/float/i))name="float";name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var computedStyle=defaultView.getComputedStyle(elem,null);if(computedStyle&&!color(elem))ret=computedStyle.getPropertyValue(name);else{var swap=[],stack=[],a=elem,i=0;for(;a&&color(a);a=a.parentNode)stack.unshift(a);for(;i<stack.length;i++)if(color(stack[i])){swap[i]=stack[i].style.display;stack[i].style.display="block";}ret=name=="display"&&swap[stack.length-1]!=null?"none":(computedStyle&&computedStyle.getPropertyValue(name))||"";for(i=0;i<swap.length;i++)if(swap[i]!=null)stack[i].style.display=swap[i];}if(name=="opacity"&&ret=="")ret="1";}else if(elem.currentStyle){var camelCase=name.replace(/\-(\w)/g,function(all,letter){return letter.toUpperCase();});ret=elem.currentStyle[name]||elem.currentStyle[camelCase];if(!/^\d+(px)?$/i.test(ret)&&/^\d/.test(ret)){var left=style.left,rsLeft=elem.runtimeStyle.left;elem.runtimeStyle.left=elem.currentStyle.left;style.left=ret||0;ret=style.pixelLeft+"px";style.left=left;elem.runtimeStyle.left=rsLeft;}}return ret;},clean:function(elems,context){var ret=[];context=context||document;if(typeof context.createElement=='undefined')context=context.ownerDocument||context[0]&&context[0].ownerDocument||document;jQuery.each(elems,function(i,elem){if(!elem)return;if(elem.constructor==Number)elem+='';if(typeof elem=="string"){elem=elem.replace(/(<(\w+)[^>]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+"></"+tag+">";});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("<opt")&&[1,"<select multiple='multiple'>","</select>"]||!tags.indexOf("<leg")&&[1,"<fieldset>","</fieldset>"]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"<table>","</table>"]||!tags.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!tags.indexOf("<td")||!tags.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||!tags.indexOf("<col")&&[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]||jQuery.browser.msie&&[1,"div<div>","</div>"]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--)div=div.lastChild;if(jQuery.browser.msie){var tbody=!tags.indexOf("<table")&&tags.indexOf("<tbody")<0?div.firstChild&&div.firstChild.childNodes:wrap[1]=="<table>"&&tags.indexOf("<tbody")<0?div.childNodes:[];for(var j=tbody.length-1;j>=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 notxml=!jQuery.isXMLDoc(elem),set=value!==undefined,msie=jQuery.browser.msie;name=notxml&&jQuery.props[name]||name;if(elem.tagName){var special=/href|src|style/.test(name);if(name=="selected"&&jQuery.browser.safari)elem.parentNode.selectedIndex;if(name in elem&&notxml&&!special){if(set){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode)throw"type property can't be changed";elem[name]=value;}if(jQuery.nodeName(elem,"form")&&elem.getAttributeNode(name))return elem.getAttributeNode(name).nodeValue;return elem[name];}if(msie&&notxml&&name=="style")return jQuery.attr(elem.style,"cssText",value);if(set)elem.setAttribute(name,""+value);var attr=msie&&notxml&&special?elem.getAttribute(name,2):elem.getAttribute(name);return attr===null?undefined:attr;}if(msie&&name=="opacity"){if(set){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(value)+''=="NaN"?"":"alpha(opacity="+value*100+")");}return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100)+'':"";}name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase();});if(set)elem[name]=value;return elem[name];},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"");},makeArray:function(array){var ret=[];if(array!=null){var i=array.length;if(i==null||array.split||array.setInterval||array.call)ret[0]=array;else
-while(i)ret[--i]=array[i];}return ret;},inArray:function(elem,array){for(var i=0,length=array.length;i<length;i++)if(array[i]===elem)return i;return-1;},merge:function(first,second){var i=0,elem,pos=first.length;if(jQuery.browser.msie){while(elem=second[i++])if(elem.nodeType!=8)first[pos++]=elem;}else
-while(elem=second[i++])first[pos++]=elem;return first;},unique:function(array){var ret=[],done={};try{for(var i=0,length=array.length;i<length;i++){var id=jQuery.data(array[i]);if(!done[id]){done[id]=true;ret.push(array[i]);}}}catch(e){ret=array;}return ret;},grep:function(elems,callback,inv){var ret=[];for(var i=0,length=elems.length;i<length;i++)if(!inv!=!callback(elems[i],i))ret.push(elems[i]);return ret;},map:function(elems,callback){var ret=[];for(var i=0,length=elems.length;i<length;i++){var value=callback(elems[i],i);if(value!=null)ret[ret.length]=value;}return ret.concat.apply([],ret);}});var userAgent=navigator.userAgent.toLowerCase();jQuery.browser={version:(userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[])[1],safari:/webkit/.test(userAgent),opera:/opera/.test(userAgent),msie:/msie/.test(userAgent)&&!/opera/.test(userAgent),mozilla:/mozilla/.test(userAgent)&&!/(compatible|webkit)/.test(userAgent)};var styleFloat=jQuery.browser.msie?"styleFloat":"cssFloat";jQuery.extend({boxModel:!jQuery.browser.msie||document.compatMode=="CSS1Compat",props:{"for":"htmlFor","class":"className","float":styleFloat,cssFloat:styleFloat,styleFloat:styleFloat,readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing"}});jQuery.each({parent:function(elem){return elem.parentNode;},parents:function(elem){return jQuery.dir(elem,"parentNode");},next:function(elem){return jQuery.nth(elem,2,"nextSibling");},prev:function(elem){return jQuery.nth(elem,2,"previousSibling");},nextAll:function(elem){return jQuery.dir(elem,"nextSibling");},prevAll:function(elem){return jQuery.dir(elem,"previousSibling");},siblings:function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},children:function(elem){return jQuery.sibling(elem.firstChild);},contents:function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}},function(name,fn){jQuery.fn[name]=function(selector){var ret=jQuery.map(this,fn);if(selector&&typeof selector=="string")ret=jQuery.multiFilter(selector,ret);return this.pushStack(jQuery.unique(ret));};});jQuery.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(name,original){jQuery.fn[name]=function(){var args=arguments;return this.each(function(){for(var i=0,length=args.length;i<length;i++)jQuery(args[i])[original](this);});};});jQuery.each({removeAttr:function(name){jQuery.attr(this,name,"");if(this.nodeType==1)this.removeAttribute(name);},addClass:function(classNames){jQuery.className.add(this,classNames);},removeClass:function(classNames){jQuery.className.remove(this,classNames);},toggleClass:function(classNames){jQuery.className[jQuery.className.has(this,classNames)?"remove":"add"](this,classNames);},remove:function(selector){if(!selector||jQuery.filter(selector,[this]).r.length){jQuery("*",this).add(this).each(function(){jQuery.event.remove(this);jQuery.removeData(this);});if(this.parentNode)this.parentNode.removeChild(this);}},empty:function(){jQuery(">*",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");};});function num(elem,prop){return elem[0]&&parseInt(jQuery.curCSS(elem[0],prop,true),10)||0;}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 i<m[3]-0;},gt:function(a,i,m){return i>m[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,re=quickChild,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<rl;j++){var n=m=="~"||m=="+"?ret[j].nextSibling:ret[j].firstChild;for(;n;n=n.nextSibling)if(n.nodeType==1){var id=jQuery.data(n);if(m=="~"&&merge[id])break;if(!nodeName||n.nodeName.toUpperCase()==nodeName){if(m=="~")merge[id]=true;r.push(n);}if(m=="+")break;}}ret=r;t=jQuery.trim(t.replace(re,""));foundToken=true;}}if(t&&!foundToken){if(!t.indexOf(",")){if(context==ret[0])ret.shift();done=jQuery.merge(done,ret);r=ret=[context];t=" "+t.substr(1,t.length);}else{var re2=quickID;var m=re2.exec(t);if(m){m=[0,m[2],m[3],m[1]];}else{re2=quickClass;m=re2.exec(t);}m[2]=m[2].replace(/\\/g,"");var elem=ret[ret.length-1];if(m[1]=="#"&&elem&&elem.getElementById&&!jQuery.isXMLDoc(elem)){var oid=elem.getElementById(m[2]);if((jQuery.browser.msie||jQuery.browser.opera)&&oid&&typeof oid.id=="string"&&oid.id!=m[2])oid=jQuery('[@id="'+m[2]+'"]',elem)[0];ret=r=oid&&(!m[3]||jQuery.nodeName(oid,m[3]))?[oid]:[];}else{for(var i=0;ret[i];i++){var tag=m[1]=="#"&&m[3]?m[3]:m[1]!=""||m[0]==""?"*":m[2];if(tag=="*"&&ret[i].nodeName.toLowerCase()=="object")tag="param";r=jQuery.merge(r,ret[i].getElementsByTagName(tag));}if(m[1]==".")r=jQuery.classFilter(r,m[2]);if(m[1]=="#"){var tmp=[];for(var i=0;r[i];i++)if(r[i].getAttribute("id")==m[2]){tmp=[r[i]];break;}r=tmp;}ret=r;}t=t.replace(re2,"");}}if(t){var val=jQuery.filter(t,r);ret=r=val.r;t=jQuery.trim(val.t);}}if(t)ret=[];if(ret&&context==ret[0])ret.shift();done=jQuery.merge(done,ret);return done;},classFilter:function(r,m,not){m=" "+m+" ";var tmp=[];for(var i=0;r[i];i++){var pass=(" "+r[i].className+" ").indexOf(m)>=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<rl;i++){var a=r[i],z=a[jQuery.props[m[2]]||m[2]];if(z==null||/href|src|selected/.test(m[2]))z=jQuery.attr(a,m[2])||'';if((type==""&&!!z||type=="="&&z==m[5]||type=="!="&&z!=m[5]||type=="^="&&z&&!z.indexOf(m[5])||type=="$="&&z.substr(z.length-m[5].length)==m[5]||(type=="*="||type=="~=")&&z.indexOf(m[5])>=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<rl;i++){var node=r[i],parentNode=node.parentNode,id=jQuery.data(parentNode);if(!merge[id]){var c=1;for(var n=parentNode.firstChild;n;n=n.nextSibling)if(n.nodeType==1)n.nodeIndex=c++;merge[id]=true;}var add=false;if(first==0){if(node.nodeIndex==last)add=true;}else if((node.nodeIndex-last)%first==0&&(node.nodeIndex-last)/first>=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=[],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&&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)elem=window;if(!handler.guid)handler.guid=this.guid++;if(data!=undefined){var fn=handler;handler=this.proxy(fn,function(){return fn.apply(this,arguments);});handler.data=data;}var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){if(typeof jQuery!="undefined"&&!jQuery.event.triggered)return jQuery.event.handle.apply(arguments.callee.elem,arguments);});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({type:type,target:elem,preventDefault:function(){},stopPropagation:function(){},timeStamp:now()});data[0][expando]=true;}data[0].type=type;if(exclusive)data[0].exclusive=true;var handle=jQuery.data(elem,"handle");if(handle)val=handle.apply(elem,data);if((!fn||(jQuery.nodeName(elem,'a')&&type=="click"))&&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,ret,namespace,all,handlers;event=arguments[0]=jQuery.event.fix(event||window.event);namespace=event.type.split(".");event.type=namespace[0];namespace=namespace[1];all=!namespace&&!event.exclusive;handlers=(jQuery.data(this,"events")||{})[event.type];for(var j in handlers){var handler=handlers[j];if(all||handler.type==namespace){event.handler=handler;event.data=handler.data;ret=handler.apply(this,arguments);if(val!==false)val=ret;if(ret===false){event.preventDefault();event.stopPropagation();}}}return val;},fix:function(event){if(event[expando]==true)return event;var originalEvent=event;event={originalEvent:originalEvent};var 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 timeStamp toElement type view wheelDelta which".split(" ");for(var i=props.length;i;i--)event[props[i]]=originalEvent[props[i]];event[expando]=true;event.preventDefault=function(){if(originalEvent.preventDefault)originalEvent.preventDefault();originalEvent.returnValue=false;};event.stopPropagation=function(){if(originalEvent.stopPropagation)originalEvent.stopPropagation();originalEvent.cancelBubble=true;};event.timeStamp=event.timeStamp||now();if(!event.target)event.target=event.srcElement||document;if(event.target.nodeType==3)event.target=event.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;},proxy:function(fn,proxy){proxy.guid=fn.guid=fn.guid||proxy.guid||this.guid++;return proxy;},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;event.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;event.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){var one=jQuery.event.proxy(fn||data,function(event){jQuery(this).unbind(event,one);return(fn||data).apply(this,arguments);});return this.each(function(){jQuery.event.add(this,type,one,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){return this[0]&&jQuery.event.trigger(type,data,this[0],false,fn);},toggle:function(fn){var args=arguments,i=1;while(i<args.length)jQuery.event.proxy(fn,args[i++]);return this.click(jQuery.event.proxy(fn,function(event){this.lastToggle=(this.lastToggle||0)%i;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.call(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<document.styleSheets.length;i++)if(document.styleSheets[i].disabled){setTimeout(arguments.callee,0);return;}jQuery.ready();},false);if(jQuery.browser.safari){var numStyles;(function(){if(jQuery.isReady)return;if(document.readyState!="loaded"&&document.readyState!="complete"){setTimeout(arguments.callee,0);return;}if(numStyles===undefined)numStyles=jQuery("style, link[rel=stylesheet]").length;if(document.styleSheets.length!=numStyles){setTimeout(arguments.callee,0);return;}jQuery.ready();})();}jQuery.event.add(window,"load",jQuery.ready);}jQuery.each(("blur,focus,load,resize,scroll,unload,click,dblclick,"+"mousedown,mouseup,mousemove,mouseover,mouseout,change,select,"+"submit,keydown,keypress,keyup,error").split(","),function(i,name){jQuery.fn[name]=function(fn){return fn?this.bind(name,fn):this.trigger(name);};});var withinElement=function(event,elem){var parent=event.relatedTarget;while(parent&&parent!=elem)try{parent=parent.parentNode;}catch(error){parent=elem;}return parent==elem;};jQuery(window).bind("unload",function(){jQuery("*").add(document).unbind();});jQuery.fn.extend({_load:jQuery.fn.load,load:function(url,params,callback){if(typeof url!='string')return this._load(url);var off=url.indexOf(" ");if(off>=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("<div/>").append(res.responseText.replace(/<script(.|\s)*?\/script>/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=now();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:{url:location.href,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){s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));var jsonp,jsre=/=\?(&|$)/g,status,data,type=s.type.toUpperCase();if(s.data&&s.processData&&typeof s.data!="string")s.data=jQuery.param(s.data);if(s.dataType=="jsonp"){if(type=="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&&type=="GET"){var ts=now();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"");}if(s.data&&type=="GET"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null;}if(s.global&&!jQuery.active++)jQuery.event.trigger("ajaxStart");var remote=/^(?:\w+:)?\/\/([^\/?#]+)/;if(s.dataType=="script"&&type=="GET"&&remote.test(s.url)&&remote.exec(s.url)[1]!=location.host){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 xhr=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();if(s.username)xhr.open(type,s.url,s.async,s.username,s.password);else
-xhr.open(type,s.url,s.async);try{if(s.data)xhr.setRequestHeader("Content-Type",s.contentType);if(s.ifModified)xhr.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT");xhr.setRequestHeader("X-Requested-With","XMLHttpRequest");xhr.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default);}catch(e){}if(s.beforeSend&&s.beforeSend(xhr,s)===false){s.global&&jQuery.active--;xhr.abort();return false;}if(s.global)jQuery.event.trigger("ajaxSend",[xhr,s]);var onreadystatechange=function(isTimeout){if(!requestDone&&xhr&&(xhr.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null;}status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xhr)&&"error"||s.ifModified&&jQuery.httpNotModified(xhr,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xhr,s.dataType,s.dataFilter);}catch(e){status="parsererror";}}if(status=="success"){var modRes;try{modRes=xhr.getResponseHeader("Last-Modified");}catch(e){}if(s.ifModified&&modRes)jQuery.lastModified[s.url]=modRes;if(!jsonp)success();}else
-jQuery.handleError(s,xhr,status);complete();if(s.async)xhr=null;}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0)setTimeout(function(){if(xhr){xhr.abort();if(!requestDone)onreadystatechange("timeout");}},s.timeout);}try{xhr.send(s.data);}catch(e){jQuery.handleError(s,xhr,null,e);}if(!s.async)onreadystatechange();function success(){if(s.success)s.success(data,status);if(s.global)jQuery.event.trigger("ajaxSuccess",[xhr,s]);}function complete(){if(s.complete)s.complete(xhr,status);if(s.global)jQuery.event.trigger("ajaxComplete",[xhr,s]);if(s.global&&!--jQuery.active)jQuery.event.trigger("ajaxStop");}return xhr;},handleError:function(s,xhr,status,e){if(s.error)s.error(xhr,status,e);if(s.global)jQuery.event.trigger("ajaxError",[xhr,s,e]);},active:0,httpSuccess:function(xhr){try{return!xhr.status&&location.protocol=="file:"||(xhr.status>=200&&xhr.status<300)||xhr.status==304||xhr.status==1223||jQuery.browser.safari&&xhr.status==undefined;}catch(e){}return false;},httpNotModified:function(xhr,url){try{var xhrRes=xhr.getResponseHeader("Last-Modified");return xhr.status==304||xhrRes==jQuery.lastModified[url]||jQuery.browser.safari&&xhr.status==undefined;}catch(e){}return false;},httpData:function(xhr,type,filter){var ct=xhr.getResponseHeader("content-type"),xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0,data=xml?xhr.responseXML:xhr.responseText;if(xml&&data.documentElement.tagName=="parsererror")throw"parsererror";if(filter)data=filter(data,type);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(jQuery.isFunction(a[j])?a[j]():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.apply(this,arguments):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),p,hidden=jQuery(this).is(":hidden"),self=this;for(p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden)return opt.complete.call(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.call(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){type=type||"fx";var q=jQuery.data(elem,type+"queue");if(!q||array)q=jQuery.data(elem,type+"queue",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].call(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:jQuery.fx.speeds[opt.duration])||jQuery.fx.speeds.def;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false)jQuery(this).dequeue();if(jQuery.isFunction(opt.old))opt.old.call(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.call(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=now();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;i<timers.length;i++)if(!timers[i]())timers.splice(i--,1);if(!timers.length){clearInterval(jQuery.timerId);jQuery.timerId=null;}},13);}},show:function(){this.options.orig[this.prop]=jQuery.attr(this.elem.style,this.prop);this.options.show=true;this.custom(0,this.cur());if(this.prop=="width"||this.prop=="height")this.elem.style[this.prop]="1px";jQuery(this.elem).show();},hide:function(){this.options.orig[this.prop]=jQuery.attr(this.elem.style,this.prop);this.options.hide=true;this.custom(this.cur(),0);},step:function(gotoEnd){var t=now();if(gotoEnd||t>this.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)this.options.complete.call(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.extend(jQuery.fx,{speeds:{slow:600,fast:200,def:400},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),css=jQuery.curCSS,fixed=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&&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(css(parent,"display")))add(-parent.scrollLeft,-parent.scrollTop);if(mozilla&&css(parent,"overflow")!="visible")border(parent);parent=parent.parentNode;}if((safari2&&(fixed||css(offsetChild,"position")=="absolute"))||(mozilla&&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,10)||0;top+=parseInt(t,10)||0;}return results;};jQuery.fn.extend({position:function(){var left=0,top=0,results;if(this[0]){var offsetParent=this.offsetParent(),offset=this.offset(),parentOffset=/^body|html$/i.test(offsetParent[0].tagName)?{top:0,left:0}:offsetParent.offset();offset.top-=num(this,'marginTop');offset.left-=num(this,'marginLeft');parentOffset.top+=num(offsetParent,'borderTopWidth');parentOffset.left+=num(offsetParent,'borderLeftWidth');results={top:offset.top-parentOffset.top,left:offset.left-parentOffset.left};}return results;},offsetParent:function(){var offsetParent=this[0].offsetParent;while(offsetParent&&(!/^body|html$/i.test(offsetParent.tagName)&&jQuery.css(offsetParent,'position')=='static'))offsetParent=offsetParent.offsetParent;return jQuery(offsetParent);}});jQuery.each(['Left','Top'],function(i,name){var method='scroll'+name;jQuery.fn[method]=function(val){if(!this[0])return;return val!=undefined?this.each(function(){this==window||this==document?window.scrollTo(!i?val:jQuery(window).scrollLeft(),i?val:jQuery(window).scrollTop()):this[method]=val;}):this[0]==window||this[0]==document?self[i?'pageYOffset':'pageXOffset']||jQuery.boxModel&&document.documentElement[method]||document.body[method]:this[0][method];};});jQuery.each(["Height","Width"],function(i,name){var tl=i?"Left":"Top",br=i?"Right":"Bottom";jQuery.fn["inner"+name]=function(){return this[name.toLowerCase()]()+num(this,"padding"+tl)+num(this,"padding"+br);};jQuery.fn["outer"+name]=function(margin){return this["inner"+name]()+num(this,"border"+tl+"Width")+num(this,"border"+br+"Width")+(margin?num(this,"margin"+tl)+num(this,"margin"+br):0);};});})();
View
5 example/assets/javascripts/2-jquery-form.min.js
@@ -1,5 +0,0 @@
-(function($){$.fn.ajaxSubmit=function(options){if(typeof options=='function')options={success:options};options=$.extend({url:this.attr('action')||window.location.toString(),type:this.attr('method')||'GET'},options||{});var veto={};this.trigger('form-pre-serialize',[this,options,veto]);if(veto.veto)return this;var a=this.formToArray(options.semantic);if(options.data){options.extraData=options.data;for(var n in options.data)a.push({name:n,value:options.data[n]});}if(options.beforeSubmit&&options.beforeSubmit(a,this,options)===false)return this;this.trigger('form-submit-validate',[a,this,options,veto]);if(veto.veto)return this;var q=$.param(a);if(options.type.toUpperCase()=='GET'){options.url+=(options.url.indexOf('?')>=0?'&':'?')+q;options.data=null;}else
-options.data=q;var $form=this,callbacks=[];if(options.resetForm)callbacks.push(function(){$form.resetForm();});if(options.clearForm)callbacks.push(function(){$form.clearForm();});if(!options.dataType&&options.target){var oldSuccess=options.success||function(){};callbacks.push(function(data){$(options.target).html(data).each(oldSuccess,arguments);});}else if(options.success)callbacks.push(options.success);options.success=function(data,status){for(var i=0,max=callbacks.length;i<max;i++)callbacks[i](data,status,$form);};var files=$('input:file',this).fieldValue();var found=false;for(var j=0;j<files.length;j++)if(files[j])found=true;if(options.iframe||found){if($.browser.safari&&options.closeKeepAlive)$.get(options.closeKeepAlive,fileUpload);else
-fileUpload();}else
-$.ajax(options);this.trigger('form-submit-notify',[this,options]);return this;function fileUpload(){var form=$form[0];var opts=$.extend({},$.ajaxSettings,options);var id='jqFormIO'+(new Date().getTime());var $io=$('<iframe id="'+id+'" name="'+id+'" />');var io=$io[0];var op8=$.browser.opera&&window.opera.version()<9;if($.browser.msie||op8)io.src='javascript:false;document.write("");';$io.css({position:'absolute',top:'-1000px',left:'-1000px'});var xhr={responseText:null,responseXML:null,status:0,statusText:'n/a',getAllResponseHeaders:function(){},getResponseHeader:function(){},setRequestHeader:function(){}};var g=opts.global;if(g&&!$.active++)$.event.trigger("ajaxStart");if(g)$.event.trigger("ajaxSend",[xhr,opts]);var cbInvoked=0;var timedOut=0;setTimeout(function(){var t=$form.attr('target'),a=$form.attr('action');$form.attr({target:id,encoding:'multipart/form-data',enctype:'multipart/form-data',method:'POST',action:opts.url});if(opts.timeout)setTimeout(function(){timedOut=true;cb();},opts.timeout);var extraInputs=[];try{if(options.extraData)for(var n in options.extraData)extraInputs.push($('<input type="hidden" name="'+n+'" value="'+options.extraData[n]+'" />').appendTo(form)[0]);$io.appendTo('body');io.attachEvent?io.attachEvent('onload',cb):io.addEventListener('load',cb,false);form.submit();}finally{$form.attr('action',a);t?$form.attr('target',t):$form.removeAttr('target');$(extraInputs).remove();}},10);function cb(){if(cbInvoked++)return;io.detachEvent?io.detachEvent('onload',cb):io.removeEventListener('load',cb,false);var ok=true;try{if(timedOut)throw'timeout';var data,doc;doc=io.contentWindow?io.contentWindow.document:io.contentDocument?io.contentDocument:io.document;xhr.responseText=doc.body?doc.body.innerHTML:null;xhr.responseXML=doc.XMLDocument?doc.XMLDocument:doc;xhr.getResponseHeader=function(header){var headers={'content-type':opts.dataType};return headers[header];};if(opts.dataType=='json'||opts.dataType=='script'){var ta=doc.getElementsByTagName('textarea')[0];xhr.responseText=ta?ta.value:xhr.responseText;}else if(opts.dataType=='xml'&&!xhr.responseXML&&xhr.responseText!=null){xhr.responseXML=toXml(xhr.responseText);}data=$.httpData(xhr,opts.dataType);}catch(e){ok=false;$.handleError(opts,xhr,'error',e);}if(ok){opts.success(data,'success');if(g)$.event.trigger("ajaxSuccess",[xhr,opts]);}if(g)$.event.trigger("ajaxComplete",[xhr,opts]);if(g&&!--$.active)$.event.trigger("ajaxStop");if(opts.complete)opts.complete(xhr,ok?'success':'error');setTimeout(function(){$io.remove();xhr.responseXML=null;},100);};function toXml(s,doc){if(window.ActiveXObject){doc=new ActiveXObject('Microsoft.XMLDOM');doc.async='false';doc.loadXML(s);}else
-doc=(new DOMParser()).parseFromString(s,'text/xml');return(doc&&doc.documentElement&&doc.documentElement.tagName!='parsererror')?doc:null;};};};$.fn.ajaxForm=function(options){return this.ajaxFormUnbind().bind('submit.form-plugin',function(){$(this).ajaxSubmit(options);return false;}).each(function(){$(":submit,input:image",this).bind('click.form-plugin',function(e){var $form=this.form;$form.clk=this;if(this.type=='image'){if(e.offsetX!=undefined){$form.clk_x=e.offsetX;$form.clk_y=e.offsetY;}else if(typeof $.fn.offset=='function'){var offset=$(this).offset();$form.clk_x=e.pageX-offset.left;$form.clk_y=e.pageY-offset.top;}else{$form.clk_x=e.pageX-this.offsetLeft;$form.clk_y=e.pageY-this.offsetTop;}}setTimeout(function(){$form.clk=$form.clk_x=$form.clk_y=null;},10);});});};$.fn.ajaxFormUnbind=function(){this.unbind('submit.form-plugin');return this.each(function(){$(":submit,input:image",this).unbind('click.form-plugin');});};$.fn.formToArray=function(semantic){var a=[];if(this.length==0)return a;var form=this[0];var els=semantic?form.getElementsByTagName('*'):form.elements;if(!els)return a;for(var i=0,max=els.length;i<max;i++){var el=els[i];var n=el.name;if(!n)continue;if(semantic&&form.clk&&el.type=="image"){if(!el.disabled&&form.clk==el)a.push({name:n+'.x',value:form.clk_x},{name:n+'.y',value:form.clk_y});continue;}var v=$.fieldValue(el,true);if(v&&v.constructor==Array){for(var j=0,jmax=v.length;j<jmax;j++)a.push({name:n,value:v[j]});}else if(v!==null&&typeof v!='undefined')a.push({name:n,value:v});}if(!semantic&&form.clk){var inputs=form.getElementsByTagName("input");for(var i=0,max=inputs.length;i<max;i++){var input=inputs[i];var n=input.name;if(n&&!input.disabled&&input.type=="image"&&form.clk==input)a.push({name:n+'.x',value:form.clk_x},{name:n+'.y',value:form.clk_y});}}return a;};$.fn.formSerialize=function(semantic){return $.param(this.formToArray(semantic));};$.fn.fieldSerialize=function(successful){var a=[];this.each(function(){var n=this.name;if(!n)return;var v=$.fieldValue(this,successful);if(v&&v.constructor==Array){for(var i=0,max=v.length;i<max;i++)a.push({name:n,value:v[i]});}else if(v!==null&&typeof v!='undefined')a.push({name:this.name,value:v});});return $.param(a);};$.fn.fieldValue=function(successful){for(var val=[],i=0,max=this.length;i<max;i++){var el=this[i];var v=$.fieldValue(el,successful);if(v===null||typeof v=='undefined'||(v.constructor==Array&&!v.length))continue;v.constructor==Array?$.merge(val,v):val.push(v);}return val;};$.fieldValue=function(el,successful){var n=el.name,t=el.type,tag=el.tagName.toLowerCase();if(typeof successful=='undefined')successful=true;if(successful&&(!n||el.disabled||t=='reset'||t=='button'||(t=='checkbox'||t=='radio')&&!el.checked||(t=='submit'||t=='image')&&el.form&&el.form.clk!=el||tag=='select'&&el.selectedIndex==-1))return null;if(tag=='select'){var index=el.selectedIndex;if(index<0)return null;var a=[],ops=el.options;var one=(t=='select-one');var max=(one?index+1:ops.length);for(var i=(one?index:0);i<max;i++){var op=ops[i];if(op.selected){var v=$.browser.msie&&!(op.attributes['value'].specified)?op.text:op.value;if(one)return v;a.push(v);}}return a;}return el.value;};$.fn.clearForm=function(){return this.each(function(){$('input,select,textarea',this).clearFields();});};$.fn.clearFields=$.fn.clearInputs=function(){return this.each(function(){var t=this.type,tag=this.tagName.toLowerCase();if(t=='text'||t=='password'||tag=='textarea')this.value='';else if(t=='checkbox'||t=='radio')this.checked=false;else if(tag=='select')this.selectedIndex=-1;});};$.fn.resetForm=function(){return this.each(function(){if(typeof this.reset=='function'||(typeof this.reset=='object'&&!this.reset.nodeType))this.reset();});};$.fn.enable=function(b){if(b==undefined)b=true;return this.each(function(){this.disabled=!b});};$.fn.select=function(select){if(select==undefined)select=true;return this.each(function(){var t=this.type;if(t=='checkbox'||t=='radio')this.checked=select;else if(this.tagName.toLowerCase()=='option'){var $sel=$(this).parent('select');if(select&&$sel[0]&&$sel[0].type=='select-one'){$sel.find('option').select(false);}this.selected=select;}});};})(jQuery);
View
45 example/assets/javascripts/3-comments.js
@@ -1,45 +0,0 @@
-(function() {
- function submit(preview) {
- $('.comment-form form').ajaxSubmit({
- url: '/comments',
- type: 'POST',
- data: {
- preview: preview
- },
- resetForm: !preview,
- beforeSubmit: function(values) {
- if (values[1].value && values[3].value) {
- $('.comment-form .loading').show();
- return true;
- }
- else {
- alert('Please enter name and text!');
- return false;
- }
- },
- success: function(data) {
- $('.comment-form .loading').hide();
- if (preview) {
- $('.comment-form .preview').html(data);
- $('.preview-header').show();
- }
- else {
- $('.preview-header').hide();
- $('.comment-form .preview').html('');
- $('.comments').html(data);
- }
- }
- });
- }
-
- $('.comment-form form').submit(function() {
- submit(false);
- return false;
- });
-
- $('.comment-form .preview-button').click(function() {
- submit(true);
- return false;
- });
-
-})();
View
13 example/assets/javascripts/4-coderay.js
@@ -1,13 +0,0 @@
-
-$('pre.highlight').each(function() {
- var pre = $(this);
- var text = $('li', pre).map(function() { return $(this).text(); }).get();
- var textarea = $('<textarea class="code-area" cols="80" rows="' + text.length + ' ">' + text.join("\n") + '</textarea>');
- var div = $('<div class="code-link"><a href="#">View plain</a></div>').insertBefore(pre);
- var toggle = false;
- $('a', div).click(function() {
- toggle ? textarea.replaceWith(pre) : pre.replaceWith(textarea);
- toggle = !toggle;
- return false;
- });
-});
View
76 example/assets/print.css
@@ -1,76 +0,0 @@
-body {
-line-height:1.5;
-font-family:"Helvetica Neue", "Lucida Grande", Arial, Verdana, sans-serif;
-color:#000;
-background:none;
-font-size:10pt;
-}
-
-.container {
-background:none;
-}
-
-h1,h2,h3,h4,h5,h6 {
-font-family:"Helvetica Neue", Arial, "Lucida Grande", sans-serif;
-}
-
-code {
-font:.9em "Courier New", Monaco, Courier, monospace;
-}
-
-img {
-float:left;
-margin:1.5em 1.5em 1.5em 0;
-}
-
-a img {
-border:none;
-}
-
-p img.top {
-margin-top:0;
-}
-
-hr {
-background:#ccc;
-color:#ccc;
-width:100%;
-height:2px;
-border:none;
-margin:2em 0;
-padding:0;
-}
-
-blockquote {
-font-style:italic;
-font-size:.9em;
-margin:1.5em;
-padding:1em;
-}
-
-.small {
-font-size:.9em;
-}
-
-.large {
-font-size:1.1em;
-}
-
-.quiet {
-color:#999;
-}
-
-.hide {
-display:none;
-}
-
-a:link,a:visited {
-background:transparent;
-font-weight:700;
-text-decoration:underline;
-}
-
-a:link:after,a:visited:after {
-content:" (" attr(href) ") ";
-font-size:90%;
-}
View
23 example/assets/stylesheets/1-reset.css
@@ -1,23 +0,0 @@
-html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p,
-blockquote, pre, a, abbr, acronym, address, del, dfn, img,
-q, fieldset, form, label, legend, table,
-caption, tbody, tfoot, thead, tr, th, td {
- margin: 0;
- padding: 0;
- border: 0;
- font-weight: inherit;
- font-style: inherit;
- font-size: 100%;
- font-family: inherit;
- vertical-align: baseline;
-}
-
-body {
- line-height: 1.5;
- background: #fff;
- margin:0.5em 0;
-}
-
-p {
- margin-bottom: 1em;
-}
View
40 example/assets/stylesheets/2-typo.css
@@ -1,40 +0,0 @@
-body {
- font-size: 80%;
- color: #222;
- font-family: Arial, sans-serif;
-}
-
-h1, h2, h3, h4, h5, h6, h1 a, h2 a, h3 a, h4 a, h5 a, h6 a,
-h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited {
- color: #444;
- font-family: Arial, sans-serif;
- font-weight: bold;
-}
-
-a {
- color: #444;
-}
-
-a:visited {
- color: #444;
-}
-
-h1 a, h2 a, h3 a, h4 a, h5 a, h6 a {
- text-decoration: none;
-}
-
-h1 { font-size: 2em; line-height: 1; margin-top: 1em; margin-bottom: 1em; }
-h2 { font-size: 1.5em; margin-top: 0.75em; margin-bottom: 0.75em; }
-h3 { font-size: 1.3em; line-height: 1; margin-top: 1.7em; margin-bottom: 1em; }
-h4 { font-size: 1.2em; line-height: 1.25; margin-top: 1.25em; margin-bottom: 1.25em; }
-h5 { font-size: 1em; font-weight: bold; margin-bottom: 1.5em; }
-h6 { font-size: 1em; font-weight: bold; }
-
-blockquote {
- border-top: 3px double #666;
- border-bottom: 3px double #666;
- padding: 5px;
- font-style: oblique;
- margin-left: 5%;
- margin-right: 5%;
-}
View
23 example/assets/stylesheets/3-table.css
@@ -1,23 +0,0 @@
-
-table {
- border-collapse: separate;
- border-spacing: 0;
-}
-
-table {
- background: #fff;
- border: 1px solid #aaa;
- margin-bottom: 10px;
- width: 100%;
-}
-
-thead th {
- border-bottom: 2px solid #aaa;
- border-left: 1px solid #aaa;
- padding: 2px 9px;
- text-align: left;
-}
-
-tbody td {
- padding: 2px 9px;
-}
View
15 example/assets/stylesheets/4-article.css
@@ -1,15 +0,0 @@
-.article {
-}
-
-.article h2 {
- margin-top:0px;
-}
-
-.article .date {
- color: #666;
-}
-
-.article .tags a {
- color: #69c;
- text-decoration: none;
-}
View
20 example/assets/stylesheets/5-comments.css
@@ -1,20 +0,0 @@
-
-.comments {
- margin-bottom: 2em;
-}
-
-.comments .comment, .preview .comment {
- margin-top: 2em;
- border: 1px solid #ccc;
-}
-
-.comments .comment .top, .preview .comment .top {
- background: #F0F0F0;
- color: #333;
- padding: 3px 5px;
-}
-
-.comments .comment .body, .preview .comment .body {
- background: #F8F8F8;
- padding: 3px 5px;
-}
View
25 example/assets/stylesheets/6-diff.css
@@ -1,25 +0,0 @@
-
-.diff {
- margin: 1em 0;
- font-family: monospace;
- border: 1px solid #ddd;
- background: #eee;
-}
-
-.diff .path {
- color: blue;
- padding: 1em;
- border-bottom: 1px solid #ddd;
-}
-
-.diff .line {
- padding-left: 1em;
-}
-
-.diff .added {
- background: #dfd;
-}
-
-.diff .deleted {
- background: #fdd;
-}
View
33 example/assets/stylesheets/7-blog.css
@@ -1,33 +0,0 @@
-body {
- padding:1em;
-}
-
-.container {
- width: 600px;
- margin: 0 auto;
-}
-
-hr {
- border: 0;
- color: #ccc;
- background-color: #ccc;
- height: 1px;
- margin-top: 2em;
- margin-bottom: 2em;
-}
-
-blockquote {
- border-top: 3px double #69c;
- border-bottom: 3px double #69c;
- padding: 5px;
- font-style: oblique;
- margin-left: 5%;
- margin-right: 5%;
-}
-
-.pagination {
- text-align: right;
- margin-top: 1em;
- font-weight: bold;
-}
-
View
6 example/config.ru
@@ -1,6 +0,0 @@
-require 'shinmun'
-
-use Rack::Session::Cookie
-use Rack::Reloader
-
-run Shinmun::Blog.new(File.dirname(__FILE__))
View
10 example/config/blog.yml
@@ -1,10 +0,0 @@
----
-language: en
-title: Blog Title
-repository: root@my-blog-url.com:/var/www/
-url: http://www.my-blog-url.com
-author: The Author
-categories:
-- Ruby
-- Javascript
-description: Blog description
View
7 example/pages/about.md
@@ -1,7 +0,0 @@
----
-title: About
----
-
-This is the blog of Heinz Heinzmann.
-
-He is also known as _Heinzi_ or _Hein_.
View
90 example/templates/_comment_form.rhtml
@@ -1,90 +0,0 @@
-<div class="comment-form">
-
- <div class="loading" style="display:none">
- <img src="/assets/images/loading.gif" />
- Posting Comment...
- </div>
-
- <h4 class="preview-header" style="display:none">Comment Preview</h4>
-
- <div class="preview">
- </div>
-
- <form>
- <input type="hidden" name="path" value="<%= @post.path %>"/>
- <p>
- <label>Name</label><br/>
- <input type="text" name="name" size="40"/>
- </p>
- <p>
- <label>Website</label><br/>
- <input type="text" name="website" size="40"/>
- </p>
- <p>
- <label>Comment (Use Markdown for formatting) <a href="#markdown-help" onclick="$('#markdown-help').show(); return false">show help</a></label><br/>
- <textarea name="text" cols="60" rows="10"></textarea>
- </p>
- <p>
- <input type="submit" value="Post comment"/>
- <input type="button" value="Preview comment" class="preview-button"/>
- </p>
- </form>
-
- <a name="markdown-help"></a>
-
- <div id="markdown-help" style="display:none; margin-top:2em">
- <h2>Comment Formatting</h2>
-
- <ul>
- <li>Comments may be formatted with Markdown.</li>
- <li>Syntax highlighting is available (see below).</li>
- <li>Errors will be shown after your comment, so please check with preview.</li>
- <li>HTML code is filtered out for security reasons.</li>
- </ul>
-
- <h4>Emphasis</h4>
- <pre>_italic_ __bold__ or *italic* **bold**</pre>
-
- <h4>Links</h4>
- <pre>[Link text](http://example.com)</pre>
-
- <h4>Lists</h4>
- <pre>
-1. Lines with beginning cardinal numbers will turn into ordered lists.
-2. This is the second item.
-
-* Lines with beginning stars will turn into unordered lists.
-* This is the second item.
- </pre>
-
- <h4>Block quotes</h4>
- <pre>
-&gt; Lines with beginning brackets will turn into block quotes.
-&gt; Block quotes may be nested. </pre>
-
- <h4>Code blocks</h4>
- Code blocks are indented with 4 spaces and surrounded by blank lines:
- <pre>
-
- $ git commit -m "added markdown help"
- </pre>
-
- <h4>Syntax highlighting</h4>
-
- Following languages are supported:
- <strong>c, diff, javascript, scheme, css, html, xml, java, json, rhtml, yaml, delphi</strong>.
-
- You have to declare the language like this:
- <pre>
-
- @@ruby
-
- def method_missing(id, *args, &block)
- puts "#{id} was called with #{args.inspect}"
- end
-
- </pre>
-
- </div>
-
-</div>
View
10 example/templates/_pagination.rhtml
@@ -1,10 +0,0 @@
-
-<div class="pagination">
- <% if @page > 0 %>
- <%= link_to 'Previous page', "#{@path}/#{@page - 1}" %>
- <% end %>
-
- <% if @page < (@list.size - 1) / @page_size %>
- <%= link_to 'Next page', "#{path}/#{@page + 1}" %>
-<% end %>
-</div>
View
1  example/templates/comments.rhtml
@@ -1 +0,0 @@
-<%= render '_comments.rhtml', :comments => @comments %>
View
82 example/templates/layout.rhtml
@@ -1,82 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title><%= @blog.title %></title>
- <meta http-equiv="Content-Language" content="English" />
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
- <link rel="shortcut icon" type="image/x-icon" href="/assets/images/favicon.ico">
- <link rel="alternate" type="application/rss+xml" title="RSS" href="/index.rss" />
- <link rel="stylesheet" media="screen" type="text/css" href="/assets/stylesheets.css" />
- <link rel="stylesheet" media="print" type="text/css" href="/assets/print.css" />
- </head>
- <body>
- <div class="container">
- <h3><a href="/"><%= @blog.title %></a> - <%= @blog.description %></h3>
-
- <span>
- <%= link_to 'Home', '/' %> -
- <%= link_to 'About', '/about' %> -
- <%= link_to 'Subscribe RSS', '/index.rss' %>
- </span>
-
- <span style="margin-left:1em">
- Categories:
- <%= link_to 'Ruby', '/categories/ruby' %> -
- <%= link_to 'Javascript', '/categories/javascript' %>
- </span>
-
- <% if session[:admin] %>
- <hr/>
- <div>
- Admin:
- <%= link_to 'Posts', '/admin/posts/' %> -
- <%= link_to 'Pages', '/admin/pages' %> -
- <%= link_to 'Commits', '/admin/commits' %>
- <% if @post %> - <%= link_to 'Edit post', "/admin/edit/#{@post.path}" %><% end %>
- </div>
- <% end %>
-
- <hr/>
-
- <%= @content %>
-
- <p>
- Archive:
- <% for year, month in @blog.archives %>
- <%= archive_link year, month %>
- <% end %>
- </p>
-
- <% if @blog.aggregations['flickr'] %>
-
- <h4>Interesting Art @ Flickr</h4>
-
- <p>
- <% for pic in @blog.aggregations['flickr'].pics %>
- <a href="<%= pic.link %>">
- <img alt="<%= pic.title %>" src="<%= pic.thumbnail %>" width="45" height="45" />
- </a>
- <% end %>
- </p>
-
- <% end %>
-
- <% if @blog.aggregations['delicious'] %>
-
- <h4>Ruby @ Delicious</h4>
-
- <ul>
- <% for item in @blog.aggregations['delicious'].items %>
- <li>
- <%= link_to item.title, item.link %>
- </li>
- <% end %>
- </ul>
-
- <% end %>
-
- <script type="text/javascript" src="/assets/javascripts.js"></script>
-
- </div>
- </body>
-</html>
View
199 lib/shinmun/blog.rb
@@ -1,104 +1,71 @@
module Shinmun
+ ROOT = File.expand_path(File.dirname(__FILE__) + '/../..')
class Blog < Kontrol::Application
-
- EXAMPLE_DIR = File.expand_path(File.dirname(__FILE__) + '/../../example')
-
include Helpers
- attr_reader :aggregations, :categories, :comments, :repo, :store
+ attr_accessor :config, :store, :posts, :pages
- %w[ assets comments config posts pages templates ].each do |name|
- define_method(name) { store.root.tree(name) }
- end
-
- %w[ title description language author url base_path categories ].each do |name|
- define_method(name) { config['blog.yml'][name] }
+ %w[ base_path title description language author categories ].each do |name|
+ define_method(name) { @config[name.to_sym] }
end
# Initialize the blog
def initialize(path)
super
- @aggregations = {}
-
if ENV['RACK_ENV'] == 'production'
@store = GitStore.new(path)
else
@store = GitStore::FileStore.new(path)
end
-
+
+ @store.handler['md'] = PostHandler.new
@store.load
-
- @repo = Grit::Repo.new(path) if defined?(Grit)
-
- Thread.start do
- loop do
- load_aggregations
- sleep 300
- end
- end
- end
- def self.init(name)
- Dir.mkdir name
- Dir.chdir name
- FileUtils.cp_r EXAMPLE_DIR + '/.', '.'
- `git init`
- `git add .`
- `git commit -m 'init'`
+ @config = {}
end
- def load_template(file)
- templates[file] or raise "template #{file} not found"
- end
+ def self.init(path)
+ path = File.expand_path(path)
+ Dir.mkdir(path)
- def render(name, vars = {})
- super(name, vars.merge(:blog => self))
- end
+ FileUtils.cp_r "#{ROOT}/assets", path
+ FileUtils.cp_r "#{ROOT}/templates", path
+ FileUtils.cp "#{ROOT}/config.ru", path
- def call(env)
- store.refresh!
- super
- end
+ Dir.mkdir("#{path}/posts")
+ Dir.mkdir("#{path}/pages")
+ Dir.mkdir("#{path}/comments")
+ Dir.mkdir("#{path}/public")
- def load_aggregations
- config['aggregations.yml'].to_a.each do |c|
- aggregations[c['name']] = Object.const_get(c['class']).new(c['url'])
- end
- end
+ FileUtils.ln_s("../assets", "#{path}/public/assets")
- def posts_by_date
- posts.sort_by { |post| post.date.to_s }.reverse
+ Dir.chdir(path) do
+ `git init`
+ `git add .`
+ `git commit -m 'init'`
+ end
end
- def recent_posts
- posts_by_date[0, 20]
+ def render(name, vars = {})
+ super(name, vars.merge(:blog => self))
end
- # Return all posts for a given month.
- def posts_for_month(year, month)
- posts_by_date.select { |p| p.year == year and p.month == month }
+ def load
+ store.load
+ @pages = store['pages'].values
+ @posts = store['posts'].values.sort_by { |post| post.date.to_s }.reverse
end
- # Return all posts with any of given tags.
- def posts_with_tags(tags)
- return [] if tags.nil? or tags.empty?
- tags = tags.split(',').map { |t| t.strip } if tags.is_a?(String)
- posts.select do |post|
- tags.any? do |tag|
- post.tag_list.include?(tag)
- end
- end
- end
-
- # Return all archives as tuples of [year, month].
- def archives
- posts.map { |p| [p.year, p.month] }.uniq.sort
+ def call(env)
+ load if store.changed?
+
+ super
end
-
- def tree(post)
- post.date ? posts.tree(post.year).tree(post.month) : pages
+
+ def url
+ "http://#{request.host}"
end
def symbolize_keys(hash)
@@ -112,36 +79,54 @@ def transaction(message, &block)
store.transaction(message, &block)
end
- # Create a new post with given attributes.
- def create_post(atts)
- post = Post.new(atts)
- transaction "create '#{post.title}'" do
- store[post.path] = post
- end
+ def post_file(post)
+ 'posts' + post_path(post) + '.' + post.type
+ end
+
+ def page_file(post)
+ 'pages' + page_path(post) + '.' + post.type
+ end
+
+ def comment_file(post)
+ 'comments/' + post_path(post) + '.yml'
end
- def update_post(post, data)
- transaction "update '#{post.title}'" do
- store.delete(post.path)
- post.parse data
- store[post.path] = post
+ def create_post(attr)
+ post = Post.new(attr)
+ path = post_file(post)
+
+ transaction "create post '#{post.title}'" do
+ store[path] = post
end
+
+ post
end
- def delete_post(post)
- transaction "delete '#{post.title}'" do
- store.delete(post.path)
+ def create_page(attr)
+ post = Post.new(attr)
+ path = page_file(post)
+
+ transaction "create page '#{post.title}'" do
+ store[path] = post
end
+
+ post
end
- def comments_for(path)
- comments[path + '.yml'] || []
+ def comments_for(post)
+ store[comment_file post] || []
end
- def post_comment(path, params)
- transaction "new comment for '#{path}'" do
- comments[path + '.yml'] = comments[path + '.yml'].to_a + [ Comment.new(params) ]
+ def create_comment(post, params)
+ path = comment_file(post)
+ comments = comments_for(post)
+ comment = Comment.new(params)
+
+ transaction "new comment for '#{post.title}'" do
+ store[path] = comments + [comment]
end
+
+ comment
end
def find_page(name)
@@ -149,22 +134,42 @@ def find_page(name)
end
def find_post(year, month, name)
- tree = posts[year, month] and tree.find { |p| p.name == name }
+ posts.find { |p| p.year == year and p.month == month and p.name == name }
end
def find_category(permalink)
- name = categories.find { |name| urlify(name) == permalink } or raise "category not found"
- posts = self.posts.select { |p| p.category == name }.sort_by { |p| p.date }.reverse
- { :name => name, :posts => posts, :permalink => permalink }
+ name = categories.find { |name| urlify(name) == permalink }
+
+ { :name => name,
+ :posts => posts.select { |p| p.category == name },
+ :permalink => permalink }
+ end
+
+ def recent_posts
+ posts[0, 20]
end
- def write(file, template, vars={})
- file = "public/#{base_path}/#{file}"
- FileUtils.mkdir_p(File.dirname(file))
- open(file, 'wb') do |io|
- io << render(template, vars)
+ # Return all posts for a given month.
+ def posts_for_month(year, month)
+ posts.select { |p| p.year == year and p.month == month }
+ end
+
+ # Return all posts with any of given tags.
+ def posts_with_tags(tags)
+ return [] if tags.nil? or tags.empty?
+ tags = tags.split(',').map { |t| t.strip } if tags.is_a?(String)
+
+ posts.select do |post|
+ tags.any? do |tag|
+ post.tag_list.include?(tag)
+ end
end
end
+
+ # Return all archives as tuples of [year, month].
+ def archives
+ posts.map { |p| [p.year, p.month] }.uniq.sort
+ end
end
View
2  lib/shinmun/comment.rb
@@ -1,7 +1,7 @@
module Shinmun
class Comment
-
+
attr_accessor :time, :name, :email, :website, :text
def initialize(attributes)
View
2  lib/shinmun/helpers.rb
@@ -35,7 +35,7 @@ def distance_of_time_in_words(from_time, to_time = 0, include_seconds = false)
def post_path(post)
"#{base_path}/#{post.year}/#{post.month}/#{post.name}"
- end
+ end
def archive_path(year, month)
"#{base_path}/#{year}/#{month}"
View
11 lib/shinmun/post_handler.rb
@@ -1,16 +1,13 @@
module Shinmun
class PostHandler
- def read(path, data)
- Post.new(:path => path, :src => data)
+ def read(data)
+ Post.new(:src => data)
end
- def write(path, post)
- post.dump
+ def write(post)
+ post.dump
end
end
end
-
-GitStore::Handler['md'] = Shinmun::PostHandler.new
-GitStore::Handler['html'] = Shinmun::PostHandler.new
View
58 lib/shinmun/routes.rb
@@ -9,12 +9,24 @@
end
tag '/tags/(.*)' do |tag|
- render 'category.rhtml', :name => "Tag: #{tag}", :posts => posts.select { |p| p.tag_list.include?(tag) }
+ render 'category.rhtml', :name => "Tag: #{tag}", :posts => posts_with_tags(tag)
+ end
+
+ comments '/(\d+)/(\d+)/(.*)/comments' do |year, month, name|
+ post = find_post(year.to_i, month.to_i, name) or raise "post not found #{request.path_info}"
+
+ if params['preview']
+ comments = comments_for(post).push(Shinmun::Comment.new(params))
+ render 'post.rhtml', :post => post, :comments => comments
+ else
+ create_comment(post, params)
+ render 'post.rhtml', :post => post, :comments => comments_for(post)
+ end
end
post '/(\d+)/(\d+)/(.*)' do |year, month, name|
- post = find_post(year.to_i, month.to_i, name)
- render 'post.rhtml', :post => post, :comments => comments_for(post.path)
+ post = find_post(year.to_i, month.to_i, name) or raise "post not found #{request.path_info}"
+ render 'post.rhtml', :post => post, :comments => comments_for(post)
end
archive '/(\d+)/(\d+)' do |year, month|
@@ -25,47 +37,21 @@
render 'index.rxml', :layout => false
end
- comments '/comments' do
- if params['preview'] == 'true'
- render 'comments.rhtml', :comments => [Shinmun::Comment.new(params)], :layout => false
- else
- post_comment(params['path'], params)
- render 'comments.rhtml', :comments => comments_for(params['path']), :layout => false
- end
- end
-
- javascripts '/assets/javascripts\.js' do
- scripts = assets['javascripts'].to_a.join
- if_none_match(etag(scripts)) do
- text scripts
- end
- end
-
- stylesheets '/assets/stylesheets\.css' do
- styles = assets['stylesheets'].to_a.join
- if_none_match(etag(styles)) do
- text styles
- end
- end
-
- assets '/assets/(.*)' do |path|
- file = assets[path] or raise "#{path} not found"
- if_none_match(etag(file)) do
- text file
- end
- end
-
- get '/$' do
+ index '/$' do
render 'index.rhtml'
end
- get '/(.*)' do |path|
+ page '/(.*)' do |path|
+ path = path.gsub('..', '')
page = find_page(path)
if page
render 'page.rhtml', :page => page
+
+ elsif File.exist?(path)
+ text File.read("#{self.path}/public/#{path}")
else
- raise "page '#{path}' not found"
+ render '404.rhtml', :path => path
end
end
View
4 templates/404.rhtml
@@ -0,0 +1,4 @@
+<h2>Not Found</h2>
+<p>
+ The page <%= @path %> was not found.
+</p>
View
19 templates/_comment_form.rhtml
@@ -0,0 +1,19 @@
+<div class="comment-form">
+ <form action="<%= post_path @post %>/comments" method="POST">
+ <p>
+ <label>Name</label><br/>
+ <input type="text" name="name" size="40" value="<%= @params['name'] %>"/>
+ </p>
+ <p>
+ <label>Website</label><br/>
+ <input type="text" name="website" size="40" value="<%= @params['website'] %>"/>
+ </p>
+ <p>
+ <label>Comment</label><br/>
+ <textarea name="text" cols="60" rows="10"><%= @params['text'] %></textarea>
+ </p>
+ <p>
+ <input type="submit" value="Post comment"/>
+ </p>
+ </form>
+</div>
View
2  example/templates/_comments.rhtml → templates/_comments.rhtml
@@ -1,7 +1,7 @@
<% for comment in @comments %>
<div class="comment">
<div class="top">
- <%= comment.website.empty? ? comment.name : link_to(comment.name, comment.website) %> said
+ <%= comment.website.to_s.empty? ? comment.name : link_to(comment.name, comment.website) %> said
<%= distance_of_time_in_words(comment.time, Time.now, true) %> ago:
</div>
<div class="body">
View
1  example/templates/archive.rhtml → templates/archive.rhtml
@@ -7,6 +7,5 @@
<h2><%= post_link post %></h2>
<%= post.summary %>
</div>
- <hr/>
<% end %>
</div>
View
3  example/templates/category.rhtml → templates/category.rhtml
@@ -1,12 +1,11 @@
<h1><%= @name %></h1>
<div class="articles">
- <% for post in @posts[0, 20] %>
+ <% for post in @posts %>
<div class="article">
<div class="date"><%= human_date post.date %></div>
<h2><%= post_link post %></h2>
<%= post.summary %>
</div>
- <hr/>
<% end %>
</div>
View
0  example/templates/category.rxml → templates/category.rxml
File renamed without changes
View
1  example/templates/index.rhtml → templates/index.rhtml
@@ -7,6 +7,5 @@
<h2><%= post_link post %></h2>
<%= post.summary %>
</div>
- <hr/>
<% end %>
</div>
View
0  example/templates/index.rxml → templates/index.rxml
File renamed without changes
View
44 templates/layout.rhtml
@@ -0,0 +1,44 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title><%= @blog.title %></title>
+ <meta http-equiv="Content-Language" content="English" />
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <link rel="alternate" type="application/rss+xml" title="RSS" href="/index.rss" />
+ <link rel="stylesheet" media="screen" type="text/css" href="/assets/styles.css" />
+ <link rel="stylesheet" media="print" type="text/css" href="/assets/print.css" />
+ </head>
+ <body>
+ <div class="container">
+ <h3><a href="/"><%= @blog.title %></a> - <%= @blog.description %></h3>
+
+ <div class="menu">
+ <%= link_to 'Home', '/' %> -
+ <%= link_to 'About', '/about' %> -
+ <%= link_to 'Subscribe RSS', '/index.rss' %>
+ </div>
+
+ <%= @content %>
+
+ <hr/>
+
+ <p>
+ <h4>Categories</h4>
+ <ul>
+ <li><%= link_to 'Ruby', '/categories/ruby' %></li>
+ <li><%= link_to 'Javascript', '/categories/javascript' %></li>
+ </ul>
+ </p>
+
+ <p>
+ <h4>Archive</h4>
+ <ul>
+ <% for year, month in @blog.archives %>
+ <li><%= archive_link year, month %></li>
+ <% end %>
+ </ul>
+ </p>
+
+ </div>
+ </body>
+</html>
View
2  example/templates/page.rhtml → templates/page.rhtml
@@ -3,5 +3,3 @@
<div class="article">
<%= @page.body_html %>
</div>
-
-<hr/>
View
27 example/templates/post.rhtml → templates/post.rhtml
@@ -8,28 +8,15 @@
<%= @post.body_html %>
- <hr/>
-
- <div style="margin:1em 0em 1em 0em; color:#666">
+ <p>
<% if @post.category %>
- Posted in category <%= link_to @post.category, "/categories/#{urlify @post.category}" %> by <%= @blog.author %>.
+ Posted in category <%= link_to @post.category, "/categories/#{urlify @post.category}" %>.
<% end %>
- Tagged with <%= @post.tag_list.map {|tag| link_to tag, "/tags/#{tag}" }.join(', ') %>.
- </div>
-
- <h6>Similar Posts</h6>
- <ul>
-
- <% for post in @blog.posts_with_tags(@post.tags) %>
- <% if post != @post %>
- <li><%= post_link post %></li>
- <% end %>
- <% end %>
-
- </ul>
-
- <hr/>
+ <% unless @post.tag_list.empty? %>
+ Tagged with <%= @post.tag_list.map {|tag| link_to tag, "/tags/#{tag}" }.join(', ') %>.
+ <% end %>
+ </p>
<% if @comments %>
<h2>Comments</h2>
@@ -44,5 +31,3 @@
<%= render '_comment_form.rhtml', :post => @post %>
</div>
-
-<hr/>
View
105 test/blog_spec.rb
@@ -1,70 +1,51 @@
require 'shinmun'
require 'rack/mock'
+require 'rexml/document'
require 'rexml/xpath'
require 'pp'
describe Shinmun::Blog do
- TEMPLATES_DIR = File.expand_path(File.dirname(__FILE__) + '/templates')
- REPO = '/tmp/shinmun-test'
+ DIR = '/tmp/shinmun-test'
before do
- FileUtils.rm_rf REPO
- Dir.mkdir REPO
- Dir.chdir REPO
- initialize_blog
- end
-
- def file(file, data)
- FileUtils.mkpath(File.dirname(file))
- open(file, 'w') { |io| io << data }
- `git add #{file}`
- end
-
- def initialize_blog
- `git init`
+ FileUtils.rm_rf DIR
+
+ Shinmun::Blog.init(DIR)
- file 'config/blog.yml', {
- 'title' => 'Title',
- 'description' => 'Description',
- 'language' => 'en',
- 'author' => 'The Author',
- 'url' => 'http://www.my-blog-url.com',
- 'categories' => ['Ruby', 'Javascript']
- }.to_yaml
-
ENV['RACK_ENV'] = 'production'
- @blog = Shinmun::Blog.new(REPO)
- @request = Rack::MockRequest.new(@blog)
-
- Dir.mkdir 'templates'
- Dir[TEMPLATES_DIR + '/*'].each do |path|
- unless path.include?('~')
- file 'templates/' + File.basename(path), File.read(path)
- end
- end
-
- `git commit -m 'spec'`
+ @blog = Shinmun::Blog.new(DIR)
+
+ @blog.config = {
+ :title => 'Title',
+ :description => 'Description',
+ :language => 'en',
+ :author => 'The Author',
+ :categories => ['Ruby', 'Javascript']
+ }
- @blog.store.load
-
@posts = [@blog.create_post(:title => 'New post', :date => '2008-10-10', :category => 'Ruby', :body => 'Body1'),
@blog.create_post(:title => 'And this', :date => '2008-10-11', :category => 'Ruby', :body => 'Body2'),
@blog.create_post(:title => 'Again', :date => '2008-11-10', :category => 'Javascript', :body => 'Body3')]
- @pages = [@blog.create_post(:title => 'Page 1', :body => 'Body1'),
- @blog.create_post(:title => 'Page 2', :body => 'Body2')]
+ @pages = [@blog.create_page(:title => 'Page 1', :body => 'Body1'),
+ @blog.create_page(:title => 'Page 2', :body => 'Body2')]
- @blog.store.load
+ @blog.load
+ end
+
+ def request(method, uri, options={})
+ @request = Rack::MockRequest.new(@blog)
+ @response = @request.request(method, uri, options)
end
def get(*args)
- @request.get(*args)
+ request(:get, *args)
end
def post(*args)
- @request.post(*args)
+ request(:post, *args)
end
def xpath(xml, path)
@@ -98,9 +79,9 @@ def assert_listing(xml, list)
end
it "should create a post" do
- @blog.create_post(:title => 'New post', :date => '2008-10-10')
- @blog.store.load
-
+ post = @blog.create_post(:title => 'New post', :date => '2008-10-10')
+ @blog.load
+
post = @blog.find_post(2008, 10, 'new-post')
post.should_not be_nil
post.title.should == 'New post'
@@ -108,26 +89,6 @@ def assert_listing(xml, list)
post.name.should == 'new-post'
end
- it "should update a post" do
- post = @blog.create_post(:title => 'New post', :date => '2008-10-10')
- @blog.update_post(post, "---\ndate: 2008-11-11\ntitle: The title\n---")
- @blog.store.load
-
- post = @blog.find_post(2008, 11, 'new-post')
- post.should_not be_nil
- post.title.should == 'The title'
- post.date.should == Date.new(2008, 11, 11)
- post.name.should == 'new-post'
- end
-
- it "should delete a post" do
- post = @blog.create_post(:title => 'New post', :date => '2008-10-10')
- @blog.delete_post(post)
- @blog.store.load
-
- @blog.find_post(2008, 10, 'new-post').should be_nil
- end
-
it "should render posts" do
xml = get('/2008/10/new-post').body
@@ -143,10 +104,10 @@ def assert_listing(xml, list)
xpath(xml, '/rss/channel/title')[0].text.should == 'Ruby'
xpath(xml, '/rss/channel/item/title')[0].text.should == 'And this'
xpath(xml, '/rss/channel/item/pubDate')[0].text.should == "Sat, 11 Oct 2008 00:00:00 +0000"
- xpath(xml, '/rss/channel/item/link')[0].text.should == "http://www.my-blog-url.com/2008/10/and-this"
+ xpath(xml, '/rss/channel/item/link')[0].text.should == "http://example.org/2008/10/and-this"
xpath(xml, '/rss/channel/item/title')[1].text.should == 'New post'
xpath(xml, '/rss/channel/item/pubDate')[1].text.should == "Fri, 10 Oct 2008 00:00:00 +0000"
- xpath(xml, '/rss/channel/item/link')[1].text.should == "http://www.my-blog-url.com/2008/10/new-post"
+ xpath(xml, '/rss/channel/item/link')[1].text.should == "http://example.org/2008/10/new-post"
assert_listing(get('/categories/ruby').body, [['And this', 'Body2'], ['New post', 'Body1']])
end
@@ -170,12 +131,10 @@ def assert_listing(xml, list)
end
it "should post a comment" do
- post "/comments?path=posts/2008/10/new-post.md&name=Hans&text=Hallo"
- post "/comments?path=posts/2008/10/new-post.md&name=Peter&text=Servus"
+ post "/2008/10/new-post/comments?name=Hans&text=Hallo"
+ post "/2008/10/new-post/comments?name=Peter&text=Servus"
- @blog.store.load
-
- comments = @blog.comments_for(@posts[0].path)
+ comments = @blog.comments_for(@posts[0])
comments[0].should_not be_nil
comments[0].name.should == 'Hans'
View
11 test/templates/templates/_comments.rhtml
@@ -0,0 +1,11 @@
+<% for comment in @comments %>
+ <div class="comment">
+ <div class="top">
+ <%= comment.website.to_s.empty? ? comment.name : link_to(comment.name, comment.website) %> said
+ <%= distance_of_time_in_words(comment.time, Time.now, true) %> ago:
+ </div>
+ <div class="body">
+ <%= markdown(comment.text, :filter_html, :filter_styles) %>
+ </div>
+ </div>
+<% end %>
View
6 test/templates/templates/archive.rhtml
@@ -0,0 +1,6 @@
+<h1><%= "#{Date::MONTHNAMES[@month]} #{@year}" %></h1>
+
+<% for post in @posts %>
+ <h2><%= post_link post %></h2>
+ <%= post.summary %>
+<% end %>
View
6 test/templates/templates/category.rhtml
@@ -0,0 +1,6 @@
+<h1><%= @name %></h1>
+
+<% for post in @posts %>
+ <h2><%= post_link post %></h2>
+ <%= post.summary %>
+<% end %>
View
20 test/templates/templates/category.rxml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<rss version="2.0">
+ <channel>
+ <title><%= @name %></title>
+ <link>http://<%= @request.domain %>/categories/<%= urlify @name %>.html</link>
+ <language><%= @blog.language %></language>
+ <copyright><%= @blog.author %></copyright>
+ <pubDate><%= rfc822 Time.now %></pubDate>
+ <% for post in @posts %>
+ <item>
+ <title><%= post.title %></title>
+ <category><%= post.category %></category>
+ <description><%= strip_tags post.summary %></description>
+ <author><%= @author || @blog.author %></author>
+ <link><%= @blog.url + post_path(post) %></link>
+ <pubDate><%= rfc822 post.date %></pubDate>
+ </item>
+ <% end %>
+ </channel>
+</rss>
View
4 test/templates/templates/index.rhtml
@@ -0,0 +1,4 @@
+<% for post in @blog.recent_posts %>
+ <h2><%= post_link post %></h2>
+ <%= post.summary %>
+<% end %>
View
21 test/templates/templates/index.rxml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<rss version="2.0">
+ <channel>
+ <title><%= @blog.title %></title>
+ <link><%= @blog.url %></link>
+ <description><%= @blog.description %></description>
+ <language><%= @blog.language %></language>
+ <copyright><%= @blog.author %></copyright>
+ <pubDate><%= rfc822 Time.now %></pubDate>
+ <% for post in @blog.recent_posts %>
+ <item>
+ <title><%= post.title %></title>
+ <category><%= post.category %></category>
+ <description><%= strip_tags post.summary %></description>
+ <author><%= @author || @blog.author %></author>
+ <link><%= @blog.url + post_path(post) %></link>
+ <pubDate><%= rfc822 post.date %></pubDate>
+ </item>
+ <% end %>
+ </channel>
+</rss>
View
9 test/templates/templates/layout.rhtml
@@ -0,0 +1,9 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title><%= @blog.title %></title>
+ </head>
+ <body>
+ <%= @content %>
+ </body>
+</html>
View
2  test/templates/templates/page.rhtml
@@ -0,0 +1,2 @@
+<h1><%= @page.title %></h1>
+<%= @page.body_html %>
View
3  test/templates/templates/post.rhtml
@@ -0,0 +1,3 @@
+<h1><%= @post.title %></h1>
+<%= human_date @post.date %>
+<%= @post.body_html %>

0 comments on commit f930470

Please sign in to comment.
Something went wrong with that request. Please try again.