kuhsaft 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/.gitignore +2 -1
  2. data/.rspec +1 -2
  3. data/README +57 -2
  4. data/app/controllers/kuhsaft/admin/pages_controller.rb +5 -1
  5. data/app/controllers/kuhsaft/pages_controller.rb +1 -1
  6. data/app/models/kuhsaft/localized_page.rb +15 -1
  7. data/app/models/kuhsaft/page.rb +18 -4
  8. data/app/stylesheets/kuhsaft/admin/partials/_assets.sass +13 -10
  9. data/app/stylesheets/kuhsaft/admin/partials/_pages.sass +5 -1
  10. data/app/uploaders/kuhsaft/asset_uploader.rb +3 -3
  11. data/app/views/kuhsaft/admin/assets/_list.html.haml +10 -6
  12. data/app/views/kuhsaft/admin/pages/_form.html.haml +2 -2
  13. data/app/views/kuhsaft/admin/pages/edit.html.haml +1 -1
  14. data/app/views/kuhsaft/admin/pages/new.html.haml +1 -1
  15. data/app/views/kuhsaft/pages/show.html.haml +1 -0
  16. data/config/routes.rb +1 -1
  17. data/kuhsaft.gemspec +1 -0
  18. data/lib/generators/kuhsaft/install/assets_generator.rb +12 -0
  19. data/lib/generators/kuhsaft/install/migrations_generator.rb +25 -0
  20. data/lib/kuhsaft.rb +1 -0
  21. data/lib/kuhsaft/engine.rb +3 -5
  22. data/lib/kuhsaft/version.rb +1 -1
  23. data/lib/templates/kuhsaft/install/add_url_to_localized_pages.rb +9 -0
  24. data/{db/migrate/20110307162621_create_assets.rb → lib/templates/kuhsaft/install/create_assets.rb} +0 -0
  25. data/{db/migrate/20110302113020_create_kuhsaft_localized_pages.rb → lib/templates/kuhsaft/install/create_kuhsaft_localized_pages.rb} +0 -0
  26. data/{db/migrate/20110302101530_create_kuhsaft_pages.rb → lib/templates/kuhsaft/install/create_kuhsaft_pages.rb} +0 -0
  27. data/{db/migrate/20110302125123_create_page_part_contents.rb → lib/templates/kuhsaft/install/create_page_part_contents.rb} +0 -0
  28. data/spec/controllers/admin_pages_controller_spec.rb +5 -0
  29. data/spec/controllers/pages_controller_spec.rb +2 -2
  30. data/spec/dummy/public/images/css3buttons_backgrounds.png +0 -0
  31. data/spec/dummy/public/images/css3buttons_icons.png +0 -0
  32. data/spec/dummy/public/images/drag-handle.png +0 -0
  33. data/spec/dummy/public/javascripts/kuhsaft/admin/jquery-1.4.4.js +7179 -0
  34. data/spec/dummy/public/javascripts/kuhsaft/admin/jquery-ui-1.8.10.custom.min.js +110 -0
  35. data/spec/dummy/public/javascripts/kuhsaft/admin/rails.js +157 -0
  36. data/spec/factories.rb +2 -0
  37. data/spec/models/localized_page_spec.rb +10 -11
  38. data/spec/models/page_spec.rb +52 -13
  39. data/spec/routing/pages_routing_spec.rb +2 -15
  40. data/spec/spec_helper.rb +3 -4
  41. metadata +39 -42
