droom 0.4.3 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/app/assets/images/droom/admin_menu.png +0 -0
- data/app/assets/images/droom/applications_menu.png +0 -0
- data/app/assets/images/droom/arrows_small.png +0 -0
- data/app/assets/images/droom/config_menu.png +0 -0
- data/app/assets/images/droom/dropdown.png +0 -0
- data/app/assets/images/droom/menu/asterisk.png +0 -0
- data/app/assets/images/droom/{smalladd.png → menu/smalladd.png} +0 -0
- data/app/assets/images/droom/{small_asterisk.png → menu/smallasterisk.png} +0 -0
- data/app/assets/images/droom/{smalldelete.png → menu/smalldelete.png} +0 -0
- data/app/assets/images/droom/{smalldownload.png → menu/smalldownload.png} +0 -0
- data/app/assets/images/droom/{smalledit.png → menu/smalledit.png} +0 -0
- data/app/assets/images/droom/message.png +0 -0
- data/app/assets/images/droom/missing/scrap.jpg +0 -0
- data/app/assets/images/droom/missing/scrap.png +0 -0
- data/app/assets/images/droom/missing/thumb.png +0 -0
- data/app/assets/images/droom/missing/user.png +0 -0
- data/app/assets/images/droom/object_icons.png +0 -0
- data/app/assets/images/droom/panel/add.png +0 -0
- data/app/assets/images/droom/panel/edit.png +0 -0
- data/app/assets/images/droom/panel/manage.png +0 -0
- data/app/assets/images/droom/pointer_upwards.png +0 -0
- data/app/assets/images/droom/search_menu.png +0 -0
- data/app/assets/images/droom/setter.png +0 -0
- data/app/assets/images/droom/small_icons.png +0 -0
- data/app/assets/images/droom/stream/closer.png +0 -0
- data/app/assets/images/droom/stream/next.png +0 -0
- data/app/assets/images/droom/stream/prev.png +0 -0
- data/app/assets/images/droom/stream/previous.png +0 -0
- data/app/assets/images/droom/subscribe.png +0 -0
- data/app/assets/javascripts/droom.js.coffee +23 -13
- data/app/assets/javascripts/droom/actions.js.coffee +104 -10
- data/app/assets/javascripts/droom/ajax.js.coffee +36 -24
- data/app/assets/javascripts/droom/extensions.js.coffee +13 -0
- data/app/assets/javascripts/droom/lib/jquery.datepicker.js +1026 -0
- data/app/assets/javascripts/droom/lib/jquery.deserialize.js +142 -0
- data/app/assets/javascripts/droom/lib/jquery_ujs.js +416 -0
- data/app/assets/javascripts/droom/lib/swipe.js +568 -0
- data/app/assets/javascripts/droom/lib/underscore.js +1276 -0
- data/app/assets/javascripts/droom/popups.js.coffee +98 -37
- data/app/assets/javascripts/droom/stream.js.coffee +119 -77
- data/app/assets/javascripts/droom/utilities.js.coffee +25 -3
- data/app/assets/javascripts/droom/widgets.js.coffee +318 -253
- data/app/assets/stylesheets/droom.css.sass +482 -955
- data/app/assets/stylesheets/droom/_mixins.css.sass +12 -42
- data/app/assets/stylesheets/droom/_popups.css.sass +28 -11
- data/app/assets/stylesheets/droom/_stream.css.sass +375 -0
- data/app/assets/stylesheets/droom/_toolbar.css.sass +0 -6
- data/app/assets/stylesheets/droom/_variables.css.sass +4 -2
- data/app/controllers/droom/agenda_categories_controller.rb +6 -14
- data/app/controllers/droom/api/api_controller.rb +56 -0
- data/app/controllers/droom/api/events_controller.rb +74 -0
- data/app/controllers/droom/api/users_controller.rb +92 -0
- data/app/controllers/droom/api/venues_controller.rb +71 -0
- data/app/controllers/droom/calendars_controller.rb +4 -10
- data/app/controllers/droom/{user_confirmations_controller.rb → confirmations_controller.rb} +8 -7
- data/app/controllers/droom/dashboard_controller.rb +2 -19
- data/app/controllers/droom/documents_controller.rb +12 -60
- data/app/controllers/droom/dropbox_tokens_controller.rb +3 -4
- data/app/controllers/droom/engine_controller.rb +39 -11
- data/app/controllers/droom/events_controller.rb +62 -84
- data/app/controllers/droom/folders_controller.rb +30 -40
- data/app/controllers/droom/group_invitations_controller.rb +6 -23
- data/app/controllers/droom/group_permissions_controller.rb +26 -0
- data/app/controllers/droom/groups_controller.rb +10 -14
- data/app/controllers/droom/invitations_controller.rb +7 -25
- data/app/controllers/droom/memberships_controller.rb +13 -18
- data/app/controllers/droom/organisations_controller.rb +6 -25
- data/app/controllers/droom/permissions_controller.rb +50 -0
- data/app/controllers/droom/preferences_controller.rb +9 -10
- data/app/controllers/droom/scraps_controller.rb +23 -26
- data/app/controllers/droom/services_controller.rb +50 -0
- data/app/controllers/droom/suggestions_controller.rb +6 -4
- data/app/controllers/droom/users/confirmations_controller.rb +24 -0
- data/app/controllers/droom/users/passwords_controller.rb +39 -0
- data/app/controllers/droom/users/sessions_controller.rb +7 -0
- data/app/controllers/droom/users_controller.rb +60 -38
- data/app/controllers/droom/venues_controller.rb +8 -15
- data/app/controllers/droom/youtube_controller.rb +1 -1
- data/app/helpers/droom/droom_helper.rb +22 -17
- data/app/models/droom/ability.rb +81 -0
- data/app/models/droom/agenda_category.rb +0 -1
- data/app/models/droom/calendar.rb +12 -7
- data/app/models/droom/category.rb +4 -10
- data/app/models/droom/concerns/slugged.rb +21 -0
- data/app/models/droom/document.rb +15 -17
- data/app/models/droom/dropbox_document.rb +3 -6
- data/app/models/droom/dropbox_token.rb +2 -3
- data/app/models/droom/event.rb +117 -163
- data/app/models/droom/event_type.rb +25 -0
- data/app/models/droom/folder.rb +36 -48
- data/app/models/droom/group.rb +35 -27
- data/app/models/droom/group_invitation.rb +7 -10
- data/app/models/droom/group_permission.rb +29 -0
- data/app/models/droom/invitation.rb +14 -23
- data/app/models/droom/mailing_list_membership.rb +0 -1
- data/app/models/droom/membership.rb +32 -31
- data/app/models/droom/organisation.rb +6 -3
- data/app/models/droom/permission.rb +19 -0
- data/app/models/droom/personal_folder.rb +9 -21
- data/app/models/droom/preference.rb +1 -2
- data/app/models/droom/scrap.rb +31 -26
- data/app/models/droom/service.rb +31 -0
- data/app/models/droom/tag.rb +10 -9
- data/app/models/droom/tagging.rb +1 -1
- data/app/models/droom/user.rb +453 -130
- data/app/models/droom/user_permission.rb +8 -0
- data/app/models/droom/venue.rb +21 -32
- data/app/serializers/droom/user_serializer.rb +45 -0
- data/app/serializers/droom/venue_serializer.rb +5 -0
- data/app/views/droom/dashboard/_documents.html.haml +1 -1
- data/app/views/droom/dashboard/_folders.html.haml +1 -1
- data/app/views/droom/dashboard/_future_events.html.haml +10 -8
- data/app/views/droom/dashboard/_groups.html.haml +1 -1
- data/app/views/droom/dashboard/_past_events.haml +19 -12
- data/app/views/droom/dashboard/_stream.html.haml +2 -2
- data/app/views/droom/{users/_extra_columns.html.haml → dashboard/_welcome.html.haml} +0 -0
- data/app/views/droom/dashboard/index.html.haml +3 -0
- data/app/views/droom/documents/_document.html.haml +0 -2
- data/app/views/droom/documents/_documents.html.haml +1 -1
- data/app/views/droom/documents/_documents_list.html.haml +1 -1
- data/app/views/droom/documents/_documents_table.html.haml +1 -1
- data/app/views/droom/documents/_form.html.haml +8 -5
- data/app/views/droom/documents/_listing.html.haml +4 -2
- data/app/views/droom/documents/index.html.haml +13 -7
- data/app/views/droom/documents/new.html.haml +1 -4
- data/app/views/droom/events/_action_menu.html.haml +2 -2
- data/app/views/droom/events/_attachments.html.haml +8 -0
- data/app/views/droom/events/_calendar.html.haml +4 -8
- data/app/views/droom/events/_event.html.haml +44 -63
- data/app/views/droom/events/_event_line.html.haml +1 -1
- data/app/views/droom/events/_events.html.haml +18 -2
- data/app/views/droom/events/_form.html.haml +26 -19
- data/app/views/droom/events/_invitations.html.haml +7 -3
- data/app/views/droom/events/_scrap_events.html.haml +8 -0
- data/app/views/droom/events/_suggested.html.haml +4 -1
- data/app/views/droom/events/calendar.html.haml +8 -0
- data/app/views/droom/events/index.html.haml +24 -26
- data/app/views/droom/events/show.html.haml +6 -6
- data/app/views/droom/folders/_contents.html.haml +34 -4
- data/app/views/droom/folders/_folder.html.haml +7 -2
- data/app/views/droom/folders/_form.html.haml +11 -8
- data/app/views/droom/folders/index.html.haml +19 -22
- data/app/views/droom/group_invitations/_attending_groups.html.haml +1 -1
- data/app/views/droom/group_permissions/_toggle.html.haml +18 -0
- data/app/views/droom/groups/_action_menu.haml +0 -2
- data/app/views/droom/groups/_created.html.haml +0 -1
- data/app/views/droom/groups/_form.html.haml +3 -0
- data/app/views/droom/groups/_group.html.haml +10 -8
- data/app/views/droom/groups/_groups.html.haml +1 -1
- data/app/views/droom/groups/_search_result.html.haml +1 -1
- data/app/views/droom/groups/_suggested.html.haml +1 -1
- data/app/views/droom/groups/index.html.haml +15 -16
- data/app/views/droom/invitations/_form.html.haml +1 -1
- data/app/views/droom/invitations/_invitation.html.haml +1 -1
- data/app/views/droom/invitations/_invitations.html.haml +4 -4
- data/app/views/droom/memberships/_button.html.haml +5 -5
- data/app/views/droom/memberships/_form.html.haml +26 -7
- data/app/views/droom/memberships/_member.html.haml +1 -1
- data/app/views/droom/memberships/{_membership_toggle.html.haml → _toggle.html.haml} +4 -4
- data/app/views/droom/memberships/index.html.haml +9 -0
- data/app/views/droom/organisations/_action_menu.html.haml +1 -1
- data/app/views/droom/organisations/_organisation.html.haml +2 -2
- data/app/views/droom/organisations/_suggested.html.haml +1 -1
- data/app/views/droom/organisations/index.html.haml +11 -11
- data/app/views/droom/panels/_admin.html.haml +2 -2
- data/app/views/droom/panels/_configuration.html.haml +28 -0
- data/app/views/droom/panels/_devices.html.haml +2 -4
- data/app/views/droom/panels/_search.html.haml +9 -0
- data/app/views/droom/permissions/_action_menu.html.haml +10 -0
- data/app/views/droom/permissions/_created.html.haml +3 -0
- data/app/views/droom/permissions/_form.html.haml +17 -0
- data/app/views/droom/permissions/edit.html.haml +7 -0
- data/app/views/droom/permissions/new.html.haml +8 -0
- data/app/views/droom/permissions/show.html.haml +4 -0
- data/app/views/droom/preferences/_checkbox.html.haml +4 -2
- data/app/views/droom/scraps/_caption.html.haml +0 -2
- data/app/views/droom/scraps/_credit.html.haml +1 -1
- data/app/views/droom/scraps/_form.html.haml +68 -69
- data/app/views/droom/scraps/_preload.html.haml +4 -0
- data/app/views/droom/scraps/_stream.html.haml +11 -3
- data/app/views/droom/scraps/_thumb.html.haml +33 -1
- data/app/views/droom/scraps/edit.html.haml +6 -1
- data/app/views/droom/scraps/full/_document.html.haml +4 -3
- data/app/views/droom/scraps/full/_event.html.haml +17 -16
- data/app/views/droom/scraps/full/_image.html.haml +1 -2
- data/app/views/droom/scraps/full/_link.html.haml +4 -3
- data/app/views/droom/scraps/full/_quote.html.haml +4 -7
- data/app/views/droom/scraps/full/_text.html.haml +3 -2
- data/app/views/droom/scraps/full/_video.html.haml +2 -2
- data/app/views/droom/scraps/new.html.haml +6 -1
- data/app/views/droom/scraps/show.html.haml +4 -3
- data/app/views/droom/services/_action_menu.html.haml +12 -0
- data/app/views/droom/services/_created.html.haml +3 -0
- data/app/views/droom/services/_form.html.haml +18 -0
- data/app/views/droom/services/_services.html.haml +44 -0
- data/app/views/droom/services/edit.html.haml +7 -0
- data/app/views/droom/services/index.html.haml +5 -0
- data/app/views/droom/{people → services}/new.html.haml +4 -3
- data/app/views/droom/services/show.html.haml +4 -0
- data/app/views/droom/shared/_controls.html.haml +2 -2
- data/app/views/droom/shared/_navigation.html.haml +2 -2
- data/app/views/droom/shared/_toolbar.html.haml +1 -1
- data/app/views/droom/suggestions/index.html.haml +1 -0
- data/app/views/droom/users/_action_menu.html.haml +21 -0
- data/app/views/droom/users/_suggested.html.haml +14 -0
- data/app/views/droom/users/_user.html.haml +2 -2
- data/app/views/droom/users/_users.html.haml +7 -0
- data/app/views/droom/users/_users_table.html.haml +21 -22
- data/app/views/droom/users/admin.html.haml +10 -0
- data/app/views/droom/users/confirmations/_after_confirmation.html.haml +2 -0
- data/app/views/droom/users/confirmations/_password_required.html.haml +30 -0
- data/app/views/droom/users/confirmations/failure.en.html.haml +22 -0
- data/app/views/droom/users/confirmations/show.html.haml +13 -0
- data/app/views/droom/users/edit.html.haml +2 -10
- data/app/views/droom/users/edit/_details.html.haml +13 -0
- data/app/views/droom/users/edit/_memberships.html.haml +13 -0
- data/app/views/droom/users/edit/_password_fields.html.haml +16 -0
- data/app/views/droom/users/edit/_preferences.html.haml +37 -0
- data/app/views/droom/users/edit/_profile.html.haml +26 -0
- data/app/views/droom/users/edit/_user_fields.html.haml +66 -0
- data/app/views/droom/users/index.html.haml +6 -32
- data/app/views/droom/users/new.html.haml +3 -0
- data/app/views/droom/users/passwords/completed.html.haml +13 -0
- data/app/views/{devise → droom/users}/passwords/edit.html.haml +10 -4
- data/app/views/{devise → droom/users}/passwords/new.html.haml +4 -3
- data/app/views/droom/users/passwords/show.html.haml +6 -0
- data/app/views/droom/users/show.html.haml +2 -0
- data/app/views/droom/users/show/_listed.html.haml +46 -0
- data/app/views/droom/users/show/_profile.html.haml +33 -0
- data/app/views/droom/users/show/_tabled.html.haml +28 -0
- data/config/initializers/chronic.rb +2 -0
- data/config/initializers/devise.rb +35 -2
- data/config/initializers/paperclip.rb +11 -6
- data/config/locales/devise.en.yml +1 -1
- data/config/locales/en.yml +198 -103
- data/config/routes.rb +37 -45
- data/db/migrate/20130207123614_stream.rb +5 -1
- data/db/migrate/20130225095328_create_droom_calendars.rb +0 -1
- data/db/migrate/20130627065459_permissions.rb +34 -0
- data/db/migrate/20130627071938_users_take_over.rb +38 -0
- data/db/migrate/20130627073759_user_properties.rb +34 -0
- data/db/migrate/20130627080021_no_more_people.rb +11 -0
- data/db/migrate/20130701122935_directory_groups.rb +8 -0
- data/db/migrate/20130701123152_remove_old_access_control.rb +16 -0
- data/db/migrate/20130729102857_more_scrap_data.rb +12 -0
- data/db/migrate/20130904080340_international_names.rb +17 -0
- data/db/migrate/20130904080341_honours.rb +5 -0
- data/db/migrate/20131124082222_simple_addresses.rb +25 -0
- data/db/migrate/20131201093351_event_time_zone.rb +5 -0
- data/db/migrate/20131217060311_session_revocable.rb +5 -0
- data/db/migrate/20131219180311_event_types.rb +15 -0
- data/lib/devise/strategies/cookie_authenticatable.rb +46 -0
- data/lib/droom.rb +48 -33
- data/lib/droom/auth_cookie.rb +82 -0
- data/lib/droom/cropper.rb +24 -0
- data/lib/droom/engine.rb +20 -2
- data/lib/droom/folders.rb +6 -6
- data/lib/droom/lazy_hash.rb +11 -1
- data/lib/droom/monkeys.rb +6 -6
- data/lib/droom/taggability.rb +1 -1
- data/lib/droom/validators.rb +1 -1
- data/lib/droom/version.rb +1 -1
- data/lib/generators/droom/install/templates/droom_initializer.rb +10 -2
- data/lib/paperclip/geometry_transformation.rb +80 -0
- data/lib/paperclip/validators/attachment_height_validator.rb +89 -0
- data/lib/paperclip/validators/attachment_width_validator.rb +89 -0
- data/lib/paperclip_processors/offset_thumbnail.rb +85 -0
- data/spec/dummy/config/application.rb +0 -7
- data/spec/dummy/config/environments/development.rb +1 -10
- data/spec/dummy/config/environments/production.rb +1 -0
- data/spec/dummy/config/environments/test.rb +2 -7
- data/spec/dummy/db/migrate/20130130120631_folder_ancestry_to_parents.droom.rb +1 -1
- data/spec/dummy/db/migrate/20130724124758_dropbox_tokens.droom.rb +10 -0
- data/spec/dummy/db/migrate/20130724124759_preference_uuids.droom.rb +6 -0
- data/spec/dummy/db/migrate/20130724124760_stream.droom.rb +14 -0
- data/spec/dummy/db/migrate/20130724124761_access_token_secret.droom.rb +6 -0
- data/spec/dummy/db/migrate/20130724124762_person_image.droom.rb +10 -0
- data/spec/dummy/db/migrate/20130724124763_devise_confirmable.droom.rb +14 -0
- data/spec/dummy/db/migrate/20130724124764_create_droom_calendars.droom.rb +20 -0
- data/spec/dummy/db/migrate/20130724124765_give_scraps_document.droom.rb +6 -0
- data/spec/dummy/db/migrate/20130724124766_privateness.droom.rb +10 -0
- data/spec/dummy/db/migrate/20130724124767_store_metadata.droom.rb +6 -0
- data/spec/dummy/db/migrate/20130724124768_folders_nicely.droom.rb +7 -0
- data/spec/dummy/db/migrate/20130724124769_niceties.droom.rb +8 -0
- data/spec/dummy/db/migrate/20130724124770_create_droom_dropbox_documents.droom.rb +12 -0
- data/spec/dummy/db/migrate/20130724124771_dropbox_documents_changed.droom.rb +6 -0
- data/spec/dummy/db/migrate/20130724124772_user_titles.droom.rb +6 -0
- data/spec/dummy/db/migrate/20130724124773_permissions.droom.rb +35 -0
- data/spec/dummy/db/migrate/20130724124774_users_take_over.droom.rb +39 -0
- data/spec/dummy/db/migrate/20130724124775_user_properties.droom.rb +35 -0
- data/spec/dummy/db/migrate/20130724124776_no_more_people.droom.rb +12 -0
- data/spec/dummy/db/migrate/20130724124777_directory_groups.droom.rb +9 -0
- data/spec/dummy/db/migrate/20130724124778_remove_old_access_control.droom.rb +17 -0
- data/spec/dummy/db/schema.rb +217 -140
- data/spec/factories/documents.rb +0 -5
- data/spec/factories/events.rb +0 -9
- data/spec/factories/user.rb +4 -2
- data/spec/lib/droom/folders_spec.rb +8 -8
- data/spec/models/droom/document_spec.rb +6 -43
- data/spec/models/droom/event_spec.rb +0 -34
- data/spec/models/droom/mailing_list_membership_spec.rb +4 -4
- data/spec/models/droom/membership_spec.rb +2 -2
- data/spec/spec_helper.rb +1 -10
- metadata +322 -282
- data/app/assets/images/droom/Untitled-1.png +0 -0
- data/app/assets/images/droom/asterisk.png +0 -0
- data/app/assets/images/droom/smallmanage.png +0 -0
- data/app/assets/javascripts/droom/lib/kalendae.js +0 -1692
- data/app/assets/stylesheets/lib/_kalendae.css.sass +0 -139
- data/app/controllers/droom/pages_controller.rb +0 -61
- data/app/controllers/droom/people_controller.rb +0 -111
- data/app/models/droom/document_attachment.rb +0 -37
- data/app/models/droom/page.rb +0 -26
- data/app/models/droom/person.rb +0 -309
- data/app/models/droom/recurrence_rule.rb +0 -82
- data/app/models/droom/user_action_observer.rb +0 -12
- data/app/views/devise/confirmations/failure.en.html.haml +0 -20
- data/app/views/devise/confirmations/show.html.haml +0 -19
- data/app/views/droom/confirmations/show.html.haml +0 -40
- data/app/views/droom/documents/_document_line.html.haml +0 -2
- data/app/views/droom/events/_created.html.haml +0 -2
- data/app/views/droom/folders/_attachments.html.haml +0 -3
- data/app/views/droom/pages/_contents.html.haml +0 -10
- data/app/views/droom/pages/_form.html.haml +0 -36
- data/app/views/droom/pages/_full_page.html.haml +0 -17
- data/app/views/droom/pages/_page.html.haml +0 -5
- data/app/views/droom/pages/_pages.html.haml +0 -2
- data/app/views/droom/pages/admin.html.haml +0 -24
- data/app/views/droom/pages/edit.html.haml +0 -1
- data/app/views/droom/pages/index.html.haml +0 -10
- data/app/views/droom/pages/new.html.haml +0 -4
- data/app/views/droom/pages/show.html.haml +0 -5
- data/app/views/droom/panels/_account.html.haml +0 -16
- data/app/views/droom/panels/_readers.html.haml +0 -18
- data/app/views/droom/panels/_suggestions.html.haml +0 -15
- data/app/views/droom/people/_action_menu.html.haml +0 -22
- data/app/views/droom/people/_created.html.haml +0 -6
- data/app/views/droom/people/_form.html.haml +0 -66
- data/app/views/droom/people/_listing.html.haml +0 -19
- data/app/views/droom/people/_memberships.html.haml +0 -24
- data/app/views/droom/people/_people.html.haml +0 -5
- data/app/views/droom/people/_person.html.haml +0 -32
- data/app/views/droom/people/_search_result.html.haml +0 -14
- data/app/views/droom/people/_suggested.html.haml +0 -14
- data/app/views/droom/people/edit.html.haml +0 -9
- data/app/views/droom/people/index.html.haml +0 -8
- data/app/views/droom/people/show.html.haml +0 -31
- data/app/views/droom/scraps/_heading.html.haml +0 -16
- data/app/views/droom/scraps/thumbs/_document.html.haml +0 -9
- data/app/views/droom/scraps/thumbs/_event.html.haml +0 -17
- data/app/views/droom/scraps/thumbs/_image.html.haml +0 -6
- data/app/views/droom/scraps/thumbs/_link.html.haml +0 -10
- data/app/views/droom/scraps/thumbs/_quote.html.haml +0 -8
- data/app/views/droom/scraps/thumbs/_text.html.haml +0 -8
- data/app/views/droom/scraps/thumbs/_video.html.haml +0 -6
- data/app/views/droom/users/_extra_columns_header.html.haml +0 -0
- data/app/views/droom/users/_extra_columns_note.html.haml +0 -0
- data/app/views/droom/users/_form.html.haml +0 -14
- data/app/views/droom/users/_password_fields.html.haml +0 -15
- data/app/views/droom/users/_user_or_person.html.haml +0 -72
- data/app/views/kaminari/_paginator.html.haml +0 -16
- data/lib/droom/dav_resource.rb +0 -36
- data/lib/droom/model_helpers.rb +0 -25
- data/lib/droom/routing.rb +0 -13
- data/spec/datasets/calendar_events_dataset.rb +0 -44
- data/spec/datasets/calendar_pages_dataset.rb +0 -8
- data/spec/datasets/calendar_sites_dataset.rb +0 -6
- data/spec/datasets/calendars_dataset.rb +0 -34
- data/spec/datasets/documents_dataset.rb +0 -28
- data/spec/datasets/recurrence_dataset.rb +0 -7
- data/spec/dummy/config/sunspot.yml +0 -17
- data/spec/dummy/log/dav.log +0 -1
- data/spec/dummy/log/development.log +0 -2
- data/spec/dummy/log/test.log +0 -1
- data/spec/dummy/solr/conf/admin-extra.html +0 -31
- data/spec/dummy/solr/conf/elevate.xml +0 -36
- data/spec/dummy/solr/conf/mapping-ISOLatin1Accent.txt +0 -246
- data/spec/dummy/solr/conf/protwords.txt +0 -21
- data/spec/dummy/solr/conf/schema.xml +0 -238
- data/spec/dummy/solr/conf/scripts.conf +0 -24
- data/spec/dummy/solr/conf/solrconfig.xml +0 -934
- data/spec/dummy/solr/conf/spellings.txt +0 -2
- data/spec/dummy/solr/conf/stopwords.txt +0 -58
- data/spec/dummy/solr/conf/synonyms.txt +0 -31
- data/spec/dummy/solr/data/development/index/segments.gen +0 -0
- data/spec/dummy/solr/data/development/index/segments_1 +0 -0
- data/spec/dummy/solr/data/development/spellchecker/segments.gen +0 -0
- data/spec/dummy/solr/data/development/spellchecker/segments_1 +0 -0
- data/spec/dummy/solr/data/test/index/segments.gen +0 -0
- data/spec/dummy/solr/data/test/index/segments_3nu +0 -0
- data/spec/dummy/solr/data/test/spellchecker/segments.gen +0 -0
- data/spec/dummy/solr/data/test/spellchecker/segments_1 +0 -0
- data/spec/factories/recurrence_rules.rb +0 -25
- data/spec/models/droom/person_spec.rb +0 -72
- data/spec/models/droom/recurrence_rule_spec.rb +0 -81
|
@@ -34,6 +34,19 @@ unless Array::empty?
|
|
|
34
34
|
Array::empty = ()->
|
|
35
35
|
@length == 0
|
|
36
36
|
|
|
37
|
+
# Returns true if this array contains that thing.
|
|
38
|
+
|
|
39
|
+
unless Array::contains?
|
|
40
|
+
Array::contains = (thing)->
|
|
41
|
+
@indexOf(thing) != -1
|
|
42
|
+
|
|
43
|
+
# Returns the position of that thing in this array, for the few browsers that don't already know how to do that.
|
|
44
|
+
unless Array::indexOf?
|
|
45
|
+
Array::indexOf = (elt)->
|
|
46
|
+
for item, i in this
|
|
47
|
+
return i if item is elt
|
|
48
|
+
return -1
|
|
49
|
+
|
|
37
50
|
# Removes one instance of the supplied thing from an array
|
|
38
51
|
|
|
39
52
|
unless Array::remove?
|
|
@@ -0,0 +1,1026 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DatePicker 1.0.0
|
|
3
|
+
*
|
|
4
|
+
* A jQuery-based DatePicker that provides an easy way of creating both single
|
|
5
|
+
* and multi-viewed calendars capable of accepting single, range, and multiple
|
|
6
|
+
* selected dates. Easily styled with two example styles provided: an attractive
|
|
7
|
+
* 'dark' style, and a Google Analytics-like 'clean' style.
|
|
8
|
+
*
|
|
9
|
+
* View project page for Examples and Documentation:
|
|
10
|
+
* http://foxrunsoftware.github.com/DatePicker/
|
|
11
|
+
*
|
|
12
|
+
* This project is distinct from and not affiliated with the jquery.ui.datepicker.
|
|
13
|
+
*
|
|
14
|
+
* Copyright 2012, Justin Stern (www.foxrunsoftware.net)
|
|
15
|
+
* Dual licensed under the MIT and GPL Version 2 licenses.
|
|
16
|
+
*
|
|
17
|
+
* Based on Work by Original Author: Stefan Petre www.eyecon.ro
|
|
18
|
+
*
|
|
19
|
+
* Depends:
|
|
20
|
+
* jquery.js
|
|
21
|
+
*/
|
|
22
|
+
(function ($) {
|
|
23
|
+
var cache = {}, tmpl,
|
|
24
|
+
DatePicker = function () {
|
|
25
|
+
var ids = {},
|
|
26
|
+
views = {
|
|
27
|
+
years: 'datepickerViewYears',
|
|
28
|
+
moths: 'datepickerViewMonths',
|
|
29
|
+
days: 'datepickerViewDays'
|
|
30
|
+
},
|
|
31
|
+
tpl = {
|
|
32
|
+
wrapper: '<div class="datepicker"><div class="datepickerBorderT" /><div class="datepickerBorderB" /><div class="datepickerBorderL" /><div class="datepickerBorderR" /><div class="datepickerBorderTL" /><div class="datepickerBorderTR" /><div class="datepickerBorderBL" /><div class="datepickerBorderBR" /><div class="datepickerContainer"><table cellspacing="0" cellpadding="0"><tbody><tr></tr></tbody></table></div></div>',
|
|
33
|
+
head: [
|
|
34
|
+
'<td class="datepickerBlock">',
|
|
35
|
+
'<table cellspacing="0" cellpadding="0">',
|
|
36
|
+
'<thead>',
|
|
37
|
+
'<tr>',
|
|
38
|
+
'<th colspan="7"><a class="datepickerGoPrev" href="#"><span><%=prev%></span></a>',
|
|
39
|
+
'<a class="datepickerMonth" href="#"><span></span></a>',
|
|
40
|
+
'<a class="datepickerGoNext" href="#"><span><%=next%></span></a></th>',
|
|
41
|
+
'</tr>',
|
|
42
|
+
'<tr class="datepickerDoW">',
|
|
43
|
+
'<th><span><%=day1%></span></th>',
|
|
44
|
+
'<th><span><%=day2%></span></th>',
|
|
45
|
+
'<th><span><%=day3%></span></th>',
|
|
46
|
+
'<th><span><%=day4%></span></th>',
|
|
47
|
+
'<th><span><%=day5%></span></th>',
|
|
48
|
+
'<th><span><%=day6%></span></th>',
|
|
49
|
+
'<th><span><%=day7%></span></th>',
|
|
50
|
+
'</tr>',
|
|
51
|
+
'</thead>',
|
|
52
|
+
'</table></td>'
|
|
53
|
+
],
|
|
54
|
+
space : '<td class="datepickerSpace"><div></div></td>',
|
|
55
|
+
days: [
|
|
56
|
+
'<tbody class="datepickerDays">',
|
|
57
|
+
'<tr>',
|
|
58
|
+
'<td class="<%=weeks[0].days[0].classname%>"><a href="#"><span><%=weeks[0].days[0].text%></span></a></td>',
|
|
59
|
+
'<td class="<%=weeks[0].days[1].classname%>"><a href="#"><span><%=weeks[0].days[1].text%></span></a></td>',
|
|
60
|
+
'<td class="<%=weeks[0].days[2].classname%>"><a href="#"><span><%=weeks[0].days[2].text%></span></a></td>',
|
|
61
|
+
'<td class="<%=weeks[0].days[3].classname%>"><a href="#"><span><%=weeks[0].days[3].text%></span></a></td>',
|
|
62
|
+
'<td class="<%=weeks[0].days[4].classname%>"><a href="#"><span><%=weeks[0].days[4].text%></span></a></td>',
|
|
63
|
+
'<td class="<%=weeks[0].days[5].classname%>"><a href="#"><span><%=weeks[0].days[5].text%></span></a></td>',
|
|
64
|
+
'<td class="<%=weeks[0].days[6].classname%>"><a href="#"><span><%=weeks[0].days[6].text%></span></a></td>',
|
|
65
|
+
'</tr>',
|
|
66
|
+
'<tr>',
|
|
67
|
+
'<td class="<%=weeks[1].days[0].classname%>"><a href="#"><span><%=weeks[1].days[0].text%></span></a></td>',
|
|
68
|
+
'<td class="<%=weeks[1].days[1].classname%>"><a href="#"><span><%=weeks[1].days[1].text%></span></a></td>',
|
|
69
|
+
'<td class="<%=weeks[1].days[2].classname%>"><a href="#"><span><%=weeks[1].days[2].text%></span></a></td>',
|
|
70
|
+
'<td class="<%=weeks[1].days[3].classname%>"><a href="#"><span><%=weeks[1].days[3].text%></span></a></td>',
|
|
71
|
+
'<td class="<%=weeks[1].days[4].classname%>"><a href="#"><span><%=weeks[1].days[4].text%></span></a></td>',
|
|
72
|
+
'<td class="<%=weeks[1].days[5].classname%>"><a href="#"><span><%=weeks[1].days[5].text%></span></a></td>',
|
|
73
|
+
'<td class="<%=weeks[1].days[6].classname%>"><a href="#"><span><%=weeks[1].days[6].text%></span></a></td>',
|
|
74
|
+
'</tr>',
|
|
75
|
+
'<tr>',
|
|
76
|
+
'<td class="<%=weeks[2].days[0].classname%>"><a href="#"><span><%=weeks[2].days[0].text%></span></a></td>',
|
|
77
|
+
'<td class="<%=weeks[2].days[1].classname%>"><a href="#"><span><%=weeks[2].days[1].text%></span></a></td>',
|
|
78
|
+
'<td class="<%=weeks[2].days[2].classname%>"><a href="#"><span><%=weeks[2].days[2].text%></span></a></td>',
|
|
79
|
+
'<td class="<%=weeks[2].days[3].classname%>"><a href="#"><span><%=weeks[2].days[3].text%></span></a></td>',
|
|
80
|
+
'<td class="<%=weeks[2].days[4].classname%>"><a href="#"><span><%=weeks[2].days[4].text%></span></a></td>',
|
|
81
|
+
'<td class="<%=weeks[2].days[5].classname%>"><a href="#"><span><%=weeks[2].days[5].text%></span></a></td>',
|
|
82
|
+
'<td class="<%=weeks[2].days[6].classname%>"><a href="#"><span><%=weeks[2].days[6].text%></span></a></td>',
|
|
83
|
+
'</tr>',
|
|
84
|
+
'<tr>',
|
|
85
|
+
'<td class="<%=weeks[3].days[0].classname%>"><a href="#"><span><%=weeks[3].days[0].text%></span></a></td>',
|
|
86
|
+
'<td class="<%=weeks[3].days[1].classname%>"><a href="#"><span><%=weeks[3].days[1].text%></span></a></td>',
|
|
87
|
+
'<td class="<%=weeks[3].days[2].classname%>"><a href="#"><span><%=weeks[3].days[2].text%></span></a></td>',
|
|
88
|
+
'<td class="<%=weeks[3].days[3].classname%>"><a href="#"><span><%=weeks[3].days[3].text%></span></a></td>',
|
|
89
|
+
'<td class="<%=weeks[3].days[4].classname%>"><a href="#"><span><%=weeks[3].days[4].text%></span></a></td>',
|
|
90
|
+
'<td class="<%=weeks[3].days[5].classname%>"><a href="#"><span><%=weeks[3].days[5].text%></span></a></td>',
|
|
91
|
+
'<td class="<%=weeks[3].days[6].classname%>"><a href="#"><span><%=weeks[3].days[6].text%></span></a></td>',
|
|
92
|
+
'</tr>',
|
|
93
|
+
'<tr>',
|
|
94
|
+
'<td class="<%=weeks[4].days[0].classname%>"><a href="#"><span><%=weeks[4].days[0].text%></span></a></td>',
|
|
95
|
+
'<td class="<%=weeks[4].days[1].classname%>"><a href="#"><span><%=weeks[4].days[1].text%></span></a></td>',
|
|
96
|
+
'<td class="<%=weeks[4].days[2].classname%>"><a href="#"><span><%=weeks[4].days[2].text%></span></a></td>',
|
|
97
|
+
'<td class="<%=weeks[4].days[3].classname%>"><a href="#"><span><%=weeks[4].days[3].text%></span></a></td>',
|
|
98
|
+
'<td class="<%=weeks[4].days[4].classname%>"><a href="#"><span><%=weeks[4].days[4].text%></span></a></td>',
|
|
99
|
+
'<td class="<%=weeks[4].days[5].classname%>"><a href="#"><span><%=weeks[4].days[5].text%></span></a></td>',
|
|
100
|
+
'<td class="<%=weeks[4].days[6].classname%>"><a href="#"><span><%=weeks[4].days[6].text%></span></a></td>',
|
|
101
|
+
'</tr>',
|
|
102
|
+
'<tr>',
|
|
103
|
+
'<td class="<%=weeks[5].days[0].classname%>"><a href="#"><span><%=weeks[5].days[0].text%></span></a></td>',
|
|
104
|
+
'<td class="<%=weeks[5].days[1].classname%>"><a href="#"><span><%=weeks[5].days[1].text%></span></a></td>',
|
|
105
|
+
'<td class="<%=weeks[5].days[2].classname%>"><a href="#"><span><%=weeks[5].days[2].text%></span></a></td>',
|
|
106
|
+
'<td class="<%=weeks[5].days[3].classname%>"><a href="#"><span><%=weeks[5].days[3].text%></span></a></td>',
|
|
107
|
+
'<td class="<%=weeks[5].days[4].classname%>"><a href="#"><span><%=weeks[5].days[4].text%></span></a></td>',
|
|
108
|
+
'<td class="<%=weeks[5].days[5].classname%>"><a href="#"><span><%=weeks[5].days[5].text%></span></a></td>',
|
|
109
|
+
'<td class="<%=weeks[5].days[6].classname%>"><a href="#"><span><%=weeks[5].days[6].text%></span></a></td>',
|
|
110
|
+
'</tr>',
|
|
111
|
+
'</tbody>'
|
|
112
|
+
],
|
|
113
|
+
months: [
|
|
114
|
+
'<tbody class="<%=className%>">',
|
|
115
|
+
'<tr>',
|
|
116
|
+
'<td colspan="2"><a href="#"><span><%=data[0]%></span></a></td>',
|
|
117
|
+
'<td colspan="2"><a href="#"><span><%=data[1]%></span></a></td>',
|
|
118
|
+
'<td colspan="2"><a href="#"><span><%=data[2]%></span></a></td>',
|
|
119
|
+
'<td colspan="1"><a href="#"><span><%=data[3]%></span></a></td>',
|
|
120
|
+
'</tr>',
|
|
121
|
+
'<tr>',
|
|
122
|
+
'<td colspan="2"><a href="#"><span><%=data[4]%></span></a></td>',
|
|
123
|
+
'<td colspan="2"><a href="#"><span><%=data[5]%></span></a></td>',
|
|
124
|
+
'<td colspan="2"><a href="#"><span><%=data[6]%></span></a></td>',
|
|
125
|
+
'<td colspan="1"><a href="#"><span><%=data[7]%></span></a></td>',
|
|
126
|
+
'</tr>',
|
|
127
|
+
'<tr>',
|
|
128
|
+
'<td colspan="2"><a href="#"><span><%=data[8]%></span></a></td>',
|
|
129
|
+
'<td colspan="2"><a href="#"><span><%=data[9]%></span></a></td>',
|
|
130
|
+
'<td colspan="2"><a href="#"><span><%=data[10]%></span></a></td>',
|
|
131
|
+
'<td colspan="1"><a href="#"><span><%=data[11]%></span></a></td>',
|
|
132
|
+
'</tr>',
|
|
133
|
+
'</tbody>'
|
|
134
|
+
]
|
|
135
|
+
},
|
|
136
|
+
defaults = {
|
|
137
|
+
/**
|
|
138
|
+
* The currently selected date(s). This can be: a single date, an array
|
|
139
|
+
* of two dates (sets a range when 'mode' is 'range'), or an array of
|
|
140
|
+
* any number of dates (selects all dates when 'mode' is 'multiple'.
|
|
141
|
+
* The supplied dates can be any one of: Date object, milliseconds
|
|
142
|
+
* (as from date.getTime(), date.valueOf()), or a date string
|
|
143
|
+
* parseable by Date.parse().
|
|
144
|
+
*/
|
|
145
|
+
date: null,
|
|
146
|
+
/**
|
|
147
|
+
* Optional date which determines the current calendar month/year. This
|
|
148
|
+
* can be one of: Date object, milliseconds (as from date.getTime(), date.valueOf()), or a date string
|
|
149
|
+
* parseable by Date.parse(). Defaults to todays date.
|
|
150
|
+
*/
|
|
151
|
+
current: null,
|
|
152
|
+
/**
|
|
153
|
+
* true causes the datepicker calendar to be appended to the DatePicker
|
|
154
|
+
* element and rendered, false binds the DatePicker to an event on the trigger element
|
|
155
|
+
*/
|
|
156
|
+
inline: false,
|
|
157
|
+
/**
|
|
158
|
+
* Date selection mode, one of 'single', 'range' or 'multiple'. Default
|
|
159
|
+
* 'single'. 'Single' allows the selection of a single date, 'range'
|
|
160
|
+
* allows the selection of range of dates, and 'multiple' allows the
|
|
161
|
+
* selection of any number of individual dates.
|
|
162
|
+
*/
|
|
163
|
+
mode: 'single',
|
|
164
|
+
/**
|
|
165
|
+
* Number of side-by-side calendars, defaults to 1.
|
|
166
|
+
*/
|
|
167
|
+
calendars: 1,
|
|
168
|
+
/**
|
|
169
|
+
* The day that starts the week, where 0: Sunday, 1: Monday, 2: Tuesday, 3: Wednesday, 4: Thursday, 5: Friday, 6: Saturday. Defaults to Sunday
|
|
170
|
+
*/
|
|
171
|
+
starts: 0,
|
|
172
|
+
/**
|
|
173
|
+
* Previous link text. Default '◀' (Unicode left arrow)
|
|
174
|
+
*/
|
|
175
|
+
prev: '◀',
|
|
176
|
+
/**
|
|
177
|
+
* Next link text. Default '◀' (Unicode left arrow)
|
|
178
|
+
*/
|
|
179
|
+
next: '▶',
|
|
180
|
+
/**
|
|
181
|
+
* Initial calendar view, one of 'days', 'months' or 'years'. Defaults to 'days'.
|
|
182
|
+
*/
|
|
183
|
+
view: 'days',
|
|
184
|
+
/**
|
|
185
|
+
* Date picker's position relative to the trigger element (non inline
|
|
186
|
+
* mode only), one of 'top', 'left', 'right' or 'bottom'. Defaults to 'bottom'
|
|
187
|
+
*/
|
|
188
|
+
position: 'bottom',
|
|
189
|
+
/**
|
|
190
|
+
* The trigger event used to show a non-inline calendar. Defaults to
|
|
191
|
+
* 'focus' which is useful when the trigger element is a text input,
|
|
192
|
+
* can also be 'click' for instance if the trigger element is a button
|
|
193
|
+
* or some text element.
|
|
194
|
+
*/
|
|
195
|
+
showOn: 'focus',
|
|
196
|
+
/**
|
|
197
|
+
* Callback, invoked prior to the rendering of each date cell, which
|
|
198
|
+
* allows control of the styling of the cell via the returned hash.
|
|
199
|
+
*
|
|
200
|
+
* @param HTMLDivElement el the datepicker containing element, ie the
|
|
201
|
+
* div with class 'datepicker'
|
|
202
|
+
* @param Date date the date that will be rendered
|
|
203
|
+
* @return hash with the following optional attributes:
|
|
204
|
+
* selected: if true, date will be selected
|
|
205
|
+
* disabled: if true, date cell will be disabled
|
|
206
|
+
* className: css class name to add to the cell
|
|
207
|
+
*/
|
|
208
|
+
onRenderCell: function() { return {} },
|
|
209
|
+
/*
|
|
210
|
+
* Callback, invoked when a date is selected, with 'this' referring to
|
|
211
|
+
* the HTMLElement that DatePicker was invoked upon.
|
|
212
|
+
*
|
|
213
|
+
* @param dates: Selected date(s) depending on calendar mode. When calendar mode is 'single' this
|
|
214
|
+
* is a single Date object. When calendar mode is 'range', this is an array containing
|
|
215
|
+
* a 'from' and 'to' Date objects. When calendar mode is 'multiple' this is an array
|
|
216
|
+
* of Date objects.
|
|
217
|
+
* @param HTMLElement el the DatePicker element, ie the element that DatePicker was invoked upon
|
|
218
|
+
*/
|
|
219
|
+
onChange: function() { },
|
|
220
|
+
/*
|
|
221
|
+
* Callback, invoked when a date range is selected, with 'this' referring to
|
|
222
|
+
* the HTMLElement that DatePicker was invoked upon.
|
|
223
|
+
*
|
|
224
|
+
* @param dates: Selected date(s), ie an array containing a 'from' and 'to' Date objects.
|
|
225
|
+
* @param HTMLElement el the DatePicker element, ie the element that DatePicker was invoked upon
|
|
226
|
+
*/
|
|
227
|
+
onRangeChange: function() { },
|
|
228
|
+
/**
|
|
229
|
+
* Invoked before a non-inline datepicker is shown, with 'this'
|
|
230
|
+
* referring to the HTMLElement that DatePicker was invoked upon, ie
|
|
231
|
+
* the trigger element
|
|
232
|
+
*
|
|
233
|
+
* @param HTMLDivElement el The datepicker container element, ie the div with class 'datepicker'.
|
|
234
|
+
* @return true to allow the datepicker to be shown, false to keep it hidden
|
|
235
|
+
*/
|
|
236
|
+
|
|
237
|
+
onBeforeShow: function() { return true },
|
|
238
|
+
/**
|
|
239
|
+
* Invoked after a non-inline datepicker is shown, with 'this'
|
|
240
|
+
* referring to the HTMLElement that DatePicker was invoked upon, ie
|
|
241
|
+
* the trigger element
|
|
242
|
+
*
|
|
243
|
+
* @param HTMLDivElement el The datepicker container element, ie the div with class 'datepicker'
|
|
244
|
+
*/
|
|
245
|
+
onAfterShow: function() { },
|
|
246
|
+
/**
|
|
247
|
+
* Invoked before a non-inline datepicker is hidden, with 'this'
|
|
248
|
+
* referring to the HTMLElement that DatePicker was invoked upon, ie
|
|
249
|
+
* the trigger element
|
|
250
|
+
*
|
|
251
|
+
* @param HTMLDivElement el The datepicker container element, ie the div with class 'datepicker'
|
|
252
|
+
* @return true to allow the datepicker to be hidden, false to keep it visible
|
|
253
|
+
*/
|
|
254
|
+
onBeforeHide: function() { return true },
|
|
255
|
+
/**
|
|
256
|
+
* Invoked after a non-inline datepicker is hidden, with 'this'
|
|
257
|
+
* referring to the HTMLElement that DatePicker was invoked upon, ie
|
|
258
|
+
* the trigger element
|
|
259
|
+
*
|
|
260
|
+
* @param HTMLDivElement el The datepicker container element, ie the div with class 'datepicker'
|
|
261
|
+
*/
|
|
262
|
+
onAfterHide: function() { },
|
|
263
|
+
/**
|
|
264
|
+
* Locale text for day/month names: provide a hash with keys 'daysMin', 'months' and 'monthsShort'. Default english
|
|
265
|
+
*/
|
|
266
|
+
locale: {
|
|
267
|
+
daysMin: ["S", "M", "T", "W", "T", "F", "S"],
|
|
268
|
+
months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
|
|
269
|
+
monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
|
|
270
|
+
},
|
|
271
|
+
/**
|
|
272
|
+
* The combined height from the top/bottom borders. 'false' is the default
|
|
273
|
+
* and generally the correct value.
|
|
274
|
+
*/
|
|
275
|
+
extraHeight: false,
|
|
276
|
+
/**
|
|
277
|
+
* The combined width from the left/right borders. 'false' is the default
|
|
278
|
+
* and generally the correct value.
|
|
279
|
+
*/
|
|
280
|
+
extraWidth: false,
|
|
281
|
+
/**
|
|
282
|
+
* Private option, used to determine when a range is selected
|
|
283
|
+
*/
|
|
284
|
+
lastSel: false
|
|
285
|
+
},
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Internal method which renders the calendar cells
|
|
289
|
+
*
|
|
290
|
+
* @param HTMLDivElement el datepicker container element
|
|
291
|
+
*/
|
|
292
|
+
fill = function(el) {
|
|
293
|
+
var options = $(el).data('datepicker');
|
|
294
|
+
var cal = $(el);
|
|
295
|
+
var currentCal = Math.floor(options.calendars/2), date, data, dow, month, cnt = 0, days, indic, indic2, html, tblCal;
|
|
296
|
+
|
|
297
|
+
cal.find('td>table tbody').remove();
|
|
298
|
+
for(var i = 0; i < options.calendars; i++) {
|
|
299
|
+
date = new Date(options.current);
|
|
300
|
+
date.addMonths(-currentCal + i);
|
|
301
|
+
tblCal = cal.find('table').eq(i+1);
|
|
302
|
+
|
|
303
|
+
if(i == 0) tblCal.addClass('datepickerFirstView');
|
|
304
|
+
if(i == options.calendars - 1) tblCal.addClass('datepickerLastView');
|
|
305
|
+
|
|
306
|
+
if(tblCal.hasClass('datepickerViewDays')) {
|
|
307
|
+
dow = date.getMonthName(true)+" "+date.getFullYear();
|
|
308
|
+
} else if(tblCal.hasClass('datepickerViewMonths')) {
|
|
309
|
+
dow = date.getFullYear();
|
|
310
|
+
} else if(tblCal.hasClass('datepickerViewYears')) {
|
|
311
|
+
dow = (date.getFullYear()-6) + ' - ' + (date.getFullYear()+5);
|
|
312
|
+
}
|
|
313
|
+
tblCal.find('thead tr:first th a:eq(1) span').text(dow);
|
|
314
|
+
dow = date.getFullYear()-6;
|
|
315
|
+
data = {
|
|
316
|
+
data: [],
|
|
317
|
+
className: 'datepickerYears'
|
|
318
|
+
}
|
|
319
|
+
for( var j = 0; j < 12; j++) {
|
|
320
|
+
data.data.push(dow + j);
|
|
321
|
+
}
|
|
322
|
+
// datepickerYears template
|
|
323
|
+
html = tmpl(tpl.months.join(''), data);
|
|
324
|
+
date.setDate(1);
|
|
325
|
+
data = {weeks:[], test: 10};
|
|
326
|
+
month = date.getMonth();
|
|
327
|
+
var dow = (date.getDay() - options.starts) % 7;
|
|
328
|
+
date.addDays(-(dow + (dow < 0 ? 7 : 0)));
|
|
329
|
+
cnt = 0;
|
|
330
|
+
while(cnt < 42) {
|
|
331
|
+
indic = parseInt(cnt/7,10);
|
|
332
|
+
indic2 = cnt%7;
|
|
333
|
+
if (!data.weeks[indic]) {
|
|
334
|
+
data.weeks[indic] = {
|
|
335
|
+
days: []
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
data.weeks[indic].days[indic2] = {
|
|
339
|
+
text: date.getDate(),
|
|
340
|
+
classname: []
|
|
341
|
+
};
|
|
342
|
+
var today = new Date();
|
|
343
|
+
if (today.getDate() == date.getDate() && today.getMonth() == date.getMonth() && today.getYear() == date.getYear()) {
|
|
344
|
+
data.weeks[indic].days[indic2].classname.push('datepickerToday');
|
|
345
|
+
}
|
|
346
|
+
if (date > today) {
|
|
347
|
+
// current month, date in future
|
|
348
|
+
data.weeks[indic].days[indic2].classname.push('datepickerFuture');
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
if (month != date.getMonth()) {
|
|
352
|
+
data.weeks[indic].days[indic2].classname.push('datepickerNotInMonth');
|
|
353
|
+
// disable clicking of the 'not in month' cells
|
|
354
|
+
data.weeks[indic].days[indic2].classname.push('datepickerDisabled');
|
|
355
|
+
}
|
|
356
|
+
if (date.getDay() == 0) {
|
|
357
|
+
data.weeks[indic].days[indic2].classname.push('datepickerSunday');
|
|
358
|
+
}
|
|
359
|
+
if (date.getDay() == 6) {
|
|
360
|
+
data.weeks[indic].days[indic2].classname.push('datepickerSaturday');
|
|
361
|
+
}
|
|
362
|
+
var fromUser = options.onRenderCell(el, date);
|
|
363
|
+
var val = date.valueOf();
|
|
364
|
+
if(options.date && (!$.isArray(options.date) || options.date.length > 0)) {
|
|
365
|
+
if (fromUser.selected || options.date == val || $.inArray(val, options.date) > -1 || (options.mode == 'range' && val >= options.date[0] && val <= options.date[1])) {
|
|
366
|
+
data.weeks[indic].days[indic2].classname.push('datepickerSelected');
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
if (fromUser.disabled) {
|
|
370
|
+
data.weeks[indic].days[indic2].classname.push('datepickerDisabled');
|
|
371
|
+
}
|
|
372
|
+
if (fromUser.className) {
|
|
373
|
+
data.weeks[indic].days[indic2].classname.push(fromUser.className);
|
|
374
|
+
}
|
|
375
|
+
data.weeks[indic].days[indic2].classname = data.weeks[indic].days[indic2].classname.join(' ');
|
|
376
|
+
cnt++;
|
|
377
|
+
date.addDays(1);
|
|
378
|
+
}
|
|
379
|
+
// Fill the datepickerDays template with data
|
|
380
|
+
html = tmpl(tpl.days.join(''), data) + html;
|
|
381
|
+
|
|
382
|
+
data = {
|
|
383
|
+
data: options.locale.monthsShort,
|
|
384
|
+
className: 'datepickerMonths'
|
|
385
|
+
};
|
|
386
|
+
// datepickerMonths template
|
|
387
|
+
html = tmpl(tpl.months.join(''), data) + html;
|
|
388
|
+
tblCal.append(html);
|
|
389
|
+
}
|
|
390
|
+
},
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Extends the Date object with some useful helper methods
|
|
394
|
+
*/
|
|
395
|
+
extendDate = function(locale) {
|
|
396
|
+
if (Date.prototype.tempDate) {
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
Date.prototype.tempDate = null;
|
|
400
|
+
Date.prototype.months = locale.months;
|
|
401
|
+
Date.prototype.monthsShort = locale.monthsShort;
|
|
402
|
+
Date.prototype.getMonthName = function(fullName) {
|
|
403
|
+
return this[fullName ? 'months' : 'monthsShort'][this.getMonth()];
|
|
404
|
+
};
|
|
405
|
+
Date.prototype.addDays = function (n) {
|
|
406
|
+
this.setDate(this.getDate() + n);
|
|
407
|
+
this.tempDate = this.getDate();
|
|
408
|
+
};
|
|
409
|
+
Date.prototype.addMonths = function (n) {
|
|
410
|
+
if (this.tempDate == null) {
|
|
411
|
+
this.tempDate = this.getDate();
|
|
412
|
+
}
|
|
413
|
+
this.setDate(1);
|
|
414
|
+
this.setMonth(this.getMonth() + n);
|
|
415
|
+
this.setDate(Math.min(this.tempDate, this.getMaxDays()));
|
|
416
|
+
};
|
|
417
|
+
Date.prototype.addYears = function (n) {
|
|
418
|
+
if (this.tempDate == null) {
|
|
419
|
+
this.tempDate = this.getDate();
|
|
420
|
+
}
|
|
421
|
+
this.setDate(1);
|
|
422
|
+
this.setFullYear(this.getFullYear() + n);
|
|
423
|
+
this.setDate(Math.min(this.tempDate, this.getMaxDays()));
|
|
424
|
+
};
|
|
425
|
+
Date.prototype.getMaxDays = function() {
|
|
426
|
+
var tmpDate = new Date(Date.parse(this)),
|
|
427
|
+
d = 28, m;
|
|
428
|
+
m = tmpDate.getMonth();
|
|
429
|
+
d = 28;
|
|
430
|
+
while (tmpDate.getMonth() == m) {
|
|
431
|
+
d ++;
|
|
432
|
+
tmpDate.setDate(d);
|
|
433
|
+
}
|
|
434
|
+
return d - 1;
|
|
435
|
+
};
|
|
436
|
+
},
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Internal method which lays out the calendar widget
|
|
440
|
+
*/
|
|
441
|
+
layout = function(el) {
|
|
442
|
+
var options = $(el).data('datepicker');
|
|
443
|
+
var cal = $('#' + options.id);
|
|
444
|
+
if (options.extraHeight === false) {
|
|
445
|
+
var divs = $(el).find('div');
|
|
446
|
+
options.extraHeight = divs.get(0).offsetHeight + divs.get(1).offsetHeight; // heights from top/bottom borders
|
|
447
|
+
options.extraWidth = divs.get(2).offsetWidth + divs.get(3).offsetWidth; // widths from left/right borders
|
|
448
|
+
}
|
|
449
|
+
var tbl = cal.find('table:first').get(0);
|
|
450
|
+
var width = tbl.offsetWidth;
|
|
451
|
+
var height = tbl.offsetHeight;
|
|
452
|
+
cal.css({
|
|
453
|
+
width: width + options.extraWidth + 'px',
|
|
454
|
+
height: height + options.extraHeight + 'px'
|
|
455
|
+
}).find('div.datepickerContainer').css({
|
|
456
|
+
width: width + 'px',
|
|
457
|
+
height: height + 'px'
|
|
458
|
+
});
|
|
459
|
+
},
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Internal method, bound to the HTML DatePicker Element, onClick.
|
|
463
|
+
* This is the function that controls the behavior of the calendar when
|
|
464
|
+
* the title, next/previous, or a date cell is clicked on.
|
|
465
|
+
*/
|
|
466
|
+
click = function(ev) {
|
|
467
|
+
if ($(ev.target).is('span')) {
|
|
468
|
+
ev.target = ev.target.parentNode;
|
|
469
|
+
}
|
|
470
|
+
var el = $(ev.target);
|
|
471
|
+
if (el.is('a')) {
|
|
472
|
+
ev.target.blur();
|
|
473
|
+
if (el.hasClass('datepickerDisabled')) {
|
|
474
|
+
return false;
|
|
475
|
+
}
|
|
476
|
+
var options = $(this).data('datepicker');
|
|
477
|
+
var parentEl = el.parent();
|
|
478
|
+
var tblEl = parentEl.parent().parent().parent();
|
|
479
|
+
var tblIndex = $('table', this).index(tblEl.get(0)) - 1;
|
|
480
|
+
var tmp = new Date(options.current);
|
|
481
|
+
var changed = false;
|
|
482
|
+
var changedRange = false;
|
|
483
|
+
var fillIt = false;
|
|
484
|
+
var currentCal = Math.floor(options.calendars/2);
|
|
485
|
+
|
|
486
|
+
if (parentEl.is('th')) {
|
|
487
|
+
// clicking the calendar title
|
|
488
|
+
|
|
489
|
+
if (el.hasClass('datepickerMonth')) {
|
|
490
|
+
// clicking on the title of a Month Datepicker
|
|
491
|
+
tmp.addMonths(tblIndex - currentCal);
|
|
492
|
+
|
|
493
|
+
if(options.mode == 'range') {
|
|
494
|
+
// range, select the whole month
|
|
495
|
+
options.date[0] = (tmp.setHours(0,0,0,0)).valueOf();
|
|
496
|
+
tmp.addDays(tmp.getMaxDays()-1);
|
|
497
|
+
tmp.setHours(23,59,59,0);
|
|
498
|
+
options.date[1] = tmp.valueOf();
|
|
499
|
+
fillIt = true;
|
|
500
|
+
changed = true;
|
|
501
|
+
options.lastSel = false;
|
|
502
|
+
} else if(options.calendars == 1) {
|
|
503
|
+
// single/multiple mode with a single calendar: swap between daily/monthly/yearly view.
|
|
504
|
+
// Note: there's no reason a multi-calendar widget can't have this functionality,
|
|
505
|
+
// however I think it looks really unintuitive.
|
|
506
|
+
if(tblEl.eq(0).hasClass('datepickerViewDays')) {
|
|
507
|
+
tblEl.eq(0).toggleClass('datepickerViewDays datepickerViewMonths');
|
|
508
|
+
el.find('span').text(tmp.getFullYear());
|
|
509
|
+
} else if(tblEl.eq(0).hasClass('datepickerViewMonths')) {
|
|
510
|
+
tblEl.eq(0).toggleClass('datepickerViewMonths datepickerViewYears');
|
|
511
|
+
el.find('span').text((tmp.getFullYear()-6) + ' - ' + (tmp.getFullYear()+5));
|
|
512
|
+
} else if(tblEl.eq(0).hasClass('datepickerViewYears')) {
|
|
513
|
+
tblEl.eq(0).toggleClass('datepickerViewYears datepickerViewDays');
|
|
514
|
+
el.find('span').text(tmp.getMonthName(true)+", "+tmp.getFullYear());
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
} else if (parentEl.parent().parent().is('thead')) {
|
|
518
|
+
// clicked either next/previous arrows
|
|
519
|
+
if(tblEl.eq(0).hasClass('datepickerViewDays')) {
|
|
520
|
+
options.current.addMonths(el.hasClass('datepickerGoPrev') ? -1 : 1);
|
|
521
|
+
} else if(tblEl.eq(0).hasClass('datepickerViewMonths')) {
|
|
522
|
+
options.current.addYears(el.hasClass('datepickerGoPrev') ? -1 : 1);
|
|
523
|
+
} else if(tblEl.eq(0).hasClass('datepickerViewYears')) {
|
|
524
|
+
options.current.addYears(el.hasClass('datepickerGoPrev') ? -12 : 12);
|
|
525
|
+
}
|
|
526
|
+
fillIt = true;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
} else if (parentEl.is('td') && !parentEl.hasClass('datepickerDisabled')) {
|
|
530
|
+
// clicking the calendar grid
|
|
531
|
+
|
|
532
|
+
if(tblEl.eq(0).hasClass('datepickerViewMonths')) {
|
|
533
|
+
// clicked a month cell
|
|
534
|
+
options.current.setMonth(tblEl.find('tbody.datepickerMonths td').index(parentEl));
|
|
535
|
+
options.current.setFullYear(parseInt(tblEl.find('thead th a.datepickerMonth span').text(), 10));
|
|
536
|
+
options.current.addMonths(currentCal - tblIndex);
|
|
537
|
+
tblEl.eq(0).toggleClass('datepickerViewMonths datepickerViewDays');
|
|
538
|
+
} else if(tblEl.eq(0).hasClass('datepickerViewYears')) {
|
|
539
|
+
// clicked a year cell
|
|
540
|
+
options.current.setFullYear(parseInt(el.text(), 10));
|
|
541
|
+
tblEl.eq(0).toggleClass('datepickerViewYears datepickerViewMonths');
|
|
542
|
+
} else {
|
|
543
|
+
// clicked a day cell
|
|
544
|
+
var val = parseInt(el.text(), 10);
|
|
545
|
+
tmp.addMonths(tblIndex - currentCal);
|
|
546
|
+
if (parentEl.hasClass('datepickerNotInMonth')) {
|
|
547
|
+
tmp.addMonths(val > 15 ? -1 : 1);
|
|
548
|
+
}
|
|
549
|
+
tmp.setDate(val);
|
|
550
|
+
switch (options.mode) {
|
|
551
|
+
case 'multiple':
|
|
552
|
+
val = (tmp.setHours(0,0,0,0)).valueOf();
|
|
553
|
+
if ($.inArray(val, options.date) > -1) {
|
|
554
|
+
$.each(options.date, function(nr, dat){
|
|
555
|
+
if (dat == val) {
|
|
556
|
+
options.date.splice(nr,1);
|
|
557
|
+
return false;
|
|
558
|
+
}
|
|
559
|
+
});
|
|
560
|
+
} else {
|
|
561
|
+
options.date.push(val);
|
|
562
|
+
}
|
|
563
|
+
break;
|
|
564
|
+
case 'range':
|
|
565
|
+
if (!options.lastSel) {
|
|
566
|
+
// first click: set to the start of the day
|
|
567
|
+
options.date[0] = (tmp.setHours(0,0,0,0)).valueOf();
|
|
568
|
+
}
|
|
569
|
+
// get the very end of the day clicked
|
|
570
|
+
val = (tmp.setHours(23,59,59,0)).valueOf();
|
|
571
|
+
|
|
572
|
+
if (val < options.date[0]) {
|
|
573
|
+
// second range click < first
|
|
574
|
+
options.date[1] = options.date[0] + 86399000; // starting date + 1 day
|
|
575
|
+
options.date[0] = val - 86399000; // minus 1 day
|
|
576
|
+
|
|
577
|
+
} else {
|
|
578
|
+
// initial range click, or final range click >= first
|
|
579
|
+
options.date[1] = val;
|
|
580
|
+
}
|
|
581
|
+
options.lastSel = !options.lastSel;
|
|
582
|
+
changedRange = !options.lastSel;
|
|
583
|
+
break;
|
|
584
|
+
default:
|
|
585
|
+
options.date = tmp.valueOf();
|
|
586
|
+
break;
|
|
587
|
+
}
|
|
588
|
+
changed = true;
|
|
589
|
+
}
|
|
590
|
+
fillIt = true;
|
|
591
|
+
}
|
|
592
|
+
if(fillIt) {
|
|
593
|
+
fill(this);
|
|
594
|
+
}
|
|
595
|
+
if(changed) {
|
|
596
|
+
options.onChange.apply(this, prepareDate(options));
|
|
597
|
+
}
|
|
598
|
+
if(changedRange) {
|
|
599
|
+
options.onRangeChange.apply(this, prepareDate(options));
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
return false;
|
|
603
|
+
},
|
|
604
|
+
|
|
605
|
+
/**
|
|
606
|
+
* Internal method, called from the public getDate() method, and when
|
|
607
|
+
* invoking the onChange callback function
|
|
608
|
+
*
|
|
609
|
+
* @param object options with the following attributes: 'mode' which can
|
|
610
|
+
* be one of 'single', 'range', or 'multiple'. Attribute 'date'
|
|
611
|
+
* which will be a single timestamp when 'mode' is 'single', or
|
|
612
|
+
* an array of timestamps otherwise. Attribute 'el' which is the
|
|
613
|
+
* HTML element that DatePicker was invoked upon.
|
|
614
|
+
* @return array where the first item is either a Date object, or an
|
|
615
|
+
* array of Date objects, depending on the DatePicker mode, and
|
|
616
|
+
* the second item is the HTMLElement that DatePicker was invoked
|
|
617
|
+
* upon.
|
|
618
|
+
*/
|
|
619
|
+
prepareDate = function (options) {
|
|
620
|
+
var dates = null;
|
|
621
|
+
if (options.mode == 'single') {
|
|
622
|
+
if(options.date) dates = new Date(options.date);
|
|
623
|
+
} else {
|
|
624
|
+
dates = new Array();
|
|
625
|
+
$(options.date).each(function(i, val){
|
|
626
|
+
dates.push(new Date(val));
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
return [dates, options.el];
|
|
630
|
+
},
|
|
631
|
+
|
|
632
|
+
/**
|
|
633
|
+
* Internal method, returns an object containing the viewport dimensions
|
|
634
|
+
*/
|
|
635
|
+
getViewport = function () {
|
|
636
|
+
var m = document.compatMode == 'CSS1Compat';
|
|
637
|
+
return {
|
|
638
|
+
l : window.pageXOffset || (m ? document.documentElement.scrollLeft : document.body.scrollLeft),
|
|
639
|
+
t : window.pageYOffset || (m ? document.documentElement.scrollTop : document.body.scrollTop),
|
|
640
|
+
w : window.innerWidth || (m ? document.documentElement.clientWidth : document.body.clientWidth),
|
|
641
|
+
h : window.innerHeight || (m ? document.documentElement.clientHeight : document.body.clientHeight)
|
|
642
|
+
};
|
|
643
|
+
},
|
|
644
|
+
|
|
645
|
+
/**
|
|
646
|
+
* Internal method, returns true if el is a child of parentEl
|
|
647
|
+
*/
|
|
648
|
+
isChildOf = function(parentEl, el, container) {
|
|
649
|
+
if(parentEl == el) {
|
|
650
|
+
return true;
|
|
651
|
+
}
|
|
652
|
+
if(parentEl.contains) {
|
|
653
|
+
return parentEl.contains(el);
|
|
654
|
+
}
|
|
655
|
+
if( parentEl.compareDocumentPosition ) {
|
|
656
|
+
return !!(parentEl.compareDocumentPosition(el) & 16);
|
|
657
|
+
}
|
|
658
|
+
var prEl = el.parentNode;
|
|
659
|
+
while(prEl && prEl != container) {
|
|
660
|
+
if(prEl == parentEl)
|
|
661
|
+
return true;
|
|
662
|
+
prEl = prEl.parentNode;
|
|
663
|
+
}
|
|
664
|
+
return false;
|
|
665
|
+
},
|
|
666
|
+
|
|
667
|
+
/**
|
|
668
|
+
* Bound to the HTML DatePicker element when it's not inline, and also
|
|
669
|
+
* can be called directly to show the bound datepicker. A DatePicker
|
|
670
|
+
* calendar shown with this method will hide on a mouseclick outside
|
|
671
|
+
* of the calendar.
|
|
672
|
+
*
|
|
673
|
+
* Method is not applicable for inline DatePickers
|
|
674
|
+
*/
|
|
675
|
+
show = function (ev) {
|
|
676
|
+
var cal = $('#' + $(this).data('datepickerId'));
|
|
677
|
+
if (!cal.is(':visible')) {
|
|
678
|
+
var calEl = cal.get(0);
|
|
679
|
+
var options = cal.data('datepicker');
|
|
680
|
+
|
|
681
|
+
var test = options.onBeforeShow.apply(this, [calEl]);
|
|
682
|
+
if(options.onBeforeShow.apply(this, [calEl]) == false) {
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
fill(calEl);
|
|
687
|
+
var pos = $(this).offset();
|
|
688
|
+
var viewPort = getViewport();
|
|
689
|
+
var top = pos.top;
|
|
690
|
+
var left = pos.left;
|
|
691
|
+
cal.css({
|
|
692
|
+
visibility: 'hidden',
|
|
693
|
+
display: 'block'
|
|
694
|
+
});
|
|
695
|
+
layout(calEl);
|
|
696
|
+
switch (options.position){
|
|
697
|
+
case 'top':
|
|
698
|
+
top -= calEl.offsetHeight;
|
|
699
|
+
break;
|
|
700
|
+
case 'left':
|
|
701
|
+
left -= calEl.offsetWidth;
|
|
702
|
+
break;
|
|
703
|
+
case 'right':
|
|
704
|
+
left += this.offsetWidth;
|
|
705
|
+
break;
|
|
706
|
+
case 'bottom':
|
|
707
|
+
top += this.offsetHeight;
|
|
708
|
+
break;
|
|
709
|
+
}
|
|
710
|
+
if(top + calEl.offsetHeight > viewPort.t + viewPort.h) {
|
|
711
|
+
top = pos.top - calEl.offsetHeight;
|
|
712
|
+
}
|
|
713
|
+
if(top < viewPort.t) {
|
|
714
|
+
top = pos.top + this.offsetHeight + calEl.offsetHeight;
|
|
715
|
+
}
|
|
716
|
+
if(left + calEl.offsetWidth > viewPort.l + viewPort.w) {
|
|
717
|
+
left = pos.left - calEl.offsetWidth;
|
|
718
|
+
}
|
|
719
|
+
if(left < viewPort.l) {
|
|
720
|
+
left = pos.left + this.offsetWidth
|
|
721
|
+
}
|
|
722
|
+
cal.css({
|
|
723
|
+
visibility: 'visible',
|
|
724
|
+
display: 'block',
|
|
725
|
+
top: top + 'px',
|
|
726
|
+
left: left + 'px'
|
|
727
|
+
});
|
|
728
|
+
options.onAfterShow.apply(this, [cal.get(0)]);
|
|
729
|
+
$(document).bind('mousedown', {cal: cal, trigger: this}, hide); // global listener so clicking outside the calendar will close it
|
|
730
|
+
}
|
|
731
|
+
return false;
|
|
732
|
+
},
|
|
733
|
+
|
|
734
|
+
/**
|
|
735
|
+
* Hide a non-inline DatePicker calendar.
|
|
736
|
+
*
|
|
737
|
+
* Not applicable for inline DatePickers.
|
|
738
|
+
*
|
|
739
|
+
* @param ev Event object
|
|
740
|
+
*/
|
|
741
|
+
hide = function (ev) {
|
|
742
|
+
if (ev.target != ev.data.trigger && !isChildOf(ev.data.cal.get(0), ev.target, ev.data.cal.get(0))) {
|
|
743
|
+
if (ev.data.cal.data('datepicker').onBeforeHide.apply(this, [ev.data.cal.get(0)]) != false) {
|
|
744
|
+
ev.data.cal.hide();
|
|
745
|
+
ev.data.cal.data('datepicker').onAfterHide.apply(this, [ev.data.cal.get(0)]);
|
|
746
|
+
$(document).unbind('mousedown', hide); // remove the global listener
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
},
|
|
750
|
+
|
|
751
|
+
/**
|
|
752
|
+
* Internal method to normalize the selected date based on the current
|
|
753
|
+
* calendar mode.
|
|
754
|
+
*/
|
|
755
|
+
normalizeDate = function (mode, date) {
|
|
756
|
+
// if range/multi mode, make sure that the current date value is at least an empty array
|
|
757
|
+
if(mode != 'single' && !date) date = [];
|
|
758
|
+
|
|
759
|
+
// if we have a selected date and not a null or empty array
|
|
760
|
+
if(date && (!$.isArray(date) || date.length > 0)) {
|
|
761
|
+
// Create a standardized date depending on the calendar mode
|
|
762
|
+
if (mode != 'single') {
|
|
763
|
+
if (!$.isArray(date)) {
|
|
764
|
+
date = [((new Date(date)).setHours(0,0,0,0)).valueOf()];
|
|
765
|
+
if (mode == 'range') {
|
|
766
|
+
// create a range of one day
|
|
767
|
+
date.push(((new Date(date[0])).setHours(23,59,59,0)).valueOf());
|
|
768
|
+
}
|
|
769
|
+
} else {
|
|
770
|
+
for (var i = 0; i < date.length; i++) {
|
|
771
|
+
date[i] = ((new Date(date[i])).setHours(0,0,0,0)).valueOf();
|
|
772
|
+
}
|
|
773
|
+
if (mode == 'range') {
|
|
774
|
+
// for range mode, create the other end of the range
|
|
775
|
+
if(date.length == 1) date.push(new Date(date[0]));
|
|
776
|
+
date[1] = ((new Date(date[1])).setHours(23,59,59,0)).valueOf();
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
} else {
|
|
780
|
+
// mode is single, convert date object into a timestamp
|
|
781
|
+
date = ((new Date(date)).setHours(0,0,0,0)).valueOf();
|
|
782
|
+
}
|
|
783
|
+
// at this point date is either a timestamp at hour zero
|
|
784
|
+
// for 'single' mode, an array of timestamps at hour zero for
|
|
785
|
+
// 'multiple' mode, or a two-item array with timestamps at hour
|
|
786
|
+
// zero and hour 23:59 for 'range' mode
|
|
787
|
+
}
|
|
788
|
+
return date;
|
|
789
|
+
};
|
|
790
|
+
return {
|
|
791
|
+
/**
|
|
792
|
+
* 'Public' functions
|
|
793
|
+
*/
|
|
794
|
+
|
|
795
|
+
/**
|
|
796
|
+
* Called when element.DatePicker() is invoked
|
|
797
|
+
*
|
|
798
|
+
* Note that 'this' is the HTML element that DatePicker was invoked upon
|
|
799
|
+
* @see DatePicker()
|
|
800
|
+
*/
|
|
801
|
+
init: function(options){
|
|
802
|
+
options = $.extend({}, defaults, options||{});
|
|
803
|
+
extendDate(options.locale);
|
|
804
|
+
options.calendars = Math.max(1, parseInt(options.calendars,10)||1);
|
|
805
|
+
options.mode = /single|multiple|range/.test(options.mode) ? options.mode : 'single';
|
|
806
|
+
|
|
807
|
+
return this.each(function(){
|
|
808
|
+
if (!$(this).data('datepicker')) {
|
|
809
|
+
options.el = this;
|
|
810
|
+
|
|
811
|
+
options.date = normalizeDate(options.mode, options.date);
|
|
812
|
+
|
|
813
|
+
if (!options.current) {
|
|
814
|
+
options.current = new Date();
|
|
815
|
+
} else {
|
|
816
|
+
options.current = new Date(options.current);
|
|
817
|
+
}
|
|
818
|
+
options.current.setDate(1);
|
|
819
|
+
options.current.setHours(0,0,0,0);
|
|
820
|
+
|
|
821
|
+
var id = 'datepicker_' + parseInt(Math.random() * 1000), cnt;
|
|
822
|
+
options.id = id;
|
|
823
|
+
$(this).data('datepickerId', options.id);
|
|
824
|
+
var cal = $(tpl.wrapper).attr('id', id).bind('click', click).data('datepicker', options);
|
|
825
|
+
if (options.className) {
|
|
826
|
+
cal.addClass(options.className);
|
|
827
|
+
}
|
|
828
|
+
var html = '';
|
|
829
|
+
for (var i = 0; i < options.calendars; i++) {
|
|
830
|
+
cnt = options.starts;
|
|
831
|
+
if (i > 0) {
|
|
832
|
+
html += tpl.space;
|
|
833
|
+
}
|
|
834
|
+
// calendar header template
|
|
835
|
+
html += tmpl(tpl.head.join(''), {
|
|
836
|
+
prev: options.prev,
|
|
837
|
+
next: options.next,
|
|
838
|
+
day1: options.locale.daysMin[(cnt++)%7],
|
|
839
|
+
day2: options.locale.daysMin[(cnt++)%7],
|
|
840
|
+
day3: options.locale.daysMin[(cnt++)%7],
|
|
841
|
+
day4: options.locale.daysMin[(cnt++)%7],
|
|
842
|
+
day5: options.locale.daysMin[(cnt++)%7],
|
|
843
|
+
day6: options.locale.daysMin[(cnt++)%7],
|
|
844
|
+
day7: options.locale.daysMin[(cnt++)%7]
|
|
845
|
+
});
|
|
846
|
+
}
|
|
847
|
+
cal
|
|
848
|
+
.find('tr:first').append(html)
|
|
849
|
+
.find('table').addClass(views[options.view]);
|
|
850
|
+
fill(cal.get(0));
|
|
851
|
+
if (options.inline) {
|
|
852
|
+
cal.appendTo(this).show().css('position', 'relative');
|
|
853
|
+
layout(cal.get(0));
|
|
854
|
+
} else {
|
|
855
|
+
cal.appendTo(document.body);
|
|
856
|
+
$(this).bind(options.showOn, show);
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
});
|
|
860
|
+
},
|
|
861
|
+
|
|
862
|
+
/**
|
|
863
|
+
* Shows the DatePicker, applicable only when the picker is not inline
|
|
864
|
+
*
|
|
865
|
+
* @return the DatePicker HTML element
|
|
866
|
+
* @see DatePickerShow()
|
|
867
|
+
*/
|
|
868
|
+
showPicker: function() {
|
|
869
|
+
return this.each( function() {
|
|
870
|
+
if ($(this).data('datepickerId')) {
|
|
871
|
+
var cal = $('#' + $(this).data('datepickerId'));
|
|
872
|
+
var options = cal.data('datepicker');
|
|
873
|
+
if(!options.inline) {
|
|
874
|
+
show.apply(this);
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
});
|
|
878
|
+
},
|
|
879
|
+
|
|
880
|
+
/**
|
|
881
|
+
* Hides the DatePicker, applicable only when the picker is not inline
|
|
882
|
+
*
|
|
883
|
+
* @return the DatePicker HTML element
|
|
884
|
+
* @see DatePickerHide()
|
|
885
|
+
*/
|
|
886
|
+
hidePicker: function() {
|
|
887
|
+
return this.each( function() {
|
|
888
|
+
if ($(this).data('datepickerId')) {
|
|
889
|
+
var cal = $('#' + $(this).data('datepickerId'));
|
|
890
|
+
var options = cal.data('datepicker');
|
|
891
|
+
if(!options.inline) {
|
|
892
|
+
$('#' + $(this).data('datepickerId')).hide();
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
});
|
|
896
|
+
},
|
|
897
|
+
|
|
898
|
+
/**
|
|
899
|
+
* Sets the DatePicker current date, and optionally shifts the current
|
|
900
|
+
* calendar to that date.
|
|
901
|
+
*
|
|
902
|
+
* @param Date|String|int|Array date The currently selected date(s).
|
|
903
|
+
* This can be: a single date, an array
|
|
904
|
+
* of two dates (sets a range when 'mode' is 'range'), or an array of
|
|
905
|
+
* any number of dates (selects all dates when 'mode' is 'multiple'.
|
|
906
|
+
* The supplied dates can be any one of: Date object, milliseconds
|
|
907
|
+
* (as from date.getTime(), date.valueOf()), or a date string
|
|
908
|
+
* parseable by Date.parse().
|
|
909
|
+
* @param boolean shiftTo if true, shifts the visible calendar to the
|
|
910
|
+
* newly set date(s)
|
|
911
|
+
*
|
|
912
|
+
* @see DatePickerSetDate()
|
|
913
|
+
*/
|
|
914
|
+
setDate: function(date, shiftTo){
|
|
915
|
+
return this.each(function(){
|
|
916
|
+
if ($(this).data('datepickerId')) {
|
|
917
|
+
var cal = $('#' + $(this).data('datepickerId'));
|
|
918
|
+
var options = cal.data('datepicker');
|
|
919
|
+
options.date = normalizeDate(options.mode, date);
|
|
920
|
+
|
|
921
|
+
if (shiftTo) {
|
|
922
|
+
options.current = new Date(options.mode != 'single' ? options.date[0] : options.date);
|
|
923
|
+
}
|
|
924
|
+
fill(cal.get(0));
|
|
925
|
+
}
|
|
926
|
+
});
|
|
927
|
+
},
|
|
928
|
+
|
|
929
|
+
/**
|
|
930
|
+
* Returns the currently selected date(s) and the datepicker element.
|
|
931
|
+
*
|
|
932
|
+
* @return array where the first element is the selected date(s) When calendar mode is 'single' this
|
|
933
|
+
* is a single date object, or null if no date is selected. When calendar mode is 'range', this is an array containing
|
|
934
|
+
* a 'from' and 'to' date objects, or the empty array if no date range is selected. When calendar mode is 'multiple' this
|
|
935
|
+
* is an array of Date objects, or the empty array if no date is selected.
|
|
936
|
+
* The second element is the HTMLElement that DatePicker was invoked upon
|
|
937
|
+
*
|
|
938
|
+
* @see DatePickerGetDate()
|
|
939
|
+
*/
|
|
940
|
+
getDate: function() {
|
|
941
|
+
if (this.size() > 0) {
|
|
942
|
+
return prepareDate($('#' + $(this).data('datepickerId')).data('datepicker'));
|
|
943
|
+
}
|
|
944
|
+
},
|
|
945
|
+
|
|
946
|
+
/**
|
|
947
|
+
* Clears the currently selected date(s)
|
|
948
|
+
*
|
|
949
|
+
* @see DatePickerClear()
|
|
950
|
+
*/
|
|
951
|
+
clear: function(){
|
|
952
|
+
return this.each(function(){
|
|
953
|
+
if ($(this).data('datepickerId')) {
|
|
954
|
+
var cal = $('#' + $(this).data('datepickerId'));
|
|
955
|
+
var options = cal.data('datepicker');
|
|
956
|
+
if (options.mode == 'single') {
|
|
957
|
+
options.date = null;
|
|
958
|
+
} else {
|
|
959
|
+
options.date = [];
|
|
960
|
+
}
|
|
961
|
+
fill(cal.get(0));
|
|
962
|
+
}
|
|
963
|
+
});
|
|
964
|
+
},
|
|
965
|
+
|
|
966
|
+
/**
|
|
967
|
+
* Only applicable when the DatePicker is inline
|
|
968
|
+
*
|
|
969
|
+
* @see DatePickerLayout()
|
|
970
|
+
*/
|
|
971
|
+
fixLayout: function(){
|
|
972
|
+
return this.each(function(){
|
|
973
|
+
if ($(this).data('datepickerId')) {
|
|
974
|
+
var cal = $('#' + $(this).data('datepickerId'));
|
|
975
|
+
var options = cal.data('datepicker');
|
|
976
|
+
if(options.inline) {
|
|
977
|
+
layout(cal.get(0));
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
});
|
|
981
|
+
}
|
|
982
|
+
};
|
|
983
|
+
}(); // DatePicker
|
|
984
|
+
|
|
985
|
+
// Extend jQuery with the following functions so that they can be called on HTML elements, ie: $('#widgetCalendar').DatePicker();
|
|
986
|
+
$.fn.extend({
|
|
987
|
+
DatePicker: DatePicker.init,
|
|
988
|
+
DatePickerHide: DatePicker.hidePicker,
|
|
989
|
+
DatePickerShow: DatePicker.showPicker,
|
|
990
|
+
DatePickerSetDate: DatePicker.setDate,
|
|
991
|
+
DatePickerGetDate: DatePicker.getDate,
|
|
992
|
+
DatePickerClear: DatePicker.clear,
|
|
993
|
+
DatePickerLayout: DatePicker.fixLayout
|
|
994
|
+
});
|
|
995
|
+
|
|
996
|
+
tmpl = function tmpl(str, data){
|
|
997
|
+
// Figure out if we're getting a template, or if we need to
|
|
998
|
+
// load the template - and be sure to cache the result.
|
|
999
|
+
var fn = !/\W/.test(str) ?
|
|
1000
|
+
cache[str] = cache[str] ||
|
|
1001
|
+
tmpl(document.getElementById(str).innerHTML) :
|
|
1002
|
+
|
|
1003
|
+
// Generate a reusable function that will serve as a template
|
|
1004
|
+
// generator (and which will be cached).
|
|
1005
|
+
new Function("obj",
|
|
1006
|
+
"var p=[],print=function(){p.push.apply(p,arguments);};" +
|
|
1007
|
+
|
|
1008
|
+
// Introduce the data as local variables using with(){}
|
|
1009
|
+
"with(obj){p.push('" +
|
|
1010
|
+
|
|
1011
|
+
// Convert the template into pure JavaScript
|
|
1012
|
+
str
|
|
1013
|
+
.replace(/[\r\t\n]/g, " ")
|
|
1014
|
+
.split("<%").join("\t")
|
|
1015
|
+
.replace(/((^|%>)[^\t]*)'/g, "$1\r")
|
|
1016
|
+
.replace(/\t=(.*?)%>/g, "',$1,'")
|
|
1017
|
+
.split("\t").join("');")
|
|
1018
|
+
.split("%>").join("p.push('")
|
|
1019
|
+
.split("\r").join("\\'")
|
|
1020
|
+
+ "');}return p.join('');");
|
|
1021
|
+
|
|
1022
|
+
// Provide some basic currying to the user
|
|
1023
|
+
return data ? fn( data ) : fn;
|
|
1024
|
+
};
|
|
1025
|
+
|
|
1026
|
+
})(jQuery);
|