From 263bed68bb598cd559792c41972dd56d4923ed32 Mon Sep 17 00:00:00 2001 From: Manson Wang Date: Thu, 16 Jan 2014 17:14:51 +0800 Subject: [PATCH] Orbit Survey Module --- .gitignore | 7 + Gemfile | 17 ++ MIT-LICENSE | 20 ++ README | 0 README.rdoc | 3 + Rakefile | 38 +++ app/assets/javascripts/jquery-ui-custom.js | 6 + app/assets/javascripts/survey.js | 266 ++++++++++++++++++ app/controllers/application_controller.rb | 23 ++ .../back_end/surveys_answers_controller.rb | 29 ++ .../survey/back_end/surveys_controller.rb | 250 ++++++++++++++++ .../survey/front_end/surveys_controller.rb | 113 ++++++++ app/models/survey.rb | 141 ++++++++++ app/models/survey_answer.rb | 7 + app/models/survey_question.rb | 48 ++++ app/models/survey_question_oneline.rb | 3 + app/models/survey_question_option.rb | 8 + app/models/survey_question_radiogroup.rb | 7 + .../survey/back_end/surveys/_filter.html.erb | 11 + .../survey/back_end/surveys/_form.html.erb | 121 ++++++++ .../surveys/_form_survey_question.html.erb | 137 +++++++++ .../_form_survey_question_option.html.erb | 26 ++ .../_form_survey_question_radiogroup.html.erb | 26 ++ .../back_end/surveys/_questions.html.erb | 172 +++++++++++ .../back_end/surveys/_sort_headers.html.erb | 0 .../survey/back_end/surveys/_survey.html.erb | 34 +++ .../survey/back_end/surveys/destroy.js.erb | 1 + .../survey/back_end/surveys/edit.html.erb | 5 + .../survey/back_end/surveys/index.html.erb | 23 ++ .../survey/back_end/surveys/index.js.erb | 4 + .../survey/back_end/surveys/jump.html.erb | 56 ++++ .../survey/back_end/surveys/new.html.erb | 6 + .../back_end/surveys/set_answers.html.erb | 34 +++ .../back_end/surveys_answers/_answer.html.erb | 22 ++ .../back_end/surveys_answers/_filter.html.erb | 11 + .../surveys_answers/_sort_headers.html.erb | 7 + .../back_end/surveys_answers/index.html.erb | 23 ++ .../back_end/surveys_answers/index.js.erb | 4 + .../front_end/surveys/_answer_error.erb | 1 + .../front_end/surveys/_answer_success.erb | 2 + .../front_end/surveys/answer_error.html.erb | 4 + .../front_end/surveys/answer_error.js.erb | 1 + .../front_end/surveys/answer_success.html.erb | 4 + .../front_end/surveys/answer_success.js.erb | 1 + .../surveys/redirect_standalone.html.erb | 3 + .../survey/front_end/surveys/result.html.erb | 77 +++++ .../survey/front_end/surveys/show.html.erb | 167 +++++++++++ config/locales/en.yml | 83 ++++++ config/locales/zh_tw.yml | 83 ++++++ config/routes.rb | 33 +++ lib/survey.rb | 58 ++++ lib/tasks/survey_tasks.rake | 4 + survey.gemspec | 19 ++ survey.json | 12 + test/dummy/README.rdoc | 261 +++++++++++++++++ test/dummy/Rakefile | 7 + .../app/assets/javascripts/application.js | 15 + .../app/assets/stylesheets/application.css | 13 + .../app/controllers/application_controller.rb | 3 + test/dummy/app/helpers/application_helper.rb | 2 + test/dummy/app/mailers/.gitkeep | 0 test/dummy/app/models/.gitkeep | 0 .../app/views/layouts/application.html.erb | 14 + test/dummy/config.ru | 4 + test/dummy/config/application.rb | 59 ++++ test/dummy/config/boot.rb | 10 + test/dummy/config/database.yml | 25 ++ test/dummy/config/environment.rb | 5 + test/dummy/config/environments/development.rb | 37 +++ test/dummy/config/environments/production.rb | 67 +++++ test/dummy/config/environments/test.rb | 37 +++ .../initializers/backtrace_silencers.rb | 7 + test/dummy/config/initializers/inflections.rb | 15 + test/dummy/config/initializers/mime_types.rb | 5 + .../dummy/config/initializers/secret_token.rb | 7 + .../config/initializers/session_store.rb | 8 + .../config/initializers/wrap_parameters.rb | 14 + test/dummy/config/locales/en.yml | 5 + test/dummy/config/routes.rb | 58 ++++ test/dummy/lib/assets/.gitkeep | 0 test/dummy/log/.gitkeep | 0 test/dummy/public/404.html | 26 ++ test/dummy/public/422.html | 26 ++ test/dummy/public/500.html | 25 ++ test/dummy/public/favicon.ico | 0 test/dummy/script/rails | 6 + test/survey_test.rb | 7 + test/test_helper.rb | 15 + 88 files changed, 3044 insertions(+) create mode 100644 .gitignore create mode 100644 Gemfile create mode 100644 MIT-LICENSE create mode 100644 README create mode 100644 README.rdoc create mode 100644 Rakefile create mode 100644 app/assets/javascripts/jquery-ui-custom.js create mode 100644 app/assets/javascripts/survey.js create mode 100644 app/controllers/application_controller.rb create mode 100644 app/controllers/panel/survey/back_end/surveys_answers_controller.rb create mode 100644 app/controllers/panel/survey/back_end/surveys_controller.rb create mode 100644 app/controllers/panel/survey/front_end/surveys_controller.rb create mode 100644 app/models/survey.rb create mode 100644 app/models/survey_answer.rb create mode 100644 app/models/survey_question.rb create mode 100644 app/models/survey_question_oneline.rb create mode 100644 app/models/survey_question_option.rb create mode 100644 app/models/survey_question_radiogroup.rb create mode 100644 app/views/panel/survey/back_end/surveys/_filter.html.erb create mode 100644 app/views/panel/survey/back_end/surveys/_form.html.erb create mode 100644 app/views/panel/survey/back_end/surveys/_form_survey_question.html.erb create mode 100644 app/views/panel/survey/back_end/surveys/_form_survey_question_option.html.erb create mode 100644 app/views/panel/survey/back_end/surveys/_form_survey_question_radiogroup.html.erb create mode 100644 app/views/panel/survey/back_end/surveys/_questions.html.erb create mode 100644 app/views/panel/survey/back_end/surveys/_sort_headers.html.erb create mode 100644 app/views/panel/survey/back_end/surveys/_survey.html.erb create mode 100644 app/views/panel/survey/back_end/surveys/destroy.js.erb create mode 100644 app/views/panel/survey/back_end/surveys/edit.html.erb create mode 100644 app/views/panel/survey/back_end/surveys/index.html.erb create mode 100644 app/views/panel/survey/back_end/surveys/index.js.erb create mode 100644 app/views/panel/survey/back_end/surveys/jump.html.erb create mode 100644 app/views/panel/survey/back_end/surveys/new.html.erb create mode 100644 app/views/panel/survey/back_end/surveys/set_answers.html.erb create mode 100644 app/views/panel/survey/back_end/surveys_answers/_answer.html.erb create mode 100644 app/views/panel/survey/back_end/surveys_answers/_filter.html.erb create mode 100644 app/views/panel/survey/back_end/surveys_answers/_sort_headers.html.erb create mode 100644 app/views/panel/survey/back_end/surveys_answers/index.html.erb create mode 100644 app/views/panel/survey/back_end/surveys_answers/index.js.erb create mode 100644 app/views/panel/survey/front_end/surveys/_answer_error.erb create mode 100644 app/views/panel/survey/front_end/surveys/_answer_success.erb create mode 100644 app/views/panel/survey/front_end/surveys/answer_error.html.erb create mode 100644 app/views/panel/survey/front_end/surveys/answer_error.js.erb create mode 100644 app/views/panel/survey/front_end/surveys/answer_success.html.erb create mode 100644 app/views/panel/survey/front_end/surveys/answer_success.js.erb create mode 100644 app/views/panel/survey/front_end/surveys/redirect_standalone.html.erb create mode 100644 app/views/panel/survey/front_end/surveys/result.html.erb create mode 100644 app/views/panel/survey/front_end/surveys/show.html.erb create mode 100644 config/locales/en.yml create mode 100644 config/locales/zh_tw.yml create mode 100644 config/routes.rb create mode 100644 lib/survey.rb create mode 100644 lib/tasks/survey_tasks.rake create mode 100644 survey.gemspec create mode 100644 survey.json create mode 100644 test/dummy/README.rdoc create mode 100644 test/dummy/Rakefile create mode 100644 test/dummy/app/assets/javascripts/application.js create mode 100644 test/dummy/app/assets/stylesheets/application.css create mode 100644 test/dummy/app/controllers/application_controller.rb create mode 100644 test/dummy/app/helpers/application_helper.rb create mode 100644 test/dummy/app/mailers/.gitkeep create mode 100644 test/dummy/app/models/.gitkeep create mode 100644 test/dummy/app/views/layouts/application.html.erb create mode 100644 test/dummy/config.ru create mode 100644 test/dummy/config/application.rb create mode 100644 test/dummy/config/boot.rb create mode 100644 test/dummy/config/database.yml create mode 100644 test/dummy/config/environment.rb create mode 100644 test/dummy/config/environments/development.rb create mode 100644 test/dummy/config/environments/production.rb create mode 100644 test/dummy/config/environments/test.rb create mode 100644 test/dummy/config/initializers/backtrace_silencers.rb create mode 100644 test/dummy/config/initializers/inflections.rb create mode 100644 test/dummy/config/initializers/mime_types.rb create mode 100644 test/dummy/config/initializers/secret_token.rb create mode 100644 test/dummy/config/initializers/session_store.rb create mode 100644 test/dummy/config/initializers/wrap_parameters.rb create mode 100644 test/dummy/config/locales/en.yml create mode 100644 test/dummy/config/routes.rb create mode 100644 test/dummy/lib/assets/.gitkeep create mode 100644 test/dummy/log/.gitkeep create mode 100644 test/dummy/public/404.html create mode 100644 test/dummy/public/422.html create mode 100644 test/dummy/public/500.html create mode 100644 test/dummy/public/favicon.ico create mode 100755 test/dummy/script/rails create mode 100644 test/survey_test.rb create mode 100644 test/test_helper.rb diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1dfe31e --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +.bundle/ +log/*.log +pkg/ +test/dummy/db/*.sqlite3 +test/dummy/log/*.log +test/dummy/tmp/ +test/dummy/.sass-cache diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..e57f76d --- /dev/null +++ b/Gemfile @@ -0,0 +1,17 @@ +source "http://rubygems.org" + +# Declare your gem's dependencies in survey.gemspec. +# Bundler will treat runtime dependencies like base dependencies, and +# development dependencies will be added by default to the :development group. +gemspec + +# jquery-rails is used by the dummy application +gem "jquery-rails" + +# Declare any dependencies that are still in development here instead of in +# your gemspec. These might include edge Rails or gems from your path or +# Git. Remember to move these dependencies to your gemspec before releasing +# your gem to rubygems.org. + +# To use debugger +# gem 'debugger' diff --git a/MIT-LICENSE b/MIT-LICENSE new file mode 100644 index 0000000..5146945 --- /dev/null +++ b/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright 2013 YOURNAME + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README b/README new file mode 100644 index 0000000..e69de29 diff --git a/README.rdoc b/README.rdoc new file mode 100644 index 0000000..e5883aa --- /dev/null +++ b/README.rdoc @@ -0,0 +1,3 @@ += Survey + +This project rocks and uses MIT-LICENSE. \ No newline at end of file diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..55c452f --- /dev/null +++ b/Rakefile @@ -0,0 +1,38 @@ +#!/usr/bin/env rake +begin + require 'bundler/setup' +rescue LoadError + puts 'You must `gem install bundler` and `bundle install` to run rake tasks' +end +begin + require 'rdoc/task' +rescue LoadError + require 'rdoc/rdoc' + require 'rake/rdoctask' + RDoc::Task = Rake::RDocTask +end + +RDoc::Task.new(:rdoc) do |rdoc| + rdoc.rdoc_dir = 'rdoc' + rdoc.title = 'Survey' + rdoc.options << '--line-numbers' + rdoc.rdoc_files.include('README.rdoc') + rdoc.rdoc_files.include('lib/**/*.rb') +end + + + + +Bundler::GemHelper.install_tasks + +require 'rake/testtask' + +Rake::TestTask.new(:test) do |t| + t.libs << 'lib' + t.libs << 'test' + t.pattern = 'test/**/*_test.rb' + t.verbose = false +end + + +task :default => :test diff --git a/app/assets/javascripts/jquery-ui-custom.js b/app/assets/javascripts/jquery-ui-custom.js new file mode 100644 index 0000000..3fb1ff6 --- /dev/null +++ b/app/assets/javascripts/jquery-ui-custom.js @@ -0,0 +1,6 @@ +/*! jQuery UI - v1.10.3 - 2013-06-05 +* http://jqueryui.com +* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.ui.tooltip.js +* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */ + +(function(e,t){function i(t,i){var a,n,r,o=t.nodeName.toLowerCase();return"area"===o?(a=t.parentNode,n=a.name,t.href&&n&&"map"===a.nodeName.toLowerCase()?(r=e("img[usemap=#"+n+"]")[0],!!r&&s(r)):!1):(/input|select|textarea|button|object/.test(o)?!t.disabled:"a"===o?t.href||i:i)&&s(t)}function s(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}var a=0,n=/^ui-id-\d+$/;e.ui=e.ui||{},e.extend(e.ui,{version:"1.10.3",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({focus:function(t){return function(i,s){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),s&&s.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),scrollParent:function(){var t;return t=e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(i){if(i!==t)return this.css("zIndex",i);if(this.length)for(var s,a,n=e(this[0]);n.length&&n[0]!==document;){if(s=n.css("position"),("absolute"===s||"relative"===s||"fixed"===s)&&(a=parseInt(n.css("zIndex"),10),!isNaN(a)&&0!==a))return a;n=n.parent()}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++a)})},removeUniqueId:function(){return this.each(function(){n.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,s){return!!e.data(t,s[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var s=e.attr(t,"tabindex"),a=isNaN(s);return(a||s>=0)&&i(t,!a)}}),e("").outerWidth(1).jquery||e.each(["Width","Height"],function(i,s){function a(t,i,s,a){return e.each(n,function(){i-=parseFloat(e.css(t,"padding"+this))||0,s&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),a&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var n="Width"===s?["Left","Right"]:["Top","Bottom"],r=s.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+s]=function(i){return i===t?o["inner"+s].call(this):this.each(function(){e(this).css(r,a(this,i)+"px")})},e.fn["outer"+s]=function(t,i){return"number"!=typeof t?o["outer"+s].call(this,t):this.each(function(){e(this).css(r,a(this,t,!0,i)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart="onselectstart"in document.createElement("div"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,i,s){var a,n=e.ui[t].prototype;for(a in s)n.plugins[a]=n.plugins[a]||[],n.plugins[a].push([i,s[a]])},call:function(e,t,i){var s,a=e.plugins[t];if(a&&e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType)for(s=0;a.length>s;s++)e.options[a[s][0]]&&a[s][1].apply(e.element,i)}},hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",a=!1;return t[s]>0?!0:(t[s]=1,a=t[s]>0,t[s]=0,a)}})})(jQuery);(function(e,t){var i=0,s=Array.prototype.slice,n=e.cleanData;e.cleanData=function(t){for(var i,s=0;null!=(i=t[s]);s++)try{e(i).triggerHandler("remove")}catch(a){}n(t)},e.widget=function(i,s,n){var a,r,o,h,l={},u=i.split(".")[0];i=i.split(".")[1],a=u+"-"+i,n||(n=s,s=e.Widget),e.expr[":"][a.toLowerCase()]=function(t){return!!e.data(t,a)},e[u]=e[u]||{},r=e[u][i],o=e[u][i]=function(e,i){return this._createWidget?(arguments.length&&this._createWidget(e,i),t):new o(e,i)},e.extend(o,r,{version:n.version,_proto:e.extend({},n),_childConstructors:[]}),h=new s,h.options=e.widget.extend({},h.options),e.each(n,function(i,n){return e.isFunction(n)?(l[i]=function(){var e=function(){return s.prototype[i].apply(this,arguments)},t=function(e){return s.prototype[i].apply(this,e)};return function(){var i,s=this._super,a=this._superApply;return this._super=e,this._superApply=t,i=n.apply(this,arguments),this._super=s,this._superApply=a,i}}(),t):(l[i]=n,t)}),o.prototype=e.widget.extend(h,{widgetEventPrefix:r?h.widgetEventPrefix:i},l,{constructor:o,namespace:u,widgetName:i,widgetFullName:a}),r?(e.each(r._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete r._childConstructors):s._childConstructors.push(o),e.widget.bridge(i,o)},e.widget.extend=function(i){for(var n,a,r=s.call(arguments,1),o=0,h=r.length;h>o;o++)for(n in r[o])a=r[o][n],r[o].hasOwnProperty(n)&&a!==t&&(i[n]=e.isPlainObject(a)?e.isPlainObject(i[n])?e.widget.extend({},i[n],a):e.widget.extend({},a):a);return i},e.widget.bridge=function(i,n){var a=n.prototype.widgetFullName||i;e.fn[i]=function(r){var o="string"==typeof r,h=s.call(arguments,1),l=this;return r=!o&&h.length?e.widget.extend.apply(null,[r].concat(h)):r,o?this.each(function(){var s,n=e.data(this,a);return n?e.isFunction(n[r])&&"_"!==r.charAt(0)?(s=n[r].apply(n,h),s!==n&&s!==t?(l=s&&s.jquery?l.pushStack(s.get()):s,!1):t):e.error("no such method '"+r+"' for "+i+" widget instance"):e.error("cannot call methods on "+i+" prior to initialization; "+"attempted to call method '"+r+"'")}):this.each(function(){var t=e.data(this,a);t?t.option(r||{})._init():e.data(this,a,new n(r,this))}),l}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
",options:{disabled:!1,create:null},_createWidget:function(t,s){s=e(s||this.defaultElement||this)[0],this.element=e(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),s!==this&&(e.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===s&&this.destroy()}}),this.document=e(s.style?s.ownerDocument:s.document||s),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(i,s){var n,a,r,o=i;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof i)if(o={},n=i.split("."),i=n.shift(),n.length){for(a=o[i]=e.widget.extend({},this.options[i]),r=0;n.length-1>r;r++)a[n[r]]=a[n[r]]||{},a=a[n[r]];if(i=n.pop(),s===t)return a[i]===t?null:a[i];a[i]=s}else{if(s===t)return this.options[i]===t?null:this.options[i];o[i]=s}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!t).attr("aria-disabled",t),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(i,s,n){var a,r=this;"boolean"!=typeof i&&(n=s,s=i,i=!1),n?(s=a=e(s),this.bindings=this.bindings.add(s)):(n=s,s=this.element,a=this.widget()),e.each(n,function(n,o){function h(){return i||r.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?r[o]:o).apply(r,arguments):t}"string"!=typeof o&&(h.guid=o.guid=o.guid||h.guid||e.guid++);var l=n.match(/^(\w+)\s*(.*)$/),u=l[1]+r.eventNamespace,c=l[2];c?a.delegate(c,u,h):s.bind(u,h)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var n,a,r=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(r)&&r.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,n,a){"string"==typeof n&&(n={effect:n});var r,o=n?n===!0||"number"==typeof n?i:n.effect||i:t;n=n||{},"number"==typeof n&&(n={duration:n}),r=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),r&&e.effects&&e.effects.effect[o]?s[t](n):o!==t&&s[o]?s[o](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}})})(jQuery);(function(e){var t=!1;e(document).mouseup(function(){t=!1}),e.widget("ui.mouse",{version:"1.10.3",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(i){return!0===e.data(i.target,t.widgetName+".preventClickEvent")?(e.removeData(i.target,t.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):undefined}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(i){if(!t){this._mouseStarted&&this._mouseUp(i),this._mouseDownEvent=i;var s=this,n=1===i.which,a="string"==typeof this.options.cancel&&i.target.nodeName?e(i.target).closest(this.options.cancel).length:!1;return n&&!a&&this._mouseCapture(i)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){s.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(i)&&this._mouseDelayMet(i)&&(this._mouseStarted=this._mouseStart(i)!==!1,!this._mouseStarted)?(i.preventDefault(),!0):(!0===e.data(i.target,this.widgetName+".preventClickEvent")&&e.removeData(i.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return s._mouseMove(e)},this._mouseUpDelegate=function(e){return s._mouseUp(e)},e(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),i.preventDefault(),t=!0,!0)):!0}},_mouseMove:function(t){return e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button?this._mouseUp(t):this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery);(function(t,e){function i(t,e,i){return[parseFloat(t[0])*(p.test(t[0])?e/100:1),parseFloat(t[1])*(p.test(t[1])?i/100:1)]}function s(e,i){return parseInt(t.css(e,i),10)||0}function n(e){var i=e[0];return 9===i.nodeType?{width:e.width(),height:e.height(),offset:{top:0,left:0}}:t.isWindow(i)?{width:e.width(),height:e.height(),offset:{top:e.scrollTop(),left:e.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:e.outerWidth(),height:e.outerHeight(),offset:e.offset()}}t.ui=t.ui||{};var a,o=Math.max,r=Math.abs,h=Math.round,l=/left|center|right/,c=/top|center|bottom/,u=/[\+\-]\d+(\.[\d]+)?%?/,d=/^\w+/,p=/%$/,f=t.fn.position;t.position={scrollbarWidth:function(){if(a!==e)return a;var i,s,n=t("
"),o=n.children()[0];return t("body").append(n),i=o.offsetWidth,n.css("overflow","scroll"),s=o.offsetWidth,i===s&&(s=n[0].clientWidth),n.remove(),a=i-s},getScrollInfo:function(e){var i=e.isWindow?"":e.element.css("overflow-x"),s=e.isWindow?"":e.element.css("overflow-y"),n="scroll"===i||"auto"===i&&e.widths?"left":i>0?"right":"center",vertical:0>a?"top":n>0?"bottom":"middle"};u>p&&p>r(i+s)&&(h.horizontal="center"),d>m&&m>r(n+a)&&(h.vertical="middle"),h.important=o(r(i),r(s))>o(r(n),r(a))?"horizontal":"vertical",e.using.call(this,t,h)}),c.offset(t.extend(C,{using:l}))})},t.ui.position={fit:{left:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=t.left-e.collisionPosition.marginLeft,h=n-r,l=r+e.collisionWidth-a-n;e.collisionWidth>a?h>0&&0>=l?(i=t.left+h+e.collisionWidth-a-n,t.left+=h-i):t.left=l>0&&0>=h?n:h>l?n+a-e.collisionWidth:n:h>0?t.left+=h:l>0?t.left-=l:t.left=o(t.left-r,t.left)},top:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollTop:s.offset.top,a=e.within.height,r=t.top-e.collisionPosition.marginTop,h=n-r,l=r+e.collisionHeight-a-n;e.collisionHeight>a?h>0&&0>=l?(i=t.top+h+e.collisionHeight-a-n,t.top+=h-i):t.top=l>0&&0>=h?n:h>l?n+a-e.collisionHeight:n:h>0?t.top+=h:l>0?t.top-=l:t.top=o(t.top-r,t.top)}},flip:{left:function(t,e){var i,s,n=e.within,a=n.offset.left+n.scrollLeft,o=n.width,h=n.isWindow?n.scrollLeft:n.offset.left,l=t.left-e.collisionPosition.marginLeft,c=l-h,u=l+e.collisionWidth-o-h,d="left"===e.my[0]?-e.elemWidth:"right"===e.my[0]?e.elemWidth:0,p="left"===e.at[0]?e.targetWidth:"right"===e.at[0]?-e.targetWidth:0,f=-2*e.offset[0];0>c?(i=t.left+d+p+f+e.collisionWidth-o-a,(0>i||r(c)>i)&&(t.left+=d+p+f)):u>0&&(s=t.left-e.collisionPosition.marginLeft+d+p+f-h,(s>0||u>r(s))&&(t.left+=d+p+f))},top:function(t,e){var i,s,n=e.within,a=n.offset.top+n.scrollTop,o=n.height,h=n.isWindow?n.scrollTop:n.offset.top,l=t.top-e.collisionPosition.marginTop,c=l-h,u=l+e.collisionHeight-o-h,d="top"===e.my[1],p=d?-e.elemHeight:"bottom"===e.my[1]?e.elemHeight:0,f="top"===e.at[1]?e.targetHeight:"bottom"===e.at[1]?-e.targetHeight:0,m=-2*e.offset[1];0>c?(s=t.top+p+f+m+e.collisionHeight-o-a,t.top+p+f+m>c&&(0>s||r(c)>s)&&(t.top+=p+f+m)):u>0&&(i=t.top-e.collisionPosition.marginTop+p+f+m-h,t.top+p+f+m>u&&(i>0||u>r(i))&&(t.top+=p+f+m))}},flipfit:{left:function(){t.ui.position.flip.left.apply(this,arguments),t.ui.position.fit.left.apply(this,arguments)},top:function(){t.ui.position.flip.top.apply(this,arguments),t.ui.position.fit.top.apply(this,arguments)}}},function(){var e,i,s,n,a,o=document.getElementsByTagName("body")[0],r=document.createElement("div");e=document.createElement(o?"div":"body"),s={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},o&&t.extend(s,{position:"absolute",left:"-1000px",top:"-1000px"});for(a in s)e.style[a]=s[a];e.appendChild(r),i=o||document.documentElement,i.insertBefore(e,i.firstChild),r.style.cssText="position: absolute; left: 10.7432222px;",n=t(r).offset().left,t.support.offsetFractions=n>10&&11>n,e.innerHTML="",i.removeChild(e)}()})(jQuery);(function(e){e.widget("ui.draggable",e.ui.mouse,{version:"1.10.3",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){"original"!==this.options.helper||/^(?:r|a|f)/.test(this.element.css("position"))||(this.element[0].style.position="relative"),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._mouseInit()},_destroy:function(){this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._mouseDestroy()},_mouseCapture:function(t){var i=this.options;return this.helper||i.disabled||e(t.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(t),this.handle?(e(i.iframeFix===!0?"iframe":i.iframeFix).each(function(){e("
").css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(e(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(t){var i=this.options;return this.helper=this._createHelper(t),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),e.ui.ddmanager&&(e.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offsetParent=this.helper.offsetParent(),this.offsetParentCssPosition=this.offsetParent.css("position"),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},this.offset.scroll=!1,e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this._setContainment(),this._trigger("start",t)===!1?(this._clear(),!1):(this._cacheHelperProportions(),e.ui.ddmanager&&!i.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this._mouseDrag(t,!0),e.ui.ddmanager&&e.ui.ddmanager.dragStart(this,t),!0)},_mouseDrag:function(t,i){if("fixed"===this.offsetParentCssPosition&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute"),!i){var s=this._uiHash();if(this._trigger("drag",t,s)===!1)return this._mouseUp({}),!1;this.position=s.position}return this.options.axis&&"y"===this.options.axis||(this.helper[0].style.left=this.position.left+"px"),this.options.axis&&"x"===this.options.axis||(this.helper[0].style.top=this.position.top+"px"),e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),!1},_mouseStop:function(t){var i=this,s=!1;return e.ui.ddmanager&&!this.options.dropBehaviour&&(s=e.ui.ddmanager.drop(this,t)),this.dropped&&(s=this.dropped,this.dropped=!1),"original"!==this.options.helper||e.contains(this.element[0].ownerDocument,this.element[0])?("invalid"===this.options.revert&&!s||"valid"===this.options.revert&&s||this.options.revert===!0||e.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?e(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){i._trigger("stop",t)!==!1&&i._clear()}):this._trigger("stop",t)!==!1&&this._clear(),!1):!1},_mouseUp:function(t){return e("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),e.ui.ddmanager&&e.ui.ddmanager.dragStop(this,t),e.ui.mouse.prototype._mouseUp.call(this,t)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(t){return this.options.handle?!!e(t.target).closest(this.element.find(this.options.handle)).length:!0},_createHelper:function(t){var i=this.options,s=e.isFunction(i.helper)?e(i.helper.apply(this.element[0],[t])):"clone"===i.helper?this.element.clone().removeAttr("id"):this.element;return s.parents("body").length||s.appendTo("parent"===i.appendTo?this.element[0].parentNode:i.appendTo),s[0]===this.element[0]||/(fixed|absolute)/.test(s.css("position"))||s.css("position","absolute"),s},_adjustOffsetFromHelper:function(t){"string"==typeof t&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){var t=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&e.ui.ie)&&(t={top:0,left:0}),{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var e=this.element.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,i,s,n=this.options;return n.containment?"window"===n.containment?(this.containment=[e(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,e(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,e(window).scrollLeft()+e(window).width()-this.helperProportions.width-this.margins.left,e(window).scrollTop()+(e(window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],undefined):"document"===n.containment?(this.containment=[0,0,e(document).width()-this.helperProportions.width-this.margins.left,(e(document).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],undefined):n.containment.constructor===Array?(this.containment=n.containment,undefined):("parent"===n.containment&&(n.containment=this.helper[0].parentNode),i=e(n.containment),s=i[0],s&&(t="hidden"!==i.css("overflow"),this.containment=[(parseInt(i.css("borderLeftWidth"),10)||0)+(parseInt(i.css("paddingLeft"),10)||0),(parseInt(i.css("borderTopWidth"),10)||0)+(parseInt(i.css("paddingTop"),10)||0),(t?Math.max(s.scrollWidth,s.offsetWidth):s.offsetWidth)-(parseInt(i.css("borderRightWidth"),10)||0)-(parseInt(i.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(t?Math.max(s.scrollHeight,s.offsetHeight):s.offsetHeight)-(parseInt(i.css("borderBottomWidth"),10)||0)-(parseInt(i.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=i),undefined):(this.containment=null,undefined)},_convertPositionTo:function(t,i){i||(i=this.position);var s="absolute"===t?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent;return this.offset.scroll||(this.offset.scroll={top:n.scrollTop(),left:n.scrollLeft()}),{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():this.offset.scroll.top)*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():this.offset.scroll.left)*s}},_generatePosition:function(t){var i,s,n,a,o=this.options,r="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,h=t.pageX,l=t.pageY;return this.offset.scroll||(this.offset.scroll={top:r.scrollTop(),left:r.scrollLeft()}),this.originalPosition&&(this.containment&&(this.relative_container?(s=this.relative_container.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,t.pageX-this.offset.click.lefti[2]&&(h=i[2]+this.offset.click.left),t.pageY-this.offset.click.top>i[3]&&(l=i[3]+this.offset.click.top)),o.grid&&(n=o.grid[1]?this.originalPageY+Math.round((l-this.originalPageY)/o.grid[1])*o.grid[1]:this.originalPageY,l=i?n-this.offset.click.top>=i[1]||n-this.offset.click.top>i[3]?n:n-this.offset.click.top>=i[1]?n-o.grid[1]:n+o.grid[1]:n,a=o.grid[0]?this.originalPageX+Math.round((h-this.originalPageX)/o.grid[0])*o.grid[0]:this.originalPageX,h=i?a-this.offset.click.left>=i[0]||a-this.offset.click.left>i[2]?a:a-this.offset.click.left>=i[0]?a-o.grid[0]:a+o.grid[0]:a)),{top:l-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():this.offset.scroll.top),left:h-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():this.offset.scroll.left)}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1},_trigger:function(t,i,s){return s=s||this._uiHash(),e.ui.plugin.call(this,t,[i,s]),"drag"===t&&(this.positionAbs=this._convertPositionTo("absolute")),e.Widget.prototype._trigger.call(this,t,i,s)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),e.ui.plugin.add("draggable","connectToSortable",{start:function(t,i){var s=e(this).data("ui-draggable"),n=s.options,a=e.extend({},i,{item:s.element});s.sortables=[],e(n.connectToSortable).each(function(){var i=e.data(this,"ui-sortable");i&&!i.options.disabled&&(s.sortables.push({instance:i,shouldRevert:i.options.revert}),i.refreshPositions(),i._trigger("activate",t,a))})},stop:function(t,i){var s=e(this).data("ui-draggable"),n=e.extend({},i,{item:s.element});e.each(s.sortables,function(){this.instance.isOver?(this.instance.isOver=0,s.cancelHelperRemoval=!0,this.instance.cancelHelperRemoval=!1,this.shouldRevert&&(this.instance.options.revert=this.shouldRevert),this.instance._mouseStop(t),this.instance.options.helper=this.instance.options._helper,"original"===s.options.helper&&this.instance.currentItem.css({top:"auto",left:"auto"})):(this.instance.cancelHelperRemoval=!1,this.instance._trigger("deactivate",t,n))})},drag:function(t,i){var s=e(this).data("ui-draggable"),n=this;e.each(s.sortables,function(){var a=!1,o=this;this.instance.positionAbs=s.positionAbs,this.instance.helperProportions=s.helperProportions,this.instance.offset.click=s.offset.click,this.instance._intersectsWith(this.instance.containerCache)&&(a=!0,e.each(s.sortables,function(){return this.instance.positionAbs=s.positionAbs,this.instance.helperProportions=s.helperProportions,this.instance.offset.click=s.offset.click,this!==o&&this.instance._intersectsWith(this.instance.containerCache)&&e.contains(o.instance.element[0],this.instance.element[0])&&(a=!1),a})),a?(this.instance.isOver||(this.instance.isOver=1,this.instance.currentItem=e(n).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item",!0),this.instance.options._helper=this.instance.options.helper,this.instance.options.helper=function(){return i.helper[0]},t.target=this.instance.currentItem[0],this.instance._mouseCapture(t,!0),this.instance._mouseStart(t,!0,!0),this.instance.offset.click.top=s.offset.click.top,this.instance.offset.click.left=s.offset.click.left,this.instance.offset.parent.left-=s.offset.parent.left-this.instance.offset.parent.left,this.instance.offset.parent.top-=s.offset.parent.top-this.instance.offset.parent.top,s._trigger("toSortable",t),s.dropped=this.instance.element,s.currentItem=s.element,this.instance.fromOutside=s),this.instance.currentItem&&this.instance._mouseDrag(t)):this.instance.isOver&&(this.instance.isOver=0,this.instance.cancelHelperRemoval=!0,this.instance.options.revert=!1,this.instance._trigger("out",t,this.instance._uiHash(this.instance)),this.instance._mouseStop(t,!0),this.instance.options.helper=this.instance.options._helper,this.instance.currentItem.remove(),this.instance.placeholder&&this.instance.placeholder.remove(),s._trigger("fromSortable",t),s.dropped=!1)})}}),e.ui.plugin.add("draggable","cursor",{start:function(){var t=e("body"),i=e(this).data("ui-draggable").options;t.css("cursor")&&(i._cursor=t.css("cursor")),t.css("cursor",i.cursor)},stop:function(){var t=e(this).data("ui-draggable").options;t._cursor&&e("body").css("cursor",t._cursor)}}),e.ui.plugin.add("draggable","opacity",{start:function(t,i){var s=e(i.helper),n=e(this).data("ui-draggable").options;s.css("opacity")&&(n._opacity=s.css("opacity")),s.css("opacity",n.opacity)},stop:function(t,i){var s=e(this).data("ui-draggable").options;s._opacity&&e(i.helper).css("opacity",s._opacity)}}),e.ui.plugin.add("draggable","scroll",{start:function(){var t=e(this).data("ui-draggable");t.scrollParent[0]!==document&&"HTML"!==t.scrollParent[0].tagName&&(t.overflowOffset=t.scrollParent.offset())},drag:function(t){var i=e(this).data("ui-draggable"),s=i.options,n=!1;i.scrollParent[0]!==document&&"HTML"!==i.scrollParent[0].tagName?(s.axis&&"x"===s.axis||(i.overflowOffset.top+i.scrollParent[0].offsetHeight-t.pageY=0;c--)r=p.snapElements[c].left,h=r+p.snapElements[c].width,l=p.snapElements[c].top,u=l+p.snapElements[c].height,r-m>v||g>h+m||l-m>y||b>u+m||!e.contains(p.snapElements[c].item.ownerDocument,p.snapElements[c].item)?(p.snapElements[c].snapping&&p.options.snap.release&&p.options.snap.release.call(p.element,t,e.extend(p._uiHash(),{snapItem:p.snapElements[c].item})),p.snapElements[c].snapping=!1):("inner"!==f.snapMode&&(s=m>=Math.abs(l-y),n=m>=Math.abs(u-b),a=m>=Math.abs(r-v),o=m>=Math.abs(h-g),s&&(i.position.top=p._convertPositionTo("relative",{top:l-p.helperProportions.height,left:0}).top-p.margins.top),n&&(i.position.top=p._convertPositionTo("relative",{top:u,left:0}).top-p.margins.top),a&&(i.position.left=p._convertPositionTo("relative",{top:0,left:r-p.helperProportions.width}).left-p.margins.left),o&&(i.position.left=p._convertPositionTo("relative",{top:0,left:h}).left-p.margins.left)),d=s||n||a||o,"outer"!==f.snapMode&&(s=m>=Math.abs(l-b),n=m>=Math.abs(u-y),a=m>=Math.abs(r-g),o=m>=Math.abs(h-v),s&&(i.position.top=p._convertPositionTo("relative",{top:l,left:0}).top-p.margins.top),n&&(i.position.top=p._convertPositionTo("relative",{top:u-p.helperProportions.height,left:0}).top-p.margins.top),a&&(i.position.left=p._convertPositionTo("relative",{top:0,left:r}).left-p.margins.left),o&&(i.position.left=p._convertPositionTo("relative",{top:0,left:h-p.helperProportions.width}).left-p.margins.left)),!p.snapElements[c].snapping&&(s||n||a||o||d)&&p.options.snap.snap&&p.options.snap.snap.call(p.element,t,e.extend(p._uiHash(),{snapItem:p.snapElements[c].item})),p.snapElements[c].snapping=s||n||a||o||d)}}),e.ui.plugin.add("draggable","stack",{start:function(){var t,i=this.data("ui-draggable").options,s=e.makeArray(e(i.stack)).sort(function(t,i){return(parseInt(e(t).css("zIndex"),10)||0)-(parseInt(e(i).css("zIndex"),10)||0)});s.length&&(t=parseInt(e(s[0]).css("zIndex"),10)||0,e(s).each(function(i){e(this).css("zIndex",t+i)}),this.css("zIndex",t+s.length))}}),e.ui.plugin.add("draggable","zIndex",{start:function(t,i){var s=e(i.helper),n=e(this).data("ui-draggable").options;s.css("zIndex")&&(n._zIndex=s.css("zIndex")),s.css("zIndex",n.zIndex)},stop:function(t,i){var s=e(this).data("ui-draggable").options;s._zIndex&&e(i.helper).css("zIndex",s._zIndex)}})})(jQuery);(function(e){function t(e,t,i){return e>t&&t+i>e}e.widget("ui.droppable",{version:"1.10.3",widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect",activate:null,deactivate:null,drop:null,out:null,over:null},_create:function(){var t=this.options,i=t.accept;this.isover=!1,this.isout=!0,this.accept=e.isFunction(i)?i:function(e){return e.is(i)},this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight},e.ui.ddmanager.droppables[t.scope]=e.ui.ddmanager.droppables[t.scope]||[],e.ui.ddmanager.droppables[t.scope].push(this),t.addClasses&&this.element.addClass("ui-droppable")},_destroy:function(){for(var t=0,i=e.ui.ddmanager.droppables[this.options.scope];i.length>t;t++)i[t]===this&&i.splice(t,1);this.element.removeClass("ui-droppable ui-droppable-disabled")},_setOption:function(t,i){"accept"===t&&(this.accept=e.isFunction(i)?i:function(e){return e.is(i)}),e.Widget.prototype._setOption.apply(this,arguments)},_activate:function(t){var i=e.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),i&&this._trigger("activate",t,this.ui(i))},_deactivate:function(t){var i=e.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),i&&this._trigger("deactivate",t,this.ui(i))},_over:function(t){var i=e.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",t,this.ui(i)))},_out:function(t){var i=e.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",t,this.ui(i)))},_drop:function(t,i){var s=i||e.ui.ddmanager.current,n=!1;return s&&(s.currentItem||s.element)[0]!==this.element[0]?(this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function(){var t=e.data(this,"ui-droppable");return t.options.greedy&&!t.options.disabled&&t.options.scope===s.options.scope&&t.accept.call(t.element[0],s.currentItem||s.element)&&e.ui.intersect(s,e.extend(t,{offset:t.element.offset()}),t.options.tolerance)?(n=!0,!1):undefined}),n?!1:this.accept.call(this.element[0],s.currentItem||s.element)?(this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",t,this.ui(s)),this.element):!1):!1},ui:function(e){return{draggable:e.currentItem||e.element,helper:e.helper,position:e.position,offset:e.positionAbs}}}),e.ui.intersect=function(e,i,s){if(!i.offset)return!1;var n,a,o=(e.positionAbs||e.position.absolute).left,r=o+e.helperProportions.width,h=(e.positionAbs||e.position.absolute).top,l=h+e.helperProportions.height,u=i.offset.left,c=u+i.proportions.width,d=i.offset.top,p=d+i.proportions.height;switch(s){case"fit":return o>=u&&c>=r&&h>=d&&p>=l;case"intersect":return o+e.helperProportions.width/2>u&&c>r-e.helperProportions.width/2&&h+e.helperProportions.height/2>d&&p>l-e.helperProportions.height/2;case"pointer":return n=(e.positionAbs||e.position.absolute).left+(e.clickOffset||e.offset.click).left,a=(e.positionAbs||e.position.absolute).top+(e.clickOffset||e.offset.click).top,t(a,d,i.proportions.height)&&t(n,u,i.proportions.width);case"touch":return(h>=d&&p>=h||l>=d&&p>=l||d>h&&l>p)&&(o>=u&&c>=o||r>=u&&c>=r||u>o&&r>c);default:return!1}},e.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(t,i){var s,n,a=e.ui.ddmanager.droppables[t.options.scope]||[],o=i?i.type:null,r=(t.currentItem||t.element).find(":data(ui-droppable)").addBack();e:for(s=0;a.length>s;s++)if(!(a[s].options.disabled||t&&!a[s].accept.call(a[s].element[0],t.currentItem||t.element))){for(n=0;r.length>n;n++)if(r[n]===a[s].element[0]){a[s].proportions.height=0;continue e}a[s].visible="none"!==a[s].element.css("display"),a[s].visible&&("mousedown"===o&&a[s]._activate.call(a[s],i),a[s].offset=a[s].element.offset(),a[s].proportions={width:a[s].element[0].offsetWidth,height:a[s].element[0].offsetHeight})}},drop:function(t,i){var s=!1;return e.each((e.ui.ddmanager.droppables[t.options.scope]||[]).slice(),function(){this.options&&(!this.options.disabled&&this.visible&&e.ui.intersect(t,this,this.options.tolerance)&&(s=this._drop.call(this,i)||s),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],t.currentItem||t.element)&&(this.isout=!0,this.isover=!1,this._deactivate.call(this,i)))}),s},dragStart:function(t,i){t.element.parentsUntil("body").bind("scroll.droppable",function(){t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,i)})},drag:function(t,i){t.options.refreshPositions&&e.ui.ddmanager.prepareOffsets(t,i),e.each(e.ui.ddmanager.droppables[t.options.scope]||[],function(){if(!this.options.disabled&&!this.greedyChild&&this.visible){var s,n,a,o=e.ui.intersect(t,this,this.options.tolerance),r=!o&&this.isover?"isout":o&&!this.isover?"isover":null;r&&(this.options.greedy&&(n=this.options.scope,a=this.element.parents(":data(ui-droppable)").filter(function(){return e.data(this,"ui-droppable").options.scope===n}),a.length&&(s=e.data(a[0],"ui-droppable"),s.greedyChild="isover"===r)),s&&"isover"===r&&(s.isover=!1,s.isout=!0,s._out.call(s,i)),this[r]=!0,this["isout"===r?"isover":"isout"]=!1,this["isover"===r?"_over":"_out"].call(this,i),s&&"isout"===r&&(s.isout=!1,s.isover=!0,s._over.call(s,i)))}})},dragStop:function(t,i){t.element.parentsUntil("body").unbind("scroll.droppable"),t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,i)}}})(jQuery);(function(e){function t(e){return parseInt(e,10)||0}function i(e){return!isNaN(parseInt(e,10))}e.widget("ui.resizable",e.ui.mouse,{version:"1.10.3",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_create:function(){var t,i,s,n,a,o=this,r=this.options;if(this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!r.aspectRatio,aspectRatio:r.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:r.helper||r.ghost||r.animate?r.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(e("
").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.data("ui-resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=r.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),t=this.handles.split(","),this.handles={},i=0;t.length>i;i++)s=e.trim(t[i]),a="ui-resizable-"+s,n=e("
"),n.css({zIndex:r.zIndex}),"se"===s&&n.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(n);this._renderAxis=function(t){var i,s,n,a;t=t||this.element;for(i in this.handles)this.handles[i].constructor===String&&(this.handles[i]=e(this.handles[i],this.element).show()),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)&&(s=e(this.handles[i],this.element),a=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),t.css(n,a),this._proportionallyResize()),e(this.handles[i]).length},this._renderAxis(this.element),this._handles=e(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=n&&n[1]?n[1]:"se")}),r.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){r.disabled||(e(this).removeClass("ui-resizable-autohide"),o._handles.show())}).mouseleave(function(){r.disabled||o.resizing||(e(this).addClass("ui-resizable-autohide"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t,i=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),t=this.element,this.originalElement.css({position:t.css("position"),width:t.outerWidth(),height:t.outerHeight(),top:t.css("top"),left:t.css("left")}).insertAfter(t),t.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_mouseCapture:function(t){var i,s,n=!1;for(i in this.handles)s=e(this.handles[i])[0],(s===t.target||e.contains(s,t.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(i){var s,n,a,o=this.options,r=this.element.position(),h=this.element;return this.resizing=!0,/absolute/.test(h.css("position"))?h.css({position:"absolute",top:h.css("top"),left:h.css("left")}):h.is(".ui-draggable")&&h.css({position:"absolute",top:r.top,left:r.left}),this._renderProxy(),s=t(this.helper.css("left")),n=t(this.helper.css("top")),o.containment&&(s+=e(o.containment).scrollLeft()||0,n+=e(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:s,top:n},this.size=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalSize=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalPosition={left:s,top:n},this.sizeDiff={width:h.outerWidth()-h.width(),height:h.outerHeight()-h.height()},this.originalMousePosition={left:i.pageX,top:i.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,a=e(".ui-resizable-"+this.axis).css("cursor"),e("body").css("cursor","auto"===a?this.axis+"-resize":a),h.addClass("ui-resizable-resizing"),this._propagate("start",i),!0},_mouseDrag:function(t){var i,s=this.helper,n={},a=this.originalMousePosition,o=this.axis,r=this.position.top,h=this.position.left,l=this.size.width,u=this.size.height,c=t.pageX-a.left||0,d=t.pageY-a.top||0,p=this._change[o];return p?(i=p.apply(this,[t,c,d]),this._updateVirtualBoundaries(t.shiftKey),(this._aspectRatio||t.shiftKey)&&(i=this._updateRatio(i,t)),i=this._respectSize(i,t),this._updateCache(i),this._propagate("resize",t),this.position.top!==r&&(n.top=this.position.top+"px"),this.position.left!==h&&(n.left=this.position.left+"px"),this.size.width!==l&&(n.width=this.size.width+"px"),this.size.height!==u&&(n.height=this.size.height+"px"),s.css(n),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),e.isEmptyObject(n)||this._trigger("resize",t,this.ui()),!1):!1},_mouseStop:function(t){this.resizing=!1;var i,s,n,a,o,r,h,l=this.options,u=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&e.ui.hasScroll(i[0],"left")?0:u.sizeDiff.height,a=s?0:u.sizeDiff.width,o={width:u.helper.width()-a,height:u.helper.height()-n},r=parseInt(u.element.css("left"),10)+(u.position.left-u.originalPosition.left)||null,h=parseInt(u.element.css("top"),10)+(u.position.top-u.originalPosition.top)||null,l.animate||this.element.css(e.extend(o,{top:h,left:r})),u.helper.height(u.size.height),u.helper.width(u.size.width),this._helper&&!l.animate&&this._proportionallyResize()),e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(e){var t,s,n,a,o,r=this.options;o={minWidth:i(r.minWidth)?r.minWidth:0,maxWidth:i(r.maxWidth)?r.maxWidth:1/0,minHeight:i(r.minHeight)?r.minHeight:0,maxHeight:i(r.maxHeight)?r.maxHeight:1/0},(this._aspectRatio||e)&&(t=o.minHeight*this.aspectRatio,n=o.minWidth/this.aspectRatio,s=o.maxHeight*this.aspectRatio,a=o.maxWidth/this.aspectRatio,t>o.minWidth&&(o.minWidth=t),n>o.minHeight&&(o.minHeight=n),o.maxWidth>s&&(o.maxWidth=s),o.maxHeight>a&&(o.maxHeight=a)),this._vBoundaries=o},_updateCache:function(e){this.offset=this.helper.offset(),i(e.left)&&(this.position.left=e.left),i(e.top)&&(this.position.top=e.top),i(e.height)&&(this.size.height=e.height),i(e.width)&&(this.size.width=e.width)},_updateRatio:function(e){var t=this.position,s=this.size,n=this.axis;return i(e.height)?e.width=e.height*this.aspectRatio:i(e.width)&&(e.height=e.width/this.aspectRatio),"sw"===n&&(e.left=t.left+(s.width-e.width),e.top=null),"nw"===n&&(e.top=t.top+(s.height-e.height),e.left=t.left+(s.width-e.width)),e},_respectSize:function(e){var t=this._vBoundaries,s=this.axis,n=i(e.width)&&t.maxWidth&&t.maxWidthe.width,r=i(e.height)&&t.minHeight&&t.minHeight>e.height,h=this.originalPosition.left+this.originalSize.width,l=this.position.top+this.size.height,u=/sw|nw|w/.test(s),c=/nw|ne|n/.test(s);return o&&(e.width=t.minWidth),r&&(e.height=t.minHeight),n&&(e.width=t.maxWidth),a&&(e.height=t.maxHeight),o&&u&&(e.left=h-t.minWidth),n&&u&&(e.left=h-t.maxWidth),r&&c&&(e.top=l-t.minHeight),a&&c&&(e.top=l-t.maxHeight),e.width||e.height||e.left||!e.top?e.width||e.height||e.top||!e.left||(e.left=null):e.top=null,e},_proportionallyResize:function(){if(this._proportionallyResizeElements.length){var e,t,i,s,n,a=this.helper||this.element;for(e=0;this._proportionallyResizeElements.length>e;e++){if(n=this._proportionallyResizeElements[e],!this.borderDif)for(this.borderDif=[],i=[n.css("borderTopWidth"),n.css("borderRightWidth"),n.css("borderBottomWidth"),n.css("borderLeftWidth")],s=[n.css("paddingTop"),n.css("paddingRight"),n.css("paddingBottom"),n.css("paddingLeft")],t=0;i.length>t;t++)this.borderDif[t]=(parseInt(i[t],10)||0)+(parseInt(s[t],10)||0);n.css({height:a.height()-this.borderDif[0]-this.borderDif[2]||0,width:a.width()-this.borderDif[1]-this.borderDif[3]||0})}}},_renderProxy:function(){var t=this.element,i=this.options;this.elementOffset=t.offset(),this._helper?(this.helper=this.helper||e("
"),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(e,t){return{width:this.originalSize.width+t}},w:function(e,t){var i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(e,t,i){return{height:this.originalSize.height+i}},se:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},sw:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,i,s]))},ne:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},nw:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,i,s]))}},_propagate:function(t,i){e.ui.plugin.call(this,t,[i,this.ui()]),"resize"!==t&&this._trigger(t,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","animate",{stop:function(t){var i=e(this).data("ui-resizable"),s=i.options,n=i._proportionallyResizeElements,a=n.length&&/textarea/i.test(n[0].nodeName),o=a&&e.ui.hasScroll(n[0],"left")?0:i.sizeDiff.height,r=a?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-o},l=parseInt(i.element.css("left"),10)+(i.position.left-i.originalPosition.left)||null,u=parseInt(i.element.css("top"),10)+(i.position.top-i.originalPosition.top)||null;i.element.animate(e.extend(h,u&&l?{top:u,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseInt(i.element.css("width"),10),height:parseInt(i.element.css("height"),10),top:parseInt(i.element.css("top"),10),left:parseInt(i.element.css("left"),10)};n&&n.length&&e(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(){var i,s,n,a,o,r,h,l=e(this).data("ui-resizable"),u=l.options,c=l.element,d=u.containment,p=d instanceof e?d.get(0):/parent/.test(d)?c.parent().get(0):d;p&&(l.containerElement=e(p),/document/.test(d)||d===document?(l.containerOffset={left:0,top:0},l.containerPosition={left:0,top:0},l.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}):(i=e(p),s=[],e(["Top","Right","Left","Bottom"]).each(function(e,n){s[e]=t(i.css("padding"+n))}),l.containerOffset=i.offset(),l.containerPosition=i.position(),l.containerSize={height:i.innerHeight()-s[3],width:i.innerWidth()-s[1]},n=l.containerOffset,a=l.containerSize.height,o=l.containerSize.width,r=e.ui.hasScroll(p,"left")?p.scrollWidth:o,h=e.ui.hasScroll(p)?p.scrollHeight:a,l.parentData={element:p,left:n.left,top:n.top,width:r,height:h}))},resize:function(t){var i,s,n,a,o=e(this).data("ui-resizable"),r=o.options,h=o.containerOffset,l=o.position,u=o._aspectRatio||t.shiftKey,c={top:0,left:0},d=o.containerElement;d[0]!==document&&/static/.test(d.css("position"))&&(c=h),l.left<(o._helper?h.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-h.left:o.position.left-c.left),u&&(o.size.height=o.size.width/o.aspectRatio),o.position.left=r.helper?h.left:0),l.top<(o._helper?h.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-h.top:o.position.top),u&&(o.size.width=o.size.height*o.aspectRatio),o.position.top=o._helper?h.top:0),o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top,i=Math.abs((o._helper?o.offset.left-c.left:o.offset.left-c.left)+o.sizeDiff.width),s=Math.abs((o._helper?o.offset.top-c.top:o.offset.top-h.top)+o.sizeDiff.height),n=o.containerElement.get(0)===o.element.parent().get(0),a=/relative|absolute/.test(o.containerElement.css("position")),n&&a&&(i-=o.parentData.left),i+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-i,u&&(o.size.height=o.size.width/o.aspectRatio)),s+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-s,u&&(o.size.width=o.size.height*o.aspectRatio))},stop:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.containerOffset,n=t.containerPosition,a=t.containerElement,o=e(t.helper),r=o.offset(),h=o.outerWidth()-t.sizeDiff.width,l=o.outerHeight()-t.sizeDiff.height;t._helper&&!i.animate&&/relative/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l}),t._helper&&!i.animate&&/static/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),e.ui.plugin.add("resizable","alsoResize",{start:function(){var t=e(this).data("ui-resizable"),i=t.options,s=function(t){e(t).each(function(){var t=e(this);t.data("ui-resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})};"object"!=typeof i.alsoResize||i.alsoResize.parentNode?s(i.alsoResize):i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):e.each(i.alsoResize,function(e){s(e)})},resize:function(t,i){var s=e(this).data("ui-resizable"),n=s.options,a=s.originalSize,o=s.originalPosition,r={height:s.size.height-a.height||0,width:s.size.width-a.width||0,top:s.position.top-o.top||0,left:s.position.left-o.left||0},h=function(t,s){e(t).each(function(){var t=e(this),n=e(this).data("ui-resizable-alsoresize"),a={},o=s&&s.length?s:t.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(o,function(e,t){var i=(n[t]||0)+(r[t]||0);i&&i>=0&&(a[t]=i||null)}),t.css(a)})};"object"!=typeof n.alsoResize||n.alsoResize.nodeType?h(n.alsoResize):e.each(n.alsoResize,function(e,t){h(e,t)})},stop:function(){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","ghost",{start:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass("string"==typeof i.ghost?i.ghost:""),t.ghost.appendTo(t.helper)},resize:function(){var t=e(this).data("ui-resizable");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=e(this).data("ui-resizable");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.size,n=t.originalSize,a=t.originalPosition,o=t.axis,r="number"==typeof i.grid?[i.grid,i.grid]:i.grid,h=r[0]||1,l=r[1]||1,u=Math.round((s.width-n.width)/h)*h,c=Math.round((s.height-n.height)/l)*l,d=n.width+u,p=n.height+c,f=i.maxWidth&&d>i.maxWidth,m=i.maxHeight&&p>i.maxHeight,g=i.minWidth&&i.minWidth>d,v=i.minHeight&&i.minHeight>p;i.grid=r,g&&(d+=h),v&&(p+=l),f&&(d-=h),m&&(p-=l),/^(se|s|e)$/.test(o)?(t.size.width=d,t.size.height=p):/^(ne)$/.test(o)?(t.size.width=d,t.size.height=p,t.position.top=a.top-c):/^(sw)$/.test(o)?(t.size.width=d,t.size.height=p,t.position.left=a.left-u):(t.size.width=d,t.size.height=p,t.position.top=a.top-c,t.position.left=a.left-u)}})})(jQuery);(function(e){e.widget("ui.selectable",e.ui.mouse,{version:"1.10.3",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch",selected:null,selecting:null,start:null,stop:null,unselected:null,unselecting:null},_create:function(){var t,i=this;this.element.addClass("ui-selectable"),this.dragged=!1,this.refresh=function(){t=e(i.options.filter,i.element[0]),t.addClass("ui-selectee"),t.each(function(){var t=e(this),i=t.offset();e.data(this,"selectable-item",{element:this,$element:t,left:i.left,top:i.top,right:i.left+t.outerWidth(),bottom:i.top+t.outerHeight(),startselected:!1,selected:t.hasClass("ui-selected"),selecting:t.hasClass("ui-selecting"),unselecting:t.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=t.addClass("ui-selectee"),this._mouseInit(),this.helper=e("
")},_destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled"),this._mouseDestroy()},_mouseStart:function(t){var i=this,s=this.options;this.opos=[t.pageX,t.pageY],this.options.disabled||(this.selectees=e(s.filter,this.element[0]),this._trigger("start",t),e(s.appendTo).append(this.helper),this.helper.css({left:t.pageX,top:t.pageY,width:0,height:0}),s.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var s=e.data(this,"selectable-item");s.startselected=!0,t.metaKey||t.ctrlKey||(s.$element.removeClass("ui-selected"),s.selected=!1,s.$element.addClass("ui-unselecting"),s.unselecting=!0,i._trigger("unselecting",t,{unselecting:s.element}))}),e(t.target).parents().addBack().each(function(){var s,n=e.data(this,"selectable-item");return n?(s=!t.metaKey&&!t.ctrlKey||!n.$element.hasClass("ui-selected"),n.$element.removeClass(s?"ui-unselecting":"ui-selected").addClass(s?"ui-selecting":"ui-unselecting"),n.unselecting=!s,n.selecting=s,n.selected=s,s?i._trigger("selecting",t,{selecting:n.element}):i._trigger("unselecting",t,{unselecting:n.element}),!1):undefined}))},_mouseDrag:function(t){if(this.dragged=!0,!this.options.disabled){var i,s=this,n=this.options,a=this.opos[0],o=this.opos[1],r=t.pageX,h=t.pageY;return a>r&&(i=r,r=a,a=i),o>h&&(i=h,h=o,o=i),this.helper.css({left:a,top:o,width:r-a,height:h-o}),this.selectees.each(function(){var i=e.data(this,"selectable-item"),l=!1;i&&i.element!==s.element[0]&&("touch"===n.tolerance?l=!(i.left>r||a>i.right||i.top>h||o>i.bottom):"fit"===n.tolerance&&(l=i.left>a&&r>i.right&&i.top>o&&h>i.bottom),l?(i.selected&&(i.$element.removeClass("ui-selected"),i.selected=!1),i.unselecting&&(i.$element.removeClass("ui-unselecting"),i.unselecting=!1),i.selecting||(i.$element.addClass("ui-selecting"),i.selecting=!0,s._trigger("selecting",t,{selecting:i.element}))):(i.selecting&&((t.metaKey||t.ctrlKey)&&i.startselected?(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.$element.addClass("ui-selected"),i.selected=!0):(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.startselected&&(i.$element.addClass("ui-unselecting"),i.unselecting=!0),s._trigger("unselecting",t,{unselecting:i.element}))),i.selected&&(t.metaKey||t.ctrlKey||i.startselected||(i.$element.removeClass("ui-selected"),i.selected=!1,i.$element.addClass("ui-unselecting"),i.unselecting=!0,s._trigger("unselecting",t,{unselecting:i.element})))))}),!1}},_mouseStop:function(t){var i=this;return this.dragged=!1,e(".ui-unselecting",this.element[0]).each(function(){var s=e.data(this,"selectable-item");s.$element.removeClass("ui-unselecting"),s.unselecting=!1,s.startselected=!1,i._trigger("unselected",t,{unselected:s.element})}),e(".ui-selecting",this.element[0]).each(function(){var s=e.data(this,"selectable-item");s.$element.removeClass("ui-selecting").addClass("ui-selected"),s.selecting=!1,s.selected=!0,s.startselected=!0,i._trigger("selected",t,{selected:s.element})}),this._trigger("stop",t),this.helper.remove(),!1}})})(jQuery);(function(t){function e(t,e,i){return t>e&&e+i>t}function i(t){return/left|right/.test(t.css("float"))||/inline|table-cell/.test(t.css("display"))}t.widget("ui.sortable",t.ui.mouse,{version:"1.10.3",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3,activate:null,beforeStop:null,change:null,deactivate:null,out:null,over:null,receive:null,remove:null,sort:null,start:null,stop:null,update:null},_create:function(){var t=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?"x"===t.axis||i(this.items[0].item):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},_destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var t=this.items.length-1;t>=0;t--)this.items[t].item.removeData(this.widgetName+"-item");return this},_setOption:function(e,i){"disabled"===e?(this.options[e]=i,this.widget().toggleClass("ui-sortable-disabled",!!i)):t.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(e,i){var s=null,n=!1,a=this;return this.reverting?!1:this.options.disabled||"static"===this.options.type?!1:(this._refreshItems(e),t(e.target).parents().each(function(){return t.data(this,a.widgetName+"-item")===a?(s=t(this),!1):undefined}),t.data(e.target,a.widgetName+"-item")===a&&(s=t(e.target)),s?!this.options.handle||i||(t(this.options.handle,s).find("*").addBack().each(function(){this===e.target&&(n=!0)}),n)?(this.currentItem=s,this._removeCurrentsFromItems(),!0):!1:!1)},_mouseStart:function(e,i,s){var n,a,o=this.options;if(this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(e),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},t.extend(this.offset,{click:{left:e.pageX-this.offset.left,top:e.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(e),this.originalPageX=e.pageX,this.originalPageY=e.pageY,o.cursorAt&&this._adjustOffsetFromHelper(o.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!==this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),o.containment&&this._setContainment(),o.cursor&&"auto"!==o.cursor&&(a=this.document.find("body"),this.storedCursor=a.css("cursor"),a.css("cursor",o.cursor),this.storedStylesheet=t("").appendTo(a)),o.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",o.opacity)),o.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",o.zIndex)),this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",e,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions(),!s)for(n=this.containers.length-1;n>=0;n--)this.containers[n]._trigger("activate",e,this._uiHash(this));return t.ui.ddmanager&&(t.ui.ddmanager.current=this),t.ui.ddmanager&&!o.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(e),!0},_mouseDrag:function(e){var i,s,n,a,o=this.options,r=!1;for(this.position=this._generatePosition(e),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs),this.options.scroll&&(this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-e.pageY=0;i--)if(s=this.items[i],n=s.item[0],a=this._intersectsWithPointer(s),a&&s.instance===this.currentContainer&&n!==this.currentItem[0]&&this.placeholder[1===a?"next":"prev"]()[0]!==n&&!t.contains(this.placeholder[0],n)&&("semi-dynamic"===this.options.type?!t.contains(this.element[0],n):!0)){if(this.direction=1===a?"down":"up","pointer"!==this.options.tolerance&&!this._intersectsWithSides(s))break;this._rearrange(e,s),this._trigger("change",e,this._uiHash());break}return this._contactContainers(e),t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),this._trigger("sort",e,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(e,i){if(e){if(t.ui.ddmanager&&!this.options.dropBehaviour&&t.ui.ddmanager.drop(this,e),this.options.revert){var s=this,n=this.placeholder.offset(),a=this.options.axis,o={};a&&"x"!==a||(o.left=n.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollLeft)),a&&"y"!==a||(o.top=n.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollTop)),this.reverting=!0,t(this.helper).animate(o,parseInt(this.options.revert,10)||500,function(){s._clear(e)})}else this._clear(e,i);return!1}},cancel:function(){if(this.dragging){this._mouseUp({target:null}),"original"===this.options.helper?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var e=this.containers.length-1;e>=0;e--)this.containers[e]._trigger("deactivate",null,this._uiHash(this)),this.containers[e].containerCache.over&&(this.containers[e]._trigger("out",null,this._uiHash(this)),this.containers[e].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),"original"!==this.options.helper&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),t.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?t(this.domPosition.prev).after(this.currentItem):t(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},t(i).each(function(){var i=(t(e.item||this).attr(e.attribute||"id")||"").match(e.expression||/(.+)[\-=_](.+)/);i&&s.push((e.key||i[1]+"[]")+"="+(e.key&&e.expression?i[1]:i[2]))}),!s.length&&e.key&&s.push(e.key+"="),s.join("&")},toArray:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},i.each(function(){s.push(t(e.item||this).attr(e.attribute||"id")||"")}),s},_intersectsWith:function(t){var e=this.positionAbs.left,i=e+this.helperProportions.width,s=this.positionAbs.top,n=s+this.helperProportions.height,a=t.left,o=a+t.width,r=t.top,h=r+t.height,l=this.offset.click.top,c=this.offset.click.left,u="x"===this.options.axis||s+l>r&&h>s+l,d="y"===this.options.axis||e+c>a&&o>e+c,p=u&&d;return"pointer"===this.options.tolerance||this.options.forcePointerForContainers||"pointer"!==this.options.tolerance&&this.helperProportions[this.floating?"width":"height"]>t[this.floating?"width":"height"]?p:e+this.helperProportions.width/2>a&&o>i-this.helperProportions.width/2&&s+this.helperProportions.height/2>r&&h>n-this.helperProportions.height/2},_intersectsWithPointer:function(t){var i="x"===this.options.axis||e(this.positionAbs.top+this.offset.click.top,t.top,t.height),s="y"===this.options.axis||e(this.positionAbs.left+this.offset.click.left,t.left,t.width),n=i&&s,a=this._getDragVerticalDirection(),o=this._getDragHorizontalDirection();return n?this.floating?o&&"right"===o||"down"===a?2:1:a&&("down"===a?2:1):!1},_intersectsWithSides:function(t){var i=e(this.positionAbs.top+this.offset.click.top,t.top+t.height/2,t.height),s=e(this.positionAbs.left+this.offset.click.left,t.left+t.width/2,t.width),n=this._getDragVerticalDirection(),a=this._getDragHorizontalDirection();return this.floating&&a?"right"===a&&s||"left"===a&&!s:n&&("down"===n&&i||"up"===n&&!i)},_getDragVerticalDirection:function(){var t=this.positionAbs.top-this.lastPositionAbs.top;return 0!==t&&(t>0?"down":"up")},_getDragHorizontalDirection:function(){var t=this.positionAbs.left-this.lastPositionAbs.left;return 0!==t&&(t>0?"right":"left")},refresh:function(t){return this._refreshItems(t),this.refreshPositions(),this},_connectWith:function(){var t=this.options;return t.connectWith.constructor===String?[t.connectWith]:t.connectWith},_getItemsAsjQuery:function(e){var i,s,n,a,o=[],r=[],h=this._connectWith();if(h&&e)for(i=h.length-1;i>=0;i--)for(n=t(h[i]),s=n.length-1;s>=0;s--)a=t.data(n[s],this.widgetFullName),a&&a!==this&&!a.options.disabled&&r.push([t.isFunction(a.options.items)?a.options.items.call(a.element):t(a.options.items,a.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),a]);for(r.push([t.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):t(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]),i=r.length-1;i>=0;i--)r[i][0].each(function(){o.push(this)});return t(o)},_removeCurrentsFromItems:function(){var e=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=t.grep(this.items,function(t){for(var i=0;e.length>i;i++)if(e[i]===t.item[0])return!1;return!0})},_refreshItems:function(e){this.items=[],this.containers=[this];var i,s,n,a,o,r,h,l,c=this.items,u=[[t.isFunction(this.options.items)?this.options.items.call(this.element[0],e,{item:this.currentItem}):t(this.options.items,this.element),this]],d=this._connectWith();if(d&&this.ready)for(i=d.length-1;i>=0;i--)for(n=t(d[i]),s=n.length-1;s>=0;s--)a=t.data(n[s],this.widgetFullName),a&&a!==this&&!a.options.disabled&&(u.push([t.isFunction(a.options.items)?a.options.items.call(a.element[0],e,{item:this.currentItem}):t(a.options.items,a.element),a]),this.containers.push(a));for(i=u.length-1;i>=0;i--)for(o=u[i][1],r=u[i][0],s=0,l=r.length;l>s;s++)h=t(r[s]),h.data(this.widgetName+"-item",o),c.push({item:h,instance:o,width:0,height:0,left:0,top:0})},refreshPositions:function(e){this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());var i,s,n,a;for(i=this.items.length-1;i>=0;i--)s=this.items[i],s.instance!==this.currentContainer&&this.currentContainer&&s.item[0]!==this.currentItem[0]||(n=this.options.toleranceElement?t(this.options.toleranceElement,s.item):s.item,e||(s.width=n.outerWidth(),s.height=n.outerHeight()),a=n.offset(),s.left=a.left,s.top=a.top);if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(i=this.containers.length-1;i>=0;i--)a=this.containers[i].element.offset(),this.containers[i].containerCache.left=a.left,this.containers[i].containerCache.top=a.top,this.containers[i].containerCache.width=this.containers[i].element.outerWidth(),this.containers[i].containerCache.height=this.containers[i].element.outerHeight();return this},_createPlaceholder:function(e){e=e||this;var i,s=e.options;s.placeholder&&s.placeholder.constructor!==String||(i=s.placeholder,s.placeholder={element:function(){var s=e.currentItem[0].nodeName.toLowerCase(),n=t("<"+s+">",e.document[0]).addClass(i||e.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper");return"tr"===s?e.currentItem.children().each(function(){t(" ",e.document[0]).attr("colspan",t(this).attr("colspan")||1).appendTo(n)}):"img"===s&&n.attr("src",e.currentItem.attr("src")),i||n.css("visibility","hidden"),n},update:function(t,n){(!i||s.forcePlaceholderSize)&&(n.height()||n.height(e.currentItem.innerHeight()-parseInt(e.currentItem.css("paddingTop")||0,10)-parseInt(e.currentItem.css("paddingBottom")||0,10)),n.width()||n.width(e.currentItem.innerWidth()-parseInt(e.currentItem.css("paddingLeft")||0,10)-parseInt(e.currentItem.css("paddingRight")||0,10)))}}),e.placeholder=t(s.placeholder.element.call(e.element,e.currentItem)),e.currentItem.after(e.placeholder),s.placeholder.update(e,e.placeholder)},_contactContainers:function(s){var n,a,o,r,h,l,c,u,d,p,f=null,m=null;for(n=this.containers.length-1;n>=0;n--)if(!t.contains(this.currentItem[0],this.containers[n].element[0]))if(this._intersectsWith(this.containers[n].containerCache)){if(f&&t.contains(this.containers[n].element[0],f.element[0]))continue;f=this.containers[n],m=n}else this.containers[n].containerCache.over&&(this.containers[n]._trigger("out",s,this._uiHash(this)),this.containers[n].containerCache.over=0);if(f)if(1===this.containers.length)this.containers[m].containerCache.over||(this.containers[m]._trigger("over",s,this._uiHash(this)),this.containers[m].containerCache.over=1);else{for(o=1e4,r=null,p=f.floating||i(this.currentItem),h=p?"left":"top",l=p?"width":"height",c=this.positionAbs[h]+this.offset.click[h],a=this.items.length-1;a>=0;a--)t.contains(this.containers[m].element[0],this.items[a].item[0])&&this.items[a].item[0]!==this.currentItem[0]&&(!p||e(this.positionAbs.top+this.offset.click.top,this.items[a].top,this.items[a].height))&&(u=this.items[a].item.offset()[h],d=!1,Math.abs(u-c)>Math.abs(u+this.items[a][l]-c)&&(d=!0,u+=this.items[a][l]),o>Math.abs(u-c)&&(o=Math.abs(u-c),r=this.items[a],this.direction=d?"up":"down"));if(!r&&!this.options.dropOnEmpty)return;if(this.currentContainer===this.containers[m])return;r?this._rearrange(s,r,null,!0):this._rearrange(s,null,this.containers[m].element,!0),this._trigger("change",s,this._uiHash()),this.containers[m]._trigger("change",s,this._uiHash(this)),this.currentContainer=this.containers[m],this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[m]._trigger("over",s,this._uiHash(this)),this.containers[m].containerCache.over=1}},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper)?t(i.helper.apply(this.element[0],[e,this.currentItem])):"clone"===i.helper?this.currentItem.clone():this.currentItem;return s.parents("body").length||t("parent"!==i.appendTo?i.appendTo:this.currentItem[0].parentNode)[0].appendChild(s[0]),s[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")}),(!s[0].style.width||i.forceHelperSize)&&s.width(this.currentItem.width()),(!s[0].style.height||i.forceHelperSize)&&s.height(this.currentItem.height()),s},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var e=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&t.ui.ie)&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var t=this.currentItem.position();return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:t.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}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={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e,i,s,n=this.options;"parent"===n.containment&&(n.containment=this.helper[0].parentNode),("document"===n.containment||"window"===n.containment)&&(this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,t("document"===n.containment?document:window).width()-this.helperProportions.width-this.margins.left,(t("document"===n.containment?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]),/^(document|window|parent)$/.test(n.containment)||(e=t(n.containment)[0],i=t(n.containment).offset(),s="hidden"!==t(e).css("overflow"),this.containment=[i.left+(parseInt(t(e).css("borderLeftWidth"),10)||0)+(parseInt(t(e).css("paddingLeft"),10)||0)-this.margins.left,i.top+(parseInt(t(e).css("borderTopWidth"),10)||0)+(parseInt(t(e).css("paddingTop"),10)||0)-this.margins.top,i.left+(s?Math.max(e.scrollWidth,e.offsetWidth):e.offsetWidth)-(parseInt(t(e).css("borderLeftWidth"),10)||0)-(parseInt(t(e).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,i.top+(s?Math.max(e.scrollHeight,e.offsetHeight):e.offsetHeight)-(parseInt(t(e).css("borderTopWidth"),10)||0)-(parseInt(t(e).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top])},_convertPositionTo:function(e,i){i||(i=this.position);var s="absolute"===e?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,a=/(html|body)/i.test(n[0].tagName);return{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():a?0:n.scrollTop())*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():a?0:n.scrollLeft())*s}},_generatePosition:function(e){var i,s,n=this.options,a=e.pageX,o=e.pageY,r="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,h=/(html|body)/i.test(r[0].tagName);return"relative"!==this.cssPosition||this.scrollParent[0]!==document&&this.scrollParent[0]!==this.offsetParent[0]||(this.offset.relative=this._getRelativeOffset()),this.originalPosition&&(this.containment&&(e.pageX-this.offset.click.leftthis.containment[2]&&(a=this.containment[2]+this.offset.click.left),e.pageY-this.offset.click.top>this.containment[3]&&(o=this.containment[3]+this.offset.click.top)),n.grid&&(i=this.originalPageY+Math.round((o-this.originalPageY)/n.grid[1])*n.grid[1],o=this.containment?i-this.offset.click.top>=this.containment[1]&&i-this.offset.click.top<=this.containment[3]?i:i-this.offset.click.top>=this.containment[1]?i-n.grid[1]:i+n.grid[1]:i,s=this.originalPageX+Math.round((a-this.originalPageX)/n.grid[0])*n.grid[0],a=this.containment?s-this.offset.click.left>=this.containment[0]&&s-this.offset.click.left<=this.containment[2]?s:s-this.offset.click.left>=this.containment[0]?s-n.grid[0]:s+n.grid[0]:s)),{top:o-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():h?0:r.scrollTop()),left:a-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():h?0:r.scrollLeft())}},_rearrange:function(t,e,i,s){i?i[0].appendChild(this.placeholder[0]):e.item[0].parentNode.insertBefore(this.placeholder[0],"down"===this.direction?e.item[0]:e.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var n=this.counter;this._delay(function(){n===this.counter&&this.refreshPositions(!s)})},_clear:function(t,e){this.reverting=!1;var i,s=[];if(!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null,this.helper[0]===this.currentItem[0]){for(i in this._storedCSS)("auto"===this._storedCSS[i]||"static"===this._storedCSS[i])&&(this._storedCSS[i]="");this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();for(this.fromOutside&&!e&&s.push(function(t){this._trigger("receive",t,this._uiHash(this.fromOutside))}),!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(".ui-sortable-helper")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||e||s.push(function(t){this._trigger("update",t,this._uiHash())}),this!==this.currentContainer&&(e||(s.push(function(t){this._trigger("remove",t,this._uiHash())}),s.push(function(t){return function(e){t._trigger("receive",e,this._uiHash(this))}}.call(this,this.currentContainer)),s.push(function(t){return function(e){t._trigger("update",e,this._uiHash(this))}}.call(this,this.currentContainer)))),i=this.containers.length-1;i>=0;i--)e||s.push(function(t){return function(e){t._trigger("deactivate",e,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over&&(s.push(function(t){return function(e){t._trigger("out",e,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over=0);if(this.storedCursor&&(this.document.find("body").css("cursor",this.storedCursor),this.storedStylesheet.remove()),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex","auto"===this._storedZIndex?"":this._storedZIndex),this.dragging=!1,this.cancelHelperRemoval){if(!e){for(this._trigger("beforeStop",t,this._uiHash()),i=0;s.length>i;i++)s[i].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!1}if(e||this._trigger("beforeStop",t,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null,!e){for(i=0;s.length>i;i++)s[i].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!0},_trigger:function(){t.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(e){var i=e||this;return{helper:i.helper,placeholder:i.placeholder||t([]),position:i.position,originalPosition:i.originalPosition,offset:i.positionAbs,item:i.currentItem,sender:e?e.element:null}}})})(jQuery);(function(t){function e(e,i){var s=(e.attr("aria-describedby")||"").split(/\s+/);s.push(i),e.data("ui-tooltip-id",i).attr("aria-describedby",t.trim(s.join(" ")))}function i(e){var i=e.data("ui-tooltip-id"),s=(e.attr("aria-describedby")||"").split(/\s+/),n=t.inArray(i,s);-1!==n&&s.splice(n,1),e.removeData("ui-tooltip-id"),s=t.trim(s.join(" ")),s?e.attr("aria-describedby",s):e.removeAttr("aria-describedby")}var s=0;t.widget("ui.tooltip",{version:"1.10.3",options:{content:function(){var e=t(this).attr("title")||"";return t("
").text(e).html()},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,tooltipClass:null,track:!1,close:null,open:null},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.options.disabled&&this._disable()},_setOption:function(e,i){var s=this;return"disabled"===e?(this[i?"_disable":"_enable"](),this.options[e]=i,void 0):(this._super(e,i),"content"===e&&t.each(this.tooltips,function(t,e){s._updateContent(e)}),void 0)},_disable:function(){var e=this;t.each(this.tooltips,function(i,s){var n=t.Event("blur");n.target=n.currentTarget=s[0],e.close(n,!0)}),this.element.find(this.options.items).addBack().each(function(){var e=t(this);e.is("[title]")&&e.data("ui-tooltip-title",e.attr("title")).attr("title","")})},_enable:function(){this.element.find(this.options.items).addBack().each(function(){var e=t(this);e.data("ui-tooltip-title")&&e.attr("title",e.data("ui-tooltip-title"))})},open:function(e){var i=this,s=t(e?e.target:this.element).closest(this.options.items);s.length&&!s.data("ui-tooltip-id")&&(s.attr("title")&&s.data("ui-tooltip-title",s.attr("title")),s.data("ui-tooltip-open",!0),e&&"mouseover"===e.type&&s.parents().each(function(){var e,s=t(this);s.data("ui-tooltip-open")&&(e=t.Event("blur"),e.target=e.currentTarget=this,i.close(e,!0)),s.attr("title")&&(s.uniqueId(),i.parents[this.id]={element:this,title:s.attr("title")},s.attr("title",""))}),this._updateContent(s,e))},_updateContent:function(t,e){var i,s=this.options.content,n=this,a=e?e.type:null;return"string"==typeof s?this._open(e,t,s):(i=s.call(t[0],function(i){t.data("ui-tooltip-open")&&n._delay(function(){e&&(e.type=a),this._open(e,t,i)})}),i&&this._open(e,t,i),void 0)},_open:function(i,s,n){function a(t){l.of=t,o.is(":hidden")||o.position(l)}var o,r,h,l=t.extend({},this.options.position);if(n){if(o=this._find(s),o.length)return o.find(".ui-tooltip-content").html(n),void 0;s.is("[title]")&&(i&&"mouseover"===i.type?s.attr("title",""):s.removeAttr("title")),o=this._tooltip(s),e(s,o.attr("id")),o.find(".ui-tooltip-content").html(n),this.options.track&&i&&/^mouse/.test(i.type)?(this._on(this.document,{mousemove:a}),a(i)):o.position(t.extend({of:s},this.options.position)),o.hide(),this._show(o,this.options.show),this.options.show&&this.options.show.delay&&(h=this.delayedShow=setInterval(function(){o.is(":visible")&&(a(l.of),clearInterval(h))},t.fx.interval)),this._trigger("open",i,{tooltip:o}),r={keyup:function(e){if(e.keyCode===t.ui.keyCode.ESCAPE){var i=t.Event(e);i.currentTarget=s[0],this.close(i,!0)}},remove:function(){this._removeTooltip(o)}},i&&"mouseover"!==i.type||(r.mouseleave="close"),i&&"focusin"!==i.type||(r.focusout="close"),this._on(!0,s,r)}},close:function(e){var s=this,n=t(e?e.currentTarget:this.element),a=this._find(n);this.closing||(clearInterval(this.delayedShow),n.data("ui-tooltip-title")&&n.attr("title",n.data("ui-tooltip-title")),i(n),a.stop(!0),this._hide(a,this.options.hide,function(){s._removeTooltip(t(this))}),n.removeData("ui-tooltip-open"),this._off(n,"mouseleave focusout keyup"),n[0]!==this.element[0]&&this._off(n,"remove"),this._off(this.document,"mousemove"),e&&"mouseleave"===e.type&&t.each(this.parents,function(e,i){t(i.element).attr("title",i.title),delete s.parents[e]}),this.closing=!0,this._trigger("close",e,{tooltip:a}),this.closing=!1)},_tooltip:function(e){var i="ui-tooltip-"+s++,n=t("
").attr({id:i,role:"tooltip"}).addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content "+(this.options.tooltipClass||""));return t("
").addClass("ui-tooltip-content").appendTo(n),n.appendTo(this.document[0].body),this.tooltips[i]=e,n},_find:function(e){var i=e.data("ui-tooltip-id");return i?t("#"+i):t()},_removeTooltip:function(t){t.remove(),delete this.tooltips[t.attr("id")]},_destroy:function(){var e=this;t.each(this.tooltips,function(i,s){var n=t.Event("blur");n.target=n.currentTarget=s[0],e.close(n,!0),t("#"+i).remove(),s.data("ui-tooltip-title")&&(s.attr("title",s.data("ui-tooltip-title")),s.removeData("ui-tooltip-title"))})}})})(jQuery); \ No newline at end of file diff --git a/app/assets/javascripts/survey.js b/app/assets/javascripts/survey.js new file mode 100644 index 0000000..0479e0a --- /dev/null +++ b/app/assets/javascripts/survey.js @@ -0,0 +1,266 @@ +// Check Questions Length +function checkQuestionsLength() { + var questionsLength = $('.questions > .attributes').length; + if(questionsLength == 1) { + $('.questions .delete').addClass('hide'); + } else { + $('.questions .delete').removeClass('hide'); + }; +}; + +// Role Attribute Template Data +function setData(l, length, optionsI, className) { + if(!optionsI) { + optionsI = 0; + } + var id = "survey_survey_questions_attributes_", + name = "survey[survey_questions_attributes][", + optionID = l+"_survey_question_options_attributes_"+optionsI+"_name_translations_", + optionName = l+"][survey_question_options_attributes]["+optionsI+"][name_translations]", + radiogroupsID = l+"_survey_question_radiogroups_attributes_"+optionsI+"_name_translations_", + radiogroupsName = l+"][survey_question_radiogroups_attributes]["+optionsI+"][name_translations]"; + data = { + _l: l, + _ques: "new", + _length: length, + _className: className, + _destroy: [id+l+"_destroy", name+l+"][_destroy]"], + _sequence : [id+l+"_sequence",name+l+"][sequence]",length-1], + _title_translations: [id+l+"_title_translations", name+l+"][title_translations]", "questions_title_"+l,{"en":"","zh_tw":""}], + _description_translations: [id+l+"_description_translations", name+l+"][description_translations]", "questions_depiction_"+l,{"en":"","zh_tw":""}], + _type: [id+l+"_type", name+l+"][type]"], + _is_required: [id+l+"_is_required", name+l+"][is_required]",false], + _option: [id+optionID, name+optionName, "attributes_"+l+"_options_"+optionsI+"_",{"en":"","zh_tw":""}], + _radiogroups: [id+radiogroupsID, name+radiogroupsName, "attributes_"+l+"_radiogroups_"+optionsI+"_",{"en":"","zh_tw":""}], + _custom_option: [id+l+"_custom_option", name+l+"][custom_option]",false] + }; + return data; +}; + +function setEditData(l, length, d, optionsI, className) { + if(!optionsI) { + optionsI = 0; + } + var id = "survey_survey_questions_attributes_", + name = "survey[survey_questions_attributes][", + optionID = l+"_survey_question_options_attributes_"+optionsI+"_name_translations_", + optionName = l+"][survey_question_options_attributes]["+optionsI+"][name_translations]", + radiogroupsID = l+"_survey_question_radiogroups_attributes_"+optionsI+"_name_translations_", + radiogroupsName = l+"][survey_question_radiogroups_attributes]["+optionsI+"][name_translations]"; + data = { + _l: l, + _ques: "old", + _length: length, + _className: className, + _destroy: [id+l+"__destroy", name+l+"][_destroy]"], + _id: [id+l+"_id", name+l+"][id]",d._id], + _sequence : [id+l+"_sequence",name+l+"][sequence]",d.sequence], + _title_translations: [id+l+"_title_translations", name+l+"][title_translations]", "questions_title_"+l,d.title_translations], + _description_translations: [id+l+"_description_translations", name+l+"][description_translations]", "questions_depiction_"+l,d.description_translations], + _type: [id+l+"_type", name+l+"][type]",d.type], + _is_required: [id+l+"_is_required", name+l+"][is_required]",d.is_required], + _option: [id+optionID, name+optionName, "attributes_"+l+"_options_"+optionsI+"_"], + _radiogroups: [id+radiogroupsID, name+radiogroupsName, "attributes_"+l+"_radiogroups_"+optionsI+"_"], + _custom_option: [id+l+"_custom_option", name+l+"][custom_option]",d.custom_option] + }; + return data; +}; + +function setEditQuestionAttributes(l, length, d, optionsI, className) { + if(!optionsI) { + optionsI = 0; + } + var id = "survey_survey_questions_attributes_", + name = "survey[survey_questions_attributes][", + optionID = l+"_survey_question_options_attributes_"+optionsI+"_name_translations_", + optionName = l+"][survey_question_options_attributes]["+optionsI+"][name_translations]", + radiogroupsID = l+"_survey_question_radiogroups_attributes_"+optionsI+"_name_translations_", + radiogroupsName = l+"][survey_question_radiogroups_attributes]["+optionsI+"][name_translations]", + option_id = l+"][survey_question_options_attributes]["+optionsI+"][id]", + destroy = l+"][survey_question_options_attributes]["+optionsI+"][_destroy]", + radiogroups_id = l+"][survey_question_radiogroups_attributes]["+optionsI+"][id]"; + data = { + _l: l, + _length: length, + _ques: "old", + _className: className, + _destroy: [name+destroy], + _option: [id+optionID, name+optionName, "attributes_"+l+"_options_"+optionsI+"_", d.name_translations], + _radiogroups: [id+radiogroupsID, name+radiogroupsName, "attributes_"+l+"_radiogroups_"+optionsI+"_",d.name_translations], + _options_id: [name+option_id,d._id], + _radiogroups_id: [name+radiogroups_id,d._id] + + }; + return data; +}; + +function inputAppendLength(element, length) { + if(length == 2) { + element.closest('.add-target').find('.remove-input').addClass('hide').prev().addClass('last'); + } + var option = element.closest('.input-append'); + if( option.data( 'question-option' ) == "old" ){ + option.hide().removeAttr( 'question-option' ).find( "input.should_destroy_option" ).val("1"); + } else if( option.data( "question-option" ) == "new"){ + option.remove(); + } +} + +function editQuestion (dataArray){ + var l = $('.questions > .attributes').length || 0; + $.each(dataArray,function ( i, d ) { + $('#template-survery').tmpl(setEditData(l, $('.questions > .attributes').length + 1, d)).appendTo($('.questions')); + checkQuestionsLength(); + textareaResizable(); // from textarea-lang-btn.js + if( d.type > 1 && d.type < 5 ){ + onQuestionTypeChanged( $(".questions .field-type:eq("+ i +")"), d.type ); + $.each(d.survey_question_options,function ( x, data ){ + $('#template-survery-option').tmpl(setEditQuestionAttributes( l, "", data, x, "options" )).insertBefore($(".questions .field-type:eq("+ i +") .options .add-btn")); + $(".questions .field-type:eq("+ i +") .options").data("index",x); + }) + } else if( d.type == 5 ) { + onQuestionTypeChanged( $(".questions .field-type:eq("+ i +")"), d.type ); + $.each(d.survey_question_radiogroups,function ( x, data ){ + $('#template-survery-option').tmpl(setEditQuestionAttributes( l, "", data, x, "rgl" )).insertBefore($(".questions .field-type:eq("+ i +") .rgl .add-btn")); + $(".questions .field-type:eq("+ i +") .options").data("index",x); + }) + $.each(d.survey_question_options,function ( x, data ){ + $('#template-survery-option').tmpl(setEditQuestionAttributes( l, "", data, x, "options" )).insertBefore($(".questions .field-type:eq("+ i +") .options .add-btn")); + $(".questions .field-type:eq("+ i +") .options").data("index",x); + }) + } + l++; + }) +} + +function onQuestionTypeChanged ( $fieldType, _val ){ + if(_val < 2) { + $fieldType.fadeOut(300); + } else { + $fieldType.fadeIn(300); + if(_val < 5) { + $fieldType.find('.rgl, hr').addClass('hide').siblings('.allow').removeClass('hide'); + } else { + $fieldType.find('.rgl, hr').removeClass('hide').siblings('.allow').addClass('hide'); + } + }; +} + +$(function() { + var l = $('.questions > .attributes').length || 0; + if($('#survey_redirect_mode').prop('checked')) { + $('.questions').fadeOut(300); + $('.redirect-url').fadeIn(300); + } else { + $('.questions').fadeIn(300); + $('.redirect-url').fadeOut(300); + }; + $('#survey_redirect_mode').change(function(event) { + if($(this).prop('checked')) { + $('.questions').fadeOut(300); + $('.redirect-url').fadeIn(300); + } else { + $('.questions').fadeIn(300); + $('.redirect-url').fadeOut(300); + } + }); + $('.field-type').each(function() { + $(this).children('.control-group').each(function() { + $(this).data().index = $(this).find('.input-append').length + }); + }); + $('.add-target').each(function() { + if($(this).children('.input-append').length == 1) { + $(this).find('.remove-input').addClass('hide').prev().addClass('last'); + }; + }); + $('.add-question').on(clickEvent, function(event) { + $('#template-survery').tmpl(setData(l, $('.questions > .attributes[data-question]').length + 1)).appendTo($('.questions')); + checkQuestionsLength(); + textareaResizable(); // from textarea-lang-btn.js + l += 1; + }); + + $('.questions').on('change', '.type-selector', function(event) { + var $fieldType = $(this).closest('.control-group').siblings('.field-type'), + _val = $(this).val(), + _index = $(this).closest('.attributes').data().index; + + onQuestionTypeChanged( $fieldType, _val ); + }); + $('.questions').on(clickEvent, "input[type=checkbox]", function(){ + if( $( this ).is(":checked") ) + $( this ).parent().find( 'input[type=hidden]' ).val("1"); + else + $( this ).parent().find( 'input[type=hidden]' ).val("0"); + }) + + $('.questions').on('keyup', '.q-title', function(event) { + var $questionsTitle = $(this).closest('.attributes-body').siblings('.attributes-header').find('.questions-title'), + $tabPane = $(this).closest('.tab-content'); + $questionsTitle.text($tabPane.find('.active input[type="text"]').val()) + event.preventDefault(); + /* Act on the event */ + }); + $(".questions").sortable({ + update : function ( event, ui ){ + $(".questions .attributes").each( function ( i ){ + $( this ).find( "input.sequence" ).val( i ); + $( this ).find( "h4 span:eq(0)" ).text( i + 1 ); + $( this ).attr( "data-index", i ); + }) + } + }); + + $('.questions').on(clickEvent, '.add-btn a, .remove-input, .delete, .attributes-header h4 i, .btn-group .btn', function(event) { + if($(this).hasClass('remove-input')){ + inputAppendLength($(this), $(this).closest('.add-target').children('.input-append').length); + } else if($(this).hasClass('delete')) { + $(this).closest('.attributes').fadeOut(300, function() { + if( $( this ).data( 'question' ) == "old" ){ + $(this).hide().removeAttr('data-question'); + $( this ).find( '.should_destroy' ).val(1); + l--; + checkQuestionsLength(); + $('.questions .attributes[data-question]').each(function(index, el) { + $( this ).find( "input.sequence" ).val( index ); + $( this ).find( "h4 span:eq(0)" ).text( index + 1 ); + $( this ).attr( "data-index", index ); + }); + } else if( $( this ).data( 'question' ) == "new" ){ + $( this ).remove(); + l--; + checkQuestionsLength(); + $('.questions .attributes[data-question]').each(function(index, el) { + $( this ).find( "input.sequence" ).val( index ); + $( this ).find( "h4 span:eq(0)" ).text( index + 1 ); + $( this ).attr( "data-index", index ); + }); + } + }); + } else if($(this).hasClass('icon-caret-up') || $(this).hasClass('icon-caret-down')) { + if($(this).hasClass('icon-caret-up')) { + $(this).closest('.attributes-header').siblings('.attributes-body').slideUp(300) + $(this).addClass('icon-caret-down').removeClass('icon-caret-up'); + } else { + $(this).closest('.attributes-header').siblings('.attributes-body').slideDown(300) + $(this).addClass('icon-caret-up').removeClass('icon-caret-down'); + } + } else if($(this).hasClass('change-title')){ + var $questionsTitle = $(this).closest('.attributes-body').siblings('.attributes-header').find('.questions-title'), + $tabPane = $(this).closest('.btn-group').siblings('.tab-content'); + $questionsTitle.text($tabPane.find('div').not('.active').children('input[type="text"]').val()) + } else { + var _i = $(this).closest('.control-group').data('index') || 0, + _className = $(this).closest('.control-group').attr('class').match(/options|rgl/g)[0], + _index = $(this).closest('.attributes').data().index, + _length = $(this).closest('.add-btn').siblings('.input-append').length; + $('#template-survery-option').tmpl(setData(_index, "", _i, _className)).insertBefore($(this).closest('.add-btn')); + $(this).closest('.add-target').find('.input-append').find('.remove-input').removeClass('hide').prev().removeClass('last'); + _i += 1 + $(this).closest('.control-group').data('index', _i); + } + event.preventDefault(); + }); + checkQuestionsLength(); +}); \ No newline at end of file diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb new file mode 100644 index 0000000..307a4ac --- /dev/null +++ b/app/controllers/application_controller.rb @@ -0,0 +1,23 @@ +class ApplicationController < ActionController::Base + protect_from_forgery + before_filter :set_locale + + # Set I18n.locale + def set_locale + # update session if passed + session[:locale] = params[:locale] if params[:locale] + + # set locale based on session or default + begin + # check if locale is valid for non site pages + if !VALID_LOCALES.include?(session[:locale]) + I18n.locale = I18n.default_locale + else + I18n.locale = session[:locale] + end + rescue + I18n.locale = I18n.default_locale + end + end + +end diff --git a/app/controllers/panel/survey/back_end/surveys_answers_controller.rb b/app/controllers/panel/survey/back_end/surveys_answers_controller.rb new file mode 100644 index 0000000..b61a5b5 --- /dev/null +++ b/app/controllers/panel/survey/back_end/surveys_answers_controller.rb @@ -0,0 +1,29 @@ +class Panel::Survey::BackEnd::SurveysAnswersController < OrbitBackendController + + include AdminHelper + include OrbitControllerLib::DivisionForDisable + + def initialize + super + @app_title = 'survey_answer' + end + + def index + @survey = ::Survey.find(params[:survey_id]) + @answers = (params[:sort]) ? get_sorted_and_filtered("@survey.survey_answers") : get_viewable("@survey.survey_answers") + respond_to do |format| + format.html # index.html.erb + format.xml { render :xml => @qas } + format.js + end + end + + def delete + @survey = ::Survey.find(params[:survey_id]) + if params[:ids] + answers = @survey.survey_answers.any_in(:_id => params[:ids]).destroy_all + end + redirect_to panel_survey_back_end_survey_answers_url(@survey, :direction => params[:direction], :sort => params[:sort], :sort_options => params[:sort_options]) + end + +end \ No newline at end of file diff --git a/app/controllers/panel/survey/back_end/surveys_controller.rb b/app/controllers/panel/survey/back_end/surveys_controller.rb new file mode 100644 index 0000000..7b31514 --- /dev/null +++ b/app/controllers/panel/survey/back_end/surveys_controller.rb @@ -0,0 +1,250 @@ +require 'csv' + +class Panel::Survey::BackEnd::SurveysController < OrbitBackendController + + include AdminHelper + include OrbitControllerLib::DivisionForDisable + + def initialize + super + @app_title = 'survey' + end + + def index + @surveys = (params[:sort]) ? get_sorted_and_filtered("survey") : get_viewable("survey") + + respond_to do |format| + format.html # index.html.erb + format.xml { render :xml => @qas } + format.js + end + end + + def new + @survey = ::Survey.new + @primary_locale = I18n.locale.to_s + @secondary_locale = (I18n.locale == :zh_tw) ? "en" : "zh_tw" + + respond_to do |format| + format.html # new.html.erb + format.xml { render :xml => @survey } + end + end + + def create + @survey = ::Survey.new(params[:survey]) + + @survey.create_user_id = current_user.id + @survey.update_user_id = current_user.id + + respond_to do |format| + if @survey.save + format.html { redirect_to(panel_survey_back_end_surveys_url) } + format.xml { render :xml => @survey, :status => :created, :location => @survey } + else + format.html { render :action => "new" } + format.xml { render :xml => @survey.errors, :status => :unprocessable_entity } + end + end + end + + def edit + @primary_locale = I18n.locale.to_s + @secondary_locale = (I18n.locale == :zh_tw) ? "en" : "zh_tw" + @survey = ::Survey.find(params[:id]) + @sqs = [] + @survey.survey_questions.each do |sq| + sq['title_translations'] = sq.title_translations + sq['description_translations'] = sq.description_translations + temp = [] + sq.survey_question_options.each do |sqo| + sqo['name_translations'] = sqo.name_translations + temp << sqo + end + temp = [] + sq.survey_question_radiogroups.each do |sqr| + sqr['name_translations'] = sqr.name_translations + temp << sqr + end + sq.survey_question_radiogroups = temp + @sqs << sq + end + end + + def update + @survey = ::Survey.find(params[:id]) + @survey.update_user_id = current_user.id + + respond_to do |format| + if @survey.update_attributes(params[:survey]) + format.html { redirect_to(panel_survey_back_end_surveys_url(:page => params[:page])) } + format.xml { head :ok } + else + format.html { render :action => "edit" } + format.xml { render :xml => @survey.errors, :status => :unprocessable_entity } + end + end + end + + def destroy + @survey = ::Survey.find(params[:id]) + + @survey.destroy + + respond_to do |format| + + format.html { redirect_to(panel_survey_back_end_surveys_url) } + format.js + end + end + + def delete + if params[:ids] + surveys = ::Survey.any_in(:_id => params[:ids]).destroy_all + end + redirect_to panel_survey_back_end_surveys_url(:direction => params[:direction], :sort => params[:sort], :sort_options => params[:sort_options]) + end + + def export + @survey = ::Survey.find(params[:id]) + @chart_data, @survey_questions, @survey_answers = @survey.generate_chart_data + + csv = CSV.generate do |csv| + row = [] + @survey_questions.each do |question| + row << question.title + row << ' ' + end + csv << row + csv_stats = [] + @survey_questions.each do |question| + csv_options = [] + csv_counts = [] + case question.type + when ::SurveyQuestion::Radio, ::SurveyQuestion::Select, ::SurveyQuestion::Check + question.survey_question_options.map do |option| + csv_options << option.name + csv_counts << "#{(@chart_data[question.id.to_s][option.name] || 0 rescue 0)}" + end + when ::SurveyQuestion::Radiogroup + question.survey_question_options.map do |option| + question.survey_question_radiogroups.map do |group| + csv_options << "#{option.name} - #{group.name}" + csv_counts << "#{(@chart_data[question.id.to_s][option.name][group.name] || 0 rescue 0)}" + end + end.flatten + else + csv_options << " " + csv_counts << " " + end + csv_stats << csv_options + csv_stats << csv_counts + end + max_length = csv_stats.map(&:length).max + csv_stats.map do |l| + while l.length < max_length + l.push ' ' + end + l + end.transpose.each do |l| + csv << l + end + @survey_answers.each do |answer| + row = [] + @survey_questions.each do |question| + if question.type == ::SurveyQuestion::Radiogroup + options = Hash[question.survey_question_options.collect{|o| [ o.id.to_s, o.name ] }] + row << Hash[answer[question.id.to_s].map {|o, g| [options[o], g]}] + else + row << answer[question.id.to_s] + end + row << ' ' + end + csv << row + end + + end + + respond_to do |format| + format.csv do + response.headers["Content-Type"] = "text/csv; charset=big5" + render :text => csv.encode('Big5') + end + end + end + + def set_answers + @survey = ::Survey.find(params[:id]) + end + + def jump + @survey = ::Survey.find(params[:id]) + @questions = @survey.survey_questions.all + + @jump_to_options = [[ t('survey.not_jump'), 0 ], [t('survey.jump_to_end'), 1]] + @jump_to_options += @questions.collect {|q| [ q.title, q.id.to_s ] } + end + + def duplicate_it + @survey = ::Survey.find(params[:id]) + + @new_survey = ::Survey.new + + @survey.attributes.each do |key, value| + unless ['_id', 'created_at', 'updated_at', 'update_user_id'].include? key + if @survey.respond_to?(key + '_translations') + @new_survey.send(key + '_translations=', value) + else + @new_survey.write_attribute(key, value) + end + end + end + @survey.survey_questions.all.each do |question| + new_question = @new_survey.survey_questions.new + question.attributes.each do |key, value| + unless ['_id', 'survey_id'].include? key + if question.respond_to?(key + '_translations') + new_question.send(key + '_translations=', value) + else + new_question.write_attribute(key, value) + end + end + end + question.survey_question_options.all.each do |option| + new_option = new_question.survey_question_options.new + option.attributes.each do |key, value| + unless ['_id', 'survey_question_id'].include? key + if option.respond_to?(key + '_translations') + new_option.send(key + '_translations=', value) + else + new_option.write_attribute(key, value) + end + end + end + end + question.survey_question_radiogroups.all.each do |radiogroup| + new_radiogroup = new_question.survey_question_radiogroups.new + radiogroup.attributes.each do |key, value| + unless ['_id', 'survey_question_id'].include? key + if radiogroup.respond_to?(key + '_translations') + new_radiogroup.send(key + '_translations=', value) + else + new_radiogroup.write_attribute(key, value) + end + end + end + end + end + + @new_survey.create_user_id = current_user.id + @new_survey.update_user_id = current_user.id + + @new_survey.save! + + respond_to do |format| + format.html { redirect_to(panel_survey_back_end_surveys_url) } + format.xml { render :xml => @survey, :status => :created, :location => @new_survey } + end + end + +end diff --git a/app/controllers/panel/survey/front_end/surveys_controller.rb b/app/controllers/panel/survey/front_end/surveys_controller.rb new file mode 100644 index 0000000..847fa43 --- /dev/null +++ b/app/controllers/panel/survey/front_end/surveys_controller.rb @@ -0,0 +1,113 @@ +class Panel::Survey::FrontEnd::SurveysController < OrbitWidgetController + helper ApplicationHelper + + def initialize + super + @app_title = 'survey' + end + + def index + end + + def show + @survey = ::Survey.find params[:id] + if @survey.redirect_mode + @redirect_url = @survey.redirect_url + render :redirect_standalone + else + redirect_standalone panel_survey_front_end_survey_path(params[:id], :standalone => 'true') do + @questions = @survey.survey_questions.all + if @survey.jump_mode + @jumpable_questions = @questions.all.select{ |q| q.jumpable? && q.can_set_jump? } + + @jump_tos_map = @jumpable_questions.map(&:get_jump_tos).inject(:merge) + end + end + end + end + + def update + @survey = ::Survey.find params[:id] + answer = params[:answer] + + @answer_model = @survey.survey_answers.new + @survey.survey_questions.each do |question| + qid = question.id.to_s + if question.is_required && answer[qid].blank? && !@survey.jump_mode #&& (! @survey.jump_mode || ( @survey.jump_mode && question.jumpable? ) ) + @answer_model.errors.add question.title, t('survey_question.required_error') + else + case question.type + when ::SurveyQuestion::Radio, ::SurveyQuestion::Select + if question.custom_option && answer[qid] == 'custom_option' + @answer_model[qid] = answer[qid + '_custom_option'] + else + if answer[qid] + @answer_model[qid] = question.survey_question_options.find(answer[qid]).name + end + end + when ::SurveyQuestion::Check + @answer_model[qid] = [] + if answer[qid] + answer[qid].each do |oid, value| + if value.to_i != 0 + if question.custom_option && oid == 'custom_option' + @answer_model[qid].push answer[qid + '_custom_option'] + else + @answer_model[qid].push question.survey_question_options.find(oid).name + end + end + end + end + when ::SurveyQuestion::Radiogroup + @answer_model[qid] = {} + options = Hash[question.survey_question_options.collect{|o| [ o.id.to_s, o.name ] }] + radiogroups = Hash[question.survey_question_radiogroups.collect{|rg| [ rg.id.to_s, rg.name] }] + if answer[qid] + answer[qid].each do |oid, value| + unless value.blank? + @answer_model[qid][oid] = radiogroups[value] + else + if question.is_required + @answer_model.errors.add question.title, t('survey_question.required_error') + end + end + end + end + when ::SurveyQuestion::Oneline, ::SurveyQuestion::Multiline + @answer_model[qid] = answer[qid] + end + end + end + if @answer_model.errors.empty? + @answer_model.save! + render :answer_success + else + @survey_answer_error = @answer_model.errors.full_messages.join(',') + render :answer_error + end + end + + def result + redirect_standalone result_panel_survey_front_end_survey_path(params[:id], :standalone => 'true') do + @survey = ::Survey.find params[:id] + @survey.result_type = ::Survey::ResultChart if params[:force_chart] + case @survey.result_type + when ::Survey::ResultChart + @chart_data, @survey_questions, @survey_answers = @survey.generate_chart_data + end + end + end + + def redirect_standalone url + unless params[:standalone] == 'true' + @redirect_url = url + render :redirect_standalone + else + module_app = ModuleApp.first(:conditions => {:key => 'survey'}) + @item = Item.where(module_app_id: module_app.id, app_frontend_url: 'default_widget').first + yield + render :layout => 'standalone' + end + end + +end \ No newline at end of file diff --git a/app/models/survey.rb b/app/models/survey.rb new file mode 100644 index 0000000..579f091 --- /dev/null +++ b/app/models/survey.rb @@ -0,0 +1,141 @@ +# encoding: utf-8 + +class Survey + + include Mongoid::Document + include Mongoid::Timestamps + + ResultChart = 0 + ResultExtern = 1 + ResultFile = 2 + + scope :available_for_lang, ->(locale){ where("available_for_#{locale}".to_sym => true) } + scope :can_display, where(is_hidden: false) + + field :title, :localize => true + field :description, :localize => true + + field :create_user_id + field :update_user_id + + field :postdate, :type => DateTime + field :deadline, :type => DateTime + + field :is_hidden, :type => Boolean, :default => false + + field :result_type, :type => Integer, :default => 0 + field :extern_link + mount_uploader :upload_file, AssetUploader + + field :jump_mode, :type => Boolean, :default => false + + field :redirect_mode, :type => Boolean, :default => false + field :redirect_url, :type => String + + validates :title, :at_least_one => true + + has_many :survey_questions, :autosave => true, :dependent => :destroy + has_many :survey_answers, :dependent => :destroy + + accepts_nested_attributes_for :survey_questions, :allow_destroy => true + + before_save :check_deadline, :update_avliable_language + + def time_range + r = "#{self.postdate.to_date}" + r += "- #{self.deadline.to_date}" if self.deadline + r + end + + def result + if ( self.result_type == Survey::ResultChart && self.deadline && Time.now > self.deadline ) || + ( self.result_type == Survey::ResultExtern && !self.extern_link.blank? ) || + ( self.result_type == Survey::ResultFile && self.upload_file? ) + ('').html_safe + else + '' + end + end + + def write + unless self.deadline && Time.now > self.deadline + ('').html_safe + else + '' + end + end + + def generate_chart_data + survey_questions = self.survey_questions.all + survey_answers = self.survey_answers.all + + chart_data = {} + + survey_questions.each do |question| + qid = question.id.to_s + options = question.survey_question_options.map(&:name) + case question.type + when ::SurveyQuestion::Radio, ::SurveyQuestion::Select + chart_data[qid] = {} + answers = survey_answers.each do |answer| + if answer[qid] + this_answer = answer[qid] + unless options.include? this_answer + this_answer = I18n.t('survey_question.use_custom_option') + end + chart_data[qid][this_answer] ||= 0 + chart_data[qid][this_answer] += 1 + end + end + when ::SurveyQuestion::Check + chart_data[qid] = {} + answers = survey_answers.each do |answer| + if answer[qid] + answer[qid].each do |option| + this_answer = option + unless options.include? this_answer + this_answer = I18n.t('survey_question.use_custom_option') + end + chart_data[qid][this_answer] ||= 0 + chart_data[qid][this_answer] += 1 + end + end + end + when ::SurveyQuestion::Radiogroup + chart_data[qid] = {} + answers = survey_answers.each do |answer| + if answer[qid] + answer[qid].each do |option, group| + chart_data[qid][option] ||= {} + chart_data[qid][option][group] ||= 0 + chart_data[qid][option][group] += 1 + end + end + end + end + end + + [chart_data, survey_questions, survey_answers] + end + + protected + + def check_deadline + if(!self.deadline.nil? and (self.deadline < self.postdate )) + self.deadline = nil + end + end + + def update_avliable_language + VALID_LOCALES.each do |locale| + if (title_translations[locale].blank? rescue true) + self["available_for_#{locale}".to_sym] = false + else + self["available_for_#{locale}".to_sym] = true + end + end + end + + paginates_per 10 + +end \ No newline at end of file diff --git a/app/models/survey_answer.rb b/app/models/survey_answer.rb new file mode 100644 index 0000000..94fa215 --- /dev/null +++ b/app/models/survey_answer.rb @@ -0,0 +1,7 @@ +class SurveyAnswer + include Mongoid::Document + include Mongoid::Timestamps + + belongs_to :survey + +end diff --git a/app/models/survey_question.rb b/app/models/survey_question.rb new file mode 100644 index 0000000..6feae2a --- /dev/null +++ b/app/models/survey_question.rb @@ -0,0 +1,48 @@ +class SurveyQuestion + + Oneline = 0 + Multiline = 1 + Radio = 2 + Check = 3 + Select = 4 + Radiogroup = 5 + + include Mongoid::Document + + field :title, :localize => true + field :description, :localize => true + field :is_required, :type => Boolean + field :type, :type => Integer + + # allow custom answer option + field :custom_option, :type => Boolean + + field :sequence, :type => Integer, :default => 0 + + belongs_to :survey + embeds_many :survey_question_options + embeds_many :survey_question_radiogroups + + accepts_nested_attributes_for :survey_question_options, :allow_destroy => true + accepts_nested_attributes_for :survey_question_radiogroups, :allow_destroy => true + + default_scope asc(:sequence) + + def jumpable? + case type + when SurveyQuestion::Radio, SurveyQuestion::Select + true + else + false + end + end + + def can_set_jump? + ( !custom_option ) + end + + def get_jump_tos + Hash[survey_question_options.select{ |o| !o.jump_to.blank? }.collect{ |o| [o.id.to_s, o.jump_to] }] + end + +end diff --git a/app/models/survey_question_oneline.rb b/app/models/survey_question_oneline.rb new file mode 100644 index 0000000..4b5dab3 --- /dev/null +++ b/app/models/survey_question_oneline.rb @@ -0,0 +1,3 @@ +class SurveyQuestionOneline < SurveyQuestion + +end \ No newline at end of file diff --git a/app/models/survey_question_option.rb b/app/models/survey_question_option.rb new file mode 100644 index 0000000..c6cc2ba --- /dev/null +++ b/app/models/survey_question_option.rb @@ -0,0 +1,8 @@ +class SurveyQuestionOption + include Mongoid::Document + + field :name, :localize => true + field :jump_to, :default => 0 + + embedded_in :survey_question +end \ No newline at end of file diff --git a/app/models/survey_question_radiogroup.rb b/app/models/survey_question_radiogroup.rb new file mode 100644 index 0000000..05d4fcf --- /dev/null +++ b/app/models/survey_question_radiogroup.rb @@ -0,0 +1,7 @@ +class SurveyQuestionRadiogroup + include Mongoid::Document + + field :name, :localize => true + + embedded_in :survey_question +end \ No newline at end of file diff --git a/app/views/panel/survey/back_end/surveys/_filter.html.erb b/app/views/panel/survey/back_end/surveys/_filter.html.erb new file mode 100644 index 0000000..0042d5c --- /dev/null +++ b/app/views/panel/survey/back_end/surveys/_filter.html.erb @@ -0,0 +1,11 @@ + + +<% content_for :page_specific_javascript do %> + <%= javascript_include_tag "sort_header" %> +<% end %> \ No newline at end of file diff --git a/app/views/panel/survey/back_end/surveys/_form.html.erb b/app/views/panel/survey/back_end/surveys/_form.html.erb new file mode 100644 index 0000000..bc54227 --- /dev/null +++ b/app/views/panel/survey/back_end/surveys/_form.html.erb @@ -0,0 +1,121 @@ +<% content_for :page_specific_css do %> + <%= stylesheet_link_tag "lib/main-forms" %> + <%= stylesheet_link_tag "lib/wrap-nav" %> + <%= stylesheet_link_tag "lib/main-list" %> +<% end %> +<% content_for :page_specific_javascript do %> + <%= javascript_include_tag "jquery-ui-custom.js" %> + <%= javascript_include_tag "lib/bootstrap-datetimepicker" %> + <%= javascript_include_tag "lib/datetimepicker/datetimepicker.js" %> + <%= javascript_include_tag "lib/member/textarea-lang-btn.js" %> + <%= javascript_include_tag "lib/jquery.tmpl.min.js" %> + <%= javascript_include_tag "survey.js" %> +<% end %> +<%= f.error_messages %> +
+
+
+
+

Basic

+
+
+
+ + +
+ +
+
+
+ <% @site_in_use_locales.each_with_index do |locale, i| %> +
" id="title_<%= locale %>"> + <%= f.fields_for :title_translations do |f| %> + <%= f.text_field locale, :class=>'span4', :value => (@survey.title_translations[locale] rescue nil), :placeholder => I18nVariable.from_locale(locale) %> + <% end %> +
+ <% end %> +
+
+ <% @site_in_use_locales.each_with_index do |locale, i| %> + " href="#title_<%= locale %>" data-toggle="tab"><%= I18nVariable.from_locale(locale) %> + <% end %> +
+
+
+
+ +
+ +
+
+
+ <% @site_in_use_locales.each_with_index do |locale, i| %> + " href="#textarea_<%= locale %>_0" data-toggle="tab"><%= I18nVariable.from_locale(locale) %> + <% end %> +
+ <% @site_in_use_locales.each_with_index do |locale, i| %> +
" id="textarea_<%= locale %>_0"> + <%= f.fields_for :description_translations do |f| %> + <%= f.text_area locale, :class=>'resizable', :value => (@survey.description_translations[locale] rescue nil), :placeholder => I18nVariable.from_locale(locale), :rows=>"3" %> + <% end %> +
+ <% end %> +
+
+
+ +
+ +
+ <%= f.datetime_picker :postdate, :no_label => true %> +
+
+ +
+ +
+ <%= f.datetime_picker :deadline, :no_label => true %> +
+
+ + +
+ +
+ +
+
+ + +
+ +
+ <%= f.text_field :redirect_url, :class=>"input-xlarge", :placeholder=>"Redirect URL" %> +
+
+ +
+ +
+ +
+ +
+ +
+ + <%= f.submit t('save'), :class=>'btn btn-primary' %> + <%= link_to t('cancel'), get_go_back, :class=>"btn" %> +
+
+ +<%= render :partial => "questions" %> + + diff --git a/app/views/panel/survey/back_end/surveys/_form_survey_question.html.erb b/app/views/panel/survey/back_end/surveys/_form_survey_question.html.erb new file mode 100644 index 0000000..2be932a --- /dev/null +++ b/app/views/panel/survey/back_end/surveys/_form_survey_question.html.erb @@ -0,0 +1,137 @@ +<% # encoding: utf-8 %> + +
" class="survey_question_item clear"> +
+
+ +
+

<%= t('survey.question') %>

+
+
+ <% @site_in_use_locales.each_with_index do |locale, i| %> + +
"> + +
+ <%= f.label :title , t('survey_question.title') %> + <%= f.fields_for :title_translations do |f| %> + <%= I18nVariable.from_locale(locale) %> + <%= f.text_field locale, :style=>"width:98%;", :value => (form_survey_question.title_translations[locale] rescue nil) %> + <% end %> +
+ +
+ <%= f.label :description ,t('survey_question.description') %> + <%= f.fields_for :description_translations do |f| %> + <%= I18nVariable.from_locale(locale) %> + <%= f.text_area locale, :rows => 5, :style=>"width:98%;", :value => (form_survey_question.description_translations[locale] rescue nil) %> + <% end %> +
+ +
+ + <% end %> + +
+ <%= f.label :sequence , t('survey_question.sequence') %> + <%= f.text_field :sequence %> + <%= t('survey_question.move_up') %> + <%= t('survey_question.move_down') %> +
+ +
+ <%= f.label :type, t('survey_question.type')%> + <%= f.select :type, { + t('survey_question.oneline') => SurveyQuestion::Oneline, + t('survey_question.multiline') => SurveyQuestion::Multiline, + t('survey_question.radio') => SurveyQuestion::Radio, + t('survey_question.check') => SurveyQuestion::Check, + t('survey_question.select') => SurveyQuestion::Select, + t('survey_question.radiogroup') => SurveyQuestion::Radiogroup + }, {}, :class => "type-selector input-medium" %> +
+ +
+ <%= f.label :is_required, t('survey_question.is_required')%> + <%= f.check_box :is_required %> +
+ +
+ <%= f.label :survey_question_options, t('survey_question.radiogroups_lists')%> + + + + + + + + + <% form_survey_question.survey_question_radiogroups.each_with_index do |survey_question_radiogroup, i| %> + <%= f.fields_for :survey_question_radiogroups, survey_question_radiogroup do |f| %> + <%= render :partial => 'form_survey_question_radiogroup', :object => survey_question_radiogroup, :locals => {:f => f, :i => i} %> + <% end %> + <% end %> + + + + + + +
<%= t('survey_question.radiogroup_label') %>
+
+ <%= f.hidden_field :survey_question_radiogroup_field_count, :value => form_survey_question.survey_question_radiogroups.count %> + <%= t(:add) %> + +
+
+
+ +
+ <%= f.label :survey_question_options, t('survey_question.options_lists')%> + + + + + + + + + <% form_survey_question.survey_question_options.each_with_index do |survey_question_option, i| %> + <%= f.fields_for :survey_question_options, survey_question_option do |f| %> + <%= render :partial => 'form_survey_question_option', :object => survey_question_option, :locals => {:f => f, :i => i} %> + <% end %> + <% end %> + + + + + + +
<%= t('survey_question.option') %>
+
+ <%= f.hidden_field :survey_question_option_field_count, :value => form_survey_question.survey_question_options.count %> + <%= t(:add) %> + +
+
+
+ <%= f.label :custom_option, t('survey_question.custom_option')%> + <%= f.check_box :custom_option %> +
+
+
+ <% if form_survey_question.new_record? %> + + <% else %> + <%= f.hidden_field :id %> + <%= hidden_field_tag :tr, (dom_id form_survey_question) %> + + <%= f.hidden_field :_destroy, :value => nil, :class => 'should_destroy' %> + <% end %> +
+
+
diff --git a/app/views/panel/survey/back_end/surveys/_form_survey_question_option.html.erb b/app/views/panel/survey/back_end/surveys/_form_survey_question_option.html.erb new file mode 100644 index 0000000..f658da2 --- /dev/null +++ b/app/views/panel/survey/back_end/surveys/_form_survey_question_option.html.erb @@ -0,0 +1,26 @@ +" class='survey_question_option_item'> + +
+ <% @site_in_use_locales.each_with_index do |locale, i| %> +
"> + <%= f.fields_for :name_translations do |f| %> + <%= I18nVariable.from_locale(locale) %> + <%= f.text_field locale, :style=>"width:98%;", :value => (form_survey_question_option.name_translations[locale] rescue nil) %> + <% end %> +
+ <% end %> +
+ + + + <% if form_survey_question_option.new_record? %> + + <% else %> + <%= f.hidden_field :id %> + <%= hidden_field_tag :tr, (dom_id form_survey_question_option) %> + + <%= f.hidden_field :_destroy, :value => nil, :class => 'should_destroy' %> + <% end %> + + + \ No newline at end of file diff --git a/app/views/panel/survey/back_end/surveys/_form_survey_question_radiogroup.html.erb b/app/views/panel/survey/back_end/surveys/_form_survey_question_radiogroup.html.erb new file mode 100644 index 0000000..10a1d04 --- /dev/null +++ b/app/views/panel/survey/back_end/surveys/_form_survey_question_radiogroup.html.erb @@ -0,0 +1,26 @@ +" class='survey_question_radiogroup_item'> + +
+ <% @site_in_use_locales.each_with_index do |locale, i| %> +
"> + <%= f.fields_for :name_translations do |f| %> + <%= I18nVariable.from_locale(locale) %> + <%= f.text_field locale, :style=>"width:98%;", :value => (form_survey_question_radiogroup.name_translations[locale] rescue nil) %> + <% end %> +
+ <% end %> +
+ + + + <% if form_survey_question_radiogroup.new_record? %> + + <% else %> + <%= f.hidden_field :id %> + <%= hidden_field_tag :tr, (dom_id form_survey_question_radiogroup) %> + + <%= f.hidden_field :_destroy, :value => nil, :class => 'should_destroy' %> + <% end %> + + + \ No newline at end of file diff --git a/app/views/panel/survey/back_end/surveys/_questions.html.erb b/app/views/panel/survey/back_end/surveys/_questions.html.erb new file mode 100644 index 0000000..76bd497 --- /dev/null +++ b/app/views/panel/survey/back_end/surveys/_questions.html.erb @@ -0,0 +1,172 @@ + + + + + \ No newline at end of file diff --git a/app/views/panel/survey/back_end/surveys/_sort_headers.html.erb b/app/views/panel/survey/back_end/surveys/_sort_headers.html.erb new file mode 100644 index 0000000..e69de29 diff --git a/app/views/panel/survey/back_end/surveys/_survey.html.erb b/app/views/panel/survey/back_end/surveys/_survey.html.erb new file mode 100644 index 0000000..1383bc0 --- /dev/null +++ b/app/views/panel/survey/back_end/surveys/_survey.html.erb @@ -0,0 +1,34 @@ + + + <% if (survey.create_user_id == current_or_guest_user.id) || is_manager? %> + <%= check_box_tag 'to_delete[]', survey.id, false, :class => "checkbox_in_list" %> + <% end -%> + + + <%= link_to survey.title, panel_survey_front_end_survey_path(survey) %> +
+ +
+ + + <%= (survey.postdate) ? display_date_time(survey.postdate): t(:no_deadline) %> + + + <%= (survey.deadline) ? display_date_time(survey.deadline): t(:no_deadline) %> + + + <%= survey.survey_answers.count %> + + <%= User.from_id(survey.update_user_id).name rescue ''%> + + diff --git a/app/views/panel/survey/back_end/surveys/destroy.js.erb b/app/views/panel/survey/back_end/surveys/destroy.js.erb new file mode 100644 index 0000000..c492e91 --- /dev/null +++ b/app/views/panel/survey/back_end/surveys/destroy.js.erb @@ -0,0 +1 @@ +$("#<%= dom_id @survey %>").remove(); \ No newline at end of file diff --git a/app/views/panel/survey/back_end/surveys/edit.html.erb b/app/views/panel/survey/back_end/surveys/edit.html.erb new file mode 100644 index 0000000..ca497b8 --- /dev/null +++ b/app/views/panel/survey/back_end/surveys/edit.html.erb @@ -0,0 +1,5 @@ + + +<%= form_for @survey, :url => panel_survey_back_end_survey_path(@survey), :html => {:class => 'form-horizontal main-forms'} do |f| %> + <%= render :partial => 'form', :locals => {:f => f} %> +<% end %> diff --git a/app/views/panel/survey/back_end/surveys/index.html.erb b/app/views/panel/survey/back_end/surveys/index.html.erb new file mode 100644 index 0000000..c95e1ff --- /dev/null +++ b/app/views/panel/survey/back_end/surveys/index.html.erb @@ -0,0 +1,23 @@ +<%= render 'filter' %> + + + + + + + + + + + + + + <%= render :partial => 'survey', :collection => @surveys %> + +
<%= t('survey.title') %><%= t('survey.postdate') %><%= t('survey.deadline') %><%= t('survey.results_count') %><%= t('survey.update_user') %>
+ +
+ <%= link_to content_tag(:i, nil, :class => 'icon-plus icon-white') + t(:add), new_panel_survey_back_end_survey_path, :class => 'btn btn-primary pull-right' if (is_manager? rescue nil) %> +
+
+
\ No newline at end of file diff --git a/app/views/panel/survey/back_end/surveys/index.js.erb b/app/views/panel/survey/back_end/surveys/index.js.erb new file mode 100644 index 0000000..548f381 --- /dev/null +++ b/app/views/panel/survey/back_end/surveys/index.js.erb @@ -0,0 +1,4 @@ +$("#delete_all").attr("action", "<%= delete_panel_survey_back_end_surveys_path(:direction => params[:direction], :sort => params[:sort], :filter => @filter, :new_filter => nil, :sort_options => params[:sort_options]) %>"); +$("#sort_headers").html("<%= j render 'sort_headers' %>"); +$("#tbody_surveys").html("<%= j render :partial => 'survey', :collection => @surveys %>"); +$("#survey_pagination").html("<%= j paginate @surveys %>"); \ No newline at end of file diff --git a/app/views/panel/survey/back_end/surveys/jump.html.erb b/app/views/panel/survey/back_end/surveys/jump.html.erb new file mode 100644 index 0000000..a56c4c1 --- /dev/null +++ b/app/views/panel/survey/back_end/surveys/jump.html.erb @@ -0,0 +1,56 @@ +

<%= @survey.title %> <%= t('survey.jump') %>

+ +<%= form_for @survey, :url => panel_survey_back_end_survey_path(@survey), :html => {:class => 'clear'} do |f| %> +
+
+
+ <%= f.label :jump_mode, t('survey.jump_mode')%> + <%= f.check_box :jump_mode %> +
+ + <% @questions.each_with_index do |question, i| %> + + <%= f.fields_for :survey_questions, question do |f| %> + +
" class="survey_question_item clear"> +
+

<%= question.title %>

+
+ <% if question.jumpable? %> + <% if question.can_set_jump? %> +
    + <% question.survey_question_options.each_with_index do |option, i| %> + + <%= f.fields_for :survey_question_options, option do |f| %> + +
  1. + <%= f.label :survey_question_options, option.name %> + <%= f.select :jump_to, @jump_to_options %> +
  2. + + <% end %> + + <% end %> +
+ <% else %> + <%= t('survey.right_type_cant_jump') %> + <% end %> + <% else %> + <%= t('survey.wrong_type_cant_jump') %> + <% end %> +
+
+
+ + <% end %> + + <% end %> + +
+ <%= hidden_field_tag 'page', params[:page] if !params[:page].blank? %> + <%= f.submit t('submit'), :class=>'btn btn-primary' %> + <%= link_to t('cancel'), get_go_back, :class=>"btn" %> +
+
+
+<% end %> \ No newline at end of file diff --git a/app/views/panel/survey/back_end/surveys/new.html.erb b/app/views/panel/survey/back_end/surveys/new.html.erb new file mode 100644 index 0000000..5bf625d --- /dev/null +++ b/app/views/panel/survey/back_end/surveys/new.html.erb @@ -0,0 +1,6 @@ +<%= flash_messages %> +
+<%= form_for @survey, :url => panel_survey_back_end_surveys_path, :html => {:class => 'form-horizontal main-forms'} do |f| %> + <%= render :partial => 'form', :locals => {:f => f} %> +<% end %> +
\ No newline at end of file diff --git a/app/views/panel/survey/back_end/surveys/set_answers.html.erb b/app/views/panel/survey/back_end/surveys/set_answers.html.erb new file mode 100644 index 0000000..99c45fd --- /dev/null +++ b/app/views/panel/survey/back_end/surveys/set_answers.html.erb @@ -0,0 +1,34 @@ +

<%= @survey.title %> <%= t('survey.set_answers') %>

+ +<%= form_for @survey, :url => panel_survey_back_end_survey_path(@survey), :html => {:class => 'clear'} do |f| %> +
+
+
+ <%= f.label :result_type, t('survey.result_type')%> + <%= f.select :result_type, { + t('survey.chart') => Survey::ResultChart, + t('survey.extern_link') => Survey::ResultExtern, + t('survey.upload_file') => Survey::ResultFile + }, {}, :class => "tinput-medium" %> +
+ +
+ <%= f.label :upload_file, t('survey.upload_file') %> + <%= f.file_field :upload_file %> + <% if @survey.upload_file? %> + <%= link_to t(:view), @survey.upload_file.url, {:class => 'for_preview btn', :target => '_blank', :title => t(:view), "data-trigger" => :hover} %> + <%= f.label :remove_upload_file, t('survey.remove_upload_file')%> + <%= f.check_box :remove_upload_file %> + <% end %> +
+
+ <%= hidden_field_tag 'page', params[:page] if !params[:page].blank? %> + <%= f.submit t('submit'), :class=>'btn btn-primary' %> + <%= link_to t('cancel'), get_go_back, :class=>"btn" %> +
+
+
+<% end %> \ No newline at end of file diff --git a/app/views/panel/survey/back_end/surveys_answers/_answer.html.erb b/app/views/panel/survey/back_end/surveys_answers/_answer.html.erb new file mode 100644 index 0000000..94a5e94 --- /dev/null +++ b/app/views/panel/survey/back_end/surveys_answers/_answer.html.erb @@ -0,0 +1,22 @@ + + + <%= check_box_tag 'to_delete[]', answer.id, false, :class => "checkbox_in_list" %> + + <% @survey.survey_questions.each do |question| %> + + <% qid = question.id %> + <% case question.type %> + <% when ::SurveyQuestion::Check %> + <%= ( answer[qid] || [] ).join(', ') %> + <% when ::SurveyQuestion::Radiogroup %> + <% options = Hash[question.survey_question_options.collect{|o| [ o.id.to_s, o.name ] }] %> + <%= ( answer[qid] || {} ).map{|key, value| ( options[key] || key ) + ': ' + value}.join('; ') unless answer[qid].blank? %> + <% else %> + <%= answer[qid] %> + <% end %> + + <% end %> + + <%= answer.created_at %> + + \ No newline at end of file diff --git a/app/views/panel/survey/back_end/surveys_answers/_filter.html.erb b/app/views/panel/survey/back_end/surveys_answers/_filter.html.erb new file mode 100644 index 0000000..0042d5c --- /dev/null +++ b/app/views/panel/survey/back_end/surveys_answers/_filter.html.erb @@ -0,0 +1,11 @@ + + +<% content_for :page_specific_javascript do %> + <%= javascript_include_tag "sort_header" %> +<% end %> \ No newline at end of file diff --git a/app/views/panel/survey/back_end/surveys_answers/_sort_headers.html.erb b/app/views/panel/survey/back_end/surveys_answers/_sort_headers.html.erb new file mode 100644 index 0000000..b4cb147 --- /dev/null +++ b/app/views/panel/survey/back_end/surveys_answers/_sort_headers.html.erb @@ -0,0 +1,7 @@ +<% _sort_args = [] %> +<% @survey.survey_questions.each do |question| %> + <% _sort_args.push [question.id.to_s, question.id.to_s, 'span1', question.title] %> +<% end %> +<% _sort_args.push ['created_at', 'created_at','span1', 'created_at'] %> +<%= render_sort_bar(true, delete_panel_survey_back_end_survey_answers_path(@survey, :direction => params[:direction], :sort => params[:sort], :sort_options => params[:sort_options]), + *_sort_args).html_safe %> \ No newline at end of file diff --git a/app/views/panel/survey/back_end/surveys_answers/index.html.erb b/app/views/panel/survey/back_end/surveys_answers/index.html.erb new file mode 100644 index 0000000..c30d7f6 --- /dev/null +++ b/app/views/panel/survey/back_end/surveys_answers/index.html.erb @@ -0,0 +1,23 @@ +<%= render 'filter' %> + + + + + + <% @survey.survey_questions.each do |question| %> + + <% end %> + + + + + <%= render :partial => 'answer', :collection => @answers %> + +
+ +
+ <%= link_to t(:back) + t('survey.survey'), panel_survey_back_end_surveys_path, :class => 'btn btn-primary pull-right' %> +
+ <%= paginate @answers %> +
+
\ No newline at end of file diff --git a/app/views/panel/survey/back_end/surveys_answers/index.js.erb b/app/views/panel/survey/back_end/surveys_answers/index.js.erb new file mode 100644 index 0000000..c199c63 --- /dev/null +++ b/app/views/panel/survey/back_end/surveys_answers/index.js.erb @@ -0,0 +1,4 @@ +$("#delete_all").attr("action", "<%= delete_panel_survey_back_end_survey_answers_path(@survey, :direction => params[:direction], :sort => params[:sort], :filter => @filter, :new_filter => nil, :sort_options => params[:sort_options]) %>"); +$("#sort_headers").html("<%= j render 'sort_headers' %>"); +$("#tbody_survey_answers").html("<%= j render :partial => 'answer', :collection => @answers %>"); +$("#survey_answers_pagination").html("<%= j paginate @answers %>"); \ No newline at end of file diff --git a/app/views/panel/survey/front_end/surveys/_answer_error.erb b/app/views/panel/survey/front_end/surveys/_answer_error.erb new file mode 100644 index 0000000..faa6598 --- /dev/null +++ b/app/views/panel/survey/front_end/surveys/_answer_error.erb @@ -0,0 +1 @@ +alert("<%= @survey_answer_error %>"); \ No newline at end of file diff --git a/app/views/panel/survey/front_end/surveys/_answer_success.erb b/app/views/panel/survey/front_end/surveys/_answer_success.erb new file mode 100644 index 0000000..3681d86 --- /dev/null +++ b/app/views/panel/survey/front_end/surveys/_answer_success.erb @@ -0,0 +1,2 @@ +alert("<%= t('survey.answer_success')%>"); +window.location.href = "<%= root_path %>"; \ No newline at end of file diff --git a/app/views/panel/survey/front_end/surveys/answer_error.html.erb b/app/views/panel/survey/front_end/surveys/answer_error.html.erb new file mode 100644 index 0000000..0e5cff4 --- /dev/null +++ b/app/views/panel/survey/front_end/surveys/answer_error.html.erb @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/app/views/panel/survey/front_end/surveys/answer_error.js.erb b/app/views/panel/survey/front_end/surveys/answer_error.js.erb new file mode 100644 index 0000000..d03295a --- /dev/null +++ b/app/views/panel/survey/front_end/surveys/answer_error.js.erb @@ -0,0 +1 @@ +<%= render 'answer_error' %> \ No newline at end of file diff --git a/app/views/panel/survey/front_end/surveys/answer_success.html.erb b/app/views/panel/survey/front_end/surveys/answer_success.html.erb new file mode 100644 index 0000000..d5e77ab --- /dev/null +++ b/app/views/panel/survey/front_end/surveys/answer_success.html.erb @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/app/views/panel/survey/front_end/surveys/answer_success.js.erb b/app/views/panel/survey/front_end/surveys/answer_success.js.erb new file mode 100644 index 0000000..c1c8ac1 --- /dev/null +++ b/app/views/panel/survey/front_end/surveys/answer_success.js.erb @@ -0,0 +1 @@ +<%= render 'answer_success' %> \ No newline at end of file diff --git a/app/views/panel/survey/front_end/surveys/redirect_standalone.html.erb b/app/views/panel/survey/front_end/surveys/redirect_standalone.html.erb new file mode 100644 index 0000000..de9b2f4 --- /dev/null +++ b/app/views/panel/survey/front_end/surveys/redirect_standalone.html.erb @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/app/views/panel/survey/front_end/surveys/result.html.erb b/app/views/panel/survey/front_end/surveys/result.html.erb new file mode 100644 index 0000000..2d02eea --- /dev/null +++ b/app/views/panel/survey/front_end/surveys/result.html.erb @@ -0,0 +1,77 @@ +<% case @survey.result_type %> +<% when ::Survey::ResultChart %> + +

<%= @survey.title %> <%= t('survey.chart') %>

+
+
+
+
+ <%= t 'survey.results_count' %>: <%= @survey.survey_answers.count %> +
+
    + <% @survey_questions.each do |question| %> + <% case question.type %> + <% when ::SurveyQuestion::Radio, ::SurveyQuestion::Check, ::SurveyQuestion::Select %> +
  1. +
    +
  2. + <% when ::SurveyQuestion::Radiogroup %> + <% question.survey_question_options.each do |option| %> +
  3. +
    +
  4. + <% end %> + <% end %> + + <% end %> +
+
+
+
+ + + +<% when ::Survey::ResultExtern %> + +<% when ::Survey::ResultFile %> +

<%= @survey.title %> <%= t('survey.upload_file') %>

+
+ <%= link_to t(:view), @survey.upload_file.url, {:class => 'for_preview btn', :target => '_blank', :title => t(:view), "data-trigger" => :hover} %> +
+<% end %> \ No newline at end of file diff --git a/app/views/panel/survey/front_end/surveys/show.html.erb b/app/views/panel/survey/front_end/surveys/show.html.erb new file mode 100644 index 0000000..3e9df01 --- /dev/null +++ b/app/views/panel/survey/front_end/surveys/show.html.erb @@ -0,0 +1,167 @@ +<% # encoding: utf-8 %> +
+ <%= form_for :answer, :method => :put, :url => panel_survey_front_end_survey_path(@survey, :standalone => true), :html => {:class => 'survey clear'} do |f| %> +

<%= @survey.title %>

+
+ <%= @survey.description %> +
+
    + <% @questions.each_with_index do |question, i| %> +
  1. + <% label = question.title %> + <% if question.is_required %> + (*) + <% end %> + <%= f.label question.id, label, :class => "o-question-title" %> +
    + <%= question.description %> +
    + <% case question.type %> + <% when ::SurveyQuestion::Oneline %> + <%= f.text_field question.id, :required => question.is_required %> + <% when ::SurveyQuestion::Multiline %> + <%= f.text_area question.id, :rows => 5, :required => question.is_required %> + <% when ::SurveyQuestion::Radio %> +
      + <% question.survey_question_options.each do |option| %> +
    • + <%= f.radio_button question.id, option.id %> + <%= f.label "#{question.id}_#{option.id}", option.name, :class => 'o-question-option' %> +
    • + <% end %> + <% if question.custom_option %> +
    • + <%= f.radio_button question.id, 'custom_option' %> + <%= f.label "#{question.id}_custom_option", t('survey_question.use_custom_option') + ': ', :class => 'o-question-option' %> + <%= f.text_field "#{question.id}_custom_option" %> +
    • + <% end %> +
    + <% when ::SurveyQuestion::Check %> +
      + <%= f.fields_for "#{question.id}" do |cf| %> + <% question.survey_question_options.each do |option| %> +
    • + <%= cf.check_box option.id %> + <%= cf.label option.id, option.name, :class => 'o-question-option' %> +
    • + <% end %> + <% if question.custom_option %> +
    • + <%= cf.check_box 'custom_option' %> + <%= f.label "#{question.id}_custom_option", t('survey_question.use_custom_option') + ': ', :class => 'o-question-option' %> + <%= f.text_field "#{question.id}_custom_option" %> +
    • + <% end %> + <% end %> +
    + <% when ::SurveyQuestion::Select %> + <% options = question.survey_question_options.collect {|o| [ o.name, o.id ] } %> + <% if question.custom_option %> + <% options.push [t('survey_question.use_custom_option'), 'custom_option'] %> + <% end %> + <%= f.select question.id, options, {}, :class => 'o-question-group view-dropdown' %> + <% if question.custom_option %> + <%= f.text_field "#{question.id}_custom_option", :class => 'custom_option' %> + <% end %> + <% when ::SurveyQuestion::Radiogroup %> + <%= f.fields_for "#{question.id}" do |rgf| %> + + + + + <% question.survey_question_radiogroups.each do |radiogroup| %> + + <% end %> + + + + <% question.survey_question_options.each_with_index do |option, j| %> + > + + <% question.survey_question_radiogroups.each do |radiogroup| %> + + <% end %> + + <% end %> + +
    + <%= radiogroup.name %> +
    + <%= option.name %> + + <%= rgf.radio_button option.id, radiogroup.id %> +
    + <% end %> + <% end %> +
  2. + <% end %> +
+
+ <%= f.submit t('submit'), :class => 'survey-submit' %> +
+ <% end %> +
+<% content_for :page_stylesheets do %> + +<% end %> + + \ No newline at end of file diff --git a/config/locales/en.yml b/config/locales/en.yml new file mode 100644 index 0000000..94e49ec --- /dev/null +++ b/config/locales/en.yml @@ -0,0 +1,83 @@ +en: + + survey: + survey: Survey + title: Title + description: Description + postdate: Start Date + deadline: End Date + no_postdate: No Start Date + no_deadline: No End Date + results_count: Results Count + update_user: Update User + question: Question + is_external: The survey is an external link + add: Add Question + + result_type: Result Type (Frontend) + extern_link: External Link + upload_file: Uploaded File + + remove_upload_file: Remove Uploaded File + + answer_success: Successfully answered,jump back now + answer_error: Unsuccessful answer + + answers_list: Answers List + export_csv: Export CSV + chart: Chart + set_answers: Set Answers + duplicate_it: Duplicate It + + view_result: View Result + + jump: Jump-To + jump_mode: Jump-To Mode + wrong_type_cant_jump: Only radio or select can set jump-to + right_type_cant_jump: Custom option allowed can't set jump-to + not_jump: Not Jump + jump_to_end: End of Survey + + redirect: Redirect + redirect_mode: Redirect Mode + redirect_url: Redirect Url + + must_answer: Must be Answered + + default_widget: + title: Title + time_range: Date Range + result: Result + + frontend: + survey: Survey Frontend + + survey_question: + title: Question + description: Description + sequence: Sequence + type: Type + is_required: Is Required + required: Required + required_error: Can't not be empty + oneline: Oneline + multiline: Multi-line + radio: Radio + check: Check + select: Select + radiogroup: Radio Group + options_lists: Options List + radiogroup_label: Radio Group Label + radiogroups_lists: Radio Groups List + option: Option + custom_option: Allow Custom Option + use_custom_option: Other + add: Add + delete: Delete + + have_not_chart: This type of question havn't chart + + move_up: Move up + move_down: Move down + + diff --git a/config/locales/zh_tw.yml b/config/locales/zh_tw.yml new file mode 100644 index 0000000..337012d --- /dev/null +++ b/config/locales/zh_tw.yml @@ -0,0 +1,83 @@ +zh_tw: + + survey: + survey: 問卷調查 + title: 問卷標題 + description: 問卷說明 + postdate: 開始時間 + deadline: 結束時間 + start_deadline: 開始/結束時間 + no_postdate: 沒有開始時間 + no_deadline: 沒有結束時間 + results_count: 填寫人數 + update_user: 最後更新者 + question: 問題 + is_external: 這份問卷為外部連結 + add: 新增題目 + + result_type: 前端結果表示方式 + extern_link: 外部連結 + upload_file: 結果文件 + + remove_upload_file: 移除存在的結果文件 + + answer_success: 問卷填寫成功,現在跳回 + answer_error: 問卷填寫錯誤 + + answers_list: 結果清單 + export_csv: 匯出CSV + chart: 結果圖表 + set_answers: 設定結果 + duplicate_it: 複製問卷 + + view_result: 查看結果 + + jump: 跳題 + jump_mode: 設爲跳題方式回答 + wrong_type_cant_jump: 不是單選或下拉無法使用跳題 + right_type_cant_jump: 允許自定回答的問題無法使用跳題 + not_jump: 依據試卷列出所有問題數 + jump_to_end: 結束問題 + + redirect: 問卷跳轉 + redirect_mode: 設爲跳轉模式 + redirect_url: 跳轉地址 + + must_answer: 必須回答這個問題 + + default_widget: + title: 問卷標題 + time_range: 問卷期間 + write: 填問卷 + result: 結果 + + frontend: + survey: 問卷調查前台 + + survey_question: + title: 題目 + description: 說明 + sequence: 順序 + type: 作答方式 + is_required: 設為必填 + required: 必填 + required_error: 沒有回答 + oneline: 單行文字 + multiline: 多行文字 + radio: 單選按鈕 + check: 多選方塊 + select: 下拉選單 + radiogroup: 格狀呈現 + options_lists: 選項清單 + radiogroup_label: 橫欄 + radiogroups_lists: 橫欄清單 + option: 選項 + custom_option: 允許自定回答選項 + use_custom_option: 其他 + add: 新增 + delete: 刪除 + + have_not_chart: 此種類型問題不含結果圖表 + + move_up: 上移 + move_down: 下移 \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb new file mode 100644 index 0000000..c33b363 --- /dev/null +++ b/config/routes.rb @@ -0,0 +1,33 @@ +Rails.application.routes.draw do + + namespace :panel do + namespace :survey do + namespace :back_end do + resources :surveys do + collection do + get 'delete' + end + member do + get 'export' + get 'set_answers' + get 'jump' + get 'duplicate_it' + end + resources :answers, :controller => :surveys_answers do + collection do + get 'delete' + end + end + end + end + namespace :front_end do + resources :surveys do + member do + get 'result' + end + end + end + end + end + match "/appfront/*path" => redirect("/panel/*path") +end \ No newline at end of file diff --git a/lib/survey.rb b/lib/survey.rb new file mode 100644 index 0000000..c7ac8ad --- /dev/null +++ b/lib/survey.rb @@ -0,0 +1,58 @@ +class Engine < Rails::Engine + initializer "survey" do + OrbitApp.registration "Survey",:type=> 'ModuleApp' do + module_label 'survey.survey' + base_url File.expand_path File.dirname(__FILE__) + # personal_plugin :enable => true,:path=>"panel/faq/plugin/profile",:i18n=>'admin.faq' + + version "0.1" + organization "Rulingcom" + author "RD dep" + intro "I am intro" + update_info 'some update_info' + + front_end do + # app_page 'survey' do + # frontend_i18n "survey.frontend.survey" + # end + end + + authorizable + + data_count 1..20 + + widgets do + default_widget do + enable ["typeA"] + query 'Survey.any_of( {:postdate.lte => Time.now} )' + link_field :title, {:method => 'panel_survey_front_end_survey_path',:args=>:self} + field :time_range + field :write + field :result + link_to_more 'panel_survey_front_end_survey_path', :title_i18n=> 'faq.default_widget.to_more' + end + end + + + side_bar do + head_label_i18n 'survey.survey',:icon_class=>"icons-pie" + available_for [:admin,:manager,:sub_manager] + active_for_controllers ({:private=>['surveys', 'surveys_answers']}) + + head_link_path "panel_survey_back_end_surveys_path" + + context_link 'list_', + :link_path=>"panel_survey_back_end_surveys_path" , + :priority=>1, + :active_for_action=>{:surveys=>:index}, + :available_for => [:all] + + context_link 'add', + :link_path=>"new_panel_survey_back_end_survey_path" , + :priority=>2, + :active_for_action=>{:surveys=>:new}, + :available_for => [:sub_manager] + end + end + end +end diff --git a/lib/tasks/survey_tasks.rake b/lib/tasks/survey_tasks.rake new file mode 100644 index 0000000..7fcf4ea --- /dev/null +++ b/lib/tasks/survey_tasks.rake @@ -0,0 +1,4 @@ +# desc "Explaining what the task does" +# task :survey do +# # Task goes here +# end diff --git a/survey.gemspec b/survey.gemspec new file mode 100644 index 0000000..0872579 --- /dev/null +++ b/survey.gemspec @@ -0,0 +1,19 @@ +$:.push File.expand_path("../lib", __FILE__) + +# Describe your gem and declare its dependencies: +Gem::Specification.new do |s| + s.name = "survey" + s.version = "0.0.1" + s.authors = ["RulingDigital"] + s.email = ["service@rulingcom.com"] + s.homepage = "http://www.rulingcom.com" + s.summary = "Orbit Survey Module" + s.description = "Orbit Survey Module" + + s.files = Dir["{app,config,db,lib}/**/*"] + ["MIT-LICENSE", "Rakefile", "README.rdoc"] + s.test_files = Dir["test/**/*"] + + s.add_dependency "rails", "~> 3.2.12" + + s.add_development_dependency "sqlite3" +end diff --git a/survey.json b/survey.json new file mode 100644 index 0000000..92faea8 --- /dev/null +++ b/survey.json @@ -0,0 +1,12 @@ +{ + "title": "survey", + "version": "0.1", + "organization": "Rulingcom", + "author": "RD dep", + "intro": "survey", + "update_info": "Some info", + "create_date": "04-18-2013", + "widgets": ["index"], + "category": [], + "enable_frontend": true +} diff --git a/test/dummy/README.rdoc b/test/dummy/README.rdoc new file mode 100644 index 0000000..7c36f23 --- /dev/null +++ b/test/dummy/README.rdoc @@ -0,0 +1,261 @@ +== Welcome to Rails + +Rails is a web-application framework that includes everything needed to create +database-backed web applications according to the Model-View-Control pattern. + +This pattern splits the view (also called the presentation) into "dumb" +templates that are primarily responsible for inserting pre-built data in between +HTML tags. The model contains the "smart" domain objects (such as Account, +Product, Person, Post) that holds all the business logic and knows how to +persist themselves to a database. The controller handles the incoming requests +(such as Save New Account, Update Product, Show Post) by manipulating the model +and directing data to the view. + +In Rails, the model is handled by what's called an object-relational mapping +layer entitled Active Record. This layer allows you to present the data from +database rows as objects and embellish these data objects with business logic +methods. You can read more about Active Record in +link:files/vendor/rails/activerecord/README.html. + +The controller and view are handled by the Action Pack, which handles both +layers by its two parts: Action View and Action Controller. These two layers +are bundled in a single package due to their heavy interdependence. This is +unlike the relationship between the Active Record and Action Pack that is much +more separate. Each of these packages can be used independently outside of +Rails. You can read more about Action Pack in +link:files/vendor/rails/actionpack/README.html. + + +== Getting Started + +1. At the command prompt, create a new Rails application: + rails new myapp (where myapp is the application name) + +2. Change directory to myapp and start the web server: + cd myapp; rails server (run with --help for options) + +3. Go to http://localhost:3000/ and you'll see: + "Welcome aboard: You're riding Ruby on Rails!" + +4. Follow the guidelines to start developing your application. You can find +the following resources handy: + +* The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html +* Ruby on Rails Tutorial Book: http://www.railstutorial.org/ + + +== Debugging Rails + +Sometimes your application goes wrong. Fortunately there are a lot of tools that +will help you debug it and get it back on the rails. + +First area to check is the application log files. Have "tail -f" commands +running on the server.log and development.log. Rails will automatically display +debugging and runtime information to these files. Debugging info will also be +shown in the browser on requests from 127.0.0.1. + +You can also log your own messages directly into the log file from your code +using the Ruby logger class from inside your controllers. Example: + + class WeblogController < ActionController::Base + def destroy + @weblog = Weblog.find(params[:id]) + @weblog.destroy + logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!") + end + end + +The result will be a message in your log file along the lines of: + + Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1! + +More information on how to use the logger is at http://www.ruby-doc.org/core/ + +Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are +several books available online as well: + +* Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe) +* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide) + +These two books will bring you up to speed on the Ruby language and also on +programming in general. + + +== Debugger + +Debugger support is available through the debugger command when you start your +Mongrel or WEBrick server with --debugger. This means that you can break out of +execution at any point in the code, investigate and change the model, and then, +resume execution! You need to install ruby-debug to run the server in debugging +mode. With gems, use sudo gem install ruby-debug. Example: + + class WeblogController < ActionController::Base + def index + @posts = Post.all + debugger + end + end + +So the controller will accept the action, run the first line, then present you +with a IRB prompt in the server window. Here you can do things like: + + >> @posts.inspect + => "[#nil, "body"=>nil, "id"=>"1"}>, + #"Rails", "body"=>"Only ten..", "id"=>"2"}>]" + >> @posts.first.title = "hello from a debugger" + => "hello from a debugger" + +...and even better, you can examine how your runtime objects actually work: + + >> f = @posts.first + => #nil, "body"=>nil, "id"=>"1"}> + >> f. + Display all 152 possibilities? (y or n) + +Finally, when you're ready to resume execution, you can enter "cont". + + +== Console + +The console is a Ruby shell, which allows you to interact with your +application's domain model. Here you'll have all parts of the application +configured, just like it is when the application is running. You can inspect +domain models, change values, and save to the database. Starting the script +without arguments will launch it in the development environment. + +To start the console, run rails console from the application +directory. + +Options: + +* Passing the -s, --sandbox argument will rollback any modifications + made to the database. +* Passing an environment name as an argument will load the corresponding + environment. Example: rails console production. + +To reload your controllers and models after launching the console run +reload! + +More information about irb can be found at: +link:http://www.rubycentral.org/pickaxe/irb.html + + +== dbconsole + +You can go to the command line of your database directly through rails +dbconsole. You would be connected to the database with the credentials +defined in database.yml. Starting the script without arguments will connect you +to the development database. Passing an argument will connect you to a different +database, like rails dbconsole production. Currently works for MySQL, +PostgreSQL and SQLite 3. + +== Description of Contents + +The default directory structure of a generated Ruby on Rails application: + + |-- app + | |-- assets + | |-- images + | |-- javascripts + | `-- stylesheets + | |-- controllers + | |-- helpers + | |-- mailers + | |-- models + | `-- views + | `-- layouts + |-- config + | |-- environments + | |-- initializers + | `-- locales + |-- db + |-- doc + |-- lib + | `-- tasks + |-- log + |-- public + |-- script + |-- test + | |-- fixtures + | |-- functional + | |-- integration + | |-- performance + | `-- unit + |-- tmp + | |-- cache + | |-- pids + | |-- sessions + | `-- sockets + `-- vendor + |-- assets + `-- stylesheets + `-- plugins + +app + Holds all the code that's specific to this particular application. + +app/assets + Contains subdirectories for images, stylesheets, and JavaScript files. + +app/controllers + Holds controllers that should be named like weblogs_controller.rb for + automated URL mapping. All controllers should descend from + ApplicationController which itself descends from ActionController::Base. + +app/models + Holds models that should be named like post.rb. Models descend from + ActiveRecord::Base by default. + +app/views + Holds the template files for the view that should be named like + weblogs/index.html.erb for the WeblogsController#index action. All views use + eRuby syntax by default. + +app/views/layouts + Holds the template files for layouts to be used with views. This models the + common header/footer method of wrapping views. In your views, define a layout + using the layout :default and create a file named default.html.erb. + Inside default.html.erb, call <% yield %> to render the view using this + layout. + +app/helpers + Holds view helpers that should be named like weblogs_helper.rb. These are + generated for you automatically when using generators for controllers. + Helpers can be used to wrap functionality for your views into methods. + +config + Configuration files for the Rails environment, the routing map, the database, + and other dependencies. + +db + Contains the database schema in schema.rb. db/migrate contains all the + sequence of Migrations for your schema. + +doc + This directory is where your application documentation will be stored when + generated using rake doc:app + +lib + Application specific libraries. Basically, any kind of custom code that + doesn't belong under controllers, models, or helpers. This directory is in + the load path. + +public + The directory available for the web server. Also contains the dispatchers and the + default HTML files. This should be set as the DOCUMENT_ROOT of your web + server. + +script + Helper scripts for automation and generation. + +test + Unit and functional tests along with fixtures. When using the rails generate + command, template test files will be generated for you and placed in this + directory. + +vendor + External libraries that the application depends on. Also includes the plugins + subdirectory. If the app has frozen rails, those gems also go here, under + vendor/rails/. This directory is in the load path. diff --git a/test/dummy/Rakefile b/test/dummy/Rakefile new file mode 100644 index 0000000..3645852 --- /dev/null +++ b/test/dummy/Rakefile @@ -0,0 +1,7 @@ +#!/usr/bin/env rake +# Add your own tasks in files placed in lib/tasks ending in .rake, +# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. + +require File.expand_path('../config/application', __FILE__) + +Dummy::Application.load_tasks diff --git a/test/dummy/app/assets/javascripts/application.js b/test/dummy/app/assets/javascripts/application.js new file mode 100644 index 0000000..9097d83 --- /dev/null +++ b/test/dummy/app/assets/javascripts/application.js @@ -0,0 +1,15 @@ +// This is a manifest file that'll be compiled into application.js, which will include all the files +// listed below. +// +// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, +// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path. +// +// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +// the compiled file. +// +// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD +// GO AFTER THE REQUIRES BELOW. +// +//= require jquery +//= require jquery_ujs +//= require_tree . diff --git a/test/dummy/app/assets/stylesheets/application.css b/test/dummy/app/assets/stylesheets/application.css new file mode 100644 index 0000000..3192ec8 --- /dev/null +++ b/test/dummy/app/assets/stylesheets/application.css @@ -0,0 +1,13 @@ +/* + * This is a manifest file that'll be compiled into application.css, which will include all the files + * listed below. + * + * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, + * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. + * + * You're free to add application-wide styles to this file and they'll appear at the top of the + * compiled file, but it's generally better to create a new file per style scope. + * + *= require_self + *= require_tree . + */ diff --git a/test/dummy/app/controllers/application_controller.rb b/test/dummy/app/controllers/application_controller.rb new file mode 100644 index 0000000..e8065d9 --- /dev/null +++ b/test/dummy/app/controllers/application_controller.rb @@ -0,0 +1,3 @@ +class ApplicationController < ActionController::Base + protect_from_forgery +end diff --git a/test/dummy/app/helpers/application_helper.rb b/test/dummy/app/helpers/application_helper.rb new file mode 100644 index 0000000..de6be79 --- /dev/null +++ b/test/dummy/app/helpers/application_helper.rb @@ -0,0 +1,2 @@ +module ApplicationHelper +end diff --git a/test/dummy/app/mailers/.gitkeep b/test/dummy/app/mailers/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/test/dummy/app/models/.gitkeep b/test/dummy/app/models/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/test/dummy/app/views/layouts/application.html.erb b/test/dummy/app/views/layouts/application.html.erb new file mode 100644 index 0000000..4cab268 --- /dev/null +++ b/test/dummy/app/views/layouts/application.html.erb @@ -0,0 +1,14 @@ + + + + Dummy + <%= stylesheet_link_tag "application", :media => "all" %> + <%= javascript_include_tag "application" %> + <%= csrf_meta_tags %> + + + +<%= yield %> + + + diff --git a/test/dummy/config.ru b/test/dummy/config.ru new file mode 100644 index 0000000..1989ed8 --- /dev/null +++ b/test/dummy/config.ru @@ -0,0 +1,4 @@ +# This file is used by Rack-based servers to start the application. + +require ::File.expand_path('../config/environment', __FILE__) +run Dummy::Application diff --git a/test/dummy/config/application.rb b/test/dummy/config/application.rb new file mode 100644 index 0000000..35ed7df --- /dev/null +++ b/test/dummy/config/application.rb @@ -0,0 +1,59 @@ +require File.expand_path('../boot', __FILE__) + +require 'rails/all' + +Bundler.require +require "survey" + +module Dummy + class Application < Rails::Application + # Settings in config/environments/* take precedence over those specified here. + # Application configuration should go into files in config/initializers + # -- all .rb files in that directory are automatically loaded. + + # Custom directories with classes and modules you want to be autoloadable. + # config.autoload_paths += %W(#{config.root}/extras) + + # Only load the plugins named here, in the order given (default is alphabetical). + # :all can be used as a placeholder for all plugins not explicitly named. + # config.plugins = [ :exception_notification, :ssl_requirement, :all ] + + # Activate observers that should always be running. + # config.active_record.observers = :cacher, :garbage_collector, :forum_observer + + # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. + # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. + # config.time_zone = 'Central Time (US & Canada)' + + # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. + # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] + # config.i18n.default_locale = :de + + # Configure the default encoding used in templates for Ruby 1.9. + config.encoding = "utf-8" + + # Configure sensitive parameters which will be filtered from the log file. + config.filter_parameters += [:password] + + # Enable escaping HTML in JSON. + config.active_support.escape_html_entities_in_json = true + + # Use SQL instead of Active Record's schema dumper when creating the database. + # This is necessary if your schema can't be completely dumped by the schema dumper, + # like if you have constraints or database-specific column types + # config.active_record.schema_format = :sql + + # Enforce whitelist mode for mass assignment. + # This will create an empty whitelist of attributes available for mass-assignment for all models + # in your app. As such, your models will need to explicitly whitelist or blacklist accessible + # parameters by using an attr_accessible or attr_protected declaration. + config.active_record.whitelist_attributes = true + + # Enable the asset pipeline + config.assets.enabled = true + + # Version of your assets, change this if you want to expire all your assets + config.assets.version = '1.0' + end +end + diff --git a/test/dummy/config/boot.rb b/test/dummy/config/boot.rb new file mode 100644 index 0000000..eba0681 --- /dev/null +++ b/test/dummy/config/boot.rb @@ -0,0 +1,10 @@ +require 'rubygems' +gemfile = File.expand_path('../../../../Gemfile', __FILE__) + +if File.exist?(gemfile) + ENV['BUNDLE_GEMFILE'] = gemfile + require 'bundler' + Bundler.setup +end + +$:.unshift File.expand_path('../../../../lib', __FILE__) \ No newline at end of file diff --git a/test/dummy/config/database.yml b/test/dummy/config/database.yml new file mode 100644 index 0000000..51a4dd4 --- /dev/null +++ b/test/dummy/config/database.yml @@ -0,0 +1,25 @@ +# SQLite version 3.x +# gem install sqlite3 +# +# Ensure the SQLite 3 gem is defined in your Gemfile +# gem 'sqlite3' +development: + adapter: sqlite3 + database: db/development.sqlite3 + pool: 5 + timeout: 5000 + +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". +# Do not set this db to the same as development or production. +test: + adapter: sqlite3 + database: db/test.sqlite3 + pool: 5 + timeout: 5000 + +production: + adapter: sqlite3 + database: db/production.sqlite3 + pool: 5 + timeout: 5000 diff --git a/test/dummy/config/environment.rb b/test/dummy/config/environment.rb new file mode 100644 index 0000000..3da5eb9 --- /dev/null +++ b/test/dummy/config/environment.rb @@ -0,0 +1,5 @@ +# Load the rails application +require File.expand_path('../application', __FILE__) + +# Initialize the rails application +Dummy::Application.initialize! diff --git a/test/dummy/config/environments/development.rb b/test/dummy/config/environments/development.rb new file mode 100644 index 0000000..82c74d1 --- /dev/null +++ b/test/dummy/config/environments/development.rb @@ -0,0 +1,37 @@ +Dummy::Application.configure do + # Settings specified here will take precedence over those in config/application.rb + + # In the development environment your application's code is reloaded on + # every request. This slows down response time but is perfect for development + # since you don't have to restart the web server when you make code changes. + config.cache_classes = false + + # Log error messages when you accidentally call methods on nil. + config.whiny_nils = true + + # Show full error reports and disable caching + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Don't care if the mailer can't send + config.action_mailer.raise_delivery_errors = false + + # Print deprecation notices to the Rails logger + config.active_support.deprecation = :log + + # Only use best-standards-support built into browsers + config.action_dispatch.best_standards_support = :builtin + + # Raise exception on mass assignment protection for Active Record models + config.active_record.mass_assignment_sanitizer = :strict + + # Log the query plan for queries taking more than this (works + # with SQLite, MySQL, and PostgreSQL) + config.active_record.auto_explain_threshold_in_seconds = 0.5 + + # Do not compress assets + config.assets.compress = false + + # Expands the lines which load the assets + config.assets.debug = true +end diff --git a/test/dummy/config/environments/production.rb b/test/dummy/config/environments/production.rb new file mode 100644 index 0000000..bdac56a --- /dev/null +++ b/test/dummy/config/environments/production.rb @@ -0,0 +1,67 @@ +Dummy::Application.configure do + # Settings specified here will take precedence over those in config/application.rb + + # Code is not reloaded between requests + config.cache_classes = true + + # Full error reports are disabled and caching is turned on + config.consider_all_requests_local = false + config.action_controller.perform_caching = true + + # Disable Rails's static asset server (Apache or nginx will already do this) + config.serve_static_assets = false + + # Compress JavaScripts and CSS + config.assets.compress = true + + # Don't fallback to assets pipeline if a precompiled asset is missed + config.assets.compile = false + + # Generate digests for assets URLs + config.assets.digest = true + + # Defaults to nil and saved in location specified by config.assets.prefix + # config.assets.manifest = YOUR_PATH + + # Specifies the header that your server uses for sending files + # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache + # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx + + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + # config.force_ssl = true + + # See everything in the log (default is :info) + # config.log_level = :debug + + # Prepend all log lines with the following tags + # config.log_tags = [ :subdomain, :uuid ] + + # Use a different logger for distributed setups + # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) + + # Use a different cache store in production + # config.cache_store = :mem_cache_store + + # Enable serving of images, stylesheets, and JavaScripts from an asset server + # config.action_controller.asset_host = "http://assets.example.com" + + # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added) + # config.assets.precompile += %w( search.js ) + + # Disable delivery errors, bad email addresses will be ignored + # config.action_mailer.raise_delivery_errors = false + + # Enable threaded mode + # config.threadsafe! + + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation can not be found) + config.i18n.fallbacks = true + + # Send deprecation notices to registered listeners + config.active_support.deprecation = :notify + + # Log the query plan for queries taking more than this (works + # with SQLite, MySQL, and PostgreSQL) + # config.active_record.auto_explain_threshold_in_seconds = 0.5 +end diff --git a/test/dummy/config/environments/test.rb b/test/dummy/config/environments/test.rb new file mode 100644 index 0000000..f1a4814 --- /dev/null +++ b/test/dummy/config/environments/test.rb @@ -0,0 +1,37 @@ +Dummy::Application.configure do + # Settings specified here will take precedence over those in config/application.rb + + # The test environment is used exclusively to run your application's + # test suite. You never need to work with it otherwise. Remember that + # your test database is "scratch space" for the test suite and is wiped + # and recreated between test runs. Don't rely on the data there! + config.cache_classes = true + + # Configure static asset server for tests with Cache-Control for performance + config.serve_static_assets = true + config.static_cache_control = "public, max-age=3600" + + # Log error messages when you accidentally call methods on nil + config.whiny_nils = true + + # Show full error reports and disable caching + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Raise exceptions instead of rendering exception templates + config.action_dispatch.show_exceptions = false + + # Disable request forgery protection in test environment + config.action_controller.allow_forgery_protection = false + + # Tell Action Mailer not to deliver emails to the real world. + # The :test delivery method accumulates sent emails in the + # ActionMailer::Base.deliveries array. + config.action_mailer.delivery_method = :test + + # Raise exception on mass assignment protection for Active Record models + config.active_record.mass_assignment_sanitizer = :strict + + # Print deprecation notices to the stderr + config.active_support.deprecation = :stderr +end diff --git a/test/dummy/config/initializers/backtrace_silencers.rb b/test/dummy/config/initializers/backtrace_silencers.rb new file mode 100644 index 0000000..59385cd --- /dev/null +++ b/test/dummy/config/initializers/backtrace_silencers.rb @@ -0,0 +1,7 @@ +# Be sure to restart your server when you modify this file. + +# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. +# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } + +# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. +# Rails.backtrace_cleaner.remove_silencers! diff --git a/test/dummy/config/initializers/inflections.rb b/test/dummy/config/initializers/inflections.rb new file mode 100644 index 0000000..5d8d9be --- /dev/null +++ b/test/dummy/config/initializers/inflections.rb @@ -0,0 +1,15 @@ +# Be sure to restart your server when you modify this file. + +# Add new inflection rules using the following format +# (all these examples are active by default): +# ActiveSupport::Inflector.inflections do |inflect| +# inflect.plural /^(ox)$/i, '\1en' +# inflect.singular /^(ox)en/i, '\1' +# inflect.irregular 'person', 'people' +# inflect.uncountable %w( fish sheep ) +# end +# +# These inflection rules are supported but not enabled by default: +# ActiveSupport::Inflector.inflections do |inflect| +# inflect.acronym 'RESTful' +# end diff --git a/test/dummy/config/initializers/mime_types.rb b/test/dummy/config/initializers/mime_types.rb new file mode 100644 index 0000000..72aca7e --- /dev/null +++ b/test/dummy/config/initializers/mime_types.rb @@ -0,0 +1,5 @@ +# Be sure to restart your server when you modify this file. + +# Add new mime types for use in respond_to blocks: +# Mime::Type.register "text/richtext", :rtf +# Mime::Type.register_alias "text/html", :iphone diff --git a/test/dummy/config/initializers/secret_token.rb b/test/dummy/config/initializers/secret_token.rb new file mode 100644 index 0000000..891dd39 --- /dev/null +++ b/test/dummy/config/initializers/secret_token.rb @@ -0,0 +1,7 @@ +# Be sure to restart your server when you modify this file. + +# Your secret key for verifying the integrity of signed cookies. +# If you change this key, all old signed cookies will become invalid! +# Make sure the secret is at least 30 characters and all random, +# no regular words or you'll be exposed to dictionary attacks. +Dummy::Application.config.secret_token = 'a44b80336f20b60a74c02239bc72f40d7213684ab512c9e3a2514408ee15b31042decfdd671d4cf118561fa1780e47b0728270c100eb4b7f805d0d4101b3a146' diff --git a/test/dummy/config/initializers/session_store.rb b/test/dummy/config/initializers/session_store.rb new file mode 100644 index 0000000..952473f --- /dev/null +++ b/test/dummy/config/initializers/session_store.rb @@ -0,0 +1,8 @@ +# Be sure to restart your server when you modify this file. + +Dummy::Application.config.session_store :cookie_store, key: '_dummy_session' + +# Use the database for sessions instead of the cookie-based default, +# which shouldn't be used to store highly confidential information +# (create the session table with "rails generate session_migration") +# Dummy::Application.config.session_store :active_record_store diff --git a/test/dummy/config/initializers/wrap_parameters.rb b/test/dummy/config/initializers/wrap_parameters.rb new file mode 100644 index 0000000..999df20 --- /dev/null +++ b/test/dummy/config/initializers/wrap_parameters.rb @@ -0,0 +1,14 @@ +# Be sure to restart your server when you modify this file. +# +# This file contains settings for ActionController::ParamsWrapper which +# is enabled by default. + +# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. +ActiveSupport.on_load(:action_controller) do + wrap_parameters format: [:json] +end + +# Disable root element in JSON by default. +ActiveSupport.on_load(:active_record) do + self.include_root_in_json = false +end diff --git a/test/dummy/config/locales/en.yml b/test/dummy/config/locales/en.yml new file mode 100644 index 0000000..179c14c --- /dev/null +++ b/test/dummy/config/locales/en.yml @@ -0,0 +1,5 @@ +# Sample localization file for English. Add more files in this directory for other locales. +# See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points. + +en: + hello: "Hello world" diff --git a/test/dummy/config/routes.rb b/test/dummy/config/routes.rb new file mode 100644 index 0000000..eb8579b --- /dev/null +++ b/test/dummy/config/routes.rb @@ -0,0 +1,58 @@ +Dummy::Application.routes.draw do + # The priority is based upon order of creation: + # first created -> highest priority. + + # Sample of regular route: + # match 'products/:id' => 'catalog#view' + # Keep in mind you can assign values other than :controller and :action + + # Sample of named route: + # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase + # This route can be invoked with purchase_url(:id => product.id) + + # Sample resource route (maps HTTP verbs to controller actions automatically): + # resources :products + + # Sample resource route with options: + # resources :products do + # member do + # get 'short' + # post 'toggle' + # end + # + # collection do + # get 'sold' + # end + # end + + # Sample resource route with sub-resources: + # resources :products do + # resources :comments, :sales + # resource :seller + # end + + # Sample resource route with more complex sub-resources + # resources :products do + # resources :comments + # resources :sales do + # get 'recent', :on => :collection + # end + # end + + # Sample resource route within a namespace: + # namespace :admin do + # # Directs /admin/products/* to Admin::ProductsController + # # (app/controllers/admin/products_controller.rb) + # resources :products + # end + + # You can have the root of your site routed with "root" + # just remember to delete public/index.html. + # root :to => 'welcome#index' + + # See how all your routes lay out with "rake routes" + + # This is a legacy wild controller route that's not recommended for RESTful applications. + # Note: This route will make all actions in every controller accessible via GET requests. + # match ':controller(/:action(/:id))(.:format)' +end diff --git a/test/dummy/lib/assets/.gitkeep b/test/dummy/lib/assets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/test/dummy/log/.gitkeep b/test/dummy/log/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/test/dummy/public/404.html b/test/dummy/public/404.html new file mode 100644 index 0000000..9a48320 --- /dev/null +++ b/test/dummy/public/404.html @@ -0,0 +1,26 @@ + + + + The page you were looking for doesn't exist (404) + + + + + +
+

The page you were looking for doesn't exist.

+

You may have mistyped the address or the page may have moved.

+
+ + diff --git a/test/dummy/public/422.html b/test/dummy/public/422.html new file mode 100644 index 0000000..83660ab --- /dev/null +++ b/test/dummy/public/422.html @@ -0,0 +1,26 @@ + + + + The change you wanted was rejected (422) + + + + + +
+

The change you wanted was rejected.

+

Maybe you tried to change something you didn't have access to.

+
+ + diff --git a/test/dummy/public/500.html b/test/dummy/public/500.html new file mode 100644 index 0000000..f3648a0 --- /dev/null +++ b/test/dummy/public/500.html @@ -0,0 +1,25 @@ + + + + We're sorry, but something went wrong (500) + + + + + +
+

We're sorry, but something went wrong.

+
+ + diff --git a/test/dummy/public/favicon.ico b/test/dummy/public/favicon.ico new file mode 100644 index 0000000..e69de29 diff --git a/test/dummy/script/rails b/test/dummy/script/rails new file mode 100755 index 0000000..f8da2cf --- /dev/null +++ b/test/dummy/script/rails @@ -0,0 +1,6 @@ +#!/usr/bin/env ruby +# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. + +APP_PATH = File.expand_path('../../config/application', __FILE__) +require File.expand_path('../../config/boot', __FILE__) +require 'rails/commands' diff --git a/test/survey_test.rb b/test/survey_test.rb new file mode 100644 index 0000000..5dc2f86 --- /dev/null +++ b/test/survey_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class SurveyTest < ActiveSupport::TestCase + test "truth" do + assert_kind_of Module, Survey + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb new file mode 100644 index 0000000..1e26a31 --- /dev/null +++ b/test/test_helper.rb @@ -0,0 +1,15 @@ +# Configure Rails Environment +ENV["RAILS_ENV"] = "test" + +require File.expand_path("../dummy/config/environment.rb", __FILE__) +require "rails/test_help" + +Rails.backtrace_cleaner.remove_silencers! + +# Load support files +Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f } + +# Load fixtures from the engine +if ActiveSupport::TestCase.method_defined?(:fixture_path=) + ActiveSupport::TestCase.fixture_path = File.expand_path("../fixtures", __FILE__) +end