@@ -0,0 +1,110 @@
1
+ /*!
2
+ * jQuery UI 1.8.10
3
+ *
4
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5
+ * Dual licensed under the MIT or GPL Version 2 licenses.
6
+ * http://jquery.org/license
7
+ *
8
+ * http://docs.jquery.com/UI
9
+ */
10
+ (function(c,j){function k(a){return!c(a).parents().andSelf().filter(function(){return c.curCSS(this,"visibility")==="hidden"||c.expr.filters.hidden(this)}).length}c.ui=c.ui||{};if(!c.ui.version){c.extend(c.ui,{version:"1.8.10",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,
11
+ NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});c.fn.extend({_focus:c.fn.focus,focus:function(a,b){return typeof a==="number"?this.each(function(){var d=this;setTimeout(function(){c(d).focus();b&&b.call(d)},a)}):this._focus.apply(this,arguments)},scrollParent:function(){var a;a=c.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.curCSS(this,
12
+ "position",1))&&/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!a.length?c(document):a},zIndex:function(a){if(a!==j)return this.css("zIndex",a);if(this.length){a=c(this[0]);for(var b;a.length&&a[0]!==document;){b=a.css("position");
13
+ if(b==="absolute"||b==="relative"||b==="fixed"){b=parseInt(a.css("zIndex"),10);if(!isNaN(b)&&b!==0)return b}a=a.parent()}}return 0},disableSelection:function(){return this.bind((c.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});c.each(["Width","Height"],function(a,b){function d(f,g,l,m){c.each(e,function(){g-=parseFloat(c.curCSS(f,"padding"+this,true))||0;if(l)g-=parseFloat(c.curCSS(f,
14
+ "border"+this+"Width",true))||0;if(m)g-=parseFloat(c.curCSS(f,"margin"+this,true))||0});return g}var e=b==="Width"?["Left","Right"]:["Top","Bottom"],h=b.toLowerCase(),i={innerWidth:c.fn.innerWidth,innerHeight:c.fn.innerHeight,outerWidth:c.fn.outerWidth,outerHeight:c.fn.outerHeight};c.fn["inner"+b]=function(f){if(f===j)return i["inner"+b].call(this);return this.each(function(){c(this).css(h,d(this,f)+"px")})};c.fn["outer"+b]=function(f,g){if(typeof f!=="number")return i["outer"+b].call(this,f);return this.each(function(){c(this).css(h,
15
+ d(this,f,true,g)+"px")})}});c.extend(c.expr[":"],{data:function(a,b,d){return!!c.data(a,d[3])},focusable:function(a){var b=a.nodeName.toLowerCase(),d=c.attr(a,"tabindex");if("area"===b){b=a.parentNode;d=b.name;if(!a.href||!d||b.nodeName.toLowerCase()!=="map")return false;a=c("img[usemap=#"+d+"]")[0];return!!a&&k(a)}return(/input|select|textarea|button|object/.test(b)?!a.disabled:"a"==b?a.href||!isNaN(d):!isNaN(d))&&k(a)},tabbable:function(a){var b=c.attr(a,"tabindex");return(isNaN(b)||b>=0)&&c(a).is(":focusable")}});
16
+ c(function(){var a=document.body,b=a.appendChild(b=document.createElement("div"));c.extend(b.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0});c.support.minHeight=b.offsetHeight===100;c.support.selectstart="onselectstart"in b;a.removeChild(b).style.display="none"});c.extend(c.ui,{plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&&a.element[0].parentNode)for(var e=0;e<b.length;e++)a.options[b[e][0]]&&
17
+ b[e][1].apply(a.element,d)}},contains:function(a,b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b)},hasScroll:function(a,b){if(c(a).css("overflow")==="hidden")return false;b=b&&b==="left"?"scrollLeft":"scrollTop";var d=false;if(a[b]>0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a<b+d},isOver:function(a,b,d,e,h,i){return c.ui.isOverAxis(a,d,h)&&c.ui.isOverAxis(b,e,i)}})}})(jQuery);
18
+ ;/*!
19
+ * jQuery UI Widget 1.8.10
20
+ *
21
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
22
+ * Dual licensed under the MIT or GPL Version 2 licenses.
23
+ * http://jquery.org/license
24
+ *
25
+ * http://docs.jquery.com/UI/Widget
26
+ */
27
+ (function(b,j){if(b.cleanData){var k=b.cleanData;b.cleanData=function(a){for(var c=0,d;(d=a[c])!=null;c++)b(d).triggerHandler("remove");k(a)}}else{var l=b.fn.remove;b.fn.remove=function(a,c){return this.each(function(){if(!c)if(!a||b.filter(a,[this]).length)b("*",this).add([this]).each(function(){b(this).triggerHandler("remove")});return l.call(b(this),a,c)})}}b.widget=function(a,c,d){var e=a.split(".")[0],f;a=a.split(".")[1];f=e+"-"+a;if(!d){d=c;c=b.Widget}b.expr[":"][f]=function(h){return!!b.data(h,
28
+ a)};b[e]=b[e]||{};b[e][a]=function(h,g){arguments.length&&this._createWidget(h,g)};c=new c;c.options=b.extend(true,{},c.options);b[e][a].prototype=b.extend(true,c,{namespace:e,widgetName:a,widgetEventPrefix:b[e][a].prototype.widgetEventPrefix||a,widgetBaseClass:f},d);b.widget.bridge(a,b[e][a])};b.widget.bridge=function(a,c){b.fn[a]=function(d){var e=typeof d==="string",f=Array.prototype.slice.call(arguments,1),h=this;d=!e&&f.length?b.extend.apply(null,[true,d].concat(f)):d;if(e&&d.charAt(0)==="_")return h;
29
+ e?this.each(function(){var g=b.data(this,a),i=g&&b.isFunction(g[d])?g[d].apply(g,f):g;if(i!==g&&i!==j){h=i;return false}}):this.each(function(){var g=b.data(this,a);g?g.option(d||{})._init():b.data(this,a,new c(d,this))});return h}};b.Widget=function(a,c){arguments.length&&this._createWidget(a,c)};b.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(a,c){b.data(c,this.widgetName,this);this.element=b(c);this.options=b.extend(true,{},this.options,
30
+ this._getCreateOptions(),a);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()});this._create();this._trigger("create");this._init()},_getCreateOptions:function(){return b.metadata&&b.metadata.get(this.element[0])[this.widgetName]},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},
31
+ widget:function(){return this.element},option:function(a,c){var d=a;if(arguments.length===0)return b.extend({},this.options);if(typeof a==="string"){if(c===j)return this.options[a];d={};d[a]=c}this._setOptions(d);return this},_setOptions:function(a){var c=this;b.each(a,function(d,e){c._setOption(d,e)});return this},_setOption:function(a,c){this.options[a]=c;if(a==="disabled")this.widget()[c?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",c);return this},
32
+ enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(a,c,d){var e=this.options[a];c=b.Event(c);c.type=(a===this.widgetEventPrefix?a:this.widgetEventPrefix+a).toLowerCase();d=d||{};if(c.originalEvent){a=b.event.props.length;for(var f;a;){f=b.event.props[--a];c[f]=c.originalEvent[f]}}this.element.trigger(c,d);return!(b.isFunction(e)&&e.call(this.element[0],c,d)===false||c.isDefaultPrevented())}}})(jQuery);
33
+ ;/*!
34
+ * jQuery UI Mouse 1.8.10
35
+ *
36
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
37
+ * Dual licensed under the MIT or GPL Version 2 licenses.
38
+ * http://jquery.org/license
39
+ *
40
+ * http://docs.jquery.com/UI/Mouse
41
+ *
42
+ * Depends:
43
+ * jquery.ui.widget.js
44
+ */
45
+ (function(c){c.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var a=this;this.element.bind("mousedown."+this.widgetName,function(b){return a._mouseDown(b)}).bind("click."+this.widgetName,function(b){if(true===c.data(b.target,a.widgetName+".preventClickEvent")){c.removeData(b.target,a.widgetName+".preventClickEvent");b.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(a){a.originalEvent=
46
+ a.originalEvent||{};if(!a.originalEvent.mouseHandled){this._mouseStarted&&this._mouseUp(a);this._mouseDownEvent=a;var b=this,e=a.which==1,f=typeof this.options.cancel=="string"?c(a.target).parents().add(a.target).filter(this.options.cancel).length:false;if(!e||f||!this._mouseCapture(a))return true;this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet)this._mouseDelayTimer=setTimeout(function(){b.mouseDelayMet=true},this.options.delay);if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a)){this._mouseStarted=
47
+ this._mouseStart(a)!==false;if(!this._mouseStarted){a.preventDefault();return true}}this._mouseMoveDelegate=function(d){return b._mouseMove(d)};this._mouseUpDelegate=function(d){return b._mouseUp(d)};c(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);a.preventDefault();return a.originalEvent.mouseHandled=true}},_mouseMove:function(a){if(c.browser.msie&&!(document.documentMode>=9)&&!a.button)return this._mouseUp(a);if(this._mouseStarted){this._mouseDrag(a);
48
+ return a.preventDefault()}if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,a)!==false)?this._mouseDrag(a):this._mouseUp(a);return!this._mouseStarted},_mouseUp:function(a){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;a.target==this._mouseDownEvent.target&&c.data(a.target,this.widgetName+".preventClickEvent",
49
+ true);this._mouseStop(a)}return false},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery);
50
+ ;/*
51
+ * jQuery UI Sortable 1.8.10
52
+ *
53
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
54
+ * Dual licensed under the MIT or GPL Version 2 licenses.
55
+ * http://jquery.org/license
56
+ *
57
+ * http://docs.jquery.com/UI/Sortables
58
+ *
59
+ * Depends:
60
+ * jquery.ui.core.js
61
+ * jquery.ui.mouse.js
62
+ * jquery.ui.widget.js
63
+ */
64
+ (function(d){d.widget("ui.sortable",d.ui.mouse,{widgetEventPrefix:"sort",options:{appendTo:"parent",axis:false,connectWith:false,containment:false,cursor:"auto",cursorAt:false,dropOnEmpty:true,forcePlaceholderSize:false,forceHelperSize:false,grid:false,handle:false,helper:"original",items:"> *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1E3},_create:function(){this.containerCache={};this.element.addClass("ui-sortable");
65
+ this.refresh();this.floating=this.items.length?/left|right/.test(this.items[0].item.css("float")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var a=this.items.length-1;a>=0;a--)this.items[a].item.removeData("sortable-item");return this},_setOption:function(a,b){if(a==="disabled"){this.options[a]=b;this.widget()[b?"addClass":"removeClass"]("ui-sortable-disabled")}else d.Widget.prototype._setOption.apply(this,
66
+ arguments)},_mouseCapture:function(a,b){if(this.reverting)return false;if(this.options.disabled||this.options.type=="static")return false;this._refreshItems(a);var c=null,e=this;d(a.target).parents().each(function(){if(d.data(this,"sortable-item")==e){c=d(this);return false}});if(d.data(a.target,"sortable-item")==e)c=d(a.target);if(!c)return false;if(this.options.handle&&!b){var f=false;d(this.options.handle,c).find("*").andSelf().each(function(){if(this==a.target)f=true});if(!f)return false}this.currentItem=
67
+ c;this._removeCurrentsFromItems();return true},_mouseStart:function(a,b,c){b=this.options;var e=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(a);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");d.extend(this.offset,
68
+ {click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]};this.helper[0]!=this.currentItem[0]&&this.currentItem.hide();this._createPlaceholder();b.containment&&this._setContainment();
69
+ if(b.cursor){if(d("body").css("cursor"))this._storedCursor=d("body").css("cursor");d("body").css("cursor",b.cursor)}if(b.opacity){if(this.helper.css("opacity"))this._storedOpacity=this.helper.css("opacity");this.helper.css("opacity",b.opacity)}if(b.zIndex){if(this.helper.css("zIndex"))this._storedZIndex=this.helper.css("zIndex");this.helper.css("zIndex",b.zIndex)}if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML")this.overflowOffset=this.scrollParent.offset();this._trigger("start",
70
+ a,this._uiHash());this._preserveHelperProportions||this._cacheHelperProportions();if(!c)for(c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("activate",a,e._uiHash(this));if(d.ui.ddmanager)d.ui.ddmanager.current=this;d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(a);return true},_mouseDrag:function(a){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");
71
+ if(!this.lastPositionAbs)this.lastPositionAbs=this.positionAbs;if(this.options.scroll){var b=this.options,c=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if(this.overflowOffset.top+this.scrollParent[0].offsetHeight-a.pageY<b.scrollSensitivity)this.scrollParent[0].scrollTop=c=this.scrollParent[0].scrollTop+b.scrollSpeed;else if(a.pageY-this.overflowOffset.top<b.scrollSensitivity)this.scrollParent[0].scrollTop=c=this.scrollParent[0].scrollTop-b.scrollSpeed;if(this.overflowOffset.left+
72
+ this.scrollParent[0].offsetWidth-a.pageX<b.scrollSensitivity)this.scrollParent[0].scrollLeft=c=this.scrollParent[0].scrollLeft+b.scrollSpeed;else if(a.pageX-this.overflowOffset.left<b.scrollSensitivity)this.scrollParent[0].scrollLeft=c=this.scrollParent[0].scrollLeft-b.scrollSpeed}else{if(a.pageY-d(document).scrollTop()<b.scrollSensitivity)c=d(document).scrollTop(d(document).scrollTop()-b.scrollSpeed);else if(d(window).height()-(a.pageY-d(document).scrollTop())<b.scrollSensitivity)c=d(document).scrollTop(d(document).scrollTop()+
73
+ b.scrollSpeed);if(a.pageX-d(document).scrollLeft()<b.scrollSensitivity)c=d(document).scrollLeft(d(document).scrollLeft()-b.scrollSpeed);else if(d(window).width()-(a.pageX-d(document).scrollLeft())<b.scrollSensitivity)c=d(document).scrollLeft(d(document).scrollLeft()+b.scrollSpeed)}c!==false&&d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a)}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+
74
+ "px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";for(b=this.items.length-1;b>=0;b--){c=this.items[b];var e=c.item[0],f=this._intersectsWithPointer(c);if(f)if(e!=this.currentItem[0]&&this.placeholder[f==1?"next":"prev"]()[0]!=e&&!d.ui.contains(this.placeholder[0],e)&&(this.options.type=="semi-dynamic"?!d.ui.contains(this.element[0],e):true)){this.direction=f==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(c))this._rearrange(a,
75
+ c);else break;this._trigger("change",a,this._uiHash());break}}this._contactContainers(a);d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);this._trigger("sort",a,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(a,b){if(a){d.ui.ddmanager&&!this.options.dropBehaviour&&d.ui.ddmanager.drop(this,a);if(this.options.revert){var c=this;b=c.placeholder.offset();c.reverting=true;d(this.helper).animate({left:b.left-this.offset.parent.left-c.margins.left+(this.offsetParent[0]==
76
+ document.body?0:this.offsetParent[0].scrollLeft),top:b.top-this.offset.parent.top-c.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){c._clear(a)})}else this._clear(a,b);return false}},cancel:function(){var a=this;if(this.dragging){this._mouseUp({target:null});this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var b=this.containers.length-
77
+ 1;b>=0;b--){this.containers[b]._trigger("deactivate",null,a._uiHash(this));if(this.containers[b].containerCache.over){this.containers[b]._trigger("out",null,a._uiHash(this));this.containers[b].containerCache.over=0}}}if(this.placeholder){this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove();d.extend(this,{helper:null,dragging:false,reverting:false,_noFinalSort:null});
78
+ this.domPosition.prev?d(this.domPosition.prev).after(this.currentItem):d(this.domPosition.parent).prepend(this.currentItem)}return this},serialize:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};d(b).each(function(){var e=(d(a.item||this).attr(a.attribute||"id")||"").match(a.expression||/(.+)[-=_](.+)/);if(e)c.push((a.key||e[1]+"[]")+"="+(a.key&&a.expression?e[1]:e[2]))});!c.length&&a.key&&c.push(a.key+"=");return c.join("&")},toArray:function(a){var b=this._getItemsAsjQuery(a&&
79
+ a.connected),c=[];a=a||{};b.each(function(){c.push(d(a.item||this).attr(a.attribute||"id")||"")});return c},_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,e=this.positionAbs.top,f=e+this.helperProportions.height,g=a.left,h=g+a.width,i=a.top,k=i+a.height,j=this.offset.click.top,l=this.offset.click.left;j=e+j>i&&e+j<k&&b+l>g&&b+l<h;return this.options.tolerance=="pointer"||this.options.forcePointerForContainers||this.options.tolerance!="pointer"&&this.helperProportions[this.floating?
80
+ "width":"height"]>a[this.floating?"width":"height"]?j:g<b+this.helperProportions.width/2&&c-this.helperProportions.width/2<h&&i<e+this.helperProportions.height/2&&f-this.helperProportions.height/2<k},_intersectsWithPointer:function(a){var b=d.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,a.top,a.height);a=d.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,a.left,a.width);b=b&&a;a=this._getDragVerticalDirection();var c=this._getDragHorizontalDirection();if(!b)return false;return this.floating?
81
+ c&&c=="right"||a=="down"?2:1:a&&(a=="down"?2:1)},_intersectsWithSides:function(a){var b=d.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,a.top+a.height/2,a.height);a=d.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,a.left+a.width/2,a.width);var c=this._getDragVerticalDirection(),e=this._getDragHorizontalDirection();return this.floating&&e?e=="right"&&a||e=="left"&&!a:c&&(c=="down"&&b||c=="up"&&!b)},_getDragVerticalDirection:function(){var a=this.positionAbs.top-this.lastPositionAbs.top;
82
+ return a!=0&&(a>0?"down":"up")},_getDragHorizontalDirection:function(){var a=this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){this._refreshItems(a);this.refreshPositions();return this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(a){var b=[],c=[],e=this._connectWith();if(e&&a)for(a=e.length-1;a>=0;a--)for(var f=d(e[a]),g=f.length-1;g>=0;g--){var h=
83
+ d.data(f[g],"sortable");if(h&&h!=this&&!h.options.disabled)c.push([d.isFunction(h.options.items)?h.options.items.call(h.element):d(h.options.items,h.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),h])}c.push([d.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):d(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(a=c.length-1;a>=0;a--)c[a][0].each(function(){b.push(this)});
84
+ return d(b)},_removeCurrentsFromItems:function(){for(var a=this.currentItem.find(":data(sortable-item)"),b=0;b<this.items.length;b++)for(var c=0;c<a.length;c++)a[c]==this.items[b].item[0]&&this.items.splice(b,1)},_refreshItems:function(a){this.items=[];this.containers=[this];var b=this.items,c=[[d.isFunction(this.options.items)?this.options.items.call(this.element[0],a,{item:this.currentItem}):d(this.options.items,this.element),this]],e=this._connectWith();if(e)for(var f=e.length-1;f>=0;f--)for(var g=
85
+ d(e[f]),h=g.length-1;h>=0;h--){var i=d.data(g[h],"sortable");if(i&&i!=this&&!i.options.disabled){c.push([d.isFunction(i.options.items)?i.options.items.call(i.element[0],a,{item:this.currentItem}):d(i.options.items,i.element),i]);this.containers.push(i)}}for(f=c.length-1;f>=0;f--){a=c[f][1];e=c[f][0];h=0;for(g=e.length;h<g;h++){i=d(e[h]);i.data("sortable-item",a);b.push({item:i,instance:a,width:0,height:0,left:0,top:0})}}},refreshPositions:function(a){if(this.offsetParent&&this.helper)this.offset.parent=
86
+ this._getParentOffset();for(var b=this.items.length-1;b>=0;b--){var c=this.items[b],e=this.options.toleranceElement?d(this.options.toleranceElement,c.item):c.item;if(!a){c.width=e.outerWidth();c.height=e.outerHeight()}e=e.offset();c.left=e.left;c.top=e.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(b=this.containers.length-1;b>=0;b--){e=this.containers[b].element.offset();this.containers[b].containerCache.left=e.left;this.containers[b].containerCache.top=
87
+ e.top;this.containers[b].containerCache.width=this.containers[b].element.outerWidth();this.containers[b].containerCache.height=this.containers[b].element.outerHeight()}return this},_createPlaceholder:function(a){var b=a||this,c=b.options;if(!c.placeholder||c.placeholder.constructor==String){var e=c.placeholder;c.placeholder={element:function(){var f=d(document.createElement(b.currentItem[0].nodeName)).addClass(e||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];
88
+ if(!e)f.style.visibility="hidden";return f},update:function(f,g){if(!(e&&!c.forcePlaceholderSize)){g.height()||g.height(b.currentItem.innerHeight()-parseInt(b.currentItem.css("paddingTop")||0,10)-parseInt(b.currentItem.css("paddingBottom")||0,10));g.width()||g.width(b.currentItem.innerWidth()-parseInt(b.currentItem.css("paddingLeft")||0,10)-parseInt(b.currentItem.css("paddingRight")||0,10))}}}}b.placeholder=d(c.placeholder.element.call(b.element,b.currentItem));b.currentItem.after(b.placeholder);
89
+ c.placeholder.update(b,b.placeholder)},_contactContainers:function(a){for(var b=null,c=null,e=this.containers.length-1;e>=0;e--)if(!d.ui.contains(this.currentItem[0],this.containers[e].element[0]))if(this._intersectsWith(this.containers[e].containerCache)){if(!(b&&d.ui.contains(this.containers[e].element[0],b.element[0]))){b=this.containers[e];c=e}}else if(this.containers[e].containerCache.over){this.containers[e]._trigger("out",a,this._uiHash(this));this.containers[e].containerCache.over=0}if(b)if(this.containers.length===
90
+ 1){this.containers[c]._trigger("over",a,this._uiHash(this));this.containers[c].containerCache.over=1}else if(this.currentContainer!=this.containers[c]){b=1E4;e=null;for(var f=this.positionAbs[this.containers[c].floating?"left":"top"],g=this.items.length-1;g>=0;g--)if(d.ui.contains(this.containers[c].element[0],this.items[g].item[0])){var h=this.items[g][this.containers[c].floating?"left":"top"];if(Math.abs(h-f)<b){b=Math.abs(h-f);e=this.items[g]}}if(e||this.options.dropOnEmpty){this.currentContainer=
91
+ this.containers[c];e?this._rearrange(a,e,null,true):this._rearrange(a,null,this.containers[c].element,true);this._trigger("change",a,this._uiHash());this.containers[c]._trigger("change",a,this._uiHash(this));this.options.placeholder.update(this.currentContainer,this.placeholder);this.containers[c]._trigger("over",a,this._uiHash(this));this.containers[c].containerCache.over=1}}},_createHelper:function(a){var b=this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a,this.currentItem])):
92
+ b.helper=="clone"?this.currentItem.clone():this.currentItem;a.parents("body").length||d(b.appendTo!="parent"?b.appendTo:this.currentItem[0].parentNode)[0].appendChild(a[0]);if(a[0]==this.currentItem[0])this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")};if(a[0].style.width==""||b.forceHelperSize)a.width(this.currentItem.width());if(a[0].style.height==
93
+ ""||b.forceHelperSize)a.height(this.currentItem.height());return a},_adjustOffsetFromHelper:function(a){if(typeof a=="string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]||0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent=
94
+ this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a={top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"),
95
+ 10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.currentItem.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions=
96
+ {width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var a=this.options;if(a.containment=="parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,d(a.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(d(a.containment=="document"?document:window).height()||
97
+ document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)){var b=d(a.containment)[0];a=d(a.containment).offset();var c=d(b).css("overflow")!="hidden";this.containment=[a.left+(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0)-this.margins.left,a.top+(parseInt(d(b).css("borderTopWidth"),10)||0)+(parseInt(d(b).css("paddingTop"),10)||0)-this.margins.top,a.left+(c?Math.max(b.scrollWidth,
98
+ b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),10)||0)-(parseInt(d(b).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,a.top+(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"),10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=
99
+ document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(c[0].tagName);return{top:b.top+this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():
100
+ e?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(c[0].tagName);if(this.cssPosition=="relative"&&!(this.scrollParent[0]!=document&&this.scrollParent[0]!=this.offsetParent[0]))this.offset.relative=this._getRelativeOffset();var f=a.pageX,g=a.pageY;if(this.originalPosition){if(this.containment){if(a.pageX-
101
+ this.offset.click.left<this.containment[0])f=this.containment[0]+this.offset.click.left;if(a.pageY-this.offset.click.top<this.containment[1])g=this.containment[1]+this.offset.click.top;if(a.pageX-this.offset.click.left>this.containment[2])f=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.top<
102
+ this.containment[1]||g-this.offset.click.top>this.containment[3])?g:!(g-this.offset.click.top<this.containment[1])?g-b.grid[1]:g+b.grid[1]:g;f=this.originalPageX+Math.round((f-this.originalPageX)/b.grid[0])*b.grid[0];f=this.containment?!(f-this.offset.click.left<this.containment[0]||f-this.offset.click.left>this.containment[2])?f:!(f-this.offset.click.left<this.containment[0])?f-b.grid[0]:f+b.grid[0]:f}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(d.browser.safari&&
103
+ this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:c.scrollTop()),left:f-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(d.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:c.scrollLeft())}},_rearrange:function(a,b,c,e){c?c[0].appendChild(this.placeholder[0]):b.item[0].parentNode.insertBefore(this.placeholder[0],this.direction=="down"?b.item[0]:b.item[0].nextSibling);this.counter=
104
+ this.counter?++this.counter:1;var f=this,g=this.counter;window.setTimeout(function(){g==f.counter&&f.refreshPositions(!e)},0)},_clear:function(a,b){this.reverting=false;var c=[];!this._noFinalSort&&this.currentItem[0].parentNode&&this.placeholder.before(this.currentItem);this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var e in this._storedCSS)if(this._storedCSS[e]=="auto"||this._storedCSS[e]=="static")this._storedCSS[e]="";this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();
105
+ this.fromOutside&&!b&&c.push(function(f){this._trigger("receive",f,this._uiHash(this.fromOutside))});if((this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||this.domPosition.parent!=this.currentItem.parent()[0])&&!b)c.push(function(f){this._trigger("update",f,this._uiHash())});if(!d.ui.contains(this.element[0],this.currentItem[0])){b||c.push(function(f){this._trigger("remove",f,this._uiHash())});for(e=this.containers.length-1;e>=0;e--)if(d.ui.contains(this.containers[e].element[0],
106
+ this.currentItem[0])&&!b){c.push(function(f){return function(g){f._trigger("receive",g,this._uiHash(this))}}.call(this,this.containers[e]));c.push(function(f){return function(g){f._trigger("update",g,this._uiHash(this))}}.call(this,this.containers[e]))}}for(e=this.containers.length-1;e>=0;e--){b||c.push(function(f){return function(g){f._trigger("deactivate",g,this._uiHash(this))}}.call(this,this.containers[e]));if(this.containers[e].containerCache.over){c.push(function(f){return function(g){f._trigger("out",
107
+ g,this._uiHash(this))}}.call(this,this.containers[e]));this.containers[e].containerCache.over=0}}this._storedCursor&&d("body").css("cursor",this._storedCursor);this._storedOpacity&&this.helper.css("opacity",this._storedOpacity);if(this._storedZIndex)this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex);this.dragging=false;if(this.cancelHelperRemoval){if(!b){this._trigger("beforeStop",a,this._uiHash());for(e=0;e<c.length;e++)c[e].call(this,a);this._trigger("stop",a,this._uiHash())}return false}b||
108
+ this._trigger("beforeStop",a,this._uiHash());this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.helper[0]!=this.currentItem[0]&&this.helper.remove();this.helper=null;if(!b){for(e=0;e<c.length;e++)c[e].call(this,a);this._trigger("stop",a,this._uiHash())}this.fromOutside=false;return true},_trigger:function(){d.Widget.prototype._trigger.apply(this,arguments)===false&&this.cancel()},_uiHash:function(a){var b=a||this;return{helper:b.helper,placeholder:b.placeholder||d([]),position:b.position,
109
+ originalPosition:b.originalPosition,offset:b.positionAbs,item:b.currentItem,sender:a?a.element:null}}});d.extend(d.ui.sortable,{version:"1.8.10"})})(jQuery);
110
+ ;
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Unobtrusive scripting adapter for jQuery
3
+ *
4
+ * Requires jQuery 1.4.3 or later.
5
+ * https://github.com/rails/jquery-ujs
6
+ */
7
+
8
+ (function($) {
9
+ // Make sure that every Ajax request sends the CSRF token
10
+ function CSRFProtection(xhr) {
11
+ var token = $('meta[name="csrf-token"]').attr('content');
12
+ if (token) xhr.setRequestHeader('X-CSRF-Token', token);
13
+ }
14
+ if ('ajaxPrefilter' in $) $.ajaxPrefilter(function(options, originalOptions, xhr){ CSRFProtection(xhr) });
15
+ else $(document).ajaxSend(function(e, xhr){ CSRFProtection(xhr) });
16
+
17
+ // Triggers an event on an element and returns the event result
18
+ function fire(obj, name, data) {
19
+ var event = new $.Event(name);
20
+ obj.trigger(event, data);
21
+ return event.result !== false;
22
+ }
23
+
24
+ // Submits "remote" forms and links with ajax
25
+ function handleRemote(element) {
26
+ var method, url, data,
27
+ dataType = element.attr('data-type') || ($.ajaxSettings && $.ajaxSettings.dataType);
28
+
29
+ if (element.is('form')) {
30
+ method = element.attr('method');
31
+ url = element.attr('action');
32
+ data = element.serializeArray();
33
+ // memoized value from clicked submit button
34
+ var button = element.data('ujs:submit-button');
35
+ if (button) {
36
+ data.push(button);
37
+ element.data('ujs:submit-button', null);
38
+ }
39
+ } else {
40
+ method = element.attr('data-method');
41
+ url = element.attr('href');
42
+ data = null;
43
+ }
44
+
45
+ $.ajax({
46
+ url: url, type: method || 'GET', data: data, dataType: dataType,
47
+ // stopping the "ajax:beforeSend" event will cancel the ajax request
48
+ beforeSend: function(xhr, settings) {
49
+ if (settings.dataType === undefined) {
50
+ xhr.setRequestHeader('accept', '*/*;q=0.5, ' + settings.accepts.script);
51
+ }
52
+ return fire(element, 'ajax:beforeSend', [xhr, settings]);
53
+ },
54
+ success: function(data, status, xhr) {
55
+ element.trigger('ajax:success', [data, status, xhr]);
56
+ },
57
+ complete: function(xhr, status) {
58
+ element.trigger('ajax:complete', [xhr, status]);
59
+ },
60
+ error: function(xhr, status, error) {
61
+ element.trigger('ajax:error', [xhr, status, error]);
62
+ }
63
+ });
64
+ }
65
+
66
+ // Handles "data-method" on links such as:
67
+ // <a href="/users/5" data-method="delete" rel="nofollow" data-confirm="Are you sure?">Delete</a>
68
+ function handleMethod(link) {
69
+ var href = link.attr('href'),
70
+ method = link.attr('data-method'),
71
+ csrf_token = $('meta[name=csrf-token]').attr('content'),
72
+ csrf_param = $('meta[name=csrf-param]').attr('content'),
73
+ form = $('<form method="post" action="' + href + '"></form>'),
74
+ metadata_input = '<input name="_method" value="' + method + '" type="hidden" />';
75
+
76
+ if (csrf_param !== undefined && csrf_token !== undefined) {
77
+ metadata_input += '<input name="' + csrf_param + '" value="' + csrf_token + '" type="hidden" />';
78
+ }
79
+
80
+ form.hide().append(metadata_input).appendTo('body');
81
+ form.submit();
82
+ }
83
+
84
+ function disableFormElements(form) {
85
+ form.find('input[data-disable-with]').each(function() {
86
+ var input = $(this);
87
+ input.data('ujs:enable-with', input.val())
88
+ .val(input.attr('data-disable-with'))
89
+ .attr('disabled', 'disabled');
90
+ });
91
+ }
92
+
93
+ function enableFormElements(form) {
94
+ form.find('input[data-disable-with]').each(function() {
95
+ var input = $(this);
96
+ input.val(input.data('ujs:enable-with')).removeAttr('disabled');
97
+ });
98
+ }
99
+
100
+ function allowAction(element) {
101
+ var message = element.attr('data-confirm');
102
+ return !message || (fire(element, 'confirm') && confirm(message));
103
+ }
104
+
105
+ function requiredValuesMissing(form) {
106
+ var missing = false;
107
+ form.find('input[name][required]').each(function() {
108
+ if (!$(this).val()) missing = true;
109
+ });
110
+ return missing;
111
+ }
112
+
113
+ $('a[data-confirm], a[data-method], a[data-remote]').live('click.rails', function(e) {
114
+ var link = $(this);
115
+ if (!allowAction(link)) return false;
116
+
117
+ if (link.attr('data-remote') != undefined) {
118
+ handleRemote(link);
119
+ return false;
120
+ } else if (link.attr('data-method')) {
121
+ handleMethod(link);
122
+ return false;
123
+ }
124
+ });
125
+
126
+ $('form').live('submit.rails', function(e) {
127
+ var form = $(this), remote = form.attr('data-remote') != undefined;
128
+ if (!allowAction(form)) return false;
129
+
130
+ // skip other logic when required values are missing
131
+ if (requiredValuesMissing(form)) return !remote;
132
+
133
+ if (remote) {
134
+ handleRemote(form);
135
+ return false;
136
+ } else {
137
+ // slight timeout so that the submit button gets properly serialized
138
+ setTimeout(function(){ disableFormElements(form) }, 13);
139
+ }
140
+ });
141
+
142
+ $('form input[type=submit], form button[type=submit], form button:not([type])').live('click.rails', function() {
143
+ var button = $(this);
144
+ if (!allowAction(button)) return false;
145
+ // register the pressed submit button
146
+ var name = button.attr('name'), data = name ? {name:name, value:button.val()} : null;
147
+ button.closest('form').data('ujs:submit-button', data);
148
+ });
149
+
150
+ $('form').live('ajax:beforeSend.rails', function(event) {
151
+ if (this == event.target) disableFormElements($(this));
152
+ });
153
+
154
+ $('form').live('ajax:complete.rails', function(event) {
155
+ if (this == event.target) enableFormElements($(this));
156
+ });
157
+ })( jQuery );
@@ -8,6 +8,8 @@ Factory.define :localized_page, :class => Kuhsaft::LocalizedPage do |p|
8
8
  p.locale 'en'
