├── .gitignore ├── Gemfile ├── MIT-LICENSE ├── README.md ├── Rakefile ├── app ├── assets │ ├── images │ │ └── fullcalendar_engine │ │ │ └── .keep │ ├── javascripts │ │ └── fullcalendar_engine │ │ │ ├── application.js │ │ │ ├── events.js.erb │ │ │ ├── fullcalendar.js │ │ │ ├── gcal.js │ │ │ └── jquery-ui-1.10.3.custom.min.js │ └── stylesheets │ │ └── fullcalendar_engine │ │ ├── application.css │ │ ├── fullcalendar.css │ │ ├── images │ │ ├── animated-overlay.gif │ │ ├── ui-bg_diagonals-thick_18_b81900_40x40.png │ │ ├── ui-bg_diagonals-thick_20_666666_40x40.png │ │ ├── ui-bg_flat_10_000000_40x100.png │ │ ├── ui-bg_glass_100_f6f6f6_1x400.png │ │ ├── ui-bg_glass_100_fdf5ce_1x400.png │ │ ├── ui-bg_glass_65_ffffff_1x400.png │ │ ├── ui-bg_gloss-wave_35_f6a828_500x100.png │ │ ├── ui-bg_highlight-soft_100_eeeeee_1x100.png │ │ ├── ui-bg_highlight-soft_75_ffe45c_1x100.png │ │ ├── ui-icons_222222_256x240.png │ │ ├── ui-icons_228ef1_256x240.png │ │ ├── ui-icons_ef8c08_256x240.png │ │ ├── ui-icons_ffd27a_256x240.png │ │ └── ui-icons_ffffff_256x240.png │ │ ├── jquery-ui-1.10.3.custom.css │ │ └── style.css ├── controllers │ └── fullcalendar_engine │ │ ├── application_controller.rb │ │ └── events_controller.rb ├── models │ └── fullcalendar_engine │ │ ├── event.rb │ │ └── event_series.rb └── views │ └── fullcalendar_engine │ └── events │ ├── _edit_form.html.erb │ ├── _form.html.erb │ ├── index.html.erb │ └── new.js.erb ├── bin └── rails ├── config ├── full-calendar.yml.dummy ├── initializers │ ├── configuration.rb │ └── constants.rb └── routes.rb ├── db └── migrate │ ├── 20131203105320_create_fullcalendar_engine_events.rb │ └── 20131203105529_create_fullcalendar_engine_event_series.rb ├── fullcalendar_engine.gemspec ├── lib ├── fullcalendar_engine.rb ├── fullcalendar_engine │ ├── engine.rb │ └── version.rb ├── generators │ └── fullcalendar_engine │ │ └── install │ │ └── install_generator.rb └── tasks │ └── fullcalendar_engine_tasks.rake └── test ├── controllers └── fullcalendar_engine │ └── events_controller_test.rb ├── fixtures └── fullcalendar_engine │ ├── event_series.yml │ └── events.yml ├── fullcalendar_engine_test.rb ├── helpers └── fullcalendar_engine │ └── events_helper_test.rb ├── integration └── navigation_test.rb ├── models └── fullcalendar_engine │ ├── event_series_test.rb │ └── event_test.rb └── test_helper.rb /.gitignore: -------------------------------------------------------------------------------- 1 | .bundle/ 2 | log/*.log 3 | pkg/ 4 | test/dummy/db/*.sqlite3 5 | test/dummy/db/*.sqlite3-journal 6 | test/dummy/log/*.log 7 | test/dummy/tmp/ 8 | test/dummy/.sass-cache 9 | Gemfile.lock -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # Declare your gem's dependencies in fullcalendar_engine.gemspec. 2 | # Bundler will treat runtime dependencies like base dependencies, and 3 | # development dependencies will be added by default to the :development group. 4 | gemspec 5 | # Declare any dependencies that are still in development here instead of in 6 | # your gemspec. These might include edge Rails or gems from your path or 7 | # Git. Remember to move these dependencies to your gemspec before releasing 8 | # your gem to rubygems.org. 9 | 10 | # To use debugger 11 | # gem 'debugger' 12 | -------------------------------------------------------------------------------- /MIT-LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2013 YOURNAME 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #FullcalendarEngine 2 | 3 | ## This engine supports only Rails 4 apps. 4 | 5 | ### Installation 6 | 7 | Add fullcalendar_engine to your Gemfile: 8 | 9 | ``` 10 | gem 'fullcalendar_engine' 11 | ``` 12 | 13 | #### Bundle install your dependencies and run the installation generator: 14 | ``` 15 | bundle install 16 | bundle exec rails g fullcalendar_engine:install 17 | ``` 18 | 19 | #### Declare routes 20 | ``` 21 | mount FullcalendarEngine::Engine => "/fullcalendar_engine" 22 | ``` 23 | 24 | #### Create Single Event 25 | ``` 26 | FullcalendarEngine::Event.create({ 27 | :title => 'title', 28 | :description => 'description', 29 | :starttime => Time.current, 30 | :endtime => Time.current + 10.minute 31 | }) 32 | ``` 33 | 34 | #### Create Event Series 35 | ``` 36 | FullcalendarEngine::EventSeries.create({ 37 | :title => 'title', 38 | :description => 'description', 39 | :starttime => Time.current, 40 | :endtime => Time.current + 10.minute, 41 | :period => 'daily', 42 | :frequency => '4' 43 | }) 44 | ``` 45 | 46 | #### In the config directory add the `fullcalendar.yml` and add `mount_path` option in it. Please note that this option is *REQUIRED* and if it is not specified then the JS and CSS of the engine would not work as desired.. 47 | ``` 48 | mount_path: "" 49 | ``` 50 | 51 | The engine can have its own layout, you can add `layout` option to the configuration file. Besides this, all the options which are available with the fullcalendar.js are listed in the *`fullcalendar.yml.dummy`* file. 52 | 53 | ## Using the Engine in some other views 54 | Initially the engine is designed to work only on the mount point but you can now use this engine anywhere in your app but there is an HTML structure which this engine expects. 55 | 56 | - Create a link or button for the creation of the new events. On its click a modal popup would appear. You can bind the dialog form generation as follows. Assign it any class or id you want. 57 | ``` 58 | $('').click(function(event) { 59 | FullcalendarEngine.Form.display() 60 | event.preventDefault(); 61 | }); 62 | ``` 63 | - For the calendar events the following HTML code must be copied and pasted directly into your view. 64 | ``` 65 |
66 |
67 |
68 | 69 | 70 | 71 | 74 | ``` 75 | 76 | - The `create_event_dialog` is the container for the dialog form. 77 | - The `event_desc_dialog` is the container for the display of the details of the event. 78 | 79 | Credits 80 | ------- 81 | 82 | [![vinsol.com: Ruby on Rails, iOS and Android developers](http://vinsol.com/vin_logo.png "Ruby on Rails, iOS and Android developers")](http://vinsol.com) 83 | 84 | Copyright (c) 2014 [vinsol.com](http://vinsol.com "Ruby on Rails, iOS and Android developers"), released under the New MIT License 85 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | begin 2 | require 'bundler/setup' 3 | rescue LoadError 4 | puts 'You must `gem install bundler` and `bundle install` to run rake tasks' 5 | end 6 | 7 | require 'rdoc/task' 8 | 9 | RDoc::Task.new(:rdoc) do |rdoc| 10 | rdoc.rdoc_dir = 'rdoc' 11 | rdoc.title = 'FullcalendarEngine' 12 | rdoc.options << '--line-numbers' 13 | rdoc.rdoc_files.include('README.rdoc') 14 | rdoc.rdoc_files.include('lib/**/*.rb') 15 | end 16 | 17 | APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__) 18 | load 'rails/tasks/engine.rake' 19 | 20 | 21 | 22 | Bundler::GemHelper.install_tasks 23 | 24 | require 'rake/testtask' 25 | 26 | Rake::TestTask.new(:test) do |t| 27 | t.libs << 'lib' 28 | t.libs << 'test' 29 | t.pattern = 'test/**/*_test.rb' 30 | t.verbose = false 31 | end 32 | 33 | 34 | task default: :test 35 | -------------------------------------------------------------------------------- /app/assets/images/fullcalendar_engine/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinsol/fullcalendar-rails-engine/4cfe2cc2c4206d4d1db5e6317d117ae698b5136f/app/assets/images/fullcalendar_engine/.keep -------------------------------------------------------------------------------- /app/assets/javascripts/fullcalendar_engine/application.js: -------------------------------------------------------------------------------- 1 | // This is a manifest file that'll be compiled into application.js, which will include all the files 2 | // listed below. 3 | // 4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, 5 | // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path. 6 | // 7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the 8 | // compiled file. 9 | // 10 | // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details 11 | // about supported directives. 12 | // 13 | //= require_tree . 14 | -------------------------------------------------------------------------------- /app/assets/javascripts/fullcalendar_engine/events.js.erb: -------------------------------------------------------------------------------- 1 | // Place all the behaviors and hooks related to the matching controller here. 2 | // All this logic will automatically be available in application.js. 3 | 4 | full_calendar_options = <%= FullcalendarEngine::Configuration.to_json.html_safe %> 5 | app_path = "<%= FullcalendarEngine::Configuration["mount_path"] %>" 6 | 7 | $.extend(full_calendar_options, { 8 | loading: function(bool){ 9 | if (bool) 10 | $('#loading').show(); 11 | else 12 | $('#loading').hide(); 13 | }, 14 | eventDrop: function(event, dayDelta, minuteDelta, allDay, revertFunc){ 15 | FullcalendarEngine.Events.move(event, dayDelta, minuteDelta, allDay); 16 | }, 17 | eventResize: function(event, dayDelta, minuteDelta, revertFunc){ 18 | FullcalendarEngine.Events.resize(event, dayDelta, minuteDelta); 19 | }, 20 | eventClick: function(event, jsEvent, view){ 21 | FullcalendarEngine.Events.showEventDetails(event); 22 | }, 23 | select: function( startDate, endDate, allDay, jsEvent, view ) { 24 | FullcalendarEngine.Form.display({ 25 | starttime: new Date(startDate.getTime()), 26 | endtime: new Date(endDate.getTime()), 27 | allDay: allDay 28 | }) 29 | } 30 | }) 31 | 32 | if (typeof(FullcalendarEngine) === 'undefined') { FullcalendarEngine = {}; } 33 | 34 | FullcalendarEngine = { 35 | Form: { 36 | display: function(options) { 37 | if (typeof(options) == 'undefined') { options = {} } 38 | FullcalendarEngine.Form.fetch(options) 39 | }, 40 | render: function(options){ 41 | $('#event_form').trigger('reset'); 42 | var startTime = options['starttime'] || new Date(), endTime = options['endtime'] || new Date(startTime.getTime()); 43 | if(startTime.getTime() == endTime.getTime()) { endTime.setMinutes(startTime.getMinutes() + 15); } 44 | FullcalendarEngine.setTime('#event_starttime', startTime) 45 | FullcalendarEngine.setTime('#event_endtime', endTime) 46 | $('#event_all_day').attr('checked', options['allDay']) 47 | $('#create_event_dialog').dialog({ 48 | title: 'New Event', 49 | modal: true, 50 | width: 500, 51 | close: function(event, ui) { $('#create_event_dialog').dialog('destroy') } 52 | }); 53 | }, 54 | fetch: function(options){ 55 | $.ajax({ 56 | type: 'get', 57 | dataType: 'script', 58 | async: true, 59 | url: FullcalendarEngine.app_path() + "/events/new", 60 | success: function(){ FullcalendarEngine.Form.render(options) } 61 | }); 62 | }, 63 | authenticity_token: function(){ 64 | return($('meta[name="csrf-token"]').attr("content")) 65 | } 66 | }, 67 | Events: { 68 | move: function(event, dayDelta, minuteDelta, allDay){ 69 | $.ajax({ 70 | data: 'title=' + event.title + '&day_delta=' + dayDelta + '&minute_delta=' + minuteDelta + '&all_day=' + allDay + '&authenticity_token=' + FullcalendarEngine.Form.authenticity_token(), 71 | dataType: 'script', 72 | type: 'post', 73 | url: FullcalendarEngine.app_path() + "/events/" + event.id + "/move", 74 | error: function(xhr){ 75 | alert(JSON.parse(xhr.responseText)["message"]) 76 | } 77 | }); 78 | }, 79 | resize: function(event, dayDelta, minuteDelta){ 80 | $.ajax({ 81 | data: 'title=' + event.title + '&day_delta=' + dayDelta + '&minute_delta=' + minuteDelta + '&authenticity_token=' + FullcalendarEngine.Form.authenticity_token(), 82 | dataType: 'script', 83 | type: 'post', 84 | url: FullcalendarEngine.app_path() + "/events/" + event.id + "/resize", 85 | error: function(xhr){ 86 | alert(JSON.parse(xhr.responseText)["message"]) 87 | } 88 | }); 89 | }, 90 | edit: function(event_id){ 91 | $.ajax({ 92 | url: FullcalendarEngine.app_path() + "/events/" + event_id + "/edit", 93 | success: function(data) { 94 | $('#edit_event_description').html(data['form']); 95 | } 96 | }); 97 | }, 98 | delete: function(event_id, delete_all){ 99 | $.ajax({ 100 | data: 'authenticity_token=' + FullcalendarEngine.Form.authenticity_token() + '&delete_all=' + delete_all, 101 | dataType: 'script', 102 | type: 'delete', 103 | url: FullcalendarEngine.app_path() + "/events/" + event_id, 104 | success: FullcalendarEngine.Events.refetch_events_and_close_dialog 105 | }); 106 | }, 107 | refetch_events_and_close_dialog: function() { 108 | $('.calendar').fullCalendar('refetchEvents'); 109 | $('.dialog:visible').dialog('destroy'); 110 | }, 111 | showEventDetails: function(event){ 112 | $('#event_desc_dialog').html('') 113 | $event_description = $('
').html(event.description).attr("id", "edit_event_description") 114 | $event_actions = $('
').attr("id", "event_actions") 115 | $edit_event = $('').attr("id", "edit_event").html("Edit"); 116 | $delete_event = $('').attr("id", "delete_event") 117 | if (event.recurring) { 118 | title = event.title + "(Recurring)"; 119 | // Cannot be refactored as of now, the event bubbling of the eventClick of the fullCalendar is the culprit 120 | $delete_event.html("  Delete Only This Occurrence"); 121 | $delete_event.append("   Delete All In Series") 122 | $delete_event.append("   Delete All Future Events") 123 | } else { 124 | title = event.title; 125 | $delete_event.html("Delete"); 126 | } 127 | $event_actions.append($edit_event).append(" | ").append($delete_event) 128 | $('#event_desc_dialog').append($event_description).append($event_actions) 129 | $('#event_desc_dialog').dialog({ 130 | title: title, 131 | modal: true, 132 | width: 500, 133 | close: function(event, ui){ $('#event_desc_dialog').html(''); $('#event_desc_dialog').dialog('destroy') } 134 | }); 135 | }, 136 | showPeriodAndFrequency: function(value){ 137 | switch (value) { 138 | case 'Daily': 139 | $('#period').html('day'); 140 | $('#frequency').show(); 141 | break; 142 | case 'Weekly': 143 | $('#period').html('week'); 144 | $('#frequency').show(); 145 | break; 146 | case 'Monthly': 147 | $('#period').html('month'); 148 | $('#frequency').show(); 149 | break; 150 | case 'Yearly': 151 | $('#period').html('year'); 152 | $('#frequency').show(); 153 | break; 154 | default: 155 | $('#frequency').hide(); 156 | } 157 | } 158 | }, 159 | setTime: function(type, time) { 160 | var $year = $(type + '_1i'), $month = $(type + '_2i'), $day = $(type + '_3i'), $hour = $(type + '_4i'), $minute = $(type + '_5i') 161 | $year.val(time.getFullYear()); 162 | $month.prop('selectedIndex', time.getMonth()); 163 | $day.prop('selectedIndex', time.getDate() - 1); 164 | $hour.prop('selectedIndex', time.getHours()); 165 | $minute.prop('selectedIndex', time.getMinutes()); 166 | }, 167 | app_path: function(){ 168 | return (app_path || window.location.pathname.match(/\/(\w)+/)[0]) 169 | } 170 | } 171 | 172 | $(document).ready(function(){ 173 | $('#create_event_dialog, #event_desc_dialog').on('submit', "#event_form", function(event) { 174 | var $spinner = $('.spinner'); 175 | event.preventDefault(); 176 | $.ajax({ 177 | type: "POST", 178 | data: $(this).serialize(), 179 | url: $(this).attr('action'), 180 | beforeSend: show_spinner, 181 | complete: hide_spinner, 182 | success: FullcalendarEngine.Events.refetch_events_and_close_dialog, 183 | error: handle_error 184 | }); 185 | 186 | function show_spinner() { 187 | $spinner.show(); 188 | } 189 | 190 | function hide_spinner() { 191 | $spinner.hide(); 192 | } 193 | 194 | function handle_error(xhr) { 195 | alert(xhr.responseText); 196 | } 197 | }) 198 | }); 199 | -------------------------------------------------------------------------------- /app/assets/javascripts/fullcalendar_engine/gcal.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * FullCalendar v1.6.4 Google Calendar Plugin 3 | * Docs & License: http://arshaw.com/fullcalendar/ 4 | * (c) 2013 Adam Shaw 5 | */ 6 | 7 | (function($) { 8 | 9 | 10 | var fc = $.fullCalendar; 11 | var formatDate = fc.formatDate; 12 | var parseISO8601 = fc.parseISO8601; 13 | var addDays = fc.addDays; 14 | var applyAll = fc.applyAll; 15 | 16 | 17 | fc.sourceNormalizers.push(function(sourceOptions) { 18 | if (sourceOptions.dataType == 'gcal' || 19 | sourceOptions.dataType === undefined && 20 | (sourceOptions.url || '').match(/^(http|https):\/\/www.google.com\/calendar\/feeds\//)) { 21 | sourceOptions.dataType = 'gcal'; 22 | if (sourceOptions.editable === undefined) { 23 | sourceOptions.editable = false; 24 | } 25 | } 26 | }); 27 | 28 | 29 | fc.sourceFetchers.push(function(sourceOptions, start, end) { 30 | if (sourceOptions.dataType == 'gcal') { 31 | return transformOptions(sourceOptions, start, end); 32 | } 33 | }); 34 | 35 | 36 | function transformOptions(sourceOptions, start, end) { 37 | 38 | var success = sourceOptions.success; 39 | var data = $.extend({}, sourceOptions.data || {}, { 40 | 'start-min': formatDate(start, 'u'), 41 | 'start-max': formatDate(end, 'u'), 42 | 'singleevents': true, 43 | 'max-results': 9999 44 | }); 45 | 46 | var ctz = sourceOptions.currentTimezone; 47 | if (ctz) { 48 | data.ctz = ctz = ctz.replace(' ', '_'); 49 | } 50 | 51 | return $.extend({}, sourceOptions, { 52 | url: sourceOptions.url.replace(/\/basic$/, '/full') + '?alt=json-in-script&callback=?', 53 | dataType: 'jsonp', 54 | data: data, 55 | startParam: false, 56 | endParam: false, 57 | success: function(data) { 58 | var events = []; 59 | if (data.feed.entry) { 60 | $.each(data.feed.entry, function(i, entry) { 61 | var startStr = entry['gd$when'][0]['startTime']; 62 | var start = parseISO8601(startStr, true); 63 | var end = parseISO8601(entry['gd$when'][0]['endTime'], true); 64 | var allDay = startStr.indexOf('T') == -1; 65 | var url; 66 | $.each(entry.link, function(i, link) { 67 | if (link.type == 'text/html') { 68 | url = link.href; 69 | if (ctz) { 70 | url += (url.indexOf('?') == -1 ? '?' : '&') + 'ctz=' + ctz; 71 | } 72 | } 73 | }); 74 | if (allDay) { 75 | addDays(end, -1); // make inclusive 76 | } 77 | events.push({ 78 | id: entry['gCal$uid']['value'], 79 | title: entry['title']['$t'], 80 | url: url, 81 | start: start, 82 | end: end, 83 | allDay: allDay, 84 | location: entry['gd$where'][0]['valueString'], 85 | description: entry['content']['$t'] 86 | }); 87 | }); 88 | } 89 | var args = [events].concat(Array.prototype.slice.call(arguments, 1)); 90 | var res = applyAll(success, this, args); 91 | if ($.isArray(res)) { 92 | return res; 93 | } 94 | return events; 95 | } 96 | }); 97 | 98 | } 99 | 100 | 101 | // legacy 102 | fc.gcalFeed = function(url, sourceOptions) { 103 | return $.extend({}, sourceOptions, { url: url, dataType: 'gcal' }); 104 | }; 105 | 106 | 107 | })(jQuery); 108 | -------------------------------------------------------------------------------- /app/assets/stylesheets/fullcalendar_engine/application.css: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a manifest file that'll be compiled into application.css, which will include all the files 3 | * listed below. 4 | * 5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, 6 | * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. 7 | * 8 | * You're free to add application-wide styles to this file and they'll appear at the top of the 9 | * compiled file, but it's generally better to create a new file per style scope. 10 | * 11 | *= require_self 12 | *= require_tree . 13 | */ 14 | -------------------------------------------------------------------------------- /app/assets/stylesheets/fullcalendar_engine/fullcalendar.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * FullCalendar v1.6.4 Stylesheet 3 | * Docs & License: http://arshaw.com/fullcalendar/ 4 | * (c) 2013 Adam Shaw 5 | */ 6 | 7 | 8 | .fc { 9 | direction: ltr; 10 | text-align: left; 11 | } 12 | 13 | .fc table { 14 | border-collapse: collapse; 15 | border-spacing: 0; 16 | } 17 | 18 | html .fc, 19 | .fc table { 20 | font-size: 1em; 21 | } 22 | 23 | .fc td, 24 | .fc th { 25 | padding: 0; 26 | vertical-align: top; 27 | } 28 | 29 | 30 | 31 | /* Header 32 | ------------------------------------------------------------------------*/ 33 | 34 | .fc-header td { 35 | white-space: nowrap; 36 | } 37 | 38 | .fc-header-left { 39 | width: 25%; 40 | text-align: left; 41 | } 42 | 43 | .fc-header-center { 44 | text-align: center; 45 | } 46 | 47 | .fc-header-right { 48 | width: 25%; 49 | text-align: right; 50 | } 51 | 52 | .fc-header-title { 53 | display: inline-block; 54 | vertical-align: top; 55 | } 56 | 57 | .fc-header-title h2 { 58 | margin-top: 0; 59 | white-space: nowrap; 60 | } 61 | 62 | .fc .fc-header-space { 63 | padding-left: 10px; 64 | } 65 | 66 | .fc-header .fc-button { 67 | margin-bottom: 1em; 68 | vertical-align: top; 69 | } 70 | 71 | /* buttons edges butting together */ 72 | 73 | .fc-header .fc-button { 74 | margin-right: -1px; 75 | } 76 | 77 | .fc-header .fc-corner-right, /* non-theme */ 78 | .fc-header .ui-corner-right { /* theme */ 79 | margin-right: 0; /* back to normal */ 80 | } 81 | 82 | /* button layering (for border precedence) */ 83 | 84 | .fc-header .fc-state-hover, 85 | .fc-header .ui-state-hover { 86 | z-index: 2; 87 | } 88 | 89 | .fc-header .fc-state-down { 90 | z-index: 3; 91 | } 92 | 93 | .fc-header .fc-state-active, 94 | .fc-header .ui-state-active { 95 | z-index: 4; 96 | } 97 | 98 | 99 | 100 | /* Content 101 | ------------------------------------------------------------------------*/ 102 | 103 | .fc-content { 104 | clear: both; 105 | zoom: 1; /* for IE7, gives accurate coordinates for [un]freezeContentHeight */ 106 | } 107 | 108 | .fc-view { 109 | width: 100%; 110 | overflow: hidden; 111 | } 112 | 113 | 114 | 115 | /* Cell Styles 116 | ------------------------------------------------------------------------*/ 117 | 118 | .fc-widget-header, /* , usually */ 119 | .fc-widget-content { /* , usually */ 120 | border: 1px solid #ddd; 121 | } 122 | 123 | .fc-state-highlight { /* today cell */ /* TODO: add .fc-today to */ 124 | background: #fcf8e3; 125 | } 126 | 127 | .fc-cell-overlay { /* semi-transparent rectangle while dragging */ 128 | background: #bce8f1; 129 | opacity: .3; 130 | filter: alpha(opacity=30); /* for IE */ 131 | } 132 | 133 | 134 | 135 | /* Buttons 136 | ------------------------------------------------------------------------*/ 137 | 138 | .fc-button { 139 | position: relative; 140 | display: inline-block; 141 | padding: 0 .6em; 142 | overflow: hidden; 143 | height: 1.9em; 144 | line-height: 1.9em; 145 | white-space: nowrap; 146 | cursor: pointer; 147 | } 148 | 149 | .fc-state-default { /* non-theme */ 150 | border: 1px solid; 151 | } 152 | 153 | .fc-state-default.fc-corner-left { /* non-theme */ 154 | border-top-left-radius: 4px; 155 | border-bottom-left-radius: 4px; 156 | } 157 | 158 | .fc-state-default.fc-corner-right { /* non-theme */ 159 | border-top-right-radius: 4px; 160 | border-bottom-right-radius: 4px; 161 | } 162 | 163 | /* 164 | Our default prev/next buttons use HTML entities like ‹ › « » 165 | and we'll try to make them look good cross-browser. 166 | */ 167 | 168 | .fc-text-arrow { 169 | margin: 0 .1em; 170 | font-size: 2em; 171 | font-family: "Courier New", Courier, monospace; 172 | vertical-align: baseline; /* for IE7 */ 173 | } 174 | 175 | .fc-button-prev .fc-text-arrow, 176 | .fc-button-next .fc-text-arrow { /* for ‹ › */ 177 | font-weight: bold; 178 | } 179 | 180 | /* icon (for jquery ui) */ 181 | 182 | .fc-button .fc-icon-wrap { 183 | position: relative; 184 | float: left; 185 | top: 50%; 186 | } 187 | 188 | .fc-button .ui-icon { 189 | position: relative; 190 | float: left; 191 | margin-top: -50%; 192 | *margin-top: 0; 193 | *top: -50%; 194 | } 195 | 196 | /* 197 | button states 198 | borrowed from twitter bootstrap (http://twitter.github.com/bootstrap/) 199 | */ 200 | 201 | .fc-state-default { 202 | background-color: #f5f5f5; 203 | background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); 204 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); 205 | background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); 206 | background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); 207 | background-image: linear-gradient(to bottom, #ffffff, #e6e6e6); 208 | background-repeat: repeat-x; 209 | border-color: #e6e6e6 #e6e6e6 #bfbfbf; 210 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 211 | color: #333; 212 | text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); 213 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); 214 | } 215 | 216 | .fc-state-hover, 217 | .fc-state-down, 218 | .fc-state-active, 219 | .fc-state-disabled { 220 | color: #333333; 221 | background-color: #e6e6e6; 222 | } 223 | 224 | .fc-state-hover { 225 | color: #333333; 226 | text-decoration: none; 227 | background-position: 0 -15px; 228 | -webkit-transition: background-position 0.1s linear; 229 | -moz-transition: background-position 0.1s linear; 230 | -o-transition: background-position 0.1s linear; 231 | transition: background-position 0.1s linear; 232 | } 233 | 234 | .fc-state-down, 235 | .fc-state-active { 236 | background-color: #cccccc; 237 | background-image: none; 238 | outline: 0; 239 | box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); 240 | } 241 | 242 | .fc-state-disabled { 243 | cursor: default; 244 | background-image: none; 245 | opacity: 0.65; 246 | filter: alpha(opacity=65); 247 | box-shadow: none; 248 | } 249 | 250 | 251 | 252 | /* Global Event Styles 253 | ------------------------------------------------------------------------*/ 254 | 255 | .fc-event-container > * { 256 | z-index: 8; 257 | } 258 | 259 | .fc-event-container > .ui-draggable-dragging, 260 | .fc-event-container > .ui-resizable-resizing { 261 | z-index: 9; 262 | } 263 | 264 | .fc-event { 265 | border: 1px solid #3a87ad; /* default BORDER color */ 266 | background-color: #3a87ad; /* default BACKGROUND color */ 267 | color: #fff; /* default TEXT color */ 268 | font-size: .85em; 269 | cursor: default; 270 | } 271 | 272 | a.fc-event { 273 | text-decoration: none; 274 | } 275 | 276 | a.fc-event, 277 | .fc-event-draggable { 278 | cursor: pointer; 279 | } 280 | 281 | .fc-rtl .fc-event { 282 | text-align: right; 283 | } 284 | 285 | .fc-event-inner { 286 | width: 100%; 287 | height: 100%; 288 | overflow: hidden; 289 | } 290 | 291 | .fc-event-time, 292 | .fc-event-title { 293 | padding: 0 1px; 294 | } 295 | 296 | .fc .ui-resizable-handle { 297 | display: block; 298 | position: absolute; 299 | z-index: 99999; 300 | overflow: hidden; /* hacky spaces (IE6/7) */ 301 | font-size: 300%; /* */ 302 | line-height: 50%; /* */ 303 | } 304 | 305 | 306 | 307 | /* Horizontal Events 308 | ------------------------------------------------------------------------*/ 309 | 310 | .fc-event-hori { 311 | border-width: 1px 0; 312 | margin-bottom: 1px; 313 | } 314 | 315 | .fc-ltr .fc-event-hori.fc-event-start, 316 | .fc-rtl .fc-event-hori.fc-event-end { 317 | border-left-width: 1px; 318 | border-top-left-radius: 3px; 319 | border-bottom-left-radius: 3px; 320 | } 321 | 322 | .fc-ltr .fc-event-hori.fc-event-end, 323 | .fc-rtl .fc-event-hori.fc-event-start { 324 | border-right-width: 1px; 325 | border-top-right-radius: 3px; 326 | border-bottom-right-radius: 3px; 327 | } 328 | 329 | /* resizable */ 330 | 331 | .fc-event-hori .ui-resizable-e { 332 | top: 0 !important; /* importants override pre jquery ui 1.7 styles */ 333 | right: -3px !important; 334 | width: 7px !important; 335 | height: 100% !important; 336 | cursor: e-resize; 337 | } 338 | 339 | .fc-event-hori .ui-resizable-w { 340 | top: 0 !important; 341 | left: -3px !important; 342 | width: 7px !important; 343 | height: 100% !important; 344 | cursor: w-resize; 345 | } 346 | 347 | .fc-event-hori .ui-resizable-handle { 348 | _padding-bottom: 14px; /* IE6 had 0 height */ 349 | } 350 | 351 | 352 | 353 | /* Reusable Separate-border Table 354 | ------------------------------------------------------------*/ 355 | 356 | table.fc-border-separate { 357 | border-collapse: separate; 358 | } 359 | 360 | .fc-border-separate th, 361 | .fc-border-separate td { 362 | border-width: 1px 0 0 1px; 363 | } 364 | 365 | .fc-border-separate th.fc-last, 366 | .fc-border-separate td.fc-last { 367 | border-right-width: 1px; 368 | } 369 | 370 | .fc-border-separate tr.fc-last th, 371 | .fc-border-separate tr.fc-last td { 372 | border-bottom-width: 1px; 373 | } 374 | 375 | .fc-border-separate tbody tr.fc-first td, 376 | .fc-border-separate tbody tr.fc-first th { 377 | border-top-width: 0; 378 | } 379 | 380 | 381 | 382 | /* Month View, Basic Week View, Basic Day View 383 | ------------------------------------------------------------------------*/ 384 | 385 | .fc-grid th { 386 | text-align: center; 387 | } 388 | 389 | .fc .fc-week-number { 390 | width: 22px; 391 | text-align: center; 392 | } 393 | 394 | .fc .fc-week-number div { 395 | padding: 0 2px; 396 | } 397 | 398 | .fc-grid .fc-day-number { 399 | float: right; 400 | padding: 0 2px; 401 | } 402 | 403 | .fc-grid .fc-other-month .fc-day-number { 404 | opacity: 0.3; 405 | filter: alpha(opacity=30); /* for IE */ 406 | /* opacity with small font can sometimes look too faded 407 | might want to set the 'color' property instead 408 | making day-numbers bold also fixes the problem */ 409 | } 410 | 411 | .fc-grid .fc-day-content { 412 | clear: both; 413 | padding: 2px 2px 1px; /* distance between events and day edges */ 414 | } 415 | 416 | /* event styles */ 417 | 418 | .fc-grid .fc-event-time { 419 | font-weight: bold; 420 | } 421 | 422 | /* right-to-left */ 423 | 424 | .fc-rtl .fc-grid .fc-day-number { 425 | float: left; 426 | } 427 | 428 | .fc-rtl .fc-grid .fc-event-time { 429 | float: right; 430 | } 431 | 432 | 433 | 434 | /* Agenda Week View, Agenda Day View 435 | ------------------------------------------------------------------------*/ 436 | 437 | .fc-agenda table { 438 | border-collapse: separate; 439 | } 440 | 441 | .fc-agenda-days th { 442 | text-align: center; 443 | } 444 | 445 | .fc-agenda .fc-agenda-axis { 446 | width: 50px; 447 | padding: 0 4px; 448 | vertical-align: middle; 449 | text-align: right; 450 | white-space: nowrap; 451 | font-weight: normal; 452 | } 453 | 454 | .fc-agenda .fc-week-number { 455 | font-weight: bold; 456 | } 457 | 458 | .fc-agenda .fc-day-content { 459 | padding: 2px 2px 1px; 460 | } 461 | 462 | /* make axis border take precedence */ 463 | 464 | .fc-agenda-days .fc-agenda-axis { 465 | border-right-width: 1px; 466 | } 467 | 468 | .fc-agenda-days .fc-col0 { 469 | border-left-width: 0; 470 | } 471 | 472 | /* all-day area */ 473 | 474 | .fc-agenda-allday th { 475 | border-width: 0 1px; 476 | } 477 | 478 | .fc-agenda-allday .fc-day-content { 479 | min-height: 34px; /* TODO: doesnt work well in quirksmode */ 480 | _height: 34px; 481 | } 482 | 483 | /* divider (between all-day and slots) */ 484 | 485 | .fc-agenda-divider-inner { 486 | height: 2px; 487 | overflow: hidden; 488 | } 489 | 490 | .fc-widget-header .fc-agenda-divider-inner { 491 | background: #eee; 492 | } 493 | 494 | /* slot rows */ 495 | 496 | .fc-agenda-slots th { 497 | border-width: 1px 1px 0; 498 | } 499 | 500 | .fc-agenda-slots td { 501 | border-width: 1px 0 0; 502 | background: none; 503 | } 504 | 505 | .fc-agenda-slots td div { 506 | height: 20px; 507 | } 508 | 509 | .fc-agenda-slots tr.fc-slot0 th, 510 | .fc-agenda-slots tr.fc-slot0 td { 511 | border-top-width: 0; 512 | } 513 | 514 | .fc-agenda-slots tr.fc-minor th, 515 | .fc-agenda-slots tr.fc-minor td { 516 | border-top-style: dotted; 517 | } 518 | 519 | .fc-agenda-slots tr.fc-minor th.ui-widget-header { 520 | *border-top-style: solid; /* doesn't work with background in IE6/7 */ 521 | } 522 | 523 | 524 | 525 | /* Vertical Events 526 | ------------------------------------------------------------------------*/ 527 | 528 | .fc-event-vert { 529 | border-width: 0 1px; 530 | } 531 | 532 | .fc-event-vert.fc-event-start { 533 | border-top-width: 1px; 534 | border-top-left-radius: 3px; 535 | border-top-right-radius: 3px; 536 | } 537 | 538 | .fc-event-vert.fc-event-end { 539 | border-bottom-width: 1px; 540 | border-bottom-left-radius: 3px; 541 | border-bottom-right-radius: 3px; 542 | } 543 | 544 | .fc-event-vert .fc-event-time { 545 | white-space: nowrap; 546 | font-size: 10px; 547 | } 548 | 549 | .fc-event-vert .fc-event-inner { 550 | position: relative; 551 | z-index: 2; 552 | } 553 | 554 | .fc-event-vert .fc-event-bg { /* makes the event lighter w/ a semi-transparent overlay */ 555 | position: absolute; 556 | z-index: 1; 557 | top: 0; 558 | left: 0; 559 | width: 100%; 560 | height: 100%; 561 | background: #fff; 562 | opacity: .25; 563 | filter: alpha(opacity=25); 564 | } 565 | 566 | .fc .ui-draggable-dragging .fc-event-bg, /* TODO: something nicer like .fc-opacity */ 567 | .fc-select-helper .fc-event-bg { 568 | display: none\9; /* for IE6/7/8. nested opacity filters while dragging don't work */ 569 | } 570 | 571 | /* resizable */ 572 | 573 | .fc-event-vert .ui-resizable-s { 574 | bottom: 0 !important; /* importants override pre jquery ui 1.7 styles */ 575 | width: 100% !important; 576 | height: 8px !important; 577 | overflow: hidden !important; 578 | line-height: 8px !important; 579 | font-size: 11px !important; 580 | font-family: monospace; 581 | text-align: center; 582 | cursor: s-resize; 583 | } 584 | 585 | .fc-agenda .ui-resizable-resizing { /* TODO: better selector */ 586 | _overflow: hidden; 587 | } 588 | 589 | 590 | -------------------------------------------------------------------------------- /app/assets/stylesheets/fullcalendar_engine/images/animated-overlay.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinsol/fullcalendar-rails-engine/4cfe2cc2c4206d4d1db5e6317d117ae698b5136f/app/assets/stylesheets/fullcalendar_engine/images/animated-overlay.gif -------------------------------------------------------------------------------- /app/assets/stylesheets/fullcalendar_engine/images/ui-bg_diagonals-thick_18_b81900_40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinsol/fullcalendar-rails-engine/4cfe2cc2c4206d4d1db5e6317d117ae698b5136f/app/assets/stylesheets/fullcalendar_engine/images/ui-bg_diagonals-thick_18_b81900_40x40.png -------------------------------------------------------------------------------- /app/assets/stylesheets/fullcalendar_engine/images/ui-bg_diagonals-thick_20_666666_40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinsol/fullcalendar-rails-engine/4cfe2cc2c4206d4d1db5e6317d117ae698b5136f/app/assets/stylesheets/fullcalendar_engine/images/ui-bg_diagonals-thick_20_666666_40x40.png -------------------------------------------------------------------------------- /app/assets/stylesheets/fullcalendar_engine/images/ui-bg_flat_10_000000_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinsol/fullcalendar-rails-engine/4cfe2cc2c4206d4d1db5e6317d117ae698b5136f/app/assets/stylesheets/fullcalendar_engine/images/ui-bg_flat_10_000000_40x100.png -------------------------------------------------------------------------------- /app/assets/stylesheets/fullcalendar_engine/images/ui-bg_glass_100_f6f6f6_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinsol/fullcalendar-rails-engine/4cfe2cc2c4206d4d1db5e6317d117ae698b5136f/app/assets/stylesheets/fullcalendar_engine/images/ui-bg_glass_100_f6f6f6_1x400.png -------------------------------------------------------------------------------- /app/assets/stylesheets/fullcalendar_engine/images/ui-bg_glass_100_fdf5ce_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinsol/fullcalendar-rails-engine/4cfe2cc2c4206d4d1db5e6317d117ae698b5136f/app/assets/stylesheets/fullcalendar_engine/images/ui-bg_glass_100_fdf5ce_1x400.png -------------------------------------------------------------------------------- /app/assets/stylesheets/fullcalendar_engine/images/ui-bg_glass_65_ffffff_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinsol/fullcalendar-rails-engine/4cfe2cc2c4206d4d1db5e6317d117ae698b5136f/app/assets/stylesheets/fullcalendar_engine/images/ui-bg_glass_65_ffffff_1x400.png -------------------------------------------------------------------------------- /app/assets/stylesheets/fullcalendar_engine/images/ui-bg_gloss-wave_35_f6a828_500x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinsol/fullcalendar-rails-engine/4cfe2cc2c4206d4d1db5e6317d117ae698b5136f/app/assets/stylesheets/fullcalendar_engine/images/ui-bg_gloss-wave_35_f6a828_500x100.png -------------------------------------------------------------------------------- /app/assets/stylesheets/fullcalendar_engine/images/ui-bg_highlight-soft_100_eeeeee_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinsol/fullcalendar-rails-engine/4cfe2cc2c4206d4d1db5e6317d117ae698b5136f/app/assets/stylesheets/fullcalendar_engine/images/ui-bg_highlight-soft_100_eeeeee_1x100.png -------------------------------------------------------------------------------- /app/assets/stylesheets/fullcalendar_engine/images/ui-bg_highlight-soft_75_ffe45c_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinsol/fullcalendar-rails-engine/4cfe2cc2c4206d4d1db5e6317d117ae698b5136f/app/assets/stylesheets/fullcalendar_engine/images/ui-bg_highlight-soft_75_ffe45c_1x100.png -------------------------------------------------------------------------------- /app/assets/stylesheets/fullcalendar_engine/images/ui-icons_222222_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinsol/fullcalendar-rails-engine/4cfe2cc2c4206d4d1db5e6317d117ae698b5136f/app/assets/stylesheets/fullcalendar_engine/images/ui-icons_222222_256x240.png -------------------------------------------------------------------------------- /app/assets/stylesheets/fullcalendar_engine/images/ui-icons_228ef1_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinsol/fullcalendar-rails-engine/4cfe2cc2c4206d4d1db5e6317d117ae698b5136f/app/assets/stylesheets/fullcalendar_engine/images/ui-icons_228ef1_256x240.png -------------------------------------------------------------------------------- /app/assets/stylesheets/fullcalendar_engine/images/ui-icons_ef8c08_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinsol/fullcalendar-rails-engine/4cfe2cc2c4206d4d1db5e6317d117ae698b5136f/app/assets/stylesheets/fullcalendar_engine/images/ui-icons_ef8c08_256x240.png -------------------------------------------------------------------------------- /app/assets/stylesheets/fullcalendar_engine/images/ui-icons_ffd27a_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinsol/fullcalendar-rails-engine/4cfe2cc2c4206d4d1db5e6317d117ae698b5136f/app/assets/stylesheets/fullcalendar_engine/images/ui-icons_ffd27a_256x240.png -------------------------------------------------------------------------------- /app/assets/stylesheets/fullcalendar_engine/images/ui-icons_ffffff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinsol/fullcalendar-rails-engine/4cfe2cc2c4206d4d1db5e6317d117ae698b5136f/app/assets/stylesheets/fullcalendar_engine/images/ui-icons_ffffff_256x240.png -------------------------------------------------------------------------------- /app/assets/stylesheets/fullcalendar_engine/jquery-ui-1.10.3.custom.css: -------------------------------------------------------------------------------- 1 | /*! jQuery UI - v1.10.3 - 2013-11-20 2 | * http://jqueryui.com 3 | * Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css, jquery.ui.theme.css 4 | * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS%2CTahoma%2CVerdana%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=gloss_wave&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=highlight_soft&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=glass&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=glass&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=highlight_soft&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=diagonals_thick&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=diagonals_thick&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=flat&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px 5 | * Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */ 6 | 7 | /* Layout helpers 8 | ----------------------------------*/ 9 | .ui-helper-hidden { 10 | display: none; 11 | } 12 | .ui-helper-hidden-accessible { 13 | border: 0; 14 | clip: rect(0 0 0 0); 15 | height: 1px; 16 | margin: -1px; 17 | overflow: hidden; 18 | padding: 0; 19 | position: absolute; 20 | width: 1px; 21 | } 22 | .ui-helper-reset { 23 | margin: 0; 24 | padding: 0; 25 | border: 0; 26 | outline: 0; 27 | line-height: 1.3; 28 | text-decoration: none; 29 | font-size: 100%; 30 | list-style: none; 31 | } 32 | .ui-helper-clearfix:before, 33 | .ui-helper-clearfix:after { 34 | content: ""; 35 | display: table; 36 | border-collapse: collapse; 37 | } 38 | .ui-helper-clearfix:after { 39 | clear: both; 40 | } 41 | .ui-helper-clearfix { 42 | min-height: 0; /* support: IE7 */ 43 | } 44 | .ui-helper-zfix { 45 | width: 100%; 46 | height: 100%; 47 | top: 0; 48 | left: 0; 49 | position: absolute; 50 | opacity: 0; 51 | filter:Alpha(Opacity=0); 52 | } 53 | 54 | .ui-front { 55 | z-index: 100; 56 | } 57 | 58 | 59 | /* Interaction Cues 60 | ----------------------------------*/ 61 | .ui-state-disabled { 62 | cursor: default !important; 63 | } 64 | 65 | 66 | /* Icons 67 | ----------------------------------*/ 68 | 69 | /* states and images */ 70 | .ui-icon { 71 | display: block; 72 | text-indent: -99999px; 73 | overflow: hidden; 74 | background-repeat: no-repeat; 75 | } 76 | 77 | 78 | /* Misc visuals 79 | ----------------------------------*/ 80 | 81 | /* Overlays */ 82 | .ui-widget-overlay { 83 | position: fixed; 84 | top: 0; 85 | left: 0; 86 | width: 100%; 87 | height: 100%; 88 | } 89 | .ui-resizable { 90 | position: relative; 91 | } 92 | .ui-resizable-handle { 93 | position: absolute; 94 | font-size: 0.1px; 95 | display: block; 96 | } 97 | .ui-resizable-disabled .ui-resizable-handle, 98 | .ui-resizable-autohide .ui-resizable-handle { 99 | display: none; 100 | } 101 | .ui-resizable-n { 102 | cursor: n-resize; 103 | height: 7px; 104 | width: 100%; 105 | top: -5px; 106 | left: 0; 107 | } 108 | .ui-resizable-s { 109 | cursor: s-resize; 110 | height: 7px; 111 | width: 100%; 112 | bottom: -5px; 113 | left: 0; 114 | } 115 | .ui-resizable-e { 116 | cursor: e-resize; 117 | width: 7px; 118 | right: -5px; 119 | top: 0; 120 | height: 100%; 121 | } 122 | .ui-resizable-w { 123 | cursor: w-resize; 124 | width: 7px; 125 | left: -5px; 126 | top: 0; 127 | height: 100%; 128 | } 129 | .ui-resizable-se { 130 | cursor: se-resize; 131 | width: 12px; 132 | height: 12px; 133 | right: 1px; 134 | bottom: 1px; 135 | } 136 | .ui-resizable-sw { 137 | cursor: sw-resize; 138 | width: 9px; 139 | height: 9px; 140 | left: -5px; 141 | bottom: -5px; 142 | } 143 | .ui-resizable-nw { 144 | cursor: nw-resize; 145 | width: 9px; 146 | height: 9px; 147 | left: -5px; 148 | top: -5px; 149 | } 150 | .ui-resizable-ne { 151 | cursor: ne-resize; 152 | width: 9px; 153 | height: 9px; 154 | right: -5px; 155 | top: -5px; 156 | } 157 | .ui-selectable-helper { 158 | position: absolute; 159 | z-index: 100; 160 | border: 1px dotted black; 161 | } 162 | .ui-accordion .ui-accordion-header { 163 | display: block; 164 | cursor: pointer; 165 | position: relative; 166 | margin-top: 2px; 167 | padding: .5em .5em .5em .7em; 168 | min-height: 0; /* support: IE7 */ 169 | } 170 | .ui-accordion .ui-accordion-icons { 171 | padding-left: 2.2em; 172 | } 173 | .ui-accordion .ui-accordion-noicons { 174 | padding-left: .7em; 175 | } 176 | .ui-accordion .ui-accordion-icons .ui-accordion-icons { 177 | padding-left: 2.2em; 178 | } 179 | .ui-accordion .ui-accordion-header .ui-accordion-header-icon { 180 | position: absolute; 181 | left: .5em; 182 | top: 50%; 183 | margin-top: -8px; 184 | } 185 | .ui-accordion .ui-accordion-content { 186 | padding: 1em 2.2em; 187 | border-top: 0; 188 | overflow: auto; 189 | } 190 | .ui-autocomplete { 191 | position: absolute; 192 | top: 0; 193 | left: 0; 194 | cursor: default; 195 | } 196 | .ui-button { 197 | display: inline-block; 198 | position: relative; 199 | padding: 0; 200 | line-height: normal; 201 | margin-right: .1em; 202 | cursor: pointer; 203 | vertical-align: middle; 204 | text-align: center; 205 | overflow: visible; /* removes extra width in IE */ 206 | } 207 | .ui-button, 208 | .ui-button:link, 209 | .ui-button:visited, 210 | .ui-button:hover, 211 | .ui-button:active { 212 | text-decoration: none; 213 | } 214 | /* to make room for the icon, a width needs to be set here */ 215 | .ui-button-icon-only { 216 | width: 2.2em; 217 | } 218 | /* button elements seem to need a little more width */ 219 | button.ui-button-icon-only { 220 | width: 2.4em; 221 | } 222 | .ui-button-icons-only { 223 | width: 3.4em; 224 | } 225 | button.ui-button-icons-only { 226 | width: 3.7em; 227 | } 228 | 229 | /* button text element */ 230 | .ui-button .ui-button-text { 231 | display: block; 232 | line-height: normal; 233 | } 234 | .ui-button-text-only .ui-button-text { 235 | padding: .4em 1em; 236 | } 237 | .ui-button-icon-only .ui-button-text, 238 | .ui-button-icons-only .ui-button-text { 239 | padding: .4em; 240 | text-indent: -9999999px; 241 | } 242 | .ui-button-text-icon-primary .ui-button-text, 243 | .ui-button-text-icons .ui-button-text { 244 | padding: .4em 1em .4em 2.1em; 245 | } 246 | .ui-button-text-icon-secondary .ui-button-text, 247 | .ui-button-text-icons .ui-button-text { 248 | padding: .4em 2.1em .4em 1em; 249 | } 250 | .ui-button-text-icons .ui-button-text { 251 | padding-left: 2.1em; 252 | padding-right: 2.1em; 253 | } 254 | /* no icon support for input elements, provide padding by default */ 255 | input.ui-button { 256 | padding: .4em 1em; 257 | } 258 | 259 | /* button icon element(s) */ 260 | .ui-button-icon-only .ui-icon, 261 | .ui-button-text-icon-primary .ui-icon, 262 | .ui-button-text-icon-secondary .ui-icon, 263 | .ui-button-text-icons .ui-icon, 264 | .ui-button-icons-only .ui-icon { 265 | position: absolute; 266 | top: 50%; 267 | margin-top: -8px; 268 | } 269 | .ui-button-icon-only .ui-icon { 270 | left: 50%; 271 | margin-left: -8px; 272 | } 273 | .ui-button-text-icon-primary .ui-button-icon-primary, 274 | .ui-button-text-icons .ui-button-icon-primary, 275 | .ui-button-icons-only .ui-button-icon-primary { 276 | left: .5em; 277 | } 278 | .ui-button-text-icon-secondary .ui-button-icon-secondary, 279 | .ui-button-text-icons .ui-button-icon-secondary, 280 | .ui-button-icons-only .ui-button-icon-secondary { 281 | right: .5em; 282 | } 283 | 284 | /* button sets */ 285 | .ui-buttonset { 286 | margin-right: 7px; 287 | } 288 | .ui-buttonset .ui-button { 289 | margin-left: 0; 290 | margin-right: -.3em; 291 | } 292 | 293 | /* workarounds */ 294 | /* reset extra padding in Firefox, see h5bp.com/l */ 295 | input.ui-button::-moz-focus-inner, 296 | button.ui-button::-moz-focus-inner { 297 | border: 0; 298 | padding: 0; 299 | } 300 | .ui-datepicker { 301 | width: 17em; 302 | padding: .2em .2em 0; 303 | display: none; 304 | } 305 | .ui-datepicker .ui-datepicker-header { 306 | position: relative; 307 | padding: .2em 0; 308 | } 309 | .ui-datepicker .ui-datepicker-prev, 310 | .ui-datepicker .ui-datepicker-next { 311 | position: absolute; 312 | top: 2px; 313 | width: 1.8em; 314 | height: 1.8em; 315 | } 316 | .ui-datepicker .ui-datepicker-prev-hover, 317 | .ui-datepicker .ui-datepicker-next-hover { 318 | top: 1px; 319 | } 320 | .ui-datepicker .ui-datepicker-prev { 321 | left: 2px; 322 | } 323 | .ui-datepicker .ui-datepicker-next { 324 | right: 2px; 325 | } 326 | .ui-datepicker .ui-datepicker-prev-hover { 327 | left: 1px; 328 | } 329 | .ui-datepicker .ui-datepicker-next-hover { 330 | right: 1px; 331 | } 332 | .ui-datepicker .ui-datepicker-prev span, 333 | .ui-datepicker .ui-datepicker-next span { 334 | display: block; 335 | position: absolute; 336 | left: 50%; 337 | margin-left: -8px; 338 | top: 50%; 339 | margin-top: -8px; 340 | } 341 | .ui-datepicker .ui-datepicker-title { 342 | margin: 0 2.3em; 343 | line-height: 1.8em; 344 | text-align: center; 345 | } 346 | .ui-datepicker .ui-datepicker-title select { 347 | font-size: 1em; 348 | margin: 1px 0; 349 | } 350 | .ui-datepicker select.ui-datepicker-month-year { 351 | width: 100%; 352 | } 353 | .ui-datepicker select.ui-datepicker-month, 354 | .ui-datepicker select.ui-datepicker-year { 355 | width: 49%; 356 | } 357 | .ui-datepicker table { 358 | width: 100%; 359 | font-size: .9em; 360 | border-collapse: collapse; 361 | margin: 0 0 .4em; 362 | } 363 | .ui-datepicker th { 364 | padding: .7em .3em; 365 | text-align: center; 366 | font-weight: bold; 367 | border: 0; 368 | } 369 | .ui-datepicker td { 370 | border: 0; 371 | padding: 1px; 372 | } 373 | .ui-datepicker td span, 374 | .ui-datepicker td a { 375 | display: block; 376 | padding: .2em; 377 | text-align: right; 378 | text-decoration: none; 379 | } 380 | .ui-datepicker .ui-datepicker-buttonpane { 381 | background-image: none; 382 | margin: .7em 0 0 0; 383 | padding: 0 .2em; 384 | border-left: 0; 385 | border-right: 0; 386 | border-bottom: 0; 387 | } 388 | .ui-datepicker .ui-datepicker-buttonpane button { 389 | float: right; 390 | margin: .5em .2em .4em; 391 | cursor: pointer; 392 | padding: .2em .6em .3em .6em; 393 | width: auto; 394 | overflow: visible; 395 | } 396 | .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { 397 | float: left; 398 | } 399 | 400 | /* with multiple calendars */ 401 | .ui-datepicker.ui-datepicker-multi { 402 | width: auto; 403 | } 404 | .ui-datepicker-multi .ui-datepicker-group { 405 | float: left; 406 | } 407 | .ui-datepicker-multi .ui-datepicker-group table { 408 | width: 95%; 409 | margin: 0 auto .4em; 410 | } 411 | .ui-datepicker-multi-2 .ui-datepicker-group { 412 | width: 50%; 413 | } 414 | .ui-datepicker-multi-3 .ui-datepicker-group { 415 | width: 33.3%; 416 | } 417 | .ui-datepicker-multi-4 .ui-datepicker-group { 418 | width: 25%; 419 | } 420 | .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header, 421 | .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { 422 | border-left-width: 0; 423 | } 424 | .ui-datepicker-multi .ui-datepicker-buttonpane { 425 | clear: left; 426 | } 427 | .ui-datepicker-row-break { 428 | clear: both; 429 | width: 100%; 430 | font-size: 0; 431 | } 432 | 433 | /* RTL support */ 434 | .ui-datepicker-rtl { 435 | direction: rtl; 436 | } 437 | .ui-datepicker-rtl .ui-datepicker-prev { 438 | right: 2px; 439 | left: auto; 440 | } 441 | .ui-datepicker-rtl .ui-datepicker-next { 442 | left: 2px; 443 | right: auto; 444 | } 445 | .ui-datepicker-rtl .ui-datepicker-prev:hover { 446 | right: 1px; 447 | left: auto; 448 | } 449 | .ui-datepicker-rtl .ui-datepicker-next:hover { 450 | left: 1px; 451 | right: auto; 452 | } 453 | .ui-datepicker-rtl .ui-datepicker-buttonpane { 454 | clear: right; 455 | } 456 | .ui-datepicker-rtl .ui-datepicker-buttonpane button { 457 | float: left; 458 | } 459 | .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current, 460 | .ui-datepicker-rtl .ui-datepicker-group { 461 | float: right; 462 | } 463 | .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header, 464 | .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { 465 | border-right-width: 0; 466 | border-left-width: 1px; 467 | } 468 | .ui-dialog { 469 | position: absolute; 470 | top: 0; 471 | left: 0; 472 | padding: .2em; 473 | outline: 0; 474 | } 475 | .ui-dialog .ui-dialog-titlebar { 476 | padding: .4em 1em; 477 | position: relative; 478 | } 479 | .ui-dialog .ui-dialog-title { 480 | float: left; 481 | margin: .1em 0; 482 | white-space: nowrap; 483 | width: 90%; 484 | overflow: hidden; 485 | text-overflow: ellipsis; 486 | } 487 | .ui-dialog .ui-dialog-titlebar-close { 488 | position: absolute; 489 | right: .3em; 490 | top: 50%; 491 | width: 21px; 492 | margin: -10px 0 0 0; 493 | padding: 1px; 494 | height: 20px; 495 | } 496 | .ui-dialog .ui-dialog-content { 497 | position: relative; 498 | border: 0; 499 | padding: .5em 1em; 500 | background: none; 501 | overflow: auto; 502 | } 503 | .ui-dialog .ui-dialog-buttonpane { 504 | text-align: left; 505 | border-width: 1px 0 0 0; 506 | background-image: none; 507 | margin-top: .5em; 508 | padding: .3em 1em .5em .4em; 509 | } 510 | .ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { 511 | float: right; 512 | } 513 | .ui-dialog .ui-dialog-buttonpane button { 514 | margin: .5em .4em .5em 0; 515 | cursor: pointer; 516 | } 517 | .ui-dialog .ui-resizable-se { 518 | width: 12px; 519 | height: 12px; 520 | right: -5px; 521 | bottom: -5px; 522 | background-position: 16px 16px; 523 | } 524 | .ui-draggable .ui-dialog-titlebar { 525 | cursor: move; 526 | } 527 | .ui-menu { 528 | list-style: none; 529 | padding: 2px; 530 | margin: 0; 531 | display: block; 532 | outline: none; 533 | } 534 | .ui-menu .ui-menu { 535 | margin-top: -3px; 536 | position: absolute; 537 | } 538 | .ui-menu .ui-menu-item { 539 | margin: 0; 540 | padding: 0; 541 | width: 100%; 542 | /* support: IE10, see #8844 */ 543 | list-style-image: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7); 544 | } 545 | .ui-menu .ui-menu-divider { 546 | margin: 5px -2px 5px -2px; 547 | height: 0; 548 | font-size: 0; 549 | line-height: 0; 550 | border-width: 1px 0 0 0; 551 | } 552 | .ui-menu .ui-menu-item a { 553 | text-decoration: none; 554 | display: block; 555 | padding: 2px .4em; 556 | line-height: 1.5; 557 | min-height: 0; /* support: IE7 */ 558 | font-weight: normal; 559 | } 560 | .ui-menu .ui-menu-item a.ui-state-focus, 561 | .ui-menu .ui-menu-item a.ui-state-active { 562 | font-weight: normal; 563 | margin: -1px; 564 | } 565 | 566 | .ui-menu .ui-state-disabled { 567 | font-weight: normal; 568 | margin: .4em 0 .2em; 569 | line-height: 1.5; 570 | } 571 | .ui-menu .ui-state-disabled a { 572 | cursor: default; 573 | } 574 | 575 | /* icon support */ 576 | .ui-menu-icons { 577 | position: relative; 578 | } 579 | .ui-menu-icons .ui-menu-item a { 580 | position: relative; 581 | padding-left: 2em; 582 | } 583 | 584 | /* left-aligned */ 585 | .ui-menu .ui-icon { 586 | position: absolute; 587 | top: .2em; 588 | left: .2em; 589 | } 590 | 591 | /* right-aligned */ 592 | .ui-menu .ui-menu-icon { 593 | position: static; 594 | float: right; 595 | } 596 | .ui-progressbar { 597 | height: 2em; 598 | text-align: left; 599 | overflow: hidden; 600 | } 601 | .ui-progressbar .ui-progressbar-value { 602 | margin: -1px; 603 | height: 100%; 604 | } 605 | .ui-progressbar .ui-progressbar-overlay { 606 | background: url("images/animated-overlay.gif"); 607 | height: 100%; 608 | filter: alpha(opacity=25); 609 | opacity: 0.25; 610 | } 611 | .ui-progressbar-indeterminate .ui-progressbar-value { 612 | background-image: none; 613 | } 614 | .ui-slider { 615 | position: relative; 616 | text-align: left; 617 | } 618 | .ui-slider .ui-slider-handle { 619 | position: absolute; 620 | z-index: 2; 621 | width: 1.2em; 622 | height: 1.2em; 623 | cursor: default; 624 | } 625 | .ui-slider .ui-slider-range { 626 | position: absolute; 627 | z-index: 1; 628 | font-size: .7em; 629 | display: block; 630 | border: 0; 631 | background-position: 0 0; 632 | } 633 | 634 | /* For IE8 - See #6727 */ 635 | .ui-slider.ui-state-disabled .ui-slider-handle, 636 | .ui-slider.ui-state-disabled .ui-slider-range { 637 | filter: inherit; 638 | } 639 | 640 | .ui-slider-horizontal { 641 | height: .8em; 642 | } 643 | .ui-slider-horizontal .ui-slider-handle { 644 | top: -.3em; 645 | margin-left: -.6em; 646 | } 647 | .ui-slider-horizontal .ui-slider-range { 648 | top: 0; 649 | height: 100%; 650 | } 651 | .ui-slider-horizontal .ui-slider-range-min { 652 | left: 0; 653 | } 654 | .ui-slider-horizontal .ui-slider-range-max { 655 | right: 0; 656 | } 657 | 658 | .ui-slider-vertical { 659 | width: .8em; 660 | height: 100px; 661 | } 662 | .ui-slider-vertical .ui-slider-handle { 663 | left: -.3em; 664 | margin-left: 0; 665 | margin-bottom: -.6em; 666 | } 667 | .ui-slider-vertical .ui-slider-range { 668 | left: 0; 669 | width: 100%; 670 | } 671 | .ui-slider-vertical .ui-slider-range-min { 672 | bottom: 0; 673 | } 674 | .ui-slider-vertical .ui-slider-range-max { 675 | top: 0; 676 | } 677 | .ui-spinner { 678 | position: relative; 679 | display: inline-block; 680 | overflow: hidden; 681 | padding: 0; 682 | vertical-align: middle; 683 | } 684 | .ui-spinner-input { 685 | border: none; 686 | background: none; 687 | color: inherit; 688 | padding: 0; 689 | margin: .2em 0; 690 | vertical-align: middle; 691 | margin-left: .4em; 692 | margin-right: 22px; 693 | } 694 | .ui-spinner-button { 695 | width: 16px; 696 | height: 50%; 697 | font-size: .5em; 698 | padding: 0; 699 | margin: 0; 700 | text-align: center; 701 | position: absolute; 702 | cursor: default; 703 | display: block; 704 | overflow: hidden; 705 | right: 0; 706 | } 707 | /* more specificity required here to overide default borders */ 708 | .ui-spinner a.ui-spinner-button { 709 | border-top: none; 710 | border-bottom: none; 711 | border-right: none; 712 | } 713 | /* vertical centre icon */ 714 | .ui-spinner .ui-icon { 715 | position: absolute; 716 | margin-top: -8px; 717 | top: 50%; 718 | left: 0; 719 | } 720 | .ui-spinner-up { 721 | top: 0; 722 | } 723 | .ui-spinner-down { 724 | bottom: 0; 725 | } 726 | 727 | /* TR overrides */ 728 | .ui-spinner .ui-icon-triangle-1-s { 729 | /* need to fix icons sprite */ 730 | background-position: -65px -16px; 731 | } 732 | .ui-tabs { 733 | position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ 734 | padding: .2em; 735 | } 736 | .ui-tabs .ui-tabs-nav { 737 | margin: 0; 738 | padding: .2em .2em 0; 739 | } 740 | .ui-tabs .ui-tabs-nav li { 741 | list-style: none; 742 | float: left; 743 | position: relative; 744 | top: 0; 745 | margin: 1px .2em 0 0; 746 | border-bottom-width: 0; 747 | padding: 0; 748 | white-space: nowrap; 749 | } 750 | .ui-tabs .ui-tabs-nav li a { 751 | float: left; 752 | padding: .5em 1em; 753 | text-decoration: none; 754 | } 755 | .ui-tabs .ui-tabs-nav li.ui-tabs-active { 756 | margin-bottom: -1px; 757 | padding-bottom: 1px; 758 | } 759 | .ui-tabs .ui-tabs-nav li.ui-tabs-active a, 760 | .ui-tabs .ui-tabs-nav li.ui-state-disabled a, 761 | .ui-tabs .ui-tabs-nav li.ui-tabs-loading a { 762 | cursor: text; 763 | } 764 | .ui-tabs .ui-tabs-nav li a, /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ 765 | .ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a { 766 | cursor: pointer; 767 | } 768 | .ui-tabs .ui-tabs-panel { 769 | display: block; 770 | border-width: 0; 771 | padding: 1em 1.4em; 772 | background: none; 773 | } 774 | .ui-tooltip { 775 | padding: 8px; 776 | position: absolute; 777 | z-index: 9999; 778 | max-width: 300px; 779 | -webkit-box-shadow: 0 0 5px #aaa; 780 | box-shadow: 0 0 5px #aaa; 781 | } 782 | body .ui-tooltip { 783 | border-width: 2px; 784 | } 785 | 786 | /* Component containers 787 | ----------------------------------*/ 788 | .ui-widget { 789 | font-family: Trebuchet MS,Tahoma,Verdana,Arial,sans-serif; 790 | font-size: 1.1em; 791 | } 792 | .ui-widget .ui-widget { 793 | font-size: 1em; 794 | } 795 | .ui-widget input, 796 | .ui-widget select, 797 | .ui-widget textarea, 798 | .ui-widget button { 799 | font-family: Trebuchet MS,Tahoma,Verdana,Arial,sans-serif; 800 | font-size: 1em; 801 | } 802 | .ui-widget-content { 803 | border: 1px solid #dddddd; 804 | background: #eeeeee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x; 805 | color: #333333; 806 | } 807 | .ui-widget-content a { 808 | color: #333333; 809 | } 810 | .ui-widget-header { 811 | border: 1px solid #e78f08; 812 | background: #f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x; 813 | color: #ffffff; 814 | font-weight: bold; 815 | } 816 | .ui-widget-header a { 817 | color: #ffffff; 818 | } 819 | 820 | /* Interaction states 821 | ----------------------------------*/ 822 | .ui-state-default, 823 | .ui-widget-content .ui-state-default, 824 | .ui-widget-header .ui-state-default { 825 | border: 1px solid #cccccc; 826 | background: #f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x; 827 | font-weight: bold; 828 | color: #1c94c4; 829 | } 830 | .ui-state-default a, 831 | .ui-state-default a:link, 832 | .ui-state-default a:visited { 833 | color: #1c94c4; 834 | text-decoration: none; 835 | } 836 | .ui-state-hover, 837 | .ui-widget-content .ui-state-hover, 838 | .ui-widget-header .ui-state-hover, 839 | .ui-state-focus, 840 | .ui-widget-content .ui-state-focus, 841 | .ui-widget-header .ui-state-focus { 842 | border: 1px solid #fbcb09; 843 | background: #fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x; 844 | font-weight: bold; 845 | color: #c77405; 846 | } 847 | .ui-state-hover a, 848 | .ui-state-hover a:hover, 849 | .ui-state-hover a:link, 850 | .ui-state-hover a:visited { 851 | color: #c77405; 852 | text-decoration: none; 853 | } 854 | .ui-state-active, 855 | .ui-widget-content .ui-state-active, 856 | .ui-widget-header .ui-state-active { 857 | border: 1px solid #fbd850; 858 | background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; 859 | font-weight: bold; 860 | color: #eb8f00; 861 | } 862 | .ui-state-active a, 863 | .ui-state-active a:link, 864 | .ui-state-active a:visited { 865 | color: #eb8f00; 866 | text-decoration: none; 867 | } 868 | 869 | /* Interaction Cues 870 | ----------------------------------*/ 871 | .ui-state-highlight, 872 | .ui-widget-content .ui-state-highlight, 873 | .ui-widget-header .ui-state-highlight { 874 | border: 1px solid #fed22f; 875 | background: #ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x; 876 | color: #363636; 877 | } 878 | .ui-state-highlight a, 879 | .ui-widget-content .ui-state-highlight a, 880 | .ui-widget-header .ui-state-highlight a { 881 | color: #363636; 882 | } 883 | .ui-state-error, 884 | .ui-widget-content .ui-state-error, 885 | .ui-widget-header .ui-state-error { 886 | border: 1px solid #cd0a0a; 887 | background: #b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat; 888 | color: #ffffff; 889 | } 890 | .ui-state-error a, 891 | .ui-widget-content .ui-state-error a, 892 | .ui-widget-header .ui-state-error a { 893 | color: #ffffff; 894 | } 895 | .ui-state-error-text, 896 | .ui-widget-content .ui-state-error-text, 897 | .ui-widget-header .ui-state-error-text { 898 | color: #ffffff; 899 | } 900 | .ui-priority-primary, 901 | .ui-widget-content .ui-priority-primary, 902 | .ui-widget-header .ui-priority-primary { 903 | font-weight: bold; 904 | } 905 | .ui-priority-secondary, 906 | .ui-widget-content .ui-priority-secondary, 907 | .ui-widget-header .ui-priority-secondary { 908 | opacity: .7; 909 | filter:Alpha(Opacity=70); 910 | font-weight: normal; 911 | } 912 | .ui-state-disabled, 913 | .ui-widget-content .ui-state-disabled, 914 | .ui-widget-header .ui-state-disabled { 915 | opacity: .35; 916 | filter:Alpha(Opacity=35); 917 | background-image: none; 918 | } 919 | .ui-state-disabled .ui-icon { 920 | filter:Alpha(Opacity=35); /* For IE8 - See #6059 */ 921 | } 922 | 923 | /* Icons 924 | ----------------------------------*/ 925 | 926 | /* states and images */ 927 | .ui-icon { 928 | width: 16px; 929 | height: 16px; 930 | } 931 | .ui-icon, 932 | .ui-widget-content .ui-icon { 933 | background-image: url(images/ui-icons_222222_256x240.png); 934 | } 935 | .ui-widget-header .ui-icon { 936 | background-image: url(images/ui-icons_ffffff_256x240.png); 937 | } 938 | .ui-state-default .ui-icon { 939 | background-image: url(images/ui-icons_ef8c08_256x240.png); 940 | } 941 | .ui-state-hover .ui-icon, 942 | .ui-state-focus .ui-icon { 943 | background-image: url(images/ui-icons_ef8c08_256x240.png); 944 | } 945 | .ui-state-active .ui-icon { 946 | background-image: url(images/ui-icons_ef8c08_256x240.png); 947 | } 948 | .ui-state-highlight .ui-icon { 949 | background-image: url(images/ui-icons_228ef1_256x240.png); 950 | } 951 | .ui-state-error .ui-icon, 952 | .ui-state-error-text .ui-icon { 953 | background-image: url(images/ui-icons_ffd27a_256x240.png); 954 | } 955 | 956 | /* positioning */ 957 | .ui-icon-blank { background-position: 16px 16px; } 958 | .ui-icon-carat-1-n { background-position: 0 0; } 959 | .ui-icon-carat-1-ne { background-position: -16px 0; } 960 | .ui-icon-carat-1-e { background-position: -32px 0; } 961 | .ui-icon-carat-1-se { background-position: -48px 0; } 962 | .ui-icon-carat-1-s { background-position: -64px 0; } 963 | .ui-icon-carat-1-sw { background-position: -80px 0; } 964 | .ui-icon-carat-1-w { background-position: -96px 0; } 965 | .ui-icon-carat-1-nw { background-position: -112px 0; } 966 | .ui-icon-carat-2-n-s { background-position: -128px 0; } 967 | .ui-icon-carat-2-e-w { background-position: -144px 0; } 968 | .ui-icon-triangle-1-n { background-position: 0 -16px; } 969 | .ui-icon-triangle-1-ne { background-position: -16px -16px; } 970 | .ui-icon-triangle-1-e { background-position: -32px -16px; } 971 | .ui-icon-triangle-1-se { background-position: -48px -16px; } 972 | .ui-icon-triangle-1-s { background-position: -64px -16px; } 973 | .ui-icon-triangle-1-sw { background-position: -80px -16px; } 974 | .ui-icon-triangle-1-w { background-position: -96px -16px; } 975 | .ui-icon-triangle-1-nw { background-position: -112px -16px; } 976 | .ui-icon-triangle-2-n-s { background-position: -128px -16px; } 977 | .ui-icon-triangle-2-e-w { background-position: -144px -16px; } 978 | .ui-icon-arrow-1-n { background-position: 0 -32px; } 979 | .ui-icon-arrow-1-ne { background-position: -16px -32px; } 980 | .ui-icon-arrow-1-e { background-position: -32px -32px; } 981 | .ui-icon-arrow-1-se { background-position: -48px -32px; } 982 | .ui-icon-arrow-1-s { background-position: -64px -32px; } 983 | .ui-icon-arrow-1-sw { background-position: -80px -32px; } 984 | .ui-icon-arrow-1-w { background-position: -96px -32px; } 985 | .ui-icon-arrow-1-nw { background-position: -112px -32px; } 986 | .ui-icon-arrow-2-n-s { background-position: -128px -32px; } 987 | .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } 988 | .ui-icon-arrow-2-e-w { background-position: -160px -32px; } 989 | .ui-icon-arrow-2-se-nw { background-position: -176px -32px; } 990 | .ui-icon-arrowstop-1-n { background-position: -192px -32px; } 991 | .ui-icon-arrowstop-1-e { background-position: -208px -32px; } 992 | .ui-icon-arrowstop-1-s { background-position: -224px -32px; } 993 | .ui-icon-arrowstop-1-w { background-position: -240px -32px; } 994 | .ui-icon-arrowthick-1-n { background-position: 0 -48px; } 995 | .ui-icon-arrowthick-1-ne { background-position: -16px -48px; } 996 | .ui-icon-arrowthick-1-e { background-position: -32px -48px; } 997 | .ui-icon-arrowthick-1-se { background-position: -48px -48px; } 998 | .ui-icon-arrowthick-1-s { background-position: -64px -48px; } 999 | .ui-icon-arrowthick-1-sw { background-position: -80px -48px; } 1000 | .ui-icon-arrowthick-1-w { background-position: -96px -48px; } 1001 | .ui-icon-arrowthick-1-nw { background-position: -112px -48px; } 1002 | .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } 1003 | .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } 1004 | .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } 1005 | .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } 1006 | .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } 1007 | .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } 1008 | .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } 1009 | .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } 1010 | .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } 1011 | .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } 1012 | .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } 1013 | .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } 1014 | .ui-icon-arrowreturn-1-w { background-position: -64px -64px; } 1015 | .ui-icon-arrowreturn-1-n { background-position: -80px -64px; } 1016 | .ui-icon-arrowreturn-1-e { background-position: -96px -64px; } 1017 | .ui-icon-arrowreturn-1-s { background-position: -112px -64px; } 1018 | .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } 1019 | .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } 1020 | .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } 1021 | .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } 1022 | .ui-icon-arrow-4 { background-position: 0 -80px; } 1023 | .ui-icon-arrow-4-diag { background-position: -16px -80px; } 1024 | .ui-icon-extlink { background-position: -32px -80px; } 1025 | .ui-icon-newwin { background-position: -48px -80px; } 1026 | .ui-icon-refresh { background-position: -64px -80px; } 1027 | .ui-icon-shuffle { background-position: -80px -80px; } 1028 | .ui-icon-transfer-e-w { background-position: -96px -80px; } 1029 | .ui-icon-transferthick-e-w { background-position: -112px -80px; } 1030 | .ui-icon-folder-collapsed { background-position: 0 -96px; } 1031 | .ui-icon-folder-open { background-position: -16px -96px; } 1032 | .ui-icon-document { background-position: -32px -96px; } 1033 | .ui-icon-document-b { background-position: -48px -96px; } 1034 | .ui-icon-note { background-position: -64px -96px; } 1035 | .ui-icon-mail-closed { background-position: -80px -96px; } 1036 | .ui-icon-mail-open { background-position: -96px -96px; } 1037 | .ui-icon-suitcase { background-position: -112px -96px; } 1038 | .ui-icon-comment { background-position: -128px -96px; } 1039 | .ui-icon-person { background-position: -144px -96px; } 1040 | .ui-icon-print { background-position: -160px -96px; } 1041 | .ui-icon-trash { background-position: -176px -96px; } 1042 | .ui-icon-locked { background-position: -192px -96px; } 1043 | .ui-icon-unlocked { background-position: -208px -96px; } 1044 | .ui-icon-bookmark { background-position: -224px -96px; } 1045 | .ui-icon-tag { background-position: -240px -96px; } 1046 | .ui-icon-home { background-position: 0 -112px; } 1047 | .ui-icon-flag { background-position: -16px -112px; } 1048 | .ui-icon-calendar { background-position: -32px -112px; } 1049 | .ui-icon-cart { background-position: -48px -112px; } 1050 | .ui-icon-pencil { background-position: -64px -112px; } 1051 | .ui-icon-clock { background-position: -80px -112px; } 1052 | .ui-icon-disk { background-position: -96px -112px; } 1053 | .ui-icon-calculator { background-position: -112px -112px; } 1054 | .ui-icon-zoomin { background-position: -128px -112px; } 1055 | .ui-icon-zoomout { background-position: -144px -112px; } 1056 | .ui-icon-search { background-position: -160px -112px; } 1057 | .ui-icon-wrench { background-position: -176px -112px; } 1058 | .ui-icon-gear { background-position: -192px -112px; } 1059 | .ui-icon-heart { background-position: -208px -112px; } 1060 | .ui-icon-star { background-position: -224px -112px; } 1061 | .ui-icon-link { background-position: -240px -112px; } 1062 | .ui-icon-cancel { background-position: 0 -128px; } 1063 | .ui-icon-plus { background-position: -16px -128px; } 1064 | .ui-icon-plusthick { background-position: -32px -128px; } 1065 | .ui-icon-minus { background-position: -48px -128px; } 1066 | .ui-icon-minusthick { background-position: -64px -128px; } 1067 | .ui-icon-close { background-position: -80px -128px; } 1068 | .ui-icon-closethick { background-position: -96px -128px; } 1069 | .ui-icon-key { background-position: -112px -128px; } 1070 | .ui-icon-lightbulb { background-position: -128px -128px; } 1071 | .ui-icon-scissors { background-position: -144px -128px; } 1072 | .ui-icon-clipboard { background-position: -160px -128px; } 1073 | .ui-icon-copy { background-position: -176px -128px; } 1074 | .ui-icon-contact { background-position: -192px -128px; } 1075 | .ui-icon-image { background-position: -208px -128px; } 1076 | .ui-icon-video { background-position: -224px -128px; } 1077 | .ui-icon-script { background-position: -240px -128px; } 1078 | .ui-icon-alert { background-position: 0 -144px; } 1079 | .ui-icon-info { background-position: -16px -144px; } 1080 | .ui-icon-notice { background-position: -32px -144px; } 1081 | .ui-icon-help { background-position: -48px -144px; } 1082 | .ui-icon-check { background-position: -64px -144px; } 1083 | .ui-icon-bullet { background-position: -80px -144px; } 1084 | .ui-icon-radio-on { background-position: -96px -144px; } 1085 | .ui-icon-radio-off { background-position: -112px -144px; } 1086 | .ui-icon-pin-w { background-position: -128px -144px; } 1087 | .ui-icon-pin-s { background-position: -144px -144px; } 1088 | .ui-icon-play { background-position: 0 -160px; } 1089 | .ui-icon-pause { background-position: -16px -160px; } 1090 | .ui-icon-seek-next { background-position: -32px -160px; } 1091 | .ui-icon-seek-prev { background-position: -48px -160px; } 1092 | .ui-icon-seek-end { background-position: -64px -160px; } 1093 | .ui-icon-seek-start { background-position: -80px -160px; } 1094 | /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ 1095 | .ui-icon-seek-first { background-position: -80px -160px; } 1096 | .ui-icon-stop { background-position: -96px -160px; } 1097 | .ui-icon-eject { background-position: -112px -160px; } 1098 | .ui-icon-volume-off { background-position: -128px -160px; } 1099 | .ui-icon-volume-on { background-position: -144px -160px; } 1100 | .ui-icon-power { background-position: 0 -176px; } 1101 | .ui-icon-signal-diag { background-position: -16px -176px; } 1102 | .ui-icon-signal { background-position: -32px -176px; } 1103 | .ui-icon-battery-0 { background-position: -48px -176px; } 1104 | .ui-icon-battery-1 { background-position: -64px -176px; } 1105 | .ui-icon-battery-2 { background-position: -80px -176px; } 1106 | .ui-icon-battery-3 { background-position: -96px -176px; } 1107 | .ui-icon-circle-plus { background-position: 0 -192px; } 1108 | .ui-icon-circle-minus { background-position: -16px -192px; } 1109 | .ui-icon-circle-close { background-position: -32px -192px; } 1110 | .ui-icon-circle-triangle-e { background-position: -48px -192px; } 1111 | .ui-icon-circle-triangle-s { background-position: -64px -192px; } 1112 | .ui-icon-circle-triangle-w { background-position: -80px -192px; } 1113 | .ui-icon-circle-triangle-n { background-position: -96px -192px; } 1114 | .ui-icon-circle-arrow-e { background-position: -112px -192px; } 1115 | .ui-icon-circle-arrow-s { background-position: -128px -192px; } 1116 | .ui-icon-circle-arrow-w { background-position: -144px -192px; } 1117 | .ui-icon-circle-arrow-n { background-position: -160px -192px; } 1118 | .ui-icon-circle-zoomin { background-position: -176px -192px; } 1119 | .ui-icon-circle-zoomout { background-position: -192px -192px; } 1120 | .ui-icon-circle-check { background-position: -208px -192px; } 1121 | .ui-icon-circlesmall-plus { background-position: 0 -208px; } 1122 | .ui-icon-circlesmall-minus { background-position: -16px -208px; } 1123 | .ui-icon-circlesmall-close { background-position: -32px -208px; } 1124 | .ui-icon-squaresmall-plus { background-position: -48px -208px; } 1125 | .ui-icon-squaresmall-minus { background-position: -64px -208px; } 1126 | .ui-icon-squaresmall-close { background-position: -80px -208px; } 1127 | .ui-icon-grip-dotted-vertical { background-position: 0 -224px; } 1128 | .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } 1129 | .ui-icon-grip-solid-vertical { background-position: -32px -224px; } 1130 | .ui-icon-grip-solid-horizontal { background-position: -48px -224px; } 1131 | .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } 1132 | .ui-icon-grip-diagonal-se { background-position: -80px -224px; } 1133 | 1134 | 1135 | /* Misc visuals 1136 | ----------------------------------*/ 1137 | 1138 | /* Corner radius */ 1139 | .ui-corner-all, 1140 | .ui-corner-top, 1141 | .ui-corner-left, 1142 | .ui-corner-tl { 1143 | border-top-left-radius: 4px; 1144 | } 1145 | .ui-corner-all, 1146 | .ui-corner-top, 1147 | .ui-corner-right, 1148 | .ui-corner-tr { 1149 | border-top-right-radius: 4px; 1150 | } 1151 | .ui-corner-all, 1152 | .ui-corner-bottom, 1153 | .ui-corner-left, 1154 | .ui-corner-bl { 1155 | border-bottom-left-radius: 4px; 1156 | } 1157 | .ui-corner-all, 1158 | .ui-corner-bottom, 1159 | .ui-corner-right, 1160 | .ui-corner-br { 1161 | border-bottom-right-radius: 4px; 1162 | } 1163 | 1164 | /* Overlays */ 1165 | .ui-widget-overlay { 1166 | background: #666666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat; 1167 | opacity: .5; 1168 | filter: Alpha(Opacity=50); 1169 | } 1170 | .ui-widget-shadow { 1171 | margin: -5px 0 0 -5px; 1172 | padding: 5px; 1173 | background: #000000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x; 1174 | opacity: .2; 1175 | filter: Alpha(Opacity=20); 1176 | border-radius: 5px; 1177 | } 1178 | -------------------------------------------------------------------------------- /app/assets/stylesheets/fullcalendar_engine/style.css: -------------------------------------------------------------------------------- 1 | body{ 2 | font-size: 12px; 3 | font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; 4 | } 5 | 6 | #loading{ 7 | position: absolute; 8 | right: 0px; 9 | top: 0px; 10 | background-color: #dd0000; 11 | font-weight:bold; 12 | color: white; 13 | margin: 5px; 14 | padding: 3px; 15 | } 16 | 17 | span > div#loading { 18 | position: fixed; 19 | } 20 | 21 | h1{ 22 | font-size: 16px; 23 | } 24 | -------------------------------------------------------------------------------- /app/controllers/fullcalendar_engine/application_controller.rb: -------------------------------------------------------------------------------- 1 | module FullcalendarEngine 2 | class ApplicationController < ActionController::Base 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/fullcalendar_engine/events_controller.rb: -------------------------------------------------------------------------------- 1 | require_dependency 'fullcalendar_engine/application_controller' 2 | 3 | module FullcalendarEngine 4 | class EventsController < ApplicationController 5 | 6 | layout FullcalendarEngine::Configuration['layout'] || 'application' 7 | 8 | before_filter :load_event, only: [:edit, :update, :destroy, :move, :resize] 9 | before_filter :determine_event_type, only: :create 10 | 11 | def create 12 | if @event.save 13 | render nothing: true 14 | else 15 | render text: @event.errors.full_messages.to_sentence, status: 422 16 | end 17 | end 18 | 19 | def new 20 | respond_to do |format| 21 | format.js 22 | end 23 | end 24 | 25 | def get_events 26 | start_time = Time.at(params[:start].to_i).to_formatted_s(:db) 27 | end_time = Time.at(params[:end].to_i).to_formatted_s(:db) 28 | 29 | @events = Event.where(' 30 | (starttime >= :start_time and endtime <= :end_time) or 31 | (starttime >= :start_time and endtime > :end_time and starttime <= :end_time) or 32 | (starttime <= :start_time and endtime >= :start_time and endtime <= :end_time) or 33 | (starttime <= :start_time and endtime > :end_time)', 34 | start_time: start_time, end_time: end_time) 35 | events = [] 36 | @events.each do |event| 37 | events << { id: event.id, 38 | title: event.title, 39 | description: event.description || '', 40 | start: event.starttime.iso8601, 41 | end: event.endtime.iso8601, 42 | allDay: event.all_day, 43 | recurring: (event.event_series_id) ? true : false } 44 | end 45 | render json: events.to_json 46 | end 47 | 48 | def move 49 | if @event 50 | @event.starttime = make_time_from_minute_and_day_delta(@event.starttime) 51 | @event.endtime = make_time_from_minute_and_day_delta(@event.endtime) 52 | @event.all_day = params[:all_day] 53 | @event.save 54 | end 55 | render nothing: true 56 | end 57 | 58 | def resize 59 | if @event 60 | @event.endtime = make_time_from_minute_and_day_delta(@event.endtime) 61 | @event.save 62 | end 63 | render nothing: true 64 | end 65 | 66 | def edit 67 | render json: { form: render_to_string(partial: 'edit_form') } 68 | end 69 | 70 | def update 71 | case params[:event][:commit_button] 72 | when 'Update All Occurrence' 73 | @events = @event.event_series.events 74 | @event.update_events(@events, event_params) 75 | when 'Update All Following Occurrence' 76 | @events = @event.event_series.events.where('starttime > :start_time', 77 | start_time: @event.starttime.to_formatted_s(:db)).to_a 78 | @event.update_events(@events, event_params) 79 | else 80 | @event.attributes = event_params 81 | @event.save 82 | end 83 | render nothing: true 84 | end 85 | 86 | def destroy 87 | case params[:delete_all] 88 | when 'true' 89 | @event.event_series.destroy 90 | when 'future' 91 | @events = @event.event_series.events.where('starttime > :start_time', 92 | start_time: @event.starttime.to_formatted_s(:db)).to_a 93 | @event.event_series.events.delete(@events) 94 | else 95 | @event.destroy 96 | end 97 | render nothing: true 98 | end 99 | 100 | private 101 | 102 | def load_event 103 | @event = Event.where(:id => params[:id]).first 104 | unless @event 105 | render json: { message: "Event Not Found.."}, status: 404 and return 106 | end 107 | end 108 | 109 | def event_params 110 | params.require(:event).permit('title', 'description', 'starttime', 'endtime', 'all_day', 'period', 'frequency', 'commit_button') 111 | end 112 | 113 | def determine_event_type 114 | if params[:event][:period] == "Does not repeat" 115 | @event = Event.new(event_params) 116 | else 117 | @event = EventSeries.new(event_params) 118 | end 119 | end 120 | 121 | def make_time_from_minute_and_day_delta(event_time) 122 | params[:minute_delta].to_i.minutes.from_now((params[:day_delta].to_i).days.from_now(event_time)) 123 | end 124 | end 125 | end 126 | -------------------------------------------------------------------------------- /app/models/fullcalendar_engine/event.rb: -------------------------------------------------------------------------------- 1 | module FullcalendarEngine 2 | class Event < ActiveRecord::Base 3 | 4 | attr_accessor :period, :frequency, :commit_button 5 | 6 | validates :title, :description, :starttime, :endtime, :presence => true 7 | validate :validate_timings 8 | 9 | belongs_to :event_series 10 | 11 | REPEATS = { 12 | :no_repeat => "Does not repeat", 13 | :days => "Daily", 14 | :weeks => "Weekly", 15 | :months => "Monthly", 16 | :years => "Yearly" 17 | } 18 | 19 | def validate_timings 20 | if starttime.present? and endtime.present? 21 | if (starttime >= endtime) and !all_day 22 | errors[:base] << "Start Time must be less than End Time" 23 | end 24 | end 25 | end 26 | 27 | def update_events(events, event) 28 | events.each do |e| 29 | begin 30 | old_start_time, old_end_time = e.starttime, e.endtime 31 | e.attributes = event 32 | if event_series.period.downcase == 'monthly' or event_series.period.downcase == 'yearly' 33 | new_start_time = make_date_time(e.starttime, old_start_time) 34 | new_end_time = make_date_time(e.starttime, old_end_time, e.endtime) 35 | else 36 | new_start_time = make_date_time(e.starttime, old_end_time) 37 | new_end_time = make_date_time(e.endtime, old_end_time) 38 | end 39 | rescue 40 | new_start_time = new_end_time = nil 41 | end 42 | if new_start_time and new_end_time 43 | e.starttime, e.endtime = new_start_time, new_end_time 44 | e.save 45 | end 46 | end 47 | 48 | event_series.attributes = event 49 | event_series.save 50 | end 51 | 52 | private 53 | 54 | def make_date_time(original_time, difference_time, event_time = nil) 55 | DateTime.parse("#{original_time.hour}:#{original_time.min}:#{original_time.sec}, #{event_time.try(:day) || difference_time.day}-#{difference_time.month}-#{difference_time.year}") 56 | end 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /app/models/fullcalendar_engine/event_series.rb: -------------------------------------------------------------------------------- 1 | module FullcalendarEngine 2 | class EventSeries < ActiveRecord::Base 3 | 4 | attr_accessor :title, :description, :commit_button 5 | 6 | validates :frequency, :period, :starttime, :endtime, :title, :description, :presence => true 7 | 8 | has_many :events, :dependent => :destroy 9 | 10 | after_create :create_events_until_end_time 11 | 12 | def create_events_until_end_time(end_time=RECURRING_EVENTS_UPTO) 13 | old_start_time = starttime 14 | old_end_time = endtime 15 | frequency_period = recurring_period(period) 16 | new_start_time, new_end_time = old_start_time, old_end_time 17 | 18 | while frequency.send(frequency_period).from_now(old_start_time) <= end_time 19 | self.events.create( 20 | :title => title, 21 | :description => description, 22 | :all_day => all_day, 23 | :starttime => new_start_time, 24 | :endtime => new_end_time 25 | ) 26 | new_start_time = old_start_time = frequency.send(frequency_period).from_now(old_start_time) 27 | new_end_time = old_end_time = frequency.send(frequency_period).from_now(old_end_time) 28 | 29 | if period.downcase == 'monthly' or period.downcase == 'yearly' 30 | begin 31 | new_start_time = make_date_time(starttime, old_start_time) 32 | new_end_time = make_date_time(endtime, old_end_time) 33 | rescue 34 | new_start_time = new_end_time = nil 35 | end 36 | end 37 | end 38 | end 39 | 40 | def recurring_period(period) 41 | Event::REPEATS.key(period.titleize).to_s.downcase 42 | end 43 | 44 | private 45 | 46 | def make_date_time(original_time, difference_time) 47 | DateTime.parse("#{original_time.hour}:#{original_time.min}:#{original_time.sec}, #{original_time.day}-#{difference_time.month}-#{difference_time.year}") 48 | end 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /app/views/fullcalendar_engine/events/_edit_form.html.erb: -------------------------------------------------------------------------------- 1 | <%= form_for @event, :html => { :id => 'event_form' } do |f| %> 2 |