9
9
  p.title 'English title'
10
10
  p.published 1
11
+ p.body 'hi'
12
+ p.url ''
11
13
  p.association :page
12
14
  p.after_create do |page|
13
15
  page.page_parts << Factory.build(:page_part, :localized_page => page)
@@ -45,23 +45,22 @@ describe Kuhsaft::LocalizedPage do
45
45
  Factory.create(:localized_page).page_parts.count.should be(1)
46
46
  end
47
47
 
48
+ it 'should delegate childs to it\'s page' do
49
+ @localized_page.childs.should == @localized_page.page.childs
50
+ end
51
+
48
52
  describe 'validations' do
49
- it 'should have a title' do
50
- localized_page = Kuhsaft::LocalizedPage.new
51
- localized_page.save
52
- localized_page.should have(1).error_on(:title)
53
+
54
+ before :each do
55
+ @page = Factory.create :page
53
56
  end
54
57
 
55
- it 'should have a locale' do
56
- localized_page = Kuhsaft::LocalizedPage.new
57
- localized_page.save
58
- localized_page.should have(1).error_on(:locale)
58
+ it 'should have a title' do
59
+ @page.translation.should have(1).error_on(:title)
59
60
  end
60
61
 
61
62
  it 'should have a slug' do
62
- localized_page = Kuhsaft::LocalizedPage.new
63
- localized_page.save
64
- localized_page.should have(1).error_on(:slug)
63
+ @page.translation.should have(1).error_on(:slug)
65
64
  end
66
65
  end
67
66
  end
@@ -4,6 +4,7 @@ describe Kuhsaft::Page do
4
4
 
5
5
  before do
6
6
  Kuhsaft::Page.translation_locales = ['en', 'de']
7
+ Kuhsaft::Page.current_translation_locale = :en
7
8
  end
8
9
 
9
10
  before :each do
@@ -87,12 +88,46 @@ describe Kuhsaft::Page do
87
88
  page2.position.should == 1
88
89
  end
89
90
 
90
- it 'should save the localized_page when saved' do
91
- @page.localized_page.title = 'some localized title'
91
+ it 'should save the translation when saved' do
92
+ @page.translation.title = 'some localized title'
92
93
  @page.should_receive(:save_translation)
93
94
  @page.save
94
95
  end
95
96
 
97
+ it 'should have an url when saved' do
98
+ page = Factory.create :page
99
+ page.url.should == 'en/english-title'
100
+ end
101
+
102
+ it 'should have a link' do
103
+ page = Factory.create :page
104
+ page.link.should == '/en/english-title'
105
+ end
106
+
107
+ it 'should include the parents slug in its url' do
108
+ page = Factory.create :page
109
+ child = Factory.create :page
110
+ page.childs << child
111
+ page.save
112
+ child.url.should == 'en/english-title/english-title'
113
+ end
114
+
115
+ it 'should return the link of its first child when its empty' do
116
+ page = Factory.create :page
117
+ child = Factory.create :page
118
+ page.childs << child
119
+ page.body = nil
120
+ page.save
121
+ page.link.should == child.link
122
+ end
123
+
124
+ it 'should find its translated content by url' do
125
+ Kuhsaft::Page.all.each { |p| p.destroy }
126
+ Kuhsaft::LocalizedPage.all.each{ |p| p.destroy }
127
+ page = Factory.create(:page)
128
+ Kuhsaft::Page.find_by_url(page.url).id.should == page.id
129
+ end
130
+
96
131
  it 'should provide an array of translation locales' do