3 | <%=f.label :title %> 4 |
5 | <%=f.text_field :title %> 6 |

7 |

8 | <%=f.label :description %> 9 |
10 | <%=f.text_area :description, :rows => 4, :cols => 30 %> 11 |

12 |

13 | <%=f.label :starttime, 'Start Time' %> 14 |
15 | <%=f.datetime_select :starttime %> 16 |

17 |

18 | <%=f.label :endtime, 'End Time' %> 19 |
20 | <%=f.datetime_select :endtime %> 21 |

22 |

23 | <%=f.label :all_day %> 24 | <%=f.check_box :all_day %> 25 |

26 | 27 | <%=f.hidden_field :commit_button, :value => ""%> 28 |

29 | <%if @event.event_series -%> 30 | <%=f.submit 'Update Only This Occurrence', :onclick => "document.getElementById('event_commit_button').value = this.value"%> 31 | <%=f.submit 'Update All Occurrence', :onclick => "document.getElementById('event_commit_button').value = this.value"%> 32 | <%=f.submit 'Update All Following Occurrence', :onclick => "document.getElementById('event_commit_button').value = this.value"%> 33 | <%else-%> 34 | <%=f.submit 'Update', :onclick => "document.getElementById('event_commit_button').value = this.value"%> 35 | <%end-%> 36 | 37 | 38 |