97
132
  Kuhsaft::Page.translation_locales.should be_a(Array)
98
133
  end
@@ -113,32 +148,36 @@ describe Kuhsaft::Page do
113
148
 
114
149
  describe 'should delegate property' do
115
150
  it 'should have a localized_page to delegate to' do
116
- @page.localized_page.should be_a(Kuhsaft::LocalizedPage)
151
+ @page.translation.should be_a(Kuhsaft::LocalizedPage)
117
152
  end
118
153
 
119
- it 'should delegate the title to the localized_page' do
154
+ it 'should delegate the title to the translation' do
120
155
  @page.title = 'Hello'
121
- @page.localized_page.title.should == 'Hello'
156
+ @page.translation.title.should == 'Hello'
122
157
  end
123
158
 
124
- it 'should delegate the slug to the localized_page' do
159
+ it 'should delegate the slug to the translation' do
125
160
  @page.slug = 'my-slug'
126
- @page.localized_page.slug.should == 'my-slug'
161
+ @page.translation.slug.should == 'my-slug'
162
+ end
163
+
164
+ it 'should delegate the url to the translation' do
165
+ @page.url.should == @page.translation.url
127
166
  end
128
167
 
129
- it 'should delegate the keywords to the localized_page' do
168
+ it 'should delegate the keywords to the translation' do
130
169
  @page.keywords = 'my keywords are superb'
131
- @page.localized_page.keywords.should == 'my keywords are superb'
170
+ @page.translation.keywords.should == 'my keywords are superb'
132
171
  end
133
172
 
134
- it 'should delegate the description to the localized_page' do
173
+ it 'should delegate the description to the translation' do
135
174
  @page.description = 'my description'
136
- @page.localized_page.description.should == 'my description'
175
+ @page.translation.description.should == 'my description'
137
176
  end
138
177
 
139
- it 'should delegate the locale to the localized_page' do
178
+ it 'should delegate the locale to the translation' do
140
179
  @page.locale = 'de'
141
- @page.localized_page.locale.should == :de
180
+ @page.translation.locale.should == :de
142
181
  end
143
182
  end
144
183
  end
@@ -1,26 +1,13 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'routing to Kuhsaft::PagesController' do
4
- it 'routes /:translation_locale/:slug to pages#show' do
4
+ it 'routes /*url to pages#show' do
5
5
  { :get => '/en/my-slug' }.should route_to(
6
6
  :controller => 'kuhsaft/pages',
7
7
  :action => 'show',
8
- :slug => 'my-slug',
9
- :translation_locale => 'en'
8
+ :url => 'en/my-slug'
10
9
  )
11
10
  end
12
-
13
- it 'does not expose pages#new' do
14
- { :get => '/pages/new' }.should_not be_routable
15
- end
16
-
17
- it 'does not expose pages#edit' do
18
- { :get => '/pages/1/edit' }.should_not be_routable
19
- end
20
-
21
- it 'does not expose pages#destroy' do
22
- { :get => '/pages/1/destroy' }.should_not be_routable
23
- end
24
11
  end
25
12
 
26
13
  describe 'routing to Kuhsaft::Admin::PagesController' do
@@ -10,6 +10,7 @@ Spork.prefork do
10
10
  require 'factory_girl'
11
11
  require "capybara/rails"
12
12
  require 'factories'
13
+ require 'generators/kuhsaft/install/migrations_generator'
13
14
 
14
15
  ActionMailer::Base.delivery_method = :test
15
16
  ActionMailer::Base.perform_deliveries = true
@@ -22,10 +23,8 @@ Spork.prefork do
22
23
  Capybara.default_selector = :css
23
24
 
24
25
  # Drop all records and run any available migration
25
- migrations_source = File.expand_path("../../db/migrate/", __FILE__)
26
- migrations_destination = File.expand_path("../dummy/db/", __FILE__)
27
-
28
- system "cp -R #{migrations_source} #{migrations_destination}"
26
+ Rails::Generators.invoke 'kuhsaft:install:migrations'
27
+
29
28
  ActiveRecord::Base.connection.tables.each { |table| ActiveRecord::Base.connection.drop_table(table) }
30
29
  ActiveRecord::Migrator.migrate File.expand_path("../dummy/db/migrate/", __FILE__)
31
30