39 | <%end %> -------------------------------------------------------------------------------- /app/views/fullcalendar_engine/events/_form.html.erb: -------------------------------------------------------------------------------- 1 | <%= form_for @event ||= FullcalendarEngine::Event.new, :html => { id: 'event_form' } do |f| %> 2 |

3 | <%=f.label :title %> 4 |
5 | <%=f.text_field :title %> 6 |

7 |

8 | <%=f.label :description %> 9 |
10 | <%=f.text_area :description, :rows => 4, :cols => 30 %> 11 |

12 |

13 | <%=f.label :starttime, 'Start Time' %> 14 |
15 | <%=f.datetime_select :starttime %> 16 |

17 |

18 | <%=f.label :endtime, 'End Time' %> 19 |
20 | <%=f.datetime_select :endtime %> 21 |

22 |

23 | <%=f.label :all_day %> 24 | <%=f.check_box :all_day %> 25 |

26 |

27 | <%=f.label :period, "Repeats" %> 28 | <%=f.select :period, FullcalendarEngine::Event::REPEATS.values, {}, onchange: "FullcalendarEngine.Events.showPeriodAndFrequency(this.value);" %> 29 |

30 | 34 |

35 | <%=f.submit %> 36 |

37 | <%end %> -------------------------------------------------------------------------------- /app/views/fullcalendar_engine/events/index.html.erb: -------------------------------------------------------------------------------- 1 |

2 | <%= link_to 'Create Event', 'javascript:void()', id: 'new_event' %> 3 |

4 |
5 |
6 |
7 | 8 | 11 | 12 | 22 | -------------------------------------------------------------------------------- /app/views/fullcalendar_engine/events/new.js.erb: -------------------------------------------------------------------------------- 1 | $("#create_event_dialog").html("<%= escape_javascript( render partial: 'form') %>") 2 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # This command will automatically be run when you run "rails" with Rails 4 gems installed from the root of your application. 3 | 4 | ENGINE_ROOT = File.expand_path('../..', __FILE__) 5 | ENGINE_PATH = File.expand_path('../../lib/fullcalendar_engine/engine', __FILE__) 6 | 7 | require 'rails/all' 8 | require 'rails/engine/commands' 9 | -------------------------------------------------------------------------------- /config/full-calendar.yml.dummy: -------------------------------------------------------------------------------- 1 | # Refer to the http://arshaw.com/fullcalendar/docs/ to know more about the following options in greater depth 2 | # defaultView: 'agendaWeek' 3 | # aspectRatio: 1.35 4 | # header: 5 | # left: 'prev,next today' 6 | # center: 'title' 7 | # right: 'month,agendaWeek,agendaDay' 8 | # weekends: true 9 | # weekNumbers: false 10 | # weekNumberCalculation: 'iso' 11 | # weekNumberTitle: 'W' 12 | 13 | # editable: true 14 | # disableDragging: false 15 | # disableResizing: false 16 | # allDayDefault: true 17 | # ignoreTimezone: true 18 | 19 | # lazyFetching: true 20 | # startParam: 'start' 21 | # endParam: 'end' 22 | 23 | # titleFormat: 24 | # month: 'MMMM yyyy' 25 | # week: "MMM d[ yyyy]{ '—'[ MMM] d yyyy}" 26 | # day: 'dddd, MMM d, yyyy' 27 | # columnFormat: 28 | # month: 'ddd' 29 | # week: 'ddd M/d' 30 | # day: 'dddd M/d' 31 | # timeFormat: 32 | # '': 'h(:mm)t' # default 33 | 34 | # isRTL: false 35 | # firstDay: 0 36 | # monthNames: ['January','February','March','April','May','June','July','August','September','October','November','December'] 37 | # monthNamesShort: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'] 38 | # dayNames: ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'] 39 | # dayNamesShort: ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'] 40 | # buttonText: 41 | # prev: "prev.." 42 | # next: "next.." 43 | # prevYear: "«" 44 | # nextYear: "»" 45 | # today: 'today' 46 | # month: 'month' 47 | # week: 'week' 48 | # day: 'day' 49 | 50 | # theme: false 51 | # buttonIcons: 52 | # prev: 'circle-triangle-w' 53 | # next: 'circle-triangle-e' 54 | # selectable: true 55 | # unselectAuto: true 56 | # dropAccept: '*' 57 | # handleWindowResize: true -------------------------------------------------------------------------------- /config/initializers/configuration.rb: -------------------------------------------------------------------------------- 1 | FULLCALENDAR_FILE_PATH = Rails.root.join('config', 'fullcalendar.yml') 2 | config = File.exists?(FULLCALENDAR_FILE_PATH) ? YAML.load_file(FULLCALENDAR_FILE_PATH) || {} : {} 3 | FullcalendarEngine::Configuration = { 4 | 'editable' => true, 5 | 'header' => { 6 | left: 'prev,next today', 7 | center: 'title', 8 | right: 'month,agendaWeek,agendaDay' 9 | }, 10 | 'defaultView' => 'agendaWeek', 11 | 'height' => 500, 12 | 'slotMinutes' => 15, 13 | 'dragOpacity' => 0.5, 14 | 'selectable' => true, 15 | 'timeFormat' => "h:mm t{ - h:mm t}" 16 | } 17 | FullcalendarEngine::Configuration.merge!(config) 18 | FullcalendarEngine::Configuration['events'] = "#{FullcalendarEngine::Configuration['mount_path']}/events/get_events" 19 | -------------------------------------------------------------------------------- /config/initializers/constants.rb: -------------------------------------------------------------------------------- 1 | RECURRING_EVENTS_UPTO = (Date.today.beginning_of_year + 5.years).to_time -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | FullcalendarEngine::Engine.routes.draw do 2 | resources :events do 3 | collection do 4 | get :get_events 5 | end 6 | member do 7 | post :move 8 | post :resize 9 | end 10 | end 11 | root :to => 'events#index' 12 | end -------------------------------------------------------------------------------- /db/migrate/20131203105320_create_fullcalendar_engine_events.rb: -------------------------------------------------------------------------------- 1 | class CreateFullcalendarEngineEvents < ActiveRecord::Migration 2 | def change 3 | create_table :fullcalendar_engine_events do |t| 4 | t.string :title 5 | t.datetime :starttime, :endtime 6 | t.boolean :all_day, :default => false 7 | t.text :description 8 | t.integer :event_series_id 9 | t.timestamps 10 | end 11 | add_index :fullcalendar_engine_events, :event_series_id 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/migrate/20131203105529_create_fullcalendar_engine_event_series.rb: -------------------------------------------------------------------------------- 1 | class CreateFullcalendarEngineEventSeries < ActiveRecord::Migration 2 | def change 3 | create_table :fullcalendar_engine_event_series do |t| 4 | t.integer :frequency, :default => 1 5 | t.string :period, :default => 'monthly' 6 | t.datetime :starttime 7 | t.datetime :endtime 8 | t.boolean :all_day, :default => false 9 | t.timestamps 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /fullcalendar_engine.gemspec: -------------------------------------------------------------------------------- 1 | $:.push File.expand_path("../lib", __FILE__) 2 | 3 | require "fullcalendar_engine/version" 4 | 5 | Gem::Specification.new do |s| 6 | s.name = "fullcalendar_engine" 7 | s.version = FullcalendarEngine::VERSION 8 | s.license = 'MIT' 9 | s.authors = ["Mohit Bansal", "Aditya Kapoor", "Shubham Gupta"] 10 | s.email = ["info@vinsol.com"] 11 | s.homepage = "http://vinsol.com" 12 | s.summary = "Engine Implementation of jQuery Full Calendar" 13 | s.description = "Engine Implementation of jQuery Full Calendar" 14 | 15 | s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.rdoc"] 16 | s.test_files = Dir["test/**/*"] 17 | 18 | s.add_dependency "rails", ">= 4.0.0" 19 | end 20 | -------------------------------------------------------------------------------- /lib/fullcalendar_engine.rb: -------------------------------------------------------------------------------- 1 | require "fullcalendar_engine/engine" 2 | 3 | module FullcalendarEngine 4 | end 5 | -------------------------------------------------------------------------------- /lib/fullcalendar_engine/engine.rb: -------------------------------------------------------------------------------- 1 | module FullcalendarEngine 2 | class Engine < ::Rails::Engine 3 | isolate_namespace FullcalendarEngine 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/fullcalendar_engine/version.rb: -------------------------------------------------------------------------------- 1 | module FullcalendarEngine 2 | VERSION = "1.0.6" 3 | end 4 | -------------------------------------------------------------------------------- /lib/generators/fullcalendar_engine/install/install_generator.rb: -------------------------------------------------------------------------------- 1 | module FullcalendarEngine 2 | module Generators 3 | class InstallGenerator < Rails::Generators::Base 4 | 5 | class_option :auto_run_migrations, type: :boolean, default: false 6 | 7 | ASSET_BASE_PATH = 'app/assets' 8 | JS_BASE_PATH = "#{ASSET_BASE_PATH}/javascripts" 9 | CSS_BASE_PATH = "#{ASSET_BASE_PATH}/stylesheets" 10 | 11 | def add_javascripts 12 | if File.exist?("#{JS_BASE_PATH}/application.js") 13 | append_file "#{JS_BASE_PATH}/application.js", "//= require fullcalendar_engine/application\n" 14 | elsif File.exist?("#{JS_BASE_PATH}/application.js.coffee") 15 | append_file "#{JS_BASE_PATH}/application.js.coffee", "//= require fullcalendar_engine/application\n" 16 | end 17 | end 18 | 19 | def add_stylesheets 20 | if File.exist?("#{CSS_BASE_PATH}/application.css") 21 | inject_into_file "#{CSS_BASE_PATH}/application.css", " *= require fullcalendar_engine/application\n", :before => /\*\//, :verbose => true 22 | elsif File.exist?("#{CSS_BASE_PATH}/application.css.scss") 23 | inject_into_file "#{CSS_BASE_PATH}/application.css.scss", " *= require fullcalendar_engine/application\n", :before => /\*\//, :verbose => true 24 | end 25 | end 26 | 27 | def add_migrations 28 | run 'bundle exec rake railties:install:migrations FROM=fullcalendar_engine' 29 | end 30 | 31 | def run_migrations 32 | run_migrations = options[:auto_run_migrations] || ['', 'y', 'Y'].include?(ask 'Would you like to run the migrations now? [Y/n]') 33 | if run_migrations 34 | run 'bundle exec rake db:migrate' 35 | else 36 | puts 'Skipping rake db:migrate, don\'t forget to run it!' 37 | end 38 | end 39 | end 40 | end 41 | end -------------------------------------------------------------------------------- /lib/tasks/fullcalendar_engine_tasks.rake: -------------------------------------------------------------------------------- 1 | # desc "Explaining what the task does" 2 | # task :fullcalendar_engine do 3 | # # Task goes here 4 | # end 5 | -------------------------------------------------------------------------------- /test/controllers/fullcalendar_engine/events_controller_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | module FullcalendarEngine 4 | class EventsControllerTest < ActionController::TestCase 5 | # test "the truth" do 6 | # assert true 7 | # end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /test/fixtures/fullcalendar_engine/event_series.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html 2 | 3 | # This model initially had no columns defined. If you add columns to the 4 | # model remove the '{}' from the fixture names and add the columns immediately 5 | # below each fixture, per the syntax in the comments below 6 | # 7 | one: {} 8 | # column: value 9 | # 10 | two: {} 11 | # column: value 12 | -------------------------------------------------------------------------------- /test/fixtures/fullcalendar_engine/events.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html 2 | 3 | # This model initially had no columns defined. If you add columns to the 4 | # model remove the '{}' from the fixture names and add the columns immediately 5 | # below each fixture, per the syntax in the comments below 6 | # 7 | one: {} 8 | # column: value 9 | # 10 | two: {} 11 | # column: value 12 | -------------------------------------------------------------------------------- /test/fullcalendar_engine_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class FullcalendarEngineTest < ActiveSupport::TestCase 4 | test "truth" do 5 | assert_kind_of Module, FullcalendarEngine 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /test/helpers/fullcalendar_engine/events_helper_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | module FullcalendarEngine 4 | class EventsHelperTest < ActionView::TestCase 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /test/integration/navigation_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class NavigationTest < ActionDispatch::IntegrationTest 4 | fixtures :all 5 | 6 | # test "the truth" do 7 | # assert true 8 | # end 9 | end 10 | 11 | -------------------------------------------------------------------------------- /test/models/fullcalendar_engine/event_series_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | module FullcalendarEngine 4 | class EventSeriesTest < ActiveSupport::TestCase 5 | # test "the truth" do 6 | # assert true 7 | # end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /test/models/fullcalendar_engine/event_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | module FullcalendarEngine 4 | class EventTest < ActiveSupport::TestCase 5 | # test "the truth" do 6 | # assert true 7 | # end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | # Configure Rails Environment 2 | ENV["RAILS_ENV"] = "test" 3 | 4 | require File.expand_path("../dummy/config/environment.rb", __FILE__) 5 | require "rails/test_help" 6 | 7 | Rails.backtrace_cleaner.remove_silencers! 8 | 9 | # Load support files 10 | Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f } 11 | 12 | # Load fixtures from the engine 13 | if ActiveSupport::TestCase.method_defined?(:fixture_path=) 14 | ActiveSupport::TestCase.fixture_path = File.expand_path("../fixtures", __FILE__) 15 | end 16 | --------------------------------------------------------------------------------