WordPress Online Booking and Scheduling Plugin – Bookly - Version 3.3

Version Description

  • Added option to hide date and time selection at the first step
  • Fixed import of customers
Download this release

Release Info

Developer Ladela
Plugin Icon 128x128 WordPress Online Booking and Scheduling Plugin – Bookly
Version 3.3
Comparing to
See all releases

Version 3.3

Files changed (123) hide show
  1. backend/AB_Backend.php +244 -0
  2. backend/modules/appearance/AB_AppearanceController.php +83 -0
  3. backend/modules/appearance/resources/css/appearance.css +25 -0
  4. backend/modules/appearance/resources/js/appearance.js +341 -0
  5. backend/modules/appearance/templates/_1_service.php +187 -0
  6. backend/modules/appearance/templates/_2_time.php +113 -0
  7. backend/modules/appearance/templates/_3_details.php +47 -0
  8. backend/modules/appearance/templates/_4_payment.php +77 -0
  9. backend/modules/appearance/templates/_5_done.php +14 -0
  10. backend/modules/appearance/templates/_card_payment.php +34 -0
  11. backend/modules/appearance/templates/_progress_tracker.php +25 -0
  12. backend/modules/appearance/templates/index.php +84 -0
  13. backend/modules/calendar/AB_CalendarController.php +850 -0
  14. backend/modules/calendar/forms/AB_AppointmentForm.php +24 -0
  15. backend/modules/calendar/forms/AB_CustomerAppointmentForm.php +20 -0
  16. backend/modules/calendar/resources/css/calendar.css +174 -0
  17. backend/modules/calendar/resources/css/chosen-sprite.png +0 -0
  18. backend/modules/calendar/resources/css/chosen-sprite@2x.png +0 -0
  19. backend/modules/calendar/resources/css/chosen.css +437 -0
  20. backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/animated-overlay.gif +0 -0
  21. backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  22. backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  23. backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  24. backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  25. backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  26. backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  27. backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  28. backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  29. backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/ui-icons_222222_256x240.png +0 -0
  30. backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/ui-icons_2e83ff_256x240.png +0 -0
  31. backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/ui-icons_454545_256x240.png +0 -0
  32. backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/ui-icons_888888_256x240.png +0 -0
  33. backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/ui-icons_cd0a0a_256x240.png +0 -0
  34. backend/modules/calendar/resources/css/jquery-ui-1.10.4/jquery-ui.min.css +7 -0
  35. backend/modules/calendar/resources/css/jquery.weekcalendar.css +291 -0
  36. backend/modules/calendar/resources/images/box-small.png +0 -0
  37. backend/modules/calendar/resources/images/calendar.png +0 -0
  38. backend/modules/calendar/resources/images/calendar1.png +0 -0
  39. backend/modules/calendar/resources/images/chosen-sprite.png +0 -0
  40. backend/modules/calendar/resources/images/information.png +0 -0
  41. backend/modules/calendar/resources/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  42. backend/modules/calendar/resources/images/user-white.png +0 -0
  43. backend/modules/calendar/resources/images/user.png +0 -0
  44. backend/modules/calendar/resources/js/calendar.js +550 -0
  45. backend/modules/calendar/resources/js/calendar_daypicker.js +126 -0
  46. backend/modules/calendar/resources/js/calendar_weekpicker.js +168 -0
  47. backend/modules/calendar/resources/js/chosen.jquery.js +1229 -0
  48. backend/modules/calendar/resources/js/jquery.weekcalendar.js +2951 -0
  49. backend/modules/calendar/resources/js/ng-app.js +436 -0
  50. backend/modules/calendar/templates/appointment_form.php +97 -0
  51. backend/modules/calendar/templates/calendar.php +127 -0
  52. backend/modules/coupons/AB_CouponsController.php +27 -0
  53. backend/modules/coupons/resources/css/coupons.css +27 -0
  54. backend/modules/coupons/resources/js/coupons.js +6 -0
  55. backend/modules/coupons/templates/index.php +31 -0
  56. backend/modules/customer/AB_CustomerController.php +188 -0
  57. backend/modules/customer/forms/AB_CustomerForm.php +28 -0
  58. backend/modules/customer/resources/js/ng-app.js +226 -0
  59. backend/modules/customer/templates/_import.php +41 -0
  60. backend/modules/customer/templates/index.php +76 -0
  61. backend/modules/customer/templates/ng-new_customer_dialog.php +50 -0
  62. backend/modules/export/AB_ExportController.php +123 -0
  63. backend/modules/export/templates/index.php +48 -0
  64. backend/modules/notifications/AB_NotificationsController.php +53 -0
  65. backend/modules/notifications/templates/_tags_client_info.php +57 -0
  66. backend/modules/notifications/templates/_tags_evening_after.php +49 -0
  67. backend/modules/notifications/templates/_tags_evening_next_day.php +49 -0
  68. backend/modules/notifications/templates/_tags_event_next_day.php +9 -0
  69. backend/modules/notifications/templates/_tags_provider_info.php +69 -0
  70. backend/modules/notifications/templates/index.php +133 -0
  71. backend/modules/payment/AB_PaymentController.php +81 -0
  72. backend/modules/payment/templates/_alert.php +4 -0
  73. backend/modules/payment/templates/index.php +116 -0
  74. backend/modules/service/AB_ServiceController.php +174 -0
  75. backend/modules/service/forms/AB_CategoryForm.php +25 -0
  76. backend/modules/service/forms/AB_ServiceForm.php +48 -0
  77. backend/modules/service/resources/css/service.css +53 -0
  78. backend/modules/service/resources/js/service.js +303 -0
  79. backend/modules/service/templates/index.php +76 -0
  80. backend/modules/service/templates/list.php +33 -0
  81. backend/modules/service/templates/list_item.php +105 -0
  82. backend/modules/settings/AB_SettingsController.php +147 -0
  83. backend/modules/settings/forms/AB_BusinessHoursForm.php +64 -0
  84. backend/modules/settings/forms/AB_CompanyForm.php +61 -0
  85. backend/modules/settings/forms/AB_PaymentsForm.php +19 -0
  86. backend/modules/settings/resources/js/settings.js +129 -0
  87. backend/modules/settings/templates/_companyForm.php +49 -0
  88. backend/modules/settings/templates/_generalForm.php +150 -0
  89. backend/modules/settings/templates/_holidaysForm.php +24 -0
  90. backend/modules/settings/templates/_hoursForm.php +31 -0
  91. backend/modules/settings/templates/_paymentsForm.php +86 -0
  92. backend/modules/settings/templates/_purchaseCodeForm.php +26 -0
  93. backend/modules/settings/templates/index.php +48 -0
  94. backend/modules/staff/AB_StaffController.php +369 -0
  95. backend/modules/staff/forms/AB_StaffMemberEditForm.php +55 -0
  96. backend/modules/staff/forms/AB_StaffMemberForm.php +51 -0
  97. backend/modules/staff/forms/AB_StaffMemberNewForm.php +13 -0
  98. backend/modules/staff/forms/AB_StaffScheduleForm.php +46 -0
  99. backend/modules/staff/forms/AB_StaffScheduleItemBreakForm.php +27 -0
  100. backend/modules/staff/forms/AB_StaffServicesForm.php +136 -0
  101. backend/modules/staff/forms/widget/AB_TimeChoiceWidget.php +89 -0
  102. backend/modules/staff/resources/css/staff.css +39 -0
  103. backend/modules/staff/resources/js/staff.js +447 -0
  104. backend/modules/staff/templates/_breaks.php +79 -0
  105. backend/modules/staff/templates/edit.php +169 -0
  106. backend/modules/staff/templates/holidays.php +25 -0
  107. backend/modules/staff/templates/list.php +34 -0
  108. backend/modules/staff/templates/list_item.php +9 -0
  109. backend/modules/staff/templates/new.php +36 -0
  110. backend/modules/staff/templates/schedule.php +112 -0
  111. backend/modules/staff/templates/services.php +108 -0
  112. backend/modules/tinymce/AB_TinyMCE_Plugin.php +66 -0
  113. backend/modules/tinymce/resources/images/calendar.png +0 -0
  114. backend/modules/tinymce/resources/images/menu-icon.png +0 -0
  115. backend/modules/tinymce/templates/popup.php +401 -0
  116. backend/resources/bootstrap/css/bootstrap-editable.css +655 -0
  117. backend/resources/bootstrap/css/bootstrap.css +6278 -0
  118. backend/resources/bootstrap/css/bootstrap.min.css +865 -0
  119. backend/resources/bootstrap/img/clear.png +0 -0
  120. backend/resources/bootstrap/img/glyphicons-halflings-white.png +0 -0
  121. backend/resources/bootstrap/img/glyphicons-halflings.png +0 -0
  122. backend/resources/bootstrap/img/loading.gif +0 -0
  123. backend/resources/bootstrap/js/bootstrap-editable.min.js +7 -0
backend/AB_Backend.php ADDED
@@ -0,0 +1,244 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ include 'modules/appearance/AB_AppearanceController.php';
6
+ include 'modules/calendar/AB_CalendarController.php';
7
+ include 'modules/customer/AB_CustomerController.php';
8
+ include 'modules/export/AB_ExportController.php';
9
+ include 'modules/notifications/AB_NotificationsController.php';
10
+ include 'modules/payment/AB_PaymentController.php';
11
+ include 'modules/service/AB_ServiceController.php';
12
+ include 'modules/settings/AB_SettingsController.php';
13
+ include 'modules/staff/AB_StaffController.php';
14
+ include 'modules/coupons/AB_CouponsController.php';
15
+ include 'modules/tinymce/AB_TinyMCE_Plugin.php';
16
+
17
+ class AB_Backend {
18
+
19
+ public function __construct() {
20
+ add_action( 'admin_menu', array( $this, 'addAdminMenu' ) );
21
+
22
+ // Backend controllers.
23
+ $this->apearanceController = new AB_AppearanceController();
24
+ $this->calendarController = new AB_CalendarController();
25
+ $this->customerController = new AB_CustomerController();
26
+ $this->exportController = new AB_ExportController();
27
+ $this->notificationsController = new AB_NotificationsController();
28
+ $this->paymentController = new AB_PaymentController();
29
+ $this->serviceController = new AB_ServiceController();
30
+ $this->settingsController = new AB_SettingsController();
31
+ $this->staffController = new AB_StaffController();
32
+ $this->couponsController = new AB_CouponsController();
33
+
34
+ // Frontend controllers that work via admin-ajax.php.
35
+ $this->bookingController = new AB_BookingController();
36
+
37
+ add_action( 'wp_loaded', array( $this, 'init' ) );
38
+ add_action( 'admin_init', array( $this, 'addTinyMCEPlugin' ) );
39
+ }
40
+
41
+ public function addTinyMCEPlugin() {
42
+ /** @var WP_User $current_user */
43
+ global $current_user;
44
+ new AB_TinyMCE_Plugin();
45
+ }
46
+
47
+ public function init() {
48
+ if ( !session_id() ) {
49
+ @session_start();
50
+ }
51
+
52
+ if ( isset( $_POST[ 'action' ] ) ) {
53
+ switch ( $_POST[ 'action' ] ) {
54
+ case 'ab_update_staff':
55
+ $this->staffController->updateStaff();
56
+ break;
57
+ }
58
+ }
59
+
60
+ // for Appearance\Services\Settings all CSS and JS must be located directly in <HEAD>
61
+ if ( isset( $_GET[ 'page' ] ) && $_GET[ 'page' ] == 'ab-system-appearance' ) { // Appearance
62
+ // include StyleSheets
63
+ wp_enqueue_style( 'ab-style', plugins_url( 'resources/css/ab_style.css', __FILE__ ) );
64
+ wp_enqueue_style( 'ab-bootstrap', plugins_url( 'resources/bootstrap/css/bootstrap.min.css', __FILE__ ) );
65
+ wp_enqueue_style( 'ab-bootstrap-editable', plugins_url( 'resources/bootstrap/css/bootstrap-editable.css', __FILE__ ) );
66
+ wp_enqueue_style( 'ab-ladda-themeless', plugins_url( 'frontend/resources/css/ladda-themeless.min.css', __DIR__ ) );
67
+ wp_enqueue_style( 'ab-ladda-min', plugins_url( 'frontend/resources/css/ladda.min.css', __DIR__ ) );
68
+ wp_enqueue_style( 'ab-frontend-style', plugins_url( 'frontend/resources/css/ab_frontend_style.css', __DIR__ ) );
69
+ wp_enqueue_style( 'ab-columnizer', plugins_url( 'frontend/resources/css/ab-columnizer.css', __DIR__ ) );
70
+ wp_enqueue_style( 'ab-pickadate', plugins_url( 'frontend/resources/css/pickadate.classic.css', __DIR__ ) );
71
+ wp_enqueue_style( 'ab-columnizer', plugins_url( 'frontend/resources/css/ab-columnizer.css', __DIR__) );
72
+ wp_enqueue_style( 'wp-color-picker' );
73
+ wp_enqueue_style( 'ab-appearance', plugins_url( 'modules/appearance/resources/css/appearance.css', __FILE__ ) );
74
+ // include JavaScript
75
+ wp_enqueue_script( 'ab-bootstrap', plugins_url( 'resources/bootstrap/js/bootstrap.min.js', __FILE__ ), array( 'jquery' ) );
76
+ wp_enqueue_script( 'ab-bootstrap-editable', plugins_url( 'resources/bootstrap/js/bootstrap-editable.min.js', __FILE__ ), array( 'jquery' ) );
77
+ wp_enqueue_script( 'ab-appearance', plugins_url( 'modules/appearance/resources/js/appearance.js', __FILE__ ), array( 'jquery' ) );
78
+ wp_enqueue_script( 'ab-pickadate', plugins_url( 'frontend/resources/js/pickadate.legacy.min.js', __DIR__ ), array( 'jquery' ) );
79
+ wp_localize_script( 'ab-pickadate', 'BooklyL10n', array(
80
+ 'today' => __( 'Today', 'ab' ),
81
+ 'month' => array(
82
+ 'January' => __( 'January', 'ab' ),
83
+ 'February' => __( 'February', 'ab' ),
84
+ 'March' => __( 'March', 'ab' ),
85
+ 'April' => __( 'April', 'ab' ),
86
+ 'May' => __( 'May', 'ab' ),
87
+ 'June' => __( 'June', 'ab' ),
88
+ 'July' => __( 'July', 'ab' ),
89
+ 'August' => __( 'August', 'ab' ),
90
+ 'September' => __( 'September', 'ab' ),
91
+ 'October' => __( 'October', 'ab' ),
92
+ 'November' => __( 'November', 'ab' ),
93
+ 'December' => __( 'December', 'ab' )
94
+ ),
95
+ 'day' => array(
96
+ 'Sun' => __( 'Sun', 'ab' ),
97
+ 'Mon' => __( 'Mon', 'ab' ),
98
+ 'Tue' => __( 'Tue', 'ab' ),
99
+ 'Wed' => __( 'Wed', 'ab' ),
100
+ 'Thu' => __( 'Thu', 'ab' ),
101
+ 'Fri' => __( 'Fri', 'ab' ),
102
+ 'Sat' => __( 'Sat', 'ab' )
103
+ )
104
+ ) );
105
+ wp_enqueue_script( 'wp-color-picker' );
106
+ } elseif ( isset( $_GET[ 'page' ] ) && $_GET[ 'page' ] == 'ab-system-services' ) { // Services
107
+ // include StyleSheets
108
+ wp_enqueue_style( 'wp-color-picker' );
109
+ wp_enqueue_style( 'ab-style', plugins_url( 'resources/css/ab_style.css', __FILE__ ) );
110
+ wp_enqueue_style( 'ab-service', plugins_url( 'modules/service/resources/css/service.css', __FILE__ ) );
111
+ wp_enqueue_style( 'ab-bootstrap', plugins_url( 'resources/bootstrap/css/bootstrap.min.css', __FILE__ ) );
112
+ // include JavaScript
113
+ wp_enqueue_script( 'wp-color-picker' );
114
+ wp_enqueue_script( 'ab-popup', plugins_url( 'resources/js/ab_popup.js', __FILE__ ), array( 'jquery' ) );
115
+ wp_enqueue_script( 'ab-bootstrap', plugins_url( 'resources/bootstrap/js/bootstrap.min.js', __FILE__ ), array( 'jquery' ) );
116
+ wp_enqueue_script( 'ab-service', plugins_url( 'modules/service/resources/js/service.js', __FILE__ ), array( 'jquery' ) );
117
+ wp_localize_script( 'ab-service', 'BooklyL10n', array(
118
+ 'are_you_sure' => __( 'Are you sure?', 'ab' ),
119
+ 'please_select_at_least_one_service' => __( 'Please select at least one service.', 'ab'),
120
+ ) );
121
+ } elseif ( isset( $_GET[ 'page' ] ) && $_GET[ 'page' ] == 'ab-system-settings' ) { // Settings
122
+ // include StyleSheets
123
+ wp_enqueue_style( 'ab-style', plugins_url( 'resources/css/ab_style.css', __FILE__ ) );
124
+ wp_enqueue_style( 'ab-bootstrap', plugins_url( 'resources/bootstrap/css/bootstrap.min.css', __FILE__ ) );
125
+ wp_enqueue_style( 'ab-jCal', plugins_url( 'resources/css/jCal.css', __FILE__ ) );
126
+ // include JavaScript
127
+ wp_enqueue_script( 'ab-bootstrap', plugins_url( 'resources/bootstrap/js/bootstrap.min.js', __FILE__ ), array( 'jquery' ) );
128
+ wp_enqueue_script( 'ab-settings', plugins_url( 'modules/settings/resources/js/settings.js', __FILE__ ), array( 'jquery' ) );
129
+ wp_enqueue_script( 'ab-jCal', plugins_url( 'resources/js/jCal.js', __FILE__ ), array( 'jquery' ) );
130
+ wp_localize_script( 'ab-jCal', 'BooklyL10n', array(
131
+ 'we_are_not_working' => __( 'We are not working on this day', 'ab' ),
132
+ 'repeat' => __( 'Repeat every year', 'ab' ),
133
+ 'month' => array(
134
+ 'January' => __( 'January', 'ab' ),
135
+ 'February' => __( 'February', 'ab' ),
136
+ 'March' => __( 'March', 'ab' ),
137
+ 'April' => __( 'April', 'ab' ),
138
+ 'May' => __( 'May', 'ab' ),
139
+ 'June' => __( 'June', 'ab' ),
140
+ 'July' => __( 'July', 'ab' ),
141
+ 'August' => __( 'August', 'ab' ),
142
+ 'September' => __( 'September', 'ab' ),
143
+ 'October' => __( 'October', 'ab' ),
144
+ 'November' => __( 'November', 'ab' ),
145
+ 'December' => __( 'December', 'ab' )
146
+ ),
147
+ 'day' => array(
148
+ 'Mon' => __( 'Mon', 'ab' ),
149
+ 'Tue' => __( 'Tue', 'ab' ),
150
+ 'Wed' => __( 'Wed', 'ab' ),
151
+ 'Thu' => __( 'Thu', 'ab' ),
152
+ 'Fri' => __( 'Fri', 'ab' ),
153
+ 'Sat' => __( 'Sat', 'ab' ),
154
+ 'Sun' => __( 'Sun', 'ab' )
155
+ )
156
+ ) );
157
+ } elseif ( isset( $_GET[ 'page' ] ) && $_GET[ 'page' ] == 'ab-system-coupons' ) { // Coupons
158
+ // include StyleSheets
159
+ wp_enqueue_style( 'ab-style', plugins_url( 'resources/css/ab_style.css', __FILE__ ) );
160
+ wp_enqueue_style( 'ab-coupons', plugins_url( 'modules/coupons/resources/css/coupons.css', __FILE__ ) );
161
+ wp_enqueue_style( 'ab-bootstrap', plugins_url( 'resources/bootstrap/css/bootstrap.min.css', __FILE__ ) );
162
+ // include JavaScript
163
+ wp_enqueue_script( 'ab-popup', plugins_url( 'resources/js/ab_popup.js', __FILE__ ), array( 'jquery' ) );
164
+ wp_enqueue_script( 'ab-bootstrap', plugins_url( 'resources/bootstrap/js/bootstrap.min.js', __FILE__ ), array( 'jquery' ) );
165
+ wp_enqueue_script( 'ab-coupons', plugins_url( 'modules/coupons/resources/js/coupons.js', __FILE__ ), array( 'jquery' ) );
166
+ wp_localize_script( 'ab-coupons', 'BooklyL10n', array(
167
+ 'are_you_sure' => __( 'Are you sure?', 'ab' ),
168
+ 'please_select_at_least_one_coupon' => __( 'Please select at least one coupon.', 'ab'),
169
+ ) );
170
+ }
171
+ }
172
+
173
+ public function addAdminMenu() {
174
+ /** @var wpdb $wpdb */
175
+ global $wpdb;
176
+ /** @var WP_User $current_user */
177
+ global $current_user;
178
+
179
+ // translated submenu pages
180
+ $calendar = __( 'Calendar', 'ab' );
181
+ $staff_members = __( 'Staff members', 'ab' );
182
+ $services = __( 'Services', 'ab' );
183
+ $customers = __( 'Customers', 'ab' );
184
+ $notifications = __( 'Notifications', 'ab' );
185
+ $payments = __( 'Payments', 'ab' );
186
+ $appearance = __( 'Appearance', 'ab' );
187
+ $settings = __( 'Settings', 'ab' );
188
+ $export = __( 'Export', 'ab' );
189
+ $coupons = __( 'Coupons', 'ab' );
190
+
191
+ if ( in_array( 'administrator', $current_user->roles )
192
+ || $wpdb->get_var( $wpdb->prepare(
193
+ 'SELECT COUNT(id) AS numb FROM ab_staff WHERE wp_user_id = %d', $current_user->ID
194
+ ) ) ) {
195
+ if ( function_exists( 'add_options_page' ) ) {
196
+ $dynamic_position = '80.0000001' . mt_rand( 1, 1000 ); // position always is under `Settings`
197
+ add_menu_page( 'Bookly', 'Bookly', 'read', 'ab-system',
198
+ array( $this->staffController, 'renderStaffMembers'),
199
+ plugins_url('resources/images/menu.png', __FILE__), $dynamic_position );
200
+ add_submenu_page( 'ab-system', $calendar, $calendar, 'read', 'ab-system-calendar',
201
+ array( $this->calendarController, 'renderCalendar' ) );
202
+ add_submenu_page( 'ab-system', $staff_members, $staff_members, 'manage_options', 'ab-system-staff',
203
+ array( $this->staffController, 'renderStaffMembers' ) );
204
+ add_submenu_page( 'ab-system', $services, $services, 'manage_options', 'ab-system-services',
205
+ array( $this->serviceController, 'index' ) );
206
+ add_submenu_page( 'ab-system', $customers, $customers, 'manage_options', 'ab-system-customers',
207
+ array( $this->customerController, 'index' ) );
208
+ add_submenu_page( 'ab-system', $notifications, $notifications, 'manage_options', 'ab-system-notifications',
209
+ array( $this->notificationsController, 'index' ) );
210
+ add_submenu_page( 'ab-system', $payments, $payments, 'manage_options', 'ab-system-payments',
211
+ array( $this->paymentController, 'index' ) );
212
+ add_submenu_page( 'ab-system', $appearance, $appearance, 'manage_options', 'ab-system-appearance',
213
+ array( $this->apearanceController, 'index' ) );
214
+ add_submenu_page( 'ab-system', $coupons, $coupons, 'manage_options', 'ab-system-coupons',
215
+ array( $this->couponsController, 'index' ) );
216
+ add_submenu_page( 'ab-system', $settings, $settings, 'manage_options', 'ab-system-settings',
217
+ array( $this->settingsController, 'index' ) );
218
+ add_submenu_page( 'ab-system', $export, $export, 'manage_options', 'ab-system-export',
219
+ array( $this->exportController, 'index' ) );
220
+
221
+ $additional_menu_items = array();
222
+ $additional_menu_items = apply_filters('ab_add_submenu_page', $additional_menu_items);
223
+
224
+ foreach ($additional_menu_items as $menu_item) {
225
+ if (isset($menu_item['name']) && isset($menu_item['menu_slug']) && isset($menu_item['callback']) ) {
226
+
227
+ add_submenu_page(
228
+ 'ab-system',
229
+ $menu_item['name'],
230
+ $menu_item['name'],
231
+ 'manage_options',
232
+ $menu_item['menu_slug'],
233
+ $menu_item['callback']
234
+ );
235
+ }
236
+ }
237
+
238
+ global $submenu;
239
+ unset( $submenu[ 'ab-system' ][ 0 ] );
240
+ }
241
+ }
242
+ }
243
+
244
+ }
backend/modules/appearance/AB_AppearanceController.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ /**
6
+ * Class AB_AppearanceController
7
+ */
8
+ class AB_AppearanceController extends AB_Controller {
9
+
10
+ /**
11
+ * Default Action
12
+ */
13
+ public function index() {
14
+ // initialize steps (tabs)
15
+ $this->steps = array(
16
+ 1 => get_option( 'ab_appearance_text_step_service' ),
17
+ 2 => get_option( 'ab_appearance_text_step_time' ),
18
+ 3 => get_option( 'ab_appearance_text_step_details' ),
19
+ 4 => get_option( 'ab_appearance_text_step_payment' ),
20
+ 5 => get_option( 'ab_appearance_text_step_done' )
21
+ );
22
+
23
+ // render general layout
24
+ $this->render( 'index' );
25
+ } // index
26
+
27
+ /**
28
+ * Update options
29
+ */
30
+ public function executeUpdateAppearanceOptions() {
31
+ if ( $this->hasParameter( 'options' ) ) {
32
+ $get_option = $this->getParameter( 'options' );
33
+ $options = array(
34
+ // Info text.
35
+ 'ab_appearance_text_info_first_step' => $get_option[ 'text_info_first_step' ],
36
+ 'ab_appearance_text_info_second_step' => $get_option[ 'text_info_second_step' ],
37
+ 'ab_appearance_text_info_third_step' => $get_option[ 'text_info_third_step' ],
38
+ 'ab_appearance_text_info_fourth_step' => $get_option[ 'text_info_fourth_step' ],
39
+ 'ab_appearance_text_info_fifth_step' => $get_option[ 'text_info_fifth_step' ],
40
+ 'ab_appearance_text_info_coupon' => $get_option[ 'text_info_coupon' ],
41
+ // Color.
42
+ 'ab_appearance_color' => $get_option[ 'color' ],
43
+ // Step, label and option texts.
44
+ 'ab_appearance_text_step_service' => $get_option[ 'text_step_service' ],
45
+ 'ab_appearance_text_step_time' => $get_option[ 'text_step_time' ],
46
+ 'ab_appearance_text_step_details' => $get_option[ 'text_step_details' ],
47
+ 'ab_appearance_text_step_payment' => $get_option[ 'text_step_payment' ],
48
+ 'ab_appearance_text_step_done' => $get_option[ 'text_step_done' ],
49
+ 'ab_appearance_text_label_category' => $get_option[ 'text_label_category' ],
50
+ 'ab_appearance_text_label_service' => $get_option[ 'text_label_service' ],
51
+ 'ab_appearance_text_label_employee' => $get_option[ 'text_label_employee' ],
52
+ 'ab_appearance_text_label_select_date' => $get_option[ 'text_label_select_date' ],
53
+ 'ab_appearance_text_label_start_from' => $get_option[ 'text_label_start_from' ],
54
+ 'ab_appearance_text_label_finish_by' => $get_option[ 'text_label_finish_by' ],
55
+ 'ab_appearance_text_label_name' => $get_option[ 'text_label_name' ],
56
+ 'ab_appearance_text_label_phone' => $get_option[ 'text_label_phone' ],
57
+ 'ab_appearance_text_label_email' => $get_option[ 'text_label_email' ],
58
+ 'ab_appearance_text_label_notes' => $get_option[ 'text_label_notes' ],
59
+ 'ab_appearance_text_option_service' => $get_option[ 'text_option_service' ],
60
+ 'ab_appearance_text_option_category' => $get_option[ 'text_option_category' ],
61
+ 'ab_appearance_text_option_employee' => $get_option[ 'text_option_employee' ],
62
+ 'ab_appearance_text_label_coupon' => $get_option[ 'text_label_coupon' ],
63
+ // Checkboxes.
64
+ 'ab_appearance_show_progress_tracker' => $get_option[ 'progress_tracker' ],
65
+ );
66
+
67
+ // Save options.
68
+ foreach ( $options as $option_name => $option_value ) {
69
+ update_option( $option_name, $option_value );
70
+ }
71
+ }
72
+ exit;
73
+ } // executeUpdateAppearanceOptions
74
+
75
+ /**
76
+ * Override parent method to add 'wp_ajax_ab_' prefix
77
+ * so current 'execute*' methods look nicer.
78
+ */
79
+ protected function registerWpActions( $prefix = '' ) {
80
+ parent::registerWpActions( 'wp_ajax_ab_' );
81
+ } // registerWpActions
82
+
83
+ } // AB_AppearanceController
backend/modules/appearance/resources/css/appearance.css ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Backend-Appearance */
2
+
3
+ div.controls {
4
+ float: right;
5
+ margin-right: 15px;
6
+ margin-top: 10px;
7
+ }
8
+
9
+ span.spinner {
10
+ float: left;
11
+ margin-right: 20px;
12
+ }
13
+
14
+ div.ab-second-step-buttons div.ab-first-step-buttons div.ab-third-step-buttons div.ab-fourth-step-buttons div.ab-fifth-step-buttons {
15
+ float: left;
16
+ margin-left: 395px;
17
+ }
18
+
19
+ div.ab-second-step-buttons input.ab-back-forth-button {
20
+ /* styles */
21
+ }
22
+
23
+ div.ab-second-step-options {
24
+ /* styles */
25
+ }
backend/modules/appearance/resources/js/appearance.js ADDED
@@ -0,0 +1,341 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(function($) {
2
+ var // Progress Tracker
3
+ $progress_tracker_option = $('input#ab-progress-tracker-checkbox'),
4
+ // Tabs
5
+ $tabs = $('div.tabbable').find('.nav-tabs'),
6
+ $tab_content = $('div.tab-content'),
7
+ // Buttons.
8
+ $update_button = $('#update_button'),
9
+ $reset_button = $('#reset_button'),
10
+ // Texts.
11
+ $text_step_service = $('#ab-text-step-service'),
12
+ $text_step_time = $('#ab-text-step-time'),
13
+ $text_step_details = $('#ab-text-step-details'),
14
+ $text_step_payment = $('#ab-text-step-payment'),
15
+ $text_step_done = $('#ab-text-step-done'),
16
+ $text_label_category = $('#ab-text-label-category'),
17
+ $text_option_category = $('#ab-text-option-category'),
18
+ $text_option_service = $('#ab-text-option-service'),
19
+ $text_option_employee = $('#ab-text-option-employee'),
20
+ $text_label_service = $('#ab-text-label-service'),
21
+ $text_label_employee = $('#ab-text-label-employee'),
22
+ $text_label_select_date = $('#ab-text-label-select_date'),
23
+ $text_label_start_from = $('#ab-text-label-start_from'),
24
+ $text_label_finish_by = $('#ab-text-label-finish_by'),
25
+ $text_label_name = $('#ab-text-label-name'),
26
+ $text_label_phone = $('#ab-text-label-phone'),
27
+ $text_label_email = $('#ab-text-label-email'),
28
+ $text_label_notes = $('#ab-text-label-notes'),
29
+ $text_label_coupon = $('#ab-text-label-coupon'),
30
+ $text_info_service = $('#ab-text-info-first'),
31
+ $text_info_time = $('#ab-text-info-second'),
32
+ $text_info_details = $('#ab-text-info-third'),
33
+ $text_info_payment = $('#ab-text-info-fourth'),
34
+ $text_info_done = $('#ab-text-info-fifth'),
35
+ $text_info_coupon = $('#ab-text-info-coupon'),
36
+ $color_picker = $('.wp-color-picker'),
37
+ $ab_editable = $('.ab_editable');
38
+
39
+ // menu fix for WP 3.8.1
40
+ $('#toplevel_page_ab-system > ul').css('margin-left', '0px');
41
+
42
+ // Tabs
43
+ $tabs.find('.ab-step-tabs').on('click', function() {
44
+ var $step_id = $(this).data('step-id');
45
+ // hide all other tab content and show only current
46
+ $tab_content.children('div[data-step-id!="' + $step_id + '"]').removeClass('active').hide();
47
+ $tab_content.children('div[data-step-id="' + $step_id + '"]').addClass('active').show();
48
+ }).filter('li:first').trigger('click');
49
+
50
+ // Apply color from color picker.
51
+ var applyColor = function() {
52
+ var color_important = $color_picker.wpColorPicker('color') + '!important';
53
+ $('div.ab-progress-tracker').find('li.ab-step-tabs').filter('.active').find('a').css('color', $color_picker.wpColorPicker('color'));
54
+ $('div.ab-progress-tracker').find('li.ab-step-tabs').filter('.active').find('div.step').css('background', $color_picker.wpColorPicker('color'));
55
+ $('.ab-mobile-step_1 label').css('color', $color_picker.wpColorPicker('color'));
56
+ $('.ab-next-step, .ab-mobile-next-step').css('background', $color_picker.wpColorPicker('color'));
57
+ $('.ab-week-days label').css('background-color', $color_picker.wpColorPicker('color'));
58
+ $('.pickadate__calendar').attr('style', 'background: ' + color_important);
59
+ $('.pickadate__header').attr('style', 'border-bottom: ' + '1px solid ' + color_important);
60
+ // $('.pickadate__nav--next, .pickadate__nav--prev').attr('style', 'border-left: 6px solid ' + color_important);
61
+ // $('.pickadate__nav--next:before').attr('style', 'border-left: 6px solid ' + color_important);
62
+ // $('.pickadate__nav--prev:before').attr('style', 'border-right: 6px solid ' + color_important);
63
+ // $('.pickadate__day:hover').attr('style', 'color: ' + color_important);
64
+ // $('.pickadate__day--selected:hover').attr('style', '');
65
+ $('.pickadate__day--selected').attr('style', 'color: ' + color_important);
66
+ $('.pickadate__button--clear').attr('style', 'color: ' + color_important);
67
+ $('.pickadate__button--today').attr('style', 'color: ' + color_important);
68
+ $('.ab-columnizer .ab-available-day').css({
69
+ 'background': $color_picker.wpColorPicker('color'),
70
+ 'border-color': $color_picker.wpColorPicker('color')
71
+ });
72
+ $('.ladda-button').css('background-color', $color_picker.wpColorPicker('color'));
73
+ $('.ab-columnizer .ab-available-hour').off().hover(
74
+ function() { // mouse-on
75
+ $(this).css({
76
+ 'color': $color_picker.wpColorPicker('color'),
77
+ 'border': '2px solid ' + $color_picker.wpColorPicker('color')
78
+ });
79
+ $(this).find('.ab-hour-icon').css({
80
+ 'border-color': $color_picker.wpColorPicker('color'),
81
+ 'color': $color_picker.wpColorPicker('color')
82
+ });
83
+ $(this).find('.ab-hour-icon > span').css({
84
+ 'background': $color_picker.wpColorPicker('color')
85
+ });
86
+ },
87
+ function() { // mouse-out
88
+ $(this).css({
89
+ 'color': '#333333',
90
+ 'border': '1px solid ' + '#cccccc'
91
+ });
92
+ $(this).find('.ab-hour-icon').css({
93
+ 'border-color': '#333333',
94
+ 'color': '#cccccc'
95
+ });
96
+ $(this).find('.ab-hour-icon > span').css({
97
+ 'background': '#cccccc'
98
+ });
99
+ }
100
+ );
101
+ $('div.ab-formGroup > label.ab-formLabel').css('color', $color_picker.wpColorPicker('color'));
102
+ $('.ab-to-second-step, .ab-to-fourth-step, .ab-to-third-step, .ab-final-step')
103
+ .css('background', $color_picker.wpColorPicker('color'));
104
+ };
105
+ $color_picker.wpColorPicker({
106
+ change : function() {
107
+ applyColor();
108
+ }
109
+ });
110
+
111
+ $('.ab-requested-date-from').pickadate({
112
+ dateMin: true,
113
+ clear: false,
114
+ onRender: function() {
115
+ applyColor();
116
+ }
117
+ });
118
+
119
+ // Update options.
120
+ $update_button.on('click', function() {
121
+ var data = {
122
+ action: 'ab_update_appearance_options',
123
+ options: {
124
+ // Color.
125
+ 'color' : $color_picker.wpColorPicker('color'),
126
+ // Info text.
127
+ 'text_info_first_step' : $.trim($text_info_service.text() == 'Empty' ? '' : $text_info_service.text()),
128
+ 'text_info_second_step' : $.trim($text_info_time.text() == 'Empty' ? '' : $text_info_time.text()),
129
+ 'text_info_third_step' : $.trim($text_info_details.text() == 'Empty' ? '' : $text_info_details.text()),
130
+ 'text_info_fourth_step' : $.trim($text_info_payment.text() == 'Empty' ? '' : $text_info_payment.text()),
131
+ 'text_info_fifth_step' : $.trim($text_info_done.text() == 'Empty' ? '' : $text_info_done.text()),
132
+ 'text_info_coupon' : $.trim($text_info_coupon.text() == 'Empty' ? '' : $text_info_coupon.text()),
133
+ // Step and label texts.
134
+ 'text_step_service' : $.trim($text_step_service.text() == 'Empty' ? '' : $text_step_service.text()),
135
+ 'text_step_time' : $.trim($text_step_time.text() == 'Empty' ? '' : $text_step_time.text()),
136
+ 'text_step_details' : $.trim($text_step_details.text() == 'Empty' ? '' : $text_step_details.text()),
137
+ 'text_step_payment' : $.trim($text_step_payment.text() == 'Empty' ? '' : $text_step_payment.text()),
138
+ 'text_step_done' : $.trim($text_step_done.text() == 'Empty' ? '' : $text_step_done.text()),
139
+ 'text_label_category' : $.trim($text_label_category.text() == 'Empty' ? '' : $text_label_category.text()),
140
+ 'text_label_service' : $.trim($text_label_service.text() == 'Empty' ? '' : $text_label_service.text()),
141
+ 'text_label_employee' : $.trim($text_label_employee.text() == 'Empty' ? '' : $text_label_employee.text()),
142
+ 'text_label_select_date' : $.trim($text_label_select_date.text() == 'Empty' ? '' : $text_label_select_date.text()),
143
+ 'text_label_start_from' : $.trim($text_label_start_from.text() == 'Empty' ? '' : $text_label_start_from.text()),
144
+ 'text_label_finish_by' : $.trim($text_label_finish_by.text() == 'Empty' ? '' : $text_label_finish_by.text()),
145
+ 'text_label_name' : $.trim($text_label_name.text() == 'Empty' ? '' : $text_label_name.text()),
146
+ 'text_label_phone' : $.trim($text_label_phone.text() == 'Empty' ? '' : $text_label_phone.text()),
147
+ 'text_label_email' : $.trim($text_label_email.text() == 'Empty' ? '' : $text_label_email.text()),
148
+ 'text_label_notes' : $.trim($text_label_notes.text() == 'Empty' ? '' : $text_label_notes.text()),
149
+ 'text_label_coupon' : $.trim($text_label_coupon.text() == 'Empty' ? '' : $text_label_coupon.text()),
150
+ 'text_option_category' : $.trim($text_option_category.text() == 'Empty' ? '' : $text_option_category.text()),
151
+ 'text_option_service' : $.trim($text_option_service.text() == 'Empty' ? '' : $text_option_service.text()),
152
+ 'text_option_employee' : $.trim($text_option_employee.text() == 'Empty' ? '' : $text_option_employee.text()),
153
+ // Checkboxes.
154
+ 'progress_tracker' : Number($('#ab-progress-tracker-checkbox').is(':checked'))
155
+ } // options
156
+ }; // data
157
+
158
+ // update data and show spinner while updating
159
+ $('#update_spinner').show();
160
+ $.post(ajaxurl, data, function (response) {
161
+ $('#update_spinner').hide();
162
+ $('.alert').show();
163
+ });
164
+ });
165
+
166
+ // Reset options to defaults.
167
+ $reset_button.on('click', function() {
168
+ // Reset color.
169
+ $color_picker.wpColorPicker('color', $color_picker.data('selected'));
170
+
171
+ // Reset texts.
172
+ jQuery.each($('.editable'), function() {
173
+ var $default_value = $(this).data('default'),
174
+ $steps = $(this).data('link-class');
175
+
176
+ $(this).text($default_value); //default value for texts
177
+ $('.' + $steps).text($default_value); //default value for steps
178
+ $(this).editable('setValue', $default_value); // default value for editable inputs
179
+ });
180
+
181
+ // default value for multiple inputs
182
+ $text_label_category.editable('setValue', {
183
+ label: $text_label_category.text(),
184
+ option: $text_option_category.text(),
185
+ id_option: $text_label_category.data('link-class')
186
+ });
187
+
188
+ $text_label_service.editable('setValue', {
189
+ label: $text_label_service.text(),
190
+ option: $text_option_service.text(),
191
+ id_option: $text_label_service.data('link-class')
192
+ });
193
+
194
+ $text_label_employee.editable('setValue', {
195
+ label: $text_label_employee.text(),
196
+ option: $text_option_employee.text(),
197
+ id_option: $text_label_employee.data('link-class')
198
+ });
199
+
200
+ });
201
+
202
+ $progress_tracker_option.change(function(){
203
+ $(this).is(':checked') ? $('div.ab-progress-tracker').show() : $('div.ab-progress-tracker').hide();
204
+ }).trigger('change');
205
+
206
+ // Clickable week-days.
207
+ $('.ab-week-day').on('change', function () {
208
+ var self = $(this);
209
+ if (self.is(':checked') && !self.parent().hasClass('active')) {
210
+ self.parent().addClass('active');
211
+ } else if (self.parent().hasClass('active')) {
212
+ self.parent().removeClass('active')
213
+ }
214
+ });
215
+
216
+ /**
217
+ * Helper functions.
218
+ */
219
+ function nl2br(str, is_xhtml) {
220
+ var breakTag = (is_xhtml || typeof is_xhtml === 'undefined') ? '<br />' : '<br>';
221
+ return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1'+ breakTag +'$2');
222
+ }
223
+ function escapeHtml(string) {
224
+ var entityMap = {
225
+ "&": "&amp;",
226
+ "<": "&lt;",
227
+ ">": "&gt;",
228
+ '"': '&quot;',
229
+ "'": '&#39;',
230
+ "/": '&#x2F;'
231
+ };
232
+ return String(string).replace(/[&<>"'\/]/g, function (s) {
233
+ return entityMap[s];
234
+ });
235
+ }
236
+
237
+ var multiple = function (options) {
238
+ this.init('multiple', options, multiple.defaults);
239
+ };
240
+
241
+ //inherit from Abstract input
242
+ $.fn.editableutils.inherit(multiple, $.fn.editabletypes.abstractinput);
243
+
244
+ $.extend(multiple.prototype, {
245
+ render: function() {
246
+ this.$input = this.$tpl.find('input');
247
+ },
248
+
249
+ value2html: function(value, element) {
250
+ if(!value) {
251
+ $(element).empty();
252
+ return;
253
+ }
254
+ $(element).text(value.label);
255
+ $('#' + value.id_option).text(value.option);
256
+ },
257
+
258
+ activate: function () {
259
+ this.$input.filter('[name="label"]').focus();
260
+ },
261
+
262
+ value2input: function(value) {
263
+ if(!value) {
264
+ return;
265
+ }
266
+ this.$input.filter('[name="label"]').val(value.label);
267
+ this.$input.filter('[name="option"]').val(value.option);
268
+ this.$input.filter('[name="id_option"]').val(value.id_option);
269
+ },
270
+
271
+ input2value: function() {
272
+ return {
273
+ label: this.$input.filter('[name="label"]').val(),
274
+ option: this.$input.filter('[name="option"]').val(),
275
+ id_option: this.$input.filter('[name="id_option"]').val()
276
+ };
277
+ }
278
+ });
279
+
280
+ multiple.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
281
+ tpl: '<div class="editable-multiple"><label><input type="text" name="label" class="input-medium"></label></div>'+
282
+ '<div style="margin-top:5px;" class="editable-multiple"><label><input type="text" name="option" class="input-medium"><input type="hidden" name="id_option"></label></div>',
283
+
284
+ inputclass: ''
285
+ });
286
+
287
+ $.fn.editabletypes.multiple = multiple;
288
+
289
+ $text_label_category.editable({
290
+ value: {
291
+ label: $text_label_category.text(),
292
+ option: $text_option_category.text(),
293
+ id_option: $text_label_category.data('link-class')
294
+ }
295
+ });
296
+ $text_label_service.editable({
297
+ value: {
298
+ label: $text_label_service.text(),
299
+ option: $text_option_service.text(),
300
+ id_option: $text_label_service.data('link-class')
301
+ }
302
+ });
303
+ $text_label_employee.editable({
304
+ value: {
305
+ label: $text_label_employee.text(),
306
+ option: $text_option_employee.text(),
307
+ id_option: $text_label_employee.data('link-class')
308
+ }
309
+ });
310
+
311
+ $('#ab-text-info-first').add('#ab-text-info-second').add('#ab-text-info-third').add('#ab-text-info-fourth').add('#ab-text-info-fifth').add('#ab-text-info-coupon').editable({placement: 'right'});
312
+ $ab_editable.editable();
313
+
314
+ $.fn.editableform.template = '<form class="form-inline editableform"> <div class="control-group"> <div> <div class="editable-input"></div><div class="editable-buttons"></div></div><div style="margin-top: 10px;" class="editable-notes"></div><div class="editable-error-block"></div></div> </form>';
315
+
316
+ $ab_editable.on('shown', function(e, editable) {
317
+ $('.editable-notes').html($(e.target).data('notes'));
318
+ });
319
+
320
+ $("span[data-link-class^='text_step_']").on('save', function(e, params) {
321
+ $("span[data-link-class='" + $(e.target).data('link-class') + "']").editable('setValue', params.newValue);
322
+ $("span." + $(e.target).data('link-class')).text(params.newValue);
323
+ });
324
+
325
+ if(jQuery('.ab-authorizenet-payment').is(':checked')) {
326
+ jQuery('form.authorizenet').show();
327
+ }
328
+
329
+ if(jQuery('.ab-stripe-payment').is(':checked')) {
330
+ jQuery('form.stripe').show();
331
+ }
332
+
333
+ jQuery('input[type=radio]').change( function() {
334
+ jQuery('form.authorizenet').add('form.stripe').hide();
335
+ if(jQuery('.ab-authorizenet-payment').is(':checked')) {
336
+ jQuery('form.authorizenet').show();
337
+ } else if(jQuery('.ab-stripe-payment').is(':checked')) {
338
+ jQuery('form.stripe').show();
339
+ }
340
+ });
341
+ }); // jQuery
backend/modules/appearance/templates/_1_service.php ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <div class="ab-booking-form" style="overflow: hidden">
3
+
4
+ <!-- Progress Tracker-->
5
+ <?php $step = 1; include '_progress_tracker.php'; ?>
6
+
7
+ <div class="ab-first-step">
8
+ <div class="ab-row-fluid">
9
+ <span data-inputclass="input-xxlarge" data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_info_first_step' ) ); ?>" data-link-class="ab-text-info-first" class="ab-bold ab_editable" id="ab-text-info-first" data-rows="7" data-type="textarea" data-pk="1"><?php echo esc_html( get_option( 'ab_appearance_text_info_first_step' ) ) ?></span>
10
+ </div>
11
+ <div class=ab-service-form>
12
+ <div class="ab-mobile-step_1 ab-row-fluid">
13
+ <div class="ab-formGroup ab-left">
14
+ <label data-default="<?php echo get_option( 'ab_appearance_text_label_category' ); ?>" data-link-class="ab-text-option-category" class="ab-formLabel text_category_label" id="ab-text-label-category" data-type="multiple" data-pk="1"><?php echo esc_html(get_option( 'ab_appearance_text_label_category' )) ?></label>
15
+ <div class="ab-formField">
16
+ <select class="ab-formElement ab-select-mobile ab-select-category" style="width: 100%">
17
+ <option value="" class="editable" id="ab-text-option-category" data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_option_category' ) ); ?>"><?php echo esc_attr( get_option( 'ab_appearance_text_option_category' ) ); ?></option>
18
+ <option value="1">Cosmetic Dentistry</option>
19
+ <option value="2">Invisalign</option>
20
+ <option value="3">Orthodontics</option>
21
+ <option value="4">Dentures</option>
22
+ </select>
23
+ </div>
24
+ </div>
25
+ <div class="ab-formGroup ab-left">
26
+ <label data-default="<?php echo get_option( 'ab_appearance_text_label_service' ); ?>" data-link-class="ab-text-option-service" class="ab-formLabel text_service_label" id="ab-text-label-service" data-type="multiple" data-pk="1"><?php echo esc_html(get_option( 'ab_appearance_text_label_service' )) ?></label>
27
+ <div class="ab-formField">
28
+ <select class="ab-formElement ab-select-mobile ab-select-service" style="width: 100%">
29
+ <option value="" class="editable" id="ab-text-option-service" data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_option_service' ) ); ?>"><?php echo esc_attr( get_option( 'ab_appearance_text_option_service' ) ); ?></option>
30
+ <option value="1">Crown and Bridge</option>
31
+ <option value="2">Teeth Whitening</option>
32
+ <option value="3">Veneers</option>
33
+ <option value="4">Invisalign (invisable braces)</option>
34
+ <option value="5">Orthodontics (braces)</option>
35
+ <option value="6">Wisdom tooth Removal</option>
36
+ <option value="7">Root Canal Treatment</option>
37
+ <option value="8">Dentures</option>
38
+ </select>
39
+ </div>
40
+ </div>
41
+ <div class="ab-formGroup ab-lastGroup ab-left">
42
+ <label data-default="<?php echo get_option( 'ab_appearance_text_label_employee' ); ?>" data-link-class="ab-text-option-employee" class="ab-formLabel text_employee_label" id="ab-text-label-employee" data-type="multiple" data-pk="1"><?php echo esc_html(get_option( 'ab_appearance_text_label_employee' )) ?></label>
43
+ <div class="ab-formField">
44
+ <select class="ab-formElement ab-select-mobile ab-select-employee" style="width: 100%">
45
+ <option value="" class="editable" id="ab-text-option-employee" data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_option_employee' ) ); ?>"><?php echo esc_attr( get_option( 'ab_appearance_text_option_employee' ) ); ?></option>
46
+ <option value="1">Nick Knight</option>
47
+ <option value="2">Jane Howard</option>
48
+ <option value="3">Ashley Stamp</option>
49
+ <option value="4">Bradley Tannen</option>
50
+ <option value="5">Wayne Turner</option>
51
+ <option value="6">Emily Taylor</option>
52
+ <option value="7">Hugh Canberg</option>
53
+ <option value="8">Jim Gonzalez</option>
54
+ <option value="9">Nancy Stinson</option>
55
+ <option value="10">Marry Murphy</option>
56
+ </select>
57
+ </div>
58
+ </div>
59
+ <button class="ab-right ab-mobile-next-step ab-btn ab-none ladda-button orange zoom-in" onclick="return false">
60
+ <span><?php _e( 'Next', 'ab' ) ?></span>
61
+ </button>
62
+ </div>
63
+ <div class="ab-mobile-step_2">
64
+ <div class="ab-row-fluid">
65
+ <div class="ab-available-date ab-left">
66
+ <label data-default="<?php echo get_option( 'ab_appearance_text_label_select_date' ); ?>" data-link-class="text_select_date_label" class="ab_editable" id="ab-text-label-select_date" data-type="text" data-pk="1"><?php echo esc_html(get_option( 'ab_appearance_text_label_select_date' )) ?></label>
67
+ <div class="ab-input-wrap">
68
+ <span class="ab-requested-date-wrap">
69
+ <input class="select-list ab-requested-date-from select-list" type="text" value="29 November, 2013">
70
+ </span>
71
+ </div>
72
+ </div>
73
+ <div class="ab-available-days ab-left">
74
+ <ul class="ab-week-days">
75
+ <li>
76
+ <div class="ab-bold"><?php _e('Sun', 'ab' ) ?></div>
77
+ <label class="active">
78
+ <input class="ab-week-day ab-week-day-1" value="1" checked="checked" type="checkbox">
79
+ </label>
80
+ </li>
81
+ <li>
82
+ <div class="ab-bold"><?php _e( 'Mon', 'ab' ) ?></div>
83
+ <label class="active">
84
+ <input class="ab-week-day ab-week-day-2" value="2" checked="checked" type="checkbox">
85
+ </label>
86
+ </li>
87
+ <li>
88
+ <div class="ab-bold"><?php _e( 'Tue', 'ab' ) ?></div>
89
+ <label class="active">
90
+ <input class="ab-week-day ab-week-day-3" value="3" checked="checked" type="checkbox">
91
+ </label>
92
+ </li>
93
+ <li>
94
+ <div class="ab-bold"><?php _e( 'Wed', 'ab' ) ?></div>
95
+ <label class="active">
96
+ <input class="ab-week-day ab-week-day-4" value="4" checked="checked" type="checkbox">
97
+ </label>
98
+ </li>
99
+ <li>
100
+ <div class="ab-bold"><?php _e( 'Thu', 'ab' ) ?></div>
101
+ <label class="active">
102
+ <input class="ab-week-day ab-week-day-5" value="5" checked="checked" type="checkbox">
103
+ </label>
104
+ </li>
105
+ <li>
106
+ <div class="ab-bold"><?php _e( 'Fri', 'ab' ) ?></div>
107
+ <label class="active">
108
+ <input class="ab-week-day ab-week-day-6" value="6" checked="checked" type="checkbox">
109
+ </label>
110
+ </li>
111
+ <li>
112
+ <div class="ab-bold"><?php _e( 'Sat', 'ab' ) ?></div>
113
+ <label class="active">
114
+ <input class="ab-week-day ab-week-day-7" value="7" checked="checked" type="checkbox">
115
+ </label>
116
+ </li>
117
+ </ul>
118
+ </div>
119
+ <div class="ab-time-range ab-left">
120
+ <div class="ab-time-from ab-left">
121
+ <label data-default="<?php echo get_option( 'ab_appearance_text_label_start_from' ); ?>" data-link-class="text_start_from_label" class="ab_editable" id="ab-text-label-start_from" data-type="text" data-pk="1"><?php echo esc_html(get_option( 'ab_appearance_text_label_start_from' )) ?></label>
122
+ <div class="ab-select-wrap">
123
+ <select class="select-list ab-requested-time-from">
124
+ <option value="00:00">12:00 am</option>
125
+ <option value="01:00">1:00 am</option>
126
+ <option value="02:00">2:00 am</option>
127
+ <option value="03:00">3:00 am</option>
128
+ <option value="04:00">4:00 am</option>
129
+ <option value="05:00">5:00 am</option>
130
+ <option value="06:00">6:00 am</option>
131
+ <option value="07:00">7:00 am</option>
132
+ <option value="08:00" selected="selected">8:00 am</option>
133
+ <option value="09:00">9:00 am</option>
134
+ <option value="10:00">10:00 am</option>
135
+ <option value="11:00">11:00 am</option>
136
+ <option value="12:00">12:00 pm</option>
137
+ <option value="13:00">1:00 pm</option>
138
+ <option value="14:00">2:00 pm</option>
139
+ <option value="15:00">3:00 pm</option>
140
+ <option value="16:00">4:00 pm</option>
141
+ <option value="17:00">5:00 pm</option>
142
+ <option value="18:00">6:00 pm</option>
143
+ <option value="19:00">7:00 pm</option>
144
+ <option value="20:00">8:00 pm</option>
145
+ <option value="21:00">9:00 pm</option>
146
+ <option value="22:00">10:00 pm</option>
147
+ <option value="23:00">11:00 pm</option>
148
+ </select>
149
+ </div>
150
+ </div>
151
+ <div class="ab-time-to ab-left">
152
+ <label data-default="<?php echo get_option( 'ab_appearance_text_label_finish_by' ); ?>" data-link-class="text_finish_by_label" class="ab_editable" id="ab-text-label-finish_by" data-type="text" data-pk="1"><?php echo esc_html(get_option( 'ab_appearance_text_label_finish_by' )) ?></label>
153
+ <div class="ab-select-wrap">
154
+ <select class="select-list ab-requested-time-to">
155
+ <option value="09:00">9:00 am</option>
156
+ <option value="10:00">10:00 am</option>
157
+ <option value="11:00">11:00 am</option>
158
+ <option value="12:00">12:00 pm</option>
159
+ <option value="13:00">1:00 pm</option>
160
+ <option value="14:00">2:00 pm</option>
161
+ <option value="15:00">3:00 pm</option>
162
+ <option value="16:00">4:00 pm</option>
163
+ <option value="17:00">5:00 pm</option>
164
+ <option value="18:00">6:00 pm</option>
165
+ <option value="19:00">7:00 pm</option>
166
+ <option value="20:00">8:00 pm</option>
167
+ <option value="21:00">9:00 pm</option>
168
+ <option value="22:00">10:00 pm</option>
169
+ <option value="23:00">11:00 pm</option>
170
+ <option value="23:59">12:00 am</option>
171
+ </select>
172
+ </div>
173
+ </div>
174
+ </div>
175
+ </div>
176
+ <div class="ab-row-fluid ab-nav-steps last-row ab-clear">
177
+ <button class="ab-right ab-mobile-prev-step ab-btn ab-none ladda-button orange zoom-in">
178
+ <span><?php _e( 'Back', 'ab' ) ?></span>
179
+ </button>
180
+ <button class="ab-right ab-next-step ab-btn ladda-button orange zoom-in">
181
+ <span><?php _e( 'Next', 'ab' ) ?></span>
182
+ </button>
183
+ </div>
184
+ </div>
185
+ </div>
186
+ </div>
187
+ </div>
backend/modules/appearance/templates/_2_time.php ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <div id="ab-booking-form" class="ab-booking-form" style="overflow: hidden">
3
+ <!-- Progress Tracker-->
4
+ <?php $step = 2; include '_progress_tracker.php'; ?>
5
+
6
+ <div style="margin-bottom: 15px!important;" class="ab-row-fluid">
7
+ <span data-inputclass="input-xxlarge" data-notes="<?php _e( '<b>[[SERVICE_NAME]]</b> - name of service, <b>[[STAFF_NAME]]</b> - name of staff,', 'ab' ); ?><br><?php _e( '<b>[[CATEGORY_NAME]]</b> - name of category.', 'ab' ); ?>" data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_info_second_step' ) ) ?>" data-link-class="ab-text-info-second" class="ab-text-info-second-preview ab-row-fluid ab_editable" id="ab-text-info-second" data-type="textarea" data-pk="1"><?php echo esc_html( get_option( 'ab_appearance_text_info_second_step' ) ) ?></span>
8
+ </div>
9
+ <!-- timeslots -->
10
+ <div class="ab-columnizer-wrap" style="height: 400px;">
11
+ <div class="ab-columnizer">
12
+ <div class="ab-time-screen">
13
+ <div class="ab-column">
14
+ <button class="ab-available-day ab-first-child" value="">Wed, Jul 31</button>
15
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>1:00 pm</button>
16
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>1:15 pm</button>
17
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>1:30 pm</button>
18
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>1:45 pm</button>
19
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>2:00 pm</button>
20
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>2:15 pm</button>
21
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>2:30 pm</button>
22
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>2:45 pm</button>
23
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>3:00 pm</button>
24
+ </div>
25
+ <div class="ab-column">
26
+ <button class="ab-available-hour ab-first-child"><i class="ab-hour-icon"><span></span></i>3:15 pm</button>
27
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>3:30 pm</button>
28
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>3:45 pm</button>
29
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>4:00 pm</button>
30
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>4:15 pm</button>
31
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>4:30 pm</button>
32
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>4:45 pm</button>
33
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>5:00 pm</button>
34
+ <button class="ab-available-day ab-first-child" value="">Thu, Aug 01</button>
35
+ <button class="ab-available-hour ab-last-child"><i class="ab-hour-icon"><span></span></i>10:00 am</button>
36
+ </div>
37
+ <div class="ab-column">
38
+ <button class="ab-available-hour ab-first-child"><i class="ab-hour-icon"><span></span></i>10:15 am</button>
39
+ <button class="ab-available-hour"><i class="ab-hour-icon"><span></span></i>10:30 am</button>
40
+ <button class="ab-available-hour"><i class="ab-hour-icon"><span></span></i>10:45 am</button>
41
+ <button class="ab-available-hour"><i class="ab-hour-icon"><span></span></i>11:00 am</button>
42
+ <button class="ab-available-hour"><i class="ab-hour-icon"><span></span></i>11:15 am</button>
43
+ <button class="ab-available-hour"><i class="ab-hour-icon"><span></span></i>11:30 am</button>
44
+ <button class="ab-available-hour"><i class="ab-hour-icon"><span></span></i>11:45 am</button>
45
+ <button class="ab-available-hour"><i class="ab-hour-icon"><span></span></i>12:00 pm</button>
46
+ <button class="ab-available-hour"><i class="ab-hour-icon"><span></span></i>12:15 pm</button>
47
+ <button class="ab-available-hour ab-last-child""><i class="ab-hour-icon"><span></span></i>12:30 pm</button>
48
+ </div>
49
+ <div class="ab-column">
50
+ <button class="ab-available-hour ab-first-child"><i class="ab-hour-icon"><span></span></i>12:45 pm</button>
51
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>1:00 pm</button>
52
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>1:15 pm</button>
53
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>3:30 pm</button>
54
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>3:45 pm</button>
55
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>4:00 pm</button>
56
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>4:15 pm</button>
57
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>4:30 pm</button>
58
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>4:45 pm</button>
59
+ <button class="ab-available-hour ab-last-child"><i class="ab-hour-icon"><span></span></i>5:00 pm</button>
60
+ </div>
61
+ <div class="ab-column">
62
+ <button class="ab-available-day ab-first-child" value="">Fri, Aug 02</button>
63
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>1:00 pm</button>
64
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>1:15 pm</button>
65
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>1:30 pm</button>
66
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>1:45 pm</button>
67
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>2:00 pm</button>
68
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>2:15 pm</button>
69
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>2:30 pm</button>
70
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>2:45 pm</button>
71
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>3:00 pm</button>
72
+ </div>
73
+ <div class="ab-column">
74
+ <button class="ab-available-hour ab-first-child"><i class="ab-hour-icon"><span></span></i>3:15 pm</button>
75
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>3:30 pm</button>
76
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>3:45 pm</button>
77
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>4:00 pm</button>
78
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>4:15 pm</button>
79
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>4:30 pm</button>
80
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>4:45 pm</button>
81
+ <button class=ab-available-hour><i class="ab-hour-icon"><span></span></i>5:00 pm</button>
82
+ <button class="ab-available-day ab-first-child" value="">Sat, Aug 03</button>
83
+ <button class="ab-available-hour ab-last-child"><i class="ab-hour-icon"><span></span></i>10:00 am</button>
84
+ </div>
85
+ <div class="ab-column">
86
+ <button class="ab-available-hour ab-first-child"><i class="ab-hour-icon"><span></span></i>10:15 am</button>
87
+ <button class="ab-available-hour"><i class="ab-hour-icon"><span></span></i>10:30 am</button>
88
+ <button class="ab-available-hour"><i class="ab-hour-icon"><span></span></i>10:45 am</button>
89
+ <button class="ab-available-hour"><i class="ab-hour-icon"><span></span></i>11:00 am</button>
90
+ <button class="ab-available-hour"><i class="ab-hour-icon"><span></span></i>11:15 am</button>
91
+ <button class="ab-available-hour"><i class="ab-hour-icon"><span></span></i>11:30 am</button>
92
+ <button class="ab-available-hour"><i class="ab-hour-icon"><span></span></i>11:45 am</button>
93
+ <button class="ab-available-hour"><i class="ab-hour-icon"><span></span></i>12:00 pm</button>
94
+ <button class="ab-available-hour"><i class="ab-hour-icon"><span></span></i>12:15 pm</button>
95
+ <button class="ab-available-hour ab-last-child""><i class="ab-hour-icon"><span></span></i>12:30 pm</button>
96
+ </div>
97
+ </div>
98
+ </div>
99
+ </div>
100
+ <div class="ab-time-buttons ab-row-fluid ab-nav-steps last-row ab-clear">
101
+ <button class="ab-time-next ab-btn ab-right ladda-button orange zoom-in">
102
+ <span class="ab_label">&gt;</span>
103
+ <span class="spinner"></span>
104
+ </button>
105
+ <button class="ab-time-prev ab-btn ab-right ladda-button orange zoom-in">
106
+ <span class="ab_label">&lt;</span>
107
+ <span class="spinner"></span>
108
+ </button>
109
+ <button class="ab-left ab-to-first-step ab-btn ladda-button orange zoom-in">
110
+ <span><?php _e( 'Back', 'ab' ) ?></span>
111
+ </button>
112
+ </div>
113
+ </div>
backend/modules/appearance/templates/_3_details.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <div class="ab-booking-form" style="overflow: hidden">
3
+ <!-- Progress Tracker-->
4
+ <?php $step = 3; include '_progress_tracker.php'; ?>
5
+
6
+ <div style="margin-bottom: 15px!important;" class="ab-row-fluid">
7
+ <span data-inputclass="input-xxlarge" data-notes = "<?php _e( '<b>[[STAFF_NAME]]</b> - name of staff, <b>[[SERVICE_NAME]]</b> - name of service,', 'ab' );?> <br> <?php _e( '<b>[[SERVICE_TIME]]</b> - time of service, <b>[[SERVICE_DATE]]</b> - date of service,', 'ab' );?> <br> <?php _e( '<b>[[SERVICE_PRICE]]</b> - price of service, <b>[[CATEGORY_NAME]]</b> - name of category.', 'ab' ); ?>" data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_info_third_step' ) ) ?>" data-link-class="ab-text-info-third" class="ab-text-info-third-preview ab-row-fluid ab_editable" id="ab-text-info-third" data-type="textarea" data-pk="1"><?php echo esc_html( get_option( 'ab_appearance_text_info_third_step' ) ) ?></span>
8
+ </div>
9
+ <form class="ab-third-step">
10
+ <div class="ab-row-fluid">
11
+ <div class="ab-formGroup ab-left">
12
+ <label data-default="<?php echo get_option( 'ab_appearance_text_label_name' ); ?>" data-link-class="text_name_label" class="ab-formLabel text_name_label ab_editable" id="ab-text-label-name" data-type="text" data-pk="1"><?php echo esc_html(get_option( 'ab_appearance_text_label_name' )) ?></label>
13
+ <div class="ab-formField">
14
+ <input class="ab-formElement" type="text" value="" maxlength="60">
15
+ </div>
16
+ </div>
17
+ <div class="ab-formGroup ab-left">
18
+ <label data-default="<?php echo get_option( 'ab_appearance_text_label_phone' ); ?>" data-link-class="text_phone_label" class="ab-formLabel text_phone_label ab_editable" id="ab-text-label-phone" data-type="text" data-pk="1"><?php echo esc_html(get_option( 'ab_appearance_text_label_phone' )) ?></label>
19
+ <div class="ab-formField">
20
+ <input class="ab-formElement" maxlength="30" type="text" value="">
21
+ </div>
22
+ </div>
23
+ <div class="ab-formGroup ab-left">
24
+ <label data-default="<?php echo get_option( 'ab_appearance_text_label_email' ); ?>" data-link-class="text_email_label" class="ab-formLabel text_email_label ab_editable" id="ab-text-label-email" data-type="text" data-pk="1"><?php echo esc_html(get_option( 'ab_appearance_text_label_email' )) ?></label>
25
+ <div class="ab-formField" style="margin-right: 0">
26
+ <input class="ab-formElement" maxlength="40" type="text" value="">
27
+ </div>
28
+ </div>
29
+ </div>
30
+ <div class="ab-row-fluid">
31
+ <div class="ab-formGroup ab-full ab-lastGroup">
32
+ <label data-default="<?php echo get_option( 'ab_appearance_text_label_notes' ); ?>" data-link-class="text_notes_label" class="ab-formLabel text_notes_label ab_editable" id="ab-text-label-notes" data-type="text" data-pk="1"><?php echo esc_html(get_option( 'ab_appearance_text_label_notes' )) ?></label>
33
+ <div class="ab-formField">
34
+ <textarea rows="3" class="ab-formElement"></textarea>
35
+ </div>
36
+ </div>
37
+ </div>
38
+ </form>
39
+ <div class="ab-row-fluid last-row ab-nav-steps ab-clear">
40
+ <button class="ab-left ab-to-second-step ab-btn ladda-button orange zoom-in" style="margin-right: 10px;">
41
+ <span><?php _e( 'Back', 'ab' ) ?></span>
42
+ </button>
43
+ <button class="ab-right ab-to-fourth-step ab-btn ladda-button orange zoom-in">
44
+ <span><?php _e( 'Next', 'ab' ) ?></span>
45
+ </button>
46
+ </div>
47
+ </div>
backend/modules/appearance/templates/_4_payment.php ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <div class="ab-booking-form" style="overflow: hidden">
3
+ <!-- Progress Tracker-->
4
+ <?php $step = 4; include '_progress_tracker.php'; ?>
5
+ <!-- payment -->
6
+ <div class="ab-payment">
7
+ <!-- Coupons -->
8
+ <div style="margin-bottom: 15px!important;" class="ab-row-fluid">
9
+ <span data-inputclass="input-xxlarge" data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_info_coupon' ) ) ?>" data-notes = "<?php _e( '<b>[[SERVICE_PRICE]]</b> - price of service', 'ab' );?>" data-link-class="ab-text-info-coupon" class="ab-text-info-coupon-preview ab-row-fluid ab_editable" id="ab-text-info-coupon" data-type="textarea" data-pk="1"><?php echo esc_html( get_option( 'ab_appearance_text_info_coupon' ) ) ?></span>
10
+ </div>
11
+
12
+ <div style="margin-bottom: 15px!important;">
13
+ <span style="display: inline-block;" data-default="<?php echo get_option( 'ab_appearance_text_label_coupon' ); ?>" data-link-class="text_coupon_label" class="ab_editable editable editable-click" id="ab-text-label-coupon" data-type="text" data-pk="1"><?php echo esc_html(get_option( 'ab_appearance_text_label_coupon' )) ?></span>
14
+ <div style="display: inline-block;">
15
+ <input class="ab-user-coupon" maxlength="40" type="text" value="" style="display: inline-block; margin: 0 10px;">
16
+ <button class="ab-btn ladda-button orange" style="display: inline-block;">Apply</button>
17
+ </div>
18
+ </div>
19
+ <div class="ab-clear"></div>
20
+
21
+ <div style="margin-bottom: 15px!important;" class="ab-row-fluid">
22
+ <span data-inputclass="input-xxlarge" data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_info_fourth_step' ) ) ?>" data-link-class="ab-text-info-fourth" class="ab-text-info-fourth-preview ab-row-fluid ab_editable" id="ab-text-info-fourth" data-type="textarea" data-pk="1"><?php echo esc_html( get_option( 'ab_appearance_text_info_fourth_step' ) ) ?></span>
23
+ </div>
24
+
25
+ <!-- label -->
26
+ <div class="ab-row-fluid">
27
+ <label>
28
+ <input type="radio" name="payment" class="ab-local-payment" checked="checked" value="local"/>
29
+ <?php _e( 'I will pay locally', 'ab' ) ?>
30
+ </label>
31
+ </div>
32
+ <div class="ab-row-fluid">
33
+ <label>
34
+ <input type="radio" name="payment" class="ab-paypal-payment" value="paypal"/>
35
+ <?php _e( 'I will pay now with PayPal', 'ab' ) ?>
36
+ <img src="<?php echo plugins_url( 'frontend/resources/images/paypal.png', AB_PATH . '/main.php' ) ?>" style="margin-left: 10px;" alt="paypal" />
37
+ </label>
38
+ </div>
39
+ <!--div class="ab-row-fluid">
40
+ <label>
41
+ <input type="radio" name="payment" class="ab-authorizenet-payment" value="authorizenet"/>
42
+ <?php _e( 'I will pay now with Credit Card', 'ab' ) ?>
43
+ <img src="<?php echo plugins_url( 'frontend/resources/images/cards.png', AB_PATH . '/main.php' ) ?>" style="margin-left: 10px;" alt="cards" />
44
+ </label>
45
+ <form class="authorizenet ab-clearBottom" style="display: none; margin-top: 15px;">
46
+ <?php include "_card_payment.php" ?>
47
+ </form>
48
+ </div-->
49
+ <div class="ab-row-fluid">
50
+ <label>
51
+ <input type="radio" name="payment" class="ab-stripe-payment" value="stripe"/>
52
+ <?php _e( 'I will pay now with Credit Card', 'ab' ) ?>
53
+ <img src="<?php echo plugins_url( 'frontend/resources/images/cards.png', AB_PATH . '/main.php' ) ?>" style="margin-left: 10px;" alt="cards" />
54
+ </label>
55
+ <form class="stripe ab-clearBottom" style="display: none; margin-top: 15px;">
56
+ <?php include "_card_payment.php" ?>
57
+ </form>
58
+ </div>
59
+
60
+ <!-- buttons -->
61
+ <div class="ab-local-pay-button ab-row-fluid ab-nav-steps last-row">
62
+ <button class="ab-left ab-to-third-step ab-btn ladda-button orange zoom-in" style="margin-right: 10px;">
63
+ <span><?php _e( 'Back', 'ab' ) ?></span>
64
+ </button>
65
+ <button class="ab-right ab-final-step ab-btn ladda-button orange zoom-in">
66
+ <span><?php _e( 'Next', 'ab' ) ?></span>
67
+ </button>
68
+ </div>
69
+ </div>
70
+ </div>
71
+
72
+ <!-- fourth step options -->
73
+ <div class="ab-fourth-step-options">
74
+ <!-- booking-info -->
75
+ <div class="ab-booking-details">
76
+ </div>
77
+ </div>
backend/modules/appearance/templates/_5_done.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <div class="ab-booking-form" style="overflow: hidden">
3
+ <!-- Progress Tracker-->
4
+ <?php $step = 5; include '_progress_tracker.php'; ?>
5
+ <div style="margin-bottom: 15px!important;" class="ab-row-fluid">
6
+ <span data-inputclass="input-xxlarge" data-link-class="ab-text-info-fifth" class="ab-text-info-fifth-preview ab_editable" data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_info_fifth_step' ) ) ?>" id="ab-text-info-fifth" data-type="textarea" data-pk="1"><?php echo nl2br( esc_html( get_option( 'ab_appearance_text_info_fifth_step' ) ) ) ?></span>
7
+ </div>
8
+ </div>
9
+
10
+ <!-- fifth step options -->
11
+ <div class="ab-fifth-step-options">
12
+ <div class="ab-booking-details">
13
+ </div>
14
+ </div>
backend/modules/appearance/templates/_card_payment.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <div class="ab-row-fluid">
3
+ <div class="ab-formGroup ab-left">
4
+ <label class="ab-formLabel"><?php _e( 'Credit Card Number', 'ab' ) ?></label>
5
+ <div class="ab-formField">
6
+ <input class="ab-formElement ab-full-name" type="text" name="ab_card_number">
7
+ </div>
8
+ </div>
9
+ <div class="ab-formGroup ab-left" style="width: auto;">
10
+ <label class="ab-formLabel"><?php _e( 'Expiration Date', 'ab' ) ?></label>
11
+ <div class="ab-formField">
12
+ <select class="ab-formElement ab-full-name" style="width: 40px;float: left;" name="ab_card_month">
13
+ <?php for ( $i = 1; $i <= 12; ++ $i ): ?>
14
+ <option value="<?php echo $i ?>"><?php printf( '%02d', $i ) ?></option>
15
+ <?php endfor; ?>
16
+ </select>
17
+ <select class="ab-formElement ab-full-name" style="width: 55px;float: left; margin-left: 10px;" name="ab_card_year">
18
+ <?php for ( $i = date('Y'); $i <= date('Y')+10; ++ $i ): ?>
19
+ <option value="<?php echo $i ?>"><?php echo $i ?></option>
20
+ <?php endfor ?>
21
+ </select>
22
+ </div>
23
+ </div>
24
+ </div>
25
+ <div class="ab-row-fluid">
26
+ <div class="ab-formGroup ab-left">
27
+ <label class="ab-formLabel"><?php _e( 'Card Security Code', 'ab' ) ?></label>
28
+ <div class="ab-formField">
29
+ <input class="ab-formElement ab-full-name" style="width: 50px;float: left;" type="text" name="ab_card_code" />
30
+ </div>
31
+ </div>
32
+ <div class="ab-clear"></div>
33
+ <div class="ab-error ab-bold ab-card-error"></div>
34
+ </div>
backend/modules/appearance/templates/_progress_tracker.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <div class="ab-progress-tracker">
3
+ <ul class="ab-progress-bar nav-3">
4
+ <li class="ab-step-tabs ab-first active">
5
+ <a href="javascript:void(0)">1. <span data-default="<?php echo get_option( 'ab_appearance_text_step_service' ); ?>" data-link-class="text_step_1" class="text_service ab_editable" id="ab-text-step-service" data-type="text" data-pk="1"><?php echo esc_html(get_option( 'ab_appearance_text_step_service' )) ?></span></a>
6
+ <div class="step"></div>
7
+ </li>
8
+ <li class="ab-step-tabs<?php if ($step >= 2): ?> active<?php endif ?>">
9
+ <a href="javascript:void(0)">2. <span data-default="<?php echo get_option( 'ab_appearance_text_step_time' ); ?>" data-link-class="text_step_2" class="text_time text_step_2 ab_editable" id="ab-text-step-time" data-type="text" data-pk="1"><?php echo esc_html(get_option( 'ab_appearance_text_step_time' )) ?></span></a>
10
+ <div class="step"></div>
11
+ </li>
12
+ <li class="ab-step-tabs<?php if ($step >= 3): ?> active<?php endif ?>">
13
+ <a href="javascript:void(0)">3. <span data-default="<?php echo get_option( 'ab_appearance_text_step_details' ); ?>" data-link-class="text_step_3" class="text_details text_step_3 ab_editable" id="ab-text-step-details" data-type="text" data-pk="1"><?php echo esc_html(get_option( 'ab_appearance_text_step_details' )) ?></span></a>
14
+ <div class="step"></div>
15
+ </li>
16
+ <li class="ab-step-tabs<?php if ($step >= 4): ?> active<?php endif ?>">
17
+ <a href="javascript:void(0)">4. <span data-default="<?php echo get_option( 'ab_appearance_text_step_payment' ); ?>" data-link-class="text_step_4" class="text_payment ab_editable" id="ab-text-step-payment" data-type="text" data-pk="1"><?php echo esc_html(get_option( 'ab_appearance_text_step_payment' )) ?></span></a>
18
+ <div class="step"></div>
19
+ </li>
20
+ <li class="ab-step-tabs ab-last<?php if ($step >= 5): ?> active<?php endif ?>">
21
+ <a href="javascript:void(0)">5. <span data-default="<?php echo get_option( 'ab_appearance_text_step_done' ); ?>" data-link-class="text_step_5" class="text_done ab_editable" id="ab-text-step-done" data-type="text" data-pk="1"><?php echo esc_html(get_option( 'ab_appearance_text_step_done' )) ?></span></a>
22
+ <div class="step"></div>
23
+ </li>
24
+ </ul>
25
+ </div>
backend/modules/appearance/templates/index.php ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <div class="ab-title">
3
+ <div class="alert" style="font-size: 14px; display: none;">
4
+ <button type="button" class="close" onclick="jQuery('.alert').hide()">&times;</button>
5
+ <?php _e( 'Settings saved.', 'ab' ); ?>
6
+ </div>
7
+ <?php _e( 'Appearance', 'ab' ) ?>
8
+ </div>
9
+
10
+ <input type=text class="wp-color-picker appearance-color-picker" name=color
11
+ value="<?php echo get_option( 'ab_appearance_color' ) ?>"
12
+ data-selected="<?php echo get_option( 'ab_appearance_color' ) ?>" />
13
+
14
+ <div style="max-width: 960px;">
15
+ <form method=post id=common_settings style="margin-right: 15px">
16
+ <legend id=main_form>
17
+ <div>
18
+ <input id=ab-progress-tracker-checkbox name=ab-progress-tracker-checkbox <?php if (get_option( 'ab_appearance_show_progress_tracker' )): ?>checked=checked<?php endif ?> type=checkbox />
19
+ <label style="display: inline" for="progress_tracker">
20
+ <b><?php _e( 'Show form progress tracker', 'ab' ) ?></b>
21
+ </label>
22
+ </div>
23
+ </legend>
24
+ </form>
25
+ <!-- Tabs -->
26
+ <div class=tabbable style="margin-top: 20px;">
27
+ <ul class="nav nav-tabs ab-nav-tabs">
28
+ <?php foreach ( $steps as $step_id => $step_name ): ?>
29
+ <li class="ab-step-tab-<?php echo $step_id ?> ab-step-tabs<?php if ( $step_id == 1 ): ?> active<?php endif ?>" data-step-id="<?php echo $step_id ?>">
30
+ <a href="#" data-toggle=tab><?php echo $step_id ?>. <span class="text_step_<?php echo $step_id ?>" ><?php echo esc_html( $step_name ) ?></span></a>
31
+ </li>
32
+ <?php endforeach ?>
33
+ </ul>
34
+ <!-- Tabs-Content -->
35
+ <div class=tab-content>
36
+ <?php foreach ( $steps as $step_id => $step_name ) : ?>
37
+ <div class="tab-pane-<?php echo $step_id ?><?php if ( $step_id == 1 ): ?> active<?php endif ?>" data-step-id="<?php echo $step_id ?>">
38
+ <?php
39
+ // Render unique data per step
40
+ switch ( $step_id ) {
41
+ // Service
42
+ case 1:
43
+ include '_1_service.php';
44
+ break;
45
+ // Time
46
+ case 2:
47
+ include '_2_time.php';
48
+ break;
49
+ // Details
50
+ case 3:
51
+ include '_3_details.php';
52
+ break;
53
+ // Payment
54
+ case 4:
55
+ include '_4_payment.php';
56
+ break;
57
+ // Done
58
+ case 5:
59
+ include '_5_done.php';
60
+ break;
61
+ }
62
+ ?>
63
+ </div>
64
+ <?php endforeach ?>
65
+ </div>
66
+ <div style="float:right;margin-right:20px;">
67
+ <p><?php _e('Click on the underlined text to edit.', 'ab') ?></p>
68
+ </div>
69
+ <div class="clear"></div>
70
+ <!-- controls -->
71
+ <div class=controls>
72
+ <!-- spinner -->
73
+ <span id="update_spinner" class="spinner"></span>
74
+ <!-- update button -->
75
+ <button id="update_button" class="btn btn-info ab-update-button ab-appearance-update">
76
+ <?php _e( 'Update', 'ab' ) ?>
77
+ </button>
78
+ <!-- reset button -->
79
+ <button id="reset_button" class="ab-reset-form ab-appearance-reset" type="reset">
80
+ <?php _e( 'Reset', 'ab' ) ?>
81
+ </button>
82
+ </div>
83
+ </div>
84
+ </div>
backend/modules/calendar/AB_CalendarController.php ADDED
@@ -0,0 +1,850 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ include 'forms/AB_AppointmentForm.php';
6
+
7
+ /**
8
+ * Class AB_CalendarController
9
+ *
10
+ * @property $collection
11
+ * @property $staff_services
12
+ * @property $startDate
13
+ * @property $period_start
14
+ * @property $period_end
15
+ * @property $customers
16
+ * @property $staff_id
17
+ * @property $service_id
18
+ * @property $customer_id
19
+ * @property $staff_collection
20
+ * @property $date_interval_not_available
21
+ * @property $date_interval_warning
22
+ * @property $notes
23
+ *
24
+ * @Security user
25
+ */
26
+ class AB_CalendarController extends AB_Controller {
27
+
28
+ public function renderCalendar() {
29
+ wp_enqueue_style( 'ab-jquery-ui-css', plugins_url( 'resources/css/jquery-ui-1.10.4/jquery-ui.min.css', __FILE__ ) );
30
+ wp_enqueue_style( 'ab-weekcalendar', plugins_url( 'resources/css/jquery.weekcalendar.css', __FILE__ ) );
31
+ wp_enqueue_style( 'ab-calendar', plugins_url( 'resources/css/calendar.css', __FILE__ ) );
32
+ wp_enqueue_style( 'ab-chosen', plugins_url( 'resources/css/chosen.css', __FILE__ ) );
33
+
34
+ wp_enqueue_style( 'ab-style', plugins_url( 'resources/css/ab_style.css', dirname( __DIR__ ) ) );
35
+ wp_enqueue_style( 'ab-bootstrap', plugins_url( 'resources/bootstrap/css/bootstrap.min.css', dirname( __DIR__ ) ) );
36
+ wp_enqueue_script( 'ab-bootstrap', plugins_url( 'resources/bootstrap/js/bootstrap.min.js', dirname( __DIR__ ) ), array( 'jquery' ) );
37
+ wp_enqueue_script( 'ab-date', plugins_url( 'resources/js/date.js', dirname( __DIR__ ) ), array( 'jquery' ) );
38
+ wp_enqueue_script( 'ab-chosen', plugins_url( 'resources/js/chosen.jquery.js', __FILE__ ) );
39
+
40
+ wp_enqueue_script(
41
+ 'ab-weekcalendar',
42
+ plugins_url( 'resources/js/jquery.weekcalendar.js', __FILE__ ),
43
+ array(
44
+ 'jquery',
45
+ 'jquery-ui-widget',
46
+ 'jquery-ui-dialog',
47
+ 'jquery-ui-button',
48
+ 'jquery-ui-draggable',
49
+ 'jquery-ui-droppable',
50
+ 'jquery-ui-resizable',
51
+ 'jquery-ui-datepicker'
52
+ )
53
+ );
54
+ wp_enqueue_script( 'ab-angularjs', plugins_url( 'resources/js/angular-1.0.6.min.js', dirname( __DIR__ ) ) );
55
+ wp_enqueue_script( 'ab-angularui', plugins_url( 'resources/js/angular-ui-0.4.0.min.js', dirname( __DIR__ ) ), array( 'ab-angularjs' ) );
56
+ wp_enqueue_script( 'ab-ng-app', plugins_url( 'resources/js/ng-app.js', __FILE__ ), array( 'jquery', 'ab-angularjs', 'ab-angularui' ) );
57
+ wp_enqueue_script( 'ab-ng-new_customer_dialog', plugins_url( 'resources/js/ng-new_customer_dialog.js', dirname( __DIR__ ) ), array( 'jquery', 'ab-angularjs' ) );
58
+ wp_enqueue_script( 'ab-calendar_daypicker', plugins_url( 'resources/js/calendar_daypicker.js', __FILE__ ), array( 'jquery', 'ab-weekcalendar' ) );
59
+ wp_enqueue_script( 'ab-calendar_weekpicker', plugins_url( 'resources/js/calendar_weekpicker.js', __FILE__ ), array( 'jquery', 'ab-weekcalendar' ) );
60
+ wp_enqueue_script( 'ab-calendar', plugins_url( 'resources/js/calendar.js', __FILE__ ), array( 'jquery', 'ab-calendar_daypicker', 'ab-calendar_weekpicker', 'ab-ng-app', 'ab-weekcalendar' ) );
61
+ wp_localize_script( 'ab-weekcalendar', 'BooklyL10n', array(
62
+ 'new_appointment' => __( 'New appointment', 'ab' ),
63
+ 'edit_appointment' => __( 'Edit appointment', 'ab' ),
64
+ 'are_you_sure' => __( 'Are you sure?', 'ab' ),
65
+ 'phone' => __( 'Phone', 'ab' ),
66
+ 'email' => __( 'Email', 'ab' ),
67
+ 'timeslotsPerHour' => 60 / get_option('ab_settings_time_slot_length'),
68
+ 'shortMonths' => array(
69
+ __( 'Jan', 'ab' ),
70
+ __( 'Feb', 'ab' ),
71
+ __( 'Mar', 'ab' ),
72
+ __( 'Apr', 'ab' ),
73
+ __( 'May', 'ab' ),
74
+ __( 'Jun', 'ab' ),
75
+ __( 'Jul', 'ab' ),
76
+ __( 'Aug', 'ab' ),
77
+ __( 'Sep', 'ab' ),
78
+ __( 'Oct', 'ab' ),
79
+ __( 'Nov', 'ab' ),
80
+ __( 'Dec', 'ab' ),
81
+ ),
82
+ 'longMonths' => array(
83
+ __( 'January', 'ab' ),
84
+ __( 'February', 'ab' ),
85
+ __( 'March', 'ab' ),
86
+ __( 'April', 'ab' ),
87
+ __( 'May', 'ab' ),
88
+ __( 'June', 'ab' ),
89
+ __( 'July', 'ab' ),
90
+ __( 'August', 'ab' ),
91
+ __( 'September', 'ab' ),
92
+ __( 'October', 'ab' ),
93
+ __( 'November', 'ab' ),
94
+ __( 'December', 'ab' )
95
+ ),
96
+ 'shortDays' => array(
97
+ __( 'Sun', 'ab' ),
98
+ __( 'Mon', 'ab' ),
99
+ __( 'Tue', 'ab' ),
100
+ __( 'Wed', 'ab' ),
101
+ __( 'Thu', 'ab' ),
102
+ __( 'Fri', 'ab' ),
103
+ __( 'Sat', 'ab' )
104
+ ),
105
+ 'longDays' => array(
106
+ __( 'Sunday', 'ab' ),
107
+ __( 'Monday', 'ab' ),
108
+ __( 'Tuesday', 'ab' ),
109
+ __( 'Wednesday', 'ab' ),
110
+ __( 'Thursday', 'ab' ),
111
+ __( 'Friday', 'ab' ),
112
+ __( 'Saturday', 'ab' ),
113
+ ),
114
+ 'PM' => __( 'PM', 'ab' ),
115
+ 'AM' => __( 'AM', 'ab' ),
116
+ 'Week' => __( 'Week', 'ab' ) . ': ',
117
+ 'dateFormat' => $this->dateFormatTojQueryUIDatePickerFormat(),
118
+ ));
119
+
120
+ if ( is_super_admin() ) {
121
+ $this->collection = $this->getWpdb()->get_results( "SELECT * FROM ab_staff" );
122
+ } else {
123
+ $this->collection = $this->getWpdb()->get_results( $this->getWpdb()->prepare( "SELECT * FROM ab_staff s WHERE s.wp_user_id = %d", array(get_current_user_id()) ) );
124
+ }
125
+
126
+ $this->render( 'calendar' );
127
+ }
128
+ /**
129
+ * Get data for WeekCalendar in `week` mode.
130
+ *
131
+ * @return json
132
+ */
133
+ public function executeWeekStaffAppointments() {
134
+ $result = array( 'events' => array(), 'freebusys' => array() );
135
+ $staff_id = $this->getParameter( 'staff_id' );
136
+ if ( $staff_id ) {
137
+ $staff = new AB_Staff();
138
+ $staff->load( $staff_id );
139
+
140
+ $start_date = $this->getParameter( 'start_date' );
141
+ $end_date = $this->getParameter( 'end_date' );
142
+
143
+ $staff_appointments = $staff->getAppointments( $start_date, $end_date );
144
+ foreach ( $staff_appointments as $appointment ) {
145
+ $result['events'][] = $this->getAppointment( $appointment );
146
+ }
147
+
148
+ $wpdb = $this->getWpdb();
149
+ $schedule = $wpdb->get_results( $wpdb->prepare(
150
+ 'SELECT
151
+ ssi.*
152
+ FROM `ab_staff_schedule_item` ssi
153
+ WHERE ssi.staff_id = %d',
154
+ $staff_id
155
+ ) );
156
+
157
+ $holidays = $wpdb->get_results( $wpdb->prepare( 'SELECT * FROM ab_holiday WHERE staff_id = %d OR staff_id IS NULL', $staff_id ) );
158
+
159
+ if ( ! empty( $schedule ) ) {
160
+ $wp_week_start_day = get_option( 'start_of_week', 1 );
161
+ $schedule_start_day = $schedule[0]->id - 1;
162
+
163
+ // if wp week start day is higher than our
164
+ // cut the list into 2 parts (before and after wp wp week start day)
165
+ // move the second part of the list above the first one
166
+ if ( $wp_week_start_day > $schedule_start_day ) {
167
+ $schedule_start = array_slice( $schedule, 0, $wp_week_start_day );
168
+ $schedule_end = array_slice( $schedule, $wp_week_start_day );
169
+ $schedule = $schedule_end;
170
+
171
+ foreach ( $schedule_start as $schedule_item ) {
172
+ $schedule[] = $schedule_item;
173
+ }
174
+ }
175
+
176
+ $active_schedule_items_ids = array();
177
+
178
+ foreach ( $schedule as $item ) {
179
+ // if start time is NULL we consider that the day is "OFF"
180
+ if ( null !== $item->start_time ) {
181
+ $day_name = AB_DateUtils::getWeekDayByNumber($item->day_index - 1);
182
+ if ($day_name == 'Sunday' && $wp_week_start_day == 0){
183
+ $date = date( 'Y-m-d', strtotime( $day_name . ' last week', strtotime( $start_date ) ) );
184
+ }else{
185
+ $date = date( 'Y-m-d', strtotime( $day_name . ' this week', strtotime( $start_date ) ) );
186
+ }
187
+ $startDate = new DateTime( $date . ' ' . $item->start_time );
188
+ $endDate = new DateTime( $date . ' ' . $item->end_time );
189
+ // Skip holidays
190
+ foreach ( $holidays as $holiday ) {
191
+ $holidayDate = new DateTime($holiday->holiday);
192
+ if ( $holiday->repeat_event ) {
193
+ if ($holidayDate->format('m-d') == $startDate->format('m-d')) {
194
+ continue 2;
195
+ }
196
+ } else {
197
+ if ($holidayDate->format('Y-m-d') == $startDate->format('Y-m-d')) {
198
+ continue 2;
199
+ }
200
+ }
201
+ }
202
+
203
+ // get available day parts
204
+ $result['freebusys'][] = $this->getFreeBusy( $startDate, $endDate, true );
205
+ $active_schedule_items_ids[] = $item->id;
206
+ }
207
+ }
208
+
209
+ if ( empty( $active_schedule_items_ids ) ) {
210
+ $active_schedule_items_ids = array( 0 );
211
+ }
212
+
213
+ $schedule_breaks = $wpdb->get_results(
214
+ 'SELECT
215
+ sib.*,
216
+ ssi.day_index AS "day_index"
217
+ FROM `ab_schedule_item_break` sib
218
+ LEFT JOIN `ab_staff_schedule_item` ssi ON sib.staff_schedule_item_id = ssi.id
219
+ WHERE sib.staff_schedule_item_id IN (' . implode( ', ', $active_schedule_items_ids ) . ')'
220
+ );
221
+
222
+ foreach ( $schedule_breaks as $break_item ) {
223
+ $day_name = AB_DateUtils::getWeekDayByNumber($break_item->day_index - 1);
224
+ $date = date( 'Y-m-d', strtotime( $day_name . ' this week', strtotime( $start_date ) ) );
225
+ $startDate = new DateTime( $date . ' ' . $break_item->start_time );
226
+ $endDate = new DateTime( $date . ' ' . $break_item->end_time );
227
+
228
+ // get breaks
229
+ $result['freebusys'][] = $this->getFreeBusy( $startDate, $endDate, false );
230
+ }
231
+ }
232
+ }
233
+ echo json_encode( $result );
234
+ exit;
235
+ }
236
+
237
+ /**
238
+ * Get data for WeekCalendar in `day` mode.
239
+ *
240
+ * @return json
241
+ */
242
+ public function executeDayStaffAppointments() {
243
+ $result = array( 'events' => array(), 'freebusys' => array() );
244
+ $staff_ids = $this->getParameter( 'staff_id' );
245
+ if (is_array($staff_ids)) {
246
+ $wpdb = $this->getWpdb();
247
+
248
+ $start_date = $this->getParameter( 'start_date' );
249
+
250
+ $appointments = $wpdb->get_results( sprintf(
251
+ 'SELECT
252
+ a.id,
253
+ a.start_date,
254
+ a.end_date,
255
+ s.title,
256
+ s.color,
257
+ staff.id AS "staff_id",
258
+ staff.full_name AS "staff_fullname",
259
+ ss.capacity AS max_capacity,
260
+ COUNT( ca.id ) AS current_capacity,
261
+ ca.customer_id,
262
+ ca.notes AS notes
263
+ FROM ab_appointment a
264
+ LEFT JOIN ab_customer_appointment ca ON ca.appointment_id = a.id
265
+ LEFT JOIN ab_service s ON a.service_id = s.id
266
+ LEFT JOIN ab_staff staff ON a.staff_id = staff.id
267
+ LEFT JOIN ab_staff_service ss ON ss.staff_id = a.staff_id AND ss.service_id = a.service_id
268
+ WHERE DATE(a.start_date) = DATE("%s") AND a.staff_id IN (%s)
269
+ GROUP BY a.id',
270
+ $wpdb->_real_escape($start_date),
271
+ implode(',', array_merge(array(0), array_map('intval', $staff_ids)))
272
+ ) );
273
+
274
+ foreach ( $appointments as $appointment ) {
275
+ $result['events'][] = $this->getAppointment( $appointment, $appointment->staff_id, $day_view = true );
276
+ }
277
+
278
+ $day_index = date("N", strtotime($start_date)) + 1;
279
+ $schedule = $wpdb->get_results(
280
+ 'SELECT
281
+ ssi.*,
282
+ s.id AS "staff_id"
283
+ FROM `ab_staff_schedule_item` ssi
284
+ LEFT JOIN `ab_staff` s ON ssi.staff_id = s.id
285
+ WHERE ssi.day_index = "' . $day_index . '"
286
+ AND ssi.start_time IS NOT NULL'
287
+ );
288
+
289
+ $active_schedule_items_ids = array();
290
+
291
+ foreach ( $schedule as $item ) {
292
+ $startDate = new DateTime(date( 'Y-m-d', strtotime( $start_date ) ) . ' ' . $item->start_time);
293
+ $endDate = new DateTime(date( 'Y-m-d', strtotime( $start_date ) ) . ' ' . $item->end_time);
294
+
295
+ $holidays = $wpdb->get_results($wpdb->prepare(
296
+ 'SELECT * FROM ab_holiday WHERE staff_id = %d and ((`repeat_event` = 0 and DATE_FORMAT( `holiday` , "%%Y-%%m-%%d" ) = %s) or (`repeat_event` = 1 and DATE_FORMAT( `holiday` , "%%Y-%%m" ) = %s))',
297
+ array($item->staff_id, $startDate->format('Y-m-d'), $startDate->format('m-d')))
298
+ );
299
+ if (!$holidays){
300
+ $result['freebusys'][] = $this->getFreeBusy( $startDate, $endDate, true, $item->staff_id );
301
+ $active_schedule_items_ids[] = $item->id;
302
+ }
303
+ }
304
+
305
+ if ( empty($active_schedule_items_ids) ) {
306
+ $active_schedule_items_ids = array( 0 );
307
+ }
308
+
309
+ $schedule_breaks = $wpdb->get_results(
310
+ 'SELECT
311
+ sib.*,
312
+ s.id AS "staff_id"
313
+ FROM `ab_schedule_item_break` sib
314
+ LEFT JOIN `ab_staff_schedule_item` ssi ON sib.staff_schedule_item_id = ssi.id
315
+ LEFT JOIN `ab_staff` s ON ssi.staff_id = s.id
316
+ WHERE sib.staff_schedule_item_id IN (' . implode( ', ', $active_schedule_items_ids ) . ')'
317
+ );
318
+
319
+ foreach ( $schedule_breaks as $break_item ) {
320
+ $startDate = new DateTime(date( 'Y-m-d', strtotime( $start_date ) ) . ' ' . $break_item->start_time);
321
+ $endDate = new DateTime(date( 'Y-m-d', strtotime( $start_date ) ) . ' ' . $break_item->end_time);
322
+
323
+ $result['freebusys'][] = $this->getFreeBusy( $startDate, $endDate, false, $break_item->staff_id );
324
+ }
325
+ }
326
+ echo json_encode( $result );
327
+ exit;
328
+ }
329
+
330
+ /**
331
+ * Get data needed for appointment form initialisation.
332
+ */
333
+ public function executeGetDataForAppointmentForm() {
334
+ $wpdb = $this->getWpdb();
335
+ $result = array(
336
+ 'staff' => array(),
337
+ 'customers' => array(),
338
+ 'time' => array(),
339
+ 'time_interval' => get_option( 'ab_settings_time_slot_length' ) * 60
340
+ );
341
+
342
+ // Staff list.
343
+ if ( is_super_admin() ) {
344
+ $staff = $wpdb->get_results( 'SELECT `id`, `full_name` FROM `ab_staff`', ARRAY_A );
345
+ } else {
346
+ $staff = $wpdb->get_results( $wpdb->prepare(
347
+ 'SELECT `id`, `full_name` FROM `ab_staff` WHERE `wp_user_id` = %d',
348
+ array( get_current_user_id() )
349
+ ), ARRAY_A );
350
+ }
351
+ foreach ( $staff as $st ) {
352
+ $services = $wpdb->get_results( $wpdb->prepare(
353
+ 'SELECT
354
+ `service`.`id`,
355
+ `service`.`title`,
356
+ `service`.`duration`
357
+ FROM `ab_service` `service`
358
+ LEFT JOIN `ab_staff_service` `ss` ON `ss`.`service_id` = `service`.`id`
359
+ LEFT JOIN `ab_staff` `staff` ON `ss`.`staff_id` = `staff`.`id`
360
+ WHERE `staff`.`id` = %d',
361
+ $st[ 'id' ]
362
+ ), ARRAY_A );
363
+ array_walk($services, create_function('&$a', '$a[\'title\'] = sprintf(\'%s (%s)\', $a[\'title\'], AB_Service::durationToString($a[\'duration\']));'));
364
+ $result[ 'staff' ][] = array(
365
+ 'id' => $st[ 'id' ],
366
+ 'full_name' => $st[ 'full_name' ],
367
+ 'services' => $services
368
+ );
369
+ }
370
+
371
+ // Customers list.
372
+ $customers = $this->getWpdb()->get_results(
373
+ 'SELECT * FROM `ab_customer` WHERE name <> "" OR phone <> "" OR email <> "" ORDER BY name',
374
+ ARRAY_A
375
+ );
376
+ $customer = new AB_Customer();
377
+ foreach ($customers as $customer_data) {
378
+ $customer->setData( $customer_data );
379
+
380
+ $name = $customer->get('name');
381
+ if ($customer->get('email') && $customer->get('phone')){
382
+ $name .= ' (' . $customer->get('email') . ', ' . $customer->get('phone') . ')';
383
+ }elseif($customer->get('email')){
384
+ $name .= ' (' . $customer->get('email') . ')';
385
+ }elseif($customer->get('phone')){
386
+ $name .= ' (' . $customer->get('phone') . ')';
387
+ }
388
+
389
+ $result[ 'customers' ][] = array(
390
+ 'id' => $customer->get('id'),
391
+ 'name' => $name,
392
+ );
393
+ }
394
+
395
+ // Time list.
396
+ $tf = get_option( 'time_format' );
397
+ $ts_length = get_option( 'ab_settings_time_slot_length' );
398
+ $time_start = new AB_DateTime( AB_StaffScheduleItem::WORKING_START_TIME, new DateTimeZone( 'UTC' ) );
399
+ $time_end = new AB_DateTime( AB_StaffScheduleItem::WORKING_END_TIME, new DateTimeZone( 'UTC' ) );
400
+
401
+ // Run the loop.
402
+ while ( $time_start->format( 'U' ) <= $time_end->format( 'U' ) ) {
403
+ $result[ 'time' ][ ] = array(
404
+ 'value' => $time_start->format( 'H:i' ),
405
+ 'title' => date_i18n( $tf, $time_start->format( 'U' ) )
406
+ );
407
+ $time_start->modify( '+' . $ts_length . ' min' );
408
+ }
409
+
410
+ echo json_encode( $result );
411
+ exit (0);
412
+ }
413
+
414
+ /**
415
+ * Get appointment data when editing the appointment.
416
+ */
417
+ public function executeGetDataForAppointment() {
418
+ /**
419
+ * @var WPDB $wpdb
420
+ */
421
+ global $wpdb;
422
+
423
+ $response = array( 'status' => 'error', 'data' => array('customers' => array()) );
424
+
425
+ $appointment = new AB_Appointment();
426
+ if ( $appointment->load( $this->getParameter( 'id' ) ) ) {
427
+ $response[ 'status' ] = 'ok';
428
+ $response[ 'data' ][ 'service_id' ] = $appointment->get( 'service_id' );
429
+
430
+ $appointment_additional_info = $wpdb->get_row( $wpdb->prepare(
431
+ 'SELECT
432
+ ss.capacity AS max_capacity,
433
+ COUNT( ca.id ) AS current_capacity,
434
+ ca.notes AS notes
435
+ FROM ab_appointment a
436
+ LEFT JOIN ab_customer_appointment ca ON ca.appointment_id = a.id
437
+ LEFT JOIN ab_staff_service ss ON ss.staff_id = a.staff_id AND ss.service_id = a.service_id
438
+ WHERE a.id = %d',
439
+ $appointment->get('id')
440
+ ) );
441
+
442
+ $response[ 'data' ][ 'current_capacity' ] = $appointment_additional_info->current_capacity;
443
+ $response[ 'data' ][ 'max_capacity' ] = $appointment_additional_info->max_capacity;
444
+ $response[ 'data' ][ 'notes' ] = $appointment_additional_info->max_capacity == 1 && $appointment_additional_info->notes ? $appointment_additional_info->notes : null;
445
+
446
+ $customers = $wpdb->get_results(
447
+ $wpdb->prepare(
448
+ 'SELECT ca.*
449
+ FROM ab_customer_appointment ca
450
+ LEFT JOIN ab_customer ac ON ac.id = ca.customer_id
451
+ WHERE ca.appointment_id = %d',
452
+ $appointment->get('id')
453
+ )
454
+ );
455
+
456
+ foreach($customers as $customer){
457
+ $response[ 'data' ][ 'customers' ][] = $customer->customer_id;
458
+ }
459
+ }
460
+
461
+ exit ( json_encode( $response ) );
462
+ }
463
+
464
+ /**
465
+ * Save appointment form (for both create and edit).
466
+ */
467
+ public function executeSaveAppointmentForm() {
468
+ /**
469
+ * @var WPDB $wpdb
470
+ */
471
+ global $wpdb;
472
+
473
+ $response = array( 'status' => 'error' );
474
+
475
+ $start_date = date('Y-m-d H:i:s', strtotime( $this->getParameter('start_date' ) ) );
476
+ $end_date = date('Y-m-d H:i:s', strtotime( $this->getParameter( 'end_date' ) ) );
477
+ $staff_id = $this->getParameter( 'staff_id' );
478
+ $service_id = $this->getParameter( 'service_id', null );
479
+ $appointment_id = $this->getParameter( 'id', 0 );
480
+ $customers = json_decode( $this->getParameter( 'customers', '[]' ) );
481
+ $notes = $this->getParameter( 'notes', '' );
482
+
483
+ $staff_service = new AB_StaffService();
484
+ $staff_service->loadByStaffAndService($staff_id, $service_id);
485
+
486
+ // Check for errors.
487
+ if ( !$this->dateIntervalIsAvailableForAppointment( $start_date, $end_date, $staff_id, $appointment_id ) ) {
488
+ $response[ 'errors' ] = array( 'date_interval_not_available' => true );
489
+ }
490
+ if (count($customers) > $staff_service->get('capacity')) {
491
+ $response['errors']['overflow_capacity'] = true;
492
+ $response['errors']['overflow_capacity_message'] = __( 'Number of customers should be not more than ', 'ab' ) . $staff_service->get('capacity');
493
+ }
494
+
495
+ // If no errors then try to save the appointment.
496
+ if ( !isset ( $response[ 'errors' ] ) ) {
497
+ $appointment = new AB_Appointment();
498
+ if ( $appointment_id ) {
499
+ // edit
500
+ $appointment->load( $appointment_id );
501
+ }
502
+ $appointment->set('start_date', $start_date);
503
+ $appointment->set('end_date', $end_date);
504
+ $appointment->set('staff_id', $staff_id );
505
+ $appointment->set('service_id', $service_id );
506
+
507
+ if ( $appointment->save() !== false ) {
508
+ // save customers
509
+ $current_customers = $appointment->getCustomers();
510
+
511
+ foreach (array_diff(array_keys($current_customers), $customers) as $el){
512
+ $wpdb->delete('ab_customer_appointment', array('appointment_id' => $appointment->get('id'), 'customer_id' => $el));
513
+ }
514
+
515
+ foreach (array_diff($customers, array_keys($current_customers)) as $el){
516
+ $customer_appointment = new AB_Customer_Appointment();
517
+ $customer_appointment->set('appointment_id', $appointment->get('id'));
518
+ $customer_appointment->set('customer_id', $el);
519
+
520
+ while (true) {
521
+ $token = md5(uniqid(time(), true));
522
+ $result = $wpdb->get_row( $wpdb->prepare('SELECT * FROM `ab_customer_appointment` WHERE token = %s', $token));
523
+ if (!$result) {
524
+ break;
525
+ }
526
+ }
527
+ $customer_appointment->set('token', $token);
528
+ $customer_appointment->save();
529
+ }
530
+
531
+ $startDate = new DateTime( $appointment->get('start_date') );
532
+ $endDate = new DateTime( $appointment->get('end_date') );
533
+ $staff = new AB_Staff();
534
+ $staff->load( $staff_id );
535
+ $service = new AB_Service();
536
+ $service->load( $service_id );
537
+ $response[ 'status' ] = 'ok';
538
+ $desc = array();
539
+
540
+ $appointment_additional_info = $wpdb->get_row( $wpdb->prepare(
541
+ 'SELECT
542
+ ss.capacity AS max_capacity,
543
+ COUNT( ca.id ) AS current_capacity,
544
+ ca.customer_id,
545
+ ca.notes,
546
+ ca.id AS ca_id
547
+ FROM ab_appointment a
548
+ LEFT JOIN ab_customer_appointment ca ON ca.appointment_id = a.id
549
+ LEFT JOIN ab_staff_service ss ON ss.staff_id = a.staff_id AND ss.service_id = a.service_id
550
+ WHERE a.id = %d',
551
+ $appointment->get('id')
552
+ ) );
553
+
554
+ if ($appointment_additional_info->max_capacity == 1){
555
+
556
+ // save notes
557
+ $customer_appointment = new AB_Customer_Appointment();
558
+ $customer_appointment->load($appointment_additional_info->ca_id);
559
+ $customer_appointment->set( 'notes', $notes );
560
+ $customer_appointment->save();
561
+
562
+ $customer = new AB_Customer();
563
+ $customer->load($appointment_additional_info->customer_id);
564
+ foreach ( array( 'name', 'phone', 'email' ) as $data_entry ) {
565
+ $entry_value = $customer->get( $data_entry );
566
+ if ( $entry_value ) {
567
+ $desc[] = '<div class="wc-employee">' . esc_html( $entry_value ) . '</div>';
568
+ }
569
+ }
570
+
571
+ $desc[] = '<div class="wc-notes">' . nl2br( esc_html($notes ?: $appointment_additional_info->notes ) ) . '</div>';
572
+ }
573
+ else {
574
+ // save notes
575
+ $customer_appointment = new AB_Customer_Appointment();
576
+ $customer_appointment->load($appointment_additional_info->ca_id);
577
+ $customer_appointment->set( 'notes', null );
578
+ $customer_appointment->save();
579
+
580
+ $desc[] = '<div class="wc-notes">Signed up ' . $appointment_additional_info->current_capacity . '</div>';
581
+ $desc[] = '<div class="wc-notes">Capacity ' . $appointment_additional_info->max_capacity . '</div>';
582
+ }
583
+
584
+ $response[ 'data' ] = array(
585
+ 'id' => (int)$appointment->get( 'id' ),
586
+ 'start' => $startDate->format( 'm/d/Y H:i' ),
587
+ 'end' => $endDate->format( 'm/d/Y H:i' ),
588
+ 'desc' => implode('', $desc),
589
+ 'title' => $service->get( 'title' ) ? $service->get( 'title' ) : __( 'Untitled', 'ab' ),
590
+ 'color' => $service->get( 'color' ),
591
+ 'userId' => (int)$appointment->get( 'staff_id' ),
592
+ );
593
+
594
+ // refresh data
595
+ $current_customers = $appointment->getCustomers();
596
+
597
+ if ( $this->getParameter( 'email_notification' ) === 'true' ) {
598
+ // Send email notification to client with appointment info
599
+ $client_notification = $wpdb->get_row( 'SELECT * FROM ab_notifications WHERE slug = "client_info" AND active = 1' );
600
+
601
+ // Send email notification to service provider with appointment info
602
+ $staff_notification = $wpdb->get_row( 'SELECT * FROM ab_notifications WHERE slug = "provider_info" AND active = 1' );
603
+
604
+ foreach ( $current_customers as $customer ) {
605
+ if ( $client_notification ) {
606
+ $replacement = new AB_NotificationReplacement();
607
+ $replacement->setClientName( $customer->name );
608
+ $replacement->setClientPhone( $customer->phone );
609
+ $replacement->setClientEmail( $customer->email );
610
+ // $replacement->setClientNotes( nl2br( esc_html( $notes ) ) );
611
+ $replacement->setAppointmentTime( $appointment->get('start_date') );
612
+ $replacement->setServiceName( $service->get( 'title' ) ? $service->get( 'title' ) : __( 'Untitled', 'ab' ) );
613
+ $replacement->setServicePrice( $staff_service->get( 'price' ) );
614
+ $replacement->setAppointmentToken( $customer->token );
615
+ $replacement->setStaffName( $staff->get( 'full_name' ) );
616
+ $message = wpautop( $replacement->replace( $client_notification->message ) );
617
+ $subject = $replacement->replaceSubject( $client_notification->subject );
618
+ wp_mail( $customer->email, $subject, $message, AB_CommonUtils::getEmailHeaderFrom() );
619
+ }
620
+
621
+ if ( $staff_notification ) {
622
+ $replacement = new AB_NotificationReplacement();
623
+ $replacement->setClientName( $customer->name );
624
+ $replacement->setClientPhone( $customer->phone );
625
+ $replacement->setClientEmail( $customer->email );
626
+ // $replacement->setClientNotes( nl2br( esc_html( $notes ) ) );
627
+ $replacement->setAppointmentTime( $appointment->get('start_date') );
628
+ $replacement->setServiceName( $service->get( 'title' ) ? $service->get( 'title' ) : __( 'Untitled', 'ab' ) );
629
+ $replacement->setServicePrice( $staff_service->get( 'price' ) );
630
+ $replacement->setAppointmentToken( $customer->token );
631
+ $replacement->setStaffName($staff->get( 'full_name' ) );
632
+ $message = wpautop( $replacement->replace( $staff_notification->message ) );
633
+ $subject = $replacement->replaceSubject( $staff_notification->subject );
634
+
635
+ // Send copy to administrators
636
+ if ( $staff_notification->copy ) {
637
+ $admin_emails = AB_CommonUtils::getAdminEmails();
638
+ if ( ! empty ( $admin_emails ) ) {
639
+ wp_mail( $admin_emails, $subject, $message, AB_CommonUtils::getEmailHeaderFrom() );
640
+ }
641
+ }
642
+
643
+ wp_mail( $staff->get( 'email' ), $subject, $message, AB_CommonUtils::getEmailHeaderFrom() );
644
+ }
645
+ }
646
+ }
647
+ } else {
648
+ $response[ 'errors' ] = array( 'unknown' => true );
649
+ }
650
+ }
651
+
652
+ exit (json_encode($response));
653
+ }
654
+
655
+ public function executeCheckAppointmentDateSelection() {
656
+ $start_date = $this->getParameter( 'start_date' );
657
+ $end_date = $this->getParameter( 'end_date' );
658
+ $staff_id = $this->getParameter( 'staff_id' );
659
+ $service_id = $this->getParameter( 'service_id' );
660
+ $appointment_id = $this->getParameter( 'appointment_id' );
661
+ $timestamp_diff = strtotime( $end_date ) - strtotime( $start_date );
662
+
663
+ $result = array(
664
+ 'date_interval_not_available' => false,
665
+ 'date_interval_warning' => false,
666
+ );
667
+
668
+ if ( !$this->dateIntervalIsAvailableForAppointment( $start_date, $end_date, $staff_id, $appointment_id ) ) {
669
+ $result['date_interval_not_available'] = true;
670
+ }
671
+
672
+ if ( $service_id ) {
673
+ $service = new AB_Service();
674
+ $service->load( $service_id );
675
+
676
+ $duration = $service->get( 'duration' );
677
+
678
+ // service duration interval is not equal to
679
+ $result['date_interval_warning'] = ($timestamp_diff != $duration);
680
+ }
681
+
682
+ echo json_encode( $result );
683
+ exit;
684
+ }
685
+
686
+ public function executeCheckAppointmentMaxSelectedOptions(){
687
+ $staff_id = $this->getParameter( 'staff_id' );
688
+ $service_id = $this->getParameter( 'service_id' );
689
+
690
+ $staff_service = new AB_StaffService();
691
+ $staff_service->loadByStaffAndService($staff_id, $service_id);
692
+
693
+ echo json_encode( array('max_selected_options' => $staff_service->get('capacity')) );
694
+ exit;
695
+ }
696
+
697
+ public function executeDeleteAppointment() {
698
+ $appointment = new AB_Appointment();
699
+ $appointment->load( $this->getParameter( 'appointment_id' ) );
700
+ $appointment->delete();
701
+ exit;
702
+ }
703
+
704
+ /**
705
+ * @param $start_date
706
+ * @param $end_date
707
+ * @param $staff_id
708
+ * @param $appointment_id
709
+ * @return bool
710
+ */
711
+ private function dateIntervalIsAvailableForAppointment( $start_date, $end_date, $staff_id, $appointment_id ) {
712
+ return ! is_object( $this->getWpdb()->get_row( $this->getWpdb()->prepare(
713
+ 'SELECT * FROM `ab_appointment`
714
+ WHERE (
715
+ start_date > %s AND start_date < %s
716
+ OR (end_date > %s AND end_date < %s)
717
+ OR (start_date < %s AND end_date > %s)
718
+ OR (start_date = %s OR end_date = %s)
719
+ )
720
+ AND staff_id = %d
721
+ AND id <> %d',
722
+ $start_date,
723
+ $end_date,
724
+ $start_date,
725
+ $end_date,
726
+ $start_date,
727
+ $end_date,
728
+ $start_date,
729
+ $end_date,
730
+ $staff_id,
731
+ $appointment_id
732
+ ) ) );
733
+ }
734
+
735
+ /**
736
+ * @param $id
737
+ *
738
+ * @return AB_Customer
739
+ */
740
+ public function getCustomer( $id ) {
741
+ $customer = new AB_Customer();
742
+ $customer_data = $this->getWpdb()->get_row( $this->getWpdb()->prepare(
743
+ 'SELECT * FROM `ab_customer` WHERE id = %d', $id
744
+ ) );
745
+ // populate customer with data
746
+ if ( $customer_data ) {
747
+ $customer->setData( $customer_data );
748
+ }
749
+
750
+ return $customer;
751
+ }
752
+
753
+ /**
754
+ * Get appointment data
755
+ *
756
+ * @param stdClass $appointment
757
+ * @param null $user_id
758
+ * @param bool $day_view
759
+ *
760
+ * @return array
761
+ */
762
+ private function getAppointment( stdClass $appointment, $user_id = null, $day_view = false ) {
763
+ $startDate = new DateTime( $appointment->start_date );
764
+ $endDate = new DateTime( $appointment->end_date );
765
+ $desc = array();
766
+
767
+ if ($appointment->max_capacity == 1){
768
+ $customer = new AB_Customer();
769
+ $customer->load($appointment->customer_id);
770
+ foreach ( array( 'name', 'phone', 'email' ) as $data_entry ) {
771
+ $entry_value = $customer->get( $data_entry );
772
+ if ( $entry_value ) {
773
+ $desc[] = '<div class="wc-employee">' . esc_html( $entry_value ) . '</div>';
774
+ }
775
+ }
776
+
777
+ if ($appointment->notes) {
778
+ $desc[] = '<div class="wc-notes">' . nl2br( esc_html( $appointment->notes ) ) . '</div>';
779
+ }
780
+ }else{
781
+ $desc[] = '<div class="wc-notes">Signed up ' . $appointment->current_capacity . '</div>';
782
+ $desc[] = '<div class="wc-notes">Capacity ' . $appointment->max_capacity . '</div>';
783
+ }
784
+
785
+ $appointment_data = array(
786
+ 'id' => $appointment->id,
787
+ 'start' => $startDate->format( 'm/d/Y H:i' ),
788
+ 'end' => $endDate->format( 'm/d/Y H:i' ),
789
+ 'title' => $appointment->title ? esc_html( $appointment->title ) : __( 'Untitled', 'ab' ),
790
+ 'desc' => implode('', $desc),
791
+ 'color' => $appointment->color,
792
+ 'notes' => $appointment->max_capacity == 1 && $appointment->notes ? $appointment->notes : null
793
+ );
794
+
795
+ // if needed to be rendered for a specific user
796
+ // pass the the user id
797
+ if ( null !== $user_id ) {
798
+ $appointment_data['userId'] = $user_id;
799
+ }
800
+ return $appointment_data;
801
+ }
802
+
803
+ /**
804
+ * Get free busy data
805
+ *
806
+ * @param DateTime $startDate
807
+ * @param DateTime $endDate
808
+ * @param $free
809
+ * @param null $user_id
810
+ *
811
+ * @return array
812
+ */
813
+ private function getFreeBusy( DateTime $startDate, DateTime $endDate, $free, $user_id = null ) {
814
+ $freebusy_data = array(
815
+ 'start' => $startDate->format( 'm/d/Y H:i' ),
816
+ 'end' => $endDate->format( 'm/d/Y H:i' ),
817
+ 'free' => $free
818
+ );
819
+ // if needed to be rendered for a specific user
820
+ // pass the the user id
821
+ if ( null !== $user_id ) {
822
+ $freebusy_data['userId'] = $user_id;
823
+ }
824
+ return $freebusy_data;
825
+ }
826
+
827
+ /**
828
+ * @return string
829
+ */
830
+ private function dateFormatTojQueryUIDatePickerFormat() {
831
+ $chars = array(
832
+ // Day
833
+ 'd' => 'dd', 'j' => 'd', 'l' => 'DD', 'D' => 'D',
834
+ // Month
835
+ 'm' => 'mm', 'n' => 'm', 'F' => 'MM', 'M' => 'M',
836
+ // Year
837
+ 'Y' => 'yy', 'y' => 'y',
838
+ );
839
+
840
+ return strtr((string)get_option('date_format'), $chars);
841
+ }
842
+
843
+ /**
844
+ * Override parent method to add 'wp_ajax_ab_' prefix
845
+ * so current 'execute*' methods look nicer.
846
+ */
847
+ protected function registerWpActions( $prefix = '' ) {
848
+ parent::registerWpActions( 'wp_ajax_ab_' );
849
+ }
850
+ }
backend/modules/calendar/forms/AB_AppointmentForm.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ include AB_PATH.'/lib/entities/AB_Appointment.php';
6
+ include AB_PATH.'/lib/entities/AB_Customer_Appointment.php';
7
+
8
+ /**
9
+ * Class AB_AppointmentForm
10
+ */
11
+ class AB_AppointmentForm extends AB_Form {
12
+
13
+ /**
14
+ * Constructor.
15
+ */
16
+ public function __construct() {
17
+ parent::$entity_class = 'AB_Appointment';
18
+ parent::__construct();
19
+ }
20
+
21
+ public function configure() {
22
+ //$this->setFields( array() );
23
+ }
24
+ }
backend/modules/calendar/forms/AB_CustomerAppointmentForm.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ include dirname(__FILE__) . '/../../../../lib/entities/AB_Customer_Appointment.php';
6
+
7
+ /**
8
+ * Class AB_AppointmentForm
9
+ */
10
+ class AB_CustomerAppointmentForm extends AB_Form {
11
+
12
+ /**
13
+ * Constructor.
14
+ */
15
+ public function __construct() {
16
+ parent::$entity_class = 'AB_Customer_Appointment';
17
+ parent::__construct();
18
+ }
19
+
20
+ }
backend/modules/calendar/resources/css/calendar.css ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ /* calendar nav */
3
+ .ab-calendar-day, .ab-calendar-week, .ab-calendar-today, .btn-list, .btn-dropdown {
4
+ display: inline-block;
5
+ padding: 2px 10px;
6
+ margin-bottom: 0;
7
+ font-size: 12px;
8
+ line-height: 20px;
9
+ color: #fff;
10
+ text-align: center;
11
+ text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
12
+ vertical-align: middle;
13
+ cursor: pointer;
14
+ background-color: #21759b;
15
+ background-image: -webkit-gradient(linear,left top,left bottom,from(#2a95c5),to(#21759b));
16
+ background-image: -webkit-linear-gradient(top,#2a95c5,#21759b);
17
+ background-image: -moz-linear-gradient(top,#2a95c5,#21759b);
18
+ background-image: -ms-linear-gradient(top,#2a95c5,#21759b);
19
+ background-image: -o-linear-gradient(top,#2a95c5,#21759b);
20
+ background-image: linear-gradient(to bottom,#2a95c5,#21759b);
21
+ background-repeat: repeat-x;
22
+ border: 1px solid #21759b;
23
+ border-color: #e6e6e6 #e6e6e6 #1e6a8d;
24
+ border-bottom-color: #b3b3b3;
25
+ -webkit-border-radius: 4px;
26
+ -moz-border-radius: 4px;
27
+ border-radius: 4px;
28
+ -webkit-box-shadow: inset 0 1px 0 rgba(120,200,230,0.5);
29
+ moz-box-shadow: inset 0 1px 0 rgba(120,200,230,0.5);
30
+ box-shadow: inset 0 1px 0 rgba(120,200,230,0.5);
31
+ }
32
+ .ab-calendar-day { border-bottom-right-radius: 0px; border-top-right-radius: 0px; margin-top: 0; }
33
+ .ab-calendar-week { border-bottom-left-radius: 0px; border-top-left-radius: 0px; margin-left: -3px; margin-top: 0; border-left: 0; }
34
+ .ab-calendar-today { margin: 0 5px; border-radius: 3px; }
35
+ .ab-nav-calendar { height: 30px; }
36
+ .ab-nav-calendar .ab-button-active {
37
+ background: #1f6a8c;
38
+ }
39
+ .ab-nav-calendar .ab-popup-wrapper { margin-left: 10px; }
40
+ .ab-popup-table td { white-space: nowrap; padding: 5px; border: 0!important; }
41
+ .ab-popup-table td > p { margin: 0; }
42
+
43
+ .ab-btn-group .btn-list,
44
+ .ab-btn-group .btn-dropdown {
45
+ margin: 0;
46
+ border: 0;
47
+ float: left;
48
+ position: relative;
49
+ }
50
+ .ab-btn-group .btn-list {
51
+ border-bottom-right-radius: 0px;
52
+ border-top-right-radius: 0px;
53
+ padding-left: 25px;
54
+ }
55
+ .ab-btn-group .btn-dropdown {
56
+ font-size: 9px;
57
+ padding-left: 0;
58
+ border-bottom-left-radius: 0px;
59
+ border-top-left-radius: 0px;
60
+ }
61
+ .ab-icon-button {
62
+ position: absolute;
63
+ top: 3px;
64
+ left: 3px;
65
+ width: 15px;
66
+ height: 15px;
67
+ }
68
+ .ab-icon-button.ab-services {
69
+ background: url("../images/box-small.png") 2px 2px no-repeat;
70
+ }
71
+ .ab-icon-button.ab-staff {
72
+ background: url("../images/user-white.png") 0 2px no-repeat;
73
+ }
74
+
75
+ /** week picker */
76
+ .ab-week-picker-wrapper { width: auto; position: relative; margin-right: 15px; }
77
+ .ab-week-picker-wrapper .ab-week-picker { clear: both; left: -1px; position: absolute; top: 30px; z-index: 1; display: none; }
78
+ .ab-week-picker-data { border-radius: 3px; background: url("../images/calendar.png") 2px 4px no-repeat; padding: 4px 7px 4px 25px; height: 16px; border: 1px solid black; }
79
+ #appendedPrependedInput { width: 340px; background-color: #FFFFFF; cursor: default; }
80
+
81
+ /** appointment dialog */
82
+ .ab-appointment-popup .ui-widget-header {
83
+ background: none!important;
84
+ border: none!important;
85
+ border-bottom: 1px solid #eee!important;
86
+ margin: -5px -5px 15px -5px!important;
87
+ font-size: 24.5px!important;
88
+ font-family: sans-serif!important;
89
+ line-height: 26px!important;
90
+ padding: 9px 15px!important;
91
+ }
92
+
93
+ .ab-appointment-popup .loading-indicator img { display: block; margin: 20px auto; }
94
+ .ab-appointment-popup .dialog-button-wrapper { }
95
+
96
+ .ab-appointment-popup .dialog-content .ab-appointment-field-value { width: 110px; vertical-align: top; }
97
+ .ab-appointment-popup .dialog-content td { padding-top: 7px; text-align: left; white-space: nowrap; }
98
+ .ab-appointment-popup .dialog-content select { width: auto; max-width: 100%; }
99
+ .ab-appointment-popup .dialog-content { color: #333333!important; font-family: "Helvetica Neue",Helvetica,Arial,sans-serif!important; font-size: 14px!important; }
100
+ .ab-appointment-popup .dialog-content .ab-reset-form { color: #21759b; }
101
+ .ab-appointment-popup .dialog-content .ab-reset-form:hover { color: #d54e21; }
102
+
103
+ /** calendars */
104
+ #day_calendar_wrapper { margin-top: 55px; }
105
+
106
+ #date_interval_warning_msg { color: #21759B }
107
+ #date_interval_not_available_msg { color: red }
108
+
109
+ /** wp elements */
110
+ #update-nag, .update-nag, #wpfooter { display: none; }
111
+ #wpbody-content { padding-bottom: 0; }
112
+
113
+ .ab-date-picker { border: 1px solid black!important; padding: 4px 4px 4px 7px; border-radius: 3px; width: 65px; }
114
+ .ab-date-paginator { margin-left: 10px; }
115
+ .ab-date-paginator > a {
116
+ float: left;
117
+ text-decoration: none;
118
+ color: black;
119
+ padding: 4px 2px;
120
+ display: block;
121
+ border: 1px solid black;
122
+ margin-left: -1px;
123
+ width: 18px;
124
+ text-align: center;
125
+ }
126
+ .ab-date-paginator > a.first {
127
+ border-bottom-left-radius: 10px;
128
+ -webkit-border-bottom-left-radius: 10px;
129
+ -moz-border-bottom-left-radius: 10px;
130
+ -o-border-bottom-left-radius: 10px;
131
+ border-top-left-radius: 10px;
132
+ -webkit-border-top-left-radius: 10px;
133
+ -moz-border-top-left-radius: 10px;
134
+ -o-border-top-left-radius: 10px;
135
+ }
136
+ .ab-date-paginator > a.last {
137
+ border-bottom-right-radius: 10px;
138
+ -webkit-border-bottom-right-radius: 10px;
139
+ -moz-border-bottom-right-radius: 10px;
140
+ -o-border-bottom-right-radius: 10px;
141
+ border-top-right-radius: 10px;
142
+ -webkit-border-top-right-radius: 10px;
143
+ -moz-border-top-right-radius: 10px;
144
+ -o-border-top-right-radius: 10px;
145
+ }
146
+ .wc-cal-event {
147
+ background-color: #DDDDDD;
148
+ line-height: 16px!important;
149
+ }
150
+ .wc-cal-event .wc-time {
151
+ background-color : #DDDDDD;
152
+ border-left-color : #DDDDDD;
153
+ border-right-color : #DDDDDD;
154
+ border-top-color : #DDDDDD;
155
+ border-bottom-color : #ABABAB;
156
+ }
157
+
158
+ .wc-information {
159
+ background: url("../images/information.png") no-repeat scroll 1px 2px transparent;
160
+ float: right;
161
+ height: 16px;
162
+ width: 16px;
163
+ z-index: 20;
164
+ }
165
+
166
+ .wc-service-name, .wc-employee {
167
+ padding: 3px 0;
168
+ }
169
+
170
+ .right-margin { margin-right: 10px; }
171
+ .pagination { margin: 0!important; }
172
+
173
+ .nav-tabs > .active > a { background: #1f6a8c!important; color: white!important; border-left: 0!important; }
174
+ .ab-date-calendar { padding-left: 25px!important; background: url("../images/calendar.png") 5px 8px no-repeat; }
backend/modules/calendar/resources/css/chosen-sprite.png ADDED
Binary file
backend/modules/calendar/resources/css/chosen-sprite@2x.png ADDED
Binary file
backend/modules/calendar/resources/css/chosen.css ADDED
@@ -0,0 +1,437 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ Chosen, a Select Box Enhancer for jQuery and Prototype
3
+ by Patrick Filler for Harvest, http://getharvest.com
4
+
5
+ Version 1.2.0
6
+ Full source at https://github.com/harvesthq/chosen
7
+ Copyright (c) 2011-2014 Harvest http://getharvest.com
8
+
9
+ MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md
10
+ This file is generated by `grunt build`, do not edit it by hand.
11
+ */
12
+
13
+ /* @group Base */
14
+ .chosen-container {
15
+ position: relative;
16
+ display: inline-block;
17
+ vertical-align: middle;
18
+ font-size: 13px;
19
+ zoom: 1;
20
+ *display: inline;
21
+ -webkit-user-select: none;
22
+ -moz-user-select: none;
23
+ user-select: none;
24
+ }
25
+ .chosen-container * {
26
+ -webkit-box-sizing: border-box;
27
+ -moz-box-sizing: border-box;
28
+ box-sizing: border-box;
29
+ }
30
+ .chosen-container .chosen-drop {
31
+ position: absolute;
32
+ top: 100%;
33
+ left: -9999px;
34
+ z-index: 1010;
35
+ width: 100%;
36
+ border: 1px solid #aaa;
37
+ border-top: 0;
38
+ background: #fff;
39
+ box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15);
40
+ }
41
+ .chosen-container.chosen-with-drop .chosen-drop {
42
+ left: 0;
43
+ }
44
+ .chosen-container a {
45
+ cursor: pointer;
46
+ }
47
+
48
+ /* @end */
49
+ /* @group Single Chosen */
50
+ .chosen-container-single .chosen-single {
51
+ position: relative;
52
+ display: block;
53
+ overflow: hidden;
54
+ padding: 0 0 0 8px;
55
+ height: 25px;
56
+ border: 1px solid #aaa;
57
+ border-radius: 5px;
58
+ background-color: #fff;
59
+ background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #ffffff), color-stop(50%, #f6f6f6), color-stop(52%, #eeeeee), color-stop(100%, #f4f4f4));
60
+ background: -webkit-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
61
+ background: -moz-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
62
+ background: -o-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
63
+ background: linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
64
+ background-clip: padding-box;
65
+ box-shadow: 0 0 3px white inset, 0 1px 1px rgba(0, 0, 0, 0.1);
66
+ color: #444;
67
+ text-decoration: none;
68
+ white-space: nowrap;
69
+ line-height: 24px;
70
+ }
71
+ .chosen-container-single .chosen-default {
72
+ color: #999;
73
+ }
74
+ .chosen-container-single .chosen-single span {
75
+ display: block;
76
+ overflow: hidden;
77
+ margin-right: 26px;
78
+ text-overflow: ellipsis;
79
+ white-space: nowrap;
80
+ }
81
+ .chosen-container-single .chosen-single-with-deselect span {
82
+ margin-right: 38px;
83
+ }
84
+ .chosen-container-single .chosen-single abbr {
85
+ position: absolute;
86
+ top: 6px;
87
+ right: 26px;
88
+ display: block;
89
+ width: 12px;
90
+ height: 12px;
91
+ background: url('chosen-sprite.png') -42px 1px no-repeat;
92
+ font-size: 1px;
93
+ }
94
+ .chosen-container-single .chosen-single abbr:hover {
95
+ background-position: -42px -10px;
96
+ }
97
+ .chosen-container-single.chosen-disabled .chosen-single abbr:hover {
98
+ background-position: -42px -10px;
99
+ }
100
+ .chosen-container-single .chosen-single div {
101
+ position: absolute;
102
+ top: 0;
103
+ right: 0;
104
+ display: block;
105
+ width: 18px;
106
+ height: 100%;
107
+ }
108
+ .chosen-container-single .chosen-single div b {
109
+ display: block;
110
+ width: 100%;
111
+ height: 100%;
112
+ background: url('chosen-sprite.png') no-repeat 0px 2px;
113
+ }
114
+ .chosen-container-single .chosen-search {
115
+ position: relative;
116
+ z-index: 1010;
117
+ margin: 0;
118
+ padding: 3px 4px;
119
+ white-space: nowrap;
120
+ }
121
+ .chosen-container-single .chosen-search input[type="text"] {
122
+ margin: 1px 0;
123
+ padding: 4px 20px 4px 5px;
124
+ width: 100%;
125
+ height: auto;
126
+ outline: 0;
127
+ border: 1px solid #aaa;
128
+ background: white url('chosen-sprite.png') no-repeat 100% -20px;
129
+ background: url('chosen-sprite.png') no-repeat 100% -20px;
130
+ font-size: 1em;
131
+ font-family: sans-serif;
132
+ line-height: normal;
133
+ border-radius: 0;
134
+ }
135
+ .chosen-container-single .chosen-drop {
136
+ margin-top: -1px;
137
+ border-radius: 0 0 4px 4px;
138
+ background-clip: padding-box;
139
+ }
140
+ .chosen-container-single.chosen-container-single-nosearch .chosen-search {
141
+ position: absolute;
142
+ left: -9999px;
143
+ }
144
+
145
+ /* @end */
146
+ /* @group Results */
147
+ .chosen-container .chosen-results {
148
+ color: #444;
149
+ position: relative;
150
+ overflow-x: hidden;
151
+ overflow-y: auto;
152
+ margin: 0 4px 4px 0;
153
+ padding: 0 0 0 4px;
154
+ max-height: 240px;
155
+ -webkit-overflow-scrolling: touch;
156
+ }
157
+ .chosen-container .chosen-results li {
158
+ display: none;
159
+ margin: 0;
160
+ padding: 5px 6px;
161
+ list-style: none;
162
+ line-height: 15px;
163
+ word-wrap: break-word;
164
+ -webkit-touch-callout: none;
165
+ }
166
+ .chosen-container .chosen-results li.active-result {
167
+ display: list-item;
168
+ cursor: pointer;
169
+ }
170
+ .chosen-container .chosen-results li.disabled-result {
171
+ display: list-item;
172
+ color: #ccc;
173
+ cursor: default;
174
+ }
175
+ .chosen-container .chosen-results li.highlighted {
176
+ background-color: #3875d7;
177
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #3875d7), color-stop(90%, #2a62bc));
178
+ background-image: -webkit-linear-gradient(#3875d7 20%, #2a62bc 90%);
179
+ background-image: -moz-linear-gradient(#3875d7 20%, #2a62bc 90%);
180
+ background-image: -o-linear-gradient(#3875d7 20%, #2a62bc 90%);
181
+ background-image: linear-gradient(#3875d7 20%, #2a62bc 90%);
182
+ color: #fff;
183
+ }
184
+ .chosen-container .chosen-results li.no-results {
185
+ color: #777;
186
+ display: list-item;
187
+ background: #f4f4f4;
188
+ }
189
+ .chosen-container .chosen-results li.group-result {
190
+ display: list-item;
191
+ font-weight: bold;
192
+ cursor: default;
193
+ }
194
+ .chosen-container .chosen-results li.group-option {
195
+ padding-left: 15px;
196
+ }
197
+ .chosen-container .chosen-results li em {
198
+ font-style: normal;
199
+ text-decoration: underline;
200
+ }
201
+
202
+ /* @end */
203
+ /* @group Multi Chosen */
204
+ .chosen-container-multi .chosen-choices {
205
+ position: relative;
206
+ overflow: hidden;
207
+ margin: 0;
208
+ padding: 0 5px;
209
+ width: 100%;
210
+ height: auto !important;
211
+ height: 1%;
212
+ border: 1px solid #aaa;
213
+ background-color: #fff;
214
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
215
+ background-image: -webkit-linear-gradient(#eeeeee 1%, #ffffff 15%);
216
+ background-image: -moz-linear-gradient(#eeeeee 1%, #ffffff 15%);
217
+ background-image: -o-linear-gradient(#eeeeee 1%, #ffffff 15%);
218
+ background-image: linear-gradient(#eeeeee 1%, #ffffff 15%);
219
+ cursor: text;
220
+ }
221
+ .chosen-container-multi .chosen-choices li {
222
+ float: left;
223
+ list-style: none;
224
+ }
225
+ .chosen-container-multi .chosen-choices li.search-field {
226
+ margin: 0;
227
+ padding: 0;
228
+ white-space: nowrap;
229
+ }
230
+ .chosen-container-multi .chosen-choices li.search-field input[type="text"] {
231
+ margin: 1px 0;
232
+ padding: 0;
233
+ height: 25px;
234
+ outline: 0;
235
+ border: 0 !important;
236
+ background: transparent !important;
237
+ box-shadow: none;
238
+ color: #999;
239
+ font-size: 100%;
240
+ font-family: sans-serif;
241
+ line-height: normal;
242
+ border-radius: 0;
243
+ }
244
+ .chosen-container-multi .chosen-choices li.search-choice {
245
+ position: relative;
246
+ margin: 3px 5px 3px 0;
247
+ padding: 3px 20px 3px 5px;
248
+ border: 1px solid #aaa;
249
+ max-width: 100%;
250
+ border-radius: 3px;
251
+ background-color: #eeeeee;
252
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));
253
+ background-image: -webkit-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
254
+ background-image: -moz-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
255
+ background-image: -o-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
256
+ background-image: linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
257
+ background-size: 100% 19px;
258
+ background-repeat: repeat-x;
259
+ background-clip: padding-box;
260
+ box-shadow: 0 0 2px white inset, 0 1px 0 rgba(0, 0, 0, 0.05);
261
+ color: #333;
262
+ line-height: 13px;
263
+ cursor: default;
264
+ }
265
+ .chosen-container-multi .chosen-choices li.search-choice span {
266
+ word-wrap: break-word;
267
+ }
268
+ .chosen-container-multi .chosen-choices li.search-choice .search-choice-close {
269
+ position: absolute;
270
+ top: 4px;
271
+ right: 3px;
272
+ display: block;
273
+ width: 12px;
274
+ height: 12px;
275
+ background: url('chosen-sprite.png') -42px 1px no-repeat;
276
+ font-size: 1px;
277
+ }
278
+ .chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover {
279
+ background-position: -42px -10px;
280
+ }
281
+ .chosen-container-multi .chosen-choices li.search-choice-disabled {
282
+ padding-right: 5px;
283
+ border: 1px solid #ccc;
284
+ background-color: #e4e4e4;
285
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));
286
+ background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
287
+ background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
288
+ background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
289
+ background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
290
+ color: #666;
291
+ }
292
+ .chosen-container-multi .chosen-choices li.search-choice-focus {
293
+ background: #d4d4d4;
294
+ }
295
+ .chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close {
296
+ background-position: -42px -10px;
297
+ }
298
+ .chosen-container-multi .chosen-results {
299
+ margin: 0;
300
+ padding: 0;
301
+ }
302
+ .chosen-container-multi .chosen-drop .result-selected {
303
+ display: list-item;
304
+ color: #ccc;
305
+ cursor: default;
306
+ }
307
+
308
+ /* @end */
309
+ /* @group Active */
310
+ .chosen-container-active .chosen-single {
311
+ border: 1px solid #5897fb;
312
+ box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
313
+ }
314
+ .chosen-container-active.chosen-with-drop .chosen-single {
315
+ border: 1px solid #aaa;
316
+ -moz-border-radius-bottomright: 0;
317
+ border-bottom-right-radius: 0;
318
+ -moz-border-radius-bottomleft: 0;
319
+ border-bottom-left-radius: 0;
320
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #eeeeee), color-stop(80%, #ffffff));
321
+ background-image: -webkit-linear-gradient(#eeeeee 20%, #ffffff 80%);
322
+ background-image: -moz-linear-gradient(#eeeeee 20%, #ffffff 80%);
323
+ background-image: -o-linear-gradient(#eeeeee 20%, #ffffff 80%);
324
+ background-image: linear-gradient(#eeeeee 20%, #ffffff 80%);
325
+ box-shadow: 0 1px 0 #fff inset;
326
+ }
327
+ .chosen-container-active.chosen-with-drop .chosen-single div {
328
+ border-left: none;
329
+ background: transparent;
330
+ }
331
+ .chosen-container-active.chosen-with-drop .chosen-single div b {
332
+ background-position: -18px 2px;
333
+ }
334
+ .chosen-container-active .chosen-choices {
335
+ border: 1px solid #5897fb;
336
+ box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
337
+ }
338
+ .chosen-container-active .chosen-choices li.search-field input[type="text"] {
339
+ color: #222 !important;
340
+ }
341
+
342
+ /* @end */
343
+ /* @group Disabled Support */
344
+ .chosen-disabled {
345
+ opacity: 0.5 !important;
346
+ cursor: default;
347
+ }
348
+ .chosen-disabled .chosen-single {
349
+ cursor: default;
350
+ }
351
+ .chosen-disabled .chosen-choices .search-choice .search-choice-close {
352
+ cursor: default;
353
+ }
354
+
355
+ /* @end */
356
+ /* @group Right to Left */
357
+ .chosen-rtl {
358
+ text-align: right;
359
+ }
360
+ .chosen-rtl .chosen-single {
361
+ overflow: visible;
362
+ padding: 0 8px 0 0;
363
+ }
364
+ .chosen-rtl .chosen-single span {
365
+ margin-right: 0;
366
+ margin-left: 26px;
367
+ direction: rtl;
368
+ }
369
+ .chosen-rtl .chosen-single-with-deselect span {
370
+ margin-left: 38px;
371
+ }
372
+ .chosen-rtl .chosen-single div {
373
+ right: auto;
374
+ left: 3px;
375
+ }
376
+ .chosen-rtl .chosen-single abbr {
377
+ right: auto;
378
+ left: 26px;
379
+ }
380
+ .chosen-rtl .chosen-choices li {
381
+ float: right;
382
+ }
383
+ .chosen-rtl .chosen-choices li.search-field input[type="text"] {
384
+ direction: rtl;
385
+ }
386
+ .chosen-rtl .chosen-choices li.search-choice {
387
+ margin: 3px 5px 3px 0;
388
+ padding: 3px 5px 3px 19px;
389
+ }
390
+ .chosen-rtl .chosen-choices li.search-choice .search-choice-close {
391
+ right: auto;
392
+ left: 4px;
393
+ }
394
+ .chosen-rtl.chosen-container-single-nosearch .chosen-search,
395
+ .chosen-rtl .chosen-drop {
396
+ left: 9999px;
397
+ }
398
+ .chosen-rtl.chosen-container-single .chosen-results {
399
+ margin: 0 0 4px 4px;
400
+ padding: 0 4px 0 0;
401
+ }
402
+ .chosen-rtl .chosen-results li.group-option {
403
+ padding-right: 15px;
404
+ padding-left: 0;
405
+ }
406
+ .chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div {
407
+ border-right: none;
408
+ }
409
+ .chosen-rtl .chosen-search input[type="text"] {
410
+ padding: 4px 5px 4px 20px;
411
+ background: white url('chosen-sprite.png') no-repeat -30px -20px;
412
+ background: url('chosen-sprite.png') no-repeat -30px -20px;
413
+ direction: rtl;
414
+ }
415
+ .chosen-rtl.chosen-container-single .chosen-single div b {
416
+ background-position: 6px 2px;
417
+ }
418
+ .chosen-rtl.chosen-container-single.chosen-with-drop .chosen-single div b {
419
+ background-position: -12px 2px;
420
+ }
421
+
422
+ /* @end */
423
+ /* @group Retina compatibility */
424
+ @media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-resolution: 144dpi) {
425
+ .chosen-rtl .chosen-search input[type="text"],
426
+ .chosen-container-single .chosen-single abbr,
427
+ .chosen-container-single .chosen-single div b,
428
+ .chosen-container-single .chosen-search input[type="text"],
429
+ .chosen-container-multi .chosen-choices .search-choice .search-choice-close,
430
+ .chosen-container .chosen-results-scroll-down span,
431
+ .chosen-container .chosen-results-scroll-up span {
432
+ background-image: url('chosen-sprite@2x.png') !important;
433
+ background-size: 52px 37px !important;
434
+ background-repeat: no-repeat !important;
435
+ }
436
+ }
437
+ /* @end */
backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/animated-overlay.gif ADDED
Binary file
backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/ui-bg_flat_0_aaaaaa_40x100.png ADDED
Binary file
backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/ui-bg_flat_75_ffffff_40x100.png ADDED
Binary file
backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/ui-bg_glass_55_fbf9ee_1x400.png ADDED
Binary file
backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/ui-bg_glass_65_ffffff_1x400.png ADDED
Binary file
backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/ui-bg_glass_75_dadada_1x400.png ADDED
Binary file
backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/ui-bg_glass_75_e6e6e6_1x400.png ADDED
Binary file
backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/ui-bg_glass_95_fef1ec_1x400.png ADDED
Binary file
backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/ui-bg_highlight-soft_75_cccccc_1x100.png ADDED
Binary file
backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/ui-icons_222222_256x240.png ADDED
Binary file
backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/ui-icons_2e83ff_256x240.png ADDED
Binary file
backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/ui-icons_454545_256x240.png ADDED
Binary file
backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/ui-icons_888888_256x240.png ADDED
Binary file
backend/modules/calendar/resources/css/jquery-ui-1.10.4/images/ui-icons_cd0a0a_256x240.png ADDED
Binary file
backend/modules/calendar/resources/css/jquery-ui-1.10.4/jquery-ui.min.css ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ /*! jQuery UI - v1.10.4 - 2014-04-02
2
+ * http://jqueryui.com
3
+ * Includes: jquery.ui.core.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.resizable.css, jquery.ui.selectable.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=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
5
+ * Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */
6
+
7
+ .ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin-top:2px;padding:.5em .5em .5em .7em;min-height:0}.ui-accordion .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-noicons{padding-left:.7em}.ui-accordion .ui-accordion-icons .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-accordion-header-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-button{display:inline-block;position:relative;padding:0;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:normal}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:49%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-dialog{overflow:hidden;position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:20px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:12px;height:12px;right:-5px;bottom:-5px;background-position:16px 16px}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-menu{list-style:none;padding:2px;margin:0;display:block;outline:none}.ui-menu .ui-menu{margin-top:-3px;position:absolute}.ui-menu .ui-menu-item{margin:0;padding:0;width:100%;list-style-image:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)}.ui-menu .ui-menu-divider{margin:5px -2px 5px -2px;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-menu-item a{text-decoration:none;display:block;padding:2px .4em;line-height:1.5;min-height:0;font-weight:normal}.ui-menu .ui-menu-item a.ui-state-focus,.ui-menu .ui-menu-item a.ui-state-active{font-weight:normal;margin:-1px}.ui-menu .ui-state-disabled{font-weight:normal;margin:.4em 0 .2em;line-height:1.5}.ui-menu .ui-state-disabled a{cursor:default}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item a{position:relative;padding-left:2em}.ui-menu .ui-icon{position:absolute;top:.2em;left:.2em}.ui-menu .ui-menu-icon{position:static;float:right}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url("images/animated-overlay.gif");height:100%;filter:alpha(opacity=25);opacity:0.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;color:inherit;padding:0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:22px}.ui-spinner-button{width:16px;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top:none;border-bottom:none;border-right:none}.ui-spinner .ui-icon{position:absolute;margin-top:-8px;top:50%;left:0}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-spinner .ui-icon-triangle-1-s{background-position:-65px -16px}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav .ui-tabs-anchor{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor{cursor:text}.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #aaa;background:#fff url("images/ui-bg_flat_75_ffffff_40x100.png") 50% 50% repeat-x;color:#222}.ui-widget-content a{color:#222}.ui-widget-header{border:1px solid #aaa;background:#ccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x;color:#222;font-weight:bold}.ui-widget-header a{color:#222}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #d3d3d3;background:#e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#555}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#555;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #999;background:#dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited{color:#212121;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #aaa;background:#fff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#212121;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fcefa1;background:#fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;color:#cd0a0a}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_222222_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_222222_256x240.png")}.ui-state-default .ui-icon{background-image:url("images/ui-icons_888888_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url("images/ui-icons_454545_256x240.png")}.ui-state-active .ui-icon{background-image:url("images/ui-icons_454545_256x240.png")}.ui-state-highlight .ui-icon{background-image:url("images/ui-icons_2e83ff_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_cd0a0a_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:4px}.ui-widget-overlay{background:#aaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30);border-radius:8px}
backend/modules/calendar/resources/css/jquery.weekcalendar.css ADDED
@@ -0,0 +1,291 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .wc-container {
2
+ font-size: 14px;
3
+ font-family: arial, helvetica;
4
+ }
5
+
6
+ .wc-toolbar {
7
+ padding: 1em;
8
+ font-size:0.8em;
9
+ }
10
+
11
+ .wc-toolbar .wc-nav {
12
+ float:left;
13
+ }
14
+
15
+ .wc-toolbar .wc-display {
16
+ float: right;
17
+ }
18
+
19
+ .wc-toolbar button {
20
+ margin-top: 0;
21
+ margin-bottom: 0;
22
+ }
23
+
24
+ .wc-toolbar .wc-title {
25
+ text-align: center;
26
+ padding:0;
27
+ margin:0;
28
+ }
29
+
30
+ .wc-container table {
31
+ border-collapse: collapse;
32
+ border-spacing: 0;
33
+ }
34
+ .wc-container table td {
35
+ margin: 0;
36
+ padding: 0;
37
+ }
38
+
39
+ .wc-header {
40
+ background: #eee;
41
+ border-width:1px 0;
42
+ border-style:solid;
43
+ }
44
+ .wc-header table{
45
+ width: 100%;
46
+ table-layout:fixed;
47
+ }
48
+
49
+ .wc-grid-timeslot-header,
50
+ .wc-header .wc-time-column-header {
51
+ width: 45px;
52
+ }
53
+
54
+ .wc-header .wc-scrollbar-shim {
55
+ /* this width replace js */
56
+ }
57
+
58
+ .wc-header .wc-day-column-header {
59
+ text-align: center;
60
+ padding: 0.4em;
61
+ }
62
+
63
+ .wc-header .wc-user-header{
64
+ text-align: center;
65
+ padding: 0.4em 0;
66
+ overflow:hidden;
67
+ }
68
+ .wc-grid-timeslot-header {
69
+ background: #eee;
70
+ }
71
+
72
+
73
+
74
+ .wc-scrollable-grid {
75
+ overflow: auto;
76
+ overflow-x: hidden !important;
77
+ overflow-y: auto !important;
78
+ position: relative;
79
+ background-color: #fff;
80
+ width: 100%;
81
+ }
82
+
83
+
84
+ table.wc-time-slots {
85
+ width: 100%;
86
+ table-layout: fixed;
87
+ cursor: default;
88
+ overflow:hidden;
89
+ }
90
+
91
+ .wc-day-column {
92
+ width: 13.5%;
93
+ overflow: visible;
94
+ vertical-align: top;
95
+ }
96
+ .wc-day-column-header{border-width: 0 0 0 3px; border-style: double;border-color:#aaaaaa;}
97
+ .wc-scrollable-grid .wc-day-column-last,
98
+ .wc-scrollable-grid .wc-day-column-middle{border-width: 0 0 0 1px; border-style: dashed;}
99
+ .wc-scrollable-grid .wc-day-column-first{border-width: 0 0 0 3px; border-style: double;}
100
+
101
+ .wc-day-column-inner {
102
+ width: 100%;
103
+ position:relative;
104
+ }
105
+
106
+ .wc-no-height-wrapper{
107
+ position:relative;
108
+ overflow: visible;
109
+ height: 0px;
110
+ }
111
+
112
+ .wc-time-slot-wrapper {
113
+ /* top: 3px;*/
114
+ }
115
+ .wc-oddeven-wrapper .wc-full-height-column{
116
+ /* top: 2px; */
117
+ /* Modern Browsers */ opacity: 0.4;
118
+ /* IE 8 */ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=40)";
119
+ /* IE 5-7 */ filter: alpha(opacity=40);
120
+ /* Netscape */ -moz-opacity: 0.4;
121
+ /* Safari 1 */ -khtml-opacity: 0.4;
122
+ }
123
+ .wc-freebusy-wrapper .wc-freebusy{
124
+ /* top: 1px;*/
125
+ /* Modern Browsers */ opacity: 0.4;
126
+ /* IE 8 */ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=40)";
127
+ /* IE 5-7 */ filter: alpha(opacity=40);
128
+ /* Netscape */ -moz-opacity: 0.4;
129
+ /* Safari 1 */ -khtml-opacity: 0.4;
130
+ }
131
+
132
+ .wc-time-slots {
133
+ position: absolute;
134
+ width: 100%;
135
+ }
136
+
137
+ .wc-column-odd,
138
+ .wc-column-even.ui-state-hover{background-image:none;border:none;}
139
+
140
+ .wc-header .wc-today.ui-state-active{background-image:none;}
141
+ .wc-header .wc-today.wc-day-column-header{border-width:0 3px; border-style: double;}
142
+ .wc-header .wc-user-header{border-width:0;}
143
+
144
+ .wc-time-slots .wc-day-column.ui-state-default{background:transparent;}
145
+ .wc-time-slots .wc-today.ui-state-active{background-image:none;}
146
+ .wc-header .wc-today.ui-state-active.wc-day-column-middle{border-width:0;}
147
+ .wc-header .wc-today.ui-state-active.wc-day-column-first{border-left-width:3px;}
148
+ .wc-header .wc-today.ui-state-active.wc-day-column-last{border-right-width:3px;}
149
+
150
+ .wc-full-height-column{
151
+ display:block;
152
+ /* width:100%;*/
153
+ }
154
+
155
+
156
+ .wc-time-header-cell {
157
+ padding: 5px;
158
+ height: 80px; /* reference height */
159
+ }
160
+
161
+
162
+ .wc-time-slot {
163
+ border-bottom: 1px dotted #ddd;
164
+ }
165
+
166
+ .wc-hour-header {
167
+ text-align: right;
168
+ }
169
+ .wc-hour-header.ui-state-active,
170
+ .wc-hour-header.ui-state-default{
171
+ border-width:0 0 1px 0;
172
+ }
173
+
174
+ .wc-hour-header.ui-state-default{
175
+ background-image: none;
176
+ }
177
+
178
+ .wc-hour-end, .wc-hour-header {
179
+ border-bottom: 1px solid #ccc;
180
+ color: #555;
181
+
182
+ }
183
+
184
+ .wc-business-hours {
185
+ background-color: #E6EEF1;
186
+ border-bottom: 1px solid #ccc;
187
+ color: #333;
188
+ font-size: 1.4em;
189
+
190
+ }
191
+
192
+ .wc-business-hours .wc-am-pm {
193
+ font-size: 0.6em;
194
+ }
195
+
196
+ .wc-day-header-cell {
197
+ text-align: center;
198
+ vertical-align: middle;
199
+ padding: 5px;
200
+ }
201
+
202
+
203
+
204
+ .wc-time-slot-header .wc-header-cell {
205
+ text-align: right;
206
+ padding-right: 10px;
207
+ }
208
+
209
+ .wc-cal-event {
210
+ background-color: #68a1e5;
211
+ /* Modern Browsers */ opacity: 0.8;
212
+ /* IE 8 */ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)";
213
+ /* IE 5-7 */ filter: alpha(opacity=80);
214
+ /* Netscape */ -moz-opacity: 0.8;
215
+ /* Safari 1 */ -khtml-opacity: 0.8;
216
+ position: absolute;
217
+ text-align: center;
218
+ overflow: hidden;
219
+ cursor: pointer;
220
+ color: #fff;
221
+ width: 100%;
222
+ display: none;
223
+ }
224
+
225
+
226
+ .wc-cal-event-delete {
227
+ float: right;
228
+ cursor: pointer;
229
+ width: 16px;
230
+ height: 16px;
231
+ }
232
+
233
+ .wc-cal-event.ui-resizable-resizing {
234
+ cursor: s-resize;
235
+ }
236
+
237
+ .wc-cal-event .wc-time {
238
+ background-color: #2b72d0;
239
+ border: 1px solid #1b62c0;
240
+ color: #fff;
241
+ padding: 0;
242
+ font-weight: bold;
243
+ }
244
+
245
+ .wc-container .ui-draggable .wc-time {
246
+ cursor: move;
247
+ }
248
+
249
+ .wc-cal-event .wc-title {
250
+ position: relative;
251
+ }
252
+
253
+ .wc-container .ui-resizable-s {
254
+ height: 10px;
255
+ line-height: 10px;
256
+ bottom: -2px;
257
+ font-size: .75em;
258
+ }
259
+
260
+
261
+ .wc-container .ui-draggable-dragging {
262
+ z-index: 1000;
263
+ }
264
+
265
+ .free-busy-free{}
266
+ .free-busy-busy{
267
+ background:url("jquery-ui-1.10.4/images/ui-bg_flat_0_aaaaaa_40x100.png") repeat scroll 50% 50% #666666;
268
+ }
269
+
270
+ /** hourLine */
271
+
272
+ .wc-hourline {
273
+ height: 0pt;
274
+ border-top: 2px solid #FF7F6E;
275
+ overflow: hidden;
276
+ position: absolute;
277
+ width: inherit;
278
+ }
279
+
280
+ /* IE6 hacks */
281
+ * html .wc-no-height-wrapper{position:absolute;}
282
+ * html .wc-time-slot-wrapper{top:3px;}
283
+ * html .wc-grid-row-oddeven{top:2px;}
284
+ * html .wc-grid-row-freebusy{top:1px;}
285
+
286
+ /* IE7 hacks */
287
+ *:first-child+html .wc-no-height-wrapper{position:relative;}
288
+ *:first-child+html .wc-time-slot-wrapper{top:3px;}
289
+ *:first-child+html .wc-grid-row-oddeven{top:2px;}
290
+ *:first-child+html .wc-grid-row-freebusy{top:1px;}
291
+ *:first-child+html .wc-time-slots .wc-today{/* due to rendering issues, no background */background:none;}
backend/modules/calendar/resources/images/box-small.png ADDED
Binary file
backend/modules/calendar/resources/images/calendar.png ADDED
Binary file
backend/modules/calendar/resources/images/calendar1.png ADDED
Binary file
backend/modules/calendar/resources/images/chosen-sprite.png ADDED
Binary file
backend/modules/calendar/resources/images/information.png ADDED
Binary file
backend/modules/calendar/resources/images/ui-bg_flat_0_aaaaaa_40x100.png ADDED
Binary file
backend/modules/calendar/resources/images/user-white.png ADDED
Binary file
backend/modules/calendar/resources/images/user.png ADDED
Binary file
backend/modules/calendar/resources/js/calendar.js ADDED
@@ -0,0 +1,550 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(function ($) {
2
+ // Resolve conflict between Bootstrap and jQuery UI in favor of jQuery UI.
3
+ $.fn.button.noConflict();
4
+
5
+ var $week_calendar_wrapper = $('#week_calendar_wrapper'),
6
+ $week_calendar = $week_calendar_wrapper.find('.ab-calendar-element'),
7
+ $tabs = $week_calendar_wrapper.find('.nav-tabs'),
8
+ $day_calendar_wrapper = $('#day_calendar_wrapper'),
9
+ $day_calendar = $day_calendar_wrapper.find('.ab-calendar-element'),
10
+ $first_day_of_week = parseInt($('#ab_calendar_data_holder .ab-calendar-first-day').text(), 10),
11
+ $time_format = $('#ab_calendar_data_holder .ab-calendar-time-format').text(),
12
+ $staff_tabs = $('.ab-calendar-tab'),
13
+ // Staff filter vars
14
+ $staff_filter_button = $('#ab-staff-button'),
15
+ $all_staff_option = $('#ab-filter-all-staff'),
16
+ $staff_option = $('.ab-staff-option'),
17
+
18
+ $calendar_common_options = {
19
+ timeslotsPerHour: BooklyL10n.timeslotsPerHour,
20
+ timeslotHeight: 25,
21
+ scrollToHourMillis : 0,
22
+ businessHours: {start: 8, end: 18},
23
+ firstDayOfWeek: $first_day_of_week,
24
+ hourLine: true,
25
+ displayFreeBusys: true,
26
+ useShortDayNames: true,
27
+ showHeader: false,
28
+ headerSeparator: '',
29
+ dateFormat: ', M d',
30
+ timeFormat: $time_format,
31
+ use24Hour: ($time_format.toLowerCase().indexOf('a') == -1),
32
+ newEventText: BooklyL10n.new_appointment,
33
+ allowEventDelete: true,
34
+ draggable: function(calEvent, element) {
35
+ return false;
36
+ },
37
+ resizable: function(calEvent, element) {
38
+ return false;
39
+ },
40
+ eventDelete: function(calEvent, element, dayFreeBusyManager, calendar, clickEvent) {
41
+ if (confirm(BooklyL10n.are_you_sure)) {
42
+ $.post(ajaxurl, {'action' : 'ab_delete_appointment', 'appointment_id' : calEvent.id }, function () {
43
+ calendar.weekCalendar('removeEvent', calEvent.id);
44
+ });
45
+ }
46
+ },
47
+ eventRender : function(calEvent, $event) {
48
+ $event.css('backgroundColor', calEvent.color);
49
+ $event.find('.wc-time').css({
50
+ backgroundColor : calEvent.color,
51
+ borderLeftColor : calEvent.color,
52
+ borderRightColor : calEvent.color,
53
+ borderTopColor : calEvent.color,
54
+ borderBottomColor : '#ABABAB'
55
+ });
56
+ },
57
+ eventAfterRender : function(calEvent, $calEventList) {
58
+ $calEventList.each(function () {
59
+ var $calEvent = $(this);
60
+ var titleHeight = $calEvent.find('.wc-title').height();
61
+ var origHeight = $calEvent.height();
62
+
63
+ if ( origHeight < titleHeight ) {
64
+ var $info = $('<div class="wc-information"/>');
65
+ var $delete = $('.wc-cal-event-delete', $calEvent);
66
+
67
+ $delete.hide();
68
+ $('.wc-time', $calEvent).prepend($info);
69
+
70
+ // mouse handlers
71
+ $info.on('mouseenter', function () {
72
+ $calEvent.css({height: (titleHeight + 30), 'z-index': 1});
73
+ $info.hide();
74
+ $delete.show();
75
+ });
76
+ $calEvent.on('mouseleave', function () {
77
+ $calEvent.css({height: origHeight, 'z-index': 'auto'});
78
+ $delete.hide();
79
+ $info.show();
80
+ });
81
+ }
82
+ });
83
+ },
84
+ eventBody : function(calEvent, calendar) {
85
+ var body = '<div class="wc-service-name">' + calEvent.title + '</div>';
86
+ if (calEvent.desc) {
87
+ body += calEvent.desc;
88
+ }
89
+ return body;
90
+ }
91
+ },
92
+ $week_calendar_options = {
93
+ daysToShow: 7,
94
+ eventNew: function(calEvent, element, dayFreeBusyManager, calendar, mouseupEvent) {
95
+ element.hide().remove();
96
+ showAppointmentDialog(
97
+ null,
98
+ $week_calendar_wrapper.find('.ab-calendar-tab.active').data('staff-id'),
99
+ calEvent.start,
100
+ null,
101
+ calendar,
102
+ 'week',
103
+ calEvent.notes
104
+ );
105
+ },
106
+ eventClick: function(calEvent, element, dayFreeBusyManager, calendar, clickEvent) {
107
+ showAppointmentDialog(
108
+ calEvent.id,
109
+ $week_calendar_wrapper.find('.ab-calendar-tab.active').data('staff-id'),
110
+ calEvent.start,
111
+ calEvent.end,
112
+ calendar,
113
+ 'week',
114
+ calEvent.notes
115
+ );
116
+ },
117
+ data: (function() {
118
+ var xhr;
119
+
120
+ return function(start, end, callback) {
121
+ if (xhr && xhr.readyState != 4) {
122
+ xhr.abort();
123
+ }
124
+ $.post(
125
+ ajaxurl,
126
+ {
127
+ action : 'ab_week_staff_appointments',
128
+ start_date : getFormattedDateForCalendar(start),
129
+ end_date : getFormattedDateForCalendar(end),
130
+ staff_id : $week_calendar_wrapper.find('.ab-calendar-tab.active').data('staff-id')
131
+ },
132
+ function (response) {
133
+ var appointments = $.map(response.events, function(value) {
134
+ return {
135
+ id : parseInt(value.id, 10),
136
+ start : new Date(value.start),
137
+ end : new Date(value.end),
138
+ title : value.title,
139
+ desc : value.desc,
140
+ color : value.color,
141
+ notes : value.notes ? value.notes : false
142
+ };
143
+ });
144
+ var free_busys = $.map(response.freebusys, function(value) {
145
+ return {
146
+ start : new Date(value.start),
147
+ end : new Date(value.end),
148
+ free : value.free,
149
+ notes : value.notes ? value.notes : false
150
+ };
151
+ });
152
+
153
+ callback({ events: appointments, freebusys: free_busys });
154
+ },
155
+ 'json'
156
+ );
157
+ };
158
+ })(),
159
+ height: function() {
160
+ var $window_height = $(window).height(),
161
+ $wp_admin_bar_height = $('#wpadminbar').height(),
162
+ $ab_calendar_header_height = $('#ab_calendar_header').height(),
163
+ $ab_calendar_tabs_height = $('#week_calendar_wrapper .tabbable').outerHeight(true),
164
+ $height_to_reduce = $wp_admin_bar_height + $ab_calendar_header_height + $ab_calendar_tabs_height,
165
+ $wrap = $('#wpbody-content .wrap');
166
+
167
+ if ($wrap.css('margin-top')) {
168
+ $height_to_reduce += parseInt($wrap.css('margin-top').replace('px', ''), 10);
169
+ }
170
+
171
+ if ($wrap.css('margin-bottom')) {
172
+ $height_to_reduce += parseInt($wrap.css('margin-bottom').replace('px', ''), 10);
173
+ }
174
+
175
+ return $window_height - $height_to_reduce;
176
+ }
177
+ },
178
+ $day_calendar_options = {
179
+ data: (function() {
180
+ var xhr;
181
+
182
+ return function(start, end, callback) {
183
+ var selected_staff_ids = [];
184
+ $('.ab-staff-option:checked').each(function() {
185
+ selected_staff_ids.push(this.value);
186
+ });
187
+ var data = {
188
+ action : 'ab_day_staff_appointments',
189
+ start_date : getFormattedDateForCalendar(start),
190
+ staff_id : selected_staff_ids
191
+ };
192
+ if (xhr && xhr.readyState != 4) {
193
+ xhr.abort();
194
+ }
195
+ xhr = $.post(
196
+ ajaxurl, data, function (response) {
197
+ var appointments = $.map(response.events, function(value) {
198
+ return {
199
+ id : parseInt(value.id, 10),
200
+ start : new Date(value.start),
201
+ end : new Date(value.end),
202
+ title : value.title,
203
+ color : value.color,
204
+ desc : value.desc,
205
+ userId : parseInt(value.userId, 10),
206
+ notes : value.notes ? value.notes : false
207
+ };
208
+ });
209
+ var free_busys = $.map(response.freebusys, function(value) {
210
+ return {
211
+ start : new Date(value.start),
212
+ end : new Date(value.end),
213
+ free : value.free,
214
+ userId : parseInt(value.userId, 10),
215
+ notes : value.notes ? value.notes : false
216
+ };
217
+ });
218
+
219
+ callback({ events: appointments, freebusys: free_busys });
220
+ },
221
+ 'json'
222
+ );
223
+ };
224
+ })(),
225
+ users: [],
226
+ getUserId: function(user, index, calendar) {
227
+ return user.staff_id;
228
+ },
229
+ getUserName: function(user, index, calendar) {
230
+ return user.full_name;
231
+ },
232
+ daysToShow: 1,
233
+ height: function() {
234
+ var $window_height = $(window).height(),
235
+ $wp_admin_bar_height = $('#wpadminbar').height(),
236
+ $ab_calendar_header_height = $('#ab_calendar_header').height(),
237
+ $height_to_reduce = $wp_admin_bar_height + $ab_calendar_header_height + $('#day_calendar_wrapper').outerHeight(true),
238
+ $wrap = $('#wpbody-content .wrap');
239
+
240
+ if ($wrap.css('margin-top')) {
241
+ $height_to_reduce += parseInt($wrap.css('margin-top').replace('px', ''), 10);
242
+ }
243
+
244
+ if ($wrap.css('margin-bottom')) {
245
+ $height_to_reduce += parseInt($wrap.css('margin-bottom').replace('px', ''), 10);
246
+ }
247
+
248
+ return $window_height - $height_to_reduce;
249
+ },
250
+ eventNew: function(calEvent, element, dayFreeBusyManager, calendar, mouseupEvent) {
251
+ element.hide().remove();
252
+ showAppointmentDialog(
253
+ null,
254
+ calEvent.userId,
255
+ calEvent.start,
256
+ null,
257
+ calendar,
258
+ 'day',
259
+ calEvent.notes
260
+ );
261
+ },
262
+ eventClick: function(calEvent, element, dayFreeBusyManager, calendar, clickEvent) {
263
+ showAppointmentDialog(
264
+ calEvent.id,
265
+ calEvent.userId,
266
+ calEvent.start,
267
+ calEvent.end,
268
+ calendar,
269
+ 'day',
270
+ calEvent.notes
271
+ );
272
+ }
273
+ };
274
+
275
+ // Datepickers.
276
+ var week_picker = new WeekPicker();
277
+ var day_picker = new DayPicker();
278
+ week_picker.attachCalendar($week_calendar);
279
+
280
+ // week calendar
281
+ $week_calendar.weekCalendar($.extend({}, $calendar_common_options, $week_calendar_options));
282
+
283
+ // click on tabs
284
+ $tabs.find('.ab-calendar-tab').on('click', function(e) {
285
+ e.stopPropagation();
286
+ $('.ab-calendar-tab').removeClass('active');
287
+ $(this).addClass('active');
288
+ // prevents console error of initialization
289
+ $week_calendar.weekCalendar(); $week_calendar.weekCalendar('refresh');
290
+ });
291
+
292
+ // today
293
+ $('.ab-nav-calendar .ab-calendar-today').on('click', function(){
294
+ var $active_view_button = $('.ab-nav-calendar .ab-calendar-switch-view.ab-button-active');
295
+ if ($active_view_button.hasClass('ab-calendar-day')) {
296
+ day_picker.setDate(new Date());
297
+ } else {
298
+ week_picker.setDate(new Date());
299
+ }
300
+ });
301
+
302
+ // day/week view
303
+ $('.ab-nav-calendar .ab-calendar-switch-view').on('click', function() {
304
+ var $this = $(this);
305
+
306
+ if ($this.hasClass('ab-button-active')) {
307
+ return false;
308
+ }
309
+ $('.ab-nav-calendar .ab-calendar-switch-view').not($this).removeClass('ab-button-active');
310
+ $('.ab-nav-calendar .ab-calendar-today').removeClass('ab-button-active');
311
+ $this.addClass('ab-button-active');
312
+
313
+ // Switch to day-view
314
+ if ($this.hasClass('ab-calendar-day')) {
315
+ $week_calendar_wrapper.hide();
316
+ $week_calendar.remove();
317
+ week_picker.hide();
318
+
319
+ var $day_calendar_container = $day_calendar_wrapper.find('.ab-calendar-element-container'),
320
+ date_from_week_picker = week_picker.getStartDate(),
321
+
322
+ /**
323
+ * Checks if current date belongs to selected week of week-picker
324
+ *
325
+ * @return bool
326
+ */
327
+ is_current_week = function() {
328
+ var now_date = new Date(),
329
+ first_day_of_week = startAndEndOfWeek(date_from_week_picker).first_day_of_week,
330
+ last_day_of_week = startAndEndOfWeek(date_from_week_picker).last_day_of_week;
331
+
332
+ return first_day_of_week <= now_date && now_date <= last_day_of_week;
333
+ },
334
+
335
+ /**
336
+ * result is an object of dates for start (monday)
337
+ * and end (sunday) of week based on supplied date object
338
+ *
339
+ * @return object
340
+ */
341
+ startAndEndOfWeek = function(date) {
342
+ var result = {
343
+ first_day_of_week : null,
344
+ last_day_of_week : null
345
+ };
346
+
347
+ // If no date object supplied, use current date
348
+ // Copy date so don't modify supplied date
349
+ var now = date ? new Date(date) : new Date();
350
+
351
+ // set time to some convenient value
352
+ now.setHours(0, 0, 0, 0);
353
+
354
+ // Get the previous Monday
355
+ var monday = new Date(now);
356
+ monday.setDate(monday.getDate() - monday.getDay() + 1);
357
+
358
+ // Get next Sunday
359
+ var sunday = new Date(now);
360
+ sunday.setDate(sunday.getDate() - sunday.getDay() + 7);
361
+
362
+ // set result's days
363
+ result.first_day_of_week = monday;
364
+ result.last_day_of_week = sunday;
365
+
366
+ return result;
367
+ };
368
+
369
+ // Set visible users.
370
+ var users = [];
371
+ $('.ab-staff-option:checked').each(function() {
372
+ users.push({staff_id: parseInt(this.value), full_name: $(this).next().text()});
373
+ });
374
+ $day_calendar = $('<div class="ab-calendar-element" />').appendTo($day_calendar_container);
375
+ $day_calendar.weekCalendar($.extend({date: date_from_week_picker}, $calendar_common_options, $day_calendar_options, {users: users}));
376
+ $day_calendar_wrapper.show();
377
+
378
+ day_picker.attachCalendar($day_calendar);
379
+
380
+ // if week is current - set current date, otherwise set date from week-picker
381
+ is_current_week() ?
382
+ day_picker.setDate(new Date(), true) :
383
+ day_picker.setDate(date_from_week_picker, true);
384
+
385
+ day_picker.show();
386
+
387
+ // styles-fixing
388
+ $('td.wc-scrollbar-shim').hide();
389
+ // Switch to week view
390
+ } else {
391
+ $day_calendar_wrapper.hide();
392
+ $day_calendar.remove();
393
+ day_picker.hide();
394
+
395
+ var $week_calendar_container = $week_calendar_wrapper.find('.ab-calendar-element-container'),
396
+ date_from_day_picker = day_picker.getDate();
397
+
398
+ // Show tabs based on selected staff members.
399
+ var active_set = false;
400
+ $staff_option.each(function() {
401
+ if (this.checked) {
402
+ $('.ab-staff-tab-' + this.value).show().toggleClass('active', active_set === false);
403
+ active_set = true;
404
+ } else {
405
+ $('.ab-staff-tab-' + this.value).hide().removeClass('active');
406
+ }
407
+ });
408
+
409
+ $week_calendar = $('<div class="ab-calendar-element" />').appendTo($week_calendar_container);
410
+ if (active_set) {
411
+ $week_calendar_wrapper.show();
412
+ }
413
+ $week_calendar.weekCalendar($.extend({date: date_from_day_picker}, $calendar_common_options, $week_calendar_options));
414
+ scrollShim = document.querySelector('.wc-scrollbar-shim');
415
+ if ( scrollShim !== null ) scrollShim.style.width = scrollWidth + 'px';
416
+
417
+ // Set date from day calendar
418
+ week_picker.setDate(date_from_day_picker, false);
419
+ week_picker.attachCalendar($week_calendar);
420
+ week_picker.show();
421
+ } // end of Week View
422
+ });
423
+
424
+ // Staff filter
425
+ $('.ab-staff-filter-button').on('click', function (e) {
426
+ e.stopPropagation();
427
+ var menu = $(this).parent().find('.dropdown-menu');
428
+ if (menu.hasClass('open')) {
429
+ menu.removeClass('open').hide();
430
+ } else {
431
+ menu.addClass('open').show();
432
+ }
433
+ });
434
+
435
+ $('.dropdown-menu').on('click', function (e) {
436
+ e.stopPropagation();
437
+ });
438
+
439
+ $all_staff_option.on('change', function () {
440
+ $staff_option.prop('checked', this.checked);
441
+ if (this.checked) {
442
+ $staff_option.filter(':first').trigger('change');
443
+ $staff_tabs.show();
444
+ } else {
445
+ $week_calendar_wrapper.hide();
446
+ $day_calendar_wrapper.hide();
447
+ }
448
+ });
449
+
450
+ $staff_option.on('change', function (e) {
451
+ var self = $(this),
452
+ $tab = $('.ab-staff-tab-' + self.val()),
453
+ $active_tab = $('ul.nav-tabs').find('li.active'),
454
+ is_day = $('button.ab-calendar-day').hasClass('ab-button-active'),
455
+ staff_option_checked = parseInt($staff_option.filter(':checked').length),
456
+ unchecked_options = [];
457
+
458
+ $all_staff_option.prop('checked', $staff_option.filter(':not(:checked)').length == 0);
459
+
460
+ if (is_day) { // Day
461
+ // checkboxes
462
+ if (staff_option_checked) {
463
+ $day_calendar_wrapper.show();
464
+ // Refresh visible users in calendar.
465
+ var users = [];
466
+ $('.ab-staff-option:checked').each(function() {
467
+ users.push({staff_id: parseInt(this.value), full_name: $(this).next().text()});
468
+ });
469
+ $day_calendar.weekCalendar('option', 'users', users);
470
+ $day_calendar.weekCalendar('refresh');
471
+ // css-fix
472
+ $('td.wc-scrollbar-shim').hide();
473
+ } else { // No staff selected
474
+ $day_calendar_wrapper.hide();
475
+ }
476
+ } else { // Week
477
+ if (this.checked) {
478
+ $tab.show().click();
479
+ $staff_option.each(function(k, v) {
480
+ if ($(v).is(':not(:checked)') && !unchecked_options[$(v).val()]) {
481
+ unchecked_options.push($(v).val());
482
+ }
483
+ });
484
+ $active_tab.parent().find('li').each(function(k, v) {
485
+ unchecked_options.forEach(function(option) {
486
+ if ($(v).data('staff-id') == option) {
487
+ $('ul.nav-tabs').find('li').filter('[data-staff-id="' + option + '"]').hide();
488
+ }
489
+ });
490
+ });
491
+ } else {
492
+ $tab.hide();
493
+ $active_tab.is(':visible') ? $active_tab.click() : $staff_tabs.filter(':visible').filter(':first').click();
494
+ }
495
+ staff_option_checked ? $week_calendar_wrapper.show() : $week_calendar_wrapper.hide();
496
+ }
497
+
498
+ // Changes staff filter button name
499
+ var selected_staff_numb = $staff_option.filter(':checked').length;
500
+ if (selected_staff_numb == 0) {
501
+ $staff_filter_button.text('No staff selected');
502
+ } else if (selected_staff_numb == 1) {
503
+ $staff_filter_button.text($("label[for='" + $staff_option.filter(':checked').attr('id') + "']").text());
504
+ } else {
505
+ $staff_filter_button.text(selected_staff_numb + ' staff members');
506
+ }
507
+ });
508
+
509
+ // End staff filter
510
+
511
+ /**
512
+ * Get formatted date(php: Y-m-d H:i:s) for calendar
513
+ *
514
+ * @param date
515
+ * @return {String}
516
+ */
517
+ function getFormattedDateForCalendar(date) {
518
+ var $hours = date.getHours(), $minutes = date.getMinutes();
519
+
520
+ if ($hours < 10) {
521
+ $hours = '0' + $hours;
522
+ }
523
+
524
+ if ($minutes < 10) {
525
+ $minutes = '0' + $minutes;
526
+ }
527
+
528
+ return $.datepicker.formatDate( 'yy-mm-dd ', date ) + $hours + ':' + $minutes + ':00';
529
+ }
530
+
531
+
532
+ /*
533
+ * scroll width
534
+ *
535
+ * not null for preventing console errors when no one staff exists
536
+ */
537
+ var scroll = document.querySelector('.wc-scrollable-grid'),
538
+ scrollShim = document.querySelector('.wc-scrollbar-shim'),
539
+ scrollWidth = scroll !== null ? scroll.offsetWidth - scroll.clientWidth : 0;
540
+
541
+ if ( scrollShim !== null ) scrollShim.style.width = scrollWidth + 'px';
542
+
543
+ /* firefox bug border */
544
+ if ( $.browser.mozilla )
545
+ $('.wc-time-column-header:first-child').css('width','43px');
546
+
547
+ $('#email_notification').on('click', function() {
548
+ $('#email_notification_text').show();
549
+ });
550
+ });
backend/modules/calendar/resources/js/calendar_daypicker.js ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Day calendar datepicker.
3
+ */
4
+ function DayPicker() {
5
+ // Private functions and variables.
6
+ var widget = {
7
+ $container : null,
8
+ $month_days : null,
9
+ $prev_date_handler : null,
10
+ $next_date_handler : null,
11
+ $picker : null, // jQuery UI DatePicker.
12
+ $calendar : null, // WeekCalendar instance.
13
+ first_day : null,
14
+ rebuildDayLine : function(date) {
15
+ var timestamp = +date / 1000,
16
+ seconds_in_day = 60 * 60 * 24;
17
+ for (var i = 1; i <= 7; ++ i) {
18
+ var next_day_timestamp = (timestamp + (i * seconds_in_day)) * 1000,
19
+ next_day = new Date(next_day_timestamp),
20
+ $day_of_month = jQuery(this.$month_days.get(i - 1));
21
+ $day_of_month
22
+ .text(next_day.getDate())
23
+ .data('date_timestamp', next_day_timestamp / 1000);
24
+ }
25
+ },
26
+ /**
27
+ * Constructor.
28
+ */
29
+ init : function() {
30
+ this.$container = jQuery('div#day-calendar-picker');
31
+ this.$month_days = this.$container.find('.ab-day-of-month');
32
+ this.$prev_date_handler = this.$container.find('.ab-week-picker-arrow-prev');
33
+ this.$next_date_handler = this.$container.find('.ab-week-picker-arrow-next');
34
+ this.$picker = this.$container.find('#appendedInput');
35
+ this.first_day = this.$container.data('first_day');
36
+ // Init datepicker.
37
+ this.$picker.datepicker({
38
+ dateFormat : BooklyL10n['dateFormat'],
39
+ showOtherMonths : true,
40
+ selectOtherMonths : true,
41
+ firstDay : widget.first_day,
42
+ monthNames : BooklyL10n['longMonths'],
43
+ monthNamesShort : BooklyL10n['shortMonths'],
44
+ dayNames : BooklyL10n['longDays'],
45
+ dayNamesMin : BooklyL10n['shortDays'],
46
+ dayNamesShort : BooklyL10n['shortDays'],
47
+ onSelect : function() {
48
+ var date = widget.$picker.datepicker('getDate');
49
+ widget.rebuildDayLine(date);
50
+ if (widget.$calendar) {
51
+ widget.$calendar.weekCalendar('gotoWeek', date);
52
+ }
53
+ widget.$month_days.parent().removeClass('active');
54
+ }
55
+ });
56
+ // Handle events.
57
+ this.$month_days.on('click', function(e) {
58
+ e.preventDefault();
59
+ var $clicked = jQuery(this),
60
+ $clicked_day_date = new Date(parseInt($clicked.data('date_timestamp'), 10) * 1000);
61
+ widget.rebuildDayLine($clicked_day_date);
62
+ widget.$picker.datepicker('setDate', $clicked_day_date);
63
+ widget.$month_days.parent().removeClass('active');
64
+ $clicked.parent().addClass('active');
65
+ if (widget.$calendar) {
66
+ widget.$calendar.weekCalendar('gotoWeek', $clicked_day_date);
67
+ }
68
+ });
69
+ this.$prev_date_handler.on('click', function() {
70
+ var date = widget.$picker.datepicker('getDate');
71
+ date.setDate(date.getDate() - 1);
72
+ widget.rebuildDayLine(date);
73
+ widget.$picker.datepicker('setDate', date);
74
+ if (widget.$calendar) {
75
+ widget.$calendar.weekCalendar('gotoWeek', date);
76
+ }
77
+ });
78
+ this.$next_date_handler.on('click', function() {
79
+ var date = widget.$picker.datepicker('getDate');
80
+ date.setDate(date.getDate() + 1);
81
+ widget.rebuildDayLine(date);
82
+ widget.$picker.datepicker('setDate', date);
83
+ if (widget.$calendar) {
84
+ widget.$calendar.weekCalendar('gotoWeek', date);
85
+ }
86
+ });
87
+ }
88
+ };
89
+
90
+ // Init.
91
+ widget.init();
92
+
93
+ // Return public methods.
94
+ return {
95
+ show : function() {
96
+ widget.$container.show();
97
+ },
98
+ hide : function() {
99
+ widget.$container.hide();
100
+ },
101
+
102
+ /**
103
+ * Set specific date to the widget (and update $calendar if update_week_calendar is true).
104
+ *
105
+ * @param date
106
+ * @param update_week_calendar
107
+ */
108
+ setDate : function(date, update_week_calendar) {
109
+ widget.rebuildDayLine(date);
110
+ widget.$picker.datepicker('setDate', date);
111
+ if (widget.$calendar && (update_week_calendar === undefined || update_week_calendar)) {
112
+ widget.$calendar.weekCalendar('gotoWeek', date);
113
+ }
114
+ },
115
+ getDate : function() {
116
+ return widget.$picker.datepicker('getDate');
117
+ },
118
+ /**
119
+ * Attach WeekCalendar to the picker.
120
+ * @param WeekCalendar $calendar
121
+ */
122
+ attachCalendar : function($calendar) {
123
+ widget.$calendar = $calendar;
124
+ }
125
+ };
126
+ }
backend/modules/calendar/resources/js/calendar_weekpicker.js ADDED
@@ -0,0 +1,168 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Week calendar datepicker.
3
+ */
4
+ function WeekPicker() {
5
+ // Private functions and variables.
6
+ var widget = {
7
+ $container : null,
8
+ $picker : null, // jQuery UI DatePicker.
9
+ $output : null, // Place to display week-start and week-end dates.
10
+ $calendar : null, // WeekCalendar instance.
11
+ start_date : null,
12
+ end_date : null,
13
+ first_day : null,
14
+ date_format : null,
15
+ /**
16
+ * Set start and end dates based on Date object.
17
+ * @param Date date.
18
+ */
19
+ updateStartAndEndDates : function(date) {
20
+ var seconds_in_one_day = 86400000;
21
+ var days_to_rewind = date.getDay() <= 0 ? 7 - this.first_day : date.getDay() - this.first_day;
22
+ var days_to_add = 6;
23
+ this.start_date = new Date(date.valueOf() - days_to_rewind * seconds_in_one_day); //rewind to start day
24
+ this.end_date = new Date(this.start_date.valueOf() + days_to_add * seconds_in_one_day); //add 6 days to get last day
25
+ },
26
+ /**
27
+ * Highlight all days in currently selected week.
28
+ */
29
+ highlightSelectedWeek : function() {
30
+ window.setTimeout(function () {
31
+ widget.$picker.find('.ui-datepicker-current-day a').addClass('ui-state-active')
32
+ }, 1);
33
+ },
34
+ /**
35
+ * Display start and end dates of the selected week.
36
+ * @param Date start_date
37
+ * @param Date end_date
38
+ */
39
+ outputFormattedDate : function() {
40
+ // show formatted date values
41
+ var formatted_start_date = jQuery.datepicker.formatDate(this.date_format, this.start_date, {monthNamesShort: BooklyL10n['shortMonths'], monthNames : BooklyL10n['longMonths']}),
42
+ formatted_end_date = jQuery.datepicker.formatDate(this.date_format, this.end_date, {monthNamesShort: BooklyL10n['shortMonths'], monthNames : BooklyL10n['longMonths']});
43
+ this.$output.val(BooklyL10n['Week'] + formatted_start_date + ' - ' + formatted_end_date);
44
+ },
45
+ /**
46
+ * Set specific date to the widget (and update $calendar if update_week_calendar is true).
47
+ *
48
+ * @param date
49
+ * @param update_week_calendar
50
+ */
51
+ setDate : function(date, update_week_calendar) {
52
+ this.updateStartAndEndDates(date);
53
+ this.$picker.datepicker('setDate', date);
54
+ this.outputFormattedDate();
55
+ this.highlightSelectedWeek();
56
+ if (this.$calendar && (update_week_calendar === undefined || update_week_calendar)) {
57
+ this.$calendar.weekCalendar('gotoWeek', this.start_date);
58
+ }
59
+ },
60
+ /**
61
+ * Constructor.
62
+ */
63
+ init : function() {
64
+ this.$container = jQuery('div#week-calendar-picker');
65
+ this.$picker = this.$container.find('div.ab-week-picker');
66
+ this.$output = this.$container.find('input.ab-date-calendar');
67
+ this.first_day = this.$container.data('first_day');
68
+ this.date_format = BooklyL10n['dateFormat'];
69
+ // Init start and end dates.
70
+ this.updateStartAndEndDates(new Date());
71
+ // Init datepicker.
72
+ this.$picker.datepicker({
73
+ showOtherMonths : true,
74
+ selectOtherMonths : true,
75
+ firstDay : widget.first_day,
76
+ monthNames : BooklyL10n['longMonths'],
77
+ monthNamesShort : BooklyL10n['shortMonths'],
78
+ dayNames : BooklyL10n['longDays'],
79
+ dayNamesMin : BooklyL10n['shortDays'],
80
+ dayNamesShort : BooklyL10n['shortDays'],
81
+ onSelect : function(dateText, inst) {
82
+ widget.updateStartAndEndDates(widget.$picker.datepicker('getDate'));
83
+ widget.outputFormattedDate();
84
+ widget.highlightSelectedWeek();
85
+ if (widget.$calendar) {
86
+ widget.$calendar.weekCalendar('gotoWeek', widget.start_date);
87
+ }
88
+ },
89
+ beforeShowDay : function(date) {
90
+ var cssClass = '';
91
+ if ((date >= widget.start_date || date.getDate() == widget.start_date.getDate()) && date <= widget.end_date) {
92
+ cssClass = 'ui-datepicker-current-day';
93
+ }
94
+ return [true, cssClass];
95
+ },
96
+ onChangeMonthYear : function(year, month, inst) {
97
+ widget.highlightSelectedWeek();
98
+ }
99
+ });
100
+ this.highlightSelectedWeek();
101
+ // Display start and end dates.
102
+ this.outputFormattedDate();
103
+ // Handle events.
104
+ this.$container
105
+ .on('mousemove', '.ui-datepicker-calendar tr', function() {
106
+ jQuery(this).find('td a').addClass('ui-state-hover');
107
+ })
108
+ .on('mouseleave', '.ui-datepicker-calendar tr', function() {
109
+ jQuery(this).find('td a').removeClass('ui-state-hover');
110
+ });
111
+ jQuery('body').click(function(e) {
112
+ jQuery('.dropdown-menu:visible').removeClass('open').hide();
113
+ if (widget.$picker.is(':visible')) {
114
+ widget.$picker.hide();
115
+ }
116
+ });
117
+ this.$picker.click(function(e) {
118
+ e.stopPropagation();
119
+ });
120
+ // open week picker
121
+ this.$output.on('click', function(e) {
122
+ widget.$picker.show();
123
+ e.stopPropagation();
124
+ });
125
+ // do not close week picker when the previous or next arrow is clicked
126
+ this.$container.find('.prev, .next').on('click', function(e) {
127
+ e.stopPropagation();
128
+ });
129
+ // handle click on the "previous week" arrow
130
+ this.$container.find('.prev').on('click', function() {
131
+ var date = widget.$picker.datepicker('getDate');
132
+ date.addDays(-7);
133
+ widget.setDate(date);
134
+ });
135
+ // handle click on the "next week" arrow
136
+ this.$container.find('.next').on('click', function() {
137
+ var date = widget.$picker.datepicker('getDate');
138
+ date.addDays(7);
139
+ widget.setDate(date);
140
+ });
141
+ }
142
+ };
143
+
144
+ // Init.
145
+ widget.init();
146
+ // Return public methods.
147
+ return {
148
+ show : function() {
149
+ widget.$container.show();
150
+ },
151
+ hide : function() {
152
+ widget.$container.hide();
153
+ },
154
+ setDate : function(date, update_week_calendar) {
155
+ widget.setDate(date, update_week_calendar);
156
+ },
157
+ getStartDate : function() {
158
+ return widget.start_date;
159
+ },
160
+ /**
161
+ * Attach WeekCalendar to the picker.
162
+ * @param WeekCalendar $calendar
163
+ */
164
+ attachCalendar : function($calendar) {
165
+ widget.$calendar = $calendar;
166
+ }
167
+ };
168
+ }
backend/modules/calendar/resources/js/chosen.jquery.js ADDED
@@ -0,0 +1,1229 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ Chosen, a Select Box Enhancer for jQuery and Prototype
3
+ by Patrick Filler for Harvest, http://getharvest.com
4
+
5
+ Version 1.2.0
6
+ Full source at https://github.com/harvesthq/chosen
7
+ Copyright (c) 2011-2014 Harvest http://getharvest.com
8
+
9
+ MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md
10
+ This file is generated by `grunt build`, do not edit it by hand.
11
+ */
12
+
13
+ (function() {
14
+ var $, AbstractChosen, Chosen, SelectParser, _ref,
15
+ __hasProp = {}.hasOwnProperty,
16
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
17
+
18
+ SelectParser = (function() {
19
+ function SelectParser() {
20
+ this.options_index = 0;
21
+ this.parsed = [];
22
+ }
23
+
24
+ SelectParser.prototype.add_node = function(child) {
25
+ if (child.nodeName.toUpperCase() === "OPTGROUP") {
26
+ return this.add_group(child);
27
+ } else {
28
+ return this.add_option(child);
29
+ }
30
+ };
31
+
32
+ SelectParser.prototype.add_group = function(group) {
33
+ var group_position, option, _i, _len, _ref, _results;
34
+ group_position = this.parsed.length;
35
+ this.parsed.push({
36
+ array_index: group_position,
37
+ group: true,
38
+ label: this.escapeExpression(group.label),
39
+ children: 0,
40
+ disabled: group.disabled
41
+ });
42
+ _ref = group.childNodes;
43
+ _results = [];
44
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
45
+ option = _ref[_i];
46
+ _results.push(this.add_option(option, group_position, group.disabled));
47
+ }
48
+ return _results;
49
+ };
50
+
51
+ SelectParser.prototype.add_option = function(option, group_position, group_disabled) {
52
+ if (option.nodeName.toUpperCase() === "OPTION") {
53
+ if (option.text !== "") {
54
+ if (group_position != null) {
55
+ this.parsed[group_position].children += 1;
56
+ }
57
+ this.parsed.push({
58
+ array_index: this.parsed.length,
59
+ options_index: this.options_index,
60
+ value: option.value,
61
+ text: option.text,
62
+ html: option.innerHTML,
63
+ selected: option.selected,
64
+ disabled: group_disabled === true ? group_disabled : option.disabled,
65
+ group_array_index: group_position,
66
+ classes: option.className,
67
+ style: option.style.cssText
68
+ });
69
+ } else {
70
+ this.parsed.push({
71
+ array_index: this.parsed.length,
72
+ options_index: this.options_index,
73
+ empty: true
74
+ });
75
+ }
76
+ return this.options_index += 1;
77
+ }
78
+ };
79
+
80
+ SelectParser.prototype.escapeExpression = function(text) {
81
+ var map, unsafe_chars;
82
+ if ((text == null) || text === false) {
83
+ return "";
84
+ }
85
+ if (!/[\&\<\>\"\'\`]/.test(text)) {
86
+ return text;
87
+ }
88
+ map = {
89
+ "<": "&lt;",
90
+ ">": "&gt;",
91
+ '"': "&quot;",
92
+ "'": "&#x27;",
93
+ "`": "&#x60;"
94
+ };
95
+ unsafe_chars = /&(?!\w+;)|[\<\>\"\'\`]/g;
96
+ return text.replace(unsafe_chars, function(chr) {
97
+ return map[chr] || "&amp;";
98
+ });
99
+ };
100
+
101
+ return SelectParser;
102
+
103
+ })();
104
+
105
+ SelectParser.select_to_array = function(select) {
106
+ var child, parser, _i, _len, _ref;
107
+ parser = new SelectParser();
108
+ _ref = select.childNodes;
109
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
110
+ child = _ref[_i];
111
+ parser.add_node(child);
112
+ }
113
+ return parser.parsed;
114
+ };
115
+
116
+ AbstractChosen = (function() {
117
+ function AbstractChosen(form_field, options) {
118
+ this.form_field = form_field;
119
+ this.options = options != null ? options : {};
120
+ if (!AbstractChosen.browser_is_supported()) {
121
+ return;
122
+ }
123
+ this.is_multiple = this.form_field.multiple;
124
+ this.set_default_text();
125
+ this.set_default_values();
126
+ this.setup();
127
+ this.set_up_html();
128
+ this.register_observers();
129
+ }
130
+
131
+ AbstractChosen.prototype.set_default_values = function() {
132
+ var _this = this;
133
+ this.click_test_action = function(evt) {
134
+ return _this.test_active_click(evt);
135
+ };
136
+ this.activate_action = function(evt) {
137
+ return _this.activate_field(evt);
138
+ };
139
+ this.active_field = false;
140
+ this.mouse_on_container = false;
141
+ this.results_showing = false;
142
+ this.result_highlighted = null;
143
+ this.allow_single_deselect = (this.options.allow_single_deselect != null) && (this.form_field.options[0] != null) && this.form_field.options[0].text === "" ? this.options.allow_single_deselect : false;
144
+ this.disable_search_threshold = this.options.disable_search_threshold || 0;
145
+ this.disable_search = this.options.disable_search || false;
146
+ this.enable_split_word_search = this.options.enable_split_word_search != null ? this.options.enable_split_word_search : true;
147
+ this.group_search = this.options.group_search != null ? this.options.group_search : true;
148
+ this.search_contains = this.options.search_contains || false;
149
+ this.single_backstroke_delete = this.options.single_backstroke_delete != null ? this.options.single_backstroke_delete : true;
150
+ this.max_selected_options = this.options.max_selected_options || Infinity;
151
+ this.inherit_select_classes = this.options.inherit_select_classes || false;
152
+ this.display_selected_options = this.options.display_selected_options != null ? this.options.display_selected_options : true;
153
+ return this.display_disabled_options = this.options.display_disabled_options != null ? this.options.display_disabled_options : true;
154
+ };
155
+
156
+ AbstractChosen.prototype.set_default_text = function() {
157
+ if (this.form_field.getAttribute("data-placeholder")) {
158
+ this.default_text = this.form_field.getAttribute("data-placeholder");
159
+ } else if (this.is_multiple) {
160
+ this.default_text = this.options.placeholder_text_multiple || this.options.placeholder_text || AbstractChosen.default_multiple_text;
161
+ } else {
162
+ this.default_text = this.options.placeholder_text_single || this.options.placeholder_text || AbstractChosen.default_single_text;
163
+ }
164
+ return this.results_none_found = this.form_field.getAttribute("data-no_results_text") || this.options.no_results_text || AbstractChosen.default_no_result_text;
165
+ };
166
+
167
+ AbstractChosen.prototype.mouse_enter = function() {
168
+ return this.mouse_on_container = true;
169
+ };
170
+
171
+ AbstractChosen.prototype.mouse_leave = function() {
172
+ return this.mouse_on_container = false;
173
+ };
174
+
175
+ AbstractChosen.prototype.input_focus = function(evt) {
176
+ var _this = this;
177
+ if (this.is_multiple) {
178
+ if (!this.active_field) {
179
+ return setTimeout((function() {
180
+ return _this.container_mousedown();
181
+ }), 50);
182
+ }
183
+ } else {
184
+ if (!this.active_field) {
185
+ return this.activate_field();
186
+ }
187
+ }
188
+ };
189
+
190
+ AbstractChosen.prototype.input_blur = function(evt) {
191
+ var _this = this;
192
+ if (!this.mouse_on_container) {
193
+ this.active_field = false;
194
+ return setTimeout((function() {
195
+ return _this.blur_test();
196
+ }), 100);
197
+ }
198
+ };
199
+
200
+ AbstractChosen.prototype.results_option_build = function(options) {
201
+ var content, data, _i, _len, _ref;
202
+ content = '';
203
+ _ref = this.results_data;
204
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
205
+ data = _ref[_i];
206
+ if (data.group) {
207
+ content += this.result_add_group(data);
208
+ } else {
209
+ content += this.result_add_option(data);
210
+ }
211
+ if (options != null ? options.first : void 0) {
212
+ if (data.selected && this.is_multiple) {
213
+ this.choice_build(data);
214
+ } else if (data.selected && !this.is_multiple) {
215
+ this.single_set_selected_text(data.text);
216
+ }
217
+ }
218
+ }
219
+ return content;
220
+ };
221
+
222
+ AbstractChosen.prototype.result_add_option = function(option) {
223
+ var classes, option_el;
224
+ if (!option.search_match) {
225
+ return '';
226
+ }
227
+ if (!this.include_option_in_results(option)) {
228
+ return '';
229
+ }
230
+ classes = [];
231
+ if (!option.disabled && !(option.selected && this.is_multiple)) {
232
+ classes.push("active-result");
233
+ }
234
+ if (option.disabled && !(option.selected && this.is_multiple)) {
235
+ classes.push("disabled-result");
236
+ }
237
+ if (option.selected) {
238
+ classes.push("result-selected");
239
+ }
240
+ if (option.group_array_index != null) {
241
+ classes.push("group-option");
242
+ }
243
+ if (option.classes !== "") {
244
+ classes.push(option.classes);
245
+ }
246
+ option_el = document.createElement("li");
247
+ option_el.className = classes.join(" ");
248
+ option_el.style.cssText = option.style;
249
+ option_el.setAttribute("data-option-array-index", option.array_index);
250
+ option_el.innerHTML = option.search_text;
251
+ return this.outerHTML(option_el);
252
+ };
253
+
254
+ AbstractChosen.prototype.result_add_group = function(group) {
255
+ var group_el;
256
+ if (!(group.search_match || group.group_match)) {
257
+ return '';
258
+ }
259
+ if (!(group.active_options > 0)) {
260
+ return '';
261
+ }
262
+ group_el = document.createElement("li");
263
+ group_el.className = "group-result";
264
+ group_el.innerHTML = group.search_text;
265
+ return this.outerHTML(group_el);
266
+ };
267
+
268
+ AbstractChosen.prototype.results_update_field = function() {
269
+ this.set_default_text();
270
+ if (!this.is_multiple) {
271
+ this.results_reset_cleanup();
272
+ }
273
+ this.result_clear_highlight();
274
+ this.results_build();
275
+ if (this.results_showing) {
276
+ return this.winnow_results();
277
+ }
278
+ };
279
+
280
+ AbstractChosen.prototype.reset_single_select_options = function() {
281
+ var result, _i, _len, _ref, _results;
282
+ _ref = this.results_data;
283
+ _results = [];
284
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
285
+ result = _ref[_i];
286
+ if (result.selected) {
287
+ _results.push(result.selected = false);
288
+ } else {
289
+ _results.push(void 0);
290
+ }
291
+ }
292
+ return _results;
293
+ };
294
+
295
+ AbstractChosen.prototype.results_toggle = function() {
296
+ if (this.results_showing) {
297
+ return this.results_hide();
298
+ } else {
299
+ return this.results_show();
300
+ }
301
+ };
302
+
303
+ AbstractChosen.prototype.results_search = function(evt) {
304
+ if (this.results_showing) {
305
+ return this.winnow_results();
306
+ } else {
307
+ return this.results_show();
308
+ }
309
+ };
310
+
311
+ AbstractChosen.prototype.winnow_results = function() {
312
+ var escapedSearchText, option, regex, results, results_group, searchText, startpos, text, zregex, _i, _len, _ref;
313
+ this.no_results_clear();
314
+ results = 0;
315
+ searchText = this.get_search_text();
316
+ escapedSearchText = searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
317
+ zregex = new RegExp(escapedSearchText, 'i');
318
+ regex = this.get_search_regex(escapedSearchText);
319
+ _ref = this.results_data;
320
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
321
+ option = _ref[_i];
322
+ option.search_match = false;
323
+ results_group = null;
324
+ if (this.include_option_in_results(option)) {
325
+ if (option.group) {
326
+ option.group_match = false;
327
+ option.active_options = 0;
328
+ }
329
+ if ((option.group_array_index != null) && this.results_data[option.group_array_index]) {
330
+ results_group = this.results_data[option.group_array_index];
331
+ if (results_group.active_options === 0 && results_group.search_match) {
332
+ results += 1;
333
+ }
334
+ results_group.active_options += 1;
335
+ }
336
+ if (!(option.group && !this.group_search)) {
337
+ option.search_text = option.group ? option.label : option.text;
338
+ option.search_match = this.search_string_match(option.search_text, regex);
339
+ if (option.search_match && !option.group) {
340
+ results += 1;
341
+ }
342
+ if (option.search_match) {
343
+ if (searchText.length) {
344
+ startpos = option.search_text.search(zregex);
345
+ text = option.search_text.substr(0, startpos + searchText.length) + '</em>' + option.search_text.substr(startpos + searchText.length);
346
+ option.search_text = text.substr(0, startpos) + '<em>' + text.substr(startpos);
347
+ }
348
+ if (results_group != null) {
349
+ results_group.group_match = true;
350
+ }
351
+ } else if ((option.group_array_index != null) && this.results_data[option.group_array_index].search_match) {
352
+ option.search_match = true;
353
+ }
354
+ }
355
+ }
356
+ }
357
+ this.result_clear_highlight();
358
+ if (results < 1 && searchText.length) {
359
+ this.update_results_content("");
360
+ return this.no_results(searchText);
361
+ } else {
362
+ this.update_results_content(this.results_option_build());
363
+ return this.winnow_results_set_highlight();
364
+ }
365
+ };
366
+
367
+ AbstractChosen.prototype.get_search_regex = function(escaped_search_string) {
368
+ var regex_anchor;
369
+ regex_anchor = this.search_contains ? "" : "^";
370
+ return new RegExp(regex_anchor + escaped_search_string, 'i');
371
+ };
372
+
373
+ AbstractChosen.prototype.search_string_match = function(search_string, regex) {
374
+ var part, parts, _i, _len;
375
+ if (regex.test(search_string)) {
376
+ return true;
377
+ } else if (this.enable_split_word_search && (search_string.indexOf(" ") >= 0 || search_string.indexOf("[") === 0)) {
378
+ parts = search_string.replace(/\[|\]/g, "").split(" ");
379
+ if (parts.length) {
380
+ for (_i = 0, _len = parts.length; _i < _len; _i++) {
381
+ part = parts[_i];
382
+ if (regex.test(part)) {
383
+ return true;
384
+ }
385
+ }
386
+ }
387
+ }
388
+ };
389
+
390
+ AbstractChosen.prototype.choices_count = function() {
391
+ var option, _i, _len, _ref;
392
+ if (this.selected_option_count != null) {
393
+ return this.selected_option_count;
394
+ }
395
+ this.selected_option_count = 0;
396
+ _ref = this.form_field.options;
397
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
398
+ option = _ref[_i];
399
+ if (option.selected) {
400
+ this.selected_option_count += 1;
401
+ }
402
+ }
403
+ return this.selected_option_count;
404
+ };
405
+
406
+ AbstractChosen.prototype.choices_click = function(evt) {
407
+ evt.preventDefault();
408
+ if (!(this.results_showing || this.is_disabled)) {
409
+ return this.results_show();
410
+ }
411
+ };
412
+
413
+ AbstractChosen.prototype.keyup_checker = function(evt) {
414
+ var stroke, _ref;
415
+ stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
416
+ this.search_field_scale();
417
+ switch (stroke) {
418
+ case 8:
419
+ if (this.is_multiple && this.backstroke_length < 1 && this.choices_count() > 0) {
420
+ return this.keydown_backstroke();
421
+ } else if (!this.pending_backstroke) {
422
+ this.result_clear_highlight();
423
+ return this.results_search();
424
+ }
425
+ break;
426
+ case 13:
427
+ evt.preventDefault();
428
+ if (this.results_showing) {
429
+ return this.result_select(evt);
430
+ }
431
+ break;
432
+ case 27:
433
+ if (this.results_showing) {
434
+ this.results_hide();
435
+ }
436
+ return true;
437
+ case 9:
438
+ case 38:
439
+ case 40:
440
+ case 16:
441
+ case 91:
442
+ case 17:
443
+ break;
444
+ default:
445
+ return this.results_search();
446
+ }
447
+ };
448
+
449
+ AbstractChosen.prototype.clipboard_event_checker = function(evt) {
450
+ var _this = this;
451
+ return setTimeout((function() {
452
+ return _this.results_search();
453
+ }), 50);
454
+ };
455
+
456
+ AbstractChosen.prototype.container_width = function() {
457
+ if (this.options.width != null) {
458
+ return this.options.width;
459
+ } else {
460
+ return "" + this.form_field.offsetWidth + "px";
461
+ }
462
+ };
463
+
464
+ AbstractChosen.prototype.include_option_in_results = function(option) {
465
+ if (this.is_multiple && (!this.display_selected_options && option.selected)) {
466
+ return false;
467
+ }
468
+ if (!this.display_disabled_options && option.disabled) {
469
+ return false;
470
+ }
471
+ if (option.empty) {
472
+ return false;
473
+ }
474
+ return true;
475
+ };
476
+
477
+ AbstractChosen.prototype.search_results_touchstart = function(evt) {
478
+ this.touch_started = true;
479
+ return this.search_results_mouseover(evt);
480
+ };
481
+
482
+ AbstractChosen.prototype.search_results_touchmove = function(evt) {
483
+ this.touch_started = false;
484
+ return this.search_results_mouseout(evt);
485
+ };
486
+
487
+ AbstractChosen.prototype.search_results_touchend = function(evt) {
488
+ if (this.touch_started) {
489
+ return this.search_results_mouseup(evt);
490
+ }
491
+ };
492
+
493
+ AbstractChosen.prototype.outerHTML = function(element) {
494
+ var tmp;
495
+ if (element.outerHTML) {
496
+ return element.outerHTML;
497
+ }
498
+ tmp = document.createElement("div");
499
+ tmp.appendChild(element);
500
+ return tmp.innerHTML;
501
+ };
502
+
503
+ AbstractChosen.browser_is_supported = function() {
504
+ if (window.navigator.appName === "Microsoft Internet Explorer") {
505
+ return document.documentMode >= 8;
506
+ }
507
+ if (/iP(od|hone)/i.test(window.navigator.userAgent)) {
508
+ return false;
509
+ }
510
+ if (/Android/i.test(window.navigator.userAgent)) {
511
+ if (/Mobile/i.test(window.navigator.userAgent)) {
512
+ return false;
513
+ }
514
+ }
515
+ return true;
516
+ };
517
+
518
+ AbstractChosen.default_multiple_text = "Select Some Options";
519
+
520
+ AbstractChosen.default_single_text = "Select an Option";
521
+
522
+ AbstractChosen.default_no_result_text = "No results match";
523
+
524
+ return AbstractChosen;
525
+
526
+ })();
527
+
528
+ $ = jQuery;
529
+
530
+ $.fn.extend({
531
+ chosen: function(options) {
532
+ if (!AbstractChosen.browser_is_supported()) {
533
+ return this;
534
+ }
535
+ return this.each(function(input_field) {
536
+ var $this, chosen;
537
+ $this = $(this);
538
+ chosen = $this.data('chosen');
539
+ if (options === 'destroy' && chosen instanceof Chosen) {
540
+ chosen.destroy();
541
+ } else if (!(chosen instanceof Chosen)) {
542
+ $this.data('chosen', new Chosen(this, options));
543
+ }
544
+ });
545
+ }
546
+ });
547
+
548
+ Chosen = (function(_super) {
549
+ __extends(Chosen, _super);
550
+
551
+ function Chosen() {
552
+ _ref = Chosen.__super__.constructor.apply(this, arguments);
553
+ return _ref;
554
+ }
555
+
556
+ Chosen.prototype.setup = function() {
557
+ this.form_field_jq = $(this.form_field);
558
+ this.current_selectedIndex = this.form_field.selectedIndex;
559
+ return this.is_rtl = this.form_field_jq.hasClass("chosen-rtl");
560
+ };
561
+
562
+ Chosen.prototype.set_up_html = function() {
563
+ var container_classes, container_props;
564
+ container_classes = ["chosen-container"];
565
+ container_classes.push("chosen-container-" + (this.is_multiple ? "multi" : "single"));
566
+ if (this.inherit_select_classes && this.form_field.className) {
567
+ container_classes.push(this.form_field.className);
568
+ }
569
+ if (this.is_rtl) {
570
+ container_classes.push("chosen-rtl");
571
+ }
572
+ container_props = {
573
+ 'class': container_classes.join(' '),
574
+ 'style': "width: " + (this.container_width()) + ";",
575
+ 'title': this.form_field.title
576
+ };
577
+ if (this.form_field.id.length) {
578
+ container_props.id = this.form_field.id.replace(/[^\w]/g, '_') + "_chosen";
579
+ }
580
+ this.container = $("<div />", container_props);
581
+ if (this.is_multiple) {
582
+ this.container.html('<ul class="chosen-choices"><li class="search-field"><input type="text" value="' + this.default_text + '" class="default" autocomplete="off" style="width:25px;" /></li></ul><div class="chosen-drop"><ul class="chosen-results"></ul></div>');
583
+ } else {
584
+ this.container.html('<a class="chosen-single chosen-default" tabindex="-1"><span>' + this.default_text + '</span><div><b></b></div></a><div class="chosen-drop"><div class="chosen-search"><input type="text" autocomplete="off" /></div><ul class="chosen-results"></ul></div>');
585
+ }
586
+ this.form_field_jq.hide().after(this.container);
587
+ this.dropdown = this.container.find('div.chosen-drop').first();
588
+ this.search_field = this.container.find('input').first();
589
+ this.search_results = this.container.find('ul.chosen-results').first();
590
+ this.search_field_scale();
591
+ this.search_no_results = this.container.find('li.no-results').first();
592
+ if (this.is_multiple) {
593
+ this.search_choices = this.container.find('ul.chosen-choices').first();
594
+ this.search_container = this.container.find('li.search-field').first();
595
+ } else {
596
+ this.search_container = this.container.find('div.chosen-search').first();
597
+ this.selected_item = this.container.find('.chosen-single').first();
598
+ }
599
+ this.results_build();
600
+ this.set_tab_index();
601
+ this.set_label_behavior();
602
+ return this.form_field_jq.trigger("chosen:ready", {
603
+ chosen: this
604
+ });
605
+ };
606
+
607
+ Chosen.prototype.register_observers = function() {
608
+ var _this = this;
609
+ this.container.bind('touchstart.chosen', function(evt) {
610
+ _this.container_mousedown(evt);
611
+ });
612
+ this.container.bind('touchend.chosen', function(evt) {
613
+ _this.container_mouseup(evt);
614
+ });
615
+ this.container.bind('mousedown.chosen', function(evt) {
616
+ _this.container_mousedown(evt);
617
+ });
618
+ this.container.bind('mouseup.chosen', function(evt) {
619
+ _this.container_mouseup(evt);
620
+ });
621
+ this.container.bind('mouseenter.chosen', function(evt) {
622
+ _this.mouse_enter(evt);
623
+ });
624
+ this.container.bind('mouseleave.chosen', function(evt) {
625
+ _this.mouse_leave(evt);
626
+ });
627
+ this.search_results.bind('mouseup.chosen', function(evt) {
628
+ _this.search_results_mouseup(evt);
629
+ });
630
+ this.search_results.bind('mouseover.chosen', function(evt) {
631
+ _this.search_results_mouseover(evt);
632
+ });
633
+ this.search_results.bind('mouseout.chosen', function(evt) {
634
+ _this.search_results_mouseout(evt);
635
+ });
636
+ this.search_results.bind('mousewheel.chosen DOMMouseScroll.chosen', function(evt) {
637
+ _this.search_results_mousewheel(evt);
638
+ });
639
+ this.search_results.bind('touchstart.chosen', function(evt) {
640
+ _this.search_results_touchstart(evt);
641
+ });
642
+ this.search_results.bind('touchmove.chosen', function(evt) {
643
+ _this.search_results_touchmove(evt);
644
+ });
645
+ this.search_results.bind('touchend.chosen', function(evt) {
646
+ _this.search_results_touchend(evt);
647
+ });
648
+ this.form_field_jq.bind("chosen:updated.chosen", function(evt) {
649
+ _this.results_update_field(evt);
650
+ });
651
+ this.form_field_jq.bind("chosen:activate.chosen", function(evt) {
652
+ _this.activate_field(evt);
653
+ });
654
+ this.form_field_jq.bind("chosen:open.chosen", function(evt) {
655
+ _this.container_mousedown(evt);
656
+ });
657
+ this.form_field_jq.bind("chosen:close.chosen", function(evt) {
658
+ _this.input_blur(evt);
659
+ });
660
+ this.search_field.bind('blur.chosen', function(evt) {
661
+ _this.input_blur(evt);
662
+ });
663
+ this.search_field.bind('keyup.chosen', function(evt) {
664
+ _this.keyup_checker(evt);
665
+ });
666
+ this.search_field.bind('keydown.chosen', function(evt) {
667
+ _this.keydown_checker(evt);
668
+ });
669
+ this.search_field.bind('focus.chosen', function(evt) {
670
+ _this.input_focus(evt);
671
+ });
672
+ this.search_field.bind('cut.chosen', function(evt) {
673
+ _this.clipboard_event_checker(evt);
674
+ });
675
+ this.search_field.bind('paste.chosen', function(evt) {
676
+ _this.clipboard_event_checker(evt);
677
+ });
678
+ if (this.is_multiple) {
679
+ return this.search_choices.bind('click.chosen', function(evt) {
680
+ _this.choices_click(evt);
681
+ });
682
+ } else {
683
+ return this.container.bind('click.chosen', function(evt) {
684
+ evt.preventDefault();
685
+ });
686
+ }
687
+ };
688
+
689
+ Chosen.prototype.destroy = function() {
690
+ $(this.container[0].ownerDocument).unbind("click.chosen", this.click_test_action);
691
+ if (this.search_field[0].tabIndex) {
692
+ this.form_field_jq[0].tabIndex = this.search_field[0].tabIndex;
693
+ }
694
+ this.container.remove();
695
+ this.form_field_jq.removeData('chosen');
696
+ return this.form_field_jq.show();
697
+ };
698
+
699
+ Chosen.prototype.search_field_disabled = function() {
700
+ this.is_disabled = this.form_field_jq[0].disabled;
701
+ if (this.is_disabled) {
702
+ this.container.addClass('chosen-disabled');
703
+ this.search_field[0].disabled = true;
704
+ if (!this.is_multiple) {
705
+ this.selected_item.unbind("focus.chosen", this.activate_action);
706
+ }
707
+ return this.close_field();
708
+ } else {
709
+ this.container.removeClass('chosen-disabled');
710
+ this.search_field[0].disabled = false;
711
+ if (!this.is_multiple) {
712
+ return this.selected_item.bind("focus.chosen", this.activate_action);
713
+ }
714
+ }
715
+ };
716
+
717
+ Chosen.prototype.container_mousedown = function(evt) {
718
+ if (!this.is_disabled) {
719
+ if (evt && evt.type === "mousedown" && !this.results_showing) {
720
+ evt.preventDefault();
721
+ }
722
+ if (!((evt != null) && ($(evt.target)).hasClass("search-choice-close"))) {
723
+ if (!this.active_field) {
724
+ if (this.is_multiple) {
725
+ this.search_field.val("");
726
+ }
727
+ $(this.container[0].ownerDocument).bind('click.chosen', this.click_test_action);
728
+ this.results_show();
729
+ } else if (!this.is_multiple && evt && (($(evt.target)[0] === this.selected_item[0]) || $(evt.target).parents("a.chosen-single").length)) {
730
+ evt.preventDefault();
731
+ this.results_toggle();
732
+ }
733
+ return this.activate_field();
734
+ }
735
+ }
736
+ };
737
+
738
+ Chosen.prototype.container_mouseup = function(evt) {
739
+ if (evt.target.nodeName === "ABBR" && !this.is_disabled) {
740
+ return this.results_reset(evt);
741
+ }
742
+ };
743
+
744
+ Chosen.prototype.search_results_mousewheel = function(evt) {
745
+ var delta;
746
+ if (evt.originalEvent) {
747
+ delta = evt.originalEvent.deltaY || -evt.originalEvent.wheelDelta || evt.originalEvent.detail;
748
+ }
749
+ if (delta != null) {
750
+ evt.preventDefault();
751
+ if (evt.type === 'DOMMouseScroll') {
752
+ delta = delta * 40;
753
+ }
754
+ return this.search_results.scrollTop(delta + this.search_results.scrollTop());
755
+ }
756
+ };
757
+
758
+ Chosen.prototype.blur_test = function(evt) {
759
+ if (!this.active_field && this.container.hasClass("chosen-container-active")) {
760
+ return this.close_field();
761
+ }
762
+ };
763
+
764
+ Chosen.prototype.close_field = function() {
765
+ $(this.container[0].ownerDocument).unbind("click.chosen", this.click_test_action);
766
+ this.active_field = false;
767
+ this.results_hide();
768
+ this.container.removeClass("chosen-container-active");
769
+ this.clear_backstroke();
770
+ this.show_search_field_default();
771
+ return this.search_field_scale();
772
+ };
773
+
774
+ Chosen.prototype.activate_field = function() {
775
+ this.container.addClass("chosen-container-active");
776
+ this.active_field = true;
777
+ this.search_field.val(this.search_field.val());
778
+ return this.search_field.focus();
779
+ };
780
+
781
+ Chosen.prototype.test_active_click = function(evt) {
782
+ var active_container;
783
+ active_container = $(evt.target).closest('.chosen-container');
784
+ if (active_container.length && this.container[0] === active_container[0]) {
785
+ return this.active_field = true;
786
+ } else {
787
+ return this.close_field();
788
+ }
789
+ };
790
+
791
+ Chosen.prototype.results_build = function() {
792
+ this.parsing = true;
793
+ this.selected_option_count = null;
794
+ this.results_data = SelectParser.select_to_array(this.form_field);
795
+ if (this.is_multiple) {
796
+ this.search_choices.find("li.search-choice").remove();
797
+ } else if (!this.is_multiple) {
798
+ this.single_set_selected_text();
799
+ if (this.disable_search || this.form_field.options.length <= this.disable_search_threshold) {
800
+ this.search_field[0].readOnly = true;
801
+ this.container.addClass("chosen-container-single-nosearch");
802
+ } else {
803
+ this.search_field[0].readOnly = false;
804
+ this.container.removeClass("chosen-container-single-nosearch");
805
+ }
806
+ }
807
+ this.update_results_content(this.results_option_build({
808
+ first: true
809
+ }));
810
+ this.search_field_disabled();
811
+ this.show_search_field_default();
812
+ this.search_field_scale();
813
+ return this.parsing = false;
814
+ };
815
+
816
+ Chosen.prototype.result_do_highlight = function(el) {
817
+ var high_bottom, high_top, maxHeight, visible_bottom, visible_top;
818
+ if (el.length) {
819
+ this.result_clear_highlight();
820
+ this.result_highlight = el;
821
+ this.result_highlight.addClass("highlighted");
822
+ maxHeight = parseInt(this.search_results.css("maxHeight"), 10);
823
+ visible_top = this.search_results.scrollTop();
824
+ visible_bottom = maxHeight + visible_top;
825
+ high_top = this.result_highlight.position().top + this.search_results.scrollTop();
826
+ high_bottom = high_top + this.result_highlight.outerHeight();
827
+ if (high_bottom >= visible_bottom) {
828
+ return this.search_results.scrollTop((high_bottom - maxHeight) > 0 ? high_bottom - maxHeight : 0);
829
+ } else if (high_top < visible_top) {
830
+ return this.search_results.scrollTop(high_top);
831
+ }
832
+ }
833
+ };
834
+
835
+ Chosen.prototype.result_clear_highlight = function() {
836
+ if (this.result_highlight) {
837
+ this.result_highlight.removeClass("highlighted");
838
+ }
839
+ return this.result_highlight = null;
840
+ };
841
+
842
+ Chosen.prototype.results_show = function() {
843
+ if (this.is_multiple && this.max_selected_options <= this.choices_count()) {
844
+ this.form_field_jq.trigger("chosen:maxselected", {
845
+ chosen: this
846
+ });
847
+ return false;
848
+ }
849
+ this.container.addClass("chosen-with-drop");
850
+ this.results_showing = true;
851
+ this.search_field.focus();
852
+ this.search_field.val(this.search_field.val());
853
+ this.winnow_results();
854
+ return this.form_field_jq.trigger("chosen:showing_dropdown", {
855
+ chosen: this
856
+ });
857
+ };
858
+
859
+ Chosen.prototype.update_results_content = function(content) {
860
+ return this.search_results.html(content);
861
+ };
862
+
863
+ Chosen.prototype.results_hide = function() {
864
+ if (this.results_showing) {
865
+ this.result_clear_highlight();
866
+ this.container.removeClass("chosen-with-drop");
867
+ this.form_field_jq.trigger("chosen:hiding_dropdown", {
868
+ chosen: this
869
+ });
870
+ }
871
+ return this.results_showing = false;
872
+ };
873
+
874
+ Chosen.prototype.set_tab_index = function(el) {
875
+ var ti;
876
+ if (this.form_field.tabIndex) {
877
+ ti = this.form_field.tabIndex;
878
+ this.form_field.tabIndex = -1;
879
+ return this.search_field[0].tabIndex = ti;
880
+ }
881
+ };
882
+
883
+ Chosen.prototype.set_label_behavior = function() {
884
+ var _this = this;
885
+ this.form_field_label = this.form_field_jq.parents("label");
886
+ if (!this.form_field_label.length && this.form_field.id.length) {
887
+ this.form_field_label = $("label[for='" + this.form_field.id + "']");
888
+ }
889
+ if (this.form_field_label.length > 0) {
890
+ return this.form_field_label.bind('click.chosen', function(evt) {
891
+ if (_this.is_multiple) {
892
+ return _this.container_mousedown(evt);
893
+ } else {
894
+ return _this.activate_field();
895
+ }
896
+ });
897
+ }
898
+ };
899
+
900
+ Chosen.prototype.show_search_field_default = function() {
901
+ if (this.is_multiple && this.choices_count() < 1 && !this.active_field) {
902
+ this.search_field.val(this.default_text);
903
+ return this.search_field.addClass("default");
904
+ } else {
905
+ this.search_field.val("");
906
+ return this.search_field.removeClass("default");
907
+ }
908
+ };
909
+
910
+ Chosen.prototype.search_results_mouseup = function(evt) {
911
+ var target;
912
+ target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
913
+ if (target.length) {
914
+ this.result_highlight = target;
915
+ this.result_select(evt);
916
+ return this.search_field.focus();
917
+ }
918
+ };
919
+
920
+ Chosen.prototype.search_results_mouseover = function(evt) {
921
+ var target;
922
+ target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
923
+ if (target) {
924
+ return this.result_do_highlight(target);
925
+ }
926
+ };
927
+
928
+ Chosen.prototype.search_results_mouseout = function(evt) {
929
+ if ($(evt.target).hasClass("active-result" || $(evt.target).parents('.active-result').first())) {
930
+ return this.result_clear_highlight();
931
+ }
932
+ };
933
+
934
+ Chosen.prototype.choice_build = function(item) {
935
+ var choice, close_link,
936
+ _this = this;
937
+ choice = $('<li />', {
938
+ "class": "search-choice"
939
+ }).html("<span>" + item.html + "</span>");
940
+ if (item.disabled) {
941
+ choice.addClass('search-choice-disabled');
942
+ } else {
943
+ close_link = $('<a />', {
944
+ "class": 'search-choice-close',
945
+ 'data-option-array-index': item.array_index
946
+ });
947
+ close_link.bind('click.chosen', function(evt) {
948
+ return _this.choice_destroy_link_click(evt);
949
+ });
950
+ choice.append(close_link);
951
+ }
952
+ return this.search_container.before(choice);
953
+ };
954
+
955
+ Chosen.prototype.choice_destroy_link_click = function(evt) {
956
+ evt.preventDefault();
957
+ evt.stopPropagation();
958
+ if (!this.is_disabled) {
959
+ return this.choice_destroy($(evt.target));
960
+ }
961
+ };
962
+
963
+ Chosen.prototype.choice_destroy = function(link) {
964
+ if (this.result_deselect(link[0].getAttribute("data-option-array-index"))) {
965
+ this.show_search_field_default();
966
+ if (this.is_multiple && this.choices_count() > 0 && this.search_field.val().length < 1) {
967
+ this.results_hide();
968
+ }
969
+ link.parents('li').first().remove();
970
+ return this.search_field_scale();
971
+ }
972
+ };
973
+
974
+ Chosen.prototype.results_reset = function() {
975
+ this.reset_single_select_options();
976
+ this.form_field.options[0].selected = true;
977
+ this.single_set_selected_text();
978
+ this.show_search_field_default();
979
+ this.results_reset_cleanup();
980
+ this.form_field_jq.trigger("change");
981
+ if (this.active_field) {
982
+ return this.results_hide();
983
+ }
984
+ };
985
+
986
+ Chosen.prototype.results_reset_cleanup = function() {
987
+ this.current_selectedIndex = this.form_field.selectedIndex;
988
+ return this.selected_item.find("abbr").remove();
989
+ };
990
+
991
+ Chosen.prototype.result_select = function(evt) {
992
+ var high, item;
993
+ if (this.result_highlight) {
994
+ high = this.result_highlight;
995
+ this.result_clear_highlight();
996
+ if (this.is_multiple && this.max_selected_options <= this.choices_count()) {
997
+ this.form_field_jq.trigger("chosen:maxselected", {
998
+ chosen: this
999
+ });
1000
+ return false;
1001
+ }
1002
+ if (this.is_multiple) {
1003
+ high.removeClass("active-result");
1004
+ } else {
1005
+ this.reset_single_select_options();
1006
+ }
1007
+ item = this.results_data[high[0].getAttribute("data-option-array-index")];
1008
+ item.selected = true;
1009
+ this.form_field.options[item.options_index].selected = true;
1010
+ this.selected_option_count = null;
1011
+ if (this.is_multiple) {
1012
+ this.choice_build(item);
1013
+ } else {
1014
+ this.single_set_selected_text(item.text);
1015
+ }
1016
+ if (!((evt.metaKey || evt.ctrlKey) && this.is_multiple)) {
1017
+ this.results_hide();
1018
+ }
1019
+ this.search_field.val("");
1020
+ if (this.is_multiple || this.form_field.selectedIndex !== this.current_selectedIndex) {
1021
+ this.form_field_jq.trigger("change", {
1022
+ 'selected': this.form_field.options[item.options_index].value
1023
+ });
1024
+ }
1025
+ this.current_selectedIndex = this.form_field.selectedIndex;
1026
+ return this.search_field_scale();
1027
+ }
1028
+ };
1029
+
1030
+ Chosen.prototype.single_set_selected_text = function(text) {
1031
+ if (text == null) {
1032
+ text = this.default_text;
1033
+ }
1034
+ if (text === this.default_text) {
1035
+ this.selected_item.addClass("chosen-default");
1036
+ } else {
1037
+ this.single_deselect_control_build();
1038
+ this.selected_item.removeClass("chosen-default");
1039
+ }
1040
+ return this.selected_item.find("span").text(text);
1041
+ };
1042
+
1043
+ Chosen.prototype.result_deselect = function(pos) {
1044
+ var result_data;
1045
+ result_data = this.results_data[pos];
1046
+ if (!this.form_field.options[result_data.options_index].disabled) {
1047
+ result_data.selected = false;
1048
+ this.form_field.options[result_data.options_index].selected = false;
1049
+ this.selected_option_count = null;
1050
+ this.result_clear_highlight();
1051
+ if (this.results_showing) {
1052
+ this.winnow_results();
1053
+ }
1054
+ this.form_field_jq.trigger("change", {
1055
+ deselected: this.form_field.options[result_data.options_index].value
1056
+ });
1057
+ this.search_field_scale();
1058
+ return true;
1059
+ } else {
1060
+ return false;
1061
+ }
1062
+ };
1063
+
1064
+ Chosen.prototype.single_deselect_control_build = function() {
1065
+ if (!this.allow_single_deselect) {
1066
+ return;
1067
+ }
1068
+ if (!this.selected_item.find("abbr").length) {
1069
+ this.selected_item.find("span").first().after("<abbr class=\"search-choice-close\"></abbr>");
1070
+ }
1071
+ return this.selected_item.addClass("chosen-single-with-deselect");
1072
+ };
1073
+
1074
+ Chosen.prototype.get_search_text = function() {
1075
+ if (this.search_field.val() === this.default_text) {
1076
+ return "";
1077
+ } else {
1078
+ return $('<div/>').text($.trim(this.search_field.val())).html();
1079
+ }
1080
+ };
1081
+
1082
+ Chosen.prototype.winnow_results_set_highlight = function() {
1083
+ var do_high, selected_results;
1084
+ selected_results = !this.is_multiple ? this.search_results.find(".result-selected.active-result") : [];
1085
+ do_high = selected_results.length ? selected_results.first() : this.search_results.find(".active-result").first();
1086
+ if (do_high != null) {
1087
+ return this.result_do_highlight(do_high);
1088
+ }
1089
+ };
1090
+
1091
+ Chosen.prototype.no_results = function(terms) {
1092
+ var no_results_html;
1093
+ no_results_html = $('<li class="no-results">' + this.results_none_found + ' "<span></span>"</li>');
1094
+ no_results_html.find("span").first().html(terms);
1095
+ this.search_results.append(no_results_html);
1096
+ return this.form_field_jq.trigger("chosen:no_results", {
1097
+ chosen: this
1098
+ });
1099
+ };
1100
+
1101
+ Chosen.prototype.no_results_clear = function() {
1102
+ return this.search_results.find(".no-results").remove();
1103
+ };
1104
+
1105
+ Chosen.prototype.keydown_arrow = function() {
1106
+ var next_sib;
1107
+ if (this.results_showing && this.result_highlight) {
1108
+ next_sib = this.result_highlight.nextAll("li.active-result").first();
1109
+ if (next_sib) {
1110
+ return this.result_do_highlight(next_sib);
1111
+ }
1112
+ } else {
1113
+ return this.results_show();
1114
+ }
1115
+ };
1116
+
1117
+ Chosen.prototype.keyup_arrow = function() {
1118
+ var prev_sibs;
1119
+ if (!this.results_showing && !this.is_multiple) {
1120
+ return this.results_show();
1121
+ } else if (this.result_highlight) {
1122
+ prev_sibs = this.result_highlight.prevAll("li.active-result");
1123
+ if (prev_sibs.length) {
1124
+ return this.result_do_highlight(prev_sibs.first());
1125
+ } else {
1126
+ if (this.choices_count() > 0) {
1127
+ this.results_hide();
1128
+ }
1129
+ return this.result_clear_highlight();
1130
+ }
1131
+ }
1132
+ };
1133
+
1134
+ Chosen.prototype.keydown_backstroke = function() {
1135
+ var next_available_destroy;
1136
+ if (this.pending_backstroke) {
1137
+ this.choice_destroy(this.pending_backstroke.find("a").first());
1138
+ return this.clear_backstroke();
1139
+ } else {
1140
+ next_available_destroy = this.search_container.siblings("li.search-choice").last();
1141
+ if (next_available_destroy.length && !next_available_destroy.hasClass("search-choice-disabled")) {
1142
+ this.pending_backstroke = next_available_destroy;
1143
+ if (this.single_backstroke_delete) {
1144
+ return this.keydown_backstroke();
1145
+ } else {
1146
+ return this.pending_backstroke.addClass("search-choice-focus");
1147
+ }
1148
+ }
1149
+ }
1150
+ };
1151
+
1152
+ Chosen.prototype.clear_backstroke = function() {
1153
+ if (this.pending_backstroke) {
1154
+ this.pending_backstroke.removeClass("search-choice-focus");
1155
+ }
1156
+ return this.pending_backstroke = null;
1157
+ };
1158
+
1159
+ Chosen.prototype.keydown_checker = function(evt) {
1160
+ var stroke, _ref1;
1161
+ stroke = (_ref1 = evt.which) != null ? _ref1 : evt.keyCode;
1162
+ this.search_field_scale();
1163
+ if (stroke !== 8 && this.pending_backstroke) {
1164
+ this.clear_backstroke();
1165
+ }
1166
+ switch (stroke) {
1167
+ case 8:
1168
+ this.backstroke_length = this.search_field.val().length;
1169
+ break;
1170
+ case 9:
1171
+ if (this.results_showing && !this.is_multiple) {
1172
+ this.result_select(evt);
1173
+ }
1174
+ this.mouse_on_container = false;
1175
+ break;
1176
+ case 13:
1177
+ if (this.results_showing) {
1178
+ evt.preventDefault();
1179
+ }
1180
+ break;
1181
+ case 32:
1182
+ if (this.disable_search) {
1183
+ evt.preventDefault();
1184
+ }
1185
+ break;
1186
+ case 38:
1187
+ evt.preventDefault();
1188
+ this.keyup_arrow();
1189
+ break;
1190
+ case 40:
1191
+ evt.preventDefault();
1192
+ this.keydown_arrow();
1193
+ break;
1194
+ }
1195
+ };
1196
+
1197
+ Chosen.prototype.search_field_scale = function() {
1198
+ var div, f_width, h, style, style_block, styles, w, _i, _len;
1199
+ if (this.is_multiple) {
1200
+ h = 0;
1201
+ w = 0;
1202
+ style_block = "position:absolute; left: -1000px; top: -1000px; display:none;";
1203
+ styles = ['font-size', 'font-style', 'font-weight', 'font-family', 'line-height', 'text-transform', 'letter-spacing'];
1204
+ for (_i = 0, _len = styles.length; _i < _len; _i++) {
1205
+ style = styles[_i];
1206
+ style_block += style + ":" + this.search_field.css(style) + ";";
1207
+ }
1208
+ div = $('<div />', {
1209
+ 'style': style_block
1210
+ });
1211
+ div.text(this.search_field.val());
1212
+ $('body').append(div);
1213
+ w = div.width() + 25;
1214
+ div.remove();
1215
+ f_width = this.container.outerWidth();
1216
+ if (w > f_width - 10) {
1217
+ w = f_width - 10;
1218
+ }
1219
+ return this.search_field.css({
1220
+ 'width': w + 'px'
1221
+ });
1222
+ }
1223
+ };
1224
+
1225
+ return Chosen;
1226
+
1227
+ })(AbstractChosen);
1228
+
1229
+ }).call(this);
backend/modules/calendar/resources/js/jquery.weekcalendar.js ADDED
@@ -0,0 +1,2951 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * jQuery.weekCalendar v2.0-dev
3
+ *
4
+ * for support join us at the google group:
5
+ * - http://groups.google.com/group/jquery-week-calendar
6
+ * have a look to the wiki for documentation:
7
+ * - http://wiki.github.com/themouette/jquery-week-calendar/
8
+ * something went bad ? report an issue:
9
+ * - http://github.com/themouette/jquery-week-calendar/issues
10
+ * get the last version on github:
11
+ * - http://github.com/themouette/jquery-week-calendar
12
+ *
13
+ * Copyright (c) 2009 Rob Monie
14
+ * Copyright (c) 2010 Julien MUETTON
15
+ * Dual licensed under the MIT and GPL licenses:
16
+ * http://www.opensource.org/licenses/mit-license.php
17
+ * http://www.gnu.org/licenses/gpl.html
18
+ *
19
+ * If you're after a monthly calendar plugin, check out this one :
20
+ * http://arshaw.com/fullcalendar/
21
+ */
22
+
23
+ (function($) {
24
+ // check the jquery version
25
+ var _v = $.fn.jquery.split('.'),
26
+ _jQuery14OrLower = (10 * _v[0] + _v[1]) < 15;
27
+
28
+ $.widget('ui.weekCalendar', (function() {
29
+ var _currentAjaxCall, _hourLineTimeout;
30
+
31
+ return {
32
+ options: {
33
+ date: new Date(),
34
+ timeFormat: null,
35
+ dateFormat: 'M d, Y',
36
+ alwaysDisplayTimeMinutes: true,
37
+ use24Hour: false,
38
+ daysToShow: 7,
39
+ minBodyHeight: 100,
40
+ firstDayOfWeek: function(calendar) {
41
+ if ($(calendar).weekCalendar('option', 'daysToShow') != 5) {
42
+ return 0;
43
+ } else {
44
+ //workweek
45
+ return 1;
46
+ }
47
+ }, // 0 = Sunday, 1 = Monday, 2 = Tuesday, ... , 6 = Saturday
48
+ useShortDayNames: false,
49
+ timeSeparator: ' to ',
50
+ startParam: 'start',
51
+ endParam: 'end',
52
+ businessHours: {start: 8, end: 18, limitDisplay: false},
53
+ newEventText: 'New Event',
54
+ timeslotHeight: 20,
55
+ defaultEventLength: 2,
56
+ timeslotsPerHour: 4,
57
+ minDate: null,
58
+ maxDate: null,
59
+ showHeader: true,
60
+ buttons: true,
61
+ buttonText: {
62
+ today: 'today',
63
+ lastWeek: 'previous',
64
+ nextWeek: 'next'
65
+ },
66
+ switchDisplay: {},
67
+ scrollToHourMillis: 500,
68
+ allowEventDelete: false,
69
+ allowCalEventOverlap: false,
70
+ overlapEventsSeparate: false,
71
+ totalEventsWidthPercentInOneColumn: 100,
72
+ readonly: false,
73
+ allowEventCreation: true,
74
+ hourLine: false,
75
+ deletable: function(calEvent, element) {
76
+ return true;
77
+ },
78
+ draggable: function(calEvent, element) {
79
+ return true;
80
+ },
81
+ resizable: function(calEvent, element) {
82
+ return true;
83
+ },
84
+ eventClick: function(calEvent, element, dayFreeBusyManager,
85
+ calendar, clickEvent) {
86
+ },
87
+ eventRender: function(calEvent, element) {
88
+ return element;
89
+ },
90
+ eventAfterRender: function(calEvent, element) {
91
+ return element;
92
+ },
93
+ eventRefresh: function(calEvent, element) {
94
+ return element;
95
+ },
96
+ eventDrag: function(calEvent, element) {
97
+ },
98
+ eventDrop: function(calEvent, element) {
99
+ },
100
+ eventResize: function(calEvent, element) {
101
+ },
102
+ eventNew: function(calEvent, element, dayFreeBusyManager,
103
+ calendar, mouseupEvent) {
104
+ },
105
+ eventMouseover: function(calEvent, $event) {
106
+ },
107
+ eventMouseout: function(calEvent, $event) {
108
+ },
109
+ eventDelete: function(calEvent, element, dayFreeBusyManager,
110
+ calendar, clickEvent) {
111
+ calendar.weekCalendar('removeEvent',calEvent.id);
112
+ },
113
+ calendarBeforeLoad: function(calendar) {
114
+ },
115
+ calendarAfterLoad: function(calendar) {
116
+ },
117
+ noEvents: function() {
118
+ },
119
+ eventHeader: function(calEvent, calendar) {
120
+ var options = calendar.weekCalendar('option');
121
+ var one_hour = 3600000;
122
+ var displayTitleWithTime = calEvent.end.getTime() - calEvent.start.getTime() <= (one_hour / options.timeslotsPerHour);
123
+ if (displayTitleWithTime) {
124
+ return calendar.weekCalendar(
125
+ 'formatTime', calEvent.start) +
126
+ ': ' + calEvent.title;
127
+ } else {
128
+ return calendar.weekCalendar(
129
+ 'formatTime', calEvent.start) +
130
+ options.timeSeparator +
131
+ calendar.weekCalendar(
132
+ 'formatTime', calEvent.end);
133
+ }
134
+ },
135
+ eventBody: function(calEvent, calendar) {
136
+ return calEvent.title;
137
+ },
138
+ shortMonths: BooklyL10n['shortMonths'],
139
+ longMonths: BooklyL10n['longMonths'],
140
+ shortDays: BooklyL10n['shortDays'],
141
+ longDays: BooklyL10n['longDays'],
142
+ /* multi-users options */
143
+ /**
144
+ * the available users for calendar.
145
+ * if you want to display users separately, enable the
146
+ * showAsSeparateUsers option.
147
+ * if you provide a list of user and do not enable showAsSeparateUsers
148
+ * option, then only the events that belongs to one or several of
149
+ * given users will be displayed
150
+ * @type {array}
151
+ */
152
+ users: [],
153
+ /**
154
+ * should the calendar be displayed with separate column for each
155
+ * users.
156
+ * note that this option does nothing if you do not provide at least
157
+ * one user.
158
+ * @type {boolean}
159
+ */
160
+ showAsSeparateUsers: true,
161
+ /**
162
+ * callback used to read user id from a user object.
163
+ * @param {Object} user the user to retrieve the id from.
164
+ * @param {number} index the user index from user list.
165
+ * @param {jQuery} calendar the calendar object.
166
+ * @return {int|String} the user id.
167
+ */
168
+ getUserId: function(user, index, calendar) {
169
+ return index;
170
+ },
171
+ /**
172
+ * callback used to read user name from a user object.
173
+ * @param {Object} user the user to retrieve the name from.
174
+ * @param {number} index the user index from user list.
175
+ * @param {jQuery} calendar the calendar object.
176
+ * @return {String} the user name.
177
+ */
178
+ getUserName: function(user, index, calendar) {
179
+ return user;
180
+ },
181
+ /**
182
+ * reads the id(s) of user(s) for who the event should be displayed.
183
+ * @param {Object} calEvent the calEvent to read informations from.
184
+ * @param {jQuery} calendar the calendar object.
185
+ * @return {number|String|Array} the user id(s) to appened events for.
186
+ */
187
+ getEventUserId: function(calEvent, calendar) {
188
+ return calEvent.userId;
189
+ },
190
+ /**
191
+ * sets user id(s) to the calEvent
192
+ * @param {Object} calEvent the calEvent to set informations to.
193
+ * @param {jQuery} calendar the calendar object.
194
+ * @return {Object} the calEvent with modified user id.
195
+ */
196
+ setEventUserId: function(userId, calEvent, calendar) {
197
+ calEvent.userId = userId;
198
+ return calEvent;
199
+ },
200
+ /* freeBusy options */
201
+ /**
202
+ * should the calendar display freebusys ?
203
+ * @type {boolean}
204
+ */
205
+ displayFreeBusys: false,
206
+ /**
207
+ * read the id(s) for who the freebusy is available
208
+ * @param {Object} calEvent the calEvent to read informations from.
209
+ * @param {jQuery} calendar the calendar object.
210
+ * @return {number|String|Array} the user id(s) to appened events for.
211
+ */
212
+ getFreeBusyUserId: function(calFreeBusy, calendar) {
213
+ return calFreeBusy.userId;
214
+ },
215
+ /**
216
+ * the default freeBusy object, used to manage default state
217
+ * @type {Object}
218
+ */
219
+ defaultFreeBusy: {free: false},
220
+ /**
221
+ * function used to display the freeBusy element
222
+ * @type {Function}
223
+ * @param {Object} freeBusy the freeBusy timeslot to render.
224
+ * @param {jQuery} $freeBusy the freeBusy HTML element.
225
+ * @param {jQuery} calendar the calendar element.
226
+ */
227
+ freeBusyRender: function(freeBusy, $freeBusy, calendar) {
228
+ if (!freeBusy.free) {
229
+ $freeBusy.addClass('free-busy-busy');
230
+ }
231
+ else {
232
+ $freeBusy.addClass('free-busy-free');
233
+ }
234
+ return $freeBusy;
235
+ },
236
+ /* other options */
237
+ /**
238
+ * true means start on first day of week, false means starts on
239
+ * startDate.
240
+ * @param {jQuery} calendar the calendar object.
241
+ * @type {Function|bool}
242
+ */
243
+ startOnFirstDayOfWeek: function(calendar) {
244
+ return $(calendar).weekCalendar('option', 'daysToShow') >= 5;
245
+ },
246
+ /**
247
+ * should the columns be rendered alternatively using odd/even
248
+ * class
249
+ * @type {boolean}
250
+ */
251
+ displayOddEven: false,
252
+ textSize: 13,
253
+ /**
254
+ * the title attribute for the calendar. possible placeholders are:
255
+ * <ul>
256
+ * <li>%start%</li>
257
+ * <li>%end%</li>
258
+ * <li>%date%</li>
259
+ * </ul>
260
+ * @type {Function|string}
261
+ * @param {number} option daysToShow.
262
+ * @return {String} the title attribute for the calendar.
263
+ */
264
+ title: '%start% - %end%',
265
+ /**
266
+ * default options to pass to callback
267
+ * you can pass a function returning an object or a litteral object
268
+ * @type {object|function(#calendar)}
269
+ */
270
+ jsonOptions: {},
271
+ headerSeparator: '<br />',
272
+ /**
273
+ * returns formatted header for day display
274
+ * @type {function(date,calendar)}
275
+ */
276
+ getHeaderDate: null,
277
+ preventDragOnEventCreation: false,
278
+ /**
279
+ * the event on which to bind calendar resize
280
+ * @type {string}
281
+ */
282
+ resizeEvent: 'resize.weekcalendar'
283
+ },
284
+
285
+ /***********************
286
+ * Initialise calendar *
287
+ ***********************/
288
+ _create: function() {
289
+ var self = this;
290
+ self._computeOptions();
291
+ self._setupEventDelegation();
292
+ self._renderCalendar();
293
+ self._loadCalEvents();
294
+ self._resizeCalendar();
295
+
296
+ if (this.options.resizeEvent) {
297
+ $(window).unbind(this.options.resizeEvent);
298
+ $(window).bind(this.options.resizeEvent, function() {
299
+ self._resizeCalendar();
300
+ });
301
+ }
302
+
303
+ },
304
+
305
+ /********************
306
+ * public functions *
307
+ ********************/
308
+ /*
309
+ * Refresh the events for the currently displayed week.
310
+ */
311
+ refresh: function() {
312
+ //reload with existing week
313
+ this._loadCalEvents(this.element.data('startDate'));
314
+ },
315
+
316
+ /*
317
+ * Clear all events currently loaded into the calendar
318
+ */
319
+ clear: function() {
320
+ this._clearCalendar();
321
+ },
322
+
323
+ /*
324
+ * Go to this week
325
+ */
326
+ today: function() {
327
+ this._clearCalendar();
328
+ this._loadCalEvents(new Date());
329
+ },
330
+
331
+ /*
332
+ * Go to the previous week relative to the currently displayed week
333
+ */
334
+ prevWeek: function() {
335
+ //minus more than 1 day to be sure we're in previous week - account for daylight savings or other anomolies
336
+ var newDate = new Date(this.element.data('startDate').getTime() - (MILLIS_IN_WEEK / 6));
337
+ this._clearCalendar();
338
+ this._loadCalEvents(newDate);
339
+ },
340
+
341
+ /*
342
+ * Go to the next week relative to the currently displayed week
343
+ */
344
+ nextWeek: function() {
345
+ //add 8 days to be sure of being in prev week - allows for daylight savings or other anomolies
346
+ var newDate = new Date(this.element.data('startDate').getTime() + MILLIS_IN_WEEK + MILLIS_IN_DAY);
347
+ this._clearCalendar();
348
+ this._loadCalEvents(newDate);
349
+ },
350
+
351
+ /*
352
+ * Reload the calendar to whatever week the date passed in falls on.
353
+ */
354
+ gotoWeek: function(date) {
355
+ this._clearCalendar();
356
+ this._loadCalEvents(date);
357
+ },
358
+
359
+ /*
360
+ * Reload the calendar to whatever week the date passed in falls on.
361
+ */
362
+ gotoDate: function(date) {
363
+ this._clearCalendar();
364
+ this._loadCalEvents(date);
365
+ },
366
+
367
+ /**
368
+ * change the number of days to show
369
+ */
370
+ setDaysToShow: function(daysToShow) {
371
+ var self = this;
372
+ var hour = self._getCurrentScrollHour();
373
+ self.options.daysToShow = daysToShow;
374
+ $(self.element).html('');
375
+ self._renderCalendar();
376
+ self._loadCalEvents();
377
+ self._resizeCalendar();
378
+ self._scrollToHour(hour, false);
379
+
380
+ if (this.options.resizeEvent) {
381
+ $(window).unbind(this.options.resizeEvent);
382
+ $(window).bind(this.options.resizeEvent, function() {
383
+ self._resizeCalendar();
384
+ });
385
+ }
386
+ },
387
+
388
+ /*
389
+ * Remove an event based on it's id
390
+ */
391
+ removeEvent: function(eventId) {
392
+
393
+ var self = this;
394
+
395
+ self.element.find('.wc-cal-event').each(function() {
396
+ if ($(this).data('calEvent').id === eventId) {
397
+ $(this).remove();
398
+ return false;
399
+ }
400
+ });
401
+
402
+ //this could be more efficient rather than running on all days regardless...
403
+ self.element.find('.wc-day-column-inner').each(function() {
404
+ self._adjustOverlappingEvents($(this));
405
+ });
406
+ },
407
+
408
+ /*
409
+ * Removes any events that have been added but not yet saved (have no id).
410
+ * This is useful to call after adding a freshly saved new event.
411
+ */
412
+ removeUnsavedEvents: function() {
413
+
414
+ var self = this;
415
+
416
+ self.element.find('.wc-new-cal-event').each(function() {
417
+ $(this).remove();
418
+ });
419
+
420
+ //this could be more efficient rather than running on all days regardless...
421
+ self.element.find('.wc-day-column-inner').each(function() {
422
+ self._adjustOverlappingEvents($(this));
423
+ });
424
+ },
425
+
426
+ /*
427
+ * update an event in the calendar. If the event exists it refreshes
428
+ * it's rendering. If it's a new event that does not exist in the calendar
429
+ * it will be added.
430
+ */
431
+ updateEvent: function(calEvent) {
432
+ this._updateEventInCalendar(calEvent);
433
+ },
434
+
435
+ /*
436
+ * Returns an array of timeslot start and end times based on
437
+ * the configured grid of the calendar. Returns in both date and
438
+ * formatted time based on the 'timeFormat' config option.
439
+ */
440
+ getTimeslotTimes: function(date) {
441
+ var options = this.options;
442
+ var firstHourDisplayed = options.businessHours.limitDisplay ? options.businessHours.start : 0;
443
+ var startDate = new Date(date.getFullYear(), date.getMonth(), date.getDate(), firstHourDisplayed);
444
+
445
+ var times = [],
446
+ startMillis = startDate.getTime();
447
+ for (var i = 0; i < options.timeslotsPerDay; i++) {
448
+ var endMillis = startMillis + options.millisPerTimeslot;
449
+ times[i] = {
450
+ start: new Date(startMillis),
451
+ startFormatted: this.formatTime(new Date(startMillis), options.timeFormat),
452
+ end: new Date(endMillis),
453
+ endFormatted: this.formatTime(new Date(endMillis), options.timeFormat)
454
+ };
455
+ startMillis = endMillis;
456
+ }
457
+ return times;
458
+ },
459
+
460
+ formatDate: function(date, format) {
461
+ if (format) {
462
+ return this._formatDate(date, format);
463
+ } else {
464
+ return this._formatDate(date, this.options.dateFormat);
465
+ }
466
+ },
467
+
468
+ formatTime: function(date, format) {
469
+ if (format) {
470
+ return this._formatDate(date, format);
471
+ } else if (this.options.timeFormat) {
472
+ return this._formatDate(date, this.options.timeFormat);
473
+ } else if (this.options.use24Hour) {
474
+ return this._formatDate(date, 'H:i');
475
+ } else {
476
+ return this._formatDate(date, 'h:i a');
477
+ }
478
+ },
479
+
480
+ serializeEvents: function() {
481
+ var self = this;
482
+ var calEvents = [];
483
+
484
+ self.element.find('.wc-cal-event').each(function() {
485
+ calEvents.push($(this).data('calEvent'));
486
+ });
487
+ return calEvents;
488
+ },
489
+
490
+ next: function() {
491
+ if (this._startOnFirstDayOfWeek()) {
492
+ return this.nextWeek();
493
+ }
494
+ var newDate = new Date(this.element.data('startDate').getTime());
495
+ newDate.setDate(newDate.getDate() + this.options.daysToShow);
496
+
497
+ this._clearCalendar();
498
+ this._loadCalEvents(newDate);
499
+ },
500
+
501
+ prev: function() {
502
+ if (this._startOnFirstDayOfWeek()) {
503
+ return this.prevWeek();
504
+ }
505
+ var newDate = new Date(this.element.data('startDate').getTime());
506
+ newDate.setDate(newDate.getDate() - this.options.daysToShow);
507
+
508
+ this._clearCalendar();
509
+ this._loadCalEvents(newDate);
510
+ },
511
+ getCurrentFirstDay: function() {
512
+ return this._dateFirstDayOfWeek(this.options.date || new Date());
513
+ },
514
+ getCurrentLastDay: function() {
515
+ return this._addDays(this.getCurrentFirstDay(), this.options.daysToShow - 1);
516
+ },
517
+
518
+ /*********************
519
+ * private functions *
520
+ *********************/
521
+ _setOption: function(key, value) {
522
+ var self = this;
523
+ if (self.options[key] != value) {
524
+ // event callback change, no need to re-render the events
525
+ if (key == 'beforeEventNew') {
526
+ self.options[key] = value;
527
+ return;
528
+ }
529
+
530
+ // this could be made more efficient at some stage by caching the
531
+ // events array locally in a store but this should be done in conjunction
532
+ // with a proper binding model.
533
+
534
+ var currentEvents = self.element.find('.wc-cal-event').map(function() {
535
+ return $(this).data('calEvent');
536
+ });
537
+
538
+ var newOptions = {};
539
+ newOptions[key] = value;
540
+ self._renderEvents({events: currentEvents, options: newOptions}, self.element.find('.wc-day-column-inner'));
541
+ }
542
+ },
543
+
544
+ // compute dynamic options based on other config values
545
+ _computeOptions: function() {
546
+ var options = this.options;
547
+ if (options.businessHours.limitDisplay) {
548
+ options.timeslotsPerDay = options.timeslotsPerHour * (options.businessHours.end - options.businessHours.start);
549
+ options.millisToDisplay = (options.businessHours.end - options.businessHours.start) * 3600000; // 60 * 60 * 1000
550
+ options.millisPerTimeslot = options.millisToDisplay / options.timeslotsPerDay;
551
+ } else {
552
+ options.timeslotsPerDay = options.timeslotsPerHour * 24;
553
+ options.millisToDisplay = MILLIS_IN_DAY;
554
+ options.millisPerTimeslot = MILLIS_IN_DAY / options.timeslotsPerDay;
555
+ }
556
+ },
557
+
558
+ /*
559
+ * Resize the calendar scrollable height based on the provided function in options.
560
+ */
561
+ _resizeCalendar: function() {
562
+ var options = this.options;
563
+ if (options && $.isFunction(options.height)) {
564
+ var calendarHeight = options.height(this.element);
565
+ var headerHeight = this.element.find('.wc-header').outerHeight();
566
+ var navHeight = this.element.find('.wc-toolbar').outerHeight();
567
+ var scrollContainerHeight = Math.max(calendarHeight - navHeight - headerHeight, options.minBodyHeight);
568
+ var timeslotHeight = this.element.find('.wc-time-slots').outerHeight();
569
+ this.element.find('.wc-scrollable-grid').height(scrollContainerHeight);
570
+ if (timeslotHeight <= scrollContainerHeight) {
571
+ this.element.find('.wc-scrollbar-shim').width(0);
572
+ }
573
+ this._trigger('resize', this.element);
574
+ }
575
+ },
576
+
577
+ _findScrollBarWidth: function() {
578
+ var parent = $('<div style="width:50px;height:50px;overflow:auto"><div/></div>').appendTo('body');
579
+ var child = parent.children();
580
+ var width = child.innerWidth() - child.height(99).innerWidth();
581
+ parent.remove();
582
+ return width || /* default to 16 that is the average */ 16;
583
+ },
584
+
585
+ /*
586
+ * configure calendar interaction events that are able to use event
587
+ * delegation for greater efficiency
588
+ */
589
+ _setupEventDelegation: function() {
590
+ var self = this;
591
+ var options = this.options;
592
+
593
+ this.element.click(function(event) {
594
+ var $target = $(event.target),
595
+ freeBusyManager;
596
+
597
+ // click is disabled
598
+ if ($target.data('preventClick')) {
599
+ return;
600
+ }
601
+
602
+ var $calEvent = $target.hasClass('wc-cal-event') ?
603
+ $target :
604
+ $target.parents('.wc-cal-event');
605
+ if (!$calEvent.length || !$calEvent.data('calEvent')) {
606
+ return;
607
+ }
608
+
609
+ freeBusyManager = self.getFreeBusyManagerForEvent($calEvent.data('calEvent'));
610
+
611
+ if (options.allowEventDelete && $target.hasClass('wc-cal-event-delete')) {
612
+ options.eventDelete($calEvent.data('calEvent'), $calEvent, freeBusyManager, self.element, event);
613
+ } else {
614
+ options.eventClick($calEvent.data('calEvent'), $calEvent, freeBusyManager, self.element, event);
615
+ }
616
+ }).mouseover(function(event) {
617
+ var $target = $(event.target);
618
+ var $calEvent = $target.hasClass('wc-cal-event') ?
619
+ $target :
620
+ $target.parents('.wc-cal-event');
621
+
622
+ if (!$calEvent.length || !$calEvent.data('calEvent')) {
623
+ return;
624
+ }
625
+
626
+ if (self._isDraggingOrResizing($calEvent)) {
627
+ return;
628
+ }
629
+
630
+ options.eventMouseover($calEvent.data('calEvent'), $calEvent, event);
631
+ }).mouseout(function(event) {
632
+ var $target = $(event.target);
633
+ var $calEvent = $target.hasClass('wc-cal-event') ?
634
+ $target :
635
+ $target.parents('.wc-cal-event');
636
+
637
+ if (!$calEvent.length || !$calEvent.data('calEvent')) {
638
+ return;
639
+ }
640
+
641
+ if (self._isDraggingOrResizing($calEvent)) {
642
+ return;
643
+ }
644
+
645
+ options.eventMouseout($calEvent.data('calEvent'), $calEvent, event);
646
+ });
647
+ },
648
+
649
+ /**
650
+ * check if a ui draggable or resizable is currently being dragged or
651
+ * resized.
652
+ */
653
+ _isDraggingOrResizing: function($target) {
654
+ return $target.hasClass('ui-draggable-dragging') ||
655
+ $target.hasClass('ui-resizable-resizing');
656
+ },
657
+
658
+ /*
659
+ * Render the main calendar layout
660
+ */
661
+ _renderCalendar: function() {
662
+ var $calendarContainer, $weekDayColumns;
663
+ var self = this;
664
+ var options = this.options;
665
+
666
+ $calendarContainer = $('<div class=\"ui-widget wc-container\">').appendTo(self.element);
667
+
668
+ //render the different parts
669
+ // nav links
670
+ self._renderCalendarButtons($calendarContainer);
671
+ // header
672
+ self._renderCalendarHeader($calendarContainer);
673
+ // body
674
+ self._renderCalendarBody($calendarContainer);
675
+
676
+ $weekDayColumns = $calendarContainer.find('.wc-day-column-inner');
677
+ $weekDayColumns.each(function(i, val) {
678
+ if (!options.readonly) {
679
+ self._addDroppableToWeekDay($(this));
680
+ if (options.allowEventCreation) {
681
+ self._setupEventCreationForWeekDay($(this));
682
+ }
683
+ }
684
+ });
685
+ },
686
+
687
+ /**
688
+ * render the nav buttons on top of the calendar
689
+ */
690
+ _renderCalendarButtons: function($calendarContainer) {
691
+ var self = this, options = this.options;
692
+ if ( !options.showHeader ) return;
693
+ if (options.buttons) {
694
+ var calendarNavHtml = '';
695
+
696
+ calendarNavHtml += '<div class=\"ui-widget-header wc-toolbar\">';
697
+ calendarNavHtml += '<div class=\"wc-display\"></div>';
698
+ calendarNavHtml += '<div class=\"wc-nav\">';
699
+ calendarNavHtml += '<button class=\"wc-prev\">' + options.buttonText.lastWeek + '</button>';
700
+ calendarNavHtml += '<button class=\"wc-today\">' + options.buttonText.today + '</button>';
701
+ calendarNavHtml += '<button class=\"wc-next\">' + options.buttonText.nextWeek + '</button>';
702
+ calendarNavHtml += '</div>';
703
+ calendarNavHtml += '<h1 class=\"wc-title\"></h1>';
704
+ calendarNavHtml += '</div>';
705
+
706
+ $(calendarNavHtml).appendTo($calendarContainer);
707
+
708
+ $calendarContainer.find('.wc-nav .wc-today')
709
+ .button({
710
+ icons: {primary: 'ui-icon-home'}})
711
+ .click(function() {
712
+ self.today();
713
+ return false;
714
+ });
715
+
716
+ $calendarContainer.find('.wc-nav .wc-prev')
717
+ .button({
718
+ text: false,
719
+ icons: {primary: 'ui-icon-seek-prev'}})
720
+ .click(function() {
721
+ self.element.weekCalendar('prev');
722
+ return false;
723
+ });
724
+
725
+ $calendarContainer.find('.wc-nav .wc-next')
726
+ .button({
727
+ text: false,
728
+ icons: {primary: 'ui-icon-seek-next'}})
729
+ .click(function() {
730
+ self.element.weekCalendar('next');
731
+ return false;
732
+ });
733
+
734
+ // now add buttons to switch display
735
+ if (this.options.switchDisplay && $.isPlainObject(this.options.switchDisplay)) {
736
+ var $container = $calendarContainer.find('.wc-display');
737
+ $.each(this.options.switchDisplay, function(label, option) {
738
+ var _id = 'wc-switch-display-' + option;
739
+ var _input = $('<input type="radio" id="' + _id + '" name="wc-switch-display" class="wc-switch-display"/>');
740
+ var _label = $('<label for="' + _id + '"></label>');
741
+ _label.html(label);
742
+ _input.val(option);
743
+ if (parseInt(self.options.daysToShow, 10) === parseInt(option, 10)) {
744
+ _input.attr('checked', 'checked');
745
+ }
746
+ $container
747
+ .append(_input)
748
+ .append(_label);
749
+ });
750
+ $container.find('input').change(function() {
751
+ self.setDaysToShow(parseInt($(this).val(), 10));
752
+ });
753
+ }
754
+ $calendarContainer.find('.wc-nav, .wc-display').buttonset();
755
+ var _height = $calendarContainer.find('.wc-nav').outerHeight();
756
+ $calendarContainer.find('.wc-title')
757
+ .height(_height)
758
+ .css('line-height', _height + 'px');
759
+ }else{
760
+ var calendarNavHtml = '';
761
+ calendarNavHtml += '<div class=\"ui-widget-header wc-toolbar\">';
762
+ calendarNavHtml += '<h1 class=\"wc-title\"></h1>';
763
+ calendarNavHtml += '</div>';
764
+ $(calendarNavHtml).appendTo($calendarContainer);
765
+
766
+ }
767
+ },
768
+
769
+ /**
770
+ * render the calendar header, including date and user header
771
+ */
772
+ _renderCalendarHeader: function($calendarContainer) {
773
+ var self = this, options = this.options,
774
+ showAsSeparatedUser = options.showAsSeparateUsers && options.users && options.users.length,
775
+ rowspan = '', colspan = '', calendarHeaderHtml;
776
+
777
+ if (showAsSeparatedUser) {
778
+ rowspan = ' rowspan=\"2\"';
779
+ colspan = ' colspan=\"' + options.users.length + '\" ';
780
+ }
781
+
782
+ //first row
783
+ calendarHeaderHtml = '<div class=\"ui-widget-content wc-header\">';
784
+ calendarHeaderHtml += '<table><tbody><tr><td class=\"wc-time-column-header\" style=\"width:44px\"></td>';
785
+ for (var i = 1; i <= options.daysToShow; i++) {
786
+ calendarHeaderHtml += '<td class=\"wc-day-column-header wc-day-' + i + '\"' + colspan + '></td>';
787
+ }
788
+ calendarHeaderHtml += '<td class=\"wc-scrollbar-shim\"' + rowspan + '></td></tr>';
789
+
790
+ //users row
791
+ if (showAsSeparatedUser) {
792
+ calendarHeaderHtml += '<tr><td class=\"wc-time-column-header\"></td>';
793
+ var uLength = options.users.length,
794
+ _headerClass = '';
795
+
796
+ for (var i = 1; i <= options.daysToShow; i++) {
797
+ for (var j = 0; j < uLength; j++) {
798
+ _headerClass = [];
799
+ if (j == 0) {
800
+ _headerClass.push('wc-day-column-first');
801
+ }
802
+ if (j == uLength - 1) {
803
+ _headerClass.push('wc-day-column-last');
804
+ }
805
+ if (!_headerClass.length) {
806
+ _headerClass = 'wc-day-column-middle';
807
+ }
808
+ else {
809
+ _headerClass = _headerClass.join(' ');
810
+ }
811
+ calendarHeaderHtml += '<td class=\"' + _headerClass + ' wc-user-header wc-day-' + i + ' wc-user-' + self._getUserIdFromIndex(j) + '\">';
812
+ // calendarHeaderHtml+= "<div class=\"wc-user-header wc-day-" + i + " wc-user-" + self._getUserIdFromIndex(j) +"\" >";
813
+ calendarHeaderHtml += self._getUserName(j);
814
+ // calendarHeaderHtml+= "</div>";
815
+ calendarHeaderHtml += '</td>';
816
+ }
817
+ }
818
+ calendarHeaderHtml += '</tr>';
819
+ }
820
+ //close the header
821
+ calendarHeaderHtml += '</tbody></table></div>';
822
+
823
+ $(calendarHeaderHtml).appendTo($calendarContainer);
824
+ },
825
+
826
+ /**
827
+ * render the calendar body.
828
+ * Calendar body is composed of several distinct parts.
829
+ * Each part is displayed in a separated row to ease rendering.
830
+ * for further explanations, see each part rendering function.
831
+ */
832
+ _renderCalendarBody: function($calendarContainer) {
833
+ var self = this, options = this.options,
834
+ showAsSeparatedUser = options.showAsSeparateUsers && options.users && options.users.length,
835
+ $calendarBody, $calendarTableTbody;
836
+ // create the structure
837
+ $calendarBody = '<div class=\"wc-scrollable-grid\">';
838
+ $calendarBody += '<table class=\"wc-time-slots\">';
839
+ $calendarBody += '<tbody>';
840
+ $calendarBody += '</tbody>';
841
+ $calendarBody += '</table>';
842
+ $calendarBody += '</div>';
843
+ $calendarBody = $($calendarBody);
844
+ $calendarTableTbody = $calendarBody.find('tbody');
845
+
846
+ self._renderCalendarBodyTimeSlots($calendarTableTbody);
847
+ self._renderCalendarBodyOddEven($calendarTableTbody);
848
+ self._renderCalendarBodyFreeBusy($calendarTableTbody);
849
+ self._renderCalendarBodyEvents($calendarTableTbody);
850
+
851
+ $calendarBody.appendTo($calendarContainer);
852
+
853
+ //set the column height
854
+ $calendarContainer.find('.wc-full-height-column').height(options.timeslotHeight * options.timeslotsPerDay);
855
+ //set the timeslot height
856
+ $calendarContainer.find('.wc-time-slot').height(options.timeslotHeight - 1); //account for border
857
+ //init the time row header height
858
+ /**
859
+ TODO if total height for an hour is less than 11px, there is a display problem.
860
+ Find a way to handle it
861
+ */
862
+ $calendarContainer.find('.wc-time-header-cell').css({
863
+ height: (options.timeslotHeight * options.timeslotsPerHour) - 11,
864
+ padding: 5
865
+ });
866
+ //add the user data to every impacted column
867
+ if (showAsSeparatedUser) {
868
+ for (var i = 0, uLength = options.users.length; i < uLength; i++) {
869
+ $calendarContainer.find('.wc-user-' + self._getUserIdFromIndex(i))
870
+ .data('wcUser', options.users[i])
871
+ .data('wcUserIndex', i)
872
+ .data('wcUserId', self._getUserIdFromIndex(i));
873
+ }
874
+ }
875
+ },
876
+
877
+ /**
878
+ * render the timeslots separation
879
+ */
880
+ _renderCalendarBodyTimeSlots: function($calendarTableTbody) {
881
+ var options = this.options,
882
+ renderRow, i, j,
883
+ showAsSeparatedUser = options.showAsSeparateUsers && options.users && options.users.length,
884
+ start = (options.businessHours.limitDisplay ? options.businessHours.start : 0),
885
+ end = (options.businessHours.limitDisplay ? options.businessHours.end : 24),
886
+ rowspan = 1;
887
+
888
+ //calculate the rowspan
889
+ if (options.displayOddEven) { rowspan += 1; }
890
+ if (options.displayFreeBusys) { rowspan += 1; }
891
+ if (rowspan > 1) {
892
+ rowspan = ' rowspan=\"' + rowspan + '\"';
893
+ }
894
+ else {
895
+ rowspan = '';
896
+ }
897
+
898
+ renderRow = '<tr class=\"wc-grid-row-timeslot\">';
899
+ renderRow += '<td class=\"wc-grid-timeslot-header\"' + rowspan + '></td>';
900
+ renderRow += '<td colspan=\"' + options.daysToShow * (showAsSeparatedUser ? options.users.length : 1) + '\">';
901
+ renderRow += '<div class=\"wc-no-height-wrapper wc-time-slot-wrapper\">';
902
+ renderRow += '<div class=\"wc-time-slots\">';
903
+
904
+ for (i = start; i < end; i++) {
905
+ for (j = 0; j < options.timeslotsPerHour - 1; j++) {
906
+ renderRow += '<div class=\"wc-time-slot\"></div>';
907
+ }
908
+ renderRow += '<div class=\"wc-time-slot wc-hour-end\"></div>';
909
+ }
910
+
911
+ renderRow += '</div>';
912
+ renderRow += '</div>';
913
+ renderRow += '</td>';
914
+ renderRow += '</tr>';
915
+
916
+ $(renderRow).appendTo($calendarTableTbody);
917
+ },
918
+
919
+ /**
920
+ * render the odd even columns
921
+ */
922
+ _renderCalendarBodyOddEven: function($calendarTableTbody) {
923
+ if (this.options.displayOddEven) {
924
+ var options = this.options,
925
+ renderRow = '<tr class=\"wc-grid-row-oddeven\">',
926
+ showAsSeparatedUser = options.showAsSeparateUsers && options.users && options.users.length,
927
+ oddEven,
928
+ // let's take advantage of the jquery ui framework
929
+ oddEvenClasses = {'odd': 'wc-column-odd', 'even': 'ui-state-hover wc-column-even'};
930
+
931
+ //now let's display oddEven placeholders
932
+ for (var i = 1; i <= options.daysToShow; i++) {
933
+ if (!showAsSeparatedUser) {
934
+ oddEven = (oddEven == 'odd' ? 'even' : 'odd');
935
+ renderRow += '<td class=\"wc-day-column day-' + i + '\">';
936
+ renderRow += '<div class=\"wc-no-height-wrapper wc-oddeven-wrapper\">';
937
+ renderRow += '<div class=\"wc-full-height-column ' + oddEvenClasses[oddEven] + '\"></div>';
938
+ renderRow += '</div>';
939
+ renderRow += '</td>';
940
+ }
941
+ else {
942
+ var uLength = options.users.length;
943
+ for (var j = 0; j < uLength; j++) {
944
+ oddEven = (oddEven == 'odd' ? 'even' : 'odd');
945
+ renderRow += '<td class=\"wc-day-column day-' + i + '\">';
946
+ renderRow += '<div class=\"wc-no-height-wrapper wc-oddeven-wrapper\">';
947
+ renderRow += '<div class=\"wc-full-height-column ' + oddEvenClasses[oddEven] + '\" ></div>';
948
+ renderRow += '</div>';
949
+ renderRow += '</td>';
950
+ }
951
+ }
952
+ }
953
+ renderRow += '</tr>';
954
+
955
+ $(renderRow).appendTo($calendarTableTbody);
956
+ }
957
+ },
958
+
959
+ /**
960
+ * render the freebusy placeholders
961
+ */
962
+ _renderCalendarBodyFreeBusy: function($calendarTableTbody) {
963
+ if (this.options.displayFreeBusys) {
964
+ var self = this, options = this.options,
965
+ renderRow = '<tr class=\"wc-grid-row-freebusy\">',
966
+ showAsSeparatedUser = options.showAsSeparateUsers && options.users && options.users.length;
967
+ renderRow += '</td>';
968
+
969
+ //now let's display freebusy placeholders
970
+ for (var i = 1; i <= options.daysToShow; i++) {
971
+ if (options.displayFreeBusys) {
972
+ if (!showAsSeparatedUser) {
973
+ renderRow += '<td class=\"wc-day-column day-' + i + '\">';
974
+ renderRow += '<div class=\"wc-no-height-wrapper wc-freebusy-wrapper\">';
975
+ renderRow += '<div class=\"wc-full-height-column wc-column-freebusy wc-day-' + i + '\"></div>';
976
+ renderRow += '</div>';
977
+ renderRow += '</td>';
978
+ }
979
+ else {
980
+ var uLength = options.users.length;
981
+ for (var j = 0; j < uLength; j++) {
982
+ renderRow += '<td class=\"wc-day-column day-' + i + '\">';
983
+ renderRow += '<div class=\"wc-no-height-wrapper wc-freebusy-wrapper\">';
984
+ renderRow += '<div class=\"wc-full-height-column wc-column-freebusy wc-day-' + i;
985
+ renderRow += ' wc-user-' + self._getUserIdFromIndex(j) + '\">';
986
+ renderRow += '</div>';
987
+ renderRow += '</div>';
988
+ renderRow += '</td>';
989
+ }
990
+ }
991
+ }
992
+ }
993
+
994
+ renderRow += '</tr>';
995
+
996
+ $(renderRow).appendTo($calendarTableTbody);
997
+ }
998
+ },
999
+
1000
+ /**
1001
+ * render the calendar body for event placeholders
1002
+ */
1003
+ _renderCalendarBodyEvents: function($calendarTableTbody) {
1004
+ var self = this, options = this.options,
1005
+ renderRow,
1006
+ showAsSeparatedUser = options.showAsSeparateUsers && options.users && options.users.length,
1007
+ start = (options.businessHours.limitDisplay ? options.businessHours.start : 0),
1008
+ end = (options.businessHours.limitDisplay ? options.businessHours.end : 24);
1009
+ renderRow = '<tr class=\"wc-grid-row-events\">';
1010
+ renderRow += '<td class=\"wc-grid-timeslot-header\">';
1011
+ for (var i = start; i < end; i++) {
1012
+ var bhClass = (options.businessHours.start <= i && options.businessHours.end > i) ? 'ui-state-active wc-business-hours' : 'ui-state-default';
1013
+ renderRow += '<div class=\"wc-hour-header ' + bhClass + '\">';
1014
+ if (options.use24Hour) {
1015
+ renderRow += '<div class=\"wc-time-header-cell\">' + self._24HourForIndex(i) + '</div>';
1016
+ }
1017
+ else {
1018
+ renderRow += '<div class=\"wc-time-header-cell\">' + self._hourForIndex(i) + '<span class=\"wc-am-pm\">' + self._amOrPm(i) + '</span></div>';
1019
+ }
1020
+ renderRow += '</div>';
1021
+ }
1022
+ renderRow += '</td>';
1023
+
1024
+ //now let's display events placeholders
1025
+ var _columnBaseClass = 'ui-state-default wc-day-column';
1026
+ for (var i = 1; i <= options.daysToShow; i++) {
1027
+ if (!showAsSeparatedUser) {
1028
+ renderRow += '<td class=\"' + _columnBaseClass + ' wc-day-column-first wc-day-column-last day-' + i + '\">';
1029
+ renderRow += '<div class=\"wc-full-height-column wc-day-column-inner day-' + i + '\"></div>';
1030
+ renderRow += '</td>';
1031
+ }
1032
+ else {
1033
+ var uLength = options.users.length;
1034
+ var columnclass;
1035
+ for (var j = 0; j < uLength; j++) {
1036
+ columnclass = [];
1037
+ if (j == 0) {
1038
+ columnclass.push('wc-day-column-first');
1039
+ }
1040
+ if (j == uLength - 1) {
1041
+ columnclass.push('wc-day-column-last');
1042
+ }
1043
+ if (!columnclass.length) {
1044
+ columnclass = 'wc-day-column-middle';
1045
+ }
1046
+ else {
1047
+ columnclass = columnclass.join(' ');
1048
+ }
1049
+ renderRow += '<td class=\"' + _columnBaseClass + ' ' + columnclass + ' day-' + i + '\">';
1050
+ renderRow += '<div class=\"wc-full-height-column wc-day-column-inner day-' + i;
1051
+ renderRow += ' wc-user-' + self._getUserIdFromIndex(j) + '\">';
1052
+ renderRow += '</div>';
1053
+ renderRow += '</td>';
1054
+ }
1055
+ }
1056
+ }
1057
+
1058
+ renderRow += '</tr>';
1059
+
1060
+ $(renderRow).appendTo($calendarTableTbody);
1061
+ },
1062
+
1063
+ /*
1064
+ * setup mouse events for capturing new events
1065
+ */
1066
+ _setupEventCreationForWeekDay: function($weekDay) {
1067
+ var self = this;
1068
+ var options = this.options;
1069
+ $weekDay.mousedown(function(event) {
1070
+ var $target = $(event.target);
1071
+ if ($target.hasClass('wc-day-column-inner')) {
1072
+
1073
+ var $newEvent = $('<div class=\"wc-cal-event wc-new-cal-event wc-new-cal-event-creating\"></div>');
1074
+
1075
+ $newEvent.css({lineHeight: (options.timeslotHeight - 2) + 'px', fontSize: (options.timeslotHeight / 2) + 'px'});
1076
+ $target.append($newEvent);
1077
+
1078
+ var columnOffset = $target.offset().top;
1079
+ var clickY = event.pageY - columnOffset;
1080
+ var clickYRounded = (clickY - (clickY % options.timeslotHeight)) / options.timeslotHeight;
1081
+ var topPosition = clickYRounded * options.timeslotHeight;
1082
+ $newEvent.css({top: topPosition});
1083
+
1084
+ if (!options.preventDragOnEventCreation) {
1085
+ $target.bind('mousemove.newevent', function(event) {
1086
+ $newEvent.show();
1087
+ $newEvent.addClass('ui-resizable-resizing');
1088
+ var height = Math.round(event.pageY - columnOffset - topPosition);
1089
+ var remainder = height % options.timeslotHeight;
1090
+ //snap to closest timeslot
1091
+ if (remainder < 0) {
1092
+ var useHeight = height - remainder;
1093
+ $newEvent.css('height', useHeight < options.timeslotHeight ? options.timeslotHeight : useHeight);
1094
+ } else {
1095
+ $newEvent.css('height', height + (options.timeslotHeight - remainder));
1096
+ }
1097
+ }).mouseup(function() {
1098
+ $target.unbind('mousemove.newevent');
1099
+ $newEvent.addClass('ui-corner-all');
1100
+ });
1101
+ }
1102
+ }
1103
+
1104
+ }).mouseup(function(event) {
1105
+ var $target = $(event.target);
1106
+
1107
+ var $weekDay = $target.closest('.wc-day-column-inner');
1108
+ var $newEvent = $weekDay.find('.wc-new-cal-event-creating');
1109
+
1110
+ if ($newEvent.length) {
1111
+ var createdFromSingleClick = !$newEvent.hasClass('ui-resizable-resizing');
1112
+
1113
+ //if even created from a single click only, default height
1114
+ if (createdFromSingleClick) {
1115
+ $newEvent.css({height: options.timeslotHeight * options.defaultEventLength}).show();
1116
+ }
1117
+ var top = parseInt($newEvent.css('top'));
1118
+ var eventDuration = self._getEventDurationFromPositionedEventElement($weekDay, $newEvent, top);
1119
+
1120
+ $newEvent.remove();
1121
+ var newCalEvent = {start: eventDuration.start, end: eventDuration.end, title: options.newEventText};
1122
+ var showAsSeparatedUser = options.showAsSeparateUsers && options.users && options.users.length;
1123
+
1124
+ if (showAsSeparatedUser) {
1125
+ newCalEvent = self._setEventUserId(newCalEvent, $weekDay.data('wcUserId'));
1126
+ }
1127
+ else if (!options.showAsSeparateUsers && options.users && options.users.length == 1) {
1128
+ newCalEvent = self._setEventUserId(newCalEvent, self._getUserIdFromIndex(0));
1129
+ }
1130
+
1131
+ var freeBusyManager = self.getFreeBusyManagerForEvent(newCalEvent);
1132
+
1133
+ var $renderedCalEvent = self._renderEvent(newCalEvent, $weekDay);
1134
+
1135
+ if (!options.allowCalEventOverlap) {
1136
+ self._adjustForEventCollisions($weekDay, $renderedCalEvent, newCalEvent, newCalEvent);
1137
+ self._positionEvent($weekDay, $renderedCalEvent);
1138
+ } else {
1139
+ self._adjustOverlappingEvents($weekDay);
1140
+ }
1141
+
1142
+ var proceed = self._trigger('beforeEventNew', event, {
1143
+ 'calEvent': newCalEvent,
1144
+ 'createdFromSingleClick': createdFromSingleClick,
1145
+ 'calendar': self.element
1146
+ });
1147
+ if (proceed) {
1148
+ options.eventNew(newCalEvent, $renderedCalEvent, freeBusyManager, self.element, event);
1149
+ }
1150
+ else {
1151
+ $($renderedCalEvent).remove();
1152
+ }
1153
+ }
1154
+ });
1155
+ },
1156
+
1157
+ /*
1158
+ * load calendar events for the week based on the date provided
1159
+ */
1160
+ _loadCalEvents: function(dateWithinWeek) {
1161
+
1162
+ var date, weekStartDate, weekEndDate, $weekDayColumns;
1163
+ var self = this;
1164
+ var options = this.options;
1165
+ date = this._fixMinMaxDate(dateWithinWeek || options.date);
1166
+ // if date is not provided
1167
+ // or was not set
1168
+ // or is different than old one
1169
+ if ((!date || !date.getTime) ||
1170
+ (!options.date || !options.date.getTime) ||
1171
+ date.getTime() != options.date.getTime()
1172
+ ) {
1173
+ // trigger the changedate event
1174
+ this._trigger('changedate', this.element, date);
1175
+ }
1176
+ this.options.date = date;
1177
+ weekStartDate = self._dateFirstDayOfWeek(date);
1178
+ weekEndDate = self._dateLastMilliOfWeek(date);
1179
+
1180
+ options.calendarBeforeLoad(self.element);
1181
+
1182
+ self.element.data('startDate', weekStartDate);
1183
+ self.element.data('endDate', weekEndDate);
1184
+
1185
+ $weekDayColumns = self.element.find('.wc-day-column-inner');
1186
+
1187
+ self._updateDayColumnHeader($weekDayColumns);
1188
+
1189
+ //load events by chosen means
1190
+ if (typeof options.data == 'string') {
1191
+ if (options.loading) {
1192
+ options.loading(true);
1193
+ }
1194
+ if (_currentAjaxCall) {
1195
+ // first abort current request.
1196
+ if (!_jQuery14OrLower) {
1197
+ _currentAjaxCall.abort();
1198
+ } else {
1199
+ // due to the fact that jquery 1.4 does not detect a request was
1200
+ // aborted, we need to replace the onreadystatechange and
1201
+ // execute the "complete" callback.
1202
+ _currentAjaxCall.onreadystatechange = null;
1203
+ _currentAjaxCall.abort();
1204
+ _currentAjaxCall = null;
1205
+ if (options.loading) {
1206
+ options.loading(false);
1207
+ }
1208
+ }
1209
+ }
1210
+ var jsonOptions = self._getJsonOptions();
1211
+ jsonOptions[options.startParam || 'start'] = Math.round(weekStartDate.getTime() / 1000);
1212
+ jsonOptions[options.endParam || 'end'] = Math.round(weekEndDate.getTime() / 1000);
1213
+ _currentAjaxCall = $.ajax({
1214
+ url: options.data,
1215
+ data: jsonOptions,
1216
+ dataType: 'json',
1217
+ error: function(XMLHttpRequest, textStatus, errorThrown) {
1218
+ // only prevent error with jQuery 1.5
1219
+ // see issue #34. thanks to dapplebeforedawn
1220
+ // (https://github.com/themouette/jquery-week-calendar/issues#issue/34)
1221
+ // for 1.5+, aborted request mean errorThrown == 'abort'
1222
+ // for prior version it means !errorThrown && !XMLHttpRequest.status
1223
+ // fixes #55
1224
+ if (errorThrown != 'abort' && XMLHttpRequest.status != 0) {
1225
+ alert('unable to get data, error:' + textStatus);
1226
+ }
1227
+ },
1228
+ success: function(data) {
1229
+ self._renderEvents(data, $weekDayColumns);
1230
+ },
1231
+ complete: function() {
1232
+ _currentAjaxCall = null;
1233
+ if (options.loading) {
1234
+ options.loading(false);
1235
+ }
1236
+ }
1237
+ });
1238
+ }
1239
+ else if ($.isFunction(options.data)) {
1240
+ options.data(weekStartDate, weekEndDate,
1241
+ function(data) {
1242
+ self._renderEvents(data, $weekDayColumns);
1243
+ if ($('.wc-hourline', self.element).length) {
1244
+ self._scrollToHour(new Date().getHours() + 1, true);
1245
+ } else {
1246
+ if (data.events.length) {
1247
+ self._scrollToHour(data.events[0].start.getHours() + 1, true);
1248
+ } else if (data.freebusys.length) {
1249
+ self._scrollToHour(data.freebusys[0].start.getHours() + 1, true);
1250
+ }
1251
+ }
1252
+ });
1253
+ }
1254
+ else if (options.data) {
1255
+ self._renderEvents(options.data, $weekDayColumns);
1256
+ }
1257
+
1258
+ self._disableTextSelect($weekDayColumns);
1259
+ },
1260
+
1261
+ /**
1262
+ * Draws a thin line which indicates the current time.
1263
+ */
1264
+ _drawCurrentHourLine: function() {
1265
+ var d = new Date(),
1266
+ options = this.options,
1267
+ businessHours = options.businessHours;
1268
+
1269
+ // first, we remove the old hourline if it exists
1270
+ $('.wc-hourline', this.element).remove();
1271
+
1272
+ // the line does not need to be displayed
1273
+ if (businessHours.limitDisplay && d.getHours() > businessHours.end) {
1274
+ return;
1275
+ }
1276
+
1277
+ // then we recreate it
1278
+ var paddingStart = businessHours.limitDisplay ? businessHours.start : 0;
1279
+ var nbHours = d.getHours() - paddingStart + d.getMinutes() / 60;
1280
+ var positionTop = nbHours * options.timeslotHeight * options.timeslotsPerHour;
1281
+ var lineWidth = $('.wc-scrollable-grid .wc-today', this.element).width() + 3;
1282
+
1283
+ $('.wc-scrollable-grid .wc-today', this.element).append(
1284
+ $('<div>', {
1285
+ 'class': 'wc-hourline',
1286
+ style: 'top: ' + positionTop + 'px; width: ' + lineWidth + 'px'
1287
+ })
1288
+ );
1289
+ },
1290
+
1291
+ /*
1292
+ * update the display of each day column header based on the calendar week
1293
+ */
1294
+ _updateDayColumnHeader: function($weekDayColumns) {
1295
+ var self = this;
1296
+ var options = this.options;
1297
+ var currentDay = self._cloneDate(self.element.data('startDate'));
1298
+ var showAsSeparatedUser = options.showAsSeparateUsers && options.users && options.users.length;
1299
+ var todayClass = 'ui-state-active wc-today';
1300
+
1301
+ self.element.find('.wc-header td.wc-day-column-header').each(function(i, val) {
1302
+ $(this).html(self._getHeaderDate(currentDay));
1303
+ if (self._isToday(currentDay)) {
1304
+ $(this).addClass(todayClass);
1305
+ } else {
1306
+ $(this).removeClass(todayClass);
1307
+ }
1308
+ currentDay = self._addDays(currentDay, 1);
1309
+
1310
+ });
1311
+
1312
+ currentDay = self._cloneDate(self.element.data('startDate'));
1313
+ if (showAsSeparatedUser)
1314
+ {
1315
+ self.element.find('.wc-header td.wc-user-header').each(function(i, val) {
1316
+ if (self._isToday(currentDay)) {
1317
+ $(this).addClass(todayClass);
1318
+ } else {
1319
+ $(this).removeClass(todayClass);
1320
+ }
1321
+ currentDay = ((i + 1) % options.users.length) ? currentDay : self._addDays(currentDay, 1);
1322
+ });
1323
+ }
1324
+
1325
+ currentDay = self._cloneDate(self.element.data('startDate'));
1326
+
1327
+ $weekDayColumns.each(function(i, val) {
1328
+
1329
+ $(this).data('startDate', self._cloneDate(currentDay));
1330
+ $(this).data('endDate', new Date(currentDay.getTime() + (MILLIS_IN_DAY)));
1331
+ if (self._isToday(currentDay)) {
1332
+ $(this).parent()
1333
+ .addClass(todayClass)
1334
+ .removeClass('ui-state-default');
1335
+ } else {
1336
+ $(this).parent()
1337
+ .removeClass(todayClass)
1338
+ .addClass('ui-state-default');
1339
+ }
1340
+
1341
+ if (!showAsSeparatedUser || !((i + 1) % options.users.length)) {
1342
+ currentDay = self._addDays(currentDay, 1);
1343
+ }
1344
+ });
1345
+
1346
+ //now update the freeBusy placeholders
1347
+ if (options.displayFreeBusys) {
1348
+ currentDay = self._cloneDate(self.element.data('startDate'));
1349
+ self.element.find('.wc-grid-row-freebusy .wc-column-freebusy').each(function(i, val) {
1350
+ $(this).data('startDate', self._cloneDate(currentDay));
1351
+ $(this).data('endDate', new Date(currentDay.getTime() + (MILLIS_IN_DAY)));
1352
+ if (!showAsSeparatedUser || !((i + 1) % options.users.length)) {
1353
+ currentDay = self._addDays(currentDay, 1);
1354
+ }
1355
+ });
1356
+ }
1357
+
1358
+ // now update the calendar title
1359
+ if (this.options.title) {
1360
+ var date = this.options.date,
1361
+ start = self._cloneDate(self.element.data('startDate')),
1362
+ end = self._dateLastDayOfWeek(new Date(this._cloneDate(self.element.data('endDate')).getTime() - (MILLIS_IN_DAY))),
1363
+ title = this._getCalendarTitle(),
1364
+ date_format = options.dateFormat;
1365
+
1366
+ // replace the placeholders contained in the title
1367
+ title = title.replace('%start%', self._formatDate(start, date_format));
1368
+ title = title.replace('%end%', self._formatDate(end, date_format));
1369
+ title = title.replace('%date%', self._formatDate(date, date_format));
1370
+
1371
+ $('.wc-toolbar .wc-title', self.element).html(title);
1372
+ }
1373
+ //self._clearFreeBusys();
1374
+ },
1375
+
1376
+ /**
1377
+ * Gets the calendar raw title.
1378
+ */
1379
+ _getCalendarTitle: function() {
1380
+ if ($.isFunction(this.options.title)) {
1381
+ return this.options.title(this.options.daysToShow);
1382
+ }
1383
+
1384
+ return this.options.title || '';
1385
+ },
1386
+
1387
+ /**
1388
+ * Render the events into the calendar
1389
+ */
1390
+ _renderEvents: function(data, $weekDayColumns) {
1391
+ var self = this;
1392
+ var options = this.options;
1393
+ var eventsToRender, nbRenderedEvents = 0;
1394
+
1395
+ if (data.options) {
1396
+ var updateLayout = false;
1397
+ // update options
1398
+ $.each(data.options, function(key, value) {
1399
+ if (value !== options[key]) {
1400
+ options[key] = value;
1401
+ updateLayout = updateLayout || $.ui.weekCalendar.updateLayoutOptions[key];
1402
+ }
1403
+ });
1404
+
1405
+ self._computeOptions();
1406
+
1407
+ if (updateLayout) {
1408
+ var hour = self._getCurrentScrollHour();
1409
+ self.element.empty();
1410
+ self._renderCalendar();
1411
+ $weekDayColumns = self.element.find('.wc-time-slots .wc-day-column-inner');
1412
+ self._updateDayColumnHeader($weekDayColumns);
1413
+ self._resizeCalendar();
1414
+ self._scrollToHour(hour, false);
1415
+ }
1416
+ }
1417
+ this._clearCalendar();
1418
+
1419
+ if ($.isArray(data)) {
1420
+ eventsToRender = self._cleanEvents(data);
1421
+ } else if (data.events) {
1422
+ eventsToRender = self._cleanEvents(data.events);
1423
+ self._renderFreeBusys(data);
1424
+ }
1425
+
1426
+ $.each(eventsToRender, function(i, calEvent) {
1427
+ // render a multi day event as various event :
1428
+ // thanks to http://github.com/fbeauchamp/jquery-week-calendar
1429
+ var initialStart = new Date(calEvent.start);
1430
+ var initialEnd = new Date(calEvent.end);
1431
+ var maxHour = self.options.businessHours.limitDisplay ? self.options.businessHours.end : 24;
1432
+ var minHour = self.options.businessHours.limitDisplay ? self.options.businessHours.start : 0;
1433
+ var start = new Date(initialStart);
1434
+ var startDate = self._formatDate(start, 'Ymd');
1435
+ var endDate = self._formatDate(initialEnd, 'Ymd');
1436
+ var $weekDay;
1437
+ var isMultiday = false;
1438
+
1439
+ while (startDate < endDate) {
1440
+ calEvent.start = start;
1441
+
1442
+ // end of this virual calEvent is set to the end of the day
1443
+ calEvent.end.setFullYear(start.getFullYear());
1444
+ calEvent.end.setDate(start.getDate());
1445
+ calEvent.end.setMonth(start.getMonth());
1446
+ calEvent.end.setHours(maxHour, 0, 0);
1447
+
1448
+ if (($weekDay = self._findWeekDayForEvent(calEvent, $weekDayColumns))) {
1449
+ self._renderEvent(calEvent, $weekDay);
1450
+ nbRenderedEvents += 1;
1451
+ }
1452
+
1453
+ // start is set to the begin of the new day
1454
+ start.setDate(start.getDate() + 1);
1455
+ start.setHours(minHour, 0, 0);
1456
+
1457
+ startDate = self._formatDate(start, 'Ymd');
1458
+ isMultiday = true;
1459
+ }
1460
+
1461
+ if (start <= initialEnd) {
1462
+ calEvent.start = start;
1463
+ calEvent.end = initialEnd;
1464
+
1465
+ if (((isMultiday && calEvent.start.getTime() != calEvent.end.getTime()) || !isMultiday) && ($weekDay = self._findWeekDayForEvent(calEvent, $weekDayColumns))) {
1466
+ self._renderEvent(calEvent, $weekDay);
1467
+ nbRenderedEvents += 1;
1468
+ }
1469
+ }
1470
+
1471
+ // put back the initial start date
1472
+ calEvent.start = initialStart;
1473
+ });
1474
+
1475
+ $weekDayColumns.each(function() {
1476
+ self._adjustOverlappingEvents($(this));
1477
+ });
1478
+
1479
+ options.calendarAfterLoad(self.element);
1480
+
1481
+ _hourLineTimeout && clearInterval(_hourLineTimeout);
1482
+
1483
+ if (options.hourLine) {
1484
+ self._drawCurrentHourLine();
1485
+
1486
+ _hourLineTimeout = setInterval(function() {
1487
+ self._drawCurrentHourLine();
1488
+ }, 60 * 1000); // redraw the line each minute
1489
+ }
1490
+
1491
+ !nbRenderedEvents && options.noEvents();
1492
+ },
1493
+
1494
+ /*
1495
+ * Render a specific event into the day provided. Assumes correct
1496
+ * day for calEvent date
1497
+ */
1498
+ _renderEvent: function(calEvent, $weekDay) {
1499
+ var self = this;
1500
+ var options = this.options;
1501
+ if (calEvent.start.getTime() > calEvent.end.getTime()) {
1502
+ return; // can't render a negative height
1503
+ }
1504
+
1505
+ var eventClass, eventHtml, $calEventList, $modifiedEvent;
1506
+
1507
+ eventClass = calEvent.id ? 'wc-cal-event' : 'wc-cal-event wc-new-cal-event';
1508
+ eventHtml = '<div class=\"' + eventClass + ' ui-corner-all\">';
1509
+ eventHtml += '<div class=\"wc-time ui-corner-top\"></div>';
1510
+ eventHtml += '<div class=\"wc-title\"></div></div>';
1511
+
1512
+ $weekDay.each(function() {
1513
+ var $calEvent = $(eventHtml);
1514
+ $modifiedEvent = options.eventRender(calEvent, $calEvent);
1515
+ $calEvent = $modifiedEvent ? $modifiedEvent.appendTo($(this)) : $calEvent.appendTo($(this));
1516
+ $calEvent.css({lineHeight: (options.textSize + 2) + 'px', fontSize: options.textSize + 'px'});
1517
+
1518
+ self._refreshEventDetails(calEvent, $calEvent);
1519
+ self._positionEvent($(this), $calEvent);
1520
+
1521
+ //add to event list
1522
+ if ($calEventList) {
1523
+ $calEventList = $calEventList.add($calEvent);
1524
+ }
1525
+ else {
1526
+ $calEventList = $calEvent;
1527
+ }
1528
+ });
1529
+ $calEventList.show();
1530
+
1531
+ if (!options.readonly && options.resizable(calEvent, $calEventList)) {
1532
+ self._addResizableToCalEvent(calEvent, $calEventList, $weekDay);
1533
+ }
1534
+ if (!options.readonly && options.draggable(calEvent, $calEventList)) {
1535
+ self._addDraggableToCalEvent(calEvent, $calEventList);
1536
+ }
1537
+ options.eventAfterRender(calEvent, $calEventList);
1538
+
1539
+ return $calEventList;
1540
+
1541
+ },
1542
+ addEvent: function() {
1543
+ return this._renderEvent.apply(this, arguments);
1544
+ },
1545
+
1546
+ _adjustOverlappingEvents: function($weekDay) {
1547
+ var self = this;
1548
+ if (self.options.allowCalEventOverlap) {
1549
+ var groupsList = self._groupOverlappingEventElements($weekDay);
1550
+ $.each(groupsList, function() {
1551
+ var curGroups = this;
1552
+ $.each(curGroups, function(groupIndex) {
1553
+ var curGroup = this;
1554
+
1555
+ // do we want events to be displayed as overlapping
1556
+ if (self.options.overlapEventsSeparate) {
1557
+ var newWidth = self.options.totalEventsWidthPercentInOneColumn / curGroups.length;
1558
+ var newLeft = groupIndex * newWidth;
1559
+ } else {
1560
+ // TODO what happens when the group has more than 10 elements
1561
+ var newWidth = self.options.totalEventsWidthPercentInOneColumn - ((curGroups.length - 1) * 10);
1562
+ var newLeft = groupIndex * 10;
1563
+ }
1564
+ $.each(curGroup, function() {
1565
+ // bring mouseovered event to the front
1566
+ if (!self.options.overlapEventsSeparate) {
1567
+ $(this).bind('mouseover.z-index', function() {
1568
+ var $elem = $(this);
1569
+ $.each(curGroup, function() {
1570
+ $(this).css({'z-index': '1'});
1571
+ });
1572
+ $elem.css({'z-index': '3'});
1573
+ });
1574
+ }
1575
+ $(this).css({width: newWidth + '%', left: newLeft + '%', right: 0});
1576
+ });
1577
+ });
1578
+ });
1579
+ }
1580
+ },
1581
+
1582
+
1583
+ /*
1584
+ * Find groups of overlapping events
1585
+ */
1586
+ _groupOverlappingEventElements: function($weekDay) {
1587
+ var $events = $weekDay.find('.wc-cal-event:visible');
1588
+ var sortedEvents = $events.sort(function(a, b) {
1589
+ return $(a).data('calEvent').start.getTime() - $(b).data('calEvent').start.getTime();
1590
+ });
1591
+
1592
+ var lastEndTime = new Date(0, 0, 0);
1593
+ var groups = [];
1594
+ var curGroups = [];
1595
+ var $curEvent;
1596
+ $.each(sortedEvents, function() {
1597
+ $curEvent = $(this);
1598
+ //checks, if the current group list is not empty, if the overlapping is finished
1599
+ if (curGroups.length > 0) {
1600
+ if (lastEndTime.getTime() <= $curEvent.data('calEvent').start.getTime()) {
1601
+ //finishes the current group list by adding it to the resulting list of groups and cleans it
1602
+
1603
+ groups.push(curGroups);
1604
+ curGroups = [];
1605
+ }
1606
+ }
1607
+
1608
+ //finds the first group to fill with the event
1609
+ for (var groupIndex = 0; groupIndex < curGroups.length; groupIndex++) {
1610
+ if (curGroups[groupIndex].length > 0) {
1611
+ //checks if the event starts after the end of the last event of the group
1612
+ if (curGroups[groupIndex][curGroups[groupIndex].length - 1].data('calEvent').end.getTime() <= $curEvent.data('calEvent').start.getTime()) {
1613
+ curGroups[groupIndex].push($curEvent);
1614
+ if (lastEndTime.getTime() < $curEvent.data('calEvent').end.getTime()) {
1615
+ lastEndTime = $curEvent.data('calEvent').end;
1616
+ }
1617
+ return;
1618
+ }
1619
+ }
1620
+ }
1621
+ //if not found, creates a new group
1622
+ curGroups.push([$curEvent]);
1623
+ if (lastEndTime.getTime() < $curEvent.data('calEvent').end.getTime()) {
1624
+ lastEndTime = $curEvent.data('calEvent').end;
1625
+ }
1626
+ });
1627
+ //adds the last groups in result
1628
+ if (curGroups.length > 0) {
1629
+ groups.push(curGroups);
1630
+ }
1631
+ return groups;
1632
+ },
1633
+
1634
+
1635
+ /*
1636
+ * find the weekday in the current calendar that the calEvent falls within
1637
+ */
1638
+ _findWeekDayForEvent: function(calEvent, $weekDayColumns) {
1639
+
1640
+ var $weekDay,
1641
+ options = this.options,
1642
+ showAsSeparatedUser = options.showAsSeparateUsers && options.users && options.users.length,
1643
+ user_ids = this._getEventUserId(calEvent);
1644
+
1645
+ if (!$.isArray(user_ids)) {
1646
+ user_ids = [user_ids];
1647
+ }
1648
+
1649
+ $weekDayColumns.each(function(index, curDay) {
1650
+ if ($(this).data('startDate').getTime() <= calEvent.start.getTime() &&
1651
+ $(this).data('endDate').getTime() >= calEvent.end.getTime() &&
1652
+ (!showAsSeparatedUser || $.inArray($(this).data('wcUserId'), user_ids) !== -1)
1653
+ ) {
1654
+ if ($weekDay) {
1655
+ $weekDay = $weekDay.add($(curDay));
1656
+ }
1657
+ else {
1658
+ $weekDay = $(curDay);
1659
+ }
1660
+ }
1661
+ });
1662
+
1663
+ return $weekDay;
1664
+ },
1665
+
1666
+ /*
1667
+ * update the events rendering in the calendar. Add if does not yet exist.
1668
+ */
1669
+ _updateEventInCalendar: function(calEvent) {
1670
+ var self = this;
1671
+ self._cleanEvent(calEvent);
1672
+
1673
+ if (calEvent.id) {
1674
+ self.element.find('.wc-cal-event').each(function() {
1675
+ if ($(this).data('calEvent').id === calEvent.id || $(this).hasClass('wc-new-cal-event')) {
1676
+ $(this).remove();
1677
+ // return false;
1678
+ }
1679
+ });
1680
+ }
1681
+
1682
+ var $weekDays = self._findWeekDayForEvent(calEvent, self.element.find('.wc-grid-row-events .wc-day-column-inner'));
1683
+ if ($weekDays) {
1684
+ $weekDays.each(function(index, weekDay) {
1685
+ var $weekDay = $(weekDay);
1686
+ var $calEvent = self._renderEvent(calEvent, $weekDay);
1687
+ self._adjustForEventCollisions($weekDay, $calEvent, calEvent, calEvent);
1688
+ // self._refreshEventDetails(calEvent, $calEvent);
1689
+ // self._positionEvent($weekDay, $calEvent);
1690
+ self._adjustOverlappingEvents($weekDay);
1691
+ });
1692
+ }
1693
+ },
1694
+
1695
+ /*
1696
+ * Position the event element within the weekday based on it's start / end dates.
1697
+ */
1698
+ _positionEvent: function($weekDay, $calEvent) {
1699
+ var options = this.options;
1700
+ var calEvent = $calEvent.data('calEvent');
1701
+ var pxPerMillis = $weekDay.height() / options.millisToDisplay;
1702
+ var firstHourDisplayed = options.businessHours.limitDisplay ? options.businessHours.start : 0;
1703
+ var startMillis = this._getDSTdayShift(calEvent.start).getTime() - this._getDSTdayShift(new Date(calEvent.start.getFullYear(), calEvent.start.getMonth(), calEvent.start.getDate(), firstHourDisplayed)).getTime();
1704
+ var eventMillis = this._getDSTdayShift(calEvent.end).getTime() - this._getDSTdayShift(calEvent.start).getTime();
1705
+ var pxTop = pxPerMillis * startMillis;
1706
+ var pxHeight = pxPerMillis * eventMillis;
1707
+ //var pxHeightFallback = pxPerMillis * (60 / options.timeslotsPerHour) * 60 * 1000;
1708
+ $calEvent.css({top: pxTop, height: pxHeight || (pxPerMillis * 3600000 / options.timeslotsPerHour)});
1709
+ },
1710
+
1711
+ /*
1712
+ * Determine the actual start and end times of a calevent based on it's
1713
+ * relative position within the weekday column and the starting hour of the
1714
+ * displayed calendar.
1715
+ */
1716
+ _getEventDurationFromPositionedEventElement: function($weekDay, $calEvent, top) {
1717
+ var options = this.options;
1718
+ var startOffsetMillis = options.businessHours.limitDisplay ? options.businessHours.start * 3600000 : 0;
1719
+ var start = new Date($weekDay.data('startDate').getTime() + startOffsetMillis + Math.round(top / options.timeslotHeight) * options.millisPerTimeslot);
1720
+ var end = new Date(start.getTime() + ($calEvent.height() / options.timeslotHeight) * options.millisPerTimeslot);
1721
+ return {start: this._getDSTdayShift(start, -1), end: this._getDSTdayShift(end, -1)};
1722
+ },
1723
+
1724
+ /*
1725
+ * If the calendar does not allow event overlap, adjust the start or end date if necessary to
1726
+ * avoid overlapping of events. Typically, shortens the resized / dropped event to it's max possible
1727
+ * duration based on the overlap. If no satisfactory adjustment can be made, the event is reverted to
1728
+ * it's original location.
1729
+ */
1730
+ _adjustForEventCollisions: function($weekDay, $calEvent, newCalEvent, oldCalEvent, maintainEventDuration) {
1731
+ var options = this.options;
1732
+
1733
+ if (options.allowCalEventOverlap) {
1734
+ return;
1735
+ }
1736
+ var adjustedStart, adjustedEnd;
1737
+ var self = this;
1738
+
1739
+ $weekDay.find('.wc-cal-event').not($calEvent).each(function() {
1740
+ var currentCalEvent = $(this).data('calEvent');
1741
+
1742
+ //has been dropped onto existing event overlapping the end time
1743
+ if (newCalEvent.start.getTime() < currentCalEvent.end.getTime() &&
1744
+ newCalEvent.end.getTime() >= currentCalEvent.end.getTime()) {
1745
+
1746
+ adjustedStart = currentCalEvent.end;
1747
+ }
1748
+
1749
+
1750
+ //has been dropped onto existing event overlapping the start time
1751
+ if (newCalEvent.end.getTime() > currentCalEvent.start.getTime() &&
1752
+ newCalEvent.start.getTime() <= currentCalEvent.start.getTime()) {
1753
+
1754
+ adjustedEnd = currentCalEvent.start;
1755
+ }
1756
+ //has been dropped inside existing event with same or larger duration
1757
+ if (oldCalEvent.resizable == false ||
1758
+ (newCalEvent.end.getTime() <= currentCalEvent.end.getTime() &&
1759
+ newCalEvent.start.getTime() >= currentCalEvent.start.getTime())) {
1760
+
1761
+ adjustedStart = oldCalEvent.start;
1762
+ adjustedEnd = oldCalEvent.end;
1763
+ return false;
1764
+ }
1765
+
1766
+ });
1767
+
1768
+
1769
+ newCalEvent.start = adjustedStart || newCalEvent.start;
1770
+
1771
+ if (adjustedStart && maintainEventDuration) {
1772
+ newCalEvent.end = new Date(adjustedStart.getTime() + (oldCalEvent.end.getTime() - oldCalEvent.start.getTime()));
1773
+ self._adjustForEventCollisions($weekDay, $calEvent, newCalEvent, oldCalEvent);
1774
+ } else {
1775
+ newCalEvent.end = adjustedEnd || newCalEvent.end;
1776
+ }
1777
+
1778
+
1779
+ //reset if new cal event has been forced to zero size
1780
+ if (newCalEvent.start.getTime() >= newCalEvent.end.getTime()) {
1781
+ newCalEvent.start = oldCalEvent.start;
1782
+ newCalEvent.end = oldCalEvent.end;
1783
+ }
1784
+
1785
+ $calEvent.data('calEvent', newCalEvent);
1786
+ },
1787
+
1788
+ /**
1789
+ * Add draggable capabilities to an event
1790
+ */
1791
+ _addDraggableToCalEvent: function(calEvent, $calEvent) {
1792
+ var options = this.options;
1793
+
1794
+ $calEvent.draggable({
1795
+ handle: '.wc-time',
1796
+ containment: 'div.wc-time-slots',
1797
+ snap: '.wc-day-column-inner',
1798
+ snapMode: 'inner',
1799
+ snapTolerance: options.timeslotHeight - 1,
1800
+ revert: 'invalid',
1801
+ opacity: 0.5,
1802
+ grid: [$calEvent.outerWidth() + 1, options.timeslotHeight],
1803
+ start: function(event, ui) {
1804
+ var $calEvent = ui.draggable || ui.helper;
1805
+ options.eventDrag(calEvent, $calEvent);
1806
+ }
1807
+ });
1808
+ },
1809
+
1810
+ /*
1811
+ * Add droppable capabilites to weekdays to allow dropping of calEvents only
1812
+ */
1813
+ _addDroppableToWeekDay: function($weekDay) {
1814
+ var self = this;
1815
+ var options = this.options;
1816
+ $weekDay.droppable({
1817
+ accept: '.wc-cal-event',
1818
+ drop: function(event, ui) {
1819
+ var $calEvent = ui.draggable;
1820
+ var top = Math.round(parseInt(ui.position.top));
1821
+ var eventDuration = self._getEventDurationFromPositionedEventElement($weekDay, $calEvent, top);
1822
+ var calEvent = $calEvent.data('calEvent');
1823
+ var newCalEvent = $.extend(true, {}, calEvent, {start: eventDuration.start, end: eventDuration.end});
1824
+ var showAsSeparatedUser = options.showAsSeparateUsers && options.users && options.users.length;
1825
+ if (showAsSeparatedUser) {
1826
+ // we may have dragged the event on column with a new user.
1827
+ // nice way to handle that is:
1828
+ // - get the newly dragged on user
1829
+ // - check if user is part of the event
1830
+ // - if yes, nothing changes, if not, find the old owner to remove it and add new one
1831
+ var newUserId = $weekDay.data('wcUserId');
1832
+ var userIdList = self._getEventUserId(calEvent);
1833
+ var oldUserId = $(ui.draggable.parents('.wc-day-column-inner').get(0)).data('wcUserId');
1834
+ if (!$.isArray(userIdList)) {
1835
+ userIdList = [userIdList];
1836
+ }
1837
+ if ($.inArray(newUserId, userIdList) == -1) {
1838
+ // remove old user
1839
+ var _index = $.inArray(oldUserId, userIdList);
1840
+ userIdList.splice(_index, 1);
1841
+ // add new user ?
1842
+ if ($.inArray(newUserId, userIdList) == -1) {
1843
+ userIdList.push(newUserId);
1844
+ }
1845
+ }
1846
+ newCalEvent = self._setEventUserId(newCalEvent, ((userIdList.length == 1) ? userIdList[0] : userIdList));
1847
+ }
1848
+ self._adjustForEventCollisions($weekDay, $calEvent, newCalEvent, calEvent, true);
1849
+ var $weekDayColumns = self.element.find('.wc-day-column-inner');
1850
+
1851
+ //trigger drop callback
1852
+ options.eventDrop(newCalEvent, calEvent, $calEvent);
1853
+
1854
+ var $newEvent = self._renderEvent(newCalEvent, self._findWeekDayForEvent(newCalEvent, $weekDayColumns));
1855
+ $calEvent.hide();
1856
+
1857
+ $calEvent.data('preventClick', true);
1858
+
1859
+ var $weekDayOld = self._findWeekDayForEvent($calEvent.data('calEvent'), self.element.find('.wc-time-slots .wc-day-column-inner'));
1860
+
1861
+ if ($weekDayOld.data('startDate') != $weekDay.data('startDate')) {
1862
+ self._adjustOverlappingEvents($weekDayOld);
1863
+ }
1864
+ self._adjustOverlappingEvents($weekDay);
1865
+
1866
+ setTimeout(function() {
1867
+ $calEvent.remove();
1868
+ }, 1000);
1869
+
1870
+ }
1871
+ });
1872
+ },
1873
+
1874
+ /*
1875
+ * Add resizable capabilities to a calEvent
1876
+ */
1877
+ _addResizableToCalEvent: function(calEvent, $calEvent, $weekDay) {
1878
+ var self = this;
1879
+ var options = this.options;
1880
+ $calEvent.resizable({
1881
+ grid: options.timeslotHeight,
1882
+ containment: $weekDay,
1883
+ handles: 's',
1884
+ minHeight: options.timeslotHeight,
1885
+ stop: function(event, ui) {
1886
+ var $calEvent = ui.element;
1887
+ var newEnd = new Date($calEvent.data('calEvent').start.getTime() + Math.max(1, Math.round(ui.size.height / options.timeslotHeight)) * options.millisPerTimeslot);
1888
+ if (self._needDSTdayShift($calEvent.data('calEvent').start, newEnd))
1889
+ newEnd = self._getDSTdayShift(newEnd, -1);
1890
+ var newCalEvent = $.extend(true, {}, calEvent, {start: calEvent.start, end: newEnd});
1891
+ self._adjustForEventCollisions($weekDay, $calEvent, newCalEvent, calEvent);
1892
+
1893
+ //trigger resize callback
1894
+ options.eventResize(newCalEvent, calEvent, $calEvent);
1895
+ self._refreshEventDetails(newCalEvent, $calEvent);
1896
+ self._positionEvent($weekDay, $calEvent);
1897
+ self._adjustOverlappingEvents($weekDay);
1898
+ $calEvent.data('preventClick', true);
1899
+ setTimeout(function() {
1900
+ $calEvent.removeData('preventClick');
1901
+ }, 500);
1902
+ }
1903
+ });
1904
+ $('.ui-resizable-handle', $calEvent).text('=');
1905
+ },
1906
+
1907
+ /*
1908
+ * Refresh the displayed details of a calEvent in the calendar
1909
+ */
1910
+ _refreshEventDetails: function(calEvent, $calEvent) {
1911
+ var prefix = '';
1912
+ if (!this.options.readonly &&
1913
+ this.options.allowEventDelete &&
1914
+ this.options.deletable(calEvent,$calEvent)) {
1915
+ prefix = '<div class="wc-cal-event-delete ui-icon ui-icon-close"></div>';
1916
+ }
1917
+ $calEvent.find('.wc-time').html(prefix + this.options.eventHeader(calEvent, this.element));
1918
+ $calEvent.find('.wc-title').html(this.options.eventBody(calEvent, this.element));
1919
+
1920
+ $calEvent.data('calEvent', calEvent);
1921
+ this.options.eventRefresh(calEvent, $calEvent);
1922
+ },
1923
+
1924
+ /*
1925
+ * Clear all cal events from the calendar
1926
+ */
1927
+ _clearCalendar: function() {
1928
+ this.element.find('.wc-day-column-inner div').remove();
1929
+ this._clearFreeBusys();
1930
+ },
1931
+
1932
+ /*
1933
+ * Scroll the calendar to a specific hour
1934
+ */
1935
+ _scrollToHour: function(hour, animate) {
1936
+ var self = this;
1937
+ var options = this.options;
1938
+ var $scrollable = this.element.find('.wc-scrollable-grid');
1939
+ var slot = hour;
1940
+ if (self.options.businessHours.limitDisplay) {
1941
+ if (hour <= self.options.businessHours.start) {
1942
+ slot = 0;
1943
+ } else if (hour >= self.options.businessHours.end) {
1944
+ slot = self.options.businessHours.end - self.options.businessHours.start - 1;
1945
+ } else {
1946
+ slot = hour - self.options.businessHours.start;
1947
+ }
1948
+ }
1949
+
1950
+ var $target = this.element.find('.wc-grid-timeslot-header .wc-hour-header:eq(' + slot + ')');
1951
+
1952
+ $scrollable.animate({scrollTop: 0}, 0, function() {
1953
+ var targetOffset = $target.offset().top;
1954
+ var scroll = targetOffset - $scrollable.offset().top - $target.outerHeight();
1955
+ if (animate) {
1956
+ $scrollable.animate({scrollTop: scroll}, options.scrollToHourMillis);
1957
+ }
1958
+ else {
1959
+ $scrollable.animate({scrollTop: scroll}, 0);
1960
+ }
1961
+ });
1962
+ },
1963
+
1964
+ /*
1965
+ * find the hour (12 hour day) for a given hour index
1966
+ */
1967
+ _hourForIndex: function(index) {
1968
+ if (index === 0) { //midnight
1969
+ return 12;
1970
+ } else if (index < 13) { //am
1971
+ return index;
1972
+ } else { //pm
1973
+ return index - 12;
1974
+ }
1975
+ },
1976
+
1977
+ _24HourForIndex: function(index) {
1978
+ if (index === 0) { //midnight
1979
+ return '00';
1980
+ } else if (index < 10) {
1981
+ return '0' + index;
1982
+ } else {
1983
+ return index;
1984
+ }
1985
+ },
1986
+
1987
+ _amOrPm: function(hourOfDay) {
1988
+ return hourOfDay < 12 ? BooklyL10n['AM'] : BooklyL10n['PM'];
1989
+ },
1990
+
1991
+ _isToday: function(date) {
1992
+ var clonedDate = this._cloneDate(date);
1993
+ this._clearTime(clonedDate);
1994
+ var today = new Date();
1995
+ this._clearTime(today);
1996
+ return today.getTime() === clonedDate.getTime();
1997
+ },
1998
+
1999
+ /*
2000
+ * Clean events to ensure correct format
2001
+ */
2002
+ _cleanEvents: function(events) {
2003
+ var self = this;
2004
+ $.each(events, function(i, event) {
2005
+ self._cleanEvent(event);
2006
+ });
2007
+ return events;
2008
+ },
2009
+
2010
+ /*
2011
+ * Clean specific event
2012
+ */
2013
+ _cleanEvent: function(event) {
2014
+ if (event.date) {
2015
+ event.start = event.date;
2016
+ }
2017
+ event.start = this._cleanDate(event.start);
2018
+ event.end = this._cleanDate(event.end);
2019
+ if (!event.end) {
2020
+ event.end = this._addDays(this._cloneDate(event.start), 1);
2021
+ }
2022
+ },
2023
+
2024
+ /*
2025
+ * Disable text selection of the elements in different browsers
2026
+ */
2027
+ _disableTextSelect: function($elements) {
2028
+ $elements.each(function() {
2029
+ if ($.browser.mozilla) {//Firefox
2030
+ $(this).css('MozUserSelect', 'none');
2031
+ } else if ($.browser.msie) {//IE
2032
+ $(this).bind('selectstart', function() {
2033
+ return false;
2034
+ });
2035
+ } else {//Opera, etc.
2036
+ $(this).mousedown(function() {
2037
+ return false;
2038
+ });
2039
+ }
2040
+ });
2041
+ },
2042
+
2043
+ /*
2044
+ * returns the date on the first millisecond of the week
2045
+ */
2046
+ _dateFirstDayOfWeek: function(date) {
2047
+ var self = this;
2048
+ var midnightCurrentDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
2049
+ var adjustedDate = new Date(midnightCurrentDate);
2050
+ adjustedDate.setDate(adjustedDate.getDate() - self._getAdjustedDayIndex(midnightCurrentDate));
2051
+
2052
+ return adjustedDate;
2053
+ },
2054
+
2055
+ /*
2056
+ * returns the date on the first millisecond of the last day of the week
2057
+ */
2058
+ _dateLastDayOfWeek: function(date) {
2059
+ var self = this;
2060
+ var midnightCurrentDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
2061
+ var adjustedDate = new Date(midnightCurrentDate);
2062
+ var daysToAdd = (self.options.daysToShow - 1 - self._getAdjustedDayIndex(midnightCurrentDate));
2063
+ adjustedDate.setDate(adjustedDate.getDate() + daysToAdd);
2064
+
2065
+ return adjustedDate;
2066
+ },
2067
+
2068
+ /**
2069
+ * fix the date if it is not within given options
2070
+ * minDate and maxDate
2071
+ */
2072
+ _fixMinMaxDate: function(date) {
2073
+ var minDate, maxDate;
2074
+ date = this._cleanDate(date);
2075
+
2076
+ // not less than minDate
2077
+ if (this.options.minDate) {
2078
+ minDate = this._cleanDate(this.options.minDate);
2079
+ // midnight on minDate
2080
+ minDate = new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate());
2081
+ if (date.getTime() < minDate.getTime()) {
2082
+ this._trigger('reachedmindate', this.element, date);
2083
+ }
2084
+ date = this._cleanDate(Math.max(date.getTime(), minDate.getTime()));
2085
+ }
2086
+
2087
+ // not more than maxDate
2088
+ if (this.options.maxDate) {
2089
+ maxDate = this._cleanDate(this.options.maxDate);
2090
+ // apply correction for max date if not startOnFirstDayOfWeek
2091
+ // to make sure no further date is displayed.
2092
+ // otherwise, the complement will still be shown
2093
+ if (!this._startOnFirstDayOfWeek()) {
2094
+ var day = maxDate.getDate() - this.options.daysToShow + 1;
2095
+ maxDate = new Date(maxDate.getFullYear(), maxDate.getMonth(), day);
2096
+ }
2097
+ // microsecond before midnight on maxDate
2098
+ maxDate = new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate(), 23, 59, 59, 999);
2099
+ if (date.getTime() > maxDate.getTime()) {
2100
+ this._trigger('reachedmaxdate', this.element, date);
2101
+ }
2102
+ date = this._cleanDate(Math.min(date.getTime(), maxDate.getTime()));
2103
+ }
2104
+
2105
+ return date;
2106
+ },
2107
+
2108
+ /*
2109
+ * gets the index of the current day adjusted based on options
2110
+ */
2111
+ _getAdjustedDayIndex: function(date) {
2112
+ if (!this._startOnFirstDayOfWeek()) {
2113
+ return 0;
2114
+ }
2115
+
2116
+ var midnightCurrentDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
2117
+ var currentDayOfStandardWeek = midnightCurrentDate.getDay();
2118
+ var days = [0, 1, 2, 3, 4, 5, 6];
2119
+ this._rotate(days, this._firstDayOfWeek());
2120
+ return days[currentDayOfStandardWeek];
2121
+ },
2122
+
2123
+ _firstDayOfWeek: function() {
2124
+ if ($.isFunction(this.options.firstDayOfWeek)) {
2125
+ return this.options.firstDayOfWeek(this.element);
2126
+ }
2127
+ return this.options.firstDayOfWeek;
2128
+ },
2129
+
2130
+ /*
2131
+ * returns the date on the last millisecond of the week
2132
+ */
2133
+ _dateLastMilliOfWeek: function(date) {
2134
+ var lastDayOfWeek = this._dateLastDayOfWeek(date);
2135
+ lastDayOfWeek = this._cloneDate(lastDayOfWeek);
2136
+ lastDayOfWeek.setDate(lastDayOfWeek.getDate() + 1);
2137
+ return lastDayOfWeek;
2138
+
2139
+ },
2140
+
2141
+ /*
2142
+ * Clear the time components of a date leaving the date
2143
+ * of the first milli of day
2144
+ */
2145
+ _clearTime: function(d) {
2146
+ d.setHours(0);
2147
+ d.setMinutes(0);
2148
+ d.setSeconds(0);
2149
+ d.setMilliseconds(0);
2150
+ return d;
2151
+ },
2152
+
2153
+ /*
2154
+ * add specific number of days to date
2155
+ */
2156
+ _addDays: function(d, n, keepTime) {
2157
+ d.setDate(d.getDate() + n);
2158
+ if (keepTime) {
2159
+ return d;
2160
+ }
2161
+ return this._clearTime(d);
2162
+ },
2163
+
2164
+ /*
2165
+ * Rotate an array by specified number of places.
2166
+ */
2167
+ _rotate: function(a /*array*/, p /* integer, positive integer rotate to the right, negative to the left... */) {
2168
+ for (var l = a.length, p = (Math.abs(p) >= l && (p %= l), p < 0 && (p += l), p), i, x; p; p = (Math.ceil(l / p) - 1) * p - l + (l = p)) {
2169
+ for (i = l; i > p; x = a[--i], a[i] = a[i - p], a[i - p] = x) {}
2170
+ }
2171
+ return a;
2172
+ },
2173
+
2174
+ _cloneDate: function(d) {
2175
+ return new Date(d.getTime());
2176
+ },
2177
+
2178
+ /**
2179
+ * Return a Date instance for different representations.
2180
+ * Valid representations are:
2181
+ * * timestamps
2182
+ * * Date objects
2183
+ * * textual representations (only these accepted by the Date
2184
+ * constructor)
2185
+ *
2186
+ * @return {Date} The clean date object.
2187
+ */
2188
+ _cleanDate: function(d) {
2189
+ if (typeof d === 'string') {
2190
+ // if is numeric
2191
+ if (!isNaN(Number(d))) {
2192
+ return this._cleanDate(parseInt(d, 10));
2193
+ }
2194
+
2195
+ // this is a human readable date
2196
+ return Date.parse(d) || new Date(d);
2197
+ }
2198
+
2199
+ if (typeof d == 'number') {
2200
+ return new Date(d);
2201
+ }
2202
+
2203
+ return d;
2204
+ },
2205
+
2206
+ /*
2207
+ * date formatting is adapted from
2208
+ * http://jacwright.com/projects/javascript/date_format
2209
+ */
2210
+ _formatDate: function(date, format) {
2211
+ var returnStr = '';
2212
+ for (var i = 0; i < format.length; i++) {
2213
+ var curChar = format.charAt(i);
2214
+ if (i != 0 && format.charAt(i - 1) == '\\') {
2215
+ returnStr += curChar;
2216
+ }
2217
+ else if (this._replaceChars[curChar]) {
2218
+ returnStr += this._replaceChars[curChar](date, this);
2219
+ } else if (curChar != '\\') {
2220
+ returnStr += curChar;
2221
+ }
2222
+ }
2223
+ return returnStr;
2224
+ },
2225
+
2226
+ _replaceChars: {
2227
+ // Day
2228
+ d: function(date) { return (date.getDate() < 10 ? '0' : '') + date.getDate(); },
2229
+ D: function(date, calendar) { return calendar.options.shortDays[date.getDay()]; },
2230
+ j: function(date) { return date.getDate(); },
2231
+ l: function(date, calendar) { return calendar.options.longDays[date.getDay()]; },
2232
+ N: function(date) { var _d = date.getDay(); return _d ? _d : 7; },
2233
+ S: function(date) { return (date.getDate() % 10 == 1 && date.getDate() != 11 ? 'st' : (date.getDate() % 10 == 2 && date.getDate() != 12 ? 'nd' : (date.getDate() % 10 == 3 && date.getDate() != 13 ? 'rd' : 'th'))); },
2234
+ w: function(date) { return date.getDay(); },
2235
+ z: function(date) { var d = new Date(date.getFullYear(), 0, 1); return Math.ceil((date - d) / 86400000); }, // Fixed now
2236
+ // Week
2237
+ W: function(date) { var d = new Date(date.getFullYear(), 0, 1); return Math.ceil((((date - d) / 86400000) + d.getDay() + 1) / 7); }, // Fixed now
2238
+ // Month
2239
+ F: function(date, calendar) { return calendar.options.longMonths[date.getMonth()]; },
2240
+ m: function(date) { return (date.getMonth() < 9 ? '0' : '') + (date.getMonth() + 1); },
2241
+ M: function(date, calendar) { return calendar.options.shortMonths[date.getMonth()]; },
2242
+ n: function(date) { return date.getMonth() + 1; },
2243
+ t: function(date) { var d = date; return new Date(d.getFullYear(), d.getMonth() + 1, 0).getDate() }, // Fixed now, gets #days of date
2244
+ // Year
2245
+ L: function(date) { var year = date.getFullYear(); return (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)); }, // Fixed now
2246
+ o: function(date) { var d = new Date(date.valueOf()); d.setDate(d.getDate() - ((date.getDay() + 6) % 7) + 3); return d.getFullYear();}, //Fixed now
2247
+ Y: function(date) { return date.getFullYear(); },
2248
+ y: function(date) { return ('' + date.getFullYear()).substr(2); },
2249
+ // Time
2250
+ a: function(date) { return date.getHours() < 12 ? BooklyL10n['AM'] : BooklyL10n['PM']; },
2251
+ A: function(date) { return date.getHours() < 12 ? BooklyL10n['AM'] : BooklyL10n['PM']; },
2252
+ B: function(date) { return Math.floor((((date.getUTCHours() + 1) % 24) + date.getUTCMinutes() / 60 + date.getUTCSeconds() / 3600) * 1000 / 24); }, // Fixed now
2253
+ g: function(date) { return date.getHours() % 12 || 12; },
2254
+ G: function(date) { return date.getHours(); },
2255
+ h: function(date) { return ((date.getHours() % 12 || 12) < 10 ? '0' : '') + (date.getHours() % 12 || 12); },
2256
+ H: function(date) { return (date.getHours() < 10 ? '0' : '') + date.getHours(); },
2257
+ i: function(date) { return (date.getMinutes() < 10 ? '0' : '') + date.getMinutes(); },
2258
+ s: function(date) { return (date.getSeconds() < 10 ? '0' : '') + date.getSeconds(); },
2259
+ u: function(date) { var m = date.getMilliseconds(); return (m < 10 ? '00' : (m < 100 ? '0' : '')) + m; },
2260
+ // Timezone
2261
+ e: function(date) { return 'Not Yet Supported'; },
2262
+ I: function(date) { return 'Not Yet Supported'; },
2263
+ O: function(date) { return (-date.getTimezoneOffset() < 0 ? '-' : '+') + (Math.abs(date.getTimezoneOffset() / 60) < 10 ? '0' : '') + (Math.abs(date.getTimezoneOffset() / 60)) + '00'; },
2264
+ P: function(date) { return (-date.getTimezoneOffset() < 0 ? '-' : '+') + (Math.abs(date.getTimezoneOffset() / 60) < 10 ? '0' : '') + (Math.abs(date.getTimezoneOffset() / 60)) + ':00'; }, // Fixed now
2265
+ T: function(date) { var m = date.getMonth(); date.setMonth(0); var result = date.toTimeString().replace(/^.+ \(?([^\)]+)\)?$/, '$1'); date.setMonth(m); return result;},
2266
+ Z: function(date) { return -date.getTimezoneOffset() * 60; },
2267
+ // Full Date/Time
2268
+ c: function(date, calendar) { return calendar._formatDate(date, 'Y-m-d\\TH:i:sP'); }, // Fixed now
2269
+ r: function(date, calendar) { return calendar._formatDate(date, 'D, d M Y H:i:s O'); },
2270
+ U: function(date) { return date.getTime() / 1000; }
2271
+ },
2272
+
2273
+ /* USER MANAGEMENT FUNCTIONS */
2274
+
2275
+ getUserForId: function(id) {
2276
+ return $.extend({}, this.options.users[this._getUserIndexFromId(id)]);
2277
+ },
2278
+
2279
+ /**
2280
+ * return the user name for header
2281
+ */
2282
+ _getUserName: function(index) {
2283
+ var self = this;
2284
+ var options = this.options;
2285
+ var user = options.users[index];
2286
+ if ($.isFunction(options.getUserName)) {
2287
+ return options.getUserName(user, index, self.element);
2288
+ }
2289
+ else {
2290
+ return user;
2291
+ }
2292
+ },
2293
+ /**
2294
+ * return the user id for given index
2295
+ */
2296
+ _getUserIdFromIndex: function(index) {
2297
+ var self = this;
2298
+ var options = this.options;
2299
+ if ($.isFunction(options.getUserId)) {
2300
+ return options.getUserId(options.users[index], index, self.element);
2301
+ }
2302
+ return index;
2303
+ },
2304
+ /**
2305
+ * returns the associated user index for given ID
2306
+ */
2307
+ _getUserIndexFromId: function(id) {
2308
+ var self = this;
2309
+ var options = this.options;
2310
+ for (var i = 0; i < options.users.length; i++) {
2311
+ if (self._getUserIdFromIndex(i) == id) {
2312
+ return i;
2313
+ }
2314
+ }
2315
+ return 0;
2316
+ },
2317
+ /**
2318
+ * return the user ids for given calEvent.
2319
+ * default is calEvent.userId field.
2320
+ */
2321
+ _getEventUserId: function(calEvent) {
2322
+ var self = this;
2323
+ var options = this.options;
2324
+ if (options.showAsSeparateUsers && options.users && options.users.length) {
2325
+ if ($.isFunction(options.getEventUserId)) {
2326
+ return options.getEventUserId(calEvent, self.element);
2327
+ }
2328
+ return calEvent.userId;
2329
+ }
2330
+ return [];
2331
+ },
2332
+ /**
2333
+ * sets the event user id on given calEvent
2334
+ * default is calEvent.userId field.
2335
+ */
2336
+ _setEventUserId: function(calEvent, userId) {
2337
+ var self = this;
2338
+ var options = this.options;
2339
+ if ($.isFunction(options.setEventUserId)) {
2340
+ return options.setEventUserId(userId, calEvent, self.element);
2341
+ }
2342
+ calEvent.userId = userId;
2343
+ return calEvent;
2344
+ },
2345
+ /**
2346
+ * return the user ids for given freeBusy.
2347
+ * default is freeBusy.userId field.
2348
+ */
2349
+ _getFreeBusyUserId: function(freeBusy) {
2350
+ var self = this;
2351
+ var options = this.options;
2352
+ if ($.isFunction(options.getFreeBusyUserId)) {
2353
+ return options.getFreeBusyUserId(freeBusy.getOption(), self.element);
2354
+ }
2355
+ return freeBusy.getOption('userId');
2356
+ },
2357
+
2358
+ /* FREEBUSY MANAGEMENT */
2359
+
2360
+ /**
2361
+ * ckean the free busy managers and remove all the freeBusy
2362
+ */
2363
+ _clearFreeBusys: function() {
2364
+ if (this.options.displayFreeBusys) {
2365
+ var self = this,
2366
+ options = this.options,
2367
+ $freeBusyPlaceholders = self.element.find('.wc-grid-row-freebusy .wc-column-freebusy');
2368
+ $freeBusyPlaceholders.each(function() {
2369
+ $(this).data('wcFreeBusyManager', new FreeBusyManager({
2370
+ start: self._cloneDate($(this).data('startDate')),
2371
+ end: self._cloneDate($(this).data('endDate')),
2372
+ defaultFreeBusy: options.defaultFreeBusy || {}
2373
+ }));
2374
+ });
2375
+ self.element.find('.wc-grid-row-freebusy .wc-freebusy').remove();
2376
+ }
2377
+ },
2378
+ /**
2379
+ * retrieve placeholders for given freebusy
2380
+ */
2381
+ _findWeekDaysForFreeBusy: function(freeBusy, $weekDays) {
2382
+ var $returnWeekDays,
2383
+ options = this.options,
2384
+ showAsSeparatedUser = options.showAsSeparateUsers && options.users && options.users.length,
2385
+ self = this,
2386
+ userList = self._getFreeBusyUserId(freeBusy);
2387
+ if (!$.isArray(userList)) {
2388
+ userList = userList != 'undefined' ? [userList] : [];
2389
+ }
2390
+ if (!$weekDays) {
2391
+ $weekDays = self.element.find('.wc-grid-row-freebusy .wc-column-freebusy');
2392
+ }
2393
+ $weekDays.each(function() {
2394
+ var manager = $(this).data('wcFreeBusyManager'),
2395
+ has_overlap = manager.isWithin(freeBusy.getStart()) ||
2396
+ manager.isWithin(freeBusy.getEnd()) ||
2397
+ freeBusy.isWithin(manager.getStart()) ||
2398
+ freeBusy.isWithin(manager.getEnd()),
2399
+ userId = $(this).data('wcUserId');
2400
+ if (has_overlap && (!showAsSeparatedUser || ($.inArray(userId, userList) != -1))) {
2401
+ $returnWeekDays = $returnWeekDays ? $returnWeekDays.add($(this)) : $(this);
2402
+ }
2403
+ });
2404
+ return $returnWeekDays;
2405
+ },
2406
+
2407
+ /**
2408
+ * used to render all freeBusys
2409
+ */
2410
+ _renderFreeBusys: function(freeBusys) {
2411
+ if (this.options.displayFreeBusys) {
2412
+ var self = this,
2413
+ $freeBusyPlaceholders = self.element.find('.wc-grid-row-freebusy .wc-column-freebusy'),
2414
+ freebusysToRender;
2415
+ //insert freebusys to dedicated placeholders freebusy managers
2416
+ if ($.isArray(freeBusys)) {
2417
+ freebusysToRender = self._cleanFreeBusys(freeBusys);
2418
+ } else if (freeBusys.freebusys) {
2419
+ freebusysToRender = self._cleanFreeBusys(freeBusys.freebusys);
2420
+ }
2421
+ else {
2422
+ freebusysToRender = [];
2423
+ }
2424
+
2425
+ $.each(freebusysToRender, function(index, freebusy) {
2426
+ var $placeholders = self._findWeekDaysForFreeBusy(freebusy, $freeBusyPlaceholders);
2427
+ if ($placeholders) {
2428
+ $placeholders.each(function() {
2429
+ var manager = $(this).data('wcFreeBusyManager');
2430
+ manager.insertFreeBusy(new FreeBusy(freebusy.getOption()));
2431
+ $(this).data('wcFreeBusyManager', manager);
2432
+ });
2433
+ }
2434
+ });
2435
+
2436
+ //now display freebusys on place holders
2437
+ self._refreshFreeBusys($freeBusyPlaceholders);
2438
+ }
2439
+ },
2440
+ /**
2441
+ * refresh freebusys for given placeholders
2442
+ */
2443
+ _refreshFreeBusys: function($freeBusyPlaceholders) {
2444
+ if (this.options.displayFreeBusys && $freeBusyPlaceholders) {
2445
+ var self = this,
2446
+ options = this.options,
2447
+ start = (options.businessHours.limitDisplay ? options.businessHours.start : 0),
2448
+ end = (options.businessHours.limitDisplay ? options.businessHours.end : 24);
2449
+
2450
+ $freeBusyPlaceholders.each(function() {
2451
+ var $placehoder = $(this);
2452
+ var s = self._cloneDate($placehoder.data('startDate')),
2453
+ e = self._cloneDate(s);
2454
+ s.setHours(start);
2455
+ e.setHours(end);
2456
+ $placehoder.find('.wc-freebusy').remove();
2457
+ $.each($placehoder.data('wcFreeBusyManager').getFreeBusys(s, e), function() {
2458
+ self._renderFreeBusy(this, $placehoder);
2459
+ });
2460
+ });
2461
+ }
2462
+ },
2463
+ /**
2464
+ * render a freebusy item on dedicated placeholders
2465
+ */
2466
+ _renderFreeBusy: function(freeBusy, $freeBusyPlaceholder) {
2467
+ if (this.options.displayFreeBusys) {
2468
+ var self = this,
2469
+ options = this.options,
2470
+ freeBusyHtml = '<div class="wc-freebusy"></div>';
2471
+
2472
+ var $fb = $(freeBusyHtml);
2473
+ $fb.data('wcFreeBusy', new FreeBusy(freeBusy.getOption()));
2474
+ this._positionFreeBusy($freeBusyPlaceholder, $fb);
2475
+ $fb = options.freeBusyRender(freeBusy.getOption(), $fb, self.element);
2476
+ if ($fb) {
2477
+ $fb.appendTo($freeBusyPlaceholder);
2478
+ }
2479
+ }
2480
+ },
2481
+ /*
2482
+ * Position the freebusy element within the weekday based on it's start / end dates.
2483
+ */
2484
+ _positionFreeBusy: function($placeholder, $freeBusy) {
2485
+ var options = this.options;
2486
+ var freeBusy = $freeBusy.data('wcFreeBusy');
2487
+ var pxPerMillis = $placeholder.height() / options.millisToDisplay;
2488
+ var firstHourDisplayed = options.businessHours.limitDisplay ? options.businessHours.start : 0;
2489
+ var startMillis = freeBusy.getStart().getTime() - new Date(freeBusy.getStart().getFullYear(), freeBusy.getStart().getMonth(), freeBusy.getStart().getDate(), firstHourDisplayed).getTime();
2490
+ var eventMillis = freeBusy.getEnd().getTime() - freeBusy.getStart().getTime();
2491
+ var pxTop = pxPerMillis * startMillis;
2492
+ var pxHeight = pxPerMillis * eventMillis;
2493
+ $freeBusy.css({top: pxTop, height: pxHeight});
2494
+ },
2495
+ /*
2496
+ * Clean freebusys to ensure correct format
2497
+ */
2498
+ _cleanFreeBusys: function(freebusys) {
2499
+ var self = this,
2500
+ freeBusyToReturn = [];
2501
+ if (!$.isArray(freebusys)) {
2502
+ var freebusys = [freebusys];
2503
+ }
2504
+ $.each(freebusys, function(i, freebusy) {
2505
+ freeBusyToReturn.push(new FreeBusy(self._cleanFreeBusy(freebusy)));
2506
+ });
2507
+ return freeBusyToReturn;
2508
+ },
2509
+
2510
+ /*
2511
+ * Clean specific freebusy
2512
+ */
2513
+ _cleanFreeBusy: function(freebusy) {
2514
+ if (freebusy.date) {
2515
+ freebusy.start = freebusy.date;
2516
+ }
2517
+ freebusy.start = this._cleanDate(freebusy.start);
2518
+ freebusy.end = this._cleanDate(freebusy.end);
2519
+ return freebusy;
2520
+ },
2521
+
2522
+ /**
2523
+ * retrives the first freebusy manager matching demand.
2524
+ */
2525
+ getFreeBusyManagersFor: function(date, users) {
2526
+ var calEvent = {
2527
+ start: date,
2528
+ end: date
2529
+ };
2530
+ this._setEventUserId(calEvent, users);
2531
+ return this.getFreeBusyManagerForEvent(calEvent);
2532
+ },
2533
+ /**
2534
+ * retrives the first freebusy manager for given event.
2535
+ */
2536
+ getFreeBusyManagerForEvent: function(newCalEvent) {
2537
+ var self = this,
2538
+ options = this.options,
2539
+ freeBusyManager;
2540
+ if (options.displayFreeBusys) {
2541
+ var $freeBusyPlaceHoders = self.element.find('.wc-grid-row-freebusy .wc-column-freebusy'),
2542
+ freeBusy = new FreeBusy({start: newCalEvent.start, end: newCalEvent.end}),
2543
+ showAsSeparatedUser = options.showAsSeparateUsers && options.users && options.users.length,
2544
+ userId = showAsSeparatedUser ? self._getEventUserId(newCalEvent) : null;
2545
+ if (!$.isArray(userId)) {
2546
+ userId = [userId];
2547
+ }
2548
+ $freeBusyPlaceHoders.each(function() {
2549
+ var manager = $(this).data('wcFreeBusyManager'),
2550
+ has_overlap = manager.isWithin(freeBusy.getEnd()) ||
2551
+ manager.isWithin(freeBusy.getEnd()) ||
2552
+ freeBusy.isWithin(manager.getStart()) ||
2553
+ freeBusy.isWithin(manager.getEnd());
2554
+ if (has_overlap && (!showAsSeparatedUser || $.inArray($(this).data('wcUserId'), userId) != -1)) {
2555
+ freeBusyManager = $(this).data('wcFreeBusyManager');
2556
+ return false;
2557
+ }
2558
+ });
2559
+ }
2560
+ return freeBusyManager;
2561
+ },
2562
+ /**
2563
+ * appends the freebusys to replace the old ones.
2564
+ * @param {array|object} freeBusys freebusy(s) to apply.
2565
+ */
2566
+ updateFreeBusy: function(freeBusys) {
2567
+ var self = this,
2568
+ options = this.options;
2569
+ if (options.displayFreeBusys) {
2570
+ var $toRender,
2571
+ $freeBusyPlaceHoders = self.element.find('.wc-grid-row-freebusy .wc-column-freebusy'),
2572
+ _freeBusys = self._cleanFreeBusys(freeBusys);
2573
+
2574
+ $.each(_freeBusys, function(index, _freeBusy) {
2575
+
2576
+ var $weekdays = self._findWeekDaysForFreeBusy(_freeBusy, $freeBusyPlaceHoders);
2577
+ //if freebusy has a placeholder
2578
+ if ($weekdays && $weekdays.length) {
2579
+ $weekdays.each(function(index, day) {
2580
+ var manager = $(day).data('wcFreeBusyManager');
2581
+ manager.insertFreeBusy(_freeBusy);
2582
+ $(day).data('wcFreeBusyManager', manager);
2583
+ });
2584
+ $toRender = $toRender ? $toRender.add($weekdays) : $weekdays;
2585
+ }
2586
+ });
2587
+ self._refreshFreeBusys($toRender);
2588
+ }
2589
+ },
2590
+
2591
+ /* NEW OPTIONS MANAGEMENT */
2592
+
2593
+ /**
2594
+ * checks wether or not the calendar should be displayed starting on first day of week
2595
+ */
2596
+ _startOnFirstDayOfWeek: function() {
2597
+ return jQuery.isFunction(this.options.startOnFirstDayOfWeek) ? this.options.startOnFirstDayOfWeek(this.element) : this.options.startOnFirstDayOfWeek;
2598
+ },
2599
+
2600
+ /**
2601
+ * finds out the current scroll to apply it when changing the view
2602
+ */
2603
+ _getCurrentScrollHour: function() {
2604
+ var self = this;
2605
+ var options = this.options;
2606
+ var $scrollable = this.element.find('.wc-scrollable-grid');
2607
+ var scroll = $scrollable.scrollTop();
2608
+ if (self.options.businessHours.limitDisplay) {
2609
+ scroll = scroll + options.businessHours.start * options.timeslotHeight * options.timeslotsPerHour;
2610
+ }
2611
+ return Math.round(scroll / (options.timeslotHeight * options.timeslotsPerHour)) + 1;
2612
+ },
2613
+ _getJsonOptions: function() {
2614
+ if ($.isFunction(this.options.jsonOptions)) {
2615
+ return $.extend({}, this.options.jsonOptions(this.element));
2616
+ }
2617
+ if ($.isPlainObject(this.options.jsonOptions)) {
2618
+ return $.extend({}, this.options.jsonOptions);
2619
+ }
2620
+ return {};
2621
+ },
2622
+ _getHeaderDate: function(date) {
2623
+ var options = this.options;
2624
+ if (options.getHeaderDate && $.isFunction(options.getHeaderDate))
2625
+ {
2626
+ return options.getHeaderDate(date, this.element);
2627
+ }
2628
+ var dayName = options.useShortDayNames ? options.shortDays[date.getDay()] : options.longDays[date.getDay()];
2629
+ return dayName + (options.headerSeparator) + this._formatDate(date, options.dateFormat);
2630
+ },
2631
+
2632
+
2633
+
2634
+ /**
2635
+ * returns corrected date related to DST problem
2636
+ */
2637
+ _getDSTdayShift: function(date, shift) {
2638
+ var start = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0);
2639
+ var offset1 = start.getTimezoneOffset();
2640
+ var offset2 = date.getTimezoneOffset();
2641
+ if (offset1 == offset2)
2642
+ return date;
2643
+ shift = shift ? shift : 1;
2644
+ return new Date(date.getTime() - shift * (offset1 > offset2 ? -1 : 1) * (Math.max(offset1, offset2) - Math.min(offset1, offset2)) * 60000);
2645
+ },
2646
+ _needDSTdayShift: function(date1, date2) {
2647
+ return date1.getTimezoneOffset() != date2.getTimezoneOffset();
2648
+ }
2649
+
2650
+
2651
+
2652
+ }; // end of widget function return
2653
+ })() //end of widget function closure execution
2654
+ ); // end of $.widget("ui.weekCalendar"...
2655
+
2656
+ $.extend($.ui.weekCalendar, {
2657
+ version: '2.0-dev',
2658
+ updateLayoutOptions: {
2659
+ startOnFirstDayOfWeek: true,
2660
+ firstDayOfWeek: true,
2661
+ daysToShow: true,
2662
+ displayOddEven: true,
2663
+ timeFormat: true,
2664
+ dateFormat: true,
2665
+ use24Hour: true,
2666
+ useShortDayNames: true,
2667
+ businessHours: true,
2668
+ timeslotHeight: true,
2669
+ timeslotsPerHour: true,
2670
+ buttonText: true,
2671
+ height: true,
2672
+ shortMonths: true,
2673
+ longMonths: true,
2674
+ shortDays: true,
2675
+ longDays: true,
2676
+ textSize: true,
2677
+ users: true,
2678
+ showAsSeparateUsers: true,
2679
+ displayFreeBusys: true
2680
+ }
2681
+ });
2682
+
2683
+ var MILLIS_IN_DAY = 86400000;
2684
+ var MILLIS_IN_WEEK = MILLIS_IN_DAY * 7;
2685
+
2686
+ /* FREE BUSY MANAGERS */
2687
+ var FreeBusyProto = {
2688
+ getStart: function() {return this.getOption('start')},
2689
+ getEnd: function() {return this.getOption('end')},
2690
+ getOption: function() {
2691
+ if (!arguments.length) { return this.options }
2692
+ if (typeof(this.options[arguments[0]]) !== 'undefined') {
2693
+ return this.options[arguments[0]];
2694
+ }
2695
+ else if (typeof(arguments[1]) !== 'undefined') {
2696
+ return arguments[1];
2697
+ }
2698
+ return null;
2699
+ },
2700
+ setOption: function(key, value) {
2701
+ if (arguments.length == 1) {
2702
+ $.extend(this.options, arguments[0]);
2703
+ return this;
2704
+ }
2705
+ this.options[key] = value;
2706
+ return this;
2707
+ },
2708
+ isWithin: function(dateTime) {return Math.floor(dateTime.getTime() / 1000) >= Math.floor(this.getStart().getTime() / 1000) && Math.floor(dateTime.getTime() / 1000) <= Math.floor(this.getEnd().getTime() / 1000)},
2709
+ isValid: function() {return this.getStart().getTime() < this.getEnd().getTime()}
2710
+ };
2711
+
2712
+ /**
2713
+ * @constructor
2714
+ * single user freebusy manager.
2715
+ */
2716
+ var FreeBusy = function(options) {
2717
+ this.options = $.extend({}, options || {});
2718
+ };
2719
+ $.extend(FreeBusy.prototype, FreeBusyProto);
2720
+
2721
+ var FreeBusyManager = function(options) {
2722
+ this.options = $.extend({
2723
+ defaultFreeBusy: {}
2724
+ }, options || {});
2725
+ this.freeBusys = [];
2726
+ this.freeBusys.push(new FreeBusy($.extend({
2727
+ start: this.getStart(),
2728
+ end: this.getEnd()
2729
+ }, this.options.defaultFreeBusy)));
2730
+ };
2731
+ $.extend(FreeBusyManager.prototype, FreeBusyProto, {
2732
+ /**
2733
+ * return matching freeBusys.
2734
+ * if you do not pass any argument, returns all freebusys.
2735
+ * if you only pass a start date, only matchinf freebusy will be returned.
2736
+ * if you pass 2 arguments, then all freebusys available within the time period will be returned
2737
+ * @param {Date} start [optionnal] if you do not pass end date, will return the freeBusy within which this date falls.
2738
+ * @param {Date} end [optionnal] the date where to stop the search.
2739
+ * @return {Array} an array of FreeBusy matching arguments.
2740
+ */
2741
+ getFreeBusys: function() {
2742
+ switch (arguments.length) {
2743
+ case 0:
2744
+ return this.freeBusys;
2745
+ case 1:
2746
+ var freeBusy = [];
2747
+ var start = arguments[0];
2748
+ if (!this.isWithin(start)) {
2749
+ return freeBusy;
2750
+ }
2751
+ $.each(this.freeBusys, function() {
2752
+ if (this.isWithin(start)) {
2753
+ freeBusy.push(this);
2754
+ }
2755
+ if (Math.floor(this.getEnd().getTime() / 1000) > Math.floor(start.getTime() / 1000)) {
2756
+ return false;
2757
+ }
2758
+ });
2759
+ return freeBusy;
2760
+ default:
2761
+ //we assume only 2 first args are revealants
2762
+ var freeBusy = [];
2763
+ var start = arguments[0], end = arguments[1];
2764
+ var tmpFreeBusy = new FreeBusy({start: start, end: end});
2765
+ if (end.getTime() < start.getTime() || this.getStart().getTime() > end.getTime() || this.getEnd().getTime() < start.getTime()) {
2766
+ return freeBusy;
2767
+ }
2768
+ $.each(this.freeBusys, function() {
2769
+ if (this.getStart().getTime() >= end.getTime()) {
2770
+ return false;
2771
+ }
2772
+ if (tmpFreeBusy.isWithin(this.getStart()) && tmpFreeBusy.isWithin(this.getEnd())) {
2773
+ freeBusy.push(this);
2774
+ }
2775
+ else if (this.isWithin(tmpFreeBusy.getStart()) && this.isWithin(tmpFreeBusy.getEnd())) {
2776
+ var _f = new FreeBusy(this.getOption());
2777
+ _f.setOption('end', tmpFreeBusy.getEnd());
2778
+ _f.setOption('start', tmpFreeBusy.getStart());
2779
+ freeBusy.push(_f);
2780
+ }
2781
+ else if (this.isWithin(tmpFreeBusy.getStart()) && this.getStart().getTime() < start.getTime()) {
2782
+ var _f = new FreeBusy(this.getOption());
2783
+ _f.setOption('start', tmpFreeBusy.getStart());
2784
+ freeBusy.push(_f);
2785
+ }
2786
+ else if (this.isWithin(tmpFreeBusy.getEnd()) && this.getEnd().getTime() > end.getTime()) {
2787
+ var _f = new FreeBusy(this.getOption());
2788
+ _f.setOption('end', tmpFreeBusy.getEnd());
2789
+ freeBusy.push(_f);
2790
+ }
2791
+ });
2792
+ return freeBusy;
2793
+ }
2794
+ },
2795
+ insertFreeBusy: function(freeBusy) {
2796
+ var freeBusy = new FreeBusy(freeBusy.getOption());
2797
+ //first, if inserted freebusy is bigger than manager
2798
+ if (freeBusy.getStart().getTime() < this.getStart().getTime()) {
2799
+ freeBusy.setOption('start', this.getStart());
2800
+ }
2801
+ if (freeBusy.getEnd().getTime() > this.getEnd().getTime()) {
2802
+ freeBusy.setOption('end', this.getEnd());
2803
+ }
2804
+ var start = freeBusy.getStart(), end = freeBusy.getEnd(),
2805
+ startIndex = 0, endIndex = this.freeBusys.length - 1,
2806
+ newFreeBusys = [];
2807
+ var pushNewFreeBusy = function(_f) {if (_f.isValid()) newFreeBusys.push(_f);};
2808
+
2809
+ $.each(this.freeBusys, function(index) {
2810
+ //within the loop, we have following vars:
2811
+ // curFreeBusyItem: the current iteration freeBusy, part of manager freeBusys list
2812
+ // start: the insterted freeBusy start
2813
+ // end: the inserted freebusy end
2814
+ var curFreeBusyItem = this;
2815
+ if (curFreeBusyItem.isWithin(start) && curFreeBusyItem.isWithin(end)) {
2816
+ /*
2817
+ we are in case where inserted freebusy fits in curFreeBusyItem:
2818
+ curFreeBusyItem: *-----------------------------*
2819
+ freeBusy: *-------------*
2820
+ obviously, start and end indexes are this item.
2821
+ */
2822
+ startIndex = index;
2823
+ endIndex = index;
2824
+ if (start.getTime() == curFreeBusyItem.getStart().getTime() && end.getTime() == curFreeBusyItem.getEnd().getTime()) {
2825
+ /*
2826
+ in this case, inserted freebusy is exactly curFreeBusyItem:
2827
+ curFreeBusyItem: *-----------------------------*
2828
+ freeBusy: *-----------------------------*
2829
+
2830
+ just replace curFreeBusyItem with freeBusy.
2831
+ */
2832
+ var _f1 = new FreeBusy(freeBusy.getOption());
2833
+ pushNewFreeBusy(_f1);
2834
+ }
2835
+ else if (start.getTime() == curFreeBusyItem.getStart().getTime()) {
2836
+ /*
2837
+ in this case inserted freebusy starts with curFreeBusyItem:
2838
+ curFreeBusyItem: *-----------------------------*
2839
+ freeBusy: *--------------*
2840
+
2841
+ just replace curFreeBusyItem with freeBusy AND the rest.
2842
+ */
2843
+ var _f1 = new FreeBusy(freeBusy.getOption());
2844
+ var _f2 = new FreeBusy(curFreeBusyItem.getOption());
2845
+ _f2.setOption('start', end);
2846
+ pushNewFreeBusy(_f1);
2847
+ pushNewFreeBusy(_f2);
2848
+ }
2849
+ else if (end.getTime() == curFreeBusyItem.getEnd().getTime()) {
2850
+ /*
2851
+ in this case inserted freebusy ends with curFreeBusyItem:
2852
+ curFreeBusyItem: *-----------------------------*
2853
+ freeBusy: *--------------*
2854
+
2855
+ just replace curFreeBusyItem with before part AND freeBusy.
2856
+ */
2857
+ var _f1 = new FreeBusy(curFreeBusyItem.getOption());
2858
+ _f1.setOption('end', start);
2859
+ var _f2 = new FreeBusy(freeBusy.getOption());
2860
+ pushNewFreeBusy(_f1);
2861
+ pushNewFreeBusy(_f2);
2862
+ }
2863
+ else {
2864
+ /*
2865
+ in this case inserted freebusy is within curFreeBusyItem:
2866
+ curFreeBusyItem: *-----------------------------*
2867
+ freeBusy: *--------------*
2868
+
2869
+ just replace curFreeBusyItem with before part AND freeBusy AND the rest.
2870
+ */
2871
+ var _f1 = new FreeBusy(curFreeBusyItem.getOption());
2872
+ var _f2 = new FreeBusy(freeBusy.getOption());
2873
+ var _f3 = new FreeBusy(curFreeBusyItem.getOption());
2874
+ _f1.setOption('end', start);
2875
+ _f3.setOption('start', end);
2876
+ pushNewFreeBusy(_f1);
2877
+ pushNewFreeBusy(_f2);
2878
+ pushNewFreeBusy(_f3);
2879
+ }
2880
+ /*
2881
+ as work is done, no need to go further.
2882
+ return false
2883
+ */
2884
+ return false;
2885
+ }
2886
+ else if (curFreeBusyItem.isWithin(start) && curFreeBusyItem.getEnd().getTime() != start.getTime()) {
2887
+ /*
2888
+ in this case, inserted freebusy starts within curFreeBusyItem:
2889
+ curFreeBusyItem: *----------*
2890
+ freeBusy: *-------------------*
2891
+
2892
+ set start index AND insert before part, we'll insert freebusy later
2893
+ */
2894
+ if (curFreeBusyItem.getStart().getTime() != start.getTime()) {
2895
+ var _f1 = new FreeBusy(curFreeBusyItem.getOption());
2896
+ _f1.setOption('end', start);
2897
+ pushNewFreeBusy(_f1);
2898
+ }
2899
+ startIndex = index;
2900
+ }
2901
+ else if (curFreeBusyItem.isWithin(end) && curFreeBusyItem.getStart().getTime() != end.getTime()) {
2902
+ /*
2903
+ in this case, inserted freebusy starts within curFreeBusyItem:
2904
+ curFreeBusyItem: *----------*
2905
+ freeBusy: *-------------------*
2906
+
2907
+ set end index AND insert freebusy AND insert after part if needed
2908
+ */
2909
+ pushNewFreeBusy(new FreeBusy(freeBusy.getOption()));
2910
+ if (end.getTime() < curFreeBusyItem.getEnd().getTime()) {
2911
+ var _f1 = new FreeBusy(curFreeBusyItem.getOption());
2912
+ _f1.setOption('start', end);
2913
+ pushNewFreeBusy(_f1);
2914
+ }
2915
+ endIndex = index;
2916
+ return false;
2917
+ }
2918
+ });
2919
+ //now compute arguments
2920
+ var tmpFB = this.freeBusys;
2921
+ this.freeBusys = [];
2922
+
2923
+ if (startIndex) {
2924
+ this.freeBusys = this.freeBusys.concat(tmpFB.slice(0, startIndex));
2925
+ }
2926
+ this.freeBusys = this.freeBusys.concat(newFreeBusys);
2927
+ if (endIndex < tmpFB.length) {
2928
+ this.freeBusys = this.freeBusys.concat(tmpFB.slice(endIndex + 1));
2929
+ }
2930
+ /* if(start.getDate() == 1){
2931
+ console.info('insert from '+freeBusy.getStart() +' to '+freeBusy.getEnd());
2932
+ console.log('index from '+ startIndex + ' to ' + endIndex);
2933
+ var str = [];
2934
+ $.each(tmpFB, function(i){str.push(i + ": " + this.getStart().getHours() + ' > ' + this.getEnd().getHours() + ' ' + (this.getOption('free') ? 'free' : 'busy'))});
2935
+ console.log(str.join('\n'));
2936
+
2937
+ console.log('insert');
2938
+ var str = [];
2939
+ $.each(newFreeBusys, function(i){str.push(this.getStart().getHours() + ' > ' + this.getEnd().getHours())});
2940
+ console.log(str.join(', '));
2941
+
2942
+ console.log('results');
2943
+ var str = [];
2944
+ $.each(this.freeBusys, function(i){str.push(i + ": " + this.getStart().getHours() + ' > ' + this.getEnd().getHours() + ' ' + (this.getOption('free') ? 'free' :'busy'))});
2945
+ console.log(str.join('\n'));
2946
+ }*/
2947
+ return this;
2948
+ }
2949
+ });
2950
+
2951
+ })(jQuery);
backend/modules/calendar/resources/js/ng-app.js ADDED
@@ -0,0 +1,436 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ;(function() {
2
+
3
+ var module = angular.module('appointmentForm', ['ui', 'newCustomerDialog']);
4
+
5
+ /**
6
+ * DataSource service.
7
+ */
8
+ module.factory('dataSource', function($q, $rootScope, $filter) {
9
+ var ds = {
10
+ data : {
11
+ staff : [],
12
+ customers : [],
13
+ time : [],
14
+ time_interval : 900
15
+ },
16
+ form : {
17
+ id : null,
18
+ staff : null,
19
+ service : null,
20
+ date : null,
21
+ start_time : null,
22
+ end_time : null,
23
+ customers : [],
24
+ email_notification : null,
25
+ notes : null,
26
+ capacity : 1
27
+ },
28
+ loadData : function() {
29
+ var deferred = $q.defer();
30
+ jQuery.get(
31
+ ajaxurl,
32
+ { action : 'ab_get_data_for_appointment_form' },
33
+ function(data) {
34
+ ds.data = data;
35
+ // Add empty element to beginning of array for single-select customer form
36
+ ds.data.customers.unshift({name: ''});
37
+
38
+ if (data.staff.length) {
39
+ ds.form.staff = data.staff[0];
40
+ }
41
+ ds.form.start_time = data.time[0];
42
+ ds.form.end_time = data.time[1];
43
+ ds.form.notes = data.notes;
44
+ $rootScope.$apply(deferred.resolve);
45
+ },
46
+ 'json'
47
+ );
48
+ return deferred.promise;
49
+ },
50
+ findStaff : function(id) {
51
+ var result = null;
52
+ jQuery.each(ds.data.staff, function(key, item) {
53
+ if (item.id == id) {
54
+ result = item;
55
+ return false;
56
+ }
57
+ });
58
+ return result;
59
+ },
60
+ findService : function(staff_id, id) {
61
+ var result = null,
62
+ staff = ds.findStaff(staff_id);
63
+
64
+ if (staff !== null) {
65
+ jQuery.each(staff.services, function(key, item) {
66
+ if (item.id == id) {
67
+ result = item;
68
+ return false;
69
+ }
70
+ });
71
+ }
72
+ return result;
73
+ },
74
+ findTime : function(date) {
75
+ var result = null,
76
+ value_to_find = $filter('date')(date, 'HH:mm');
77
+
78
+ jQuery.each(ds.data.time, function(key, item) {
79
+ if (item.value === value_to_find) {
80
+ result = item;
81
+ return false;
82
+ }
83
+ });
84
+ return result;
85
+ },
86
+ findCustomer : function(id) {
87
+ var result = null;
88
+ jQuery.each(ds.data.customers, function(key, item) {
89
+ if (item.id == id) {
90
+ result = item;
91
+ return false;
92
+ }
93
+ });
94
+ return result;
95
+ },
96
+ getDataForEndTime : function() {
97
+ var result = [];
98
+ jQuery.each(ds.data.time, function(key, item) {
99
+ if (
100
+ ds.form.start_time === null ||
101
+ item.value > ds.form.start_time.value
102
+ ) {
103
+ result.push(item);
104
+ }
105
+ });
106
+ return result;
107
+ },
108
+ setEndTimeBasedOnService : function() {
109
+ var i = jQuery.inArray(ds.form.start_time, ds.data.time),
110
+ d = ds.form.service ? ds.form.service.duration : ds.data.time_interval;
111
+ if (i !== -1) {
112
+ for (; i < ds.data.time.length; ++ i) {
113
+ d -= ds.data.time_interval;
114
+ if (d < 0) {
115
+ break;
116
+ }
117
+ }
118
+ ds.form.end_time = ds.data.time[i];
119
+ }
120
+ },
121
+ getStartAndEndDates : function() {
122
+ var date = $filter('date')(ds.form.date, 'yyyy-MM-dd');
123
+ return {
124
+ start_date : date + ' ' + ds.form.start_time.value,
125
+ end_date : date + ' ' + ds.form.end_time.value
126
+ };
127
+ }
128
+ };
129
+
130
+ return ds;
131
+ });
132
+
133
+ /**
134
+ * Controller for "create/edit appointment" dialog form.
135
+ */
136
+ module.controller('appointmentDialogCtrl', function($scope, $element, dataSource) {
137
+ // Set up initial data.
138
+ $scope.loading = true;
139
+ $scope.$week_calendar = null;
140
+ $scope.calendar_mode = 'week';
141
+ // Set up data source.
142
+ $scope.dataSource = dataSource;
143
+ $scope.form = dataSource.form; // shortcut
144
+ $scope.show_notes = false;
145
+ // Populate data source.
146
+ dataSource.loadData().then(function() {
147
+ $scope.loading = false;
148
+ });
149
+ // Error messages.
150
+ $scope.errors = {};
151
+ // Id of the staff whos events are currently being edited/created.
152
+ var current_staff_id = null;
153
+
154
+ /**
155
+ * Prepare the form for new event.
156
+ *
157
+ * @param int staff_id
158
+ * @param Date start_date
159
+ */
160
+ $scope.configureNewForm = function(staff_id, start_date) {
161
+ jQuery.extend($scope.form, {
162
+ id : null,
163
+ staff : dataSource.findStaff(staff_id),
164
+ service : null,
165
+ date : start_date,
166
+ start_time : dataSource.findTime(start_date),
167
+ end_time : null,
168
+ customers : [],
169
+ email_notification : null,
170
+ notes : null
171
+ });
172
+ $scope.errors = {};
173
+ dataSource.setEndTimeBasedOnService();
174
+ current_staff_id = staff_id;
175
+
176
+ $scope.redrawStaffSelector(1);
177
+ };
178
+
179
+ /**
180
+ * Prepare the form for editing event.
181
+ */
182
+ $scope.configureEditForm = function(appointment_id, staff_id, start_date, end_date) {
183
+ $scope.loading = true;
184
+ jQuery.post(
185
+ ajaxurl,
186
+ { action : 'ab_get_data_for_appointment', id : appointment_id },
187
+ function(response) {
188
+ $scope.$apply(function($scope) {
189
+ if (response.status === 'ok') {
190
+ jQuery.extend($scope.form, {
191
+ id : appointment_id,
192
+ staff : $scope.dataSource.findStaff(staff_id),
193
+ service : $scope.dataSource.findService(staff_id, response.data.service_id),
194
+ date : start_date,
195
+ start_time : $scope.dataSource.findTime(start_date),
196
+ end_time : $scope.dataSource.findTime(end_date),
197
+ customers : [],
198
+ notes : response.data.notes
199
+ });
200
+
201
+ $scope.redrawStaffSelector(response.data.max_capacity);
202
+ $scope.show_notes = response.data.max_capacity == 1;
203
+
204
+ response.data.customers.forEach(function(item, i, arr){
205
+ $scope.form.customers.push($scope.dataSource.findCustomer(item))
206
+ });
207
+ }
208
+ $scope.loading = false;
209
+ });
210
+ },
211
+ 'json'
212
+ );
213
+ $scope.errors = {};
214
+ current_staff_id = staff_id;
215
+ };
216
+
217
+ var checkTimeInterval = function() {
218
+ var dates = $scope.dataSource.getStartAndEndDates();
219
+ jQuery.get(
220
+ ajaxurl,
221
+ {
222
+ action : 'ab_check_appointment_date_selection',
223
+ start_date : dates.start_date,
224
+ end_date : dates.end_date,
225
+ appointment_id : $scope.form.id,
226
+ staff_id : $scope.form.staff ? $scope.form.staff.id : null,
227
+ service_id : $scope.form.service ? $scope.form.service.id : null
228
+ },
229
+ function(response){
230
+ $scope.$apply(function($scope) {
231
+ $scope.errors = response;
232
+ });
233
+ },
234
+ 'json'
235
+ );
236
+ };
237
+
238
+ var checkAppointmentMaxSelectedOptions = function(){
239
+ jQuery.get(
240
+ ajaxurl,
241
+ {
242
+ action : 'ab_check_appointment_max_selected_options',
243
+ staff_id : $scope.form.staff ? $scope.form.staff.id : null,
244
+ service_id : $scope.form.service ? $scope.form.service.id : null
245
+ },
246
+ function(response){
247
+ $scope.redrawStaffSelector(response.max_selected_options);
248
+ $scope.$apply(function () {
249
+ $scope.show_notes = response.max_selected_options == 1;
250
+ });
251
+ },
252
+ 'json'
253
+ );
254
+ };
255
+
256
+ $scope.onServiceChange = function() {
257
+ $scope.dataSource.setEndTimeBasedOnService();
258
+ checkTimeInterval();
259
+ checkAppointmentMaxSelectedOptions();
260
+ };
261
+
262
+ $scope.onStartTimeChange = function() {
263
+ $scope.dataSource.setEndTimeBasedOnService();
264
+ checkTimeInterval();
265
+ };
266
+
267
+ $scope.onEndTimeChange = function() {
268
+ checkTimeInterval();
269
+ };
270
+
271
+ $scope.processForm = function() {
272
+ $scope.loading = true;
273
+ var dates = $scope.dataSource.getStartAndEndDates(),
274
+ customers = [];
275
+
276
+ $scope.form.customers.forEach(function(item, i, arr){
277
+ customers.push(item.id);
278
+ });
279
+
280
+ jQuery.post(
281
+ ajaxurl,
282
+ {
283
+ action : 'ab_save_appointment_form',
284
+ id : $scope.form.id,
285
+ staff_id : $scope.form.staff ? $scope.form.staff.id : null,
286
+ service_id : $scope.form.service ? $scope.form.service.id : null,
287
+ start_date : dates.start_date,
288
+ end_date : dates.end_date,
289
+ customers : JSON.stringify(customers),
290
+ email_notification : $scope.form.email_notification,
291
+ notes : $scope.form.notes
292
+ },
293
+ function (response) {
294
+ $scope.$apply(function($scope) {
295
+ if (response.status === 'ok') {
296
+ if ($scope.$week_calendar) {
297
+ if ($scope.calendar_mode === 'day' || current_staff_id === response.data.userId) {
298
+ // Update/create event in current calendar when:
299
+ // - current view mode is "day"
300
+ // OR
301
+ // - ID of event owner matches the ID of active staff ("week" mode)
302
+ $scope.$week_calendar.weekCalendar('updateEvent', response.data);
303
+ } else {
304
+ // Else switch to the event owner tab ("week" mode).
305
+ jQuery('li.ab-staff-tab-' + response.data.userId).click();
306
+ }
307
+ }
308
+ // Close the dialog.
309
+ $element.dialog('close');
310
+ } else {
311
+ $scope.errors = response.errors;
312
+ }
313
+ $scope.loading = false;
314
+ });
315
+ },
316
+ 'json'
317
+ );
318
+ };
319
+
320
+ // On 'Cancel' button click.
321
+ $scope.closeDialog = function() {
322
+ // Close the dialog.
323
+ $element.dialog('close');
324
+ };
325
+
326
+ $scope.createCustomer = function(customer) {
327
+ // Add new customer to the list.
328
+ var new_customer = {id : customer.id.toString(), name : customer.name};
329
+
330
+ if (customer.email || customer.phone){
331
+ new_customer.name += ' (' + [customer.email, customer.phone].filter(Boolean).join(', ') + ')';
332
+ }
333
+
334
+ dataSource.data.customers.push(new_customer);
335
+ // Make it selected.
336
+ if (dataSource.form.customers.length < dataSource.form.capacity){
337
+ dataSource.form.customers.push(new_customer);
338
+ }
339
+
340
+ //TODO find better solution. Callback on modification of selector
341
+ setTimeout(function(){jQuery("#chosen").trigger("chosen:updated");}, 100);
342
+ };
343
+
344
+ $scope.redrawStaffSelector = function(max_selected_options){
345
+ dataSource.form.capacity = max_selected_options;
346
+
347
+ jQuery('#chosen')
348
+ .chosen('destroy')
349
+ .chosen({
350
+ search_contains : true,
351
+ width : '400px',
352
+ max_selected_options: max_selected_options
353
+ });
354
+ };
355
+
356
+ $scope.dateOptions = {
357
+ dateFormat : 'M, dd yy',
358
+ dayNamesMin : BooklyL10n['shortDays'],
359
+ monthNames : BooklyL10n['longMonths'],
360
+ monthNamesShort : BooklyL10n['shortMonths']
361
+ };
362
+ });
363
+
364
+ /**
365
+ * Directive for slide up/down.
366
+ */
367
+ module.directive('mySlideUp', function() {
368
+ return function(scope, element, attrs) {
369
+ element.hide();
370
+ // watch the expression, and update the UI on change.
371
+ scope.$watch(attrs.mySlideUp, function(value) {
372
+ if (value) {
373
+ element.delay(0).slideDown();
374
+ } else {
375
+ element.slideUp();
376
+ }
377
+ });
378
+ };
379
+ });
380
+
381
+ module.directive('chosen',function(){
382
+ var linker = function(scope,element,attrs) {
383
+ scope.$watch(attrs['chosen'], function() {
384
+ element.trigger("chosen:updated");
385
+ });
386
+
387
+ scope.$watch(attrs['ngModel'], function() {
388
+ element.trigger("chosen:updated");
389
+ });
390
+
391
+ scope.redrawStaffSelector(1);
392
+ };
393
+
394
+ return {
395
+ restrict:'A',
396
+ link: linker
397
+ }
398
+ });
399
+
400
+ /**
401
+ * Directive for Popover jQuery plugin.
402
+ */
403
+ module.directive('popover', function() {
404
+ return function(scope, element, attrs) {
405
+ element.popover({
406
+ trigger : 'hover',
407
+ content : attrs.popover,
408
+ html : true
409
+ });
410
+ };
411
+ });
412
+
413
+ })();
414
+
415
+ var showAppointmentDialog = function(appointment_id, staff_id, start_date, end_date, calendar, mode, notes) {
416
+ var $scope = angular.element(document.getElementById('ab_appointment_dialog')).scope(),
417
+ title = null;
418
+ $scope.$apply(function($scope){
419
+ $scope.$week_calendar = calendar;
420
+ $scope.calendar_mode = mode;
421
+ if (appointment_id) {
422
+ $scope.configureEditForm(appointment_id, staff_id, start_date, end_date);
423
+ title = BooklyL10n['edit_appointment'];
424
+ } else {
425
+ $scope.configureNewForm(staff_id, start_date);
426
+ title = BooklyL10n['new_appointment'];
427
+ }
428
+ });
429
+ jQuery('#ab_appointment_dialog').dialog({
430
+ width: 700,
431
+ position: ['center', 150],
432
+ modal: true,
433
+ dialogClass: 'ab-appointment-popup',
434
+ title: title
435
+ });
436
+ };
backend/modules/calendar/templates/appointment_form.php ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <div ng-controller=appointmentDialogCtrl id=ab_appointment_dialog style="display: none">
3
+
4
+ <div ng-hide=loading class=dialog-content>
5
+ <form ng-submit=processForm() class=form-horizontal>
6
+
7
+ <div class=control-group>
8
+ <label class=control-label><?php _e('Provider', 'ab') ?></label>
9
+ <div class=controls>
10
+ <select class="field" ng-model=form.staff ng-options="s.full_name for s in dataSource.data.staff"></select>
11
+ </div>
12
+ </div>
13
+
14
+ <div class=control-group>
15
+ <label class=control-label><?php _e('Service', 'ab') ?></label>
16
+ <div class=controls>
17
+ <select class="field" ng-model=form.service ng-options="s.title for s in form.staff.services" ng-change=onServiceChange()>
18
+ <option value=""><?php _e('-- Select a service --', 'ab') ?></option>
19
+ </select>
20
+ </div>
21
+ </div>
22
+
23
+ <div class=control-group>
24
+ <label class=control-label><?php _e('Date', 'ab') ?></label>
25
+ <div class=controls>
26
+ <input class="field" type=text ng-model=form.date ui-date="dateOptions" />
27
+ </div>
28
+ </div>
29
+
30
+ <div class=control-group>
31
+ <label class=control-label><?php _e('Period', 'ab') ?></label>
32
+ <div class=controls>
33
+ <div my-slide-up=errors.date_interval_not_available id=date_interval_not_available_msg>
34
+ <?php _e( 'The selected period is occupied by another appointment!', 'ab' ) ?>
35
+ </div>
36
+ <select class="field-col-2" ng-model=form.start_time ng-options="t.title for t in dataSource.data.time" ng-change=onStartTimeChange()></select>
37
+ <span><?php _e( ' to ', 'ab' ) ?></span>
38
+ <select class="field-col-2" ng-model=form.end_time ng-options="t.title for t in dataSource.getDataForEndTime()" ng-change=onEndTimeChange()></select>
39
+ <div my-slide-up=errors.date_interval_warning id=date_interval_warning_msg>
40
+ <?php _e( 'The selected period does\'t match default duration for the selected service!', 'ab' ) ?>
41
+ </div>
42
+ </div>
43
+ </div>
44
+
45
+ <div class=control-group>
46
+ <label class=control-label><?php _e('Customer', 'ab') ?></label>
47
+ <div class=controls>
48
+ <select id="chosen" multiple data-placeholder="<?php _e('-- Select a customer --', 'ab') ?>" class="field chzn-select" chosen="dataSource.data.customers"
49
+ ng-model="form.customers" ng-options="c.name for c in dataSource.data.customers">
50
+ </select>
51
+ <div new-customer-dialog=createCustomer(customer) backdrop=false btn-class=""></div>
52
+ </div>
53
+ <div class=controls>
54
+ <div my-slide-up="errors.overflow_capacity" ng-bind="errors.overflow_capacity_message" style="color: red;"></div>
55
+ </div>
56
+ </div>
57
+
58
+ <div class="control-group" ng-show="show_notes">
59
+ <label class=control-label><?php _e('Notes', 'ab') ?></label>
60
+ <div class=controls>
61
+ <textarea class="field" ng-model=form.notes></textarea>
62
+ </div>
63
+ </div>
64
+
65
+ <div class=control-group>
66
+ <label class=control-label></label>
67
+ <div class=controls>
68
+ <input style="margin-top: 0" type="checkbox" id="email_notification" /> <?php _e('Send email notifications', 'ab') ?>
69
+ <img
70
+ src="<?php echo plugins_url( 'backend/resources/images/help.png', AB_PATH . '/main.php' ) ?>"
71
+ alt=""
72
+ class="ab-popover"
73
+ popover="<?php echo esc_attr(__('If email notifications are enabled and you want the customer or the staff member to be notified about this appointment after saving, tick this checkbox before clicking Save.', 'ab')) ?>"
74
+ style="width:16px;margin-left:0;"
75
+ />
76
+ <div id="email_notification_text" style="display: none; margin-top: 10px;"><?php _e('This function is disabled in the lite version of Bookly. If you find the plugin useful for your business please consider buying a licence for the full version. It costs just $38 and for this money you will get many useful functions, lifetime free update and excellent support! More information can be found here', 'ab'); ?>: <a href="http://bookly.ladela.com" target="_blank">http://bookly.ladela.com</a></div>
77
+ </div>
78
+ </div>
79
+
80
+ <div class=control-group>
81
+ <label class=control-label></label>
82
+ <div class=controls>
83
+ <div class=dialog-button-wrapper>
84
+ <input type=submit class="btn btn-info ab-update-button" value="<?php _e('Save') ?>" />
85
+ <a ng-click=closeDialog() class=ab-reset-form href=""><?php _e('Cancel') ?></a>
86
+ </div>
87
+ </div>
88
+ </div>
89
+
90
+ </form>
91
+ </div>
92
+
93
+ <div ng-show=loading class=loading-indicator>
94
+ <img src="<?php echo plugins_url('resources/images/ajax_loader_32x32.gif', dirname(__FILE__) . '/../../../AB_Backend.php') ?>" alt="" />
95
+ </div>
96
+
97
+ </div>
backend/modules/calendar/templates/calendar.php ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
3
+ // wp start day
4
+ $week_start_day = get_option('start_of_week', 1);
5
+ ?>
6
+ <div ng-app=appointmentForm class="wrap">
7
+ <div id="ab_calendar_header">
8
+ <h2><?php _e('Calendar', 'ab') ?></h2>
9
+ <div class="ab-nav-calendar">
10
+ <div class="btn-group right-margin left">
11
+ <button class="btn btn-info ab-calendar-switch-view ab-calendar-day"><?php _e('Day','ab') ?></button>
12
+ <button class="btn btn-info ab-calendar-switch-view ab-calendar-week ab-button-active"><?php _e('Week','ab') ?></button>
13
+ </div>
14
+ <button class="btn btn-info ab-calendar-today right-margin left"><?php _e('Today','ab') ?></button>
15
+ <div id="week-calendar-picker" class="ab-week-picker-wrapper left right-margin" data-first_day="<?php echo $week_start_day ?>">
16
+ <div class="input-prepend input-append">
17
+ <span class="ab-week-picker-arrow prev add-on col-arrow">&#9668;</span>
18
+ <input class="span2 ab-date-calendar" readonly="readonly" id="appendedPrependedInput" size="16" type="text" value="" />
19
+ <span class="ab-week-picker-arrow next add-on col-arrow">&#9658;</span>
20
+ </div>
21
+ <div class="ab-week-picker"></div>
22
+ </div>
23
+ <div id="day-calendar-picker" class="ab-week-picker-wrapper left right-margin" style="display: none;" data-first_day="<?php echo $week_start_day ?>">
24
+ <div class="pagination left">
25
+ <ul>
26
+ <li><a href="#" class="ab-week-picker-arrow-prev">&#9668;</a></li>
27
+ <li><a style="padding: 0" href="#"></a></li>
28
+ </ul>
29
+ </div>
30
+ <div class="input-append left" style="margin-right:-1px">
31
+ <input style="width:131px;margin-left:-2px;border-radius:0" class="span2" id="appendedInput" size="16" type="text" value="" /><span style="border-radius:0" class="add-on col-arrow">▼</span>
32
+ </div>
33
+ <div class="pagination left">
34
+ <ul>
35
+ <?php for ( $i = 1; $i <= 7; ++ $i ) : ?>
36
+ <li>
37
+ <a href="#" class="ab-day-of-month" <?php if ( 1 == $i ) : ?> style="border-radius:0"<?php endif; ?>></a>
38
+ </li>
39
+ <?php endfor; ?>
40
+ <li><a href="#" class="ab-week-picker-arrow-next">&#9658;</a></li>
41
+ </ul>
42
+ </div>
43
+ </div>
44
+ <!--div class="btn-group right right-margin">
45
+ <a class="btn btn-info" href="#"><i class="icon-user icon-white"></i><?php _e(' All services','ab') ?></a>
46
+ <a class="btn btn-info dropdown-toggle" data-toggle="dropdown" href="#"><span class="caret"></span></a>
47
+ <ul class="dropdown-menu">
48
+ <li>
49
+ <a href="javascript:void(0)">
50
+ <input style="margin-right: 5px;" type="checkbox" id="" class="all-staff left">
51
+ <label for=""><?php _e('All staff','ab') ?></label>
52
+ </a>
53
+ </li>
54
+ </ul>
55
+ </div-->
56
+ <div class="btn-group pull-right">
57
+ <a class="btn btn-info ab-staff-filter-button" href="javascript:void(0)">
58
+ <i class="icon-user icon-white"></i>
59
+ <span id="ab-staff-button">
60
+ <?php
61
+ $staff_numb = count($collection);
62
+ if ($staff_numb == 0) {
63
+ _e(' No staff selected','ab');
64
+ } else if ($staff_numb == 1) {
65
+ echo $collection[0]->full_name;
66
+ } else {
67
+ echo $staff_numb . ' '. __('staff members','ab');
68
+ }
69
+ ?>
70
+ </span>
71
+ </a>
72
+ <a class="btn btn-info dropdown-toggle ab-staff-filter-button" href="javascript:void(0)"><span class="caret"></span></a>
73
+ <ul class="dropdown-menu pull-right">
74
+ <li>
75
+ <a href="javascript:void(0)">
76
+ <input style="margin-right: 5px;" type="checkbox" checked="checked" id="ab-filter-all-staff" class="left">
77
+ <label for="ab-filter-all-staff"><?php _e('All staff','ab') ?></label>
78
+ </a>
79
+ <?php foreach ($collection as $staff) : ?>
80
+ <a style="padding-left: 35px;" href="javascript:void(0)">
81
+ <input style="margin-right: 5px;" type="checkbox" checked="checked" id="ab-filter-staff-<?php echo $staff->id ?>" value="<?php echo $staff->id ?>" class="ab-staff-option left">
82
+ <label style="padding-right: 15px;" for="ab-filter-staff-<?php echo $staff->id ?>"><?php echo $staff->full_name ?></label>
83
+ </a>
84
+ <?php endforeach ?>
85
+ </li>
86
+ </ul>
87
+ </div>
88
+ </div>
89
+ </div>
90
+ <?php if ( $collection ) : ?>
91
+ <?php
92
+ $user_names = array();
93
+ $user_ids = array();
94
+ ?>
95
+ <div id="week_calendar_wrapper">
96
+ <div class="tabbable" style="margin-top: 20px;">
97
+ <ul class="nav nav-tabs" style="margin-bottom:0;border-bottom: 6px solid #1f6a8c">
98
+ <?php foreach ($collection as $i => $staff) : ?>
99
+ <li class="ab-staff-tab-<?php echo $staff->id ?> ab-calendar-tab<?php echo 0 == $i ? ' active' : '' ?>" data-staff-id="<?php echo $staff->id ?>">
100
+ <a href="#" data-toggle="tab"><?php echo $staff->full_name ?></a>
101
+ </li>
102
+ <?php
103
+ $user_names[] = $staff->full_name;
104
+ $user_ids[] = $staff->id;
105
+ ?>
106
+ <?php endforeach ?>
107
+ </ul>
108
+ </div>
109
+ <div class="ab-calendar-element-container">
110
+ <div class="ab-calendar-element"></div>
111
+ </div>
112
+ </div>
113
+ <div id="day_calendar_wrapper" style="display: none">
114
+ <div class="ab-calendar-element-container">
115
+ <div class="ab-calendar-element"></div>
116
+ </div>
117
+ </div>
118
+ <?php include 'appointment_form.php' ?>
119
+ </div>
120
+ <span id="staff_ids" style="display: none"><?php echo json_encode($user_ids) ?></span>
121
+ <span id="ab_calendar_data_holder" style="display: none">
122
+ <span class="ab-calendar-first-day"><?php echo $week_start_day ?></span>
123
+ <span class="ab-calendar-time-format"><?php echo get_option( 'time_format' ) ?></span>
124
+ <span class="ab-calendar-users"><?php echo implode( '|', $user_names ) ?></span>
125
+ </span>
126
+ <?php endif; ?>
127
+ </div>
backend/modules/coupons/AB_CouponsController.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ /**
6
+ * Class AB_CouponsController
7
+ */
8
+ class AB_CouponsController extends AB_Controller {
9
+
10
+ /**
11
+ *
12
+ */
13
+ public function index() {
14
+ $this->render( 'index' );
15
+ }
16
+
17
+ // Protected methods.
18
+
19
+ /**
20
+ * Override parent method to add 'wp_ajax_ab_' prefix
21
+ * so current 'execute*' methods look nicer.
22
+ */
23
+ protected function registerWpActions( $prefix = '' ) {
24
+ parent::registerWpActions( 'wp_ajax_ab_' );
25
+ }
26
+
27
+ }
backend/modules/coupons/resources/css/coupons.css ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .ab-active {
2
+ background-color: #ccc;
3
+ }
4
+
5
+ #ab_coupons_wrapper .list-wrapper { min-width: 590px }
6
+ #ab_coupons_wrapper .list-wrapper .list-actions { overflow: hidden; margin-top: 10px; }
7
+ #ab_coupons_wrapper .list-wrapper .list-actions .add-service { float: left }
8
+ #ab_coupons_wrapper .list-wrapper .list-actions .delete { float: right }
9
+
10
+ #coupons_list td.last,
11
+ #coupons_list th.last { width: 16px; vertical-align: middle; }
12
+ #coupons_list th, #coupons_list td { padding:5px }
13
+ #coupons_list .service-color-cell { width: 28px; }
14
+
15
+ #ab-coupons-list .displayed-value { border: 1px solid transparent; padding: 4px 6px; min-height: 20px; }
16
+ #ab-coupons-list .ab-text-focus,
17
+ #ab-coupons-list .ab-text-focus:focus { text-align: right; padding-right: 2px; width: 58px; margin: 0!important; height: 30px; }
18
+ #ab-coupons-list .displayed-value:hover {
19
+ border: 1px solid #aaa;
20
+ background: #fff;
21
+ border-radius: 3px;
22
+ padding: 4px 6px;
23
+ -webkit-box-shadow: 1px 1px 2px rgba(0,0,0,0.1);
24
+ -moz-box-shadow: 1px 1px 2px rgba(0,0,0,0.1);
25
+ -o-box-shadow: 1px 1px 2px rgba(0,0,0,0.1);
26
+ box-shadow: 1px 1px 2px rgba(0,0,0,0.1);
27
+ }
backend/modules/coupons/resources/js/coupons.js ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ jQuery(function($) {
2
+ // On click on 'Add Coupon' button.
3
+ $('a.add-coupon').on('click', function(e) {
4
+ $('#lite_notice').modal('show');
5
+ });
6
+ });
backend/modules/coupons/templates/index.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <div class="ab-title"><?php _e('Coupons', 'ab') ?></div>
3
+ <div style="min-width: 800px;">
4
+ <div class="ab-right-content" style="border: 0" id="ab_coupons_wrapper">
5
+ <div class="no-result"><?php _e( 'No coupons found','ab' ) ?></div>
6
+ <div class="list-wrapper">
7
+ <div id="ab-coupons-list">
8
+ </div>
9
+ <div class="list-actions">
10
+ <a class="add-coupon btn btn-info" href="#"><?php _e('Add Coupon','ab') ?></a>
11
+ </div>
12
+ </div>
13
+ </div>
14
+ </div>
15
+
16
+
17
+ <div class="modal fade" id="lite_notice" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
18
+ <div class="modal-dialog">
19
+ <div class="modal-content">
20
+ <div class="modal-header">
21
+ <h4 class="modal-title"><?php _e('Notice', 'ab') ?></h4>
22
+ </div>
23
+ <div class="modal-body">
24
+ <?php _e('This function is disabled in the lite version of Bookly. If you find the plugin useful for your business please consider buying a licence for the full version. It costs just $38 and for this money you will get many useful functions, lifetime free update and excellent support! More information can be found here', 'ab'); ?>: <a href="http://bookly.ladela.com" target="_blank">http://bookly.ladela.com</a>
25
+ </div>
26
+ <div class="modal-footer">
27
+ <button type="button" class="btn btn-default" data-dismiss="modal"><?php _e('Close', 'ab') ?></button>
28
+ </div>
29
+ </div><!-- /.modal-content -->
30
+ </div><!-- /.modal-dialog -->
31
+ </div><!-- /.modal -->
backend/modules/customer/AB_CustomerController.php ADDED
@@ -0,0 +1,188 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ include 'forms/AB_CustomerForm.php';
6
+
7
+ class AB_CustomerController extends AB_Controller {
8
+
9
+ public function index() {
10
+ if ( !empty ( $_POST )){
11
+ $this->importCustomers();
12
+ }
13
+
14
+ $path = dirname( __DIR__ );
15
+
16
+ wp_enqueue_style( 'ab-style', plugins_url( 'resources/css/ab_style.css', $path ) );
17
+ wp_enqueue_style( 'ab-bootstrap', plugins_url( 'resources/bootstrap/css/bootstrap.min.css', $path ) );
18
+ wp_enqueue_script( 'ab-bootstrap', plugins_url( 'resources/bootstrap/js/bootstrap.min.js', $path ), array( 'jquery' ) );
19
+ wp_enqueue_script( 'ab-angularjs', plugins_url( 'resources/js/angular-1.0.6.min.js', $path ) );
20
+ wp_enqueue_script( 'ab-angularui', plugins_url( 'resources/js/angular-ui-0.4.0.min.js', $path ) );
21
+ wp_enqueue_script( 'ab-ng-sanitize', plugins_url( 'resources/js/angular-sanitize-1.0.6.min.js', $path ) );
22
+ wp_enqueue_script( 'ab-ng-app', plugins_url( 'resources/js/ng-app.js', __FILE__ ), array( 'jquery', 'ab-angularjs', 'ab-angularui', 'ab-ng-sanitize' ) );
23
+ wp_enqueue_script( 'ab-ng-new_customer_dialog', plugins_url( 'resources/js/ng-new_customer_dialog.js', dirname(__FILE__) . '/../../AB_Backend.php' ), array( 'jquery', 'ab-angularjs' ) );
24
+
25
+ $this->render('index');
26
+ }
27
+
28
+ /**
29
+ * Get list of customers.
30
+ */
31
+ public function executeGetCustomers() {
32
+ $wpdb = $this->getWpdb();
33
+
34
+ $response = array(
35
+ 'status' => 'ok',
36
+ 'data' => array(
37
+ 'customers' => array(),
38
+ 'total' => 0,
39
+ 'pages' => 0,
40
+ 'active_page' => 0,
41
+ )
42
+ );
43
+
44
+ $page = intval( $this->getParameter( 'page' ) );
45
+ $sort = in_array( $this->getParameter( 'sort' ), array( 'name', 'phone', 'email', 'notes', 'last_appointment', 'total_appointments', 'payments' ) )
46
+ ? $this->getParameter( 'sort' ) : 'name';
47
+ $order = in_array( $this->getParameter( 'order' ), array( 'asc', 'desc' ) ) ? $this->getParameter( 'order' ) : 'asc';
48
+ $filter = $wpdb->_real_escape( $this->getParameter( 'filter' ) );
49
+
50
+ $items_per_page = 20;
51
+ $total = $wpdb->get_var( 'SELECT COUNT(*) FROM `ab_customer`' );
52
+ $pages = ceil( $total / $items_per_page );
53
+ if ( $page < 1 || $page > $pages ) {
54
+ $page = 1;
55
+ }
56
+
57
+ if ( $total ) {
58
+ $query = "SELECT `c`.*, MAX(`a`.`start_date`) AS `last_appointment`, COUNT(`a`.`id`) AS `total_appointments`, COALESCE(SUM(`p`.`total`),0) AS `payments`
59
+ FROM `ab_customer` `c`
60
+ LEFT JOIN `ab_customer_appointment` `ca` ON `ca`.`customer_id` = `c`.`id`
61
+ LEFT JOIN `ab_appointment` `a` ON `a`.`id` = `ca`.`appointment_id`
62
+ LEFT JOIN `ab_payment` `p` ON `p`.`appointment_id` = `a`.`id` and `p`.`customer_id` = `c`.`id`";
63
+ // WHERE
64
+ if ( $filter !== '' ) {
65
+ $query .= " WHERE `c`.`name` LIKE '%{$filter}%' OR `c`.`phone` LIKE '%{$filter}%' OR `c`.`email` LIKE '%{$filter}%'";
66
+ }
67
+ // GROUP BY
68
+ $query .= ' GROUP BY `c`.`id`';
69
+ // ORDER BY
70
+ $query .= " ORDER BY {$sort} {$order}";
71
+ // LIMIT
72
+ $start = ( $page - 1) * $items_per_page;
73
+ $query .= " LIMIT {$start}, {$items_per_page}";
74
+
75
+ $data = $wpdb->get_results( $query );
76
+ array_walk( $data, function ( $row ) {
77
+ $row->last_appointment = AB_CommonUtils::getFormattedDateTime( $row->last_appointment );
78
+ $row->payments = AB_CommonUtils::formatPrice( $row->payments );
79
+ } );
80
+
81
+ // Populate response.
82
+ $response[ 'data' ][ 'customers' ] = $data;
83
+ $response[ 'data' ][ 'total' ] = $total;
84
+ $response[ 'data' ][ 'pages' ] = $pages;
85
+ $response[ 'data' ][ 'active_page' ] = $page;
86
+ }
87
+
88
+ echo json_encode( $response );
89
+ exit ( 0 );
90
+ }
91
+
92
+ /**
93
+ * Create or edit a customer.
94
+ *
95
+ * @Security user
96
+ */
97
+ public function executeSaveCustomer() {
98
+ $response = array();
99
+ $form = new AB_CustomerForm();
100
+
101
+ do {
102
+ if ( $this->getParameter( 'name' ) !== '' ) {
103
+ $form->bind( $this->getPostParameters() );
104
+ /** @var AB_Customer $customer */
105
+ $customer = $form->save();
106
+ if ( $customer ) {
107
+ $response[ 'status' ] = 'ok';
108
+ $response[ 'customer' ] = array(
109
+ 'id' => $customer->id,
110
+ 'name' => $customer->name,
111
+ 'phone' => $customer->phone,
112
+ 'email' => $customer->email,
113
+ 'notes' => $customer->notes,
114
+ 'jsonString' => json_encode( array(
115
+ 'name' => $customer->name,
116
+ 'phone' => $customer->phone,
117
+ 'email' => $customer->email,
118
+ 'notes' => $customer->notes
119
+ ) )
120
+ );
121
+ break;
122
+ }
123
+ }
124
+ $response[ 'status' ] = 'error';
125
+ $response[ 'errors' ] = array( 'name' => array( 'required' ) );
126
+ } while ( 0 );
127
+
128
+ echo json_encode( $response );
129
+ exit ( 0 );
130
+ }
131
+
132
+ /**
133
+ * Import customers from CSV.
134
+ */
135
+ private function importCustomers() {
136
+ @ini_set( 'auto_detect_line_endings', true );
137
+
138
+ $csv_mime_types = array(
139
+ 'text/csv',
140
+ 'application/csv',
141
+ 'text/comma-separated-values',
142
+ 'application/excel',
143
+ 'application/vnd.ms-excel',
144
+ 'application/vnd.msexcel'
145
+ );
146
+
147
+ if ( in_array( $_FILES[ 'import_customers_file' ][ 'type' ], $csv_mime_types ) ) {
148
+ $file = fopen ( $_FILES[ 'import_customers_file' ][ 'tmp_name' ], 'r' );
149
+ while ( $line = fgetcsv( $file, null, $this->getParameter( 'import_customers_delimiter' ) ) ) {
150
+ if ( !empty ( $line[ 0 ] ) ) {
151
+ $customer = new AB_Customer();
152
+ $customer->set( 'name', $line[ 0 ] );
153
+ if ( isset ( $line[ 1 ] ) ) {
154
+ $customer->set( 'phone', $line[ 1 ] );
155
+ }
156
+ if ( isset ( $line[ 2 ] ) ) {
157
+ $customer->set( 'email', $line[ 2 ] );
158
+ }
159
+ $customer->save();
160
+ }
161
+ }
162
+ }
163
+ }
164
+
165
+ /**
166
+ * Get angulars template for new customer dialog.
167
+ * @Security user
168
+ */
169
+ public function executeGetNgNewCustomerDialogTemplate() {
170
+ $this->render( 'ng-new_customer_dialog' );
171
+ exit ( 0 );
172
+ }
173
+
174
+ /**
175
+ * Delete a customer.
176
+ */
177
+ public function executeDeleteCustomer() {
178
+ $this->getWpdb()->delete('ab_customer', array( 'id' => $this->getParameter( 'id' ) ), array( '%d' ) );
179
+ }
180
+
181
+ /**
182
+ * Override parent method to add 'wp_ajax_ab_' prefix
183
+ * so current 'execute*' methods look nicer.
184
+ */
185
+ protected function registerWpActions( $prefix = '' ) {
186
+ parent::registerWpActions( 'wp_ajax_ab_' );
187
+ }
188
+ }
backend/modules/customer/forms/AB_CustomerForm.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ include AB_PATH.'/lib/entities/AB_Customer.php';
6
+
7
+ /**
8
+ * Class AB_CustomerForm
9
+ */
10
+ class AB_CustomerForm extends AB_Form {
11
+
12
+ /**
13
+ * Constructor.
14
+ */
15
+ public function __construct() {
16
+ parent::$entity_class = 'AB_Customer';
17
+ parent::__construct();
18
+ }
19
+
20
+ public function configure() {
21
+ $this->setFields(array(
22
+ 'name',
23
+ 'phone',
24
+ 'email',
25
+ 'notes'
26
+ ));
27
+ }
28
+ }
backend/modules/customer/resources/js/ng-app.js ADDED
@@ -0,0 +1,226 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ;(function() {
2
+
3
+ var module = angular.module('customers', ['ui', 'newCustomerDialog', 'ngSanitize']);
4
+
5
+ module.factory('dataSource', function($q, $rootScope) {
6
+ var ds = {
7
+ customers : [],
8
+ total : 0,
9
+ pages : [],
10
+ form : {
11
+ new_customer : {
12
+ name : null,
13
+ phone : null,
14
+ email : null,
15
+ notes : null
16
+ }
17
+ },
18
+ loadData : function(params) {
19
+ var deferred = $q.defer();
20
+ jQuery.ajax({
21
+ url : ajaxurl,
22
+ type : 'POST',
23
+ data : jQuery.extend({ action : 'ab_get_customers' }, params),
24
+ dataType : 'json',
25
+ success : function(response) {
26
+ if (response.status === 'ok') {
27
+ ds.customers = response.data.customers;
28
+ ds.total = response.data.total;
29
+ ds.pages = [];
30
+ for (var i = 0; i < response.data.pages; ++ i) {
31
+ ds.pages.push({
32
+ number : i + 1,
33
+ active : response.data.active_page == i + 1
34
+ });
35
+ }
36
+ }
37
+ $rootScope.$apply(deferred.resolve);
38
+ },
39
+ error : function() {
40
+ ds.customers = [];
41
+ ds.total = 0;
42
+ $rootScope.$apply(deferred.resolve);
43
+ }
44
+ });
45
+ return deferred.promise;
46
+ }
47
+ };
48
+
49
+ return ds;
50
+ });
51
+
52
+ module.controller('customersCtrl', function($scope, dataSource) {
53
+ // Set up initial data.
54
+ var params = {
55
+ page : 1,
56
+ sort : 'name',
57
+ order : 'asc',
58
+ filter : ''
59
+ };
60
+ $scope.loading = true;
61
+ $scope.css_class = {
62
+ name : 'asc',
63
+ phone : '',
64
+ email : '',
65
+ notes : '',
66
+ last_appointment : '',
67
+ total_appointments : '',
68
+ payments : ''
69
+ };
70
+ // Set up data source (data will be loaded in reload function).
71
+ $scope.dataSource = dataSource;
72
+
73
+ $scope.reload = function( opt ) {
74
+ $scope.loading = true;
75
+ if (opt !== undefined) {
76
+ if (opt.sort !== undefined) {
77
+ if (params.sort === opt.sort) {
78
+ // Toggle order when sorting by the same field.
79
+ params.order = params.order === 'asc' ? 'desc' : 'asc';
80
+ } else {
81
+ params.order = 'asc';
82
+ }
83
+ $scope.css_class = {
84
+ name : '',
85
+ phone : '',
86
+ email : '',
87
+ notes : '',
88
+ last_appointment : '',
89
+ total_appointments : '',
90
+ payments : ''
91
+ };
92
+ $scope.css_class[opt.sort] = params.order;
93
+ }
94
+ jQuery.extend(params, opt);
95
+ }
96
+ dataSource.loadData(params).then(function() {
97
+ $scope.loading = false;
98
+ });
99
+ };
100
+
101
+ var filter_delay = null;
102
+ $scope.$watch('filter', function() {
103
+ if (filter_delay !== null) {
104
+ clearTimeout(filter_delay);
105
+ }
106
+ filter_delay = setTimeout(function() {
107
+ filter_delay = null;
108
+ $scope.$apply(function($scope) {
109
+ $scope.reload({filter: $scope.filter});
110
+ });
111
+ }, 400);
112
+ });
113
+
114
+ /**
115
+ * Edit customer.
116
+ *
117
+ * @param object customer
118
+ * @param object params
119
+ */
120
+ $scope.saveCustomer = function(customer, params) {
121
+ customer.edit_name = false;
122
+ customer.edit_phone = false;
123
+ customer.edit_email = false;
124
+ customer.edit_notes = false;
125
+ customer.errors = {};
126
+
127
+ $scope.loading = true;
128
+ jQuery.ajax({
129
+ url : ajaxurl,
130
+ type : 'POST',
131
+ data : {
132
+ action : 'ab_save_customer',
133
+ id : customer.id,
134
+ name : customer.name,
135
+ phone : customer.phone,
136
+ email : customer.email,
137
+ notes : customer.notes
138
+ },
139
+ dataType : 'json',
140
+ success : function(response) {
141
+ $scope.$apply(function($scope) {
142
+ if (response.status === 'error') {
143
+ jQuery.each(response.errors, function(field, errors) {
144
+ customer.errors[field] = {};
145
+ customer['edit_' + field] = true;
146
+ jQuery.each(errors, function(key, error) {
147
+ customer.errors[field][error] = true;
148
+ });
149
+ });
150
+ }
151
+ $scope.loading = false;
152
+ });
153
+ },
154
+ error : function(response) {
155
+ $scope.$apply(function($scope) {
156
+ $scope.loading = false;
157
+ });
158
+ }
159
+ });
160
+ };
161
+
162
+ /**
163
+ * Callback for creating new customer.
164
+ *
165
+ * @param object customer
166
+ */
167
+ $scope.createCustomer = function(customer) {
168
+ dataSource.customers.push(customer);
169
+ $scope.reload(params.page);
170
+ };
171
+
172
+ /**
173
+ * Delete customer.
174
+ *
175
+ * @param customer
176
+ */
177
+ $scope.deleteCustomer = function(customer) {
178
+ if (confirm('Are you sure ?')) {
179
+ jQuery.ajax({
180
+ url : ajaxurl,
181
+ type : 'POST',
182
+ data : {
183
+ action : 'ab_delete_customer',
184
+ id : customer.id
185
+ },
186
+ dataType : 'json',
187
+ success : function(response) {
188
+ $scope.$apply(function($scope) {
189
+ jQuery.each(dataSource.customers, function(index, value) {
190
+ if(value.id == customer.id) {
191
+ dataSource.customers.splice(index, 1);
192
+ $scope.reload(params.page);
193
+ return false;
194
+ }
195
+ });
196
+ });
197
+ }
198
+ });
199
+ }
200
+ };
201
+ });
202
+
203
+ /**
204
+ * Directive for setting focus to element.
205
+ */
206
+ module.directive('focusMe', function($timeout) {
207
+ return {
208
+ link: function(scope, element, attrs) {
209
+ scope.$watch(attrs.focusMe, function(value) {
210
+ if (value) {
211
+ $timeout(function() {
212
+ element[0].focus();
213
+ });
214
+ }
215
+ });
216
+ }
217
+ };
218
+ });
219
+
220
+ module.filter('nl2br', function() {
221
+ return function(input) {
222
+ return ('' + input).split('\n').join('<br>');
223
+ };
224
+ });
225
+
226
+ })();
backend/modules/customer/templates/_import.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <div id="ab_import_customers_dialog" class="modal hide fade" tabindex=-1 role="dialog" aria-labelledby="importCustomersModalLabel" aria-hidden="true">
3
+ <div class="dialog-content">
4
+ <form class="form-horizontal" enctype="multipart/form-data" action="?page=ab-system-customers" method="POST">
5
+ <div class="modal-header">
6
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
7
+ <h3 id="importCustomersModalLabel"><?php _e( 'Import', 'ab' ) ?></h3>
8
+ </div>
9
+ <div class="modal-body">
10
+ <div class="control-group">
11
+ <label class="control-label"><?php _e( 'Note' , 'ab' ) ?></label>
12
+ <div class="controls">
13
+ <?php _e( 'You may import list of clients in CSV format. The file needs to have three columns: Name, Phone and Email.' , 'ab' ) ?>
14
+ </div>
15
+ </div>
16
+ <div class="control-group">
17
+ <label class="control-label"><?php _e( 'Select file' , 'ab' ) ?></label>
18
+ <div class="controls">
19
+ <input name="import_customers_file" type="file">
20
+ </div>
21
+ </div>
22
+ <div class="control-group">
23
+ <label class="control-label"><?php _e( 'Delimiter' , 'ab' ) ?></label>
24
+ <div class="controls">
25
+ <select name="import_customers_delimiter">
26
+ <option value=","><?php _e( 'Comma (,)', 'ab' ) ?></option>
27
+ <option value=";"><?php _e( 'Semicolon (;)', 'ab' ) ?></option>
28
+ </select>
29
+ </div>
30
+ </div>
31
+ </div>
32
+ <div class="modal-footer">
33
+ <div class="ab-modal-button">
34
+ <input type="hidden" name="import">
35
+ <input type="submit" class="btn btn-info ab-popup-save ab-update-button" value="<?php _e( 'Import' , 'ab' ) ?>" />
36
+ <button class="ab-reset-form" data-dismiss="modal" aria-hidden="true"><?php _e( 'Cancel' , 'ab' ) ?></button>
37
+ </div>
38
+ </div>
39
+ </form>
40
+ </div>
41
+ </div>
backend/modules/customer/templates/index.php ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <div class="ab-title"><?php _e( 'Customers', 'ab' ); ?></div>
3
+ <div ng-app="customers" ng-controller="customersCtrl" style="min-width: 800px;" class="form-horizontal ng-cloak">
4
+
5
+ <div class="control-group left">
6
+ <label class=control-label><?php _e( 'Quick search customer', 'ab' ) ?></label>
7
+ <div class=controls>
8
+ <input type=text ng-model=filter />
9
+ </div>
10
+ </div>
11
+
12
+ <div style="margin-left: 50%;">
13
+ <div style="display: inline;" new-customer-dialog="createCustomer(customer)" backdrop="true" btn-class="btn btn-info"></div>
14
+ <div style="display: inline;" btn-class="btn btn-info">
15
+ <a href="#ab_import_customers_dialog" class="btn btn-info" data-toggle="modal"><?php _e( 'Import' , 'ab' ) ?></a>
16
+ <?php include "_import.php"; ?>
17
+ </div>
18
+ </div>
19
+
20
+ <table id="ab_customers_list" class="table table-striped" cellspacing=0 cellpadding=0 border=0 style="clear: both;">
21
+ <thead>
22
+ <tr>
23
+ <th width=150 ng-class=css_class.name><a href="" ng-click=reload({sort:'name'})><?php _e( 'Name', 'ab' ); ?></a></th>
24
+ <th width=100 ng-class=css_class.phone><a href="" ng-click=reload({sort:'phone'})><?php _e( 'Phone', 'ab' ); ?></a></th>
25
+ <th width=150 ng-class=css_class.email><a href="" ng-click=reload({sort:'email'})><?php _e( 'Email', 'ab' ); ?></a></th>
26
+ <th width=150 ng-class=css_class.notes><a href="" ng-click=reload({sort:'notes'})><?php _e( 'Notes', 'ab' ); ?></a></th>
27
+ <th width=150 ng-class=css_class.last_appointment><a href="" ng-click=reload({sort:'last_appointment'})><?php _e( 'Last appointment', 'ab' ); ?></a></th>
28
+ <th width=150 ng-class=css_class.total_appointments><a href="" ng-click=reload({sort:'total_appointments'})><?php _e( 'Total appointments', 'ab'); ?></a></th>
29
+ <th width=150 ng-class=css_class.payments><a href="" ng-click=reload({sort:'payments'})><?php _e( 'Payments', 'ab'); ?></a></th>
30
+ </tr>
31
+ </thead>
32
+ <tbody>
33
+ <tr ng-repeat="customer in dataSource.customers">
34
+ <td>
35
+ <div ng-click="customer.edit_name = true" ng-hide=customer.edit_name class=displayed-value>{{customer.name}}</div>
36
+ <span ng-show=customer.errors.name.required><?php _e( 'Required', 'ab' ) ?></span>
37
+ <input class=ab-value ng-model=customer.name ui-event="{blur:'saveCustomer(customer)'}" ng-show=customer.edit_name focus-me=customer.edit_name required />
38
+ </td>
39
+ <td class="ab-phone">
40
+ <div ng-click="customer.edit_phone = true" ng-hide=customer.edit_phone class=displayed-value>{{customer.phone}}</div>
41
+ <input class=ab-value ng-model=customer.phone ui-event="{blur:'saveCustomer(customer)'}" ng-show=customer.edit_phone focus-me=customer.edit_phone />
42
+ </td>
43
+ <td>
44
+ <div ng-click="customer.edit_email = true" ng-hide=customer.edit_email class=displayed-value>{{customer.email}}</div>
45
+ <input class=ab-value ng-model=customer.email ui-event="{blur:'saveCustomer(customer)'}" ng-show=customer.edit_email focus-me=customer.edit_email />
46
+ </td>
47
+ <td>
48
+ <div ng-click="customer.edit_notes = true" ng-hide=customer.edit_notes class=displayed-value ng-bind-html="customer.notes | nl2br"></div>
49
+ <textarea class=ab-value ng-model="customer.notes" ui-event="{blur:'saveCustomer(customer)'}" ng-show=customer.edit_notes focus-me=customer.edit_notes></textarea>
50
+ </td>
51
+ <td>
52
+ <div ng-model=customer.last_appointment class=displayed-value>{{customer.last_appointment}}</div>
53
+ </td>
54
+ <td>
55
+ <div ng-model=customer.total_appointments class=displayed-value>{{customer.total_appointments}}</div>
56
+ </td>
57
+ <td>
58
+ <div ng-model=customer.payments class=displayed-value>{{customer.payments}}</div>
59
+ </td>
60
+ <td><a href="" ng-click="deleteCustomer(customer)" role="button" class="btn btn-danger" id="{{customer.id}}" name="customer_delete"><?php _e( 'Delete', 'ab' ) ?></a></td>
61
+ </tr>
62
+ <tr ng-hide="dataSource.customers.length || loading"><td colspan=6><?php _e( 'No customers', 'ab' ); ?></td></tr>
63
+ </tbody>
64
+ </table>
65
+ <div class="btn-toolbar" ng-hide="dataSource.pages.length == 1">
66
+ <div class="btn-group">
67
+ <button ng-click=reload({page:page.number}) class="btn" ng-repeat="page in dataSource.pages" ng-switch on=page.active>
68
+ <span ng-switch-when=true>{{page.number}}</span>
69
+ <a href="" ng-switch-default>{{page.number}}</a>
70
+ </button>
71
+ </div>
72
+ </div>
73
+ <div ng-show="loading" class="loading-indicator">
74
+ <img src="<?php echo plugins_url( 'backend/resources/images/ajax_loader_32x32.gif', AB_PATH . '/main.php' ) ?>" alt="" />
75
+ </div>
76
+ </div>
backend/modules/customer/templates/ng-new_customer_dialog.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <div>
3
+ <a href=#ab_new_customer_dialog class="{{btn_class}}" data-toggle=modal data-backdrop={{backdrop}}><?php _e( 'New customer' , 'ab' ) ?></a>
4
+ <div id=ab_new_customer_dialog class="modal hide fade" tabindex=-1 role=dialog aria-labelledby=myModalLabel aria-hidden=true>
5
+ <div class=dialog-content>
6
+ <form class=form-horizontal ng-hide=loading>
7
+ <div class=modal-header>
8
+ <button type=button class=close data-dismiss=modal aria-hidden=true>×</button>
9
+ <h3 id=myModalLabel><?php _e( 'New Customer', 'ab' ) ?></h3>
10
+ </div>
11
+ <div class=modal-body>
12
+ <div class=control-group>
13
+ <label class=control-label><?php _e( 'Name' , 'ab' ) ?></label>
14
+ <div class=controls>
15
+ <input type=text ng-model=form.name required />
16
+ <span style="font-size: 11px;color: red" ng-show=errors.name.required><?php _e( 'Required' , 'ab' ) ?></span>
17
+ </div>
18
+ </div>
19
+ <div class=control-group>
20
+ <label class=control-label><?php _e( 'Phone' , 'ab' ) ?></label>
21
+ <div class=controls>
22
+ <input type=text ng-model=form.phone />
23
+ </div>
24
+ </div>
25
+ <div class=control-group>
26
+ <label class=control-label><?php _e( 'Email' , 'ab' ) ?></label>
27
+ <div class=controls>
28
+ <input type=text ng-model=form.email />
29
+ </div>
30
+ </div>
31
+ <div class=control-group>
32
+ <label class=control-label><?php _e( 'Notes' , 'ab' ) ?></label>
33
+ <div class=controls>
34
+ <textarea ng-model=form.notes></textarea>
35
+ </div>
36
+ </div>
37
+ </div>
38
+ <div class=modal-footer>
39
+ <div class=ab-modal-button>
40
+ <button ng-click=processForm() class="btn btn-info ab-popup-save ab-update-button"><?php _e( 'Save customer' , 'ab' ) ?></button>
41
+ <button class=ab-reset-form data-dismiss=modal aria-hidden=true><?php _e( 'Cancel' , 'ab' ) ?></button>
42
+ </div>
43
+ </div>
44
+ </form>
45
+ <div ng-show=loading class=loading-indicator>
46
+ <img src="<?php echo plugins_url( 'backend/resources/images/ajax_loader_32x32.gif', AB_PATH . '/main.php' ) ?>" alt="" />
47
+ </div>
48
+ </div>
49
+ </div>
50
+ </div>
backend/modules/export/AB_ExportController.php ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ /**
6
+ * Class AB_ExportController
7
+ */
8
+ class AB_ExportController extends AB_Controller {
9
+
10
+ public function index() {
11
+ $path = dirname( __DIR__ );
12
+ wp_enqueue_style( 'ab-style', plugins_url( 'resources/css/ab_style.css', $path ) );
13
+ wp_enqueue_style( 'ab-bootstrap', plugins_url( 'resources/bootstrap/css/bootstrap.min.css', $path ) );
14
+ wp_enqueue_script( 'ab-bootstrap', plugins_url( 'resources/bootstrap/js/bootstrap.min.js', $path ), array( 'jquery' ) );
15
+ wp_enqueue_script( 'ab-date', plugins_url( 'resources/js/date.js', $path ), array( 'jquery' ) );
16
+ wp_enqueue_script( 'ab-daterangepicker-js', plugins_url( 'resources/js/daterangepicker.js', $path ), array( 'jquery' ) );
17
+ wp_enqueue_style( 'ab-daterangepicker-css', plugins_url( 'resources/css/daterangepicker.css', $path ) );
18
+ wp_enqueue_script( 'ab-bootstrap-select-js', plugins_url( 'resources/js/bootstrap-select.min.js', $path ));
19
+ wp_enqueue_style( 'ab-bootstrap-select-css', plugins_url( 'resources/css/bootstrap-select.min.css', $path ));
20
+ wp_localize_script( 'ab-daterangepicker-js', 'BooklyL10n', array(
21
+ 'today' => __( 'Today', 'ab' ),
22
+ 'yesterday' => __( 'Yesterday', 'ab' ),
23
+ 'last_7' => __( 'Last 7 Days', 'ab' ),
24
+ 'last_30' => __( 'Last 30 Days', 'ab' ),
25
+ 'this_month' => __( 'This Month', 'ab' ),
26
+ 'last_month' => __( 'Last Month', 'ab' ),
27
+ 'custom_range' => __( 'Custom Range', 'ab' ),
28
+ 'apply' => __( 'Apply', 'ab' ),
29
+ 'clear' => __( 'Clear', 'ab' ),
30
+ 'to' => __( 'To', 'ab' ),
31
+ 'from' => __( 'From', 'ab' ),
32
+ 'month' => array(
33
+ 0 => __( 'January', 'ab' ),
34
+ 1 => __( 'February', 'ab' ),
35
+ 2 => __( 'March', 'ab' ),
36
+ 3 => __( 'April', 'ab' ),
37
+ 4 => __( 'May', 'ab' ),
38
+ 5 => __( 'June', 'ab' ),
39
+ 6 => __( 'July', 'ab' ),
40
+ 7 => __( 'August', 'ab' ),
41
+ 8 => __( 'September', 'ab' ),
42
+ 9 => __( 'October', 'ab' ),
43
+ 10 => __( 'November', 'ab' ),
44
+ 11 => __( 'December', 'ab' )
45
+ ),
46
+ 'day' => array(
47
+ 'Mon' => __( 'Mon', 'ab' ),
48
+ 'Tue' => __( 'Tue', 'ab' ),
49
+ 'Wed' => __( 'Wed', 'ab' ),
50
+ 'Thu' => __( 'Thu', 'ab' ),
51
+ 'Fri' => __( 'Fri', 'ab' ),
52
+ 'Sat' => __( 'Sat', 'ab' ),
53
+ 'Sun' => __( 'Sun', 'ab' )
54
+ )
55
+ ));
56
+ $this->render( 'index' );
57
+ }
58
+
59
+ /**
60
+ * Export Appointment to CSV
61
+ */
62
+ public function executeExportToCSV ( ) {
63
+ $start_date = new DateTime( $this->getParameter( 'date_start' ) );
64
+ $start_date = $start_date->format('Y-m-d H:i:s');
65
+ $end_date = new DateTime( $this->getParameter( 'date_end' ) );
66
+ $end_date->modify( '+1 day' );
67
+ $end_date = $end_date->format('Y-m-d H:i:s');
68
+
69
+ header('Content-Type: text/csv; charset=' . (get_locale() == 'ru_RU') ? 'windows-1251': 'utf-8');
70
+ header('Content-Disposition: attachment; filename=appointment.csv');
71
+
72
+ if (get_locale() == 'ru_RU'){
73
+ $headings = array(
74
+ iconv('utf-8', 'windows-1251', __('Customer name', 'ab')),
75
+ iconv('utf-8', 'windows-1251', __('Service title', 'ab')),
76
+ iconv('utf-8', 'windows-1251', __('Start date', 'ab')),
77
+ iconv('utf-8', 'windows-1251', __('End date', 'ab')),
78
+ iconv('utf-8', 'windows-1251', __('Notes', 'ab')));
79
+ }else{
80
+ $headings = array(
81
+ __('Customer name', 'ab'),
82
+ __('Service title', 'ab'),
83
+ __('Start date', 'ab'),
84
+ __('End date', 'ab'),
85
+ __('Notes', 'ab'));
86
+ }
87
+ $output = fopen('php://output', 'w');
88
+ fputcsv($output, $headings);
89
+
90
+ $appointments = $this->getWpdb()->get_results("
91
+ SELECT c.name AS customer_name,
92
+ s.title AS service_title,
93
+ a.start_date AS start_date,
94
+ a.end_date AS end_date,
95
+ ca.notes AS notes
96
+ FROM ab_customer_appointment ca
97
+ LEFT JOIN ab_appointment a ON a.id = ca.appointment_id
98
+ LEFT JOIN ab_service s ON a.service_id = s.id
99
+ LEFT JOIN ab_customer c ON ca.customer_id = c.id
100
+ WHERE a.start_date between '{$start_date}' AND '{$end_date}'
101
+ ORDER BY a.start_date DESC
102
+ ", ARRAY_A);
103
+
104
+ foreach( $appointments as $appointment ) {
105
+ if (get_locale() == 'ru_RU'){
106
+ $appointment['customer_name'] = iconv('utf-8', 'windows-1251', $appointment['customer_name']);
107
+ $appointment['notes'] = iconv('utf-8', 'windows-1251', $appointment['notes']);
108
+ $appointment['service_title'] = iconv('utf-8', 'windows-1251', $appointment['service_title']);
109
+ }
110
+ fputcsv($output, $appointment);
111
+ }
112
+ fclose($output);
113
+ exit();
114
+ }
115
+
116
+ /**
117
+ * Override parent method to add 'wp_ajax_ab_' prefix
118
+ * so current 'execute*' methods look nicer.
119
+ */
120
+ protected function registerWpActions( $prefix = '' ) {
121
+ parent::registerWpActions( 'wp_ajax_ab_' );
122
+ }
123
+ }
backend/modules/export/templates/index.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <div class="ab-title"><?php _e( 'Export appointments', 'ab' ); ?></div>
3
+ <div class=ab-nav-payment>
4
+ <form action="<?php echo get_admin_url(); ?>admin-ajax.php?action=ab_export_to_csv" method="post" style="margin: 0">
5
+ <div id=reportrange class="pull-left ab-reportrange" style="margin-bottom: 10px">
6
+
7
+ <i class="icon-calendar icon-large"></i>
8
+ <span data-date="<?php echo date( 'F j, Y', strtotime( '-30 day' ) ) ?> - <?php echo date( 'F j, Y' ) ?>"><?php echo date_i18n( get_option( 'date_format' ), strtotime( '-30 day' ) ) ?> - <?php echo date_i18n( get_option( 'date_format' ) ) ?></span> <b style="margin-top: 8px;" class=caret></b>
9
+
10
+ </div>
11
+ <input type="hidden" id="date_start" name="date_start" value="<?php echo date_i18n( get_option( 'date_format' ) ) ?>"/>
12
+ <input type="hidden" id="date_end" name="date_end" value="<?php echo date_i18n( get_option( 'date_format' ) ) ?>"/>
13
+ <input type="submit" class="btn btn-info right-margin left" value="<?php _e('Export to CSV','ab') ?>">
14
+ </form>
15
+
16
+ </div>
17
+ <script type="text/javascript">
18
+ jQuery(function($) {
19
+ var data = {},
20
+ $report_range = $('#reportrange span'),
21
+ picker_ranges = {},
22
+ l10nRanges = {
23
+ response: function(start, end) {
24
+ return $.post(ajaxurl, {action: 'ab_l10n_ranges', start: start, end: end});
25
+ },
26
+ l10n: function(start, end) {
27
+ this.response(start, end).done(function(response) {
28
+ var ranges = JSON.parse(response);
29
+ $report_range.data('date', start.toString('MMMM d, yyyy') + ' - ' + end.toString('MMMM d, yyyy'));
30
+ $report_range.html(ranges.start + ' - ' + ranges.end);
31
+ });
32
+ }
33
+ };
34
+
35
+ picker_ranges[BooklyL10n.today] = ['today', 'today'];
36
+ picker_ranges[BooklyL10n.yesterday] = ['yesterday', 'yesterday'];
37
+ picker_ranges[BooklyL10n.last_7] = [Date.today().add({ days: -6 }), 'today'];
38
+ picker_ranges[BooklyL10n.last_30] = [Date.today().add({ days: -30 }), 'today','selected'];
39
+ picker_ranges[BooklyL10n.this_month] = [Date.today().moveToFirstDayOfMonth(), Date.today().moveToLastDayOfMonth()];
40
+ picker_ranges[BooklyL10n.last_month] = [Date.today().moveToFirstDayOfMonth().add({ months: -1 }), Date.today().moveToFirstDayOfMonth().add({ days: -1 })];
41
+
42
+ $('#reportrange').daterangepicker({ranges: picker_ranges}, function(start, end) {
43
+ l10nRanges.l10n(start, end);
44
+ $('#date_start').val(start);
45
+ $('#date_end').val(end);
46
+ });
47
+ });
48
+ </script>
backend/modules/notifications/AB_NotificationsController.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ class AB_NotificationsController extends AB_Controller {
6
+
7
+ public function index() {
8
+ $path = dirname( __DIR__ );
9
+ wp_enqueue_style( 'ab-style', plugins_url( 'resources/css/ab_style.css', $path ) );
10
+ wp_enqueue_style( 'ab-bootstrap', plugins_url( 'resources/bootstrap/css/bootstrap.min.css', $path ) );
11
+ wp_enqueue_script( 'ab-bootstrap', plugins_url( 'resources/bootstrap/js/bootstrap.min.js', $path ), array( 'jquery' ) );
12
+
13
+ $this->notifications = array(
14
+ 'client_info' => array(
15
+ 'name' => __( 'Notification to Customer about Appointment details', 'ab' ),
16
+ 'subject' => __( 'Your appointment information', 'ab' ),
17
+ 'message' => wpautop( __("Dear [[CLIENT_NAME]].\n\nThis is confirmation that you have booked [[SERVICE_NAME]].\n\nWe are waiting you at [[COMPANY_ADDRESS]] on [[APPOINTMENT_DATE]] at [[APPOINTMENT_TIME]].\n\nThank you for choosing our company.\n\n[[COMPANY_NAME]]\n[[COMPANY_PHONE]]\n[[COMPANY_WEBSITE]]", 'ab' ) ),
18
+ ),
19
+ 'provider_info' => array(
20
+ 'name' => __( 'Notification to Staff Member about Appointment details', 'ab' ),
21
+ 'subject' => __( 'New booking information', 'ab' ),
22
+ 'message' => wpautop( __( "Hello.\n\nYou have new booking.\n\nService: [[SERVICE_NAME]]\nDate: [[APPOINTMENT_DATE]]\nTime: [[APPOINTMENT_TIME]]\nClient name: [[CLIENT_NAME]]\nClient phone: [[CLIENT_PHONE]]\nClient email: [[CLIENT_EMAIL]]\nClient notes: [[CLIENT_NOTES]]", 'ab' ) ),
23
+ ),
24
+ 'evening_next_day' => array(
25
+ 'name' => __( 'Evening reminder to Customer about next day Appointment', 'ab' ),
26
+ 'subject' => __( 'Your appointment at [[COMPANY_NAME]]', 'ab' ),
27
+ 'message' => wpautop( __( "Dear [[CLIENT_NAME]].\n\nWe would like to remind you that you have booked [[SERVICE_NAME]] tomorrow on [[APPOINTMENT_TIME]]. We are waiting you at [[COMPANY_ADDRESS]].\n\nThank you for choosing our company.\n\n[[COMPANY_NAME]]\n[[COMPANY_PHONE]]\n[[COMPANY_WEBSITE]]", 'ab' ) ),
28
+ ),
29
+ 'evening_after' => array(
30
+ 'name' => __( 'Follow-up message on the day after Appointment', 'ab' ),
31
+ 'subject' => __( 'Your visit to [[COMPANY_NAME]]', 'ab' ),
32
+ 'message' => wpautop( __( "Dear [[CLIENT_NAME]].\n\nThank you for choosing [[COMPANY_NAME]]. We hope you were satisfied with your [[SERVICE_NAME]].\n\nThank you and we look forward to seeing you again soon.\n\n[[COMPANY_NAME]]\n[[COMPANY_PHONE]]\n[[COMPANY_WEBSITE]]", 'ab' ) ),
33
+ ),
34
+ 'event_next_day' => array(
35
+ 'name' => __( 'Evening notification with the next day agenda to Staff Member', 'ab' ),
36
+ 'subject' => __( 'Your agenda for [[TOMORROW_DATE]]', 'ab' ),
37
+ 'message' => wpautop( __( "Hello.\n\nYour agenda for tomorrow is:\n\n[[NEXT_DAY_AGENDA]]", 'ab' ) ),
38
+ )
39
+ );
40
+
41
+ $this->render( 'index' );
42
+ }
43
+
44
+ // Protected methods.
45
+
46
+ /**
47
+ * Override parent method to add 'wp_ajax_ab_' prefix
48
+ * so current 'execute*' methods look nicer.
49
+ */
50
+ protected function registerWpActions( $prefix = '' ) {
51
+ parent::registerWpActions( 'wp_ajax_ab_' );
52
+ }
53
+ }
backend/modules/notifications/templates/_tags_client_info.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <tr>
3
+ <th><?php _e('Subject', 'ab') ?></th>
4
+ <th><?php _e('Message', 'ab') ?></th>
5
+ </tr>
6
+ <tr>
7
+ <td><?php _e('[[COMPANY_NAME]] - name of the company', 'ab') ?></td>
8
+ <td><?php _e('[[CLIENT_NAME]] - name of client', 'ab') ?></td>
9
+ </tr>
10
+ <tr>
11
+ <td></td>
12
+ <td><?php _e('[[STAFF_NAME]] - name of staff', 'ab') ?></td>
13
+ </tr>
14
+ <tr>
15
+ <td></td>
16
+ <td><?php _e('[[APPOINTMENT_DATE]] - date of appointment', 'ab') ?></td>
17
+ </tr>
18
+ <tr>
19
+ <td></td>
20
+ <td><?php _e('[[APPOINTMENT_TIME]] - time of appointment', 'ab') ?></td>
21
+ </tr>
22
+ <tr>
23
+ <td></td>
24
+ <td><?php _e('[[SERVICE_NAME]] - name of service', 'ab') ?></td>
25
+ </tr>
26
+ <tr>
27
+ <td></td>
28
+ <td><?php _e('[[SERVICE_PRICE]] - price of service', 'ab') ?></td>
29
+ </tr>
30
+ <tr>
31
+ <td></td>
32
+ <td><?php _e('[[CATEGORY_NAME]] - name of category', 'ab') ?></td>
33
+ </tr>
34
+ <tr>
35
+ <td></td>
36
+ <td><?php _e('[[COMPANY_NAME]] - name of the company', 'ab') ?></td>
37
+ </tr>
38
+ <tr>
39
+ <td></td>
40
+ <td><?php _e('[[COMPANY_LOGO]] - company logo', 'ab') ?></td>
41
+ </tr>
42
+ <tr>
43
+ <td></td>
44
+ <td><?php _e('[[COMPANY_ADDRESS]] - address of your company', 'ab') ?></td>
45
+ </tr>
46
+ <tr>
47
+ <td></td>
48
+ <td><?php _e('[[COMPANY_PHONE]] - company phone', 'ab') ?></td>
49
+ </tr>
50
+ <tr>
51
+ <td></td>
52
+ <td><?php _e('[[COMPANY_WEBSITE]] - this web-site address', 'ab') ?></td>
53
+ </tr>
54
+ <tr>
55
+ <td></td>
56
+ <td><?php _e('[[CANCEL_APPOINTMENT]] - cancel appointment link', 'ab') ?></td>
57
+ </tr>
backend/modules/notifications/templates/_tags_evening_after.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <tr>
3
+ <th><?php _e('Subject', 'ab') ?></th>
4
+ <th><?php _e('Message', 'ab') ?></th>
5
+ </tr>
6
+ <tr>
7
+ <td><?php _e('[[COMPANY_NAME]] - name of the company', 'ab') ?></td>
8
+ <td><?php _e('[[CLIENT_NAME]] - name of client', 'ab') ?></td>
9
+ </tr>
10
+ <tr>
11
+ <td></td>
12
+ <td><?php _e('[[APPOINTMENT_DATE]] - date of appointment', 'ab') ?></td>
13
+ </tr>
14
+ <tr>
15
+ <td></td>
16
+ <td><?php _e('[[APPOINTMENT_TIME]] - time of appointment', 'ab') ?></td>
17
+ </tr>
18
+ <tr>
19
+ <td></td>
20
+ <td><?php _e('[[SERVICE_NAME]] - name of service', 'ab') ?></td>
21
+ </tr>
22
+ <tr>
23
+ <td></td>
24
+ <td><?php _e('[[SERVICE_PRICE]] - price of service', 'ab') ?></td>
25
+ </tr>
26
+ <tr>
27
+ <td></td>
28
+ <td><?php _e('[[CATEGORY_NAME]] - name of category', 'ab') ?></td>
29
+ </tr>
30
+ <tr>
31
+ <td></td>
32
+ <td><?php _e('[[COMPANY_NAME]] - name of the company', 'ab') ?></td>
33
+ </tr>
34
+ <tr>
35
+ <td></td>
36
+ <td><?php _e('[[COMPANY_LOGO]] - company logo', 'ab') ?></td>
37
+ </tr>
38
+ <tr>
39
+ <td></td>
40
+ <td><?php _e('[[COMPANY_ADDRESS]] - address of your company', 'ab') ?></td>
41
+ </tr>
42
+ <tr>
43
+ <td></td>
44
+ <td><?php _e('[[COMPANY_PHONE]] - company phone', 'ab') ?></td>
45
+ </tr>
46
+ <tr>
47
+ <td></td>
48
+ <td><?php _e('[[COMPANY_WEBSITE]] - this web-site address', 'ab') ?></td>
49
+ </tr>
backend/modules/notifications/templates/_tags_evening_next_day.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <tr>
3
+ <th><?php _e('Subject', 'ab') ?></th>
4
+ <th><?php _e('Message', 'ab') ?></th>
5
+ </tr>
6
+ <tr>
7
+ <td><?php _e('[[COMPANY_NAME]] - name of the company', 'ab') ?></td>
8
+ <td><?php _e('[[CLIENT_NAME]] - name of client', 'ab') ?></td>
9
+ </tr>
10
+ <tr>
11
+ <td></td>
12
+ <td><?php _e('[[APPOINTMENT_DATE]] - date of appointment', 'ab') ?></td>
13
+ </tr>
14
+ <tr>
15
+ <td></td>
16
+ <td><?php _e('[[APPOINTMENT_TIME]] - time of appointment', 'ab') ?></td>
17
+ </tr>
18
+ <tr>
19
+ <td></td>
20
+ <td><?php _e('[[SERVICE_NAME]] - name of service', 'ab') ?></td>
21
+ </tr>
22
+ <tr>
23
+ <td></td>
24
+ <td><?php _e('[[SERVICE_PRICE]] - price of service', 'ab') ?></td>
25
+ </tr>
26
+ <tr>
27
+ <td></td>
28
+ <td><?php _e('[[CATEGORY_NAME]] - name of category', 'ab') ?></td>
29
+ </tr>
30
+ <tr>
31
+ <td></td>
32
+ <td><?php _e('[[COMPANY_NAME]] - name of the company', 'ab') ?></td>
33
+ </tr>
34
+ <tr>
35
+ <td></td>
36
+ <td><?php _e('[[COMPANY_LOGO]] - company logo', 'ab') ?></td>
37
+ </tr>
38
+ <tr>
39
+ <td></td>
40
+ <td><?php _e('[[COMPANY_ADDRESS]] - address of your company', 'ab') ?></td>
41
+ </tr>
42
+ <tr>
43
+ <td></td>
44
+ <td><?php _e('[[COMPANY_PHONE]] - company phone', 'ab') ?></td>
45
+ </tr>
46
+ <tr>
47
+ <td></td>
48
+ <td><?php _e('[[COMPANY_WEBSITE]] - this web-site address', 'ab') ?></td>
49
+ </tr>
backend/modules/notifications/templates/_tags_event_next_day.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <tr>
3
+ <th><?php _e('Subject', 'ab') ?></th>
4
+ <th><?php _e('Message', 'ab') ?></th>
5
+ </tr>
6
+ <tr>
7
+ <td><?php _e('[[TOMORROW_DATE]] - date of next day', 'ab') ?></td>
8
+ <td><?php _e('[[NEXT_DAY_AGENDA]] - staff agenda for next day', 'ab') ?></td>
9
+ </tr>
backend/modules/notifications/templates/_tags_provider_info.php ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <tr>
3
+ <th><?php _e('Subject', 'ab') ?></th>
4
+ <th><?php _e('Message', 'ab') ?></th>
5
+ </tr>
6
+ <tr>
7
+ <td><?php _e('[[COMPANY_NAME]] - name of the company', 'ab') ?></td>
8
+ <td><?php _e('[[CLIENT_NAME]] - name of client', 'ab') ?></td>
9
+ </tr>
10
+ <tr>
11
+ <td></td>
12
+ <td><?php _e('[[CLIENT_PHONE]] - сlient phone', 'ab') ?></td>
13
+ </tr>
14
+ <tr>
15
+ <td></td>
16
+ <td><?php _e('[[CLIENT_EMAIL]] - сlient email', 'ab') ?></td>
17
+ </tr>
18
+ <tr>
19
+ <td></td>
20
+ <td><?php _e('[[CLIENT_NOTES]] - сlient notes', 'ab') ?></td>
21
+ </tr>
22
+ <tr>
23
+ <td></td>
24
+ <td><?php _e('[[STAFF_NAME]] - name of staff', 'ab') ?></td>
25
+ </tr>
26
+ <tr>
27
+ <td></td>
28
+ <td><?php _e('[[APPOINTMENT_DATE]] - date of appointment', 'ab') ?></td>
29
+ </tr>
30
+ <tr>
31
+ <td></td>
32
+ <td><?php _e('[[APPOINTMENT_TIME]] - time of appointment', 'ab') ?></td>
33
+ </tr>
34
+ <tr>
35
+ <td></td>
36
+ <td><?php _e('[[SERVICE_NAME]] - name of service', 'ab') ?></td>
37
+ </tr>
38
+ <tr>
39
+ <td></td>
40
+ <td><?php _e('[[SERVICE_PRICE]] - price of service', 'ab') ?></td>
41
+ </tr>
42
+ <tr>
43
+ <td></td>
44
+ <td><?php _e('[[CATEGORY_NAME]] - name of category', 'ab') ?></td>
45
+ </tr>
46
+ <tr>
47
+ <td></td>
48
+ <td><?php _e('[[COMPANY_NAME]] - name of the company', 'ab') ?></td>
49
+ </tr>
50
+ <tr>
51
+ <td></td>
52
+ <td><?php _e('[[COMPANY_LOGO]] - company logo', 'ab') ?></td>
53
+ </tr>
54
+ <tr>
55
+ <td></td>
56
+ <td><?php _e('[[COMPANY_ADDRESS]] - address of your company', 'ab') ?></td>
57
+ </tr>
58
+ <tr>
59
+ <td></td>
60
+ <td><?php _e('[[COMPANY_PHONE]] - company phone', 'ab') ?></td>
61
+ </tr>
62
+ <tr>
63
+ <td></td>
64
+ <td><?php _e('[[COMPANY_WEBSITE]] - this web-site address', 'ab') ?></td>
65
+ </tr>
66
+ <tr>
67
+ <td></td>
68
+ <td><?php _e('[[CANCEL_APPOINTMENT]] - cancel appointment link', 'ab') ?></td>
69
+ </tr>
backend/modules/notifications/templates/index.php ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
2
+ $settings = array(
3
+ 'textarea_name' => $name,
4
+ 'media_buttons' => false,
5
+ 'tinymce' => array(
6
+ 'theme_advanced_buttons1' => 'formatselect,|,bold,italic,underline,|,' .
7
+ 'bullist,blockquote,|,justifyleft,justifycenter' .
8
+ ',justifyright,justifyfull,|,link,unlink,|' .
9
+ ',spellchecker,wp_fullscreen,wp_adv'
10
+ )
11
+ );
12
+ ?>
13
+ <div class="ab-title"><?php _e('Notifications','ab') ?></div>
14
+ <div style="min-width: 800px;margin-top: -20px">
15
+ <form method="post">
16
+ <div class="ab-notifications">
17
+ <?php
18
+ $sender_name = get_option( 'ab_settings_sender_name' ) == '' ?
19
+ get_option( 'blogname' ) : get_option( 'ab_settings_sender_name' );
20
+ $sender_email = get_option( 'ab_settings_sender_email' ) == '' ?
21
+ get_option( 'admin_email' ) : get_option( 'ab_settings_sender_email' );
22
+ ?>
23
+ <!-- sender name -->
24
+ <label for="sender_name" style="display: inline;"><?php _e( 'Sender name', 'ab' ); ?></label>
25
+ <input id="sender_name" name="sender_name" class="ab-sender" type="text" value="<?php echo $sender_name ; ?>"/><br>
26
+ <!-- sender email -->
27
+ <label for="sender_email" style="display: inline;"><?php _e( 'Sender email', 'ab' ); ?></label>
28
+ <input id="sender_email" name="sender_email" class="ab-sender" type="text" value="<?php echo $sender_email; ?>"/>
29
+ </div>
30
+ <?php foreach ( $notifications as $k => $slug ): ?>
31
+ <div class="ab-notifications">
32
+ <div class="ab-toggle-arrow"></div>
33
+ <legend id='legend_<?php echo $k; ?>_active'>
34
+ <input type=checkbox id="<?php echo $k; ?>_active" type="checkbox" value="1" name=<?php echo $k; ?>[active]"/>
35
+ <label for='<?php echo $k; ?>_active'><?php echo $slug['name']; ?></label>
36
+ </legend>
37
+ <div class="ab-form-field">
38
+ <div class="ab-form-row">
39
+ <label class='ab-form-label'><?php __( 'Subject','ab'); ?></label><input type='text' size='70' value='<?php echo $slug['subject']; ?>'/>
40
+ </div>
41
+ <div id="message_editor" class="ab-form-row">
42
+ <label class="ab-form-label" style="margin-top: 35px;"><?php _e( 'Message', 'ab' ) ?></label>
43
+ <?php wp_editor( $slug['message'], $k . '_message', array_merge(array('name' => $k . '[message]'), $settings) ) ?>
44
+ </div>
45
+ <?php if ('provider_info' == $k): ?>
46
+ <div class='ab-form-row'>
47
+ <label class='ab-form-label'></label>
48
+ <div class='left'>
49
+ <legend>
50
+ <input type=checkbox />
51
+ <label> <?php _e('Send copy to administrators', 'ab');?></label>
52
+ </legend>
53
+ </div>
54
+ </div>
55
+ <?php endif ?>
56
+ <div class="ab-form-row">
57
+ <label class="ab-form-label"><?php _e( 'Tags ','ab' ) ?></label>
58
+ <div class="ab-tags-form left">
59
+ <table>
60
+ <tbody>
61
+ <?php include "_tags_{$k}.php"; ?>
62
+ </tbody>
63
+ </table>
64
+ </div>
65
+ </div>
66
+ </div>
67
+ </div>
68
+ <?php endforeach; ?>
69
+ <div class="ab-notifications" style="border: 0">
70
+ <input type="submit" value="<?php _e( 'Save Changes', 'ab' )?>" class="btn btn-info ab-update-button" />
71
+ <button class="ab-reset-form" type="reset"><?php _e( 'Reset', 'ab' )?></button>
72
+ </div>
73
+ </form>
74
+ </div>
75
+
76
+ <div class="modal fade" id="lite_notice" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
77
+ <div class="modal-dialog">
78
+ <div class="modal-content">
79
+ <div class="modal-header">
80
+ <h4 class="modal-title"><?php _e('Notice', 'ab') ?></h4>
81
+ </div>
82
+ <div class="modal-body">
83
+ <?php _e('This function is disabled in the lite version of Bookly. If you find the plugin useful for your business please consider buying a licence for the full version. It costs just $38 and for this money you will get many useful functions, lifetime free update and excellent support! More information can be found here', 'ab'); ?>: <a href="http://bookly.ladela.com" target="_blank">http://bookly.ladela.com</a>
84
+ </div>
85
+ <div class="modal-footer">
86
+ <button type="button" class="btn btn-default" data-dismiss="modal"><?php _e('Close', 'ab') ?></button>
87
+ </div>
88
+ </div><!-- /.modal-content -->
89
+ </div><!-- /.modal-dialog -->
90
+ </div><!-- /.modal -->
91
+
92
+ <script type="text/javascript">
93
+ jQuery(function($) {
94
+ // menu fix for WP 3.8.1
95
+ $('#toplevel_page_ab-system > ul').css('margin-left', '0px');
96
+ // Show-hide Notifications
97
+ $('input:checkbox[id!=_active]').each(function() {
98
+ $(this).change(function() {
99
+ if ( $(this).attr('checked') ) {
100
+ $(this).parent().next('div.ab-form-field').show(200);
101
+ $(this).parents('.ab-notifications').find('.ab-toggle-arrow').css('background','url(<?php echo plugins_url( 'resources/images/notifications-arrow-up.png', dirname(__FILE__).'/../../../AB_Backend.php' ) ?>) 100% 0 no-repeat');
102
+ } else {
103
+ $(this).parent().next('div.ab-form-field').hide(200);
104
+ $(this).parents('.ab-notifications').find('.ab-toggle-arrow').css('background','url(<?php echo plugins_url( 'resources/images/notifications-arrow-down.png', dirname(__FILE__).'/../../../AB_Backend.php' ) ?>) 100% 0 no-repeat');
105
+ }
106
+ }).change();
107
+ });
108
+ $('.ab-toggle-arrow').click(function() {
109
+ $(this).nextAll('.ab-form-field').toggle(200, function() {
110
+ if ( $('.ab-form-field').css('display') == 'block' ) {
111
+ $(this).prevAll('.ab-toggle-arrow').css('background','url(<?php echo plugins_url( 'resources/images/notifications-arrow-up.png', dirname(__FILE__).'/../../../AB_Backend.php' ) ?>) 100% 0 no-repeat');
112
+ } else {
113
+ $(this).prevAll('.ab-toggle-arrow').css('background','url(<?php echo plugins_url( 'resources/images/notifications-arrow-down.png', dirname(__FILE__).'/../../../AB_Backend.php' ) ?>) 100% 0 no-repeat');
114
+ }
115
+ });
116
+ });
117
+ // filter sender name and email
118
+ var escapeXSS = function (infected) {
119
+ var regexp = /([<|(]("[^"]*"|'[^']*'|[^'">])*[>|)])/gi;
120
+ return infected.replace(regexp, '');
121
+ };
122
+ $('input.ab-sender').on('change', function() {
123
+ var $val = $(this).val();
124
+ $(this).val(escapeXSS($val));
125
+ });
126
+
127
+ $("input[id$='_active']").change(function(){
128
+ if ($(this).is(':checked')){
129
+ $('#lite_notice').modal('show');
130
+ }
131
+ });
132
+ });
133
+ </script>
backend/modules/payment/AB_PaymentController.php ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ class AB_PaymentController extends AB_Controller {
6
+
7
+ public function index() {
8
+ $path = dirname( __DIR__ );
9
+ wp_enqueue_style( 'ab-style', plugins_url( 'resources/css/ab_style.css', $path ) );
10
+ wp_enqueue_style( 'ab-bootstrap', plugins_url( 'resources/bootstrap/css/bootstrap.min.css', $path ) );
11
+ wp_enqueue_script( 'ab-bootstrap', plugins_url( 'resources/bootstrap/js/bootstrap.min.js', $path ), array( 'jquery' ) );
12
+ wp_enqueue_script( 'ab-date', plugins_url( 'resources/js/date.js', $path ), array( 'jquery' ) );
13
+ wp_enqueue_script( 'ab-daterangepicker-js', plugins_url( 'resources/js/daterangepicker.js', $path ), array( 'jquery' ) );
14
+ wp_enqueue_style( 'ab-daterangepicker-css', plugins_url( 'resources/css/daterangepicker.css', $path ) );
15
+ wp_enqueue_script( 'ab-bootstrap-select-js', plugins_url( 'resources/js/bootstrap-select.min.js', $path ));
16
+ wp_enqueue_style( 'ab-bootstrap-select-css', plugins_url( 'resources/css/bootstrap-select.min.css', $path ));
17
+ wp_localize_script( 'ab-daterangepicker-js', 'BooklyL10n', array(
18
+ 'today' => __( 'Today', 'ab' ),
19
+ 'yesterday' => __( 'Yesterday', 'ab' ),
20
+ 'last_7' => __( 'Last 7 Days', 'ab' ),
21
+ 'last_30' => __( 'Last 30 Days', 'ab' ),
22
+ 'this_month' => __( 'This Month', 'ab' ),
23
+ 'last_month' => __( 'Last Month', 'ab' ),
24
+ 'custom_range' => __( 'Custom Range', 'ab' ),
25
+ 'apply' => __( 'Apply', 'ab' ),
26
+ 'clear' => __( 'Clear', 'ab' ),
27
+ 'to' => __( 'To', 'ab' ),
28
+ 'from' => __( 'From', 'ab' ),
29
+ 'month' => array(
30
+ 0 => __( 'January', 'ab' ),
31
+ 1 => __( 'February', 'ab' ),
32
+ 2 => __( 'March', 'ab' ),
33
+ 3 => __( 'April', 'ab' ),
34
+ 4 => __( 'May', 'ab' ),
35
+ 5 => __( 'June', 'ab' ),
36
+ 6 => __( 'July', 'ab' ),
37
+ 7 => __( 'August', 'ab' ),
38
+ 8 => __( 'September', 'ab' ),
39
+ 9 => __( 'October', 'ab' ),
40
+ 10 => __( 'November', 'ab' ),
41
+ 11 => __( 'December', 'ab' )
42
+ ),
43
+ 'day' => array(
44
+ 'Mon' => __( 'Mon', 'ab' ),
45
+ 'Tue' => __( 'Tue', 'ab' ),
46
+ 'Wed' => __( 'Wed', 'ab' ),
47
+ 'Thu' => __( 'Thu', 'ab' ),
48
+ 'Fri' => __( 'Fri', 'ab' ),
49
+ 'Sat' => __( 'Sat', 'ab' ),
50
+ 'Sun' => __( 'Sun', 'ab' )
51
+ )
52
+ ));
53
+
54
+ $this->types = $this->customers = $this->providers = $this->services = array();
55
+
56
+ $this->render( 'index' );
57
+ }
58
+
59
+ /**
60
+ * Translate date-ranges
61
+ */
62
+ public function executeL10nRanges() {
63
+ $start = '';
64
+ $end = '';
65
+ if ( $this->hasParameter( 'start' ) && $this->hasParameter( 'end' ) ) {
66
+ $start = date_i18n( get_option( 'date_format' ), strtotime( $this->getParameter( 'start' ) ) );
67
+ $end = date_i18n( get_option( 'date_format' ), strtotime( $this->getParameter( 'end' ) ) );
68
+ }
69
+
70
+ echo json_encode( (object) array( 'start' => $start, 'end' => $end ) );
71
+ exit;
72
+ }
73
+
74
+ /**
75
+ * Override parent method to add 'wp_ajax_ab_' prefix
76
+ * so current 'execute*' methods look nicer.
77
+ */
78
+ protected function registerWpActions( $prefix = '' ) {
79
+ parent::registerWpActions( 'wp_ajax_ab_' );
80
+ }
81
+ }
backend/modules/payment/templates/_alert.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <div id="ab_filter_error" class="alert alert-error" >
3
+ <?php _e('This function is disabled in the lite version of Bookly. If you find the plugin useful for your business please consider buying a licence for the full version. It costs just $38 and for this money you will get many useful functions, lifetime free update and excellent support! More information can be found here', 'ab'); ?>: <a href="http://bookly.ladela.com" target="_blank">http://bookly.ladela.com</a>
4
+ </div>
backend/modules/payment/templates/index.php ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @var array $customers
4
+ * @var array $types
5
+ * @var array $providers
6
+ * @var array $services
7
+ */
8
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
9
+ ?>
10
+ <div class=ab-title><?php _e( 'Payments','ab' ) ?></div>
11
+ <div style="min-width: 800px;margin-right: 15px;">
12
+ <div class=ab-nav-payment>
13
+ <div class=row-fluid>
14
+ <div id=reportrange class="pull-left ab-reportrange" style="margin-bottom: 10px">
15
+ <i class="icon-calendar icon-large"></i>
16
+ <span data-date="<?php echo date( 'F j, Y', strtotime( '-30 day' ) ) ?> - <?php echo date( 'F j, Y' ) ?>"><?php echo date_i18n( get_option( 'date_format' ), strtotime( '-30 day' ) ) ?> - <?php echo date_i18n( get_option( 'date_format' ) ) ?></span> <b style="margin-top: 8px;" class=caret></b>
17
+ </div>
18
+ <div class=pull-left>
19
+ <select id=ab-type-filter class=selectpicker>
20
+ <option value="-1"><?php _e( 'All payment types', 'ab' ) ?></option>
21
+ <?php foreach ( $types as $type ): ?>
22
+ <option value="<?php echo esc_attr( $type ) ?>">
23
+ <?php
24
+ switch( $type ) {
25
+ case 'paypal':
26
+ echo 'PayPal';
27
+ break;
28
+ case 'authorizeNet':
29
+ echo 'authorizeNet';
30
+ break;
31
+ case 'stripe':
32
+ echo 'Stripe';
33
+ break;
34
+ default:
35
+ echo __( 'Local', 'ab' );
36
+ break;
37
+ }
38
+ ?>
39
+ </option>
40
+ <?php endforeach ?>
41
+ </select>
42
+ <select id=ab-customer-filter class=selectpicker>
43
+ <option value="-1"><?php _e( 'All customers', 'ab' ) ?></option>
44
+ <?php foreach ( $customers as $customer ): ?>
45
+ <option><?php echo esc_html($customer) ?></option>
46
+ <?php endforeach ?>
47
+ </select>
48
+ <select id=ab-provider-filter class=selectpicker>
49
+ <option value="-1"><?php _e( 'All providers', 'ab' ) ?></option>
50
+ <?php foreach ( $providers as $provider ): ?>
51
+ <option><?php echo esc_html($provider) ?></option>
52
+ <?php endforeach ?>
53
+ </select>
54
+ <select id=ab-service-filter class=selectpicker>
55
+ <option value="-1"><?php _e( 'All services', 'ab' ) ?></option>
56
+ <?php foreach ( $services as $service ): ?>
57
+ <option><?php echo esc_html($service) ?></option>
58
+ <?php endforeach ?>
59
+ </select>
60
+ <a id=ab-filter-submit style="margin:0 0 10px 5px;" href="#" class="btn btn-primary"><?php _e( 'Filter', 'ab' ) ?></a>
61
+ </div>
62
+ </div>
63
+ </div>
64
+ <div id=ab-alert-div class=alert style="display: none"></div>
65
+ <table class="table table-bordered" cellspacing=0 cellpadding=0 border=0 id=ab_payments_list style="clear: both;">
66
+ <thead>
67
+ <tr>
68
+ <th width=150 class="desc active" order-by=created><a href="javascript:void(0)"><?php _e( 'Date', 'ab' ) ?></a></th>
69
+ <th width=100 order-by=type><a href="javascript:void(0)"><?php _e( 'Type', 'ab' ) ?></a></th>
70
+ <th width=150 order-by=customer><a href="javascript:void(0)"><?php _e( 'Customer', 'ab' ) ?></a></th>
71
+ <th width=150 order-by=provider><a href="javascript:void(0)"><?php _e( 'Provider', 'ab' ) ?></a></th>
72
+ <th width=150 order-by=service><a href="javascript:void(0)"><?php _e( 'Service', 'ab' ) ?></a></th>
73
+ <th width=50 order-by=total><a href="javascript:void(0)"><?php _e( 'Amount', 'ab') ?></a></th>
74
+ <th width=50 order-by=coupon><a href="javascript:void(0)"><?php _e( 'Coupon', 'ab') ?></a></th>
75
+ <th width=150 order-by=start_date><a href="javascript:void(0)"><?php _e( 'Appointment Date', 'ab' ) ?></a></th>
76
+ </tr>
77
+ </thead>
78
+ <tbody id=ab-tb-body>
79
+ </tbody>
80
+ </table>
81
+ <?php include '_alert.php'; ?>
82
+ </div>
83
+
84
+ <script type="text/javascript">
85
+ jQuery(function($) {
86
+ var data = {},
87
+ $report_range = $('#reportrange span'),
88
+ picker_ranges = {},
89
+ l10nRanges = {
90
+ response: function(start, end) {
91
+ return $.post(ajaxurl, {action: 'ab_l10n_ranges', start: start, end: end});
92
+ },
93
+ l10n: function(start, end) {
94
+ this.response(start, end).done(function(response) {
95
+ var ranges = JSON.parse(response);
96
+ $report_range.data('date', start.toString('MMMM d, yyyy') + ' - ' + end.toString('MMMM d, yyyy'));
97
+ $report_range.html(ranges.start + ' - ' + ranges.end);
98
+ });
99
+ }
100
+ };
101
+
102
+ picker_ranges[BooklyL10n.today] = ['today', 'today'];
103
+ picker_ranges[BooklyL10n.yesterday] = ['yesterday', 'yesterday'];
104
+ picker_ranges[BooklyL10n.last_7] = [Date.today().add({ days: -6 }), 'today'];
105
+ picker_ranges[BooklyL10n.last_30] = [Date.today().add({ days: -30 }), 'today','selected'];
106
+ picker_ranges[BooklyL10n.this_month] = [Date.today().moveToFirstDayOfMonth(), Date.today().moveToLastDayOfMonth()];
107
+ picker_ranges[BooklyL10n.last_month] = [Date.today().moveToFirstDayOfMonth().add({ months: -1 }), Date.today().moveToFirstDayOfMonth().add({ days: -1 })];
108
+
109
+ $('.selectpicker').selectpicker({style: 'btn-info', size: 5});
110
+
111
+ $('#reportrange').daterangepicker({ranges: picker_ranges}, function(start, end) {
112
+ l10nRanges.l10n(start, end);
113
+ });
114
+
115
+ });
116
+ </script>
backend/modules/service/AB_ServiceController.php ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ include 'forms/AB_CategoryForm.php';
6
+ include 'forms/AB_ServiceForm.php';
7
+
8
+ /**
9
+ * Class AB_ServiceController
10
+ */
11
+ class AB_ServiceController extends AB_Controller {
12
+
13
+ /**
14
+ *
15
+ */
16
+ public function index() {
17
+ $this->staff_collection = $this->getStaffCollection();
18
+ $this->category_collection = $this->getCategoryCollection();
19
+ $this->service_collection = $this->getServiceCollection();
20
+ $this->render( 'index' );
21
+ }
22
+
23
+ /**
24
+ *
25
+ */
26
+ public function executeCategoryServices() {
27
+ $this->setDataForServiceList();
28
+ $this->render( 'list' );
29
+ exit;
30
+ }
31
+
32
+ /**
33
+ *
34
+ */
35
+ public function executeCategoryForm() {
36
+ $this->form = new AB_CategoryForm();
37
+
38
+ if ( !empty ( $_POST ) ) {
39
+ $this->form->bind( $this->getPostParameters() );
40
+ if ( $category = $this->form->save() ) {
41
+ echo "<div class='ab-category-item' data-id='{$category->id}'>
42
+ <span class='left displayed-value'>{$category->name}</span>
43
+ <a href='#' class='left ab-hidden ab-edit'></a>
44
+ <input class=value type=text name=name value='{$category->name}' style='display: none' />
45
+ <a href='#' class='left ab-hidden ab-delete'></a></div>";
46
+ exit;
47
+ }
48
+ }
49
+ exit;
50
+ }
51
+
52
+ /**
53
+ * Update category.
54
+ */
55
+ public function executeUpdateCategory() {
56
+ $form = new AB_CategoryForm();
57
+ $form->bind( $this->getPostParameters() );
58
+ $form->save();
59
+ }
60
+
61
+ /**
62
+ * Delete category.
63
+ */
64
+ public function executeDeleteCategory() {
65
+ $category = new AB_Category();
66
+ $category->set( 'id', $this->getParameter( 'id', 0 ) );
67
+ $category->delete();
68
+ }
69
+
70
+
71
+ public function executeAddService() {
72
+ $form = new AB_ServiceForm();
73
+ $form->bind( $this->getPostParameters() );
74
+ $service = $form->save();
75
+ $this->setDataForServiceList( $service->get( 'category_id' ) );
76
+ $this->render( 'list' );
77
+ exit;
78
+ }
79
+
80
+ public function executeRemoveServices() {
81
+ $service_ids = $this->getParameter( 'service_ids', array() );
82
+ if ( is_array( $service_ids ) && !empty ( $service_ids ) ) {
83
+ $this->getWpdb()->query('DELETE FROM ab_service WHERE id IN (' . implode(', ', $service_ids) . ')');
84
+ }
85
+ }
86
+
87
+ public function executeAssignStaff() {
88
+ $service_id = $this->getParameter( 'service_id', 0 );
89
+ $staff_ids = $this->getParameter( 'staff_ids', array() );
90
+
91
+ if ( $service_id ) {
92
+ $this->getWpdb()->delete('ab_staff_service', array( 'service_id' => $service_id ), array( '%d' ) );
93
+ $service = new AB_Service();
94
+ if ( ! empty( $staff_ids ) && $service->load( $service_id ) ) {
95
+ foreach ( $staff_ids as $staff_id ) {
96
+ $staff_service = new AB_StaffService();
97
+ $staff_service->set( 'staff_id', $staff_id );
98
+ $staff_service->set( 'service_id', $service_id );
99
+ $staff_service->set( 'price', $service->get( 'price' ) );
100
+ $staff_service->save();
101
+ }
102
+ }
103
+ echo count( $staff_ids );
104
+ exit;
105
+ }
106
+ }
107
+
108
+ public function executeUpdateServiceValue() {
109
+ $form = new AB_ServiceForm();
110
+ $form->bind( $this->getPostParameters() );
111
+ $form->save();
112
+ }
113
+
114
+ /**
115
+ * @param int $category_id
116
+ */
117
+ private function setDataForServiceList( $category_id = 0 ) {
118
+ if (!$category_id) {
119
+ $category_id = $this->getParameter( 'category_id', 0 );
120
+ }
121
+
122
+ $this->service_collection = $this->getServiceCollection($category_id);
123
+ $this->staff_collection = $this->getStaffCollection();
124
+ $this->category_collection = $this->getCategoryCollection();
125
+ }
126
+
127
+ /**
128
+ * @return mixed
129
+ */
130
+ private function getCategoryCollection() {
131
+ return $this->getWpdb()->get_results( "SELECT * FROM ab_category" );
132
+ }
133
+
134
+ /**
135
+ * @return mixed
136
+ */
137
+ private function getStaffCollection() {
138
+ return $this->getWpdb()->get_results( "SELECT * FROM ab_staff" );
139
+ }
140
+
141
+ /**
142
+ * @param int $id
143
+ * @return mixed
144
+ */
145
+ private function getServiceCollection( $id = 0 ) {
146
+
147
+ $query = $this->getWpdb()->prepare(
148
+ 'SELECT
149
+ `s`.*,
150
+ COUNT(`st`.`id`) AS `total_staff`,
151
+ GROUP_CONCAT(DISTINCT `st`.`id`) AS `staff_ids`
152
+ FROM `ab_service` `s`
153
+ LEFT JOIN `ab_staff_service` `sts` ON `sts`.`service_id` = `s`.`id`
154
+ LEFT JOIN `ab_staff` `st` ON `st`.`id` = `sts`.`staff_id`
155
+ WHERE `s`.`category_id` = %d OR !%d
156
+ GROUP BY `s`.`id` ORDER BY ISNULL(`s`.`title`), `s`.`title`',
157
+ $id,
158
+ $id
159
+ );
160
+
161
+ return $this->getWpdb()->get_results($query);
162
+ }
163
+
164
+ // Protected methods.
165
+
166
+ /**
167
+ * Override parent method to add 'wp_ajax_ab_' prefix
168
+ * so current 'execute*' methods look nicer.
169
+ */
170
+ protected function registerWpActions( $prefix = '' ) {
171
+ parent::registerWpActions( 'wp_ajax_ab_' );
172
+ }
173
+
174
+ }
backend/modules/service/forms/AB_CategoryForm.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ /**
6
+ * Class AB_CategoryForm
7
+ */
8
+ class AB_CategoryForm extends AB_Form {
9
+
10
+ /**
11
+ * Constructor.
12
+ */
13
+ public function __construct() {
14
+ parent::$entity_class = 'AB_Category';
15
+ parent::__construct();
16
+ }
17
+
18
+ /**
19
+ * Configure the form.
20
+ */
21
+ public function configure() {
22
+ $this->setFields( array( 'name' ) );
23
+ }
24
+
25
+ }
backend/modules/service/forms/AB_ServiceForm.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ include AB_PATH . '/lib/entities/AB_Service.php';
6
+
7
+ /**
8
+ * Class AB_ServiceForm
9
+ */
10
+ class AB_ServiceForm extends AB_Form {
11
+
12
+ /**
13
+ * Constructor.
14
+ */
15
+ public function __construct() {
16
+ parent::$entity_class = 'AB_Service';
17
+ parent::__construct();
18
+ }
19
+
20
+ public function configure() {
21
+ $this->setFields(array('id', 'title', 'duration', 'price', 'category_id', 'color', 'capacity'));
22
+ }
23
+
24
+ /**
25
+ * Bind values to form.
26
+ *
27
+ * @param array $post
28
+ * @param array $files
29
+ */
30
+ public function bind( array $post, array $files = array() ) {
31
+ if ( array_key_exists('category_id', $post) && !$post['category_id'] ) {
32
+ $post['category_id'] = null;
33
+ }
34
+ parent::bind($post, $files);
35
+ }
36
+
37
+ public function save() {
38
+ if ( $this->isNew() ) {
39
+ $colors = array('#B0171F', '#DA70D6', '#BF3EFF', '#8470FF', '#4876FF', '#63B8FF', '#00B2EE', '#00F5FF', '#00C78C', '#BDFCC9', '#B4EEB4', '#7CFC00', '#ADFF2F', '#FFFFF0', '#CDCDB4', '#FFFF00', '#FFF68F', '#F0E68C', '#E3CF57', '#FFEBCD', '#FF8C00', '#EE4000', '#FA8072', '#F08080', '#CD0000');
40
+ // when adding new service - set its color randomly
41
+ $this->data[ 'color' ] = $colors[mt_rand(0, count($colors) - 1)];
42
+ }
43
+
44
+ $this->data['capacity'] = 1;
45
+
46
+ return parent::save();
47
+ }
48
+ }
backend/modules/service/resources/css/service.css ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .ab-category-item {
2
+ width: 110px;
3
+ padding: 10px;
4
+ padding-left: 50px;
5
+ vertical-align: middle;
6
+ -moz-border-radius: 5px;
7
+ border-radius: 5px;
8
+ cursor: pointer;
9
+ }
10
+ .ab-active {
11
+ background-color: #ccc;
12
+ }
13
+
14
+ .wp-picker-container .iris-picker {
15
+ border-color: black;
16
+ margin-left: 35px;
17
+ margin-top: 6px;
18
+ }
19
+
20
+ #services_list .service-color-wrapper .wp-picker-open + .wp-picker-input-wrap {
21
+ display: block;
22
+ margin-left: 50px;
23
+ margin-top: 20px;
24
+ }
25
+
26
+ .wp-picker-container, .wp-picker-container:active {
27
+ display: inline-block;
28
+ outline: 0 none;
29
+ position: absolute;
30
+ margin-top: 3px;
31
+ }
32
+
33
+ /** Services list **/
34
+ #ab_services_wrapper .list-wrapper { min-width: 590px }
35
+ #ab_services_wrapper .list-wrapper .list-actions { overflow: hidden; margin-top: 10px; }
36
+ #ab_services_wrapper .list-wrapper .list-actions .add-service { float: left }
37
+ #ab_services_wrapper .list-wrapper .list-actions .delete { float: right }
38
+
39
+ #services_list td.last,
40
+ #services_list th.last { width: 16px; vertical-align: middle; }
41
+ #services_list th, #services_list td { padding:5px }
42
+ #services_list select { width: auto; margin: 0; }
43
+ #services_list .service-color-cell { width: 28px; }
44
+ #services_list .service-color-wrapper .wp-color-result { padding-left: 25px; margin: 0; top: auto; }
45
+ #services_list .service-color-wrapper .wp-color-result.wp-picker-open { top: auto }
46
+ #services_list .service-color-wrapper .wp-color-result:after { top: auto; content: none; }
47
+ #services_list .service-color-wrapper .wp-color-result.wp-picker-open:after { content: none }
48
+ #services_list .service-color-wrapper .wp-picker-open + .wp-picker-input-wrap { display: block; visibility: hidden; margin-top: -25px; margin-left: 34px; }
49
+ #services_list .service-color-wrapper .button { margin-left: 0 }
50
+
51
+ #new_category_popup .ab-popup { width: 187px }
52
+ .staff-popup-wrapper .staff-row { white-space: nowrap; margin: 0; }
53
+
backend/modules/service/resources/js/service.js ADDED
@@ -0,0 +1,303 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(function($) {
2
+ var $no_result = $('#ab_services_wrapper .no-result');
3
+
4
+ // On new category form submit.
5
+ $('#new-category-form').on('submit', function(event) {
6
+ var data = $(this).serialize();
7
+ $.post(ajaxurl, data, function(response) {
8
+ $('.ab-category-item-list').append(response);
9
+ $('#new_category_popup').ab_popup('close');
10
+ // add created category to services
11
+ $.each($('#services_list').find('select[name="category_id"]'), function(key, value) {
12
+ var $new_category = $('.ab-category-item:last');
13
+ $(value).append('<option value="' + $new_category.data('id') + '">'
14
+ + $new_category.find('input').val() + ' </option>');
15
+ });
16
+ });
17
+ return false;
18
+ });
19
+
20
+ // Preventing multiple creation of new category by pressing Enter-key
21
+ $('input[value="ab_category_form"]').parent().find('input:first').one('keypress', function(e) {
22
+ var code = (e.keyCode ? e.keyCode : e.which);
23
+ if (code == 13) {
24
+ $(this).trigger(e).blur();
25
+ }
26
+ });
27
+
28
+ // Categories list delegated events.
29
+ $('#ab-categories-list')
30
+
31
+ // On category item click.
32
+ .on('click', '.ab-category-item', function() {
33
+ var $clicked = $(this);
34
+ $.get(ajaxurl, {action:'ab_category_services', category_id: $clicked.data('id')}, function(response) {
35
+ $('.ab-category-item').not($clicked).removeClass('ab-active');
36
+ $('.ab-category-title').text($clicked.text());
37
+ $clicked.addClass('ab-active');
38
+ refreshList(response);
39
+ });
40
+ })
41
+
42
+ // On edit category click.
43
+ .on('click', '.ab-category-item .ab-edit', function(e) {
44
+ // Keep category item click from being executed.
45
+ e.stopPropagation();
46
+ // Prevent navigating to '#'.
47
+ e.preventDefault();
48
+ // Hide edit button.
49
+ $(this).hide()
50
+ // Hide displayed category name and delete button.
51
+ .siblings('.displayed-value, .ab-delete').hide().end()
52
+ // Show input field.
53
+ .nextAll('.value').show().focus();
54
+ })
55
+
56
+ // On blur of category edit input.
57
+ .on('blur', '.ab-category-item input.value', function() {
58
+ var $this = $(this),
59
+ $item = $this.closest('.ab-category-item'),
60
+ field = $this.attr('name'),
61
+ value = $this.attr('value'),
62
+ id = $item.data('id');
63
+ if (value) {
64
+ var data = { action: 'ab_update_category', id: id };
65
+ data[field] = value;
66
+ $.post(ajaxurl, data, function(response) {
67
+ // Hide input field.
68
+ $this.hide()
69
+ // Show modified category name.
70
+ .prevAll('.displayed-value').text(value).show().end()
71
+ // Show edit and delete buttons.
72
+ .siblings('.ab-edit, .ab-delete').show();
73
+ // update edited category's name for services
74
+ $.each($('#services_list').find('select[name="category_id"]'), function(k, v) {
75
+ $(v).find('option:selected[value="' + id + '"]').text(value);
76
+ });
77
+ });
78
+ }
79
+ })
80
+
81
+ // On delete category click.
82
+ .on('click', '.ab-category-item .ab-delete', function(e) {
83
+ // Keep category item click from being executed.
84
+ e.stopPropagation();
85
+ // Prevent navigating to '#'.
86
+ e.preventDefault();
87
+ // Ask user if he is sure.
88
+ if (confirm(BooklyL10n.are_you_sure)) {
89
+ var $item = $(this).closest('.ab-category-item');
90
+ var data = { action: 'ab_delete_category', id: $item.data('id') };
91
+ $.post(ajaxurl, data, function(response) {
92
+ // Remove category item from Services
93
+ $.each($('#services_list').find('select[name="category_id"]'), function(key, value) {
94
+ $(value).find('option[value="' + $item.data('id') + '"]').remove();
95
+ });
96
+ // Remove category item from DOM.
97
+ $item.remove();
98
+ if ($item.is('.ab-active')) {
99
+ location.reload(true);
100
+ }
101
+ });
102
+ }
103
+ });
104
+
105
+
106
+ // Services list delegated events.
107
+ $('#ab_services_wrapper')
108
+
109
+ // On click on editable cell.
110
+ .on('click', '.editable-cell div.displayed-value', function() {
111
+ var $this = $(this);
112
+ $this.hide().next('.value').show();
113
+ // Fix FF accidental blur of input[type=number].
114
+ setTimeout( function() { $this.next('.value').focus(); }, 100 );
115
+ })
116
+
117
+ // On blur of input in editable cell.
118
+ .on('blur', '.editable-cell input.value', function() {
119
+ var $this = $(this),
120
+ field = $this.attr('name'),
121
+ value = $this.attr('value'),
122
+ id = $this.parents('.service-row').attr('id');
123
+ if (value) {
124
+ var data = { action: 'ab_update_service_value', id: id };
125
+ data[field] = value;
126
+ $.post(ajaxurl, data, function(response) {
127
+ $this.hide();
128
+ $this.prev('.displayed-value').text(value).show();
129
+ });
130
+ }
131
+ })
132
+
133
+ // On change in 'Duration' or 'Category' drop-down lists.
134
+ .on('change', 'select', function() {
135
+ var $this = $(this),
136
+ field = $this.attr('name'),
137
+ value = $this.val(),
138
+ $row = $this.parents('.service-row'),
139
+ id = $row.attr('id');
140
+ if (value) {
141
+ var data = { action: 'ab_update_service_value', id: id };
142
+ data[field] = value;
143
+ $.post(ajaxurl, data, function(response) {
144
+ if ($this.attr('name') == 'category_id') {
145
+ var services_category_id = parseInt($('.ab-category-item.ab-active').data('id')),
146
+ selected_category_id = parseInt(value);
147
+ if (services_category_id && selected_category_id != services_category_id) {
148
+ if ($('#services_list > tbody > tr').length == 1) {
149
+ $('#services_list > tbody > tr').remove();
150
+ $('#services_list').hide();
151
+ $no_result.show();
152
+ } else {
153
+ $row.removeClass('last').prev().addClass('last');
154
+ $row.remove();
155
+ }
156
+ }
157
+ }
158
+ });
159
+ }
160
+ })
161
+
162
+ // On click on 'Add Service' button.
163
+ .on('click', 'a.add-service', function(e) {
164
+ e.preventDefault();
165
+ var selected_category_id = $('#ab-categories-list .ab-active').data('id'),
166
+ data = { action: 'ab_add_service' };
167
+ if (selected_category_id) {
168
+ data['category_id'] = selected_category_id;
169
+ }
170
+ $.post(ajaxurl, data, function(response) {
171
+ refreshList(response);
172
+ });
173
+ })
174
+
175
+ // On change in `select row` checkbox.
176
+ .on('change', 'input.row-checker', function() {
177
+ if ($(this).attr('checked')) {
178
+ $(this).parents('.service-row').addClass('checked');
179
+ } else {
180
+ $(this).parents('.service-row').removeClass('checked');
181
+ }
182
+ })
183
+
184
+ // On click on 'Delete' button.
185
+ .on('click', 'a.delete', function(e){
186
+ e.preventDefault();
187
+ var $checked_rows = $('#services_list .service-row.checked');
188
+ if (!$checked_rows.length) {
189
+ alert(BooklyL10n.please_select_at_least_one_service);
190
+ return false;
191
+ }
192
+ var selected_category_id = $('#ab-categories-list .ab-active').data('id'),
193
+ data = { action: 'ab_remove_services' },
194
+ row_ids = [];
195
+ $checked_rows.each(function() {
196
+ row_ids.push($(this).attr('id'));
197
+ });
198
+ if (selected_category_id) {
199
+ data['category_id'] = selected_category_id;
200
+ }
201
+ data['service_ids[]'] = row_ids;
202
+ $.post(ajaxurl, data, function() {
203
+ $checked_rows.fadeOut(700, function() {
204
+ $(this).each(function() {
205
+ if ($(this).hasClass('last')) {
206
+ $(this).removeClass('last').prev().addClass('last');
207
+ }
208
+ });
209
+ $(this).remove();
210
+ $('#services_list .service-row').removeClass('even odd').each(function(index, value) {
211
+ if (index % 2) {
212
+ $(this).addClass('even');
213
+ } else {
214
+ $(this).addClass('odd');
215
+ }
216
+ });
217
+ if (!$('#services_list > tbody > tr').length) {
218
+ $('#services_list').hide();
219
+ $no_result.show();
220
+ }
221
+ });
222
+ });
223
+ })
224
+
225
+ // On change in `select staff` checkbox.
226
+ .on('change', 'input.all-staff, input.staff', function(){
227
+ var $this = $(this),
228
+ $row = $this.parents('.service-row'),
229
+ staff_ids = [],
230
+ data = { action: 'ab_assign_staff', service_id: $row.attr('id') };
231
+ if ($this.hasClass('all-staff')) {
232
+ $row.find('.staff').prop('checked', $this.prop('checked'));
233
+ } else {
234
+ $row.find('.all-staff').prop(
235
+ 'checked',
236
+ $row.find('.staff:not(:checked)').length == 0
237
+ );
238
+ }
239
+ $row.find('.staff:checked').each(function(){
240
+ staff_ids.push($(this).val());
241
+ });
242
+ data['staff_ids[]'] = staff_ids;
243
+ $.post(ajaxurl, data, function(response) {
244
+ if (response) {
245
+ $row.find('.staff-count').text(response);
246
+ }
247
+ });
248
+ })
249
+
250
+ .on('change', '[name=capacity]', function(){
251
+ $('#lite_notice').modal('show');
252
+ $(this).val(1);
253
+ });
254
+
255
+ function refreshList(response) {
256
+ var $list = $('#ab-services-list');
257
+ $list.html(response);
258
+ doNotCloseDropDowns();
259
+ initColorPicker($list.find('.service-color'));
260
+ initPopovers();
261
+
262
+ if (response) {
263
+ $no_result.hide();
264
+ } else {
265
+ $no_result.show();
266
+ }
267
+ }
268
+
269
+ function initColorPicker($jquery_collection) {
270
+ $jquery_collection.wpColorPicker({
271
+ change: function() {
272
+ var data = {
273
+ action :'ab_update_service_value',
274
+ id : $(this).parents('.service-row').first().attr('id')
275
+ };
276
+ data['color'] = $(this).wpColorPicker('color');
277
+ $.post(ajaxurl, data);
278
+ }
279
+ });
280
+ }
281
+
282
+ function doNotCloseDropDowns() {
283
+ $('#ab-services-list .dropdown-menu').on('click', function(e) {
284
+ e.stopPropagation();
285
+ });
286
+ }
287
+
288
+ function initPopovers() {
289
+ // Popovers initialization.
290
+ $('.ab-popover').popover({
291
+ trigger : 'hover'
292
+ });
293
+ }
294
+
295
+ doNotCloseDropDowns();
296
+ initColorPicker($('.service-color'));
297
+ initPopovers();
298
+
299
+ $.ajaxSetup({
300
+ mode: 'abort',
301
+ port: 'ab_service'
302
+ });
303
+ });
backend/modules/service/templates/index.php ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <div class="ab-title"><?php _e('Services', 'ab') ?></div>
3
+ <div style="min-width: 800px;">
4
+ <div class="ab-left-bar">
5
+ <div id="ab-categories-list">
6
+ <div class="ab-category-item ab-active ab-main-category-item" data-id=""><?php _e('All Services','ab') ?></div>
7
+ <div class="ab-category-item-list">
8
+ <?php if (count($category_collection)): ?>
9
+ <?php foreach ($category_collection as $category):?>
10
+ <div class="ab-category-item" data-id="<?php echo $category->id ?>">
11
+ <span class="left displayed-value"><?php echo esc_html($category->name) ?></span>
12
+ <a href="#" class="left ab-hidden ab-edit"></a>
13
+ <input class="value ab-value" type="text" name="name" value="<?php echo esc_attr($category->name) ?>" style="display: none" />
14
+ <a href="#" class="left ab-hidden ab-delete"></a>
15
+ </div>
16
+ <?php endforeach ?>
17
+ <?php endif ?>
18
+ </div>
19
+ </div>
20
+ <input type="hidden" id="color" />
21
+ <div id="new_category_popup" class="ab-popup-wrapper">
22
+ <input class="btn btn-info ab-popup-trigger" data- type="submit" value="<?php _e('New Category','ab') ?>" />
23
+ <div class="ab-popup" style="display: none">
24
+ <div class="ab-arrow"></div>
25
+ <div class="ab-content">
26
+ <form method="post" id="new-category-form">
27
+ <table class="form-horizontal">
28
+ <tr>
29
+ <td>
30
+ <input class="ab-clear-text" style="width: 170px" type="text" name="name" />
31
+ <input type="hidden" name="action" value="ab_category_form" />
32
+ </td>
33
+ </tr>
34
+ <tr>
35
+ <td>
36
+ <input type="submit" class="btn btn-info ab-popup-save ab-update-button" value="<?php _e('Save category','ab') ?>" />
37
+ <a class="ab-popup-close" href="#"><?php _e('Cancel','ab') ?></a>
38
+ </td>
39
+ </tr>
40
+ </table>
41
+ <a class="ab-popup-close ab-popup-close-icon" href="#"></a>
42
+ </form>
43
+ </div>
44
+ </div>
45
+ </div>
46
+ </div>
47
+ <div class="ab-right-content" id="ab_services_wrapper">
48
+ <h2 class="ab-category-title"><?php _e('All services','ab') ?></h2>
49
+ <div class="no-result"<?php if (count($category_collection)) : ?> style="display: none"<?php endif; ?>><?php _e( 'No services found. Please add services.','ab' ) ?></div>
50
+ <div class="list-wrapper">
51
+ <div id="ab-services-list">
52
+ <?php include 'list.php' ?>
53
+ </div>
54
+ <div class="list-actions">
55
+ <a class="add-service btn btn-info" href="#"><?php _e('Add Service','ab') ?></a>
56
+ <a class="delete btn btn-info" href="#"><?php _e('Delete','ab') ?></a>
57
+ </div>
58
+ </div>
59
+ </div>
60
+ </div>
61
+
62
+ <div class="modal fade" id="lite_notice" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
63
+ <div class="modal-dialog">
64
+ <div class="modal-content">
65
+ <div class="modal-header">
66
+ <h4 class="modal-title"><?php _e('Notice', 'ab') ?></h4>
67
+ </div>
68
+ <div class="modal-body">
69
+ <?php _e('This function is disabled in the lite version of Bookly. If you find the plugin useful for your business please consider buying a licence for the full version. It costs just $38 and for this money you will get many useful functions, lifetime free update and excellent support! More information can be found here', 'ab'); ?>: <a href="http://bookly.ladela.com" target="_blank">http://bookly.ladela.com</a>
70
+ </div>
71
+ <div class="modal-footer">
72
+ <button type="button" class="btn btn-default" data-dismiss="modal"><?php _e('Close', 'ab') ?></button>
73
+ </div>
74
+ </div><!-- /.modal-content -->
75
+ </div><!-- /.modal-dialog -->
76
+ </div><!-- /.modal -->
backend/modules/service/templates/list.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <?php if ( count( $service_collection ) ) : ?>
3
+ <table class="table table-striped" cellspacing="0" cellpadding="0" border="0" id="services_list">
4
+ <thead>
5
+ <tr>
6
+ <th class="first">&nbsp;</th>
7
+ <th><?php _e( 'Title', 'ab' ) ?></th>
8
+ <th style="width: 95px;"><?php _e( 'Duration', 'ab' ) ?></th>
9
+ <th><?php _e( 'Price', 'ab' ) ?></th>
10
+ <th><?php _e( 'Capacity', 'ab' ) ?>
11
+ <img title="" data-original-title="" src="<?php echo plugins_url( 'backend/resources/images/help.png', AB_PATH . '/main.php' ) ?>" alt="" class="ab-popover" data-content="<?php echo esc_attr( __( 'The maximum number of customers allowed to book the service for the certain time period.' ) ) ?>" style="width:16px;margin-left:0;"></th>
12
+ <th style="width: 65px;"><?php _e( 'Staff', 'ab' ) ?></th>
13
+ <th><?php _e( 'Category', 'ab' ) ?></th>
14
+ <th class="last">&nbsp;</th>
15
+ </tr>
16
+ </thead>
17
+ <tbody>
18
+ <?php
19
+ foreach ( $service_collection as $i => $service ) {
20
+ $row_class = 'service-row ';
21
+ $row_class .= $i % 2 ? 'even' : 'odd';
22
+ if ( 0 == $i ) {
23
+ $row_class .= ' first';
24
+ }
25
+ if ( ! isset( $service_collection[$i + 1] ) ) {
26
+ $row_class .= ' last';
27
+ }
28
+ include 'list_item.php';
29
+ }
30
+ ?>
31
+ </tbody>
32
+ </table>
33
+ <?php endif ?>
backend/modules/service/templates/list_item.php ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @var array $category_collection
4
+ * @var array $staff_collection
5
+ * @var AB_Service $service
6
+ */
7
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
8
+ ?>
9
+ <tr id="<?php echo $service->id ?>" class="<?php echo $row_class ?>">
10
+ <td class="first service-color-cell">
11
+ <div class="service-color-wrapper">
12
+ <input type="hidden" class="service-color" name="color" value="<?php echo $service->color ?>" />
13
+ </div>
14
+ </td>
15
+ <td class="title editable-cell">
16
+ <?php if ( $service->title ) : ?>
17
+ <div class="displayed-value"><?php echo esc_html($service->title) ?></div>
18
+ <input class="value ab-value" type="text" name="title" value="<?php echo esc_attr( $service->title ) ?>" style="display: none" />
19
+ <?php else : ?>
20
+ <div class="displayed-value" style="display: none"></div>
21
+ <input class="value ab-value" type="text" name="title" />
22
+ <?php endif; ?>
23
+ </td>
24
+ <td>
25
+ <select name="duration">
26
+ <?php
27
+ $time_interval = get_option( 'ab_settings_time_slot_length' );
28
+ ?>
29
+ <!-- Build service duration choices with the range from Time Interval Option to 12. -->
30
+ <?php for ( $j = $time_interval; $j <= 720; $j += $time_interval ) : ?>
31
+ <?php
32
+ $duration = $j * 60;
33
+ $duration_output = AB_Service::durationToString( $duration );
34
+ ?>
35
+ <option value="<?php echo $duration ?>" <?php selected($service->duration, $duration) ?>>
36
+ <?php echo $duration_output ?>
37
+ </option>
38
+ <?php endfor; ?>
39
+ </select>
40
+ </td>
41
+ <td align='right' class="editable-cell price">
42
+ <div class="displayed-value ab-rtext"><?php echo $service->price ?></div>
43
+ <?php if ( $service->price ) : ?>
44
+ <input class="value ab-text-focus" type="number" min="0.00" step="any" name="price" value="<?php echo esc_attr( $service->price ) ?>" style="display: none" />
45
+ <?php else : ?>
46
+ <input class="value ab-text-focus" type="number" min="0.00" step="any" name="price" />
47
+ <?php endif; ?>
48
+ </td>
49
+ <td align='right' class="editable-cell capacity">
50
+ <div class="displayed-value ab-rtext">1</div>
51
+ <input class="value ab-text-focus" type="number" min="1" step="any" name="capacity" value="1" style="display: none" />
52
+ </td>
53
+ <td>
54
+ <?php if ( count( $staff_collection ) ) : ?>
55
+ <div class="btn-group">
56
+ <?php
57
+ $assigned_staff_ids = $service->staff_ids ? explode(',', $service->staff_ids) : array();
58
+ $all_staff_selected = count( $assigned_staff_ids ) == count( $staff_collection );
59
+ ?>
60
+ <button class="btn btn-info"><i class="icon-user icon-white"></i> <span class=staff-count><?php echo $service->total_staff ?></span></button>
61
+ <button class="btn btn-info dropdown-toggle" data-toggle="dropdown">
62
+ <span class="caret"></span>
63
+ </button>
64
+ <ul class="dropdown-menu">
65
+ <li>
66
+ <a href="javascript:void(0)">
67
+ <input type="checkbox" id="service_<?php echo $service->id ?>_all_staff" class="all-staff"<?php if ( $all_staff_selected ) : ?> checked="checked" <?php endif; ?> />
68
+ <label class="inline" for="service_<?php echo $service->id ?>_all_staff"><?php _e('All staff','ab') ?></label>
69
+ </a>
70
+ </li>
71
+ <?php foreach ( $staff_collection as $i => $staff ) : ?>
72
+ <li>
73
+ <a href="javascript:void(0)" style="padding-left: 30px">
74
+ <?php $staff_checked = in_array( $staff->id, $assigned_staff_ids ) ?>
75
+ <input type="checkbox" name="staff_ids[]" class="staff" id="service_<?php echo $service->id ?>_staff_<?php echo $i ?>" value="<?php echo $staff->id ?>"<?php if ( $staff_checked ) : ?> checked="checked"<?php endif; ?>/>
76
+ <label class="inline" for="service_<?php echo $service->id ?>_staff_<?php echo $i ?>">
77
+ <?php echo esc_html($staff->full_name) ?>
78
+ </label>
79
+ </a>
80
+ </li>
81
+ <?php endforeach; ?>
82
+ </ul>
83
+ </div>
84
+ <?php else : ?>
85
+ &nbsp;
86
+ <?php endif; ?>
87
+ </td>
88
+ <td>
89
+ <?php if ( count( $category_collection ) ) : ?>
90
+ <select name="category_id">
91
+ <option value="0"></option>
92
+ <?php foreach ( $category_collection as $category ) : ?>
93
+ <option value="<?php echo $category->id ?>" <?php selected($category->id, $service->category_id) ?>>
94
+ <?php echo esc_html($category->name) ?>
95
+ </option>
96
+ <?php endforeach; ?>
97
+ </select>
98
+ <?php else: ?>
99
+ &nbsp;
100
+ <?php endif; ?>
101
+ </td>
102
+ <td class="last">
103
+ <input type="checkbox" class="row-checker" />
104
+ </td>
105
+ </tr>
backend/modules/settings/AB_SettingsController.php ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ include 'forms/AB_CompanyForm.php';
6
+ include 'forms/AB_PaymentsForm.php';
7
+ include 'forms/AB_BusinessHoursForm.php';
8
+ include AB_PATH . '/lib/Payment/PayPal.php';
9
+
10
+ /**
11
+ * Class AB_SettingsController
12
+ */
13
+ class AB_SettingsController extends AB_Controller {
14
+
15
+ public function index() {
16
+ // save the settings
17
+ if ( !empty ( $_POST ) ) {
18
+ // Payments form
19
+ if ( $this->getParameter( 'type' ) == '_payments' ) {
20
+ $this->form = new AB_PaymentsForm();
21
+ $this->message_p = __( 'Settings saved.', 'ab' );
22
+
23
+ // Business hours form
24
+ }
25
+ else if ( $this->getParameter( 'type' ) == '_hours' ) {
26
+ $this->form = new AB_BusinessHoursForm();
27
+ $this->message_h = __( 'Settings saved.', 'ab' );
28
+ }
29
+ // Purchase Code Form
30
+ else if ( $this->getParameter( 'type' ) == '_purchase_code' ) {
31
+ update_option( 'ab_envato_purchase_code', esc_html( $this->getParameter( 'ab_envato_purchase_code' ) ) );
32
+ $this->message_pc = __( 'Settings saved.', 'ab' );
33
+ }
34
+ else if ( $this->getParameter( 'type' ) == '_general' ) {
35
+ $ab_settings_time_slot_length = $this->getParameter( 'ab_settings_time_slot_length' );
36
+ if ( in_array( $ab_settings_time_slot_length, array( 5, 10, 12, 15, 20, 30, 60 ) ) ) {
37
+ update_option( 'ab_settings_time_slot_length', $ab_settings_time_slot_length );
38
+ }
39
+ update_option( 'ab_settings_no_current_day_appointments', (int)$this->getParameter( 'ab_settings_no_current_day_appointments' ) );
40
+ update_option( 'ab_settings_use_client_time_zone', (int)$this->getParameter( 'ab_settings_use_client_time_zone' ) );
41
+ update_option( 'ab_settings_cancel_page_url', $this->getParameter( 'ab_settings_cancel_page_url' ) );
42
+
43
+ $this->message_g = __( 'Settings saved.', 'ab' );
44
+ }
45
+ // Holidays form
46
+ else if ( $this->getParameter( 'type' ) == '_holidays' ) {
47
+ // Company form
48
+ }
49
+ else {
50
+ $this->form = new AB_CompanyForm();
51
+ $this->message_c = __( 'Settings saved.', 'ab' );
52
+ }
53
+ if ( $this->getParameter( 'type' ) != '_purchase_code' && $this->getParameter( 'type' ) != '_holidays'
54
+ && $this->getParameter( 'type' ) != '_import' && $this->getParameter( 'type' ) != '_general' ) {
55
+ $this->form->bind( $this->getPostParameters(), $_FILES );
56
+ $this->form->save();
57
+ }
58
+ }
59
+
60
+ // get holidays
61
+ $this->holidays = $this->getHolidays();
62
+
63
+ $this->render( 'index' );
64
+ } // index
65
+
66
+ /**
67
+ * Ajax request for Holidays calendar
68
+ */
69
+ public function executeSettingsHoliday() {
70
+ $id = $this->getParameter( 'id', false );
71
+ $holiday = $this->getParameter( 'holiday' ) == 'true';
72
+ $repeat = $this->getParameter( 'repeat' ) == 'true';
73
+ $day = $this->getParameter( 'day', false );
74
+
75
+ // update or delete the event
76
+ if ( $id ) {
77
+ if ( $holiday ) {
78
+ $this->getWpdb()->update( 'ab_holiday', array('repeat_event' => intval( $repeat ) ), array( 'id' => $id ), array( '%d' ) );
79
+ $this->getWpdb()->update( 'ab_holiday', array( 'repeat_event' => intval( $repeat ) ), array( 'parent_id' => $id ), array( '%d' ) );
80
+ } else {
81
+ $this->getWpdb()->delete( 'ab_holiday', array( 'id' => $id ), array( '%d' ) );
82
+ $this->getWpdb()->delete( 'ab_holiday', array( 'parent_id' => $id ), array( '%d' ) );
83
+ }
84
+ // add the new event
85
+ } elseif ( $holiday && $day ) {
86
+ $day = new DateTime( $day );
87
+ $this->getWpdb()->insert( 'ab_holiday', array( 'holiday' => $day->format( 'Y-m-d H:i:s' ), 'repeat_event' => intval( $repeat ) ), array( '%s', '%d' ) );
88
+ $parent_id = $this->getWpdb()->insert_id;
89
+ $staff = $this->getWpdb()->get_results( 'SELECT id FROM ab_staff' );
90
+ foreach ( $staff as $employee ) {
91
+ $this->getWpdb()->insert( 'ab_holiday',
92
+ array(
93
+ 'holiday' => date( 'Y-m-d H:i:s', $day->format( 'U' ) ),
94
+ 'repeat_event' => intval( $repeat ),
95
+ 'staff_id' => $employee->id,
96
+ 'parent_id' => $parent_id
97
+ ),
98
+ array( '%s', '%d', '%d' )
99
+ );
100
+ }
101
+ }
102
+
103
+ // and return refreshed events
104
+ echo $this->getHolidays();
105
+ exit;
106
+ }
107
+
108
+ /**
109
+ * @return mixed|string|void
110
+ */
111
+ protected function getHolidays() {
112
+ $collection = $this->getWpdb()->get_results( "SELECT * FROM ab_holiday WHERE staff_id IS NULL" );
113
+ $holidays = array();
114
+ if ( count( $collection ) ) {
115
+ foreach ( $collection as $holiday ) {
116
+ $holidays[ $holiday->id ] = array(
117
+ 'm' => intval( date( 'm', strtotime( $holiday->holiday ) ) ),
118
+ 'd' => intval( date( 'd', strtotime( $holiday->holiday ) ) ),
119
+ 'title' => $holiday->title,
120
+ );
121
+ // if not repeated holiday, add the year
122
+ if ( ! $holiday->repeat_event ) {
123
+ $holidays[ $holiday->id ][ 'y' ] = intval( date( 'Y', strtotime( $holiday->holiday ) ) );
124
+ }
125
+ }
126
+ }
127
+
128
+ return json_encode( (object) $holidays );
129
+ }
130
+
131
+ /**
132
+ * Ajax request to dismiss admin notice for current user.
133
+ */
134
+ public function executeDismissAdminNotice() {
135
+ global $current_user;
136
+
137
+ update_user_meta( $current_user->ID, 'ab_dismiss_admin_notice', 1 );
138
+ }
139
+
140
+ /**
141
+ * Override parent method to add 'wp_ajax_ab_' prefix
142
+ * so current 'execute*' methods look nicer.
143
+ */
144
+ protected function registerWpActions( $prefix = '' ) {
145
+ parent::registerWpActions( 'wp_ajax_ab_' );
146
+ }
147
+ }
backend/modules/settings/forms/AB_BusinessHoursForm.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ class AB_BusinessHoursForm extends AB_Form {
6
+
7
+ public function __construct() {
8
+ $this->setFields(array(
9
+ 'ab_settings_monday_start',
10
+ 'ab_settings_monday_end',
11
+ 'ab_settings_tuesday_start',
12
+ 'ab_settings_tuesday_end',
13
+ 'ab_settings_wednesday_start',
14
+ 'ab_settings_wednesday_end',
15
+ 'ab_settings_thursday_start',
16
+ 'ab_settings_thursday_end',
17
+ 'ab_settings_friday_start',
18
+ 'ab_settings_friday_end',
19
+ 'ab_settings_saturday_start',
20
+ 'ab_settings_saturday_end',
21
+ 'ab_settings_sunday_start',
22
+ 'ab_settings_sunday_end',
23
+ ));
24
+ }
25
+
26
+ public function save() {
27
+
28
+ foreach ( $this->data as $field => $value ) {
29
+ update_option( $field, $value );
30
+ }
31
+ }
32
+
33
+ /**
34
+ * @param string $field_name
35
+ * @param bool $is_start
36
+ * @return string
37
+ */
38
+ public function renderField($field_name = 'ab_settings_monday', $is_start = true) {
39
+
40
+ $time_format = get_option( 'time_format' );
41
+ $ts_length = get_option( 'ab_settings_time_slot_length' );
42
+ $time_output = new DateTime( AB_StaffScheduleItem::WORKING_START_TIME, new DateTimeZone( 'UTC' ) );
43
+ $time_end = new DateTime( AB_StaffScheduleItem::WORKING_END_TIME, new DateTimeZone( 'UTC' ) );
44
+ $ts_length = '+' . $ts_length . ' min';
45
+ $option_name = $field_name . ( $is_start ? '_start' : '_end' );
46
+ $class_name = $is_start ? 'select_start' : 'select_end';
47
+ $selected_value = get_option( $option_name );
48
+ $output = "<select name={$option_name} class={$class_name}>";
49
+
50
+ if( $is_start ) $output .= "<option value=''>" . __( 'OFF','ab' ) . "</option>";
51
+
52
+ while ( $time_output <= $time_end ) {
53
+ $value = $time_output->format( 'H:i' );
54
+ $op_name = $time_output->format( $time_format );
55
+ $selected = $value == $selected_value ? ' selected="selected"' : '';
56
+ $output .= "<option value='{$value}'{$selected}>{$op_name}</option>";
57
+ $time_output->modify( $ts_length );
58
+ }
59
+
60
+ $output .= '</select>';
61
+
62
+ return $output;
63
+ }
64
+ }
backend/modules/settings/forms/AB_CompanyForm.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ class AB_CompanyForm extends AB_Form {
6
+
7
+ public function __construct() {
8
+ $this->setFields(array(
9
+ 'ab_settings_company_name',
10
+ 'ab_settings_company_logo',
11
+ 'ab_settings_company_address',
12
+ 'ab_settings_company_phone',
13
+ 'ab_settings_company_website',
14
+ 'ab_settings_company_logo_path',
15
+ 'ab_settings_company_logo_url',
16
+ ));
17
+ }
18
+
19
+ /**
20
+ * @param array $post
21
+ * @param array $files
22
+ */
23
+ public function bind( array $post, array $files = array() ) {
24
+
25
+ parent::bind( $post, $files );
26
+
27
+ // remove the old image
28
+ if ( isset( $post['ab_remove_logo'] ) && file_exists( get_option( 'ab_settings_company_logo_path' ) ) ) {
29
+ unlink( get_option( 'ab_settings_company_logo_path' ) );
30
+ update_option( 'ab_settings_company_logo_path', '' );
31
+ update_option( 'ab_settings_company_logo_url', '' );
32
+ }
33
+
34
+ // and add new
35
+ if ( isset ($files['ab_settings_company_logo']) && $files['ab_settings_company_logo']['tmp_name'] ) {
36
+
37
+ if ( in_array( $files['ab_settings_company_logo']['type'], array( "image/gif", "image/jpeg", "image/png" ) ) ) {
38
+ $movefile = wp_handle_upload( $files['ab_settings_company_logo'], array( 'test_form' => false ) );
39
+ if ( $movefile ) {
40
+ $imageResize = new AB_ImageResize($movefile['file']);
41
+ $imageResize->resizeImage( 150, 150 );
42
+ $imageResize->saveImage($movefile['file']);
43
+
44
+ $this->data['ab_settings_company_logo_path'] = $movefile['file'];
45
+ $this->data['ab_settings_company_logo_url'] = $movefile['url'];
46
+
47
+ // remove the old image
48
+ if ( file_exists( get_option( 'ab_settings_company_logo_path' ) ) ) {
49
+ unlink( get_option( 'ab_settings_company_logo_path' ) );
50
+ }
51
+ }
52
+ }
53
+ }
54
+ }
55
+
56
+ public function save() {
57
+ foreach ( $this->data as $field => $value ) {
58
+ update_option( $field, $value );
59
+ }
60
+ }
61
+ }
backend/modules/settings/forms/AB_PaymentsForm.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ class AB_PaymentsForm extends AB_Form {
6
+
7
+ public function __construct() {
8
+ $this->setFields(array(
9
+ 'ab_settings_pay_locally',
10
+ 'ab_paypal_currency',
11
+ ));
12
+ }
13
+
14
+ public function save() {
15
+ foreach ( $this->data as $field => $value ) {
16
+ update_option( $field, $value );
17
+ }
18
+ }
19
+ }
backend/modules/settings/resources/js/settings.js ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(function ($) {
2
+ var $form = $('#business-hours'),
3
+ $all_tabs = $('#ab_settings_company, #ab_settings_payments, #ab_settings_hours, #ab_settings_holidays, #ab_settings_purchase_code, #ab_settings_general'),
4
+ $all_forms = $('#company-form, #payments-form, #hours-form, #holidays-form, #purchase-code-form, #general-form');
5
+ $('.select_start', $form).on('change', function () {
6
+ var $row = $(this).parent(),
7
+ $end_select = $('.select_end', $row),
8
+ $start_select = $(this);
9
+
10
+ if ($start_select.val()) {
11
+ $end_select.show();
12
+ $('span', $row).show();
13
+
14
+ var start_time = $start_select.val();
15
+
16
+ $('span > option', $end_select).each(function () {
17
+ $(this).unwrap();
18
+ });
19
+
20
+ // Hides end time options with value less than in the start time
21
+ $('option', $end_select).each(function () {
22
+ if ($(this).val() <= start_time) {
23
+ $(this).wrap("<span>").parent().hide();
24
+ }
25
+ });
26
+
27
+ if (start_time >= $end_select.val()) {
28
+ $('option:visible:first', $end_select).attr('selected', true);
29
+ }
30
+ } else { // OFF
31
+ $end_select.hide();
32
+ $('span', $row).hide();
33
+ }
34
+ }).each(function () {
35
+ var $row = $(this).parent(),
36
+ $end_select = $('.select_end', $row);
37
+
38
+ $(this).data('default_value', $(this).val());
39
+ $end_select.data('default_value', $end_select.val());
40
+
41
+ // Hides end select for "OFF" days
42
+ if (!$(this).val()) {
43
+ $end_select.hide();
44
+ $('span', $row).hide();
45
+ }
46
+ }).trigger('change');
47
+
48
+ // Reset
49
+ $('#ab-hours-reset', $form).on('click', function () {
50
+ $('.select_start', $form).each(function () {
51
+ $(this).val($(this).data('default_value'));
52
+ $(this).trigger('click');
53
+ });
54
+
55
+ $('.select_end', $form).each(function () {
56
+ $(this).val($(this).data('default_value'));
57
+ });
58
+
59
+ $('.select_start', $form).trigger('change');
60
+ });
61
+
62
+ // Tabs Onclick Handlers
63
+ $all_tabs.on('click', function() {
64
+ $('.ab-active').removeClass('ab-active');
65
+ $(this).addClass('ab-active');
66
+ });
67
+ $('#ab_settings_company').on('click', function() {
68
+ $all_forms.addClass('hidden');
69
+ $('#company-form').removeClass('hidden');
70
+ });
71
+ $('#ab_settings_payments').on('click', function() {
72
+ $all_forms.addClass('hidden');
73
+ $('#payments-form').removeClass('hidden');
74
+ });
75
+ $('#ab_settings_hours').on('click', function() {
76
+ $all_forms.addClass('hidden');
77
+ $('#hours-form').removeClass('hidden');
78
+ });
79
+ $('#ab_settings_holidays').on('click', function() {
80
+ $all_forms.addClass('hidden');
81
+ $('#holidays-form').removeClass('hidden');
82
+ });
83
+ $('#ab_settings_purchase_code').on('click', function() {
84
+ $all_forms.addClass('hidden');
85
+ $('#purchase-code-form').removeClass('hidden');
86
+ });
87
+ $('#ab_settings_general').on('click', function() {
88
+ $all_forms.addClass('hidden');
89
+ $('#general-form').removeClass('hidden');
90
+ });
91
+
92
+ // Company Tab
93
+ $('#ab-delete-logo').on('click', function() {
94
+ $('#ab-show-logo').hide(300).append('<input type="hidden" id="ab-remove-logo" name="ab_remove_logo" value="1" />');
95
+ });
96
+ $('#ab_settings_company_logo').on('change', function() { $('#ab-remove-logo').remove(); });
97
+
98
+ $('#ab-settings-company-reset').on('click', function() {
99
+ $('#ab-remove-logo').remove();
100
+ $('#ab-show-logo').show(300);
101
+ });
102
+
103
+ //Payment Tab
104
+ $('#ab_paypal_type,#ab_authorizenet_type,#ab_stripe,[name=ab_settings_coupons]').change(function() {
105
+ $('#lite_notice').modal('show');
106
+ $(this).val('disabled');
107
+ });
108
+
109
+ $("#ab-payments-reset").on("click", function(event){
110
+ event.preventDefault();
111
+ $(this).closest('form').get(0).reset();
112
+ });
113
+
114
+ $('.ab-popover').popover({
115
+ trigger : 'hover'
116
+ });
117
+
118
+ $('.ab-popover-ext').popover({
119
+ content: function() {
120
+ return $('#' + $(this).data('ext_id')).html();
121
+ },
122
+ html: true
123
+ });
124
+
125
+ $('[name=ab_settings_google_client_id],[name=ab_settings_google_client_secret],.lite-help').on('click', function(){
126
+ $('#lite_notice').modal('show');
127
+ });
128
+ });
129
+
backend/modules/settings/templates/_companyForm.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <form method="post" action="<?php echo add_query_arg( 'type', '_company' ) ?>" enctype="multipart/form-data" class="ab-staff-form">
3
+
4
+ <?php if (isset($message_c)) : ?>
5
+ <div id="message" style="margin: 0px!important;" class="updated below-h2">
6
+ <button type="button" class="close" data-dismiss="alert">&times;</button>
7
+ <p><?php echo $message_c ?></p>
8
+ </div>
9
+ <?php endif ?>
10
+
11
+ <table class="form-horizontal">
12
+ <tr>
13
+ <td><?php _e('Company name','ab') ?></td>
14
+ <td><input type="text" size="33" name="ab_settings_company_name" value="<?php echo get_option('ab_settings_company_name') ?>" reset="<?php echo get_option('ab_settings_company_name') ?>"/></td>
15
+ </tr>
16
+ <tr>
17
+ <td valign="top"><?php _e('Company logo','ab') ?></td>
18
+ <td>
19
+ <?php if ( get_option( 'ab_settings_company_logo_url' ) ): ?>
20
+ <div id="ab-show-logo">
21
+ <img src="<?php echo get_option( 'ab_settings_company_logo_url' ) ?>" alt="<?php _e( 'Company logo','ab' ) ?>"/>
22
+ <a id="ab-delete-logo" href="javascript:void(0)"><?php _e( 'Delete','ab' ) ?></a>
23
+ <br/>
24
+ </div>
25
+ <?php endif ?>
26
+ <input name="ab_settings_company_logo" id="ab_settings_company_logo" type="file" />
27
+ </td>
28
+ </tr>
29
+ <tr>
30
+ <td valign="top"><?php _e('Address','ab') ?></td>
31
+ <td><textarea cols="32" rows="5" name="ab_settings_company_address"><?php echo get_option('ab_settings_company_address') ?></textarea></td>
32
+ </tr>
33
+ <tr>
34
+ <td><?php _e('Phone','ab') ?></td>
35
+ <td><input type="text" size="33" name="ab_settings_company_phone" value="<?php echo get_option('ab_settings_company_phone') ?>" /></td>
36
+ </tr>
37
+ <tr>
38
+ <td><?php _e('Website','ab') ?></td>
39
+ <td><input type="text" size="33" name="ab_settings_company_website" value="<?php echo get_option('ab_settings_company_website') ?>" /></td>
40
+ </tr>
41
+ <tr>
42
+ <td></td>
43
+ <td>
44
+ <input type="submit" value="<?php _e( 'Save', 'ab' ) ?>" class="btn btn-info ab-update-button" />
45
+ <button id="ab-settings-company-reset" class="ab-reset-form" type="reset"><?php _e( ' Reset ', 'ab' ) ?></button>
46
+ </td>
47
+ </tr>
48
+ </table>
49
+ </form>
backend/modules/settings/templates/_generalForm.php ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <form method="post" action="<?php echo add_query_arg( 'type', '_general' ) ?>" enctype="multipart/form-data" class="ab-staff-form">
3
+
4
+ <?php if (isset($message_g)) : ?>
5
+ <div id="message" style="margin: 0px!important;" class="updated below-h2">
6
+ <button type="button" class="close" data-dismiss="alert">&times;</button>
7
+ <p><?php echo $message_g ?></p>
8
+ </div>
9
+ <?php endif ?>
10
+
11
+ <table class="form-horizontal">
12
+ <tr>
13
+ <td><?php _e('Time slot length','ab') ?></td>
14
+ <td>
15
+ <select name="ab_settings_time_slot_length" style="width: 200px;">
16
+ <?php
17
+ foreach ( array( 5, 10, 12, 15, 20, 30, 60 ) as $duration ) {
18
+ $duration_output = AB_Service::durationToString( $duration * 60 );
19
+ ?>
20
+ <option value="<?php echo $duration ?>" <?php selected( get_option( 'ab_settings_time_slot_length' ), $duration ); ?>>
21
+ <?php echo $duration_output ?>
22
+ </option>
23
+ <?php } ?>
24
+ </select>
25
+ </td>
26
+ <td>
27
+ <img
28
+ src="<?php echo plugins_url( 'backend/resources/images/help.png', AB_PATH . '/main.php' ) ?>"
29
+ alt=""
30
+ class="ab-popover"
31
+ data-content="<?php echo esc_attr( __( 'Select the time interval that will be used in frontend and backend, e.g. in calendar, second step of the booking process, while indicating the working hours, etc.', 'ab' ) ) ?>"
32
+ />
33
+ </td>
34
+ </tr>
35
+ <tr>
36
+ <td>
37
+ <label><?php _e( 'Make it impossible for users to book appointments on the current day (last minute appointments)', 'ab' ) ?></label>
38
+ </td>
39
+ <td style="vertical-align: top">
40
+ <select name="ab_settings_no_current_day_appointments" style="width: 200px;">
41
+ <?php foreach ( array( __( 'Disabled', 'ab' ) => '0', __( 'Enabled', 'ab' ) => '1' ) as $text => $mode ): ?>
42
+ <option value="<?php echo $mode ?>" <?php selected( get_option( 'ab_settings_no_current_day_appointments' ), $mode ); ?> ><?php echo $text ?></option>
43
+ <?php endforeach ?>
44
+ </select>
45
+ </td>
46
+ </tr>
47
+ <tr>
48
+ <td>
49
+ <label><?php _e( 'Display available time slots in client\'s time zone', 'ab' ) ?></label>
50
+ </td>
51
+ <td>
52
+ <select name="ab_settings_use_client_time_zone" style="width: 200px;">
53
+ <?php foreach ( array( __( 'Disabled', 'ab' ) => '0', __( 'Enabled', 'ab' ) => '1' ) as $text => $mode ): ?>
54
+ <option value="<?php echo $mode ?>" <?php selected( get_option( 'ab_settings_use_client_time_zone' ), $mode ); ?> ><?php echo $text ?></option>
55
+ <?php endforeach ?>
56
+ </select>
57
+ </td>
58
+ <td>
59
+ <img
60
+ src="<?php echo plugins_url( 'backend/resources/images/help.png', AB_PATH . '/main.php' ) ?>"
61
+ alt=""
62
+ class="ab-popover"
63
+ data-content="<?php echo esc_attr( __( 'The value is taken from client’s browser.', 'ab' ) ) ?>"
64
+ />
65
+ </td>
66
+ </tr>
67
+ <tr>
68
+ <td>
69
+ <label><?php _e( 'Cancel appointment page URL', 'ab' ) ?></label>
70
+ </td>
71
+ <td>
72
+ <input type="text" name="ab_settings_cancel_page_url" value="<?php echo get_option( 'ab_settings_cancel_page_url' ) ?>" >
73
+ </td>
74
+ <td>
75
+ <img
76
+ src="<?php echo plugins_url( 'backend/resources/images/help.png', AB_PATH . '/main.php' ) ?>"
77
+ alt=""
78
+ class="ab-popover"
79
+ data-content="<?php echo esc_attr( __( 'Insert the URL of the page that is shown to clients after they have cancelled their booking.', 'ab' ) ) ?>"
80
+ />
81
+ </td>
82
+ </tr>
83
+ <tr>
84
+ <td colspan="3">
85
+ <h4 style="float:left"><?php _e( 'Google Calendar', 'ab' ) ?></h4>
86
+ <img
87
+ style="float: left;margin-top: 8px;margin-left:15px;"
88
+ src="<?php echo plugins_url( 'backend/resources/images/help.png', AB_PATH . '/main.php' ) ?>"
89
+ alt=""
90
+ class="ab-popover lite-help"
91
+ />
92
+ </td>
93
+ </tr>
94
+ <tr>
95
+ <td>
96
+ <label><?php _e( 'Client ID', 'ab' ) ?></label>
97
+ </td>
98
+ <td>
99
+ <input type="text" name="ab_settings_google_client_id" value="" >
100
+ </td>
101
+ <td>
102
+ <img
103
+ src="<?php echo plugins_url( 'backend/resources/images/help.png', AB_PATH . '/main.php' ) ?>"
104
+ alt=""
105
+ class="ab-popover"
106
+ data-content="<?php echo esc_attr( __( 'The client ID obtained from the Developers Console', 'ab' ) ) ?>"
107
+ />
108
+ </td>
109
+ </tr>
110
+ <tr>
111
+ <td>
112
+ <label><?php _e( 'Client secret', 'ab' ) ?></label>
113
+ </td>
114
+ <td>
115
+ <input type="text" name="ab_settings_google_client_secret" value="" >
116
+ </td>
117
+ <td>
118
+ <img
119
+ src="<?php echo plugins_url( 'backend/resources/images/help.png', AB_PATH . '/main.php' ) ?>"
120
+ alt=""
121
+ class="ab-popover"
122
+ data-content="<?php echo esc_attr( __( 'The client secret obtained from the Developers Console', 'ab' ) ) ?>"
123
+ />
124
+ </td>
125
+ </tr>
126
+ <tr>
127
+ <td>
128
+ <label><?php _e( 'Redirect URI', 'ab' ) ?></label>
129
+ </td>
130
+ <td>
131
+ <input type="text" readonly value="" onclick="this.select();" style="cursor: pointer;">
132
+ </td>
133
+ <td>
134
+ <img
135
+ src="<?php echo plugins_url( 'backend/resources/images/help.png', AB_PATH . '/main.php' ) ?>"
136
+ alt=""
137
+ class="ab-popover"
138
+ data-content="<?php _e('Enter this URL as a redirect URI in the Developers Console', 'ab') ?>"
139
+ />
140
+ </td>
141
+ </tr>
142
+ <tr>
143
+ <td></td>
144
+ <td>
145
+ <input type="submit" value="<?php _e( 'Save', 'ab' ) ?>" class="btn btn-info ab-update-button" />
146
+ <button class="ab-reset-form" type="reset"><?php _e( ' Reset ', 'ab' ) ?></button>
147
+ </td>
148
+ </tr>
149
+ </table>
150
+ </form>
backend/modules/settings/templates/_holidaysForm.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <div id="ab-annual-calendar-scroll" style="text-align: center;">
3
+ <div class="input-prepend input-append">
4
+ <span class="ab-week-picker-arrow prev add-on col-arrow">◄</span>
5
+ <input style="width: 70px; text-align: center;background: white" class="span2 jcal_year" readonly="readonly" id="appendedPrependedInput" size="16" type="text" value="2014">
6
+ <span class="ab-week-picker-arrow next add-on col-arrow">►</span>
7
+ </div>
8
+ </div>
9
+ <div id="ab-annual-calendar"></div>
10
+
11
+ <script type="text/javascript">
12
+ jQuery(function($) {
13
+ var d = new Date();
14
+ $('#ab-annual-calendar').jCal({
15
+ day: new Date(d.getFullYear(), 0, 1),
16
+ days: 1,
17
+ showMonths: 12,
18
+ scrollSpeed: 350,
19
+ events: <?php echo $holidays ?>,
20
+ action: 'ab_settings_holiday',
21
+ dayOffset: <?php echo get_option('start_of_week', 0) ?>
22
+ });
23
+ });
24
+ </script>
backend/modules/settings/templates/_hoursForm.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <form method="post" action="<?php echo add_query_arg( 'type', '_hours' ) ?>" class="ab-staff-form" id="business-hours">
3
+ <?php if (isset($message_h)) : ?>
4
+ <div class="alert">
5
+ <button type="button" class="close" data-dismiss="alert">&times;</button>
6
+ <?php echo $message_h ?>
7
+ </div>
8
+ <?php endif ?>
9
+
10
+ <?php $form = new AB_BusinessHoursForm(); ?>
11
+
12
+ <table>
13
+ <?php foreach ( array( 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday' ) as $day ): ?>
14
+ <tr>
15
+ <td><?php _e( ucfirst( $day ) ) ?></td>
16
+ <td>
17
+ <?php echo $form->renderField( 'ab_settings_' . $day ); ?>
18
+ <span><?php _e( ' to ', 'ab' ) ?></span>
19
+ <?php echo $form->renderField( 'ab_settings_' . $day, false ); ?>
20
+ </td>
21
+ </tr>
22
+ <?php endforeach; ?>
23
+ <tr>
24
+ <td></td>
25
+ <td>
26
+ <input type="submit" value="<?php _e( 'Save', 'ab' ) ?>" class="btn btn-info ab-update-button" />
27
+ <a id="ab-hours-reset" href="javascript:void(0)"><?php _e( 'Reset', 'ab' ) ?></a>
28
+ </td>
29
+ </tr>
30
+ </table>
31
+ </form>
backend/modules/settings/templates/_paymentsForm.php ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <form method="post" action="<?php echo add_query_arg( 'type', '_payments' ) ?>" class="ab-staff-form">
3
+ <?php if (isset($message_p)) : ?>
4
+ <div id="message" style="margin: 0px!important;" class="updated below-h2">
5
+ <button type="button" class="close" data-dismiss="alert">&times;</button>
6
+ <p><?php echo $message_p ?></p>
7
+ </div>
8
+ <?php endif ?>
9
+ <table class="form-horizontal">
10
+ <tr>
11
+ <td style="width: 170px;"><?php _e( 'Currency','ab' ) ?></td>
12
+ <td>
13
+ <select name="ab_paypal_currency" style="width: 200px;">
14
+ <?php foreach ( PayPal::getCurrencyCodes() as $code ): ?>
15
+ <option value="<?php echo $code ?>" <?php selected( get_option( 'ab_paypal_currency' ), $code ); ?> ><?php echo $code ?></option>
16
+ <?php endforeach ?>
17
+ </select>
18
+ </td>
19
+ </tr>
20
+ <tr>
21
+ <td style="width: 170px;"><?php _e( 'Coupons','ab' ) ?></td>
22
+ <td>
23
+ <select name="ab_settings_coupons" style="width: 200px;">
24
+ <?php foreach ( array( __( 'Disabled', 'ab' ) => 'disabled', __( 'Enabled', 'ab' ) => '1' ) as $text => $mode ): ?>
25
+ <option value="<?php echo $mode ?>" <?php selected( get_option( 'ab_settings_coupons' ), $mode ); ?> ><?php echo $text ?></option>
26
+ <?php endforeach ?>
27
+ </select>
28
+ </td>
29
+ </tr>
30
+ <tr>
31
+ <td colspan="2"><div class="ab-payments-title"><?php _e( 'Service paid locally','ab' ) ?></div></td>
32
+ </tr>
33
+ <tr>
34
+ <td colspan="2">
35
+ <select name="ab_settings_pay_locally" style="width: 200px;">
36
+ <?php foreach ( array( __( 'Disabled', 'ab' ) => '0', __( 'Enabled', 'ab' ) => '1' ) as $text => $mode ): ?>
37
+ <option value="<?php echo $mode ?>" <?php selected( get_option( 'ab_settings_pay_locally' ), $mode ); ?> ><?php echo $text ?></option>
38
+ <?php endforeach ?>
39
+ </select>
40
+ </td>
41
+ </tr>
42
+ <tr>
43
+ <td colspan="2"><div class="ab-payments-title">PayPal</div></td>
44
+ </tr>
45
+ <tr>
46
+ <td colspan="2">
47
+ <select id="ab_paypal_type" style="width: 200px;">
48
+ <?php foreach ( array( __( 'Disabled', 'ab' ) => 'disabled', 'PayPal Express Checkout' => 'ec' ) as $text => $mode ): ?>
49
+ <option value="<?php echo $mode ?>" ><?php echo $text ?></option>
50
+ <?php endforeach ?>
51
+ </select>
52
+ </td>
53
+ </tr>
54
+ <tr>
55
+ <td colspan="2"><div class="ab-payments-title">Authorize.Net</div></td>
56
+ </tr>
57
+ <tr>
58
+ <td colspan="2">
59
+ <select name="ab_authorizenet_type" id="ab_authorizenet_type" style="width: 200px;">
60
+ <?php foreach ( array( __( 'Disabled', 'ab' ) => 'disabled', 'Authorize.Net AIM' => 'aim' ) as $text => $mode ): ?>
61
+ <option value="<?php echo $mode ?>" <?php selected( get_option( 'ab_authorizenet_type' ), $mode ); ?> ><?php echo $text ?></option>
62
+ <?php endforeach ?>
63
+ </select>
64
+ </td>
65
+ </tr>
66
+ <tr>
67
+ <td colspan="2"><div class="ab-payments-title">Stripe</div></td>
68
+ </tr>
69
+ <tr>
70
+ <td colspan="2">
71
+ <select name="ab_stripe" id="ab_stripe" style="width: 200px;">
72
+ <?php foreach ( array( __( 'Disabled', 'ab' ) => 0, __( 'Enabled', 'ab' ) => 1 ) as $text => $mode ): ?>
73
+ <option value="<?php echo $mode ?>" <?php selected( get_option( 'ab_stripe' ), $mode ); ?> ><?php echo $text ?></option>
74
+ <?php endforeach ?>
75
+ </select>
76
+ </td>
77
+ </tr>
78
+ <tr>
79
+ <td colspan="2">
80
+ <input type="submit" value="<?php _e( 'Save', 'ab' ) ?>" class="btn btn-info ab-update-button" />
81
+ <button id="ab-payments-reset" class="ab-reset-form" type="reset"><?php _e( 'Reset', 'ab' ) ?></button>
82
+ </td>
83
+ <td></td>
84
+ </tr>
85
+ </table>
86
+ </form>
backend/modules/settings/templates/_purchaseCodeForm.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <form enctype="multipart/form-data" method="post" action="<?php echo add_query_arg( 'type', '_purchase_code' ) ?>" class="ab-staff-form" id="purchase_code">
3
+ <?php if ( isset ( $message_pc ) ) : ?>
4
+ <div class="alert">
5
+ <button type="button" class="close" data-dismiss="alert">&times;</button>
6
+ <?php echo $message_pc ?>
7
+ </div>
8
+ <?php endif ?>
9
+
10
+ <table class="form-horizontal">
11
+ <tr>
12
+ <td><?php _e( 'Purchase Code', 'ab' ) ?></td>
13
+ <td>
14
+ <label for="purchase_code"></label>
15
+ <input class="purchase-code" type="text" size="255" name="ab_envato_purchase_code" value="<?php echo get_option( 'ab_envato_purchase_code' ) ?>" />
16
+ </td>
17
+ </tr>
18
+ <tr>
19
+ <td></td>
20
+ <td>
21
+ <input type="submit" value="<?php _e( 'Save', 'ab' ) ?>" class="btn btn-info ab-update-button" />
22
+ <button class="ab-reset-form" type="reset"><?php _e( ' Reset ', 'ab' ) ?></button>
23
+ </td>
24
+ </tr>
25
+ </table>
26
+ </form>
backend/modules/settings/templates/index.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <div class="ab-title"><?php _e('Settings', 'ab') ?></div>
3
+ <div style="min-width: 800px;">
4
+ <div class="ab-left-bar">
5
+ <div id="ab_settings_general" class="ab-left-tab <?php echo ( ! isset( $_GET[ 'type' ] ) || $_GET[ 'type' ] == '_general' ) ? 'ab-active' : '' ?>"><?php _e( 'General','ab' ) ?></div>
6
+ <div id="ab_settings_company" class="ab-left-tab <?php echo isset( $_GET['type'] ) && $_GET['type'] == '_company' ? 'ab-active' : '' ?>"><?php _e( 'Company','ab' ) ?></div>
7
+ <div id="ab_settings_payments" class="ab-left-tab <?php echo isset( $_GET['type'] ) && $_GET['type'] == '_payments' ? 'ab-active' : '' ?>"><?php _e( 'Payments','ab' ) ?></div>
8
+ <div id="ab_settings_hours" class="ab-left-tab <?php echo isset( $_GET['type'] ) && $_GET['type'] == '_hours' ? 'ab-active' : '' ?>"><?php _e( 'Business hours','ab' ) ?></div>
9
+ <div id="ab_settings_holidays" class="ab-left-tab <?php echo isset( $_GET['type'] ) && $_GET['type'] == '_holidays' ? 'ab-active' : '' ?>"><?php _e( 'Holidays','ab' ) ?></div>
10
+ <div id="ab_settings_purchase_code" class="ab-left-tab <?php echo isset( $_GET[ 'type' ] ) && $_GET[ 'type' ] == '_purchase_code' ? 'ab-active' : '' ?>"><?php _e( 'Purchase Code','ab' ) ?></div>
11
+ </div>
12
+ <div class="ab-right-content" id="content_wrapper">
13
+ <div id="general-form" class="<?php echo ( ! isset( $_GET[ 'type' ] ) || $_GET[ 'type' ] == '_general' ) ? '' : 'hidden' ?> ab-staff-tab-content">
14
+ <?php include '_generalForm.php' ?>
15
+ </div>
16
+ <div id="company-form" class="<?php echo ( isset( $_GET['type'] ) && $_GET['type'] == '_company' ) ? '' : 'hidden' ?>">
17
+ <?php include '_companyForm.php' ?>
18
+ </div>
19
+ <div id="payments-form" class="<?php echo ( isset( $_GET['type'] ) && $_GET['type'] == '_payments' ) ? '' : 'hidden' ?>">
20
+ <?php include '_paymentsForm.php' ?>
21
+ </div>
22
+ <div id="hours-form" class="<?php echo ( isset( $_GET['type'] ) && $_GET['type'] == '_hours' ) ? '' : 'hidden' ?>">
23
+ <?php include '_hoursForm.php' ?>
24
+ </div>
25
+ <div id="holidays-form" class="<?php echo ( isset( $_GET['type'] ) && $_GET['type'] == '_holidays' ) ? '' : 'hidden' ?> ab-staff-tab-content">
26
+ <?php include '_holidaysForm.php' ?>
27
+ </div>
28
+ <div id="purchase-code-form" class="<?php echo ( isset( $_GET[ 'type' ] ) && $_GET[ 'type' ] == '_purchase_code' ) ? '' : 'hidden' ?> ab-staff-tab-content">
29
+ <?php include '_purchaseCodeForm.php' ?>
30
+ </div>
31
+ </div>
32
+ </div>
33
+
34
+ <div class="modal fade" id="lite_notice" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
35
+ <div class="modal-dialog">
36
+ <div class="modal-content">
37
+ <div class="modal-header">
38
+ <h4 class="modal-title"><?php _e('Notice', 'ab') ?></h4>
39
+ </div>
40
+ <div class="modal-body">
41
+ <?php _e('This function is disabled in the lite version of Bookly. If you find the plugin useful for your business please consider buying a licence for the full version. It costs just $38 and for this money you will get many useful functions, lifetime free update and excellent support! More information can be found here', 'ab'); ?>: <a href="http://bookly.ladela.com" target="_blank">http://bookly.ladela.com</a>
42
+ </div>
43
+ <div class="modal-footer">
44
+ <button type="button" class="btn btn-default" data-dismiss="modal"><?php _e('Close', 'ab') ?></button>
45
+ </div>
46
+ </div><!-- /.modal-content -->
47
+ </div><!-- /.modal-dialog -->
48
+ </div><!-- /.modal -->
backend/modules/staff/AB_StaffController.php ADDED
@@ -0,0 +1,369 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ include 'forms/AB_StaffMemberNewForm.php';
6
+ include 'forms/AB_StaffMemberEditForm.php';
7
+ include 'forms/AB_StaffServicesForm.php';
8
+ include 'forms/AB_StaffScheduleForm.php';
9
+ include 'forms/AB_StaffScheduleItemBreakForm.php';
10
+ include 'forms/widget/AB_TimeChoiceWidget.php';
11
+
12
+ /**
13
+ * Class AB_StaffController
14
+ *
15
+ * @property $form
16
+ * @property $collection
17
+ * @property $services
18
+ * @property $staff_id
19
+ * @property AB_Staff $staff
20
+ */
21
+ class AB_StaffController extends AB_Controller {
22
+
23
+ public function renderStaffMembers() {
24
+ $path = dirname( __DIR__ );
25
+ wp_enqueue_style( 'ab-style', plugins_url( 'resources/css/ab_style.css', $path ) );
26
+ wp_enqueue_style( 'ab-staff', plugins_url( 'resources/css/staff.css', __FILE__ ) );
27
+ wp_enqueue_style( 'ab-bootstrap', plugins_url( 'resources/bootstrap/css/bootstrap.min.css', $path ) );
28
+ wp_enqueue_script( 'ab-bootstrap', plugins_url( 'resources/bootstrap/js/bootstrap.min.js', $path ), array( 'jquery' ) );
29
+ wp_enqueue_script( 'ab-popup', plugins_url( 'resources/js/ab_popup.js', $path ), array( 'jquery' ) );
30
+ wp_enqueue_script( 'ab-system-staff', plugins_url( 'resources/js/staff.js', __FILE__ ), array( 'jquery' ) );
31
+ wp_enqueue_script( 'ab-jCal', plugins_url( 'resources/js/jCal.js', $path ), array( 'jquery' ) );
32
+ wp_enqueue_style( 'ab-jCal', plugins_url( 'resources/css/jCal.css', $path ) );
33
+ wp_localize_script( 'ab-jCal', 'BooklyL10n', array(
34
+ 'we_are_not_working' => __( 'We are not working on this day', 'ab' ),
35
+ 'repeat' => __( 'Repeat every year', 'ab' ),
36
+ 'month' => array(
37
+ 'January' => __( 'January', 'ab' ),
38
+ 'February' => __( 'February', 'ab' ),
39
+ 'March' => __( 'March', 'ab' ),
40
+ 'April' => __( 'April', 'ab' ),
41
+ 'May' => __( 'May', 'ab' ),
42
+ 'June' => __( 'June', 'ab' ),
43
+ 'July' => __( 'July', 'ab' ),
44
+ 'August' => __( 'August', 'ab' ),
45
+ 'September' => __( 'September', 'ab' ),
46
+ 'October' => __( 'October', 'ab' ),
47
+ 'November' => __( 'November', 'ab' ),
48
+ 'December' => __( 'December', 'ab' )
49
+ ),
50
+ 'day' => array(
51
+ 'Mon' => __( 'Mon', 'ab' ),
52
+ 'Tue' => __( 'Tue', 'ab' ),
53
+ 'Wed' => __( 'Wed', 'ab' ),
54
+ 'Thu' => __( 'Thu', 'ab' ),
55
+ 'Fri' => __( 'Fri', 'ab' ),
56
+ 'Sat' => __( 'Sat', 'ab' ),
57
+ 'Sun' => __( 'Sun', 'ab' )
58
+ )
59
+ ) );
60
+
61
+ wp_enqueue_script('jquery-ui-dialog');
62
+ wp_enqueue_style("wp-jquery-ui-dialog");
63
+
64
+ $this->form = new AB_StaffMemberNewForm();
65
+ $this->collection = $this->getWpdb()->get_results( "SELECT * FROM ab_staff LIMIT 1" );
66
+ if ( !isset ( $this->active_staff_id ) ) {
67
+ if ( $this->hasParameter( 'staff_id' ) ) {
68
+ $this->active_staff_id = $this->getParameter( 'staff_id' );
69
+ }
70
+ else {
71
+ $this->active_staff_id = $this->collection ? $this->collection[0]->id : 0;
72
+ }
73
+ }
74
+
75
+ $this->render( 'list' );
76
+ }
77
+
78
+ public function executeStaffServices() {
79
+ $this->form = new AB_StaffServicesForm();
80
+ $this->form->load( 1 );
81
+ $this->staff_id = 1;
82
+ $this->render( 'services' );
83
+ exit;
84
+ }
85
+
86
+ public function executeStaffSchedule() {
87
+ $staff = new AB_Staff();
88
+ $staff->load( 1 );
89
+ $this->schedule_list = $staff->getScheduleList();
90
+ $this->staff_id = 1;
91
+ $this->render( 'schedule' );
92
+ exit;
93
+ }
94
+
95
+ public function executeStaffScheduleUpdate() {
96
+ $this->form = new AB_StaffScheduleForm();
97
+ $this->form->bind( $this->getPostParameters() );
98
+ $this->form->save();
99
+ exit;
100
+ }
101
+
102
+ /**
103
+ *
104
+ * @throws Exception
105
+ */
106
+ public function executeResetBreaks() {
107
+ global $wpdb;
108
+ $breaks = $this->getParameter( 'breaks' );
109
+
110
+ // remove all breaks for staff member
111
+ $break = new AB_ScheduleItemBreak();
112
+ $break->removeBreaksByStaffId( $breaks[ 'staff_id' ] );
113
+ $html_breaks = array();
114
+
115
+ // restore previous breaks
116
+ if (isset($breaks['breaks']) && is_array($breaks['breaks'])) {
117
+ $query = "INSERT INTO ab_schedule_item_break (staff_schedule_item_id, start_time, end_time) VALUES ";
118
+
119
+ foreach ($breaks['breaks'] as $day) {
120
+ $query .= "($day[staff_schedule_item_id], '$day[start]', '$day[end]'), ";
121
+ }
122
+ $query = rtrim($query, ", ");
123
+ $wpdb->get_results($query);
124
+ }
125
+
126
+ $staff = new AB_Staff();
127
+ $staff->load( $breaks['staff_id'] );
128
+
129
+ // make array with breaks (html) for each day
130
+ foreach ($staff->getScheduleList() as $list_item) {
131
+ $html_breaks[$list_item->id] = $this->render("_breaks", array(
132
+ 'day_is_not_available' => null === $list_item->start_time,
133
+ 'list_item' => $list_item,
134
+ 'time_format' => get_option( 'time_format' ),
135
+ ), false);
136
+ }
137
+
138
+ echo json_encode($html_breaks);
139
+ exit();
140
+ }
141
+
142
+ public function executeStaffScheduleHandleBreak() {
143
+ $start_time = $this->getParameter( 'start_time' );
144
+ $end_time = $this->getParameter( 'end_time' );
145
+ $working_start = $this->getParameter( 'working_start' );
146
+ $working_end = $this->getParameter( 'working_end' );
147
+
148
+ if ( strtotime( date( 'Y-m-d ' . $start_time ) ) >= strtotime( date( 'Y-m-d ' . $end_time ) ) ) {
149
+ echo json_encode( array(
150
+ 'success' => false,
151
+ 'error_msg' => __( 'The start time must be less than the end one', 'ab'),
152
+ ) );
153
+ exit;
154
+ }
155
+
156
+ $staffScheduleItem = new AB_StaffScheduleItem();
157
+ $staffScheduleItem->load( $this->getParameter( 'staff_schedule_item_id' ) );
158
+
159
+ $break_id = $this->getParameter( 'break_id', 0 );
160
+
161
+ $in_working_time = $working_start <= $start_time && $start_time <= $working_end
162
+ && $working_start <= $end_time && $end_time <= $working_end;
163
+ if ( !$in_working_time || ! $staffScheduleItem->isBreakIntervalAvailable( $start_time, $end_time, $break_id ) ) {
164
+ echo json_encode( array(
165
+ 'success' => false,
166
+ 'error_msg' => __( 'The requested interval is not available', 'ab'),
167
+ ) );
168
+ exit;
169
+ }
170
+
171
+ $time_format = get_option( 'time_format' );
172
+ $formatted_interval_start = date_i18n( $time_format, strtotime( $start_time ) );
173
+ $formatted_interval_end = date_i18n( $time_format, strtotime( $end_time ) );
174
+ $formatted_interval = $formatted_interval_start . ' - ' . $formatted_interval_end;
175
+
176
+ if ( $break_id ) {
177
+ $break = new AB_ScheduleItemBreak();
178
+ $break->load( $break_id );
179
+ $break->set( 'start_time', $start_time );
180
+ $break->set( 'end_time', $end_time );
181
+ $break->save();
182
+
183
+ echo json_encode( array(
184
+ 'success' => true,
185
+ 'new_interval' => $formatted_interval,
186
+ ) );
187
+ } else {
188
+ $this->form = new AB_StaffScheduleItemBreakForm();
189
+ $this->form->bind( $this->getPostParameters() );
190
+
191
+ $staffScheduleItemBreak = $this->form->save();
192
+ if ( $staffScheduleItemBreak ) {
193
+ $breakStart = new AB_TimeChoiceWidget( array( 'use_empty' => false ) );
194
+ $break_start_choices = $breakStart->render(
195
+ '',
196
+ $start_time,
197
+ array(
198
+ 'class' => 'break-start',
199
+ 'data-default_value' => AB_StaffScheduleItem::WORKING_START_TIME
200
+ )
201
+ );
202
+ $breakEnd = new AB_TimeChoiceWidget( array( 'use_empty' => false ) );
203
+ $break_end_choices = $breakEnd->render(
204
+ '',
205
+ $end_time,
206
+ array(
207
+ 'class' => 'break-end',
208
+ 'data-default_value' => date( 'H:i:s', strtotime( AB_StaffScheduleItem::WORKING_START_TIME . ' + 1 hour' ) )
209
+ )
210
+ );
211
+ echo json_encode(array(
212
+ 'success' => true,
213
+ 'item_content' => '<div class="break-interval-wrapper" data-break_id="' . $staffScheduleItemBreak->get( 'id' ) . '">
214
+ <div class="ab-popup-wrapper hide-on-non-working-day">
215
+ <a class="ab-popup-trigger break-interval" href="javascript:void(0)">' . $formatted_interval . '</a>
216
+ <div class="ab-popup" style="display: none">
217
+ <div class="ab-arrow"></div>
218
+ <div class="error" style="display: none"></div>
219
+ <div class="ab-content">
220
+ <table cellspacing="0" cellpadding="0">
221
+ <tr>
222
+ <td>' . $break_start_choices . ' <span class="hide-on-non-working-day">' . __( 'to', 'ab') . '</span> ' . $break_end_choices . '</td>
223
+ </tr>
224
+ <tr>
225
+ <td>
226
+ <a class="btn btn-info ab-popup-save ab-save-break">' . __('Save break','ab') . '</a>
227
+ <a class="ab-popup-close" href="#">' . __('Cancel', 'ab') . '</a>
228
+ </td>
229
+ </tr>
230
+ </table>
231
+ <a class="ab-popup-close ab-popup-close-icon" href="javascript:void(0)"></a>
232
+ </div>
233
+ </div>
234
+ </div>
235
+ <img class="delete-break" src="' . plugins_url( 'backend/resources/images/delete_cross.png', AB_PATH . '/main.php' ) . '" />
236
+ </div>'
237
+ ) );
238
+ } else {
239
+ echo json_encode( array(
240
+ 'success' => false,
241
+ 'error_msg' => __( 'Error adding the break interval', 'ab'),
242
+ ) );
243
+ }
244
+ }
245
+
246
+ exit;
247
+ }
248
+
249
+ public function executeDeleteStaffScheduleBreak() {
250
+ $break = new AB_ScheduleItemBreak();
251
+ $break->load( 1 );
252
+ $break->delete();
253
+ exit;
254
+ }
255
+
256
+ public function executeStaffServicesUpdate() {
257
+ $this->form = new AB_StaffServicesForm();
258
+ $this->form->bind( $this->getPostParameters() );
259
+ $this->form->save();
260
+ exit;
261
+ }
262
+
263
+ public function executeEditStaff() {
264
+ $this->form = new AB_StaffMemberEditForm();
265
+ $this->staff = new AB_Staff();
266
+ $this->staff->load( 1 );
267
+ $staff_errors = array();
268
+
269
+ if ( isset( $_SESSION['was_update'] ) ) {
270
+ unset($_SESSION['was_update']);
271
+ $this->update = true;
272
+ }
273
+
274
+ $this->render('edit', array(
275
+ 'staff_errors' => $staff_errors
276
+ ));
277
+ exit;
278
+ }
279
+
280
+ public function updateStaff() {
281
+ $form = new AB_StaffMemberEditForm();
282
+ $form->bind( $this->getPostParameters(), $_FILES );
283
+ $result = $form->save();
284
+
285
+ $this->active_staff_id = 1;
286
+
287
+ if ($result === false){
288
+
289
+ }else{
290
+ $_SESSION['was_update'] = true;
291
+ }
292
+ }
293
+
294
+ public function executeDeleteStaffAvatar() {
295
+ $staff = new AB_Staff();
296
+ $staff->load( 1 );
297
+ unlink( $staff->get( 'avatar_path' ) );
298
+ $staff->set( 'avatar_url', '' );
299
+ $staff->set( 'avatar_path', '' );
300
+ $staff->save();
301
+ exit;
302
+ }
303
+
304
+ public function executeStaffHolidays() {
305
+ $this->id = $this->getParameter( 'id', 0 );
306
+ $this->holidays = $this->getHolidays( $this->id );
307
+ $this->render('holidays');
308
+ exit;
309
+ }
310
+
311
+ public function executeStaffHolidaysUpdate() {
312
+ $id = $this->getParameter( 'id' );
313
+ $holiday = $this->getParameter( 'holiday' ) == 'true';
314
+ $repeat = $this->getParameter( 'repeat' ) == 'true';
315
+ $day = $this->getParameter( 'day', false );
316
+ $staff_id = $this->getParameter( 'staff_id' );
317
+
318
+ if ( $staff_id ) {
319
+ // update or delete the event
320
+ if ( $id ) {
321
+ if ( $holiday ) {
322
+ $this->getWpdb()->update( 'ab_holiday', array( 'repeat_event' => intval( $repeat ) ), array( 'id' => $id ), array( '%d' ) );
323
+ } else {
324
+ $this->getWpdb()->delete( 'ab_holiday', array( 'id' => $id ), array( '%d' ) );
325
+ }
326
+ // add the new event
327
+ } else if ( $holiday && $day ) {
328
+ $day = new DateTime($day);
329
+ $this->getWpdb()->insert( 'ab_holiday', array( 'holiday' => date( 'Y-m-d H:i:s', $day->format( 'U' ) ), 'repeat_event' => intval( $repeat ), 'staff_id' => $staff_id ), array( '%s', '%d', '%d' ) );
330
+ }
331
+
332
+ // and return refreshed events
333
+ echo $this->getHolidays($staff_id);
334
+ }
335
+ exit;
336
+ }
337
+
338
+
339
+
340
+ // Protected methods.
341
+
342
+ /**
343
+ * Override parent method to add 'wp_ajax_ab_' prefix
344
+ * so current 'execute*' methods look nicer.
345
+ */
346
+ protected function registerWpActions( $prefix = '' ) {
347
+ parent::registerWpActions( 'wp_ajax_ab_' );
348
+ }
349
+
350
+ protected function getHolidays($id) {
351
+ $collection = $this->getWpdb()->get_results( $this->getWpdb()->prepare( "SELECT * FROM ab_holiday WHERE staff_id = %d", $id ) );
352
+ $holidays = array();
353
+ if ( count( $collection ) ) {
354
+ foreach ( $collection as $holiday ) {
355
+ $holidays[$holiday->id] = array(
356
+ 'm' => intval(date('m', strtotime($holiday->holiday))),
357
+ 'd' => intval(date('d', strtotime($holiday->holiday))),
358
+ 'title' => $holiday->title,
359
+ );
360
+ // if not repeated holiday, add the year
361
+ if ( ! $holiday->repeat_event ) {
362
+ $holidays[$holiday->id]['y'] = intval(date('Y', strtotime($holiday->holiday)));
363
+ }
364
+ }
365
+ }
366
+
367
+ return json_encode( (object) $holidays );
368
+ }
369
+ }
backend/modules/staff/forms/AB_StaffMemberEditForm.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
3
+ if ( !function_exists( 'wp_handle_upload' ) ) require_once(ABSPATH . 'wp-admin/includes/file.php');
4
+ include AB_PATH . '/lib/AB_ImageResize.php';
5
+
6
+ class AB_StaffMemberEditForm extends AB_StaffMemberForm {
7
+
8
+ private $errors = array();
9
+
10
+ public function configure() {
11
+ $this->setFields( array(
12
+ 'wp_user_id',
13
+ 'full_name',
14
+ 'email',
15
+ 'phone',
16
+ 'avatar',
17
+ 'google_calendar_id',
18
+ ) );
19
+ }
20
+
21
+ /**
22
+ * @param array $post
23
+ * @param array $files
24
+ */
25
+ public function bind( array $post, array $files = array() ) {
26
+ if ( isset( $post[ 'wp_user_id' ] ) && ! $post[ 'wp_user_id' ] ) {
27
+ $post[ 'wp_user_id' ] = null;
28
+ }
29
+
30
+ parent::bind( $post );
31
+
32
+ if ( isset ( $files[ 'avatar' ] ) && $files[ 'avatar' ][ 'tmp_name' ] ) {
33
+
34
+ if ( in_array( $files[ 'avatar' ][ 'type' ], array( "image/gif", "image/jpeg", "image/png" ) ) ) {
35
+ $movefile = wp_handle_upload( $files[ 'avatar' ], array( 'test_form' => false ) );
36
+ if ( $movefile ) {
37
+ $imageResize = new AB_ImageResize( $movefile[ 'file' ] );
38
+ $imageResize->resizeImage( 80, 80 );
39
+ $imageResize->saveImage( $movefile[ 'file' ], 80 );
40
+
41
+ $this->data[ 'avatar_path' ] = $movefile[ 'file' ];
42
+ $this->data[ 'avatar_url' ] = $movefile[ 'url' ];
43
+ }
44
+ }
45
+ }
46
+ }
47
+
48
+ /**
49
+ * @return array
50
+ */
51
+ public function getErrors()
52
+ {
53
+ return $this->errors;
54
+ }
55
+ }
backend/modules/staff/forms/AB_StaffMemberForm.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ include AB_PATH . '/lib/entities/AB_Staff.php';
6
+
7
+ /**
8
+ * Class AB_StaffMemberForm
9
+ *
10
+ * @property AB_Staff $staff
11
+ */
12
+ class AB_StaffMemberForm extends AB_Form {
13
+
14
+ /**
15
+ * Constructor.
16
+ */
17
+ public function __construct() {
18
+ parent::$entity_class = 'AB_Staff';
19
+ parent::__construct();
20
+ }
21
+
22
+ protected $wp_users;
23
+
24
+
25
+ // Help methods for rendering widgets.
26
+
27
+ /**
28
+ * Get list of users available for particular staff.
29
+ *
30
+ * @global string $table_prefix
31
+ * @param integer $staff_id If null then it means new staff
32
+ * @return array
33
+ */
34
+ public function getUsersForStaff($staff_id = null) {
35
+ /** @var wpdb $wpdb */
36
+ global $wpdb;
37
+ global $table_prefix;
38
+
39
+ $query = sprintf(
40
+ 'SELECT ID, user_email, display_name FROM %susers
41
+ WHERE ID NOT IN(SELECT DISTINCT IFNULL( wp_user_id, 0 ) FROM ab_staff %s)
42
+ ORDER BY display_name',
43
+ $table_prefix,
44
+ $staff_id !== null
45
+ ? "WHERE ab_staff.id <> $staff_id"
46
+ : ''
47
+ );
48
+
49
+ return $wpdb->get_results( $query );
50
+ }
51
+ }
backend/modules/staff/forms/AB_StaffMemberNewForm.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
3
+ include 'AB_StaffMemberForm.php';
4
+
5
+ /**
6
+ * Class AB_StaffMemberNewForm
7
+ */
8
+ class AB_StaffMemberNewForm extends AB_StaffMemberForm {
9
+
10
+ public function configure() {
11
+ $this->setFields( array( 'wp_user_id', 'full_name' ) );
12
+ }
13
+ }
backend/modules/staff/forms/AB_StaffScheduleForm.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ /**
6
+ * Class AB_StaffScheduleForm
7
+ */
8
+ class AB_StaffScheduleForm extends AB_Form {
9
+
10
+ /**
11
+ * Constructor.
12
+ */
13
+ public function __construct() {
14
+ parent::$entity_class = 'AB_StaffScheduleItem';
15
+ parent::__construct();
16
+ }
17
+
18
+ /**
19
+ * @var wpdb $wpdb
20
+ */
21
+ private $wpdb;
22
+
23
+ public function configure() {
24
+ global $wpdb;
25
+ $this->wpdb = $wpdb;
26
+ $this->setFields( array( 'days', 'staff_id', 'start_time', 'end_time' ) );
27
+ }
28
+
29
+ public function save() {
30
+ if ( isset($this->data['days']) ) {
31
+ foreach ( $this->data['days'] as $id => $day_index ) {
32
+ $staffScheduleItem = new AB_StaffScheduleItem();
33
+ $staffScheduleItem->load( $id );
34
+ $staffScheduleItem->set( 'day_index', $day_index );
35
+ if ($this->data['start_time'][$day_index]) {
36
+ $staffScheduleItem->set( 'start_time', $this->data['start_time'][$day_index] );
37
+ $staffScheduleItem->set( 'end_time', $this->data['end_time'][$day_index] );
38
+ } else {
39
+ $staffScheduleItem->set( 'start_time', null );
40
+ $staffScheduleItem->set( 'end_time', null );
41
+ }
42
+ $staffScheduleItem->save();
43
+ }
44
+ }
45
+ }
46
+ }
backend/modules/staff/forms/AB_StaffScheduleItemBreakForm.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ include AB_PATH . '/lib/entities/AB_ScheduleItemBreak.php';
6
+
7
+ /**
8
+ * Class AB_StaffScheduleItemBreakForm
9
+ */
10
+ class AB_StaffScheduleItemBreakForm extends AB_Form {
11
+
12
+ /**
13
+ * Constructor.
14
+ */
15
+ public function __construct() {
16
+ parent::$entity_class = 'AB_ScheduleItemBreak';
17
+ parent::__construct();
18
+ }
19
+
20
+ public function configure() {
21
+ $this->setFields( array(
22
+ 'staff_schedule_item_id',
23
+ 'start_time',
24
+ 'end_time'
25
+ ) );
26
+ }
27
+ }
backend/modules/staff/forms/AB_StaffServicesForm.php ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ include AB_PATH . '/lib/entities/AB_Category.php';
6
+ include AB_PATH . '/lib/entities/AB_StaffService.php';
7
+
8
+ /**
9
+ * Class AB_StaffServicesForm
10
+ */
11
+ class AB_StaffServicesForm extends AB_Form {
12
+
13
+ /**
14
+ * Constructor.
15
+ */
16
+ public function __construct() {
17
+ parent::$entity_class = 'AB_StaffService';
18
+ parent::__construct();
19
+ }
20
+
21
+ /**
22
+ * @var wpdb $wpdb
23
+ */
24
+ private $wpdb;
25
+
26
+ /**
27
+ * @var AB_Category[]
28
+ */
29
+ private $collection = array();
30
+
31
+ /**
32
+ * @var array
33
+ */
34
+ private $selected = array();
35
+
36
+ /**
37
+ * @var array
38
+ */
39
+ private $category_services = array();
40
+
41
+ /**
42
+ * @var array
43
+ */
44
+ private $uncategorized_services = array();
45
+
46
+ public function configure() {
47
+ global $wpdb;
48
+ $this->wpdb = $wpdb;
49
+ $this->setFields( array( 'price', 'service', 'staff_id', 'capacity' ) );
50
+ }
51
+
52
+ public function load($staff_id) {
53
+ $data = $this->wpdb->get_results( '
54
+ SELECT c.name AS category_name, s.*
55
+ FROM ab_category c
56
+ INNER JOIN ab_service s ON c.id = s.category_id
57
+ ', ARRAY_A );
58
+
59
+ if ( !$data ) {
60
+ $data = array();
61
+ }
62
+
63
+ $uncategorized_services = $this->wpdb->get_results( 'SELECT * FROM ab_service WHERE category_id IS NULL' );
64
+ foreach ( $uncategorized_services as $uncategorized_service ) {
65
+ $abService = new AB_Service();
66
+ $abService->setData($uncategorized_service);
67
+
68
+ $this->uncategorized_services[] = $abService;
69
+ }
70
+
71
+ $rows = $this->wpdb->get_results( $this->wpdb->prepare('
72
+ SELECT s.service_id, s.price, s.capacity
73
+ FROM ab_staff_service s
74
+ WHERE s.staff_id = %d
75
+ ', $staff_id) );
76
+
77
+ if ( $rows ) {
78
+ foreach ($rows as $row) {
79
+ $this->selected[$row->service_id] = array('price' => $row->price, 'capacity' => $row->capacity);
80
+ }
81
+ }
82
+
83
+ foreach ($data as $row) {
84
+ if ( !isset($this->collection[ $row['category_id'] ]) ) {
85
+ $abCategory = new AB_Category();
86
+ $abCategory->set( 'id', $row['category_id'] );
87
+ $abCategory->set( 'name', $row['category_name'] );
88
+ $this->collection[ $row['category_id'] ] = $abCategory;
89
+ }
90
+ unset( $row['category_name'] );
91
+
92
+ $abService = new AB_Service();
93
+ $abService->setData($row);
94
+ $this->category_services[$row['category_id']][] = $abService->get( 'id' );
95
+ $this->collection[ $row['category_id'] ]->addService($abService);
96
+ }
97
+ }
98
+
99
+ public function save() {
100
+ $staff_id = $this->data['staff_id'];
101
+ if ( $staff_id ) {
102
+ $this->wpdb->delete( 'ab_staff_service', array( 'staff_id' => $staff_id ), array( '%d' ) );
103
+ if ( isset($this->data['service']) ) {
104
+ foreach ( $this->data['service'] as $service_id ) {
105
+ $staffService = new AB_StaffService();
106
+ $staffService->set( 'service_id', $service_id );
107
+ $staffService->set( 'staff_id', $staff_id );
108
+ $staffService->set( 'price', $this->data['price'][ $service_id ] );
109
+ $staffService->save();
110
+ }
111
+ }
112
+ }
113
+ }
114
+
115
+ /**
116
+ * @return AB_Category[]|array
117
+ */
118
+ public function getCollection() {
119
+ return $this->collection;
120
+ }
121
+
122
+ /**
123
+ * @return array
124
+ */
125
+ public function getSelected() {
126
+ return $this->selected;
127
+ }
128
+
129
+ /**
130
+ * @return array
131
+ */
132
+ public function getUncategorizedServices()
133
+ {
134
+ return $this->uncategorized_services;
135
+ }
136
+ }
backend/modules/staff/forms/widget/AB_TimeChoiceWidget.php ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( !defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ class AB_TimeChoiceWidget {
6
+ /**
7
+ * @var array
8
+ */
9
+ protected $values = array();
10
+
11
+ /**
12
+ * Constructor.
13
+ *
14
+ * @param array $options
15
+ */
16
+ public function __construct( array $options = array() ) {
17
+ // Handle widget options.
18
+ $options = array_merge( array(
19
+ 'use_empty' => true,
20
+ 'empty_value' => null
21
+ ), $options );
22
+
23
+ // Insert empty value if required.
24
+ if ( $options[ 'use_empty' ] ) {
25
+ $this->values[ null ] = $options[ 'empty_value' ];
26
+ }
27
+
28
+ $tf = get_option( 'time_format' );
29
+ $ts_length = get_option( 'ab_settings_time_slot_length' );
30
+ $time_start = new AB_DateTime( AB_StaffScheduleItem::WORKING_START_TIME, new DateTimeZone( 'UTC' ) );
31
+ $time_end = new AB_DateTime( AB_StaffScheduleItem::WORKING_END_TIME, new DateTimeZone( 'UTC' ) );
32
+
33
+ // Run the loop.
34
+ while ( $time_start->format( 'U' ) <= $time_end->format( 'U' ) ) {
35
+ $this->values[ $time_start->format( 'H:i:s' ) ] = $time_start->format( $tf );
36
+ $time_start->modify( '+' . $ts_length . ' min' );
37
+ }
38
+ $this->values[ $time_end->format( 'H:i:s' ) ] = $time_end->format( $tf );
39
+ }
40
+
41
+ /**
42
+ * Render the widget.
43
+ *
44
+ * @param $name
45
+ * @param null $value
46
+ * @param array $attributes
47
+ *
48
+ * @return string
49
+ */
50
+ public function render( $name, $value = null, array $attributes = array() ) {
51
+ $options = array();
52
+ $attributes_str = '';
53
+ foreach ( $this->values as $option_value => $option_text ) {
54
+
55
+ $selected = strval( $value ) == strval( $option_value );
56
+ $options[ ] = sprintf(
57
+ '<option value="%s"%s>%s</option>',
58
+ $option_value,
59
+ ($selected ? ' selected="selected"' : ''),
60
+ $option_text
61
+ );
62
+ }
63
+ foreach ( $attributes as $attr_name => $attr_value ) {
64
+ $attributes_str .= sprintf( ' %s="%s"', $attr_name, $attr_value );
65
+ }
66
+
67
+ return sprintf( '<select name="%s"%s>%s</select>', $name, $attributes_str, implode( '', $options ) );
68
+ }
69
+
70
+ /**
71
+ * @param $start
72
+ * @param string $selected
73
+ * @return array
74
+ */
75
+ public function renderOptions( $start, $selected = '' ) {
76
+ $options = array();
77
+ foreach ( $this->values as $option_value => $option_text ) {
78
+ if ( $start && strval( $option_value ) < strval( $start ) ) continue;
79
+ $options[ ] = sprintf(
80
+ '<option value="%s"%s>%s</option>',
81
+ $option_value,
82
+ (strval( $selected ) == strval( $option_value ) ? 'selected="selected"' : ''),
83
+ $option_text
84
+ );
85
+ }
86
+
87
+ return $options;
88
+ }
89
+ }
backend/modules/staff/resources/css/staff.css ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ab-staff-schedule > table { width: 100% }
2
+ #ab-staff-schedule .staff-schedule-item-row > td { padding: 10px 0; border-bottom: 1px solid #DDDDDD; }
3
+ #ab-staff-schedule .staff-schedule-item-row.ab-last-row > td { border: 0; }
4
+ #ab-staff-schedule .staff-schedule-item-row > td.first { width: 115px }
5
+ #ab-staff-schedule .staff-schedule-item-row td.add-break { width: 80px }
6
+ #ab-staff-schedule .staff-schedule-item-row td.working-intervals { width: 210px }
7
+ #ab-staff-schedule .staff-schedule-item-row .break-interval-wrapper { margin-right: 7px; white-space: nowrap; float: left; }
8
+ #ab-staff-schedule .staff-schedule-item-row .break-interval-wrapper img {
9
+ border: 0 none;
10
+ cursor: pointer;
11
+ display: block;
12
+ float: left;
13
+ margin-left: 5px;
14
+ margin-top: 2px;
15
+ width: 12px;
16
+ }
17
+ #ab-staff-schedule .staff-schedule-item-row .breaks-list { width: 100% }
18
+ #ab-staff-schedule .staff-schedule-item-row .breaks-list .breaks-list-label { width: 60px }
19
+ #ab-staff-schedule .staff-schedule-item-row .ab-popup-wrapper .error { padding: 3px; margin: 5px; }
20
+ #ab-staff-schedule .staff-schedule-item-row .breaks-list .ab-popup-wrapper { float: left; margin-right: 3px; }
21
+ #ab-staff-schedule .error { margin: 0 }
22
+ #ab-staff-list { margin-left: 0; }
23
+ #ab-edit-staff .ab-nav-tabs { height: 37px; }
24
+ .ab-staff-form .control-label { text-align: left!important; }
25
+ .working-end, .working-start { margin-bottom: 0; font-size: 13px; }
26
+ .ab-content .break-end, .ab-content .break-start { width: auto; margin-bottom: 0; }
27
+ .add-break form { margin: 0; }
28
+
29
+ #ab-staff-services ul ul li { margin-left: 20px; }
30
+ #ab-staff-services ul ul li.ab-services-category { margin: 25px 0px 15px 20px; position: relative; }
31
+ #ab-staff-services ul .ab-title-service { position: absolute; right: 0px; top: 1px; }
32
+ #ab-staff-services ul .ab-title-service > div { display: inline-block; width: 60px; text-align: center; }
33
+ #ab-staff-services ul .ab-title-service > div:first-child { margin-right: 5px; }
34
+ #ab-staff-services ul ul li ul li { margin-left: 20px; overflow: hidden; }
35
+ #ab-staff-services ul ul li ul li .ab-price { width: 60px; margin: 0 0 0 5px; text-align: right; height: 30px!important; }
36
+ #ab-staff-services ul ul li ul li .ab-list-title { margin: 5px 5px 0 0; }
37
+ #ab-staff-services { max-width: 590px; }
38
+ #ab-staff-services #ab-staff-services-update { margin-left: 115px; }
39
+ #ab-staff-services .spinner { float: left }
backend/modules/staff/resources/js/staff.js ADDED
@@ -0,0 +1,447 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(function($) {
2
+
3
+ var $name_input = $('#ab-newstaff-fullname'),
4
+ $wp_user_select = $('#ab-newstaff-wpuser'),
5
+ $staff_member = $('.ab-staff-member'),
6
+ $edit_form = $('#ab-edit-staff-member'),
7
+ $new_form = $('#ab-new-satff');
8
+
9
+ // Saves new staff form
10
+ $('#ab-save-newstaff').bind('click', function () {
11
+ $('#lite_notice').modal('show');
12
+ });
13
+
14
+ // Save new staff on enter press
15
+ $name_input.bind('keypress', function (e) {
16
+ var code = (e.keyCode ? e.keyCode : e.which);
17
+ if (code == 13) {
18
+ $('#lite_notice').modal('show');
19
+ }
20
+ });
21
+
22
+ // Close new staff form on esc
23
+ $new_form.bind('keypress', function (e) {
24
+ var code = (e.keyCode ? e.keyCode : e.which);
25
+ if (code == 27) {
26
+ $('.ab-popup-wrapper').ab_popup('close');
27
+ }
28
+ });
29
+
30
+ function loadEditForm() {
31
+ // Marks selected element as active
32
+ $(this).parent().find('.ab-active').removeClass('ab-active');
33
+ $(this).addClass('ab-active');
34
+
35
+ var staff_id = $(this).data('staff-id');
36
+ var active_tab_id = $('ul.nav li.active a').attr('id');
37
+ $.get(ajaxurl, { action: 'ab_edit_staff', id: staff_id }, function (response) {
38
+ $edit_form.html(response);
39
+
40
+ // Deletes staff avatar
41
+ $('#ab-delete-avatar').bind('click', function () {
42
+ $.post(ajaxurl, { action: 'ab_delete_staff_avatar', id: staff_id }, function () {
43
+ $('#ab-staff-avatar-image', $edit_form).remove();
44
+ });
45
+ });
46
+
47
+ $('#ab-update-staff').bind('click', function (e) {
48
+ if (!validateForm($edit_form)) {
49
+ e.preventDefault(e);
50
+ e.stopPropagation(e);
51
+ }
52
+ });
53
+
54
+ $('#ab-staff-wpuser').bind('change', function () {
55
+ if ($(this).val()) {
56
+ $('#ab-staff-full-name').val($(this).find(':selected').text());
57
+ $('#ab-staff-email').val($(this).find(':selected').data('email'));
58
+ }
59
+ });
60
+
61
+ helpInit();
62
+
63
+ var service_container = $('#ab-staff-services-container'),
64
+ details_container = $('#ab-staff-details-container'),
65
+ schedule_container = $('#ab-staff-schedule-container'),
66
+ holidays_container = $('#ab-staff-holidays-container'),
67
+ $schedule_form,
68
+ services_form,
69
+ tabs = $('.ab-list-link', $edit_form);
70
+
71
+ // Opens services tab
72
+ $('#ab-staff-services-tab').bind('click', function () {
73
+ activateTab.call($(this));
74
+ service_container.show();
75
+
76
+ // Loads services form
77
+ if (!service_container.children().length) {
78
+ $.post(ajaxurl, { action: 'ab_staff_services', id: staff_id }, function (response) {
79
+ service_container.html(response);
80
+ services_form = $('form', service_container);
81
+
82
+ var auto_tick_checkboxes = function() {
83
+ // Handle 'select category' checkbox.
84
+ $('.ab-services-category .ab-category-checkbox').each(function() {
85
+ $(this).prop(
86
+ 'checked',
87
+ $('.ab-category-services .ab-service-checkbox.ab-category-' + $(this).data('category-id') + ':not(:checked)').length == 0
88
+ );
89
+ });
90
+ // Handle 'select all services' checkbox.
91
+ $('#ab-all-services').prop(
92
+ 'checked',
93
+ $('.ab-service-checkbox:not(:checked)').length == 0
94
+ );
95
+ };
96
+
97
+ // Select all services related to choosen category
98
+ $('.ab-category-checkbox', services_form).bind('click', function () {
99
+ $('.ab-category-services .ab-category-' + $(this).data('category-id')).attr('checked', $(this).is(':checked')).change();
100
+ auto_tick_checkboxes();
101
+ });
102
+
103
+ // Select all services
104
+ $('#ab-all-services').bind('click', function () {
105
+ $('.ab-service-checkbox', services_form).attr('checked', $(this).is(':checked')).change();
106
+ $('.ab-category-checkbox').attr('checked', $(this).is(':checked'));
107
+ });
108
+
109
+ // Select service
110
+ $('.ab-service-checkbox', services_form).bind('click', function () {
111
+ var $this = $(this);
112
+ var $price = $this.closest('li').find('.ab-price');
113
+ $this.is(':checked') ? $price.removeAttr('disabled') : $price.attr('disabled', true);
114
+ auto_tick_checkboxes();
115
+ });
116
+
117
+ $('.ab-service-checkbox',services_form).bind('change', function(){
118
+ var $input_fields = $('.ab-price[name="price['+$(this).val()+']"]').add('.ab-price[name="capacity['+$(this).val()+']"]');
119
+ $(this).is(':checked') ? $input_fields.removeAttr('disabled') : $input_fields.attr('disabled', true);
120
+ });
121
+
122
+ // Saves services
123
+ $('#ab-staff-services-update').bind('click', function () {
124
+ $('.spinner', services_form).fadeIn('slow');
125
+ $.post(ajaxurl, services_form.serialize(), function (response) {
126
+ $('.spinner', services_form).fadeOut('slow');
127
+ });
128
+ });
129
+
130
+ auto_tick_checkboxes();
131
+
132
+ // On click on 'Add Coupon' button.
133
+ $('[name^=capacity]').on('change', function(e) {
134
+ $('#lite_notice').modal('show');
135
+ $(this).val(1);
136
+ });
137
+ });
138
+ }
139
+ });
140
+
141
+ // Opens schedule tab
142
+ $('#ab-staff-schedule-tab').bind('click', function () {
143
+ activateTab.call($(this));
144
+ schedule_container.show();
145
+
146
+ // Loads schedule list
147
+ if (!schedule_container.children().length) {
148
+ $.post(ajaxurl, { action: 'ab_staff_schedule', id: staff_id }, function (response) {
149
+ // fill in the container
150
+ schedule_container.html(response);
151
+ $schedule_form = $('form', schedule_container);
152
+
153
+ // Saves initial values
154
+ $('.working-start', schedule_container).each(function () {
155
+ $(this).data('default_value', $(this).val());
156
+ });
157
+
158
+ $('.working-end', schedule_container).each(function () {
159
+ $(this).data('default_value', $(this).val());
160
+ });
161
+
162
+ // Resets initial values
163
+ $('#ab-schedule-reset').bind('click', function () {
164
+ $('.working-start', schedule_container).each(function () {
165
+ $(this).val($(this).data('default_value'));
166
+ $(this).trigger('click');
167
+ });
168
+
169
+ $('.working-end', schedule_container).each(function () {
170
+ $(this).val($(this).data('default_value'));
171
+ });
172
+
173
+ // reset breaks
174
+ $.ajax({
175
+ url : ajaxurl,
176
+ type : 'POST',
177
+ data : { action : 'ab_reset_breaks', breaks : $.parseJSON($(this).attr('default-breaks'))},
178
+ success : function(response) {
179
+ var days = $.parseJSON(response);
180
+ for (var k in days) {
181
+ var $content = $(days[k]);
182
+ $("[data-id=" + k +"] .breaks", schedule_container).html($content);
183
+
184
+ $content.find('.break-interval').bind('click', function(){
185
+ markBreakIntervalActive.call($(this));
186
+ });
187
+
188
+ $content.find('.break-interval-wrapper .delete-break').bind('click', function(){
189
+ deleteStaffScheduleBreakInterval.call($(this));
190
+ });
191
+ schedule_container.find('.ab-popup-wrapper').ab_popup();
192
+ }
193
+ }
194
+ });
195
+ });
196
+
197
+ $('#ab-staff-schedule-update', schedule_container).bind('click', function () {
198
+ $('.spinner', $schedule_form).fadeIn('slow');
199
+ var data = {};
200
+ $('select.working-start, select.working-end, input:hidden', $schedule_form).each(function() {
201
+ data[this.name] = this.value;
202
+ });
203
+ $.post(ajaxurl, $.param(data), function (response) {
204
+ $('.spinner', $schedule_form).fadeOut('slow');
205
+ schedule_container.html('');
206
+ $('#ab-staff-schedule-tab').trigger('click');
207
+ });
208
+ });
209
+
210
+ // init "add break" functionality
211
+ schedule_container.find('.ab-popup-wrapper').ab_popup();
212
+ schedule_container.find('.ab-popup-trigger:not(.break-interval)').bind('click', function() {
213
+ var $row = $(this).parents('.staff-schedule-item-row').first(),
214
+ $working_start = $row.find('.working-start').val(),
215
+ $working_end = $row.find('.working-end').val();
216
+
217
+ // if the day is the working one - handle "add break" selected values
218
+ if ($working_start.length && $working_end.length) {
219
+ var $working_start_time = $working_start.split(':'),
220
+ $working_start_hours = parseInt($working_start_time[0], 10),
221
+ $break_end = $row.find('.add-break .break-end'),
222
+ $break_end_hours = $working_start_hours + 2;
223
+
224
+ if ($break_end_hours < 10) {
225
+ $break_end_hours = '0' + $break_end_hours;
226
+ }
227
+ var $break_end_hours_str = $break_end_hours + ':' + $working_start_time[1] + ':' + $working_start_time[2],
228
+ $break_end_option = $break_end.find('option[value="' + $break_end_hours_str + '"]'),
229
+ $break_start = $row.find('.add-break .break-start');
230
+
231
+ if ($break_end_option.length) {
232
+ var $break_start_hours = $working_start_hours + 1;
233
+ if ($break_start_hours < 10) {
234
+ $break_start_hours = '0' + $break_start_hours;
235
+ }
236
+ var $break_start_hours_str = $break_start_hours + ':' + $working_start_time[1] + ':' + $working_start_time[2];
237
+
238
+ $break_start.val($break_start_hours_str);
239
+ $break_end.val($break_end_hours_str);
240
+ } else {
241
+ // set defaults
242
+ $break_start.val($break_start.data('default_value'));
243
+ $break_end.val($break_end.data('default_value'));
244
+ }
245
+ $break_start.trigger('change');
246
+ }
247
+ });
248
+
249
+ // when the working day is disabled (working start time is set to "OFF")
250
+ // hide all the elements inside the row
251
+ schedule_container.find('.working-start').bind('click', function(){
252
+ var $this = $(this),
253
+ $row = $this.parents('.staff-schedule-item-row');
254
+
255
+ if (!$this.val()) {
256
+ $row.find('.hide-on-non-working-day').hide();
257
+ } else {
258
+ $row.find('.hide-on-non-working-day:hidden').show();
259
+ }
260
+ });
261
+
262
+ $('.working-start', schedule_container).on('change', function () {
263
+ var $row = $(this).parents('.staff-schedule-item-row').first(),
264
+ $end_select = $('.working-end', $row),
265
+ start_time = $(this).val();
266
+
267
+ $('span > option', $end_select).each(function () {
268
+ if ( start_time < $(this).val()) {
269
+ $(this).unwrap();
270
+ }
271
+ });
272
+
273
+ // Hides end time options with value less than in the start time
274
+ $('option', $end_select).each(function () {
275
+ if ($(this).val() <= start_time) {
276
+ $(this).wrap("<span>").parent().hide();
277
+ }
278
+ });
279
+ }).trigger('change');
280
+
281
+ schedule_container.find('.ab-popup-wrapper .break-interval').bind('click', function(){
282
+ markBreakIntervalActive.call($(this));
283
+ });
284
+
285
+ schedule_container.find('.break-interval-wrapper .delete-break').bind('click', function(){
286
+ deleteStaffScheduleBreakInterval.call($(this));
287
+ });
288
+
289
+ schedule_container.find('.break-start').bind('change', function(){
290
+ var start = $(this);
291
+ var end = start.parent().find('.break-end');
292
+ checkStaffScheduleBreakTimeRange(start,end);
293
+ }).trigger('change');
294
+
295
+ schedule_container.delegate('.ab-save-break', 'click', function() {
296
+ var $table = $(this).closest('table'),
297
+ $row = $table.parents('.staff-schedule-item-row').first(),
298
+ $break_list_label = $row.find('.breaks-list-label span'),
299
+ $break_interval_wrapper = $table.parents('.break-interval-wrapper').first(),
300
+ $error = $table.parents('.ab-popup-wrapper').find('.error'),
301
+ $data = {
302
+ action : 'ab_staff_schedule_handle_break',
303
+ working_start : $row.find('.working-start > option:selected').val(),
304
+ working_end : $row.find('.working-end > option:selected').val(),
305
+ start_time : $table.find('.break-start > option:selected').val(),
306
+ end_time : $table.find('.break-end > option:selected').val(),
307
+ staff_schedule_item_id : $row.data('staff_schedule_item_id')
308
+ };
309
+
310
+ if ($break_interval_wrapper.data('break_id')) {
311
+ $data['break_id'] = $break_interval_wrapper.data('break_id');
312
+ }
313
+
314
+ $.post(
315
+ ajaxurl,
316
+ $data,
317
+ function (response) {
318
+ if (response['success']) {
319
+ if (response['item_content']) {
320
+ var $new_break_interval_item = $(response['item_content']);
321
+ $new_break_interval_item
322
+ .hide()
323
+ .appendTo($row.find('.breaks-list-content'))
324
+ .fadeIn('slow');
325
+ $new_break_interval_item.find('.break-interval').bind('click', function(){
326
+ markBreakIntervalActive.call($(this));
327
+ });
328
+ $new_break_interval_item.find('.delete-break').bind('click', function(){
329
+ deleteStaffScheduleBreakInterval.call($(this));
330
+ });
331
+ if ($break_list_label.is(':hidden')) {
332
+ $break_list_label.fadeIn('slow');
333
+ }
334
+ schedule_container.find('.ab-popup-wrapper').ab_popup();
335
+ } else if (response['new_interval']) {
336
+ $break_interval_wrapper
337
+ .find('.break-interval.active')
338
+ .text(response['new_interval'])
339
+ .removeClass('active');
340
+ }
341
+ $row.find('.ab-popup-wrapper').ab_popup('close');
342
+ } else {
343
+ $error.text(response['error_msg']);
344
+ $error.slideDown();
345
+ var t = setTimeout(function() {
346
+ $error.hide();
347
+ clearTimeout(t);
348
+ }, 3000);
349
+ }
350
+ },
351
+ 'json'
352
+ );
353
+
354
+ return false;
355
+ });
356
+ });
357
+ }
358
+ });
359
+
360
+ // Opens details tab
361
+ $('#ab-staff-details-tab').bind('click', function () {
362
+ activateTab.call($(this));
363
+ details_container.show();
364
+ });
365
+
366
+ // Opens "Days off" tab
367
+ $('#ab-staff-holidays-tab').bind('click', function () {
368
+ activateTab.call($(this));
369
+ holidays_container.show();
370
+
371
+ if (!holidays_container.children().length) {
372
+ holidays_container.load(ajaxurl, { action: 'ab_staff_holidays', id: staff_id });
373
+ }
374
+ });
375
+
376
+ function markBreakIntervalActive() {
377
+ $(this).parents('.breaks-list-content').find('.break-interval').removeClass('.active');
378
+ $(this).addClass('active');
379
+ }
380
+
381
+ function checkStaffScheduleBreakTimeRange( start, end )
382
+ {
383
+ var start_time = start.val();
384
+
385
+ $('span > option', end).each(function () {
386
+ if (start_time < $(this).val()) {
387
+ $(this).unwrap();
388
+ }
389
+ });
390
+
391
+ // Hides end time options with value less than in the start time
392
+ $('option', end).each(function () {
393
+ if ($(this).val() <= start_time) {
394
+ $(this).wrap("<span>").parent().hide();
395
+ }
396
+ });
397
+ }
398
+
399
+ function deleteStaffScheduleBreakInterval() {
400
+ var $break_interval_wrapper = $(this).parent(),
401
+ $row = $break_interval_wrapper.parents('.staff-schedule-item-row').first();
402
+ if (confirm('Are you sure?')) {
403
+ $.post(ajaxurl, { action: 'ab_delete_staff_schedule_break', id: $break_interval_wrapper.data('break_id') }, function (response) {
404
+ $break_interval_wrapper.fadeOut(700, function() {
405
+ $(this).remove();
406
+ if (!$row.find('.break-interval-wrapper').length) {
407
+ $row.find('.breaks-list-label span').hide();
408
+ }
409
+ });
410
+ });
411
+ }
412
+ }
413
+
414
+ function activateTab() {
415
+ // $('.ab-active', tabs).removeClass('ab-active');
416
+ // $(this).addClass('ab-active');
417
+ $('.ab-staff-tab-content').not(':hidden').hide();
418
+ }
419
+
420
+ $('#' + active_tab_id).click();
421
+ });
422
+ }
423
+
424
+ function helpInit() {
425
+ // Popovers initialization.
426
+ $('.ab-popover-ext').popover({
427
+ trigger : 'hover',
428
+ content: function() {
429
+ return $('#' + $(this).data('ext_id')).html()
430
+ },
431
+ html: true
432
+ });
433
+ }
434
+
435
+ $wp_user_select.bind('change', function () {
436
+ if ($(this).val()) {
437
+ $name_input.val($(this).find(':selected').text());
438
+ }
439
+ });
440
+
441
+ $staff_member.click(function () {
442
+ loadEditForm.call(this);
443
+ });
444
+ $staff_member.filter('[data-active="true"]').click();
445
+
446
+ helpInit();
447
+ });
backend/modules/staff/templates/_breaks.php ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <?php
3
+ $staffScheduleItem = new AB_StaffScheduleItem();
4
+ $staffScheduleItem->load($list_item->staff_schedule_item_id);
5
+
6
+ $breaks_list = $staffScheduleItem->getBreaksList();
7
+ $display = count( $breaks_list ) ? 'inline-block' : 'none;';
8
+ ?>
9
+ <table class="breaks-list hide-on-non-working-day" cellspacing="0" cellpadding="0"<?php if ( $day_is_not_available ) : ?> style="display: none"<?php endif; ?>>
10
+ <tr>
11
+ <td class="breaks-list-label">
12
+ <span style="display: <?php echo $display ?>">
13
+ <?php _e('breaks:','ab') ?>
14
+ </span>
15
+ </td>
16
+ <td class="breaks-list-content">
17
+ <?php foreach ( $breaks_list as $break_interval ) : ?>
18
+ <?php
19
+ $formatted_interval_start = date( $time_format, strtotime( $break_interval->start_time ) );
20
+ $formatted_interval_end = date( $time_format, strtotime( $break_interval->end_time ) );
21
+ $formatted_interval = $formatted_interval_start . ' - ' . $formatted_interval_end;
22
+ if (isset($default_breaks)) {
23
+ $default_breaks['breaks'][] = array(
24
+ 'start' => $break_interval->start_time,
25
+ 'end' => $break_interval->end_time,
26
+ 'schedule_item_id' => $break_interval->staff_schedule_item_id
27
+ );
28
+ }
29
+ ?>
30
+ <div class="break-interval-wrapper" data-break_id="<?php echo $break_interval->id ?>">
31
+ <div class="ab-popup-wrapper">
32
+ <a class="ab-popup-trigger break-interval" href="javascript:void(0)"><?php echo $formatted_interval ?></a>
33
+ <div class="ab-popup" style="display: none">
34
+ <div class="ab-arrow"></div>
35
+ <div class="error" style="display: none"></div>
36
+ <div class="ab-content">
37
+ <table cellspacing="0" cellpadding="0">
38
+ <tr>
39
+ <td>
40
+ <?php
41
+ $breakStart = new AB_TimeChoiceWidget( array( 'use_empty' => false ) );
42
+ $break_start_choices = $breakStart->render(
43
+ '',
44
+ $break_interval->start_time,
45
+ array(
46
+ 'class' => 'break-start',
47
+ 'data-default_value' => $start_time_default_value
48
+ )
49
+ );
50
+ $breakEnd = new AB_TimeChoiceWidget( array( 'use_empty' => false ) );
51
+ $break_end_choices = $breakEnd->render(
52
+ '',
53
+ $break_interval->end_time,
54
+ array(
55
+ 'class' => 'break-end',
56
+ 'data-default_value' => $end_time_default_value
57
+ )
58
+ );
59
+ echo $break_start_choices . ' <span>' . __( 'to','ab' ) . '</span> ' . $break_end_choices;
60
+ ?>
61
+ </td>
62
+ </tr>
63
+ <tr>
64
+ <td>
65
+ <a class="btn btn-info ab-popup-save ab-save-break ab-update-button"><?php _e('Save break','ab') ?></a>
66
+ <a class="ab-popup-close" href="#"><?php _e('Cancel','ab') ?></a>
67
+ </td>
68
+ </tr>
69
+ </table>
70
+ <a class="ab-popup-close ab-popup-close-icon" href="javascript:void(0)"></a>
71
+ </div>
72
+ </div>
73
+ </div>
74
+ <img class="delete-break" src="<?php echo plugins_url( 'backend/resources/images/delete_cross.png', AB_PATH . '/main.php' ) ?>" />
75
+ </div>
76
+ <?php endforeach; ?>
77
+ </td>
78
+ </tr>
79
+ </table>
backend/modules/staff/templates/edit.php ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @var AB_Staff $staff
4
+ * @var string $authUrl
5
+ * @var array $staff_errors
6
+ */
7
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
8
+ ?>
9
+ <div id="ab-edit-staff">
10
+ <?php if( isset($update) ): ?>
11
+ <div class="alert">
12
+ <button type="button" class="close" data-dismiss="alert">&times;</button>
13
+ <?php _e( 'Settings saved.', 'ab' )?>
14
+ </div>
15
+ <?php endif ?>
16
+ <?php if ($staff_errors): ?>
17
+ <div class="error">
18
+ <button type="button" class="close" data-dismiss="alert">&times;</button>
19
+ <?php
20
+ foreach ($staff_errors as $staff_error){
21
+ echo $staff_error . "<br>";
22
+ }
23
+ ?>
24
+ </div>
25
+ <?php endif ?>
26
+ <div style="overflow: hidden; position: relative">
27
+ <h2 class="left"><?php echo $staff->get( 'full_name' ) ?></h2>
28
+ </div>
29
+ <div class="tabbable">
30
+ <ul class="nav nav-tabs ab-nav-tabs">
31
+ <li class="active"><a id="ab-staff-details-tab" href="#tab1" data-toggle="tab"><?php _e( 'Details', 'ab' ) ?></a></li>
32
+ <li><a id="ab-staff-services-tab" href="#tab2" data-toggle="tab"><?php _e( 'Services', 'ab' ) ?></a></li>
33
+ <li><a id="ab-staff-schedule-tab" href="#tab3" data-toggle="tab"><?php _e( 'Schedule', 'ab') ?></a></li>
34
+ <li><a id="ab-staff-holidays-tab" href="#tab4" data-toggle="tab"><?php _e( 'Days off', 'ab') ?></a></li>
35
+ </ul>
36
+ <div class="tab-content">
37
+ <div class="tab-pane active" id="tab1">
38
+ <div id="ab-staff-details-container" class="ab-staff-tab-content">
39
+ <form class="ab-staff-form bs-docs-example form-horizontal" action="" name="ab_staff" method="POST" enctype="multipart/form-data">
40
+ <table cellspacing="0">
41
+ <tbody>
42
+ <tr>
43
+ <td class="control-group">
44
+ <label class="control-label" for="ab-staff-wpuser"><?php _e( 'User', 'ab') ?></label>
45
+ <div class="controls">
46
+ <select name="wp_user_id" id="ab-staff-wpuser">
47
+ <option value=""><?php _e( 'Select from WP users', 'ab') ?></option>
48
+ <?php foreach ( $form->getUsersForStaff( $staff->id ) as $user ) : ?>
49
+ <option value="<?php echo $user->ID ?>" data-email="<?php echo $user->user_email ?>" <?php selected($user->ID, $staff->get( 'wp_user_id' )) ?>><?php echo $user->display_name ?></option>
50
+ <?php endforeach ?>
51
+ </select>
52
+ <img
53
+ src="<?php echo plugins_url( 'backend/resources/images/help.png', AB_PATH . '/main.php' ) ?>"
54
+ alt=""
55
+ class="ab-popover-ext"
56
+ data-ext_id="ab-staff-popover-ext"
57
+ />
58
+ </div>
59
+ </td>
60
+ </tr>
61
+ <tr>
62
+ <td class="control-group">
63
+ <label class="control-label" for="ab-staff-full-name"><?php _e( 'Photo', 'ab') ?></label>
64
+ <div class="controls">
65
+ <div id="ab-staff-avatar-image">
66
+ <?php if ( $staff->get( 'avatar_url' ) ) : ?>
67
+ <img src="<?php echo $staff->get( 'avatar_url' ) ?>" alt="<?php _e( 'Avatar', 'ab') ?>"/>
68
+ <a id="ab-delete-avatar" href="javascript:void(0)"><?php _e( 'Delete current photo', 'ab') ?></a>
69
+ <?php endif ?>
70
+ </div>
71
+ <input id="ab-staff-avatar" name="avatar" type="file"/>
72
+ </div>
73
+ </td>
74
+ </tr>
75
+ <tr class="form-field form-required">
76
+ <td class="control-group">
77
+ <label class="control-label" for="ab-staff-full-name"><?php _e( 'Full name', 'ab') ?></label>
78
+ <div class="controls">
79
+ <input id="ab-staff-full-name" name="full_name" value="<?php echo esc_attr($staff->get('full_name')) ?>" type="text"/><span class="red"> *</span>
80
+ </div>
81
+ </td>
82
+ </tr>
83
+ <tr>
84
+ <td class="control-group">
85
+ <label class="control-label" for="ab-staff-email"><?php _e( 'Email', 'ab') ?></label>
86
+ <div class="controls">
87
+ <input id="ab-staff-email" name="email" value="<?php echo esc_attr($staff->get( 'email' )) ?>" type="text"/>
88
+ </div>
89
+ </td>
90
+ </tr>
91
+ <tr>
92
+ <td class="control-group">
93
+ <label class="control-label" for="ab-staff-phone"><?php _e( 'Phone', 'ab') ?></label>
94
+ <div class="controls">
95
+ <input id="ab-staff-phone" name="phone" value="<?php echo esc_attr($staff->get( 'phone')) ?>" type="text"/>
96
+ </div>
97
+ </td>
98
+ </tr>
99
+ <tr>
100
+ <td class="control-group">
101
+ <h4 style="float: left"><?php _e( 'Google Calendar integration', 'ab' ) ?></h4>
102
+ <img style="float: left;margin-top: 8px;margin-left:15px;"
103
+ src="<?php echo plugins_url( 'backend/resources/images/help.png', AB_PATH . '/main.php' ) ?>"
104
+ alt=""
105
+ class="ab-popover-ext"
106
+ data-ext_id="ab-staff-google-popover-ext"
107
+ />
108
+ </td>
109
+ </tr>
110
+ <tr>
111
+ <td class="control-group">
112
+ <label class="control-label" for="ab-staff-google-pass">
113
+ <?php _e( 'Please configure Google Calendar <a href="?page=ab-system-settings">settings</a> first', 'ab' ) ?>
114
+ </label>
115
+ <div class="controls">
116
+ </div>
117
+ </td>
118
+ </tr>
119
+ <tr>
120
+ <td class="control-group">
121
+ <label class="control-label"></label>
122
+ <div class="controls">
123
+ <input id="ab-update-staff" type="submit" value="<?php _e( 'Update', 'ab') ?>" class="btn btn-info ab-update-button">
124
+ <button class="ab-reset-form" type="reset"><?php _e( 'Reset', 'ab') ?></button>
125
+ </div>
126
+ </td>
127
+ </tr>
128
+ </tbody>
129
+ </table>
130
+ <input type="hidden" name="id" value="<?php echo $staff->get( 'id' ) ?>"/>
131
+ <input type="hidden" name="action" value="ab_update_staff"/>
132
+ </form>
133
+ </div>
134
+ </div>
135
+ <div class="tab-pane" id="tab2">
136
+ <div id="ab-staff-services-container" class="ab-staff-tab-content" style="display: none"></div>
137
+ </div>
138
+ <div class="tab-pane" id="tab3">
139
+ <div id="ab-staff-schedule-container" class="ab-staff-tab-content" style="display: none"></div>
140
+ </div>
141
+ <div class="tab-pane" id="tab4">
142
+ <div id="ab-staff-holidays-container" class="ab-staff-tab-content" style="display: none"></div>
143
+ </div>
144
+ </div>
145
+ </div>
146
+ </div>
147
+
148
+
149
+ <div class="modal fade" id="lite_notice" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
150
+ <div class="modal-dialog">
151
+ <div class="modal-content">
152
+ <div class="modal-header">
153
+ <h4 class="modal-title"><?php _e('Notice', 'ab') ?></h4>
154
+ </div>
155
+ <div class="modal-body">
156
+ <?php _e('This function is disabled in the lite version of Bookly. If you find the plugin useful for your business please consider buying a licence for the full version. It costs just $38 and for this money you will get many useful functions, lifetime free update and excellent support! More information can be found here', 'ab'); ?>: <a href="http://bookly.ladela.com" target="_blank">http://bookly.ladela.com</a>
157
+ </div>
158
+ <div class="modal-footer">
159
+ <button type="button" class="btn btn-default" data-dismiss="modal"><?php _e('Close', 'ab') ?></button>
160
+ </div>
161
+ </div><!-- /.modal-content -->
162
+ </div><!-- /.modal-dialog -->
163
+ </div><!-- /.modal -->
164
+
165
+ <script>
166
+ jQuery('.ab-staff-google').on('focus', function(){
167
+ jQuery('#lite_notice').modal('show');
168
+ });
169
+ </script>
backend/modules/staff/templates/holidays.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <div id="ab-annual-calendar-scroll" style="text-align: center;">
3
+ <div class="input-prepend input-append">
4
+ <span class="ab-week-picker-arrow prev add-on col-arrow">◄</span>
5
+ <input style="width: 70px; text-align: center;background: white" class="span2 jcal_year" readonly="readonly" id="appendedPrependedInput" size="16" type="text" value="2014">
6
+ <span class="ab-week-picker-arrow next add-on col-arrow">►</span>
7
+ </div>
8
+ </div>
9
+ <div id="ab-annual-calendar"></div>
10
+
11
+ <script type="text/javascript">
12
+ jQuery(function($) {
13
+ var d = new Date();
14
+ $('#ab-annual-calendar').jCal({
15
+ day: new Date(d.getFullYear(), 0, 1),
16
+ days: 1,
17
+ showMonths: 12,
18
+ scrollSpeed: 350,
19
+ events: <?php echo $holidays ?>,
20
+ action: 'ab_staff_holidays_update',
21
+ staff_id: <?php echo $id ?>,
22
+ dayOffset: <?php echo get_option('start_of_week', 0) ?>
23
+ });
24
+ });
25
+ </script>
backend/modules/staff/templates/list.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <div class="ab-title"><?php _e( 'Staff Members', 'ab') ?> (<span id="ab-list-item-number"><?php echo count($collection) ?></span>)</div>
3
+ <div id="ab-staff" class="ab-left-bar ab-static-width">
4
+ <ul id="ab-staff-list">
5
+ <?php if ( $collection ) : ?>
6
+ <?php foreach ($collection as $staff) : ?>
7
+ <li class="ab-staff-member" id="ab-list-staff-<?php echo $staff->id ?>" data-staff-id="<?php echo $staff->id ?>"<?php if ( $active_staff_id == $staff->id ): ?> data-active="true"<?php endif ?>>
8
+ <?php if ($staff->avatar_url) : ?>
9
+ <img class="left ab-avatar" src="<?php echo $staff->avatar_url ?>" />
10
+ <?php else : ?>
11
+ <img class="left ab-avatar" src="<?php echo plugins_url( 'backend/resources/images/default-avatar.png', AB_PATH . '/main.php' ) ?>" />
12
+ <?php endif ?>
13
+ <div class="ab-text-align"><?php echo esc_html($staff->full_name) ?></div>
14
+ </li>
15
+ <?php endforeach ?>
16
+ <?php endif ?>
17
+ </ul>
18
+ <?php include 'new.php' ?>
19
+
20
+ </div>
21
+
22
+ <div id="ab-edit-staff-member" class="ab-right-content ab-full-width"></div>
23
+ <div id="ab-staff-popover-ext" style="display: none">
24
+ <p><?php _e('If this staff member requires separate login to access personal calendar, a regular WP user needs to be created for this purpose.', 'ab') ?></p>
25
+ <p><?php _e('User with "Administrator" role will have access to calendars and settings of all staff members, user with some other role will have access only to personal calendar and settings.', 'ab') ?></p>
26
+ <p><?php _e('If you will leave this field blank, this staff member will not be able to access personal calendar using WP backend.', 'ab') ?></p>
27
+ </div>
28
+ <div id="ab-staff-google-popover-ext" style="display: none">
29
+ <p><?php _e('Synchronize the data of the staff member bookings with Google Calendar.', 'ab') ?></p>
30
+ </div>
31
+ <div id="ab-staff-calendar-id-popover-ext" style="display: none">
32
+ <p><?php _e('The Calendar ID can be found by clicking on "Calendar settings" next to the calendar you wish to display. The Calendar ID is then shown beside "Calendar Address".', 'ab') ?></p>
33
+ <p><?php _e( '<b>Leave this field empty</b> to work with the default calendar.', 'ab' ) ?></p>
34
+ </div>
backend/modules/staff/templates/list_item.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
2
+ /**
3
+ * @var AB_Staff $staff
4
+ */
5
+ ?>
6
+ <li class="ab-staff-member" id="ab-list-staff-<?php echo $staff->get( 'id' ) ?>" data-staff-id="<?php echo $staff->get( 'id' ) ?>">
7
+ <img class="left ab-avatar" src="<?php echo plugins_url( 'backend/resources/images/default-avatar.png', AB_PATH . '/main.php' ) ?>" />
8
+ <div class="ab-text-align"><?php echo esc_html($staff->get('full_name')) ?></div>
9
+ </li>
backend/modules/staff/templates/new.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <div class="ab-popup-wrapper">
3
+ <a class="btn btn-info ab-popup-trigger" id="ab-newstaff-member"><?php _e('New Staff Member', 'ab') ?></a>
4
+ <div class="ab-popup" style="display: none">
5
+ <div class="ab-arrow"></div>
6
+ <div id="ab-new-satff" class="ab-content">
7
+ <table class="form-horizontal" cellspacing="0">
8
+ <tbody>
9
+ <tr>
10
+ <td><label for="ab-newstaff-wpuser"><?php _e('User','ab') ?></label></td>
11
+ <td>
12
+ <select class="auto-w" name="ab_newstaff_wpuser" id="ab-newstaff-wpuser">
13
+ <option value=""><?php _e('Select from WP users', 'ab') ?></option>
14
+ <?php foreach ( $form->getUsersForStaff() as $user ) : ?>
15
+ <option value="<?php echo $user->ID ?>"><?php echo $user->display_name ?></option>
16
+ <?php endforeach ?>
17
+ </select>
18
+ <img src="<?php echo plugins_url( 'backend/resources/images/help.png', AB_PATH . '/main.php' ) ?>" alt="" class="ab-popover" data-ext_id="ab-staff-popover-ext"/>
19
+ </td>
20
+ </tr>
21
+ <tr class="form-field form-required">
22
+ <td><label for="ab-newstaff-fullname"><?php _e('Full name', 'ab') ?></label></td>
23
+ <td><input class="ab-clear-text" id="ab-newstaff-fullname" name="ab_newstaff_fullname" type="text"/><span class="red" style="vertical-align: bottom;font-size: 26px;"> *</span></td>
24
+ </tr>
25
+ <tr>
26
+ <td></td>
27
+ <td>
28
+ <input id="ab-save-newstaff" type="submit" value="<?php _e( 'Save Member', 'ab') ?>" class="btn btn-info ab-update-button">
29
+ <a class="ab-popup-close" href="javascript:void(0)"><?php _e('Cancel', 'ab') ?></a>
30
+ </td>
31
+ </tbody>
32
+ </table>
33
+ <a class="ab-popup-close ab-popup-close-icon" href="javascript:void(0)"></a>
34
+ </div>
35
+ </div>
36
+ </div>
backend/modules/staff/templates/schedule.php ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <div id="ab-staff-schedule">
3
+ <?php if ( count( $schedule_list ) ) : ?>
4
+ <?php
5
+ $time_format = get_option( 'time_format' );
6
+ $one_hour_in_seconds = 1 * 60 * 60;
7
+
8
+ $start_time_default_value = AB_StaffScheduleItem::WORKING_START_TIME;
9
+ $end_time_default_value = date( 'H:i:s', strtotime( AB_StaffScheduleItem::WORKING_START_TIME . ' + 1 hour' ) );
10
+ $default_breaks = array('staff_id' => $staff_id);
11
+ ?>
12
+ <div class="alert" style="display: none">
13
+ <button type="button" class="close" data-dismiss="alert">&times;</button>
14
+ <!-- text -->
15
+ </div>
16
+ <form>
17
+ <table cellspacing="0" cellpadding="0">
18
+ <tbody>
19
+ <?php foreach ( $schedule_list as $list_item ) : ?>
20
+ <?php $day_is_not_available = null === $list_item->start_time ?>
21
+ <tr data-id="<?php echo $list_item->day_index ?>" data-staff_schedule_item_id="<?php echo $list_item->staff_schedule_item_id ?>" class="staff-schedule-item-row">
22
+ <td class="first"><?php echo __( $list_item->name, 'ab' ) ?></td>
23
+ <td class="working-intervals">
24
+ <?php
25
+ $workingStart = new AB_TimeChoiceWidget( array( 'empty_value' => __('OFF', 'ab') ) );
26
+ $working_start_choices = $workingStart->render(
27
+ 'start_time[' . $list_item->day_index . ']',
28
+ $list_item->start_time,
29
+ array( 'class' => 'working-start', 'style' => 'width:auto' )
30
+ );
31
+ $workingEnd = new AB_TimeChoiceWidget( array( 'use_empty' => false ) );
32
+ $working_end_choices_attributes = array( 'class' => 'working-end hide-on-non-working-day', 'style' => 'width:auto' );
33
+ if ( $day_is_not_available ) {
34
+ $working_end_choices_attributes['style'] = 'display:none; width:auto';
35
+ }
36
+ $working_end_choices = $workingEnd->render(
37
+ 'end_time[' . $list_item->day_index . ']',
38
+ $list_item->end_time,
39
+ $working_end_choices_attributes
40
+ );
41
+ echo $working_start_choices . ' <span class="hide-on-non-working-day"' . ($day_is_not_available ? ' style="display: none"' : '') . '>' . __( 'to', 'ab') . '</span> ' . $working_end_choices;
42
+ ?>
43
+ <input type="hidden" name="days[<?php echo $list_item->staff_schedule_item_id ?>]" value="<?php echo $list_item->day_index ?>"/>
44
+ </td>
45
+ <td class="add-break">
46
+ <div class="ab-popup-wrapper hide-on-non-working-day"<?php if ( $day_is_not_available ) : ?> style="display: none"<?php endif; ?>>
47
+ <a class="ab-popup-trigger" href="javascript:void(0)"><?php _e('add break', 'ab') ?></a>
48
+ <div class="ab-popup" style="display: none">
49
+ <div class="ab-arrow"></div>
50
+ <div class="error" style="display: none"></div>
51
+ <div class="ab-content">
52
+ <table cellspacing="0" cellpadding="0">
53
+ <tr>
54
+ <td>
55
+ <?php
56
+ $breakStart = new AB_TimeChoiceWidget( array( 'use_empty' => false ) );
57
+ $break_start_choices = $breakStart->render(
58
+ '',
59
+ null,
60
+ array(
61
+ 'class' => 'break-start',
62
+ 'data-default_value' => $start_time_default_value
63
+ )
64
+ );
65
+ $breakEnd = new AB_TimeChoiceWidget( array( 'use_empty' => false ) );
66
+ $break_end_choices = $breakEnd->render(
67
+ '',
68
+ null,
69
+ array(
70
+ 'class' => 'break-end',
71
+ 'data-default_value' => $end_time_default_value
72
+ )
73
+ );
74
+ echo $break_start_choices . ' <span>' . __( 'to','ab' ) . '</span> ' . $break_end_choices;
75
+ ?>
76
+ </td>
77
+ </tr>
78
+ <tr>
79
+ <td>
80
+ <a class="btn btn-info ab-popup-save ab-save-break ab-update-button"><?php _e('Save break','ab') ?></a>
81
+ <a class="ab-popup-close" href="#"><?php _e('Cancel','ab') ?></a>
82
+ </td>
83
+ </tr>
84
+ </table>
85
+ <a class="ab-popup-close ab-popup-close-icon" href="javascript:void(0)"></a>
86
+ </div>
87
+ </div>
88
+ </div>
89
+ </td>
90
+ <td class="breaks">
91
+ <?php include("_breaks.php");?>
92
+ </td>
93
+ </tr>
94
+ <?php endforeach ?>
95
+ <tr class="staff-schedule-item-row ab-last-row">
96
+ <td></td>
97
+ <td colspan="3">
98
+ <input type="hidden" name="action" value="ab_staff_schedule_update"/>
99
+ <span class="spinner left"></span>
100
+ <a id="ab-staff-schedule-update" href="javascript:void(0)" class="btn btn-info ab-update-button"><?php _e( 'Update', 'ab' ) ?></a>
101
+ <a id="ab-schedule-reset" class="ab-reset-form" href="javascript:void(0)" default-breaks='<?php echo json_encode($default_breaks); ?>'>
102
+ <?php _e( 'Reset', 'ab') ?>
103
+ </a>
104
+ </td>
105
+ </tr>
106
+ </tbody>
107
+ </table>
108
+ </form>
109
+ <?php else: ?>
110
+ <h3 align="center"><?php _e('No result','ab') ?></h3>
111
+ <?php endif; ?>
112
+ </div>
backend/modules/staff/templates/services.php ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
3
+ /**
4
+ * @var AB_Category[] $collection
5
+ * @var AB_StaffServicesForm $form
6
+ * @var int $staff_id
7
+ */
8
+ $collection = $form->getCollection();
9
+ $selected = $form->getSelected();
10
+ $uncategorized_services = $form->getUncategorizedServices();
11
+
12
+ $currentDateTime = new DateTime( 'now' );
13
+ $durationDateTime = new DateTime( 'now' );
14
+ $current_time = time();
15
+ ?>
16
+ <div id="ab-staff-services">
17
+ <?php if ( count( $collection ) ) : ?>
18
+ <form>
19
+ <ul>
20
+ <li>
21
+ <input id="ab-all-services" type="checkbox" />
22
+ <span><?php _e( 'All services', 'ab' ) ?></span>
23
+ <?php if ( !empty ( $uncategorized_services ) ) : ?>
24
+ <div class="ab-title-service">
25
+ <div><?php _e( 'Price' ) ?></div>
26
+ <div><?php _e( 'Capacity' ) ?></div>
27
+ </div>
28
+ <?php endif ?>
29
+ </li>
30
+ <?php if ( !empty ( $uncategorized_services ) ) : ?>
31
+ <li>
32
+ <ul>
33
+ <li class="ab-category-services">
34
+ <ul>
35
+ <?php foreach ( $uncategorized_services as $service ) : ?>
36
+ <li>
37
+ <div class="left ab-list-title">
38
+ <input class="ab-service-checkbox" <?php if ( array_key_exists( $service->get( 'id' ), $selected ) ) echo 'checked=checked' ?> type="checkbox" value="<?php echo $service->get( 'id' ) ?>" name="service[<?php echo $service->get( 'id' ) ?>]"/>
39
+ <?php echo esc_html($service->get('title')) ?>
40
+ </div>
41
+ <div class="right">
42
+ <input class="ab-price" type="text" <?php if ( !array_key_exists( $service->get( 'id' ), $selected ) ) echo 'disabled=disabled' ?> name="price[<?php echo $service->get( 'id' ) ?>]" value="<?php echo array_key_exists( $service->get( 'id' ), $selected ) ? $selected[ $service->get('id') ]['price'] : $service->get( 'price' )?>">
43
+ <input class="ab-price" type="number" min=1 <?php if ( !array_key_exists( $service->get( 'id' ), $selected )) echo 'disabled=disabled' ?> name="capacity[<?php echo $service->get( 'id' ) ?>]" value="1" />
44
+ </div>
45
+ <div style="border-bottom: 1px dotted black; overflow: hidden; padding-top: 15px;"></div>
46
+ </li>
47
+ <?php endforeach; ?>
48
+ </ul>
49
+ </li>
50
+ </ul>
51
+ </li>
52
+ <?php endif; ?>
53
+ <li>
54
+ <ul>
55
+ <?php foreach ( $collection as $category ) : ?>
56
+ <li class="ab-services-category">
57
+ <input class="ab-category-checkbox ab-category-<?php echo $category->get( 'id' ) ?>" data-category-id="<?php echo $category->get( 'id' ) ?>" type="checkbox" value="" />
58
+ <span><?php echo esc_html($category->get('name')) ?></span>
59
+ <div class="ab-title-service">
60
+ <div><?php _e( 'Price' ) ?></div>
61
+ <div><?php _e( 'Capacity' ) ?></div>
62
+ </div>
63
+ </li>
64
+ <li class="ab-category-services">
65
+ <ul>
66
+ <?php foreach ( $category->getServices() as $service ) : ?>
67
+ <li>
68
+ <div class="left ab-list-title">
69
+ <input class="ab-service-checkbox ab-category-<?php echo $category->get( 'id' ) ?>" data-category-id="<?php echo $category->get( 'id' ) ?>" <?php if ( array_key_exists( $service->get( 'id' ), $selected )) echo 'checked=checked' ?> type="checkbox" value="<?php echo $service->get( 'id' ) ?>" name="service[<?php echo $service->get( 'id' ) ?>]"/>
70
+ <?php echo esc_html($service->get('title')) ?>
71
+ </div>
72
+ <div class="right">
73
+ <input class="ab-price" type="text" <?php if ( !array_key_exists( $service->get( 'id' ), $selected )) echo 'disabled=disabled' ?> name="price[<?php echo $service->get( 'id' ) ?>]" value="<?php echo array_key_exists( $service->get( 'id' ), $selected ) ? $selected[$service->get('id')]['price'] : $service->get('price')?>">
74
+ <input class="ab-price" type="number" min=1 <?php if ( !array_key_exists( $service->get( 'id' ), $selected )) echo 'disabled=disabled' ?> name="capacity[<?php echo $service->get( 'id' ) ?>]" value="<?php echo array_key_exists( $service->get( 'id' ), $selected ) ? $selected[$service->get('id')]['capacity'] : $service->get('capacity')?>">
75
+ </div>
76
+ <div style="border-bottom: 1px dotted black; overflow: hidden; padding-top: 15px;"></div>
77
+ </li>
78
+ <?php endforeach ?>
79
+ </ul>
80
+ </li>
81
+ <?php endforeach ?>
82
+ </ul>
83
+ </li>
84
+ </ul>
85
+ <input type="hidden" name="action" value="ab_staff_services_update"/>
86
+ <input type="hidden" name="staff_id" value="<?php echo $staff_id ?>"/>
87
+ <span class="spinner"></span>
88
+ <a class="btn btn-info ab-update-button" href="javascript:void(0)" id="ab-staff-services-update"><?php _e('Update', 'ab') ?></a>
89
+ <button class="ab-reset-form" type="reset"><?php _e( 'Reset', 'ab' ) ?></button>
90
+ </form>
91
+ <?php endif; ?>
92
+ </div>
93
+
94
+ <div class="modal fade" id="lite_notice" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
95
+ <div class="modal-dialog">
96
+ <div class="modal-content">
97
+ <div class="modal-header">
98
+ <h4 class="modal-title"><?php _e('Notice', 'ab') ?></h4>
99
+ </div>
100
+ <div class="modal-body">
101
+ <?php _e('This function is disabled in the lite version of Bookly. If you find the plugin useful for your business please consider buying a licence for the full version. It costs just $38 and for this money you will get many useful functions, lifetime free update and excellent support! More information can be found here', 'ab'); ?>: <a href="http://bookly.ladela.com" target="_blank">http://bookly.ladela.com</a>
102
+ </div>
103
+ <div class="modal-footer">
104
+ <button type="button" class="btn btn-default" data-dismiss="modal"><?php _e('Close', 'ab') ?></button>
105
+ </div>
106
+ </div><!-- /.modal-content -->
107
+ </div><!-- /.modal-dialog -->
108
+ </div><!-- /.modal -->
backend/modules/tinymce/AB_TinyMCE_Plugin.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
+
5
+ class AB_TinyMCE_Plugin {
6
+
7
+ private $vars = array();
8
+
9
+ public function __construct() {
10
+ global $PHP_SELF;
11
+ if ( // check if we are in admin area and current page is adding/editing the post
12
+ is_admin() && ( strpos( $PHP_SELF, 'post-new.php' ) !== false || strpos( $PHP_SELF, 'post.php' ) !== false )
13
+ ) {
14
+ wp_enqueue_script( 'backbone' );
15
+ wp_enqueue_script( 'underscore' );
16
+ add_action( 'admin_footer', array( &$this, 'renderPopup' ) );
17
+ add_filter( 'media_buttons', array( &$this, 'addButton' ), 50 );
18
+
19
+ $configuration = new AB_BookingConfiguration();
20
+
21
+ $this->vars['categoriesJson'] = $configuration->getCategoriesJson();
22
+ $this->vars['staffJson'] = $configuration->getStaffJson();
23
+ $this->vars['servicesJson'] = $configuration->getServicesJson();
24
+ }
25
+ }
26
+
27
+ public function addButton( $buttons ) {
28
+ // don't show on dashboard (QuickPress)
29
+ $current_screen = get_current_screen();
30
+ if ( 'dashboard' == $current_screen->base )
31
+ return;
32
+
33
+ // don't display button for users who don't have access
34
+ if ( ! current_user_can('edit_posts') && ! current_user_can('edit_pages') )
35
+ return;
36
+
37
+ // do a version check for the new 3.5 UI
38
+ $version = get_bloginfo('version');
39
+
40
+ if ($version < 3.5) {
41
+ // show button for v 3.4 and below
42
+ echo '<a href="#TB_inline?width=640&amp;inlineId=ab-tinymce-popup&amp;height=650" id="add-ap-booking" title="' . esc_attr__( 'Add Booking Form', 'ab' ) . '">' . __('Add Booking Form', 'ab' ) . '</a>';
43
+ } else {
44
+ // display button matching new UI
45
+ $img = '<span class="ab-media-icon"></span> ';
46
+ echo '<a href="#TB_inline?width=640&amp;inlineId=ab-tinymce-popup&amp;height=650" id="add-ap-booking" class="button ab-media-button" title="' . esc_attr__( 'Add Booking Form', 'ab' ) . '">' . $img . __( 'Add Booking Form', 'ab' ) . '</a>';
47
+ }
48
+ }
49
+
50
+ public function renderPopup() {
51
+ extract($this->vars);
52
+
53
+ // render
54
+ ob_start();
55
+ ob_implicit_flush(0);
56
+
57
+ try {
58
+ include 'templates/popup.php';
59
+ } catch (Exception $e) {
60
+ ob_end_clean();
61
+ throw $e;
62
+ }
63
+
64
+ echo ob_get_clean();
65
+ }
66
+ }
backend/modules/tinymce/resources/images/calendar.png ADDED
Binary file
backend/modules/tinymce/resources/images/menu-icon.png ADDED
Binary file
backend/modules/tinymce/templates/popup.php ADDED
@@ -0,0 +1,401 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
2
+ <div id="ab-tinymce-popup" style="display: none">
3
+ <form id="ab-shortcode-form">
4
+ <table>
5
+ <tr>
6
+ <td>
7
+ <label for="ab-select-category"><?php _e( 'Default value for category select', 'ab' ); ?></label>
8
+ </td>
9
+ <td>
10
+ <select class="select-list" id="ab-select-category">
11
+ <option value=""><?php _e( 'Select category', 'ab' ); ?></option>
12
+ </select>
13
+ </td>
14
+ </tr>
15
+ <tr>
16
+ <td></td>
17
+ <td>
18
+ <input type="checkbox" id="ab-hide-categories" /> <?php _e( 'Hide this field', 'ab' ); ?>
19
+ <p><?php _e( 'Please be aware that a value in this field is required in the frontend. If you choose to hide this field, please be sure to select a default value for it', 'ab' ) ?></p>
20
+ </td>
21
+ </tr>
22
+ <tr>
23
+ <td>
24
+ <label for="ab-select-service"><?php _e( 'Default value for service select', 'ab' ); ?></label>
25
+ </td>
26
+ <td>
27
+ <select class="select-list" id="ab-select-service">
28
+ <option value=""><?php _e('Select service') ?></option>
29
+ </select>
30
+ </td>
31
+ </tr>
32
+ <tr>
33
+ <td></td>
34
+ <td>
35
+ <input type="checkbox" id="ab-hide-services" /> <?php _e( 'Hide this field', 'ab' ); ?>
36
+ <p><?php _e( 'Please be aware that a value in this field is required in the frontend. If you choose to hide this field, please be sure to select a default value for it', 'ab' ) ?></p>
37
+ </td>
38
+ </tr>
39
+ <tr>
40
+ <td>
41
+ <label for="ab-select-employee"><?php _e('Default value for employee select', 'ab') ?></label>
42
+ </td>
43
+ <td>
44
+ <select class="select-list ab-select-mobile" id="ab-select-employee">
45
+ <option value=""><?php _e( 'Any', 'ab' ) ?></option>
46
+ </select>
47
+ </td>
48
+ </tr>
49
+ <tr>
50
+ <td></td>
51
+ <td>
52
+ <input type="checkbox" id="ab-hide-employee" /> <?php _e( 'Hide this field', 'ab' ); ?>
53
+ </td>
54
+ </tr>
55
+ <tr>
56
+ <td>
57
+ <label for="ab-hide-available"><?php _e('"I\'m available on …" block', 'ab') ?></label>
58
+ </td>
59
+ <td>
60
+ <input type="checkbox" id="ab-hide-available" /> <?php _e( 'Hide this block', 'ab' ) ?>
61
+ </td>
62
+ </tr>
63
+ <tr>
64
+ <td></td>
65
+ <td>
66
+ <input class="button button-primary" id="ab-insert-shortcode" type="submit" value="<?php _e( 'Insert', 'ab' ); ?>" />
67
+ </td>
68
+ </tr>
69
+ </table>
70
+ </form>
71
+ </div>
72
+ <style type="text/css">
73
+ #ab-shortcode-form { margin-top: 15px; }
74
+ #ab-shortcode-form table { width: 100%; }
75
+ #ab-shortcode-form table td { padding: 5px; vertical-align: 0; }
76
+ #ab-shortcode-form table td select { width: 100%; margin-bottom: 5px; }
77
+ .ab-media-icon {
78
+ display: inline-block;
79
+ width: 16px;
80
+ height: 16px;
81
+ vertical-align: text-top;
82
+ margin: 0 2px;
83
+ background: url("<?php echo plugins_url( 'resources/images/calendar.png' , __DIR__ ) ?>") 0 0 no-repeat;
84
+ }
85
+ .ab-booking_form-units {
86
+ width: 17%;
87
+ margin-left: 5px;
88
+ }
89
+ </style>
90
+ <script type="text/javascript">
91
+ jQuery(function ($) {
92
+ var $select_category = $('#ab-select-category'),
93
+ $select_service = $('#ab-select-service'),
94
+ $select_employee = $('#ab-select-employee'),
95
+ $hide_categories = $('#ab-hide-categories'),
96
+ $hide_services = $('#ab-hide-services'),
97
+ $hide_staff = $('#ab-hide-employee'),
98
+ $hide_available = $('#ab-hide-available'),
99
+ $add_button = $('#add-ap-booking'),
100
+ $insert = $('#ab-insert-shortcode'),
101
+ abCategories = <?php echo $categoriesJson ?>,
102
+ abStaff = <?php echo $staffJson ?>,
103
+ abServices = <?php echo $servicesJson ?>;
104
+
105
+ $add_button.on('click', function () {
106
+ window.parent.tb_show(<?php echo json_encode( __( 'Insert Appointment Booking Form', 'ab' ) ) ?>, this.href);
107
+ });
108
+
109
+ var AB_Category = Backbone.Model.extend();
110
+ var AB_Service = Backbone.Model.extend();
111
+ var AB_Employee = Backbone.Model.extend();
112
+
113
+ var AB_Categories = Backbone.Collection.extend({
114
+ model: AB_Category
115
+ });
116
+
117
+ var AB_Services = Backbone.Collection.extend({
118
+ model: AB_Service
119
+ });
120
+
121
+ var AB_Staff = Backbone.Collection.extend({
122
+ model: AB_Employee
123
+ });
124
+
125
+ var AB_OptionView = Backbone.View.extend({
126
+ tagName: "option",
127
+
128
+ initialize: function(){
129
+ _.bindAll(this, 'render');
130
+ },
131
+ render: function(){
132
+ this.$el.attr('value', this.model.get('id')).html(this.model.get('name'));
133
+ return this;
134
+ }
135
+ });
136
+
137
+ var AB_SelectView = Backbone.View.extend({
138
+ events: {
139
+ "change": "changeSelected"
140
+ },
141
+
142
+ initialize: function() {
143
+ _.bindAll(this, 'addOne', 'addAll');
144
+ this.selectView = [];
145
+ this.collection.bind('reset', this.addAll);
146
+ },
147
+ addOne: function(location) {
148
+ var optionView = new AB_OptionView({ model: location });
149
+ this.selectView.push(optionView);
150
+ this.$el.append(optionView.render().el);
151
+ },
152
+ addAll: function() {
153
+ _.each(this.selectView, function(optionView) { optionView.remove(); });
154
+ this.selectView = [];
155
+
156
+ this.collection.each(this.addOne);
157
+
158
+ if (this.selectedId) {
159
+ this.$el.val(this.selectedId);
160
+ }
161
+ },
162
+ changeSelected: function() {
163
+ this.setSelectedId(this.$el.val());
164
+ }
165
+ });
166
+
167
+ var AB_CategoriesView = AB_SelectView.extend({
168
+ setSelectedId: function(categoryId) {
169
+ this.selectedId = categoryId;
170
+ if (this.staffView.selectedId && !this.servicesView.selectedId) {
171
+ this.servicesView.collection.reset();
172
+ this.servicesView.setCategoryEmployeeIds(categoryId, this.staffView.selectedId);
173
+ } else {
174
+ this.servicesView.selectedId = null;
175
+ this.staffView.selectedId = null;
176
+ this.servicesView.collection.reset();
177
+ this.staffView.collection.reset();
178
+ if (categoryId) {
179
+ this.servicesView.setCategoryId(categoryId);
180
+ this.staffView.setCategoryId(categoryId);
181
+ } else {
182
+ this.servicesView.setDefaultValues();
183
+ this.staffView.setDefaultValues();
184
+ }
185
+ }
186
+ },
187
+ setEmployeeId: function(employeeId) {
188
+ this.populate(abStaff[employeeId].categories);
189
+ },
190
+ populate: function(categories) {
191
+ var category;
192
+ for (var category_id in categories) {
193
+ category = new AB_Service();
194
+ category.set({
195
+ id: category_id,
196
+ name: categories[category_id].name
197
+ });
198
+ this.collection.push(category);
199
+ }
200
+ this.addAll();
201
+ },
202
+ setDefaultValues: function () {
203
+ var category;
204
+ for (var category_id in abCategories) {
205
+ category = new AB_Category();
206
+ category.set({
207
+ id: category_id,
208
+ name: abCategories[category_id].name
209
+ });
210
+ this.collection.push(category);
211
+ }
212
+ this.addAll();
213
+ }
214
+ });
215
+
216
+ var AB_ServicesView = AB_SelectView.extend({
217
+ setSelectedId: function(serviceId) {
218
+ this.selectedId = serviceId;
219
+ this.staffView.selectedId = null;
220
+ if (serviceId) {
221
+ if (!this.categoriesView.selectedId) {
222
+ this.categoriesView.selectedId = abServices[serviceId].category_id;
223
+ this.categoriesView.$el.val(this.categoriesView.selectedId);
224
+ }
225
+ this.staffView.collection.reset();
226
+ this.staffView.setServiceId(serviceId);
227
+ } else if (this.categoriesView.selectedId) {
228
+ this.staffView.$el.val('');
229
+ this.staffView.setCategoryId(this.categoriesView.selectedId)
230
+ }
231
+ },
232
+ setCategoryId: function(categoryId) {
233
+ this.populate(abCategories[categoryId].services);
234
+ },
235
+ setEmployeeId: function(employeeId) {
236
+ this.populate(abStaff[employeeId].services);
237
+ },
238
+ setCategoryEmployeeIds: function(categoryId, employeeId) {
239
+ var service, collection = this.collection, employee = abStaff[employeeId];
240
+ // It is possible that employeeId does not exist and remain only as short code argument
241
+ if (employee) {
242
+ _.each(employee.services, function(srv, serviceId) {
243
+ if (Number(srv.category_id) == categoryId) {
244
+ service = new AB_Service();
245
+ service.set({
246
+ id: serviceId,
247
+ name: employee.services[serviceId].name
248
+ });
249
+ collection.push(service);
250
+ }
251
+ });
252
+ this.addAll();
253
+ }
254
+ },
255
+ populate: function(services) {
256
+ var service;
257
+ for (var service_id in services) {
258
+ service = new AB_Service();
259
+ service.set({
260
+ id: service_id,
261
+ name: services[service_id].name
262
+ });
263
+ this.collection.push(service);
264
+ }
265
+ this.addAll();
266
+ },
267
+ setDefaultValues: function () {
268
+ var service;
269
+ for (var service_id in abServices) {
270
+ service = new AB_Service();
271
+ service.set({
272
+ id: service_id,
273
+ name: abServices[service_id].name
274
+ });
275
+ this.collection.push(service);
276
+ }
277
+ this.addAll();
278
+ }
279
+ });
280
+
281
+ var AB_StaffView = AB_SelectView.extend({
282
+ setSelectedId: function(employeeId) {
283
+ this.selectedId = employeeId;
284
+ if (employeeId) {
285
+ if (!this.categoriesView.selectedId && !this.servicesView.selectedId) {
286
+ this.categoriesView.collection.reset();
287
+ this.servicesView.collection.reset();
288
+ this.servicesView.setEmployeeId(employeeId);
289
+ this.categoriesView.setEmployeeId(employeeId);
290
+ } else if (!this.servicesView.selectedId) {
291
+ this.servicesView.collection.reset();
292
+ this.servicesView.setCategoryEmployeeIds(this.categoriesView.selectedId, employeeId);
293
+ }
294
+ } else if (!this.categoriesView.selectedId && !this.servicesView.selectedId) {
295
+ this.categoriesView.collection.reset();
296
+ this.servicesView.collection.reset();
297
+ this.categoriesView.setDefaultValues();
298
+ this.servicesView.setDefaultValues();
299
+ } else if (this.categoriesView.selectedId && !this.servicesView.selectedId) {
300
+ this.categoriesView.collection.reset();
301
+ this.categoriesView.setDefaultValues();
302
+ this.categoriesView.$el.val(this.categoriesView.selectedId);
303
+ this.servicesView.setCategoryId(this.categoriesView.selectedId);
304
+ }
305
+ },
306
+ setServiceId: function(serviceId) {
307
+ this.populate(abServices[serviceId].staff);
308
+ },
309
+ setCategoryId: function(categoryId) {
310
+ this.populate(abCategories[categoryId].staff);
311
+ },
312
+ populate: function(staff) {
313
+ var employee;
314
+ for (var employee_id in staff) {
315
+ employee = new AB_Employee();
316
+ employee.set({
317
+ id: employee_id,
318
+ name: staff[employee_id].name
319
+ });
320
+ this.collection.push(employee);
321
+ }
322
+ this.addAll();
323
+ },
324
+ setDefaultValues: function () {
325
+ var employee;
326
+ for (var employee_id in abStaff) {
327
+ employee = new AB_Employee;
328
+ employee.set({
329
+ id: employee_id,
330
+ name: abStaff[employee_id].name
331
+ });
332
+ this.collection.push(employee);
333
+ }
334
+ this.addAll();
335
+ }
336
+ });
337
+
338
+ var categoriesView = new AB_CategoriesView({el: $select_category, collection: new AB_Categories() });
339
+ var servicesView = new AB_ServicesView({el: $select_service, collection: new AB_Services() });
340
+ var staffView = new AB_StaffView({el: $select_employee, collection: new AB_Staff() });
341
+
342
+ categoriesView.servicesView = servicesView;
343
+ categoriesView.staffView = staffView;
344
+ servicesView.staffView = staffView;
345
+ servicesView.categoriesView = categoriesView;
346
+ staffView.categoriesView = categoriesView;
347
+ staffView.servicesView = servicesView;
348
+ categoriesView.setDefaultValues();
349
+ servicesView.setDefaultValues();
350
+ staffView.setDefaultValues();
351
+
352
+ $insert.on('click', function (e) {
353
+ e.preventDefault();
354
+
355
+ var insert = '[ap-booking';
356
+
357
+ if ($select_category.val()) {
358
+ insert += ' cid="' + $select_category.val() + '"';
359
+ }
360
+
361
+ if ($hide_categories.is(':checked')) {
362
+ insert += ' ch="1"';
363
+ }
364
+
365
+ if ($select_service.val()) {
366
+ insert += ' sid="' + $select_service.val() + '"';
367
+ }
368
+
369
+ if ($hide_services.is(':checked')) {
370
+ insert += ' hs="1"';
371
+ }
372
+
373
+ if ($select_employee.val()) {
374
+ insert += ' eid="' + $select_employee.val() + '"';
375
+ }
376
+
377
+ if ($hide_staff.is(':checked')) {
378
+ insert += ' he="1"';
379
+ }
380
+
381
+ if ($hide_available.is(':checked')) {
382
+ insert += ' ha="1"';
383
+ }
384
+
385
+ insert += ']';
386
+
387
+ window.send_to_editor(insert);
388
+
389
+ $select_category.val('');
390
+ $select_service.val('');
391
+ $select_employee.val('');
392
+ $hide_categories.prop('checked', false);
393
+ $hide_services.prop('checked', false);
394
+ $hide_staff.prop('checked', false);
395
+ $hide_available.prop('checked', false);
396
+
397
+ window.parent.tb_remove();
398
+ return false;
399
+ });
400
+ });
401
+ </script>
backend/resources/bootstrap/css/bootstrap-editable.css ADDED
@@ -0,0 +1,655 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*! X-editable - v1.5.0
2
+ * In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery
3
+ * http://github.com/vitalets/x-editable
4
+ * Copyright (c) 2013 Vitaliy Potapov; Licensed MIT */
5
+ .editableform {
6
+ margin-bottom: 0; /* overwrites bootstrap margin */
7
+ }
8
+
9
+ .editableform .control-group {
10
+ margin-bottom: 0; /* overwrites bootstrap margin */
11
+ white-space: nowrap; /* prevent wrapping buttons on new line */
12
+ line-height: 20px; /* overwriting bootstrap line-height. See #133 */
13
+ }
14
+
15
+ .editable-buttons {
16
+ display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
17
+ vertical-align: top;
18
+ margin-left: 7px;
19
+ /* inline-block emulation for IE7*/
20
+ zoom: 1;
21
+ *display: inline;
22
+ }
23
+
24
+ .editable-buttons.editable-buttons-bottom {
25
+ display: block;
26
+ margin-top: 7px;
27
+ margin-left: 0;
28
+ }
29
+
30
+ .editable-input {
31
+ vertical-align: top;
32
+ display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
33
+ width: auto; /* bootstrap-responsive has width: 100% that breakes layout */
34
+ white-space: normal; /* reset white-space decalred in parent*/
35
+ /* display-inline emulation for IE7*/
36
+ zoom: 1;
37
+ *display: inline;
38
+ }
39
+
40
+ .editable-buttons .editable-cancel {
41
+ margin-left: 7px;
42
+ }
43
+
44
+ /*for jquery-ui buttons need set height to look more pretty*/
45
+ .editable-buttons button.ui-button-icon-only {
46
+ height: 24px;
47
+ width: 30px;
48
+ }
49
+
50
+ .editableform-loading {
51
+ background: url('../img/loading.gif') center center no-repeat;
52
+ height: 25px;
53
+ width: auto;
54
+ min-width: 25px;
55
+ }
56
+
57
+ .editable-inline .editableform-loading {
58
+ background-position: left 5px;
59
+ }
60
+
61
+ .editable-error-block {
62
+ max-width: 300px;
63
+ margin: 5px 0 0 0;
64
+ width: auto;
65
+ white-space: normal;
66
+ }
67
+
68
+ /*add padding for jquery ui*/
69
+ .editable-error-block.ui-state-error {
70
+ padding: 3px;
71
+ }
72
+
73
+ .editable-error {
74
+ color: red;
75
+ }
76
+
77
+ /* ---- For specific types ---- */
78
+
79
+ .editableform .editable-date {
80
+ padding: 0;
81
+ margin: 0;
82
+ float: left;
83
+ }
84
+
85
+ /* move datepicker icon to center of add-on button. See https://github.com/vitalets/x-editable/issues/183 */
86
+ .editable-inline .add-on .icon-th {
87
+ margin-top: 3px;
88
+ margin-left: 1px;
89
+ }
90
+
91
+
92
+ /* checklist vertical alignment */
93
+ .editable-checklist label input[type="checkbox"],
94
+ .editable-checklist label span {
95
+ vertical-align: middle;
96
+ margin: 0;
97
+ }
98
+
99
+ .editable-checklist label {
100
+ white-space: nowrap;
101
+ }
102
+
103
+ /* set exact width of textarea to fit buttons toolbar */
104
+ .editable-wysihtml5 {
105
+ width: 566px;
106
+ height: 250px;
107
+ }
108
+
109
+ /* clear button shown as link in date inputs */
110
+ .editable-clear {
111
+ clear: both;
112
+ font-size: 0.9em;
113
+ text-decoration: none;
114
+ text-align: right;
115
+ }
116
+
117
+ /* IOS-style clear button for text inputs */
118
+ .editable-clear-x {
119
+ background: url('../img/clear.png') center center no-repeat;
120
+ display: block;
121
+ width: 13px;
122
+ height: 13px;
123
+ position: absolute;
124
+ opacity: 0.6;
125
+ z-index: 100;
126
+
127
+ top: 50%;
128
+ right: 6px;
129
+ margin-top: -6px;
130
+
131
+ }
132
+
133
+ .editable-clear-x:hover {
134
+ opacity: 1;
135
+ }
136
+
137
+ .editable-pre-wrapped {
138
+ white-space: pre-wrap;
139
+ }
140
+ .editable-container.editable-popup {
141
+ max-width: none !important; /* without this rule poshytip/tooltip does not stretch */
142
+ }
143
+
144
+ .editable-container.popover {
145
+ width: auto; /* without this rule popover does not stretch */
146
+ }
147
+
148
+ .editable-container.editable-inline {
149
+ display: inline-block;
150
+ vertical-align: middle;
151
+ width: auto;
152
+ /* inline-block emulation for IE7*/
153
+ zoom: 1;
154
+ *display: inline;
155
+ }
156
+
157
+ .editable-container.ui-widget {
158
+ font-size: inherit; /* jqueryui widget font 1.1em too big, overwrite it */
159
+ z-index: 9990; /* should be less than select2 dropdown z-index to close dropdown first when click */
160
+ }
161
+ .editable-click,
162
+ a.editable-click,
163
+ a.editable-click:hover {
164
+ text-decoration: none;
165
+ border-bottom: dashed 1px #0088cc;
166
+ }
167
+
168
+ .editable-click.editable-disabled,
169
+ a.editable-click.editable-disabled,
170
+ a.editable-click.editable-disabled:hover {
171
+ color: #585858;
172
+ cursor: default;
173
+ border-bottom: none;
174
+ }
175
+
176
+ .editable-empty, .editable-empty:hover, .editable-empty:focus{
177
+ font-style: italic;
178
+ color: #DD1144;
179
+ /* border-bottom: none; */
180
+ text-decoration: none;
181
+ }
182
+
183
+ .editable-unsaved {
184
+ font-weight: bold;
185
+ }
186
+
187
+ .editable-unsaved:after {
188
+ /* content: '*'*/
189
+ }
190
+
191
+ .editable-bg-transition {
192
+ -webkit-transition: background-color 1400ms ease-out;
193
+ -moz-transition: background-color 1400ms ease-out;
194
+ -o-transition: background-color 1400ms ease-out;
195
+ -ms-transition: background-color 1400ms ease-out;
196
+ transition: background-color 1400ms ease-out;
197
+ }
198
+
199
+ /*see https://github.com/vitalets/x-editable/issues/139 */
200
+ .form-horizontal .editable
201
+ {
202
+ padding-top: 5px;
203
+ display:inline-block;
204
+ }
205
+
206
+
207
+ /*!
208
+ * Datepicker for Bootstrap
209
+ *
210
+ * Copyright 2012 Stefan Petre
211
+ * Improvements by Andrew Rowls
212
+ * Licensed under the Apache License v2.0
213
+ * http://www.apache.org/licenses/LICENSE-2.0
214
+ *
215
+ */
216
+ .datepicker {
217
+ padding: 4px;
218
+ -webkit-border-radius: 4px;
219
+ -moz-border-radius: 4px;
220
+ border-radius: 4px;
221
+ direction: ltr;
222
+ /*.dow {
223
+ border-top: 1px solid #ddd !important;
224
+ }*/
225
+
226
+ }
227
+ .datepicker-inline {
228
+ width: 220px;
229
+ }
230
+ .datepicker.datepicker-rtl {
231
+ direction: rtl;
232
+ }
233
+ .datepicker.datepicker-rtl table tr td span {
234
+ float: right;
235
+ }
236
+ .datepicker-dropdown {
237
+ top: 0;
238
+ left: 0;
239
+ }
240
+ .datepicker-dropdown:before {
241
+ content: '';
242
+ display: inline-block;
243
+ border-left: 7px solid transparent;
244
+ border-right: 7px solid transparent;
245
+ border-bottom: 7px solid #ccc;
246
+ border-bottom-color: rgba(0, 0, 0, 0.2);
247
+ position: absolute;
248
+ top: -7px;
249
+ left: 6px;
250
+ }
251
+ .datepicker-dropdown:after {
252
+ content: '';
253
+ display: inline-block;
254
+ border-left: 6px solid transparent;
255
+ border-right: 6px solid transparent;
256
+ border-bottom: 6px solid #ffffff;
257
+ position: absolute;
258
+ top: -6px;
259
+ left: 7px;
260
+ }
261
+ .datepicker > div {
262
+ display: none;
263
+ }
264
+ .datepicker.days div.datepicker-days {
265
+ display: block;
266
+ }
267
+ .datepicker.months div.datepicker-months {
268
+ display: block;
269
+ }
270
+ .datepicker.years div.datepicker-years {
271
+ display: block;
272
+ }
273
+ .datepicker table {
274
+ margin: 0;
275
+ }
276
+ .datepicker td,
277
+ .datepicker th {
278
+ text-align: center;
279
+ width: 20px;
280
+ height: 20px;
281
+ -webkit-border-radius: 4px;
282
+ -moz-border-radius: 4px;
283
+ border-radius: 4px;
284
+ border: none;
285
+ }
286
+ .table-striped .datepicker table tr td,
287
+ .table-striped .datepicker table tr th {
288
+ background-color: transparent;
289
+ }
290
+ .datepicker table tr td.day:hover {
291
+ background: #eeeeee;
292
+ cursor: pointer;
293
+ }
294
+ .datepicker table tr td.old,
295
+ .datepicker table tr td.new {
296
+ color: #999999;
297
+ }
298
+ .datepicker table tr td.disabled,
299
+ .datepicker table tr td.disabled:hover {
300
+ background: none;
301
+ color: #999999;
302
+ cursor: default;
303
+ }
304
+ .datepicker table tr td.today,
305
+ .datepicker table tr td.today:hover,
306
+ .datepicker table tr td.today.disabled,
307
+ .datepicker table tr td.today.disabled:hover {
308
+ background-color: #fde19a;
309
+ background-image: -moz-linear-gradient(top, #fdd49a, #fdf59a);
310
+ background-image: -ms-linear-gradient(top, #fdd49a, #fdf59a);
311
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a));
312
+ background-image: -webkit-linear-gradient(top, #fdd49a, #fdf59a);
313
+ background-image: -o-linear-gradient(top, #fdd49a, #fdf59a);
314
+ background-image: linear-gradient(top, #fdd49a, #fdf59a);
315
+ background-repeat: repeat-x;
316
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);
317
+ border-color: #fdf59a #fdf59a #fbed50;
318
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
319
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
320
+ color: #000;
321
+ }
322
+ .datepicker table tr td.today:hover,
323
+ .datepicker table tr td.today:hover:hover,
324
+ .datepicker table tr td.today.disabled:hover,
325
+ .datepicker table tr td.today.disabled:hover:hover,
326
+ .datepicker table tr td.today:active,
327
+ .datepicker table tr td.today:hover:active,
328
+ .datepicker table tr td.today.disabled:active,
329
+ .datepicker table tr td.today.disabled:hover:active,
330
+ .datepicker table tr td.today.active,
331
+ .datepicker table tr td.today:hover.active,
332
+ .datepicker table tr td.today.disabled.active,
333
+ .datepicker table tr td.today.disabled:hover.active,
334
+ .datepicker table tr td.today.disabled,
335
+ .datepicker table tr td.today:hover.disabled,
336
+ .datepicker table tr td.today.disabled.disabled,
337
+ .datepicker table tr td.today.disabled:hover.disabled,
338
+ .datepicker table tr td.today[disabled],
339
+ .datepicker table tr td.today:hover[disabled],
340
+ .datepicker table tr td.today.disabled[disabled],
341
+ .datepicker table tr td.today.disabled:hover[disabled] {
342
+ background-color: #fdf59a;
343
+ }
344
+ .datepicker table tr td.today:active,
345
+ .datepicker table tr td.today:hover:active,
346
+ .datepicker table tr td.today.disabled:active,
347
+ .datepicker table tr td.today.disabled:hover:active,
348
+ .datepicker table tr td.today.active,
349
+ .datepicker table tr td.today:hover.active,
350
+ .datepicker table tr td.today.disabled.active,
351
+ .datepicker table tr td.today.disabled:hover.active {
352
+ background-color: #fbf069 \9;
353
+ }
354
+ .datepicker table tr td.today:hover:hover {
355
+ color: #000;
356
+ }
357
+ .datepicker table tr td.today.active:hover {
358
+ color: #fff;
359
+ }
360
+ .datepicker table tr td.range,
361
+ .datepicker table tr td.range:hover,
362
+ .datepicker table tr td.range.disabled,
363
+ .datepicker table tr td.range.disabled:hover {
364
+ background: #eeeeee;
365
+ -webkit-border-radius: 0;
366
+ -moz-border-radius: 0;
367
+ border-radius: 0;
368
+ }
369
+ .datepicker table tr td.range.today,
370
+ .datepicker table tr td.range.today:hover,
371
+ .datepicker table tr td.range.today.disabled,
372
+ .datepicker table tr td.range.today.disabled:hover {
373
+ background-color: #f3d17a;
374
+ background-image: -moz-linear-gradient(top, #f3c17a, #f3e97a);
375
+ background-image: -ms-linear-gradient(top, #f3c17a, #f3e97a);
376
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f3c17a), to(#f3e97a));
377
+ background-image: -webkit-linear-gradient(top, #f3c17a, #f3e97a);
378
+ background-image: -o-linear-gradient(top, #f3c17a, #f3e97a);
379
+ background-image: linear-gradient(top, #f3c17a, #f3e97a);
380
+ background-repeat: repeat-x;
381
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0);
382
+ border-color: #f3e97a #f3e97a #edde34;
383
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
384
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
385
+ -webkit-border-radius: 0;
386
+ -moz-border-radius: 0;
387
+ border-radius: 0;
388
+ }
389
+ .datepicker table tr td.range.today:hover,
390
+ .datepicker table tr td.range.today:hover:hover,
391
+ .datepicker table tr td.range.today.disabled:hover,
392
+ .datepicker table tr td.range.today.disabled:hover:hover,
393
+ .datepicker table tr td.range.today:active,
394
+ .datepicker table tr td.range.today:hover:active,
395
+ .datepicker table tr td.range.today.disabled:active,
396
+ .datepicker table tr td.range.today.disabled:hover:active,
397
+ .datepicker table tr td.range.today.active,
398
+ .datepicker table tr td.range.today:hover.active,
399
+ .datepicker table tr td.range.today.disabled.active,
400
+ .datepicker table tr td.range.today.disabled:hover.active,
401
+ .datepicker table tr td.range.today.disabled,
402
+ .datepicker table tr td.range.today:hover.disabled,
403
+ .datepicker table tr td.range.today.disabled.disabled,
404
+ .datepicker table tr td.range.today.disabled:hover.disabled,
405
+ .datepicker table tr td.range.today[disabled],
406
+ .datepicker table tr td.range.today:hover[disabled],
407
+ .datepicker table tr td.range.today.disabled[disabled],
408
+ .datepicker table tr td.range.today.disabled:hover[disabled] {
409
+ background-color: #f3e97a;
410
+ }
411
+ .datepicker table tr td.range.today:active,
412
+ .datepicker table tr td.range.today:hover:active,
413
+ .datepicker table tr td.range.today.disabled:active,
414
+ .datepicker table tr td.range.today.disabled:hover:active,
415
+ .datepicker table tr td.range.today.active,
416
+ .datepicker table tr td.range.today:hover.active,
417
+ .datepicker table tr td.range.today.disabled.active,
418
+ .datepicker table tr td.range.today.disabled:hover.active {
419
+ background-color: #efe24b \9;
420
+ }
421
+ .datepicker table tr td.selected,
422
+ .datepicker table tr td.selected:hover,
423
+ .datepicker table tr td.selected.disabled,
424
+ .datepicker table tr td.selected.disabled:hover {
425
+ background-color: #9e9e9e;
426
+ background-image: -moz-linear-gradient(top, #b3b3b3, #808080);
427
+ background-image: -ms-linear-gradient(top, #b3b3b3, #808080);
428
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#b3b3b3), to(#808080));
429
+ background-image: -webkit-linear-gradient(top, #b3b3b3, #808080);
430
+ background-image: -o-linear-gradient(top, #b3b3b3, #808080);
431
+ background-image: linear-gradient(top, #b3b3b3, #808080);
432
+ background-repeat: repeat-x;
433
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0);
434
+ border-color: #808080 #808080 #595959;
435
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
436
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
437
+ color: #fff;
438
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
439
+ }
440
+ .datepicker table tr td.selected:hover,
441
+ .datepicker table tr td.selected:hover:hover,
442
+ .datepicker table tr td.selected.disabled:hover,
443
+ .datepicker table tr td.selected.disabled:hover:hover,
444
+ .datepicker table tr td.selected:active,
445
+ .datepicker table tr td.selected:hover:active,
446
+ .datepicker table tr td.selected.disabled:active,
447
+ .datepicker table tr td.selected.disabled:hover:active,
448
+ .datepicker table tr td.selected.active,
449
+ .datepicker table tr td.selected:hover.active,
450
+ .datepicker table tr td.selected.disabled.active,
451
+ .datepicker table tr td.selected.disabled:hover.active,
452
+ .datepicker table tr td.selected.disabled,
453
+ .datepicker table tr td.selected:hover.disabled,
454
+ .datepicker table tr td.selected.disabled.disabled,
455
+ .datepicker table tr td.selected.disabled:hover.disabled,
456
+ .datepicker table tr td.selected[disabled],
457
+ .datepicker table tr td.selected:hover[disabled],
458
+ .datepicker table tr td.selected.disabled[disabled],
459
+ .datepicker table tr td.selected.disabled:hover[disabled] {
460
+ background-color: #808080;
461
+ }
462
+ .datepicker table tr td.selected:active,
463
+ .datepicker table tr td.selected:hover:active,
464
+ .datepicker table tr td.selected.disabled:active,
465
+ .datepicker table tr td.selected.disabled:hover:active,
466
+ .datepicker table tr td.selected.active,
467
+ .datepicker table tr td.selected:hover.active,
468
+ .datepicker table tr td.selected.disabled.active,
469
+ .datepicker table tr td.selected.disabled:hover.active {
470
+ background-color: #666666 \9;
471
+ }
472
+ .datepicker table tr td.active,
473
+ .datepicker table tr td.active:hover,
474
+ .datepicker table tr td.active.disabled,
475
+ .datepicker table tr td.active.disabled:hover {
476
+ background-color: #006dcc;
477
+ background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
478
+ background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
479
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
480
+ background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
481
+ background-image: -o-linear-gradient(top, #0088cc, #0044cc);
482
+ background-image: linear-gradient(top, #0088cc, #0044cc);
483
+ background-repeat: repeat-x;
484
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
485
+ border-color: #0044cc #0044cc #002a80;
486
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
487
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
488
+ color: #fff;
489
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
490
+ }
491
+ .datepicker table tr td.active:hover,
492
+ .datepicker table tr td.active:hover:hover,
493
+ .datepicker table tr td.active.disabled:hover,
494
+ .datepicker table tr td.active.disabled:hover:hover,
495
+ .datepicker table tr td.active:active,
496
+ .datepicker table tr td.active:hover:active,
497
+ .datepicker table tr td.active.disabled:active,
498
+ .datepicker table tr td.active.disabled:hover:active,
499
+ .datepicker table tr td.active.active,
500
+ .datepicker table tr td.active:hover.active,
501
+ .datepicker table tr td.active.disabled.active,
502
+ .datepicker table tr td.active.disabled:hover.active,
503
+ .datepicker table tr td.active.disabled,
504
+ .datepicker table tr td.active:hover.disabled,
505
+ .datepicker table tr td.active.disabled.disabled,
506
+ .datepicker table tr td.active.disabled:hover.disabled,
507
+ .datepicker table tr td.active[disabled],
508
+ .datepicker table tr td.active:hover[disabled],
509
+ .datepicker table tr td.active.disabled[disabled],
510
+ .datepicker table tr td.active.disabled:hover[disabled] {
511
+ background-color: #0044cc;
512
+ }
513
+ .datepicker table tr td.active:active,
514
+ .datepicker table tr td.active:hover:active,
515
+ .datepicker table tr td.active.disabled:active,
516
+ .datepicker table tr td.active.disabled:hover:active,
517
+ .datepicker table tr td.active.active,
518
+ .datepicker table tr td.active:hover.active,
519
+ .datepicker table tr td.active.disabled.active,
520
+ .datepicker table tr td.active.disabled:hover.active {
521
+ background-color: #003399 \9;
522
+ }
523
+ .datepicker table tr td span {
524
+ display: block;
525
+ width: 23%;
526
+ height: 54px;
527
+ line-height: 54px;
528
+ float: left;
529
+ margin: 1%;
530
+ cursor: pointer;
531
+ -webkit-border-radius: 4px;
532
+ -moz-border-radius: 4px;
533
+ border-radius: 4px;
534
+ }
535
+ .datepicker table tr td span:hover {
536
+ background: #eeeeee;
537
+ }
538
+ .datepicker table tr td span.disabled,
539
+ .datepicker table tr td span.disabled:hover {
540
+ background: none;
541
+ color: #999999;
542
+ cursor: default;
543
+ }
544
+ .datepicker table tr td span.active,
545
+ .datepicker table tr td span.active:hover,
546
+ .datepicker table tr td span.active.disabled,
547
+ .datepicker table tr td span.active.disabled:hover {
548
+ background-color: #006dcc;
549
+ background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
550
+ background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
551
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
552
+ background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
553
+ background-image: -o-linear-gradient(top, #0088cc, #0044cc);
554
+ background-image: linear-gradient(top, #0088cc, #0044cc);
555
+ background-repeat: repeat-x;
556
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
557
+ border-color: #0044cc #0044cc #002a80;
558
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
559
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
560
+ color: #fff;
561
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
562
+ }
563
+ .datepicker table tr td span.active:hover,
564
+ .datepicker table tr td span.active:hover:hover,
565
+ .datepicker table tr td span.active.disabled:hover,
566
+ .datepicker table tr td span.active.disabled:hover:hover,
567
+ .datepicker table tr td span.active:active,
568
+ .datepicker table tr td span.active:hover:active,
569
+ .datepicker table tr td span.active.disabled:active,
570
+ .datepicker table tr td span.active.disabled:hover:active,
571
+ .datepicker table tr td span.active.active,
572
+ .datepicker table tr td span.active:hover.active,
573
+ .datepicker table tr td span.active.disabled.active,
574
+ .datepicker table tr td span.active.disabled:hover.active,
575
+ .datepicker table tr td span.active.disabled,
576
+ .datepicker table tr td span.active:hover.disabled,
577
+ .datepicker table tr td span.active.disabled.disabled,
578
+ .datepicker table tr td span.active.disabled:hover.disabled,
579
+ .datepicker table tr td span.active[disabled],
580
+ .datepicker table tr td span.active:hover[disabled],
581
+ .datepicker table tr td span.active.disabled[disabled],
582
+ .datepicker table tr td span.active.disabled:hover[disabled] {
583
+ background-color: #0044cc;
584
+ }
585
+ .datepicker table tr td span.active:active,
586
+ .datepicker table tr td span.active:hover:active,
587
+ .datepicker table tr td span.active.disabled:active,
588
+ .datepicker table tr td span.active.disabled:hover:active,
589
+ .datepicker table tr td span.active.active,
590
+ .datepicker table tr td span.active:hover.active,
591
+ .datepicker table tr td span.active.disabled.active,
592
+ .datepicker table tr td span.active.disabled:hover.active {
593
+ background-color: #003399 \9;
594
+ }
595
+ .datepicker table tr td span.old,
596
+ .datepicker table tr td span.new {
597
+ color: #999999;
598
+ }
599
+ .datepicker th.datepicker-switch {
600
+ width: 145px;
601
+ }
602
+ .datepicker thead tr:first-child th,
603
+ .datepicker tfoot tr th {
604
+ cursor: pointer;
605
+ }
606
+ .datepicker thead tr:first-child th:hover,
607
+ .datepicker tfoot tr th:hover {
608
+ background: #eeeeee;
609
+ }
610
+ .datepicker .cw {
611
+ font-size: 10px;
612
+ width: 12px;
613
+ padding: 0 2px 0 5px;
614
+ vertical-align: middle;
615
+ }
616
+ .datepicker thead tr:first-child th.cw {
617
+ cursor: default;
618
+ background-color: transparent;
619
+ }
620
+ .input-append.date .add-on i,
621
+ .input-prepend.date .add-on i {
622
+ display: block;
623
+ cursor: pointer;
624
+ width: 16px;
625
+ height: 16px;
626
+ }
627
+ .input-daterange input {
628
+ text-align: center;
629
+ }
630
+ .input-daterange input:first-child {
631
+ -webkit-border-radius: 3px 0 0 3px;
632
+ -moz-border-radius: 3px 0 0 3px;
633
+ border-radius: 3px 0 0 3px;
634
+ }
635
+ .input-daterange input:last-child {
636
+ -webkit-border-radius: 0 3px 3px 0;
637
+ -moz-border-radius: 0 3px 3px 0;
638
+ border-radius: 0 3px 3px 0;
639
+ }
640
+ .input-daterange .add-on {
641
+ display: inline-block;
642
+ width: auto;
643
+ min-width: 16px;
644
+ height: 18px;
645
+ padding: 4px 5px;
646
+ font-weight: normal;
647
+ line-height: 18px;
648
+ text-align: center;
649
+ text-shadow: 0 1px 0 #ffffff;
650
+ vertical-align: middle;
651
+ background-color: #eeeeee;
652
+ border: 1px solid #ccc;
653
+ margin-left: -5px;
654
+ margin-right: -5px;
655
+ }
backend/resources/bootstrap/css/bootstrap.css ADDED
@@ -0,0 +1,6278 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Bootstrap v2.3.1
3
+ *
4
+ * Copyright 2012 Twitter, Inc
5
+ * Licensed under the Apache License v2.0
6
+ * http://www.apache.org/licenses/LICENSE-2.0
7
+ *
8
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
9
+ */
10
+ .clearfix {
11
+ *zoom: 1;
12
+ }
13
+ .clearfix:before,
14
+ .clearfix:after {
15
+ display: table;
16
+ content: "";
17
+ line-height: 0;
18
+ }
19
+ .clearfix:after {
20
+ clear: both;
21
+ }
22
+ .hide-text {
23
+ font: 0/0 a;
24
+ color: transparent;
25
+ text-shadow: none;
26
+ background-color: transparent;
27
+ border: 0;
28
+ }
29
+ .input-block-level {
30
+ display: block;
31
+ width: 100%;
32
+ min-height: 30px;
33
+ -webkit-box-sizing: border-box;
34
+ -moz-box-sizing: border-box;
35
+ box-sizing: border-box;
36
+ }
37
+ article,
38
+ aside,
39
+ details,
40
+ figcaption,
41
+ figure,
42
+ footer,
43
+ header,
44
+ hgroup,
45
+ nav,
46
+ section {
47
+ display: block;
48
+ }
49
+ audio,
50
+ canvas,
51
+ video {
52
+ display: inline-block;
53
+ *display: inline;
54
+ *zoom: 1;
55
+ }
56
+ audio:not([controls]) {
57
+ display: none;
58
+ }
59
+ html {
60
+ font-size: 100%;
61
+ -webkit-text-size-adjust: 100%;
62
+ -ms-text-size-adjust: 100%;
63
+ }
64
+ a:focus {
65
+ outline: thin dotted #333;
66
+ outline: 5px auto -webkit-focus-ring-color;
67
+ outline-offset: -2px;
68
+ }
69
+ a:hover,
70
+ a:active {
71
+ outline: 0;
72
+ }
73
+ sub,
74
+ sup {
75
+ position: relative;
76
+ font-size: 75%;
77
+ line-height: 0;
78
+ vertical-align: baseline;
79
+ }
80
+ sup {
81
+ top: -0.5em;
82
+ }
83
+ sub {
84
+ bottom: -0.25em;
85
+ }
86
+ img {
87
+ /* Responsive images (ensure images don't scale beyond their parents) */
88
+
89
+ max-width: 100%;
90
+ /* Part 1: Set a maxium relative to the parent */
91
+
92
+ width: auto\9;
93
+ /* IE7-8 need help adjusting responsive images */
94
+
95
+ height: auto;
96
+ /* Part 2: Scale the height according to the width, otherwise you get stretching */
97
+
98
+ vertical-align: middle;
99
+ border: 0;
100
+ -ms-interpolation-mode: bicubic;
101
+ }
102
+ #map_canvas img,
103
+ .google-maps img {
104
+ max-width: none;
105
+ }
106
+ button,
107
+ input,
108
+ select,
109
+ textarea {
110
+ margin: 0;
111
+ font-size: 100%;
112
+ vertical-align: middle;
113
+ }
114
+ button,
115
+ input {
116
+ *overflow: visible;
117
+ line-height: normal;
118
+ }
119
+ button::-moz-focus-inner,
120
+ input::-moz-focus-inner {
121
+ padding: 0;
122
+ border: 0;
123
+ }
124
+ button,
125
+ html input[type="button"],
126
+ input[type="reset"],
127
+ input[type="submit"] {
128
+ -webkit-appearance: button;
129
+ cursor: pointer;
130
+ }
131
+ label,
132
+ select,
133
+ button,
134
+ input[type="button"],
135
+ input[type="reset"],
136
+ input[type="submit"],
137
+ input[type="radio"],
138
+ input[type="checkbox"] {
139
+ cursor: pointer;
140
+ }
141
+ input[type="search"] {
142
+ -webkit-box-sizing: content-box;
143
+ -moz-box-sizing: content-box;
144
+ box-sizing: content-box;
145
+ -webkit-appearance: textfield;
146
+ }
147
+ input[type="search"]::-webkit-search-decoration,
148
+ input[type="search"]::-webkit-search-cancel-button {
149
+ -webkit-appearance: none;
150
+ }
151
+ textarea {
152
+ overflow: auto;
153
+ vertical-align: top;
154
+ }
155
+ @media print {
156
+ * {
157
+ text-shadow: none !important;
158
+ color: #000 !important;
159
+ background: transparent !important;
160
+ box-shadow: none !important;
161
+ }
162
+ a,
163
+ a:visited {
164
+ text-decoration: underline;
165
+ }
166
+ a[href]:after {
167
+ content: " (" attr(href) ")";
168
+ }
169
+ abbr[title]:after {
170
+ content: " (" attr(title) ")";
171
+ }
172
+ .ir a:after,
173
+ a[href^="javascript:"]:after,
174
+ a[href^="#"]:after {
175
+ content: "";
176
+ }
177
+ pre,
178
+ blockquote {
179
+ border: 1px solid #999;
180
+ page-break-inside: avoid;
181
+ }
182
+ thead {
183
+ display: table-header-group;
184
+ }
185
+ tr,
186
+ img {
187
+ page-break-inside: avoid;
188
+ }
189
+ img {
190
+ max-width: 100% !important;
191
+ }
192
+ @page {
193
+ margin: 0.5cm;
194
+ }
195
+ p,
196
+ h2,
197
+ h3 {
198
+ orphans: 3;
199
+ widows: 3;
200
+ }
201
+ h2,
202
+ h3 {
203
+ page-break-after: avoid;
204
+ }
205
+ }
206
+ body {
207
+ margin: 0;
208
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
209
+ font-size: 14px;
210
+ line-height: 20px;
211
+ color: #333333;
212
+ background-color: #ffffff;
213
+ }
214
+ a {
215
+ color: #0088cc;
216
+ text-decoration: none;
217
+ }
218
+ a:hover,
219
+ a:focus {
220
+ color: #005580;
221
+ text-decoration: underline;
222
+ }
223
+ .img-rounded {
224
+ -webkit-border-radius: 6px;
225
+ -moz-border-radius: 6px;
226
+ border-radius: 6px;
227
+ }
228
+ .img-polaroid {
229
+ padding: 4px;
230
+ background-color: #fff;
231
+ border: 1px solid #ccc;
232
+ border: 1px solid rgba(0, 0, 0, 0.2);
233
+ -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
234
+ -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
235
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
236
+ }
237
+ .img-circle {
238
+ -webkit-border-radius: 500px;
239
+ -moz-border-radius: 500px;
240
+ border-radius: 500px;
241
+ }
242
+ .row {
243
+ margin-left: -20px;
244
+ *zoom: 1;
245
+ }
246
+ .row:before,
247
+ .row:after {
248
+ display: table;
249
+ content: "";
250
+ line-height: 0;
251
+ }
252
+ .row:after {
253
+ clear: both;
254
+ }
255
+ [class*="span"] {
256
+ float: left;
257
+ min-height: 1px;
258
+ margin-left: 20px;
259
+ }
260
+ .container,
261
+ .navbar-static-top .container,
262
+ .navbar-fixed-top .container,
263
+ .navbar-fixed-bottom .container {
264
+ width: 940px;
265
+ }
266
+ .span12 {
267
+ width: 940px;
268
+ }
269
+ .span11 {
270
+ width: 860px;
271
+ }
272
+ .span10 {
273
+ width: 780px;
274
+ }
275
+ .span9 {
276
+ width: 700px;
277
+ }
278
+ .span8 {
279
+ width: 620px;
280
+ }
281
+ .span7 {
282
+ width: 540px;
283
+ }
284
+ .span6 {
285
+ width: 460px;
286
+ }
287
+ .span5 {
288
+ width: 380px;
289
+ }
290
+ .span4 {
291
+ width: 300px;
292
+ }
293
+ .span3 {
294
+ width: 220px;
295
+ }
296
+ .span2 {
297
+ width: 140px;
298
+ }
299
+ .span1 {
300
+ width: 60px;
301
+ }
302
+ .offset12 {
303
+ margin-left: 980px;
304
+ }
305
+ .offset11 {
306
+ margin-left: 900px;
307
+ }
308
+ .offset10 {
309
+ margin-left: 820px;
310
+ }
311
+ .offset9 {
312
+ margin-left: 740px;
313
+ }
314
+ .offset8 {
315
+ margin-left: 660px;
316
+ }
317
+ .offset7 {
318
+ margin-left: 580px;
319
+ }
320
+ .offset6 {
321
+ margin-left: 500px;
322
+ }
323
+ .offset5 {
324
+ margin-left: 420px;
325
+ }
326
+ .offset4 {
327
+ margin-left: 340px;
328
+ }
329
+ .offset3 {
330
+ margin-left: 260px;
331
+ }
332
+ .offset2 {
333
+ margin-left: 180px;
334
+ }
335
+ .offset1 {
336
+ margin-left: 100px;
337
+ }
338
+ .row-fluid {
339
+ width: 100%;
340
+ *zoom: 1;
341
+ }
342
+ .row-fluid:before,
343
+ .row-fluid:after {
344
+ display: table;
345
+ content: "";
346
+ line-height: 0;
347
+ }
348
+ .row-fluid:after {
349
+ clear: both;
350
+ }
351
+ .row-fluid [class*="span"] {
352
+ display: block;
353
+ width: 100%;
354
+ min-height: 30px;
355
+ -webkit-box-sizing: border-box;
356
+ -moz-box-sizing: border-box;
357
+ box-sizing: border-box;
358
+ float: left;
359
+ margin-left: 2.127659574468085%;
360
+ *margin-left: 2.074468085106383%;
361
+ }
362
+ .row-fluid [class*="span"]:first-child {
363
+ margin-left: 0;
364
+ }
365
+ .row-fluid .controls-row [class*="span"] + [class*="span"] {
366
+ margin-left: 2.127659574468085%;
367
+ }
368
+ .row-fluid .span12 {
369
+ width: 100%;
370
+ *width: 99.94680851063829%;
371
+ }
372
+ .row-fluid .span11 {
373
+ width: 91.48936170212765%;
374
+ *width: 91.43617021276594%;
375
+ }
376
+ .row-fluid .span10 {
377
+ width: 82.97872340425532%;
378
+ *width: 82.92553191489361%;
379
+ }
380
+ .row-fluid .span9 {
381
+ width: 74.46808510638297%;
382
+ *width: 74.41489361702126%;
383
+ }
384
+ .row-fluid .span8 {
385
+ width: 65.95744680851064%;
386
+ *width: 65.90425531914893%;
387
+ }
388
+ .row-fluid .span7 {
389
+ width: 57.44680851063829%;
390
+ *width: 57.39361702127659%;
391
+ }
392
+ .row-fluid .span6 {
393
+ width: 48.93617021276595%;
394
+ *width: 48.88297872340425%;
395
+ }
396
+ .row-fluid .span5 {
397
+ width: 40.42553191489362%;
398
+ *width: 40.37234042553192%;
399
+ }
400
+ .row-fluid .span4 {
401
+ width: 31.914893617021278%;
402
+ *width: 31.861702127659576%;
403
+ }
404
+ .row-fluid .span3 {
405
+ width: 23.404255319148934%;
406
+ *width: 23.351063829787233%;
407
+ }
408
+ .row-fluid .span2 {
409
+ width: 14.893617021276595%;
410
+ *width: 14.840425531914894%;
411
+ }
412
+ .row-fluid .span1 {
413
+ width: 6.382978723404255%;
414
+ *width: 6.329787234042553%;
415
+ }
416
+ .row-fluid .offset12 {
417
+ margin-left: 104.25531914893617%;
418
+ *margin-left: 104.14893617021275%;
419
+ }
420
+ .row-fluid .offset12:first-child {
421
+ margin-left: 102.12765957446808%;
422
+ *margin-left: 102.02127659574467%;
423
+ }
424
+ .row-fluid .offset11 {
425
+ margin-left: 95.74468085106382%;
426
+ *margin-left: 95.6382978723404%;
427
+ }
428
+ .row-fluid .offset11:first-child {
429
+ margin-left: 93.61702127659574%;
430
+ *margin-left: 93.51063829787232%;
431
+ }
432
+ .row-fluid .offset10 {
433
+ margin-left: 87.23404255319149%;
434
+ *margin-left: 87.12765957446807%;
435
+ }
436
+ .row-fluid .offset10:first-child {
437
+ margin-left: 85.1063829787234%;
438
+ *margin-left: 84.99999999999999%;
439
+ }
440
+ .row-fluid .offset9 {
441
+ margin-left: 78.72340425531914%;
442
+ *margin-left: 78.61702127659572%;
443
+ }
444
+ .row-fluid .offset9:first-child {
445
+ margin-left: 76.59574468085106%;
446
+ *margin-left: 76.48936170212764%;
447
+ }
448
+ .row-fluid .offset8 {
449
+ margin-left: 70.2127659574468%;
450
+ *margin-left: 70.10638297872339%;
451
+ }
452
+ .row-fluid .offset8:first-child {
453
+ margin-left: 68.08510638297872%;
454
+ *margin-left: 67.9787234042553%;
455
+ }
456
+ .row-fluid .offset7 {
457
+ margin-left: 61.70212765957446%;
458
+ *margin-left: 61.59574468085106%;
459
+ }
460
+ .row-fluid .offset7:first-child {
461
+ margin-left: 59.574468085106375%;
462
+ *margin-left: 59.46808510638297%;
463
+ }
464
+ .row-fluid .offset6 {
465
+ margin-left: 53.191489361702125%;
466
+ *margin-left: 53.085106382978715%;
467
+ }
468
+ .row-fluid .offset6:first-child {
469
+ margin-left: 51.063829787234035%;
470
+ *margin-left: 50.95744680851063%;
471
+ }
472
+ .row-fluid .offset5 {
473
+ margin-left: 44.68085106382979%;
474
+ *margin-left: 44.57446808510638%;
475
+ }
476
+ .row-fluid .offset5:first-child {
477
+ margin-left: 42.5531914893617%;
478
+ *margin-left: 42.4468085106383%;
479
+ }
480
+ .row-fluid .offset4 {
481
+ margin-left: 36.170212765957444%;
482
+ *margin-left: 36.06382978723405%;
483
+ }
484
+ .row-fluid .offset4:first-child {
485
+ margin-left: 34.04255319148936%;
486
+ *margin-left: 33.93617021276596%;
487
+ }
488
+ .row-fluid .offset3 {
489
+ margin-left: 27.659574468085104%;
490
+ *margin-left: 27.5531914893617%;
491
+ }
492
+ .row-fluid .offset3:first-child {
493
+ margin-left: 25.53191489361702%;
494
+ *margin-left: 25.425531914893618%;
495
+ }
496
+ .row-fluid .offset2 {
497
+ margin-left: 19.148936170212764%;
498
+ *margin-left: 19.04255319148936%;
499
+ }
500
+ .row-fluid .offset2:first-child {
501
+ margin-left: 17.02127659574468%;
502
+ *margin-left: 16.914893617021278%;
503
+ }
504
+ .row-fluid .offset1 {
505
+ margin-left: 10.638297872340425%;
506
+ *margin-left: 10.53191489361702%;
507
+ }
508
+ .row-fluid .offset1:first-child {
509
+ margin-left: 8.51063829787234%;
510
+ *margin-left: 8.404255319148938%;
511
+ }
512
+ [class*="span"].hide,
513
+ .row-fluid [class*="span"].hide {
514
+ display: none;
515
+ }
516
+ [class*="span"].pull-right,
517
+ .row-fluid [class*="span"].pull-right {
518
+ float: right;
519
+ }
520
+ .container {
521
+ margin-right: auto;
522
+ margin-left: auto;
523
+ *zoom: 1;
524
+ }
525
+ .container:before,
526
+ .container:after {
527
+ display: table;
528
+ content: "";
529
+ line-height: 0;
530
+ }
531
+ .container:after {
532
+ clear: both;
533
+ }
534
+ .container-fluid {
535
+ padding-right: 20px;
536
+ padding-left: 20px;
537
+ *zoom: 1;
538
+ }
539
+ .container-fluid:before,
540
+ .container-fluid:after {
541
+ display: table;
542
+ content: "";
543
+ line-height: 0;
544
+ }
545
+ .container-fluid:after {
546
+ clear: both;
547
+ }
548
+ p {
549
+ margin: 0 0 10px;
550
+ }
551
+ .lead {
552
+ margin-bottom: 20px;
553
+ font-size: 21px;
554
+ font-weight: 200;
555
+ line-height: 30px;
556
+ }
557
+ small {
558
+ font-size: 85%;
559
+ }
560
+ strong {
561
+ font-weight: bold;
562
+ }
563
+ em {
564
+ font-style: italic;
565
+ }
566
+ cite {
567
+ font-style: normal;
568
+ }
569
+ .muted {
570
+ color: #999999;
571
+ }
572
+ a.muted:hover,
573
+ a.muted:focus {
574
+ color: #808080;
575
+ }
576
+ .text-warning {
577
+ color: #c09853;
578
+ }
579
+ a.text-warning:hover,
580
+ a.text-warning:focus {
581
+ color: #a47e3c;
582
+ }
583
+ .text-error {
584
+ color: #b94a48;
585
+ }
586
+ a.text-error:hover,
587
+ a.text-error:focus {
588
+ color: #953b39;
589
+ }
590
+ .text-info {
591
+ color: #3a87ad;
592
+ }
593
+ a.text-info:hover,
594
+ a.text-info:focus {
595
+ color: #2d6987;
596
+ }
597
+ .text-success {
598
+ color: #468847;
599
+ }
600
+ a.text-success:hover,
601
+ a.text-success:focus {
602
+ color: #356635;
603
+ }
604
+ .text-left {
605
+ text-align: left;
606
+ }
607
+ .text-right {
608
+ text-align: right;
609
+ }
610
+ .text-center {
611
+ text-align: center;
612
+ }
613
+ h1,
614
+ h2,
615
+ h3,
616
+ h4,
617
+ h5,
618
+ h6 {
619
+ margin: 10px 0;
620
+ font-family: inherit;
621
+ font-weight: bold;
622
+ line-height: 20px;
623
+ color: inherit;
624
+ text-rendering: optimizelegibility;
625
+ }
626
+ h1 small,
627
+ h2 small,
628
+ h3 small,
629
+ h4 small,
630
+ h5 small,
631
+ h6 small {
632
+ font-weight: normal;
633
+ line-height: 1;
634
+ color: #999999;
635
+ }
636
+ h1,
637
+ h2,
638
+ h3 {
639
+ line-height: 40px;
640
+ }
641
+ h1 {
642
+ font-size: 38.5px;
643
+ }
644
+ h2 {
645
+ font-size: 31.5px;
646
+ }
647
+ h3 {
648
+ font-size: 24.5px;
649
+ }
650
+ h4 {
651
+ font-size: 17.5px;
652
+ }
653
+ h5 {
654
+ font-size: 14px;
655
+ }
656
+ h6 {
657
+ font-size: 11.9px;
658
+ }
659
+ h1 small {
660
+ font-size: 24.5px;
661
+ }
662
+ h2 small {
663
+ font-size: 17.5px;
664
+ }
665
+ h3 small {
666
+ font-size: 14px;
667
+ }
668
+ h4 small {
669
+ font-size: 14px;
670
+ }
671
+ .page-header {
672
+ padding-bottom: 9px;
673
+ margin: 20px 0 30px;
674
+ border-bottom: 1px solid #eeeeee;
675
+ }
676
+ ul,
677
+ ol {
678
+ padding: 0;
679
+ margin: 0 0 10px 25px;
680
+ }
681
+ ul ul,
682
+ ul ol,
683
+ ol ol,
684
+ ol ul {
685
+ margin-bottom: 0;
686
+ }
687
+ li {
688
+ line-height: 20px;
689
+ }
690
+ ul.unstyled,
691
+ ol.unstyled {
692
+ margin-left: 0;
693
+ list-style: none;
694
+ }
695
+ ul.inline,
696
+ ol.inline {
697
+ margin-left: 0;
698
+ list-style: none;
699
+ }
700
+ ul.inline > li,
701
+ ol.inline > li {
702
+ display: inline-block;
703
+ *display: inline;
704
+ /* IE7 inline-block hack */
705
+
706
+ *zoom: 1;
707
+ padding-left: 5px;
708
+ padding-right: 5px;
709
+ }
710
+ dl {
711
+ margin-bottom: 20px;
712
+ }
713
+ dt,
714
+ dd {
715
+ line-height: 20px;
716
+ }
717
+ dt {
718
+ font-weight: bold;
719
+ }
720
+ dd {
721
+ margin-left: 10px;
722
+ }
723
+ .dl-horizontal {
724
+ *zoom: 1;
725
+ }
726
+ .dl-horizontal:before,
727
+ .dl-horizontal:after {
728
+ display: table;
729
+ content: "";
730
+ line-height: 0;
731
+ }
732
+ .dl-horizontal:after {
733
+ clear: both;
734
+ }
735
+ .dl-horizontal dt {
736
+ float: left;
737
+ width: 160px;
738
+ clear: left;
739
+ text-align: right;
740
+ overflow: hidden;
741
+ text-overflow: ellipsis;
742
+ white-space: nowrap;
743
+ }
744
+ .dl-horizontal dd {
745
+ margin-left: 180px;
746
+ }
747
+ hr {
748
+ margin: 20px 0;
749
+ border: 0;
750
+ border-top: 1px solid #eeeeee;
751
+ border-bottom: 1px solid #ffffff;
752
+ }
753
+ abbr[title],
754
+ abbr[data-original-title] {
755
+ cursor: help;
756
+ border-bottom: 1px dotted #999999;
757
+ }
758
+ abbr.initialism {
759
+ font-size: 90%;
760
+ text-transform: uppercase;
761
+ }
762
+ blockquote {
763
+ padding: 0 0 0 15px;
764
+ margin: 0 0 20px;
765
+ border-left: 5px solid #eeeeee;
766
+ }
767
+ blockquote p {
768
+ margin-bottom: 0;
769
+ font-size: 17.5px;
770
+ font-weight: 300;
771
+ line-height: 1.25;
772
+ }
773
+ blockquote small {
774
+ display: block;
775
+ line-height: 20px;
776
+ color: #999999;
777
+ }
778
+ blockquote small:before {
779
+ content: '\2014 \00A0';
780
+ }
781
+ blockquote.pull-right {
782
+ float: right;
783
+ padding-right: 15px;
784
+ padding-left: 0;
785
+ border-right: 5px solid #eeeeee;
786
+ border-left: 0;
787
+ }
788
+ blockquote.pull-right p,
789
+ blockquote.pull-right small {
790
+ text-align: right;
791
+ }
792
+ blockquote.pull-right small:before {
793
+ content: '';
794
+ }
795
+ blockquote.pull-right small:after {
796
+ content: '\00A0 \2014';
797
+ }
798
+ q:before,
799
+ q:after,
800
+ blockquote:before,
801
+ blockquote:after {
802
+ content: "";
803
+ }
804
+ address {
805
+ display: block;
806
+ margin-bottom: 20px;
807
+ font-style: normal;
808
+ line-height: 20px;
809
+ }
810
+ code,
811
+ pre {
812
+ padding: 0 3px 2px;
813
+ font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
814
+ font-size: 12px;
815
+ color: #333333;
816
+ -webkit-border-radius: 3px;
817
+ -moz-border-radius: 3px;
818
+ border-radius: 3px;
819
+ }
820
+ code {
821
+ padding: 2px 4px;
822
+ color: #d14;
823
+ background-color: #f7f7f9;
824
+ border: 1px solid #e1e1e8;
825
+ white-space: nowrap;
826
+ }
827
+ pre {
828
+ display: block;
829
+ padding: 9.5px;
830
+ margin: 0 0 10px;
831
+ font-size: 13px;
832
+ line-height: 20px;
833
+ word-break: break-all;
834
+ word-wrap: break-word;
835
+ white-space: pre;
836
+ white-space: pre-wrap;
837
+ background-color: #f5f5f5;
838
+ border: 1px solid #ccc;
839
+ border: 1px solid rgba(0, 0, 0, 0.15);
840
+ -webkit-border-radius: 4px;
841
+ -moz-border-radius: 4px;
842
+ border-radius: 4px;
843
+ }
844
+ pre.prettyprint {
845
+ margin-bottom: 20px;
846
+ }
847
+ pre code {
848
+ padding: 0;
849
+ color: inherit;
850
+ white-space: pre;
851
+ white-space: pre-wrap;
852
+ background-color: transparent;
853
+ border: 0;
854
+ }
855
+ .pre-scrollable {
856
+ max-height: 340px;
857
+ overflow-y: scroll;
858
+ }
859
+ .label,
860
+ .badge {
861
+ display: inline-block;
862
+ padding: 2px 4px;
863
+ font-size: 11.844px;
864
+ font-weight: bold;
865
+ line-height: 14px;
866
+ color: #ffffff;
867
+ vertical-align: baseline;
868
+ white-space: nowrap;
869
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
870
+ background-color: #999999;
871
+ }
872
+ .label {
873
+ -webkit-border-radius: 3px;
874
+ -moz-border-radius: 3px;
875
+ border-radius: 3px;
876
+ }
877
+ .badge {
878
+ padding-left: 9px;
879
+ padding-right: 9px;
880
+ -webkit-border-radius: 9px;
881
+ -moz-border-radius: 9px;
882
+ border-radius: 9px;
883
+ }
884
+ .label:empty,
885
+ .badge:empty {
886
+ display: none;
887
+ }
888
+ a.label:hover,
889
+ a.label:focus,
890
+ a.badge:hover,
891
+ a.badge:focus {
892
+ color: #ffffff;
893
+ text-decoration: none;
894
+ cursor: pointer;
895
+ }
896
+ .label-important,
897
+ .badge-important {
898
+ background-color: #b94a48;
899
+ }
900
+ .label-important[href],
901
+ .badge-important[href] {
902
+ background-color: #953b39;
903
+ }
904
+ .label-warning,
905
+ .badge-warning {
906
+ background-color: #f89406;
907
+ }
908
+ .label-warning[href],
909
+ .badge-warning[href] {
910
+ background-color: #c67605;
911
+ }
912
+ .label-success,
913
+ .badge-success {
914
+ background-color: #468847;
915
+ }
916
+ .label-success[href],
917
+ .badge-success[href] {
918
+ background-color: #356635;
919
+ }
920
+ .label-info,
921
+ .badge-info {
922
+ background-color: #3a87ad;
923
+ }
924
+ .label-info[href],
925
+ .badge-info[href] {
926
+ background-color: #2d6987;
927
+ }
928
+ .label-inverse,
929
+ .badge-inverse {
930
+ background-color: #333333;
931
+ }
932
+ .label-inverse[href],
933
+ .badge-inverse[href] {
934
+ background-color: #1a1a1a;
935
+ }
936
+ .btn .label,
937
+ .btn .badge {
938
+ position: relative;
939
+ top: -1px;
940
+ }
941
+ .btn-mini .label,
942
+ .btn-mini .badge {
943
+ top: 0;
944
+ }
945
+ table {
946
+ max-width: 100%;
947
+ background-color: transparent;
948
+ border-collapse: collapse;
949
+ border-spacing: 0;
950
+ }
951
+ .table {
952
+ width: 100%;
953
+ margin-bottom: 20px;
954
+ }
955
+ .table th,
956
+ .table td {
957
+ padding: 8px;
958
+ line-height: 20px;
959
+ text-align: left;
960
+ vertical-align: top;
961
+ border-top: 1px solid #dddddd;
962
+ }
963
+ .table th {
964
+ font-weight: bold;
965
+ }
966
+ .table thead th {
967
+ vertical-align: bottom;
968
+ }
969
+ .table caption + thead tr:first-child th,
970
+ .table caption + thead tr:first-child td,
971
+ .table colgroup + thead tr:first-child th,
972
+ .table colgroup + thead tr:first-child td,
973
+ .table thead:first-child tr:first-child th,
974
+ .table thead:first-child tr:first-child td {
975
+ border-top: 0;
976
+ }
977
+ .table tbody + tbody {
978
+ border-top: 2px solid #dddddd;
979
+ }
980
+ .table .table {
981
+ background-color: #ffffff;
982
+ }
983
+ .table-condensed th,
984
+ .table-condensed td {
985
+ padding: 4px 5px;
986
+ }
987
+ .table-bordered {
988
+ border: 1px solid #dddddd;
989
+ border-collapse: separate;
990
+ *border-collapse: collapse;
991
+ border-left: 0;
992
+ -webkit-border-radius: 4px;
993
+ -moz-border-radius: 4px;
994
+ border-radius: 4px;
995
+ }
996
+ .table-bordered th,
997
+ .table-bordered td {
998
+ border-left: 1px solid #dddddd;
999
+ }
1000
+ .table-bordered caption + thead tr:first-child th,
1001
+ .table-bordered caption + tbody tr:first-child th,
1002
+ .table-bordered caption + tbody tr:first-child td,
1003
+ .table-bordered colgroup + thead tr:first-child th,
1004
+ .table-bordered colgroup + tbody tr:first-child th,
1005
+ .table-bordered colgroup + tbody tr:first-child td,
1006
+ .table-bordered thead:first-child tr:first-child th,
1007
+ .table-bordered tbody:first-child tr:first-child th,
1008
+ .table-bordered tbody:first-child tr:first-child td {
1009
+ border-top: 0;
1010
+ }
1011
+ .table-bordered thead:first-child tr:first-child > th:first-child,
1012
+ .table-bordered tbody:first-child tr:first-child > td:first-child,
1013
+ .table-bordered tbody:first-child tr:first-child > th:first-child {
1014
+ -webkit-border-top-left-radius: 4px;
1015
+ -moz-border-radius-topleft: 4px;
1016
+ border-top-left-radius: 4px;
1017
+ }
1018
+ .table-bordered thead:first-child tr:first-child > th:last-child,
1019
+ .table-bordered tbody:first-child tr:first-child > td:last-child,
1020
+ .table-bordered tbody:first-child tr:first-child > th:last-child {
1021
+ -webkit-border-top-right-radius: 4px;
1022
+ -moz-border-radius-topright: 4px;
1023
+ border-top-right-radius: 4px;
1024
+ }
1025
+ .table-bordered thead:last-child tr:last-child > th:first-child,
1026
+ .table-bordered tbody:last-child tr:last-child > td:first-child,
1027
+ .table-bordered tbody:last-child tr:last-child > th:first-child,
1028
+ .table-bordered tfoot:last-child tr:last-child > td:first-child,
1029
+ .table-bordered tfoot:last-child tr:last-child > th:first-child {
1030
+ -webkit-border-bottom-left-radius: 4px;
1031
+ -moz-border-radius-bottomleft: 4px;
1032
+ border-bottom-left-radius: 4px;
1033
+ }
1034
+ .table-bordered thead:last-child tr:last-child > th:last-child,
1035
+ .table-bordered tbody:last-child tr:last-child > td:last-child,
1036
+ .table-bordered tbody:last-child tr:last-child > th:last-child,
1037
+ .table-bordered tfoot:last-child tr:last-child > td:last-child,
1038
+ .table-bordered tfoot:last-child tr:last-child > th:last-child {
1039
+ -webkit-border-bottom-right-radius: 4px;
1040
+ -moz-border-radius-bottomright: 4px;
1041
+ border-bottom-right-radius: 4px;
1042
+ }
1043
+ .table-bordered tfoot + tbody:last-child tr:last-child td:first-child {
1044
+ -webkit-border-bottom-left-radius: 0;
1045
+ -moz-border-radius-bottomleft: 0;
1046
+ border-bottom-left-radius: 0;
1047
+ }
1048
+ .table-bordered tfoot + tbody:last-child tr:last-child td:last-child {
1049
+ -webkit-border-bottom-right-radius: 0;
1050
+ -moz-border-radius-bottomright: 0;
1051
+ border-bottom-right-radius: 0;
1052
+ }
1053
+ .table-bordered caption + thead tr:first-child th:first-child,
1054
+ .table-bordered caption + tbody tr:first-child td:first-child,
1055
+ .table-bordered colgroup + thead tr:first-child th:first-child,
1056
+ .table-bordered colgroup + tbody tr:first-child td:first-child {
1057
+ -webkit-border-top-left-radius: 4px;
1058
+ -moz-border-radius-topleft: 4px;
1059
+ border-top-left-radius: 4px;
1060
+ }
1061
+ .table-bordered caption + thead tr:first-child th:last-child,
1062
+ .table-bordered caption + tbody tr:first-child td:last-child,
1063
+ .table-bordered colgroup + thead tr:first-child th:last-child,
1064
+ .table-bordered colgroup + tbody tr:first-child td:last-child {
1065
+ -webkit-border-top-right-radius: 4px;
1066
+ -moz-border-radius-topright: 4px;
1067
+ border-top-right-radius: 4px;
1068
+ }
1069
+ .table-striped tbody > tr:nth-child(odd) > td,
1070
+ .table-striped tbody > tr:nth-child(odd) > th {
1071
+ background-color: #f9f9f9;
1072
+ }
1073
+ .table-hover tbody tr:hover > td,
1074
+ .table-hover tbody tr:hover > th {
1075
+ background-color: #f5f5f5;
1076
+ }
1077
+ table td[class*="span"],
1078
+ table th[class*="span"],
1079
+ .row-fluid table td[class*="span"],
1080
+ .row-fluid table th[class*="span"] {
1081
+ display: table-cell;
1082
+ float: none;
1083
+ margin-left: 0;
1084
+ }
1085
+ .table td.span1,
1086
+ .table th.span1 {
1087
+ float: none;
1088
+ width: 44px;
1089
+ margin-left: 0;
1090
+ }
1091
+ .table td.span2,
1092
+ .table th.span2 {
1093
+ float: none;
1094
+ width: 124px;
1095
+ margin-left: 0;
1096
+ }
1097
+ .table td.span3,
1098
+ .table th.span3 {
1099
+ float: none;
1100
+ width: 204px;
1101
+ margin-left: 0;
1102
+ }
1103
+ .table td.span4,
1104
+ .table th.span4 {
1105
+ float: none;
1106
+ width: 284px;
1107
+ margin-left: 0;
1108
+ }
1109
+ .table td.span5,
1110
+ .table th.span5 {
1111
+ float: none;
1112
+ width: 364px;
1113
+ margin-left: 0;
1114
+ }
1115
+ .table td.span6,
1116
+ .table th.span6 {
1117
+ float: none;
1118
+ width: 444px;
1119
+ margin-left: 0;
1120
+ }
1121
+ .table td.span7,
1122
+ .table th.span7 {
1123
+ float: none;
1124
+ width: 524px;
1125
+ margin-left: 0;
1126
+ }
1127
+ .table td.span8,
1128
+ .table th.span8 {
1129
+ float: none;
1130
+ width: 604px;
1131
+ margin-left: 0;
1132
+ }
1133
+ .table td.span9,
1134
+ .table th.span9 {
1135
+ float: none;
1136
+ width: 684px;
1137
+ margin-left: 0;
1138
+ }
1139
+ .table td.span10,
1140
+ .table th.span10 {
1141
+ float: none;
1142
+ width: 764px;
1143
+ margin-left: 0;
1144
+ }
1145
+ .table td.span11,
1146
+ .table th.span11 {
1147
+ float: none;
1148
+ width: 844px;
1149
+ margin-left: 0;
1150
+ }
1151
+ .table td.span12,
1152
+ .table th.span12 {
1153
+ float: none;
1154
+ width: 924px;
1155
+ margin-left: 0;
1156
+ }
1157
+ .table tbody tr.success > td {
1158
+ background-color: #dff0d8;
1159
+ }
1160
+ .table tbody tr.error > td {
1161
+ background-color: #f2dede;
1162
+ }
1163
+ .table tbody tr.warning > td {
1164
+ background-color: #fcf8e3;
1165
+ }
1166
+ .table tbody tr.info > td {
1167
+ background-color: #d9edf7;
1168
+ }
1169
+ .table-hover tbody tr.success:hover > td {
1170
+ background-color: #d0e9c6;
1171
+ }
1172
+ .table-hover tbody tr.error:hover > td {
1173
+ background-color: #ebcccc;
1174
+ }
1175
+ .table-hover tbody tr.warning:hover > td {
1176
+ background-color: #faf2cc;
1177
+ }
1178
+ .table-hover tbody tr.info:hover > td {
1179
+ background-color: #c4e3f3;
1180
+ }
1181
+ form {
1182
+ margin: 0 0 20px;
1183
+ }
1184
+ fieldset {
1185
+ padding: 0;
1186
+ margin: 0;
1187
+ border: 0;
1188
+ }
1189
+ legend {
1190
+ display: block;
1191
+ width: 100%;
1192
+ padding: 0;
1193
+ margin-bottom: 20px;
1194
+ font-size: 21px;
1195
+ line-height: 40px;
1196
+ color: #333333;
1197
+ border: 0;
1198
+ border-bottom: 1px solid #e5e5e5;
1199
+ }
1200
+ legend small {
1201
+ font-size: 15px;
1202
+ color: #999999;
1203
+ }
1204
+ label,
1205
+ input,
1206
+ button,
1207
+ select,
1208
+ textarea {
1209
+ font-size: 14px;
1210
+ font-weight: normal;
1211
+ line-height: 20px;
1212
+ }
1213
+ input,
1214
+ button,
1215
+ select,
1216
+ textarea {
1217
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
1218
+ }
1219
+ label {
1220
+ display: block;
1221
+ margin-bottom: 5px;
1222
+ }
1223
+ select,
1224
+ textarea,
1225
+ input[type="text"],
1226
+ input[type="password"],
1227
+ input[type="datetime"],
1228
+ input[type="datetime-local"],
1229
+ input[type="date"],
1230
+ input[type="month"],
1231
+ input[type="time"],
1232
+ input[type="week"],
1233
+ input[type="number"],
1234
+ input[type="email"],
1235
+ input[type="url"],
1236
+ input[type="search"],
1237
+ input[type="tel"],
1238
+ input[type="color"],
1239
+ .uneditable-input {
1240
+ display: inline-block;
1241
+ height: 20px;
1242
+ padding: 4px 6px;
1243
+ margin-bottom: 10px;
1244
+ font-size: 14px;
1245
+ line-height: 20px;
1246
+ color: #555555;
1247
+ -webkit-border-radius: 4px;
1248
+ -moz-border-radius: 4px;
1249
+ border-radius: 4px;
1250
+ vertical-align: middle;
1251
+ }
1252
+ input,
1253
+ textarea,
1254
+ .uneditable-input {
1255
+ width: 206px;
1256
+ }
1257
+ textarea {
1258
+ height: auto;
1259
+ }
1260
+ textarea,
1261
+ input[type="text"],
1262
+ input[type="password"],
1263
+ input[type="datetime"],
1264
+ input[type="datetime-local"],
1265
+ input[type="date"],
1266
+ input[type="month"],
1267
+ input[type="time"],
1268
+ input[type="week"],
1269
+ input[type="number"],
1270
+ input[type="email"],
1271
+ input[type="url"],
1272
+ input[type="search"],
1273
+ input[type="tel"],
1274
+ input[type="color"],
1275
+ .uneditable-input {
1276
+ background-color: #ffffff;
1277
+ border: 1px solid #cccccc;
1278
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1279
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1280
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1281
+ -webkit-transition: border linear .2s, box-shadow linear .2s;
1282
+ -moz-transition: border linear .2s, box-shadow linear .2s;
1283
+ -o-transition: border linear .2s, box-shadow linear .2s;
1284
+ transition: border linear .2s, box-shadow linear .2s;
1285
+ }
1286
+ textarea:focus,
1287
+ input[type="text"]:focus,
1288
+ input[type="password"]:focus,
1289
+ input[type="datetime"]:focus,
1290
+ input[type="datetime-local"]:focus,
1291
+ input[type="date"]:focus,
1292
+ input[type="month"]:focus,
1293
+ input[type="time"]:focus,
1294
+ input[type="week"]:focus,
1295
+ input[type="number"]:focus,
1296
+ input[type="email"]:focus,
1297
+ input[type="url"]:focus,
1298
+ input[type="search"]:focus,
1299
+ input[type="tel"]:focus,
1300
+ input[type="color"]:focus,
1301
+ .uneditable-input:focus {
1302
+ border-color: rgba(82, 168, 236, 0.8);
1303
+ outline: 0;
1304
+ outline: thin dotted \9;
1305
+ /* IE6-9 */
1306
+
1307
+ -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);
1308
+ -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);
1309
+ box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);
1310
+ }
1311
+ input[type="radio"],
1312
+ input[type="checkbox"] {
1313
+ margin: 4px 0 0;
1314
+ *margin-top: 0;
1315
+ /* IE7 */
1316
+
1317
+ margin-top: 1px \9;
1318
+ /* IE8-9 */
1319
+
1320
+ line-height: normal;
1321
+ }
1322
+ input[type="file"],
1323
+ input[type="image"],
1324
+ input[type="submit"],
1325
+ input[type="reset"],
1326
+ input[type="button"],
1327
+ input[type="radio"],
1328
+ input[type="checkbox"] {
1329
+ width: auto;
1330
+ }
1331
+ select,
1332
+ input[type="file"] {
1333
+ height: 30px;
1334
+ /* In IE7, the height of the select element cannot be changed by height, only font-size */
1335
+
1336
+ *margin-top: 4px;
1337
+ /* For IE7, add top margin to align select with labels */
1338
+
1339
+ line-height: 30px;
1340
+ }
1341
+ select {
1342
+ width: 220px;
1343
+ border: 1px solid #cccccc;
1344
+ background-color: #ffffff;
1345
+ }
1346
+ select[multiple],
1347
+ select[size] {
1348
+ height: auto;
1349
+ }
1350
+ select:focus,
1351
+ input[type="file"]:focus,
1352
+ input[type="radio"]:focus,
1353
+ input[type="checkbox"]:focus {
1354
+ outline: thin dotted #333;
1355
+ outline: 5px auto -webkit-focus-ring-color;
1356
+ outline-offset: -2px;
1357
+ }
1358
+ .uneditable-input,
1359
+ .uneditable-textarea {
1360
+ color: #999999;
1361
+ background-color: #fcfcfc;
1362
+ border-color: #cccccc;
1363
+ -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
1364
+ -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
1365
+ box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
1366
+ cursor: not-allowed;
1367
+ }
1368
+ .uneditable-input {
1369
+ overflow: hidden;
1370
+ white-space: nowrap;
1371
+ }
1372
+ .uneditable-textarea {
1373
+ width: auto;
1374
+ height: auto;
1375
+ }
1376
+ input:-moz-placeholder,
1377
+ textarea:-moz-placeholder {
1378
+ color: #999999;
1379
+ }
1380
+ input:-ms-input-placeholder,
1381
+ textarea:-ms-input-placeholder {
1382
+ color: #999999;
1383
+ }
1384
+ input::-webkit-input-placeholder,
1385
+ textarea::-webkit-input-placeholder {
1386
+ color: #999999;
1387
+ }
1388
+ .radio,
1389
+ .checkbox {
1390
+ min-height: 20px;
1391
+ padding-left: 20px;
1392
+ }
1393
+ .radio input[type="radio"],
1394
+ .checkbox input[type="checkbox"] {
1395
+ float: left;
1396
+ margin-left: -20px;
1397
+ }
1398
+ .controls > .radio:first-child,
1399
+ .controls > .checkbox:first-child {
1400
+ padding-top: 5px;
1401
+ }
1402
+ .radio.inline,
1403
+ .checkbox.inline {
1404
+ display: inline-block;
1405
+ padding-top: 5px;
1406
+ margin-bottom: 0;
1407
+ vertical-align: middle;
1408
+ }
1409
+ .radio.inline + .radio.inline,
1410
+ .checkbox.inline + .checkbox.inline {
1411
+ margin-left: 10px;
1412
+ }
1413
+ .input-mini {
1414
+ width: 60px;
1415
+ }
1416
+ .input-small {
1417
+ width: 90px;
1418
+ }
1419
+ .input-medium {
1420
+ width: 150px;
1421
+ }
1422
+ .input-large {
1423
+ width: 210px;
1424
+ }
1425
+ .input-xlarge {
1426
+ width: 270px;
1427
+ }
1428
+ .input-xxlarge {
1429
+ width: 530px;
1430
+ }
1431
+ input[class*="span"],
1432
+ select[class*="span"],
1433
+ textarea[class*="span"],
1434
+ .uneditable-input[class*="span"],
1435
+ .row-fluid input[class*="span"],
1436
+ .row-fluid select[class*="span"],
1437
+ .row-fluid textarea[class*="span"],
1438
+ .row-fluid .uneditable-input[class*="span"] {
1439
+ float: none;
1440
+ margin-left: 0;
1441
+ }
1442
+ .input-append input[class*="span"],
1443
+ .input-append .uneditable-input[class*="span"],
1444
+ .input-prepend input[class*="span"],
1445
+ .input-prepend .uneditable-input[class*="span"],
1446
+ .row-fluid input[class*="span"],
1447
+ .row-fluid select[class*="span"],
1448
+ .row-fluid textarea[class*="span"],
1449
+ .row-fluid .uneditable-input[class*="span"],
1450
+ .row-fluid .input-prepend [class*="span"],
1451
+ .row-fluid .input-append [class*="span"] {
1452
+ display: inline-block;
1453
+ }
1454
+ input,
1455
+ textarea,
1456
+ .uneditable-input {
1457
+ margin-left: 0;
1458
+ }
1459
+ .controls-row [class*="span"] + [class*="span"] {
1460
+ margin-left: 20px;
1461
+ }
1462
+ input.span12,
1463
+ textarea.span12,
1464
+ .uneditable-input.span12 {
1465
+ width: 926px;
1466
+ }
1467
+ input.span11,
1468
+ textarea.span11,
1469
+ .uneditable-input.span11 {
1470
+ width: 846px;
1471
+ }
1472
+ input.span10,
1473
+ textarea.span10,
1474
+ .uneditable-input.span10 {
1475
+ width: 766px;
1476
+ }
1477
+ input.span9,
1478
+ textarea.span9,
1479
+ .uneditable-input.span9 {
1480
+ width: 686px;
1481
+ }
1482
+ input.span8,
1483
+ textarea.span8,
1484
+ .uneditable-input.span8 {
1485
+ width: 606px;
1486
+ }
1487
+ input.span7,
1488
+ textarea.span7,
1489
+ .uneditable-input.span7 {
1490
+ width: 526px;
1491
+ }
1492
+ input.span6,
1493
+ textarea.span6,
1494
+ .uneditable-input.span6 {
1495
+ width: 446px;
1496
+ }
1497
+ input.span5,
1498
+ textarea.span5,
1499
+ .uneditable-input.span5 {
1500
+ width: 366px;
1501
+ }
1502
+ input.span4,
1503
+ textarea.span4,
1504
+ .uneditable-input.span4 {
1505
+ width: 286px;
1506
+ }
1507
+ input.span3,
1508
+ textarea.span3,
1509
+ .uneditable-input.span3 {
1510
+ width: 206px;
1511
+ }
1512
+ input.span2,
1513
+ textarea.span2,
1514
+ .uneditable-input.span2 {
1515
+ width: 126px;
1516
+ }
1517
+ input.span1,
1518
+ textarea.span1,
1519
+ .uneditable-input.span1 {
1520
+ width: 46px;
1521
+ }
1522
+ .controls-row {
1523
+ *zoom: 1;
1524
+ }
1525
+ .controls-row:before,
1526
+ .controls-row:after {
1527
+ display: table;
1528
+ content: "";
1529
+ line-height: 0;
1530
+ }
1531
+ .controls-row:after {
1532
+ clear: both;
1533
+ }
1534
+ .controls-row [class*="span"],
1535
+ .row-fluid .controls-row [class*="span"] {
1536
+ float: left;
1537
+ }
1538
+ .controls-row .checkbox[class*="span"],
1539
+ .controls-row .radio[class*="span"] {
1540
+ padding-top: 5px;
1541
+ }
1542
+ input[disabled],
1543
+ select[disabled],
1544
+ textarea[disabled],
1545
+ input[readonly],
1546
+ select[readonly],
1547
+ textarea[readonly] {
1548
+ cursor: not-allowed;
1549
+ background-color: #eeeeee;
1550
+ }
1551
+ input[type="radio"][disabled],
1552
+ input[type="checkbox"][disabled],
1553
+ input[type="radio"][readonly],
1554
+ input[type="checkbox"][readonly] {
1555
+ background-color: transparent;
1556
+ }
1557
+ .control-group.warning .control-label,
1558
+ .control-group.warning .help-block,
1559
+ .control-group.warning .help-inline {
1560
+ color: #c09853;
1561
+ }
1562
+ .control-group.warning .checkbox,
1563
+ .control-group.warning .radio,
1564
+ .control-group.warning input,
1565
+ .control-group.warning select,
1566
+ .control-group.warning textarea {
1567
+ color: #c09853;
1568
+ }
1569
+ .control-group.warning input,
1570
+ .control-group.warning select,
1571
+ .control-group.warning textarea {
1572
+ border-color: #c09853;
1573
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1574
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1575
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1576
+ }
1577
+ .control-group.warning input:focus,
1578
+ .control-group.warning select:focus,
1579
+ .control-group.warning textarea:focus {
1580
+ border-color: #a47e3c;
1581
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;
1582
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;
1583
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;
1584
+ }
1585
+ .control-group.warning .input-prepend .add-on,
1586
+ .control-group.warning .input-append .add-on {
1587
+ color: #c09853;
1588
+ background-color: #fcf8e3;
1589
+ border-color: #c09853;
1590
+ }
1591
+ .control-group.error .control-label,
1592
+ .control-group.error .help-block,
1593
+ .control-group.error .help-inline {
1594
+ color: #b94a48;
1595
+ }
1596
+ .control-group.error .checkbox,
1597
+ .control-group.error .radio,
1598
+ .control-group.error input,
1599
+ .control-group.error select,
1600
+ .control-group.error textarea {
1601
+ color: #b94a48;
1602
+ }
1603
+ .control-group.error input,
1604
+ .control-group.error select,
1605
+ .control-group.error textarea {
1606
+ border-color: #b94a48;
1607
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1608
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1609
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1610
+ }
1611
+ .control-group.error input:focus,
1612
+ .control-group.error select:focus,
1613
+ .control-group.error textarea:focus {
1614
+ border-color: #953b39;
1615
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;
1616
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;
1617
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;
1618
+ }
1619
+ .control-group.error .input-prepend .add-on,
1620
+ .control-group.error .input-append .add-on {
1621
+ color: #b94a48;
1622
+ background-color: #f2dede;
1623
+ border-color: #b94a48;
1624
+ }
1625
+ .control-group.success .control-label,
1626
+ .control-group.success .help-block,
1627
+ .control-group.success .help-inline {
1628
+ color: #468847;
1629
+ }
1630
+ .control-group.success .checkbox,
1631
+ .control-group.success .radio,
1632
+ .control-group.success input,
1633
+ .control-group.success select,
1634
+ .control-group.success textarea {
1635
+ color: #468847;
1636
+ }
1637
+ .control-group.success input,
1638
+ .control-group.success select,
1639
+ .control-group.success textarea {
1640
+ border-color: #468847;
1641
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1642
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1643
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1644
+ }
1645
+ .control-group.success input:focus,
1646
+ .control-group.success select:focus,
1647
+ .control-group.success textarea:focus {
1648
+ border-color: #356635;
1649
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;
1650
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;
1651
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;
1652
+ }
1653
+ .control-group.success .input-prepend .add-on,
1654
+ .control-group.success .input-append .add-on {
1655
+ color: #468847;
1656
+ background-color: #dff0d8;
1657
+ border-color: #468847;
1658
+ }
1659
+ .control-group.info .control-label,
1660
+ .control-group.info .help-block,
1661
+ .control-group.info .help-inline {
1662
+ color: #3a87ad;
1663
+ }
1664
+ .control-group.info .checkbox,
1665
+ .control-group.info .radio,
1666
+ .control-group.info input,
1667
+ .control-group.info select,
1668
+ .control-group.info textarea {
1669
+ color: #3a87ad;
1670
+ }
1671
+ .control-group.info input,
1672
+ .control-group.info select,
1673
+ .control-group.info textarea {
1674
+ border-color: #3a87ad;
1675
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1676
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1677
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1678
+ }
1679
+ .control-group.info input:focus,
1680
+ .control-group.info select:focus,
1681
+ .control-group.info textarea:focus {
1682
+ border-color: #2d6987;
1683
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;
1684
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;
1685
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;
1686
+ }
1687
+ .control-group.info .input-prepend .add-on,
1688
+ .control-group.info .input-append .add-on {
1689
+ color: #3a87ad;
1690
+ background-color: #d9edf7;
1691
+ border-color: #3a87ad;
1692
+ }
1693
+ input:focus:invalid,
1694
+ textarea:focus:invalid,
1695
+ select:focus:invalid {
1696
+ color: #b94a48;
1697
+ border-color: #ee5f5b;
1698
+ }
1699
+ input:focus:invalid:focus,
1700
+ textarea:focus:invalid:focus,
1701
+ select:focus:invalid:focus {
1702
+ border-color: #e9322d;
1703
+ -webkit-box-shadow: 0 0 6px #f8b9b7;
1704
+ -moz-box-shadow: 0 0 6px #f8b9b7;
1705
+ box-shadow: 0 0 6px #f8b9b7;
1706
+ }
1707
+ .form-actions {
1708
+ padding: 19px 20px 20px;
1709
+ margin-top: 20px;
1710
+ margin-bottom: 20px;
1711
+ background-color: #f5f5f5;
1712
+ border-top: 1px solid #e5e5e5;
1713
+ *zoom: 1;
1714
+ }
1715
+ .form-actions:before,
1716
+ .form-actions:after {
1717
+ display: table;
1718
+ content: "";
1719
+ line-height: 0;
1720
+ }
1721
+ .form-actions:after {
1722
+ clear: both;
1723
+ }
1724
+ .help-block,
1725
+ .help-inline {
1726
+ color: #595959;
1727
+ }
1728
+ .help-block {
1729
+ display: block;
1730
+ margin-bottom: 10px;
1731
+ }
1732
+ .help-inline {
1733
+ display: inline-block;
1734
+ *display: inline;
1735
+ /* IE7 inline-block hack */
1736
+
1737
+ *zoom: 1;
1738
+ vertical-align: middle;
1739
+ padding-left: 5px;
1740
+ }
1741
+ .input-append,
1742
+ .input-prepend {
1743
+ display: inline-block;
1744
+ margin-bottom: 10px;
1745
+ vertical-align: middle;
1746
+ font-size: 0;
1747
+ white-space: nowrap;
1748
+ }
1749
+ .input-append input,
1750
+ .input-prepend input,
1751
+ .input-append select,
1752
+ .input-prepend select,
1753
+ .input-append .uneditable-input,
1754
+ .input-prepend .uneditable-input,
1755
+ .input-append .dropdown-menu,
1756
+ .input-prepend .dropdown-menu,
1757
+ .input-append .popover,
1758
+ .input-prepend .popover {
1759
+ font-size: 14px;
1760
+ }
1761
+ .input-append input,
1762
+ .input-prepend input,
1763
+ .input-append select,
1764
+ .input-prepend select,
1765
+ .input-append .uneditable-input,
1766
+ .input-prepend .uneditable-input {
1767
+ position: relative;
1768
+ margin-bottom: 0;
1769
+ *margin-left: 0;
1770
+ vertical-align: top;
1771
+ -webkit-border-radius: 0 4px 4px 0;
1772
+ -moz-border-radius: 0 4px 4px 0;
1773
+ border-radius: 0 4px 4px 0;
1774
+ }
1775
+ .input-append input:focus,
1776
+ .input-prepend input:focus,
1777
+ .input-append select:focus,
1778
+ .input-prepend select:focus,
1779
+ .input-append .uneditable-input:focus,
1780
+ .input-prepend .uneditable-input:focus {
1781
+ z-index: 2;
1782
+ }
1783
+ .input-append .add-on,
1784
+ .input-prepend .add-on {
1785
+ display: inline-block;
1786
+ width: auto;
1787
+ height: 20px;
1788
+ min-width: 16px;
1789
+ padding: 4px 5px;
1790
+ font-size: 14px;
1791
+ font-weight: normal;
1792
+ line-height: 20px;
1793
+ text-align: center;
1794
+ text-shadow: 0 1px 0 #ffffff;
1795
+ background-color: #eeeeee;
1796
+ border: 1px solid #ccc;
1797
+ }
1798
+ .input-append .add-on,
1799
+ .input-prepend .add-on,
1800
+ .input-append .btn,
1801
+ .input-prepend .btn,
1802
+ .input-append .btn-group > .dropdown-toggle,
1803
+ .input-prepend .btn-group > .dropdown-toggle {
1804
+ vertical-align: top;
1805
+ -webkit-border-radius: 0;
1806
+ -moz-border-radius: 0;
1807
+ border-radius: 0;
1808
+ }
1809
+ .input-append .active,
1810
+ .input-prepend .active {
1811
+ background-color: #a9dba9;
1812
+ border-color: #46a546;
1813
+ }
1814
+ .input-prepend .add-on,
1815
+ .input-prepend .btn {
1816
+ margin-right: -1px;
1817
+ }
1818
+ .input-prepend .add-on:first-child,
1819
+ .input-prepend .btn:first-child {
1820
+ -webkit-border-radius: 4px 0 0 4px;
1821
+ -moz-border-radius: 4px 0 0 4px;
1822
+ border-radius: 4px 0 0 4px;
1823
+ }
1824
+ .input-append input,
1825
+ .input-append select,
1826
+ .input-append .uneditable-input {
1827
+ -webkit-border-radius: 4px 0 0 4px;
1828
+ -moz-border-radius: 4px 0 0 4px;
1829
+ border-radius: 4px 0 0 4px;
1830
+ }
1831
+ .input-append input + .btn-group .btn:last-child,
1832
+ .input-append select + .btn-group .btn:last-child,
1833
+ .input-append .uneditable-input + .btn-group .btn:last-child {
1834
+ -webkit-border-radius: 0 4px 4px 0;
1835
+ -moz-border-radius: 0 4px 4px 0;
1836
+ border-radius: 0 4px 4px 0;
1837
+ }
1838
+ .input-append .add-on,
1839
+ .input-append .btn,
1840
+ .input-append .btn-group {
1841
+ margin-left: -1px;
1842
+ }
1843
+ .input-append .add-on:last-child,
1844
+ .input-append .btn:last-child,
1845
+ .input-append .btn-group:last-child > .dropdown-toggle {
1846
+ -webkit-border-radius: 0 4px 4px 0;
1847
+ -moz-border-radius: 0 4px 4px 0;
1848
+ border-radius: 0 4px 4px 0;
1849
+ }
1850
+ .input-prepend.input-append input,
1851
+ .input-prepend.input-append select,
1852
+ .input-prepend.input-append .uneditable-input {
1853
+ -webkit-border-radius: 0;
1854
+ -moz-border-radius: 0;
1855
+ border-radius: 0;
1856
+ }
1857
+ .input-prepend.input-append input + .btn-group .btn,
1858
+ .input-prepend.input-append select + .btn-group .btn,
1859
+ .input-prepend.input-append .uneditable-input + .btn-group .btn {
1860
+ -webkit-border-radius: 0 4px 4px 0;
1861
+ -moz-border-radius: 0 4px 4px 0;
1862
+ border-radius: 0 4px 4px 0;
1863
+ }
1864
+ .input-prepend.input-append .add-on:first-child,
1865
+ .input-prepend.input-append .btn:first-child {
1866
+ margin-right: -1px;
1867
+ -webkit-border-radius: 4px 0 0 4px;
1868
+ -moz-border-radius: 4px 0 0 4px;
1869
+ border-radius: 4px 0 0 4px;
1870
+ }
1871
+ .input-prepend.input-append .add-on:last-child,
1872
+ .input-prepend.input-append .btn:last-child {
1873
+ margin-left: -1px;
1874
+ -webkit-border-radius: 0 4px 4px 0;
1875
+ -moz-border-radius: 0 4px 4px 0;
1876
+ border-radius: 0 4px 4px 0;
1877
+ }
1878
+ .input-prepend.input-append .btn-group:first-child {
1879
+ margin-left: 0;
1880
+ }
1881
+ input.search-query {
1882
+ padding-right: 14px;
1883
+ padding-right: 4px \9;
1884
+ padding-left: 14px;
1885
+ padding-left: 4px \9;
1886
+ /* IE7-8 doesn't have border-radius, so don't indent the padding */
1887
+
1888
+ margin-bottom: 0;
1889
+ -webkit-border-radius: 15px;
1890
+ -moz-border-radius: 15px;
1891
+ border-radius: 15px;
1892
+ }
1893
+ /* Allow for input prepend/append in search forms */
1894
+ .form-search .input-append .search-query,
1895
+ .form-search .input-prepend .search-query {
1896
+ -webkit-border-radius: 0;
1897
+ -moz-border-radius: 0;
1898
+ border-radius: 0;
1899
+ }
1900
+ .form-search .input-append .search-query {
1901
+ -webkit-border-radius: 14px 0 0 14px;
1902
+ -moz-border-radius: 14px 0 0 14px;
1903
+ border-radius: 14px 0 0 14px;
1904
+ }
1905
+ .form-search .input-append .btn {
1906
+ -webkit-border-radius: 0 14px 14px 0;
1907
+ -moz-border-radius: 0 14px 14px 0;
1908
+ border-radius: 0 14px 14px 0;
1909
+ }
1910
+ .form-search .input-prepend .search-query {
1911
+ -webkit-border-radius: 0 14px 14px 0;
1912
+ -moz-border-radius: 0 14px 14px 0;
1913
+ border-radius: 0 14px 14px 0;
1914
+ }
1915
+ .form-search .input-prepend .btn {
1916
+ -webkit-border-radius: 14px 0 0 14px;
1917
+ -moz-border-radius: 14px 0 0 14px;
1918
+ border-radius: 14px 0 0 14px;
1919
+ }
1920
+ .form-search input,
1921
+ .form-inline input,
1922
+ .form-horizontal input,
1923
+ .form-search textarea,
1924
+ .form-inline textarea,
1925
+ .form-horizontal textarea,
1926
+ .form-search select,
1927
+ .form-inline select,
1928
+ .form-horizontal select,
1929
+ .form-search .help-inline,
1930
+ .form-inline .help-inline,
1931
+ .form-horizontal .help-inline,
1932
+ .form-search .uneditable-input,
1933
+ .form-inline .uneditable-input,
1934
+ .form-horizontal .uneditable-input,
1935
+ .form-search .input-prepend,
1936
+ .form-inline .input-prepend,
1937
+ .form-horizontal .input-prepend,
1938
+ .form-search .input-append,
1939
+ .form-inline .input-append,
1940
+ .form-horizontal .input-append {
1941
+ display: inline-block;
1942
+ *display: inline;
1943
+ /* IE7 inline-block hack */
1944
+
1945
+ *zoom: 1;
1946
+ margin-bottom: 0;
1947
+ vertical-align: middle;
1948
+ }
1949
+ .form-search .hide,
1950
+ .form-inline .hide,
1951
+ .form-horizontal .hide {
1952
+ display: none;
1953
+ }
1954
+ .form-search label,
1955
+ .form-inline label,
1956
+ .form-search .btn-group,
1957
+ .form-inline .btn-group {
1958
+ display: inline-block;
1959
+ }
1960
+ .form-search .input-append,
1961
+ .form-inline .input-append,
1962
+ .form-search .input-prepend,
1963
+ .form-inline .input-prepend {
1964
+ margin-bottom: 0;
1965
+ }
1966
+ .form-search .radio,
1967
+ .form-search .checkbox,
1968
+ .form-inline .radio,
1969
+ .form-inline .checkbox {
1970
+ padding-left: 0;
1971
+ margin-bottom: 0;
1972
+ vertical-align: middle;
1973
+ }
1974
+ .form-search .radio input[type="radio"],
1975
+ .form-search .checkbox input[type="checkbox"],
1976
+ .form-inline .radio input[type="radio"],
1977
+ .form-inline .checkbox input[type="checkbox"] {
1978
+ float: left;
1979
+ margin-right: 3px;
1980
+ margin-left: 0;
1981
+ }
1982
+ .control-group {
1983
+ margin-bottom: 10px;
1984
+ }
1985
+ legend + .control-group {
1986
+ margin-top: 20px;
1987
+ -webkit-margin-top-collapse: separate;
1988
+ }
1989
+ .form-horizontal .control-group {
1990
+ margin-bottom: 20px;
1991
+ *zoom: 1;
1992
+ }
1993
+ .form-horizontal .control-group:before,
1994
+ .form-horizontal .control-group:after {
1995
+ display: table;
1996
+ content: "";
1997
+ line-height: 0;
1998
+ }
1999
+ .form-horizontal .control-group:after {
2000
+ clear: both;
2001
+ }
2002
+ .form-horizontal .control-label {
2003
+ float: left;
2004
+ width: 160px;
2005
+ padding-top: 5px;
2006
+ text-align: right;
2007
+ }
2008
+ .form-horizontal .controls {
2009
+ *display: inline-block;
2010
+ *padding-left: 20px;
2011
+ margin-left: 180px;
2012
+ *margin-left: 0;
2013
+ }
2014
+ .form-horizontal .controls:first-child {
2015
+ *padding-left: 180px;
2016
+ }
2017
+ .form-horizontal .help-block {
2018
+ margin-bottom: 0;
2019
+ }
2020
+ .form-horizontal input + .help-block,
2021
+ .form-horizontal select + .help-block,
2022
+ .form-horizontal textarea + .help-block,
2023
+ .form-horizontal .uneditable-input + .help-block,
2024
+ .form-horizontal .input-prepend + .help-block,
2025
+ .form-horizontal .input-append + .help-block {
2026
+ margin-top: 10px;
2027
+ }
2028
+ .form-horizontal .form-actions {
2029
+ padding-left: 180px;
2030
+ }
2031
+ .btn {
2032
+ display: inline-block;
2033
+ *display: inline;
2034
+ /* IE7 inline-block hack */
2035
+
2036
+ *zoom: 1;
2037
+ padding: 4px 12px;
2038
+ margin-bottom: 0;
2039
+ font-size: 14px;
2040
+ line-height: 20px;
2041
+ text-align: center;
2042
+ vertical-align: middle;
2043
+ cursor: pointer;
2044
+ color: #333333;
2045
+ text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
2046
+ background-color: #f5f5f5;
2047
+ background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);
2048
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));
2049
+ background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);
2050
+ background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);
2051
+ background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);
2052
+ background-repeat: repeat-x;
2053
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);
2054
+ border-color: #e6e6e6 #e6e6e6 #bfbfbf;
2055
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
2056
+ *background-color: #e6e6e6;
2057
+ /* Darken IE7 buttons by default so they stand out more given they won't have borders */
2058
+
2059
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
2060
+ border: 1px solid #cccccc;
2061
+ *border: 0;
2062
+ border-bottom-color: #b3b3b3;
2063
+ -webkit-border-radius: 4px;
2064
+ -moz-border-radius: 4px;
2065
+ border-radius: 4px;
2066
+ *margin-left: .3em;
2067
+ -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
2068
+ -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
2069
+ box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
2070
+ }
2071
+ .btn:hover,
2072
+ .btn:focus,
2073
+ .btn:active,
2074
+ .btn.active,
2075
+ .btn.disabled,
2076
+ .btn[disabled] {
2077
+ color: #333333;
2078
+ background-color: #e6e6e6;
2079
+ *background-color: #d9d9d9;
2080
+ }
2081
+ .btn:active,
2082
+ .btn.active {
2083
+ background-color: #cccccc \9;
2084
+ }
2085
+ .btn:first-child {
2086
+ *margin-left: 0;
2087
+ }
2088
+ .btn:hover,
2089
+ .btn:focus {
2090
+ color: #333333;
2091
+ text-decoration: none;
2092
+ background-position: 0 -15px;
2093
+ -webkit-transition: background-position 0.1s linear;
2094
+ -moz-transition: background-position 0.1s linear;
2095
+ -o-transition: background-position 0.1s linear;
2096
+ transition: background-position 0.1s linear;
2097
+ }
2098
+ .btn:focus {
2099
+ outline: thin dotted #333;
2100
+ outline: 5px auto -webkit-focus-ring-color;
2101
+ outline-offset: -2px;
2102
+ }
2103
+ .btn.active,
2104
+ .btn:active {
2105
+ background-image: none;
2106
+ outline: 0;
2107
+ -webkit-box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);
2108
+ -moz-box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);
2109
+ box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);
2110
+ }
2111
+ .btn.disabled,
2112
+ .btn[disabled] {
2113
+ cursor: default;
2114
+ background-image: none;
2115
+ opacity: 0.65;
2116
+ filter: alpha(opacity=65);
2117
+ -webkit-box-shadow: none;
2118
+ -moz-box-shadow: none;
2119
+ box-shadow: none;
2120
+ }
2121
+ .btn-large {
2122
+ padding: 11px 19px;
2123
+ font-size: 17.5px;
2124
+ -webkit-border-radius: 6px;
2125
+ -moz-border-radius: 6px;
2126
+ border-radius: 6px;
2127
+ }
2128
+ .btn-large [class^="icon-"],
2129
+ .btn-large [class*=" icon-"] {
2130
+ margin-top: 4px;
2131
+ }
2132
+ .btn-small {
2133
+ padding: 2px 10px;
2134
+ font-size: 11.9px;
2135
+ -webkit-border-radius: 3px;
2136
+ -moz-border-radius: 3px;
2137
+ border-radius: 3px;
2138
+ }
2139
+ .btn-small [class^="icon-"],
2140
+ .btn-small [class*=" icon-"] {
2141
+ margin-top: 0;
2142
+ }
2143
+ .btn-mini [class^="icon-"],
2144
+ .btn-mini [class*=" icon-"] {
2145
+ margin-top: -1px;
2146
+ }
2147
+ .btn-mini {
2148
+ padding: 0 6px;
2149
+ font-size: 10.5px;
2150
+ -webkit-border-radius: 3px;
2151
+ -moz-border-radius: 3px;
2152
+ border-radius: 3px;
2153
+ }
2154
+ .btn-block {
2155
+ display: block;
2156
+ width: 100%;
2157
+ padding-left: 0;
2158
+ padding-right: 0;
2159
+ -webkit-box-sizing: border-box;
2160
+ -moz-box-sizing: border-box;
2161
+ box-sizing: border-box;
2162
+ }
2163
+ .btn-block + .btn-block {
2164
+ margin-top: 5px;
2165
+ }
2166
+ input[type="submit"].btn-block,
2167
+ input[type="reset"].btn-block,
2168
+ input[type="button"].btn-block {
2169
+ width: 100%;
2170
+ }
2171
+ .btn-primary.active,
2172
+ .btn-warning.active,
2173
+ .btn-danger.active,
2174
+ .btn-success.active,
2175
+ .btn-info.active,
2176
+ .btn-inverse.active {
2177
+ color: rgba(255, 255, 255, 0.75);
2178
+ }
2179
+ .btn-primary {
2180
+ color: #ffffff;
2181
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
2182
+ background-color: #006dcc;
2183
+ background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
2184
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
2185
+ background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
2186
+ background-image: -o-linear-gradient(top, #0088cc, #0044cc);
2187
+ background-image: linear-gradient(to bottom, #0088cc, #0044cc);
2188
+ background-repeat: repeat-x;
2189
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);
2190
+ border-color: #0044cc #0044cc #002a80;
2191
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
2192
+ *background-color: #0044cc;
2193
+ /* Darken IE7 buttons by default so they stand out more given they won't have borders */
2194
+
2195
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
2196
+ }
2197
+ .btn-primary:hover,
2198
+ .btn-primary:focus,
2199
+ .btn-primary:active,
2200
+ .btn-primary.active,
2201
+ .btn-primary.disabled,
2202
+ .btn-primary[disabled] {
2203
+ color: #ffffff;
2204
+ background-color: #0044cc;
2205
+ *background-color: #003bb3;
2206
+ }
2207
+ .btn-primary:active,
2208
+ .btn-primary.active {
2209
+ background-color: #003399 \9;
2210
+ }
2211
+ .btn-warning {
2212
+ color: #ffffff;
2213
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
2214
+ background-color: #faa732;
2215
+ background-image: -moz-linear-gradient(top, #fbb450, #f89406);
2216
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));
2217
+ background-image: -webkit-linear-gradient(top, #fbb450, #f89406);
2218
+ background-image: -o-linear-gradient(top, #fbb450, #f89406);
2219
+ background-image: linear-gradient(to bottom, #fbb450, #f89406);
2220
+ background-repeat: repeat-x;
2221
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);
2222
+ border-color: #f89406 #f89406 #ad6704;
2223
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
2224
+ *background-color: #f89406;
2225
+ /* Darken IE7 buttons by default so they stand out more given they won't have borders */
2226
+
2227
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
2228
+ }
2229
+ .btn-warning:hover,
2230
+ .btn-warning:focus,
2231
+ .btn-warning:active,
2232
+ .btn-warning.active,
2233
+ .btn-warning.disabled,
2234
+ .btn-warning[disabled] {
2235
+ color: #ffffff;
2236
+ background-color: #f89406;
2237
+ *background-color: #df8505;
2238
+ }
2239
+ .btn-warning:active,
2240
+ .btn-warning.active {
2241
+ background-color: #c67605 \9;
2242
+ }
2243
+ .btn-danger {
2244
+ color: #ffffff;
2245
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
2246
+ background-color: #da4f49;
2247
+ background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);
2248
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));
2249
+ background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);
2250
+ background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);
2251
+ background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);
2252
+ background-repeat: repeat-x;
2253
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);
2254
+ border-color: #bd362f #bd362f #802420;
2255
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
2256
+ *background-color: #bd362f;
2257
+ /* Darken IE7 buttons by default so they stand out more given they won't have borders */
2258
+
2259
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
2260
+ }
2261
+ .btn-danger:hover,
2262
+ .btn-danger:focus,
2263
+ .btn-danger:active,
2264
+ .btn-danger.active,
2265
+ .btn-danger.disabled,
2266
+ .btn-danger[disabled] {
2267
+ color: #ffffff;
2268
+ background-color: #bd362f;
2269
+ *background-color: #a9302a;
2270
+ }
2271
+ .btn-danger:active,
2272
+ .btn-danger.active {
2273
+ background-color: #942a25 \9;
2274
+ }
2275
+ .btn-success {
2276
+ color: #ffffff;
2277
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
2278
+ background-color: #5bb75b;
2279
+ background-image: -moz-linear-gradient(top, #62c462, #51a351);
2280
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));
2281
+ background-image: -webkit-linear-gradient(top, #62c462, #51a351);
2282
+ background-image: -o-linear-gradient(top, #62c462, #51a351);
2283
+ background-image: linear-gradient(to bottom, #62c462, #51a351);
2284
+ background-repeat: repeat-x;
2285
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);
2286
+ border-color: #51a351 #51a351 #387038;
2287
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
2288
+ *background-color: #51a351;
2289
+ /* Darken IE7 buttons by default so they stand out more given they won't have borders */
2290
+
2291
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
2292
+ }
2293
+ .btn-success:hover,
2294
+ .btn-success:focus,
2295
+ .btn-success:active,
2296
+ .btn-success.active,
2297
+ .btn-success.disabled,
2298
+ .btn-success[disabled] {
2299
+ color: #ffffff;
2300
+ background-color: #51a351;
2301
+ *background-color: #499249;
2302
+ }
2303
+ .btn-success:active,
2304
+ .btn-success.active {
2305
+ background-color: #408140 \9;
2306
+ }
2307
+ .btn-info {
2308
+ color: #ffffff;
2309
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
2310
+ background-color: #49afcd;
2311
+ background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);
2312
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));
2313
+ background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);
2314
+ background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);
2315
+ background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);
2316
+ background-repeat: repeat-x;
2317
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);
2318
+ border-color: #2f96b4 #2f96b4 #1f6377;
2319
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
2320
+ *background-color: #2f96b4;
2321
+ /* Darken IE7 buttons by default so they stand out more given they won't have borders */
2322
+
2323
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
2324
+ }
2325
+ .btn-info:hover,
2326
+ .btn-info:focus,
2327
+ .btn-info:active,
2328
+ .btn-info.active,
2329
+ .btn-info.disabled,
2330
+ .btn-info[disabled] {
2331
+ color: #ffffff;
2332
+ background-color: #2f96b4;
2333
+ *background-color: #2a85a0;
2334
+ }
2335
+ .btn-info:active,
2336
+ .btn-info.active {
2337
+ background-color: #24748c \9;
2338
+ }
2339
+ .btn-inverse {
2340
+ color: #ffffff;
2341
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
2342
+ background-color: #363636;
2343
+ background-image: -moz-linear-gradient(top, #444444, #222222);
2344
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));
2345
+ background-image: -webkit-linear-gradient(top, #444444, #222222);
2346
+ background-image: -o-linear-gradient(top, #444444, #222222);
2347
+ background-image: linear-gradient(to bottom, #444444, #222222);
2348
+ background-repeat: repeat-x;
2349
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);
2350
+ border-color: #222222 #222222 #000000;
2351
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
2352
+ *background-color: #222222;
2353
+ /* Darken IE7 buttons by default so they stand out more given they won't have borders */
2354
+
2355
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
2356
+ }
2357
+ .btn-inverse:hover,
2358
+ .btn-inverse:focus,
2359
+ .btn-inverse:active,
2360
+ .btn-inverse.active,
2361
+ .btn-inverse.disabled,
2362
+ .btn-inverse[disabled] {
2363
+ color: #ffffff;
2364
+ background-color: #222222;
2365
+ *background-color: #151515;
2366
+ }
2367
+ .btn-inverse:active,
2368
+ .btn-inverse.active {
2369
+ background-color: #080808 \9;
2370
+ }
2371
+ button.btn,
2372
+ input[type="submit"].btn {
2373
+ *padding-top: 3px;
2374
+ *padding-bottom: 3px;
2375
+ }
2376
+ button.btn::-moz-focus-inner,
2377
+ input[type="submit"].btn::-moz-focus-inner {
2378
+ padding: 0;
2379
+ border: 0;
2380
+ }
2381
+ button.btn.btn-large,
2382
+ input[type="submit"].btn.btn-large {
2383
+ *padding-top: 7px;
2384
+ *padding-bottom: 7px;
2385
+ }
2386
+ button.btn.btn-small,
2387
+ input[type="submit"].btn.btn-small {
2388
+ *padding-top: 3px;
2389
+ *padding-bottom: 3px;
2390
+ }
2391
+ button.btn.btn-mini,
2392
+ input[type="submit"].btn.btn-mini {
2393
+ *padding-top: 1px;
2394
+ *padding-bottom: 1px;
2395
+ }
2396
+ .btn-link,
2397
+ .btn-link:active,
2398
+ .btn-link[disabled] {
2399
+ background-color: transparent;
2400
+ background-image: none;
2401
+ -webkit-box-shadow: none;
2402
+ -moz-box-shadow: none;
2403
+ box-shadow: none;
2404
+ }
2405
+ .btn-link {
2406
+ border-color: transparent;
2407
+ cursor: pointer;
2408
+ color: #0088cc;
2409
+ -webkit-border-radius: 0;
2410
+ -moz-border-radius: 0;
2411
+ border-radius: 0;
2412
+ }
2413
+ .btn-link:hover,
2414
+ .btn-link:focus {
2415
+ color: #005580;
2416
+ text-decoration: underline;
2417
+ background-color: transparent;
2418
+ }
2419
+ .btn-link[disabled]:hover,
2420
+ .btn-link[disabled]:focus {
2421
+ color: #333333;
2422
+ text-decoration: none;
2423
+ }
2424
+ [class^="icon-"],
2425
+ [class*=" icon-"] {
2426
+ display: inline-block;
2427
+ width: 14px;
2428
+ height: 14px;
2429
+ *margin-right: .3em;
2430
+ line-height: 14px;
2431
+ vertical-align: text-top;
2432
+ background-image: url("../img/glyphicons-halflings.png");
2433
+ background-position: 14px 14px;
2434
+ background-repeat: no-repeat;
2435
+ margin-top: 1px;
2436
+ }
2437
+ /* White icons with optional class, or on hover/focus/active states of certain elements */
2438
+ .icon-white,
2439
+ .nav-pills > .active > a > [class^="icon-"],
2440
+ .nav-pills > .active > a > [class*=" icon-"],
2441
+ .nav-list > .active > a > [class^="icon-"],
2442
+ .nav-list > .active > a > [class*=" icon-"],
2443
+ .navbar-inverse .nav > .active > a > [class^="icon-"],
2444
+ .navbar-inverse .nav > .active > a > [class*=" icon-"],
2445
+ .dropdown-menu > li > a:hover > [class^="icon-"],
2446
+ .dropdown-menu > li > a:focus > [class^="icon-"],
2447
+ .dropdown-menu > li > a:hover > [class*=" icon-"],
2448
+ .dropdown-menu > li > a:focus > [class*=" icon-"],
2449
+ .dropdown-menu > .active > a > [class^="icon-"],
2450
+ .dropdown-menu > .active > a > [class*=" icon-"],
2451
+ .dropdown-submenu:hover > a > [class^="icon-"],
2452
+ .dropdown-submenu:focus > a > [class^="icon-"],
2453
+ .dropdown-submenu:hover > a > [class*=" icon-"],
2454
+ .dropdown-submenu:focus > a > [class*=" icon-"] {
2455
+ background-image: url("../img/glyphicons-halflings-white.png");
2456
+ }
2457
+ .icon-glass {
2458
+ background-position: 0 0;
2459
+ }
2460
+ .icon-music {
2461
+ background-position: -24px 0;
2462
+ }
2463
+ .icon-search {
2464
+ background-position: -48px 0;
2465
+ }
2466
+ .icon-envelope {
2467
+ background-position: -72px 0;
2468
+ }
2469
+ .icon-heart {
2470
+ background-position: -96px 0;
2471
+ }
2472
+ .icon-star {
2473
+ background-position: -120px 0;
2474
+ }
2475
+ .icon-star-empty {
2476
+ background-position: -144px 0;
2477
+ }
2478
+ .icon-user {
2479
+ background-position: -168px 0;
2480
+ }
2481
+ .icon-film {
2482
+ background-position: -192px 0;
2483
+ }
2484
+ .icon-th-large {
2485
+ background-position: -216px 0;
2486
+ }
2487
+ .icon-th {
2488
+ background-position: -240px 0;
2489
+ }
2490
+ .icon-th-list {
2491
+ background-position: -264px 0;
2492
+ }
2493
+ .icon-ok {
2494
+ background-position: -288px 0;
2495
+ }
2496
+ .icon-remove {
2497
+ background-position: -312px 0;
2498
+ }
2499
+ .icon-zoom-in {
2500
+ background-position: -336px 0;
2501
+ }
2502
+ .icon-zoom-out {
2503
+ background-position: -360px 0;
2504
+ }
2505
+ .icon-off {
2506
+ background-position: -384px 0;
2507
+ }
2508
+ .icon-signal {
2509
+ background-position: -408px 0;
2510
+ }
2511
+ .icon-cog {
2512
+ background-position: -432px 0;
2513
+ }
2514
+ .icon-trash {
2515
+ background-position: -456px 0;
2516
+ }
2517
+ .icon-home {
2518
+ background-position: 0 -24px;
2519
+ }
2520
+ .icon-file {
2521
+ background-position: -24px -24px;
2522
+ }
2523
+ .icon-time {
2524
+ background-position: -48px -24px;
2525
+ }
2526
+ .icon-road {
2527
+ background-position: -72px -24px;
2528
+ }
2529
+ .icon-download-alt {
2530
+ background-position: -96px -24px;
2531
+ }
2532
+ .icon-download {
2533
+ background-position: -120px -24px;
2534
+ }
2535
+ .icon-upload {
2536
+ background-position: -144px -24px;
2537
+ }
2538
+ .icon-inbox {
2539
+ background-position: -168px -24px;
2540
+ }
2541
+ .icon-play-circle {
2542
+ background-position: -192px -24px;
2543
+ }
2544
+ .icon-repeat {
2545
+ background-position: -216px -24px;
2546
+ }
2547
+ .icon-refresh {
2548
+ background-position: -240px -24px;
2549
+ }
2550
+ .icon-list-alt {
2551
+ background-position: -264px -24px;
2552
+ }
2553
+ .icon-lock {
2554
+ background-position: -287px -24px;
2555
+ }
2556
+ .icon-flag {
2557
+ background-position: -312px -24px;
2558
+ }
2559
+ .icon-headphones {
2560
+ background-position: -336px -24px;
2561
+ }
2562
+ .icon-volume-off {
2563
+ background-position: -360px -24px;
2564
+ }
2565
+ .icon-volume-down {
2566
+ background-position: -384px -24px;
2567
+ }
2568
+ .icon-volume-up {
2569
+ background-position: -408px -24px;
2570
+ }
2571
+ .icon-qrcode {
2572
+ background-position: -432px -24px;
2573
+ }
2574
+ .icon-barcode {
2575
+ background-position: -456px -24px;
2576
+ }
2577
+ .icon-tag {
2578
+ background-position: 0 -48px;
2579
+ }
2580
+ .icon-tags {
2581
+ background-position: -25px -48px;
2582
+ }
2583
+ .icon-book {
2584
+ background-position: -48px -48px;
2585
+ }
2586
+ .icon-bookmark {
2587
+ background-position: -72px -48px;
2588
+ }
2589
+ .icon-print {
2590
+ background-position: -96px -48px;
2591
+ }
2592
+ .icon-camera {
2593
+ background-position: -120px -48px;
2594
+ }
2595
+ .icon-font {
2596
+ background-position: -144px -48px;
2597
+ }
2598
+ .icon-bold {
2599
+ background-position: -167px -48px;
2600
+ }
2601
+ .icon-italic {
2602
+ background-position: -192px -48px;
2603
+ }
2604
+ .icon-text-height {
2605
+ background-position: -216px -48px;
2606
+ }
2607
+ .icon-text-width {
2608
+ background-position: -240px -48px;
2609
+ }
2610
+ .icon-align-left {
2611
+ background-position: -264px -48px;
2612
+ }
2613
+ .icon-align-center {
2614
+ background-position: -288px -48px;
2615
+ }
2616
+ .icon-align-right {
2617
+ background-position: -312px -48px;
2618
+ }
2619
+ .icon-align-justify {
2620
+ background-position: -336px -48px;
2621
+ }
2622
+ .icon-list {
2623
+ background-position: -360px -48px;
2624
+ }
2625
+ .icon-indent-left {
2626
+ background-position: -384px -48px;
2627
+ }
2628
+ .icon-indent-right {
2629
+ background-position: -408px -48px;
2630
+ }
2631
+ .icon-facetime-video {
2632
+ background-position: -432px -48px;
2633
+ }
2634
+ .icon-picture {
2635
+ background-position: -456px -48px;
2636
+ }
2637
+ .icon-pencil {
2638
+ background-position: 0 -72px;
2639
+ }
2640
+ .icon-map-marker {
2641
+ background-position: -24px -72px;
2642
+ }
2643
+ .icon-adjust {
2644
+ background-position: -48px -72px;
2645
+ }
2646
+ .icon-tint {
2647
+ background-position: -72px -72px;
2648
+ }
2649
+ .icon-edit {
2650
+ background-position: -96px -72px;
2651
+ }
2652
+ .icon-share {
2653
+ background-position: -120px -72px;
2654
+ }
2655
+ .icon-check {
2656
+ background-position: -144px -72px;
2657
+ }
2658
+ .icon-move {
2659
+ background-position: -168px -72px;
2660
+ }
2661
+ .icon-step-backward {
2662
+ background-position: -192px -72px;
2663
+ }
2664
+ .icon-fast-backward {
2665
+ background-position: -216px -72px;
2666
+ }
2667
+ .icon-backward {
2668
+ background-position: -240px -72px;
2669
+ }
2670
+ .icon-play {
2671
+ background-position: -264px -72px;
2672
+ }
2673
+ .icon-pause {
2674
+ background-position: -288px -72px;
2675
+ }
2676
+ .icon-stop {
2677
+ background-position: -312px -72px;
2678
+ }
2679
+ .icon-forward {
2680
+ background-position: -336px -72px;
2681
+ }
2682
+ .icon-fast-forward {
2683
+ background-position: -360px -72px;
2684
+ }
2685
+ .icon-step-forward {
2686
+ background-position: -384px -72px;
2687
+ }
2688
+ .icon-eject {
2689
+ background-position: -408px -72px;
2690
+ }
2691
+ .icon-chevron-left {
2692
+ background-position: -432px -72px;
2693
+ }
2694
+ .icon-chevron-right {
2695
+ background-position: -456px -72px;
2696
+ }
2697
+ .icon-plus-sign {
2698
+ background-position: 0 -96px;
2699
+ }
2700
+ .icon-minus-sign {
2701
+ background-position: -24px -96px;
2702
+ }
2703
+ .icon-remove-sign {
2704
+ background-position: -48px -96px;
2705
+ }
2706
+ .icon-ok-sign {
2707
+ background-position: -72px -96px;
2708
+ }
2709
+ .icon-question-sign {
2710
+ background-position: -96px -96px;
2711
+ }
2712
+ .icon-info-sign {
2713
+ background-position: -120px -96px;
2714
+ }
2715
+ .icon-screenshot {
2716
+ background-position: -144px -96px;
2717
+ }
2718
+ .icon-remove-circle {
2719
+ background-position: -168px -96px;
2720
+ }
2721
+ .icon-ok-circle {
2722
+ background-position: -192px -96px;
2723
+ }
2724
+ .icon-ban-circle {
2725
+ background-position: -216px -96px;
2726
+ }
2727
+ .icon-arrow-left {
2728
+ background-position: -240px -96px;
2729
+ }
2730
+ .icon-arrow-right {
2731
+ background-position: -264px -96px;
2732
+ }
2733
+ .icon-arrow-up {
2734
+ background-position: -289px -96px;
2735
+ }
2736
+ .icon-arrow-down {
2737
+ background-position: -312px -96px;
2738
+ }
2739
+ .icon-share-alt {
2740
+ background-position: -336px -96px;
2741
+ }
2742
+ .icon-resize-full {
2743
+ background-position: -360px -96px;
2744
+ }
2745
+ .icon-resize-small {
2746
+ background-position: -384px -96px;
2747
+ }
2748
+ .icon-plus {
2749
+ background-position: -408px -96px;
2750
+ }
2751
+ .icon-minus {
2752
+ background-position: -433px -96px;
2753
+ }
2754
+ .icon-asterisk {
2755
+ background-position: -456px -96px;
2756
+ }
2757
+ .icon-exclamation-sign {
2758
+ background-position: 0 -120px;
2759
+ }
2760
+ .icon-gift {
2761
+ background-position: -24px -120px;
2762
+ }
2763
+ .icon-leaf {
2764
+ background-position: -48px -120px;
2765
+ }
2766
+ .icon-fire {
2767
+ background-position: -72px -120px;
2768
+ }
2769
+ .icon-eye-open {
2770
+ background-position: -96px -120px;
2771
+ }
2772
+ .icon-eye-close {
2773
+ background-position: -120px -120px;
2774
+ }
2775
+ .icon-warning-sign {
2776
+ background-position: -144px -120px;
2777
+ }
2778
+ .icon-plane {
2779
+ background-position: -168px -120px;
2780
+ }
2781
+ .icon-calendar {
2782
+ background-position: -192px -120px;
2783
+ }
2784
+ .icon-random {
2785
+ background-position: -216px -120px;
2786
+ width: 16px;
2787
+ }
2788
+ .icon-comment {
2789
+ background-position: -240px -120px;
2790
+ }
2791
+ .icon-magnet {
2792
+ background-position: -264px -120px;
2793
+ }
2794
+ .icon-chevron-up {
2795
+ background-position: -288px -120px;
2796
+ }
2797
+ .icon-chevron-down {
2798
+ background-position: -313px -119px;
2799
+ }
2800
+ .icon-retweet {
2801
+ background-position: -336px -120px;
2802
+ }
2803
+ .icon-shopping-cart {
2804
+ background-position: -360px -120px;
2805
+ }
2806
+ .icon-folder-close {
2807
+ background-position: -384px -120px;
2808
+ width: 16px;
2809
+ }
2810
+ .icon-folder-open {
2811
+ background-position: -408px -120px;
2812
+ width: 16px;
2813
+ }
2814
+ .icon-resize-vertical {
2815
+ background-position: -432px -119px;
2816
+ }
2817
+ .icon-resize-horizontal {
2818
+ background-position: -456px -118px;
2819
+ }
2820
+ .icon-hdd {
2821
+ background-position: 0 -144px;
2822
+ }
2823
+ .icon-bullhorn {
2824
+ background-position: -24px -144px;
2825
+ }
2826
+ .icon-bell {
2827
+ background-position: -48px -144px;
2828
+ }
2829
+ .icon-certificate {
2830
+ background-position: -72px -144px;
2831
+ }
2832
+ .icon-thumbs-up {
2833
+ background-position: -96px -144px;
2834
+ }
2835
+ .icon-thumbs-down {
2836
+ background-position: -120px -144px;
2837
+ }
2838
+ .icon-hand-right {
2839
+ background-position: -144px -144px;
2840
+ }
2841
+ .icon-hand-left {
2842
+ background-position: -168px -144px;
2843
+ }
2844
+ .icon-hand-up {
2845
+ background-position: -192px -144px;
2846
+ }
2847
+ .icon-hand-down {
2848
+ background-position: -216px -144px;
2849
+ }
2850
+ .icon-circle-arrow-right {
2851
+ background-position: -240px -144px;
2852
+ }
2853
+ .icon-circle-arrow-left {
2854
+ background-position: -264px -144px;
2855
+ }
2856
+ .icon-circle-arrow-up {
2857
+ background-position: -288px -144px;
2858
+ }
2859
+ .icon-circle-arrow-down {
2860
+ background-position: -312px -144px;
2861
+ }
2862
+ .icon-globe {
2863
+ background-position: -336px -144px;
2864
+ }
2865
+ .icon-wrench {
2866
+ background-position: -360px -144px;
2867
+ }
2868
+ .icon-tasks {
2869
+ background-position: -384px -144px;
2870
+ }
2871
+ .icon-filter {
2872
+ background-position: -408px -144px;
2873
+ }
2874
+ .icon-briefcase {
2875
+ background-position: -432px -144px;
2876
+ }
2877
+ .icon-fullscreen {
2878
+ background-position: -456px -144px;
2879
+ }
2880
+ .btn-group {
2881
+ position: relative;
2882
+ display: inline-block;
2883
+ *display: inline;
2884
+ /* IE7 inline-block hack */
2885
+
2886
+ *zoom: 1;
2887
+ font-size: 0;
2888
+ vertical-align: middle;
2889
+ white-space: nowrap;
2890
+ *margin-left: .3em;
2891
+ }
2892
+ .btn-group:first-child {
2893
+ *margin-left: 0;
2894
+ }
2895
+ .btn-group + .btn-group {
2896
+ margin-left: 5px;
2897
+ }
2898
+ .btn-toolbar {
2899
+ font-size: 0;
2900
+ margin-top: 10px;
2901
+ margin-bottom: 10px;
2902
+ }
2903
+ .btn-toolbar > .btn + .btn,
2904
+ .btn-toolbar > .btn-group + .btn,
2905
+ .btn-toolbar > .btn + .btn-group {
2906
+ margin-left: 5px;
2907
+ }
2908
+ .btn-group > .btn {
2909
+ position: relative;
2910
+ -webkit-border-radius: 0;
2911
+ -moz-border-radius: 0;
2912
+ border-radius: 0;
2913
+ }
2914
+ .btn-group > .btn + .btn {
2915
+ margin-left: -1px;
2916
+ }
2917
+ .btn-group > .btn,
2918
+ .btn-group > .dropdown-menu,
2919
+ .btn-group > .popover {
2920
+ font-size: 14px;
2921
+ }
2922
+ .btn-group > .btn-mini {
2923
+ font-size: 10.5px;
2924
+ }
2925
+ .btn-group > .btn-small {
2926
+ font-size: 11.9px;
2927
+ }
2928
+ .btn-group > .btn-large {
2929
+ font-size: 17.5px;
2930
+ }
2931
+ .btn-group > .btn:first-child {
2932
+ margin-left: 0;
2933
+ -webkit-border-top-left-radius: 4px;
2934
+ -moz-border-radius-topleft: 4px;
2935
+ border-top-left-radius: 4px;
2936
+ -webkit-border-bottom-left-radius: 4px;
2937
+ -moz-border-radius-bottomleft: 4px;
2938
+ border-bottom-left-radius: 4px;
2939
+ }
2940
+ .btn-group > .btn:last-child,
2941
+ .btn-group > .dropdown-toggle {
2942
+ -webkit-border-top-right-radius: 4px;
2943
+ -moz-border-radius-topright: 4px;
2944
+ border-top-right-radius: 4px;
2945
+ -webkit-border-bottom-right-radius: 4px;
2946
+ -moz-border-radius-bottomright: 4px;
2947
+ border-bottom-right-radius: 4px;
2948
+ }
2949
+ .btn-group > .btn.large:first-child {
2950
+ margin-left: 0;
2951
+ -webkit-border-top-left-radius: 6px;
2952
+ -moz-border-radius-topleft: 6px;
2953
+ border-top-left-radius: 6px;
2954
+ -webkit-border-bottom-left-radius: 6px;
2955
+ -moz-border-radius-bottomleft: 6px;
2956
+ border-bottom-left-radius: 6px;
2957
+ }
2958
+ .btn-group > .btn.large:last-child,
2959
+ .btn-group > .large.dropdown-toggle {
2960
+ -webkit-border-top-right-radius: 6px;
2961
+ -moz-border-radius-topright: 6px;
2962
+ border-top-right-radius: 6px;
2963
+ -webkit-border-bottom-right-radius: 6px;
2964
+ -moz-border-radius-bottomright: 6px;
2965
+ border-bottom-right-radius: 6px;
2966
+ }
2967
+ .btn-group > .btn:hover,
2968
+ .btn-group > .btn:focus,
2969
+ .btn-group > .btn:active,
2970
+ .btn-group > .btn.active {
2971
+ z-index: 2;
2972
+ }
2973
+ .btn-group .dropdown-toggle:active,
2974
+ .btn-group.open .dropdown-toggle {
2975
+ outline: 0;
2976
+ }
2977
+ .btn-group > .btn + .dropdown-toggle {
2978
+ padding-left: 8px;
2979
+ padding-right: 8px;
2980
+ -webkit-box-shadow: inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
2981
+ -moz-box-shadow: inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
2982
+ box-shadow: inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
2983
+ *padding-top: 5px;
2984
+ *padding-bottom: 5px;
2985
+ }
2986
+ .btn-group > .btn-mini + .dropdown-toggle {
2987
+ padding-left: 5px;
2988
+ padding-right: 5px;
2989
+ *padding-top: 2px;
2990
+ *padding-bottom: 2px;
2991
+ }
2992
+ .btn-group > .btn-small + .dropdown-toggle {
2993
+ *padding-top: 5px;
2994
+ *padding-bottom: 4px;
2995
+ }
2996
+ .btn-group > .btn-large + .dropdown-toggle {
2997
+ padding-left: 12px;
2998
+ padding-right: 12px;
2999
+ *padding-top: 7px;
3000
+ *padding-bottom: 7px;
3001
+ }
3002
+ .btn-group.open .dropdown-toggle {
3003
+ background-image: none;
3004
+ -webkit-box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);
3005
+ -moz-box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);
3006
+ box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);
3007
+ }
3008
+ .btn-group.open .btn.dropdown-toggle {
3009
+ background-color: #e6e6e6;
3010
+ }
3011
+ .btn-group.open .btn-primary.dropdown-toggle {
3012
+ background-color: #0044cc;
3013
+ }
3014
+ .btn-group.open .btn-warning.dropdown-toggle {
3015
+ background-color: #f89406;
3016
+ }
3017
+ .btn-group.open .btn-danger.dropdown-toggle {
3018
+ background-color: #bd362f;
3019
+ }
3020
+ .btn-group.open .btn-success.dropdown-toggle {
3021
+ background-color: #51a351;
3022
+ }
3023
+ .btn-group.open .btn-info.dropdown-toggle {
3024
+ background-color: #2f96b4;
3025
+ }
3026
+ .btn-group.open .btn-inverse.dropdown-toggle {
3027
+ background-color: #222222;
3028
+ }
3029
+ .btn .caret {
3030
+ margin-top: 8px;
3031
+ margin-left: 0;
3032
+ }
3033
+ .btn-large .caret {
3034
+ margin-top: 6px;
3035
+ }
3036
+ .btn-large .caret {
3037
+ border-left-width: 5px;
3038
+ border-right-width: 5px;
3039
+ border-top-width: 5px;
3040
+ }
3041
+ .btn-mini .caret,
3042
+ .btn-small .caret {
3043
+ margin-top: 8px;
3044
+ }
3045
+ .dropup .btn-large .caret {
3046
+ border-bottom-width: 5px;
3047
+ }
3048
+ .btn-primary .caret,
3049
+ .btn-warning .caret,
3050
+ .btn-danger .caret,
3051
+ .btn-info .caret,
3052
+ .btn-success .caret,
3053
+ .btn-inverse .caret {
3054
+ border-top-color: #ffffff;
3055
+ border-bottom-color: #ffffff;
3056
+ }
3057
+ .btn-group-vertical {
3058
+ display: inline-block;
3059
+ *display: inline;
3060
+ /* IE7 inline-block hack */
3061
+
3062
+ *zoom: 1;
3063
+ }
3064
+ .btn-group-vertical > .btn {
3065
+ display: block;
3066
+ float: none;
3067
+ max-width: 100%;
3068
+ -webkit-border-radius: 0;
3069
+ -moz-border-radius: 0;
3070
+ border-radius: 0;
3071
+ }
3072
+ .btn-group-vertical > .btn + .btn {
3073
+ margin-left: 0;
3074
+ margin-top: -1px;
3075
+ }
3076
+ .btn-group-vertical > .btn:first-child {
3077
+ -webkit-border-radius: 4px 4px 0 0;
3078
+ -moz-border-radius: 4px 4px 0 0;
3079
+ border-radius: 4px 4px 0 0;
3080
+ }
3081
+ .btn-group-vertical > .btn:last-child {
3082
+ -webkit-border-radius: 0 0 4px 4px;
3083
+ -moz-border-radius: 0 0 4px 4px;
3084
+ border-radius: 0 0 4px 4px;
3085
+ }
3086
+ .btn-group-vertical > .btn-large:first-child {
3087
+ -webkit-border-radius: 6px 6px 0 0;
3088
+ -moz-border-radius: 6px 6px 0 0;
3089
+ border-radius: 6px 6px 0 0;
3090
+ }
3091
+ .btn-group-vertical > .btn-large:last-child {
3092
+ -webkit-border-radius: 0 0 6px 6px;
3093
+ -moz-border-radius: 0 0 6px 6px;
3094
+ border-radius: 0 0 6px 6px;
3095
+ }
3096
+ .nav {
3097
+ margin-left: 0;
3098
+ margin-bottom: 20px;
3099
+ list-style: none;
3100
+ }
3101
+ .nav > li > a {
3102
+ display: block;
3103
+ }
3104
+ .nav > li > a:hover,
3105
+ .nav > li > a:focus {
3106
+ text-decoration: none;
3107
+ background-color: #eeeeee;
3108
+ }
3109
+ .nav > li > a > img {
3110
+ max-width: none;
3111
+ }
3112
+ .nav > .pull-right {
3113
+ float: right;
3114
+ }
3115
+ .nav-header {
3116
+ display: block;
3117
+ padding: 3px 15px;
3118
+ font-size: 11px;
3119
+ font-weight: bold;
3120
+ line-height: 20px;
3121
+ color: #999999;
3122
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
3123
+ text-transform: uppercase;
3124
+ }
3125
+ .nav li + .nav-header {
3126
+ margin-top: 9px;
3127
+ }
3128
+ .nav-list {
3129
+ padding-left: 15px;
3130
+ padding-right: 15px;
3131
+ margin-bottom: 0;
3132
+ }
3133
+ .nav-list > li > a,
3134
+ .nav-list .nav-header {
3135
+ margin-left: -15px;
3136
+ margin-right: -15px;
3137
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
3138
+ }
3139
+ .nav-list > li > a {
3140
+ padding: 3px 15px;
3141
+ }
3142
+ .nav-list > .active > a,
3143
+ .nav-list > .active > a:hover,
3144
+ .nav-list > .active > a:focus {
3145
+ color: #ffffff;
3146
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);
3147
+ background-color: #0088cc;
3148
+ }
3149
+ .nav-list [class^="icon-"],
3150
+ .nav-list [class*=" icon-"] {
3151
+ margin-right: 2px;
3152
+ }
3153
+ .nav-list .divider {
3154
+ *width: 100%;
3155
+ height: 1px;
3156
+ margin: 9px 1px;
3157
+ *margin: -5px 0 5px;
3158
+ overflow: hidden;
3159
+ background-color: #e5e5e5;
3160
+ border-bottom: 1px solid #ffffff;
3161
+ }
3162
+ .nav-tabs,
3163
+ .nav-pills {
3164
+ *zoom: 1;
3165
+ }
3166
+ .nav-tabs:before,
3167
+ .nav-pills:before,
3168
+ .nav-tabs:after,
3169
+ .nav-pills:after {
3170
+ display: table;
3171
+ content: "";
3172
+ line-height: 0;
3173
+ }
3174
+ .nav-tabs:after,
3175
+ .nav-pills:after {
3176
+ clear: both;
3177
+ }
3178
+ .nav-tabs > li,
3179
+ .nav-pills > li {
3180
+ float: left;
3181
+ }
3182
+ .nav-tabs > li > a,
3183
+ .nav-pills > li > a {
3184
+ padding-right: 12px;
3185
+ padding-left: 12px;
3186
+ margin-right: 2px;
3187
+ line-height: 14px;
3188
+ }
3189
+ .nav-tabs {
3190
+ border-bottom: 1px solid #ddd;
3191
+ }
3192
+ .nav-tabs > li {
3193
+ margin-bottom: -1px;
3194
+ }
3195
+ .nav-tabs > li > a {
3196
+ padding-top: 8px;
3197
+ padding-bottom: 8px;
3198
+ line-height: 20px;
3199
+ border: 1px solid transparent;
3200
+ -webkit-border-radius: 4px 4px 0 0;
3201
+ -moz-border-radius: 4px 4px 0 0;
3202
+ border-radius: 4px 4px 0 0;
3203
+ }
3204
+ .nav-tabs > li > a:hover,
3205
+ .nav-tabs > li > a:focus {
3206
+ border-color: #eeeeee #eeeeee #dddddd;
3207
+ }
3208
+ .nav-tabs > .active > a,
3209
+ .nav-tabs > .active > a:hover,
3210
+ .nav-tabs > .active > a:focus {
3211
+ color: #555555;
3212
+ background-color: #ffffff;
3213
+ border: 1px solid #ddd;
3214
+ border-bottom-color: transparent;
3215
+ cursor: default;
3216
+ }
3217
+ .nav-pills > li > a {
3218
+ padding-top: 8px;
3219
+ padding-bottom: 8px;
3220
+ margin-top: 2px;
3221
+ margin-bottom: 2px;
3222
+ -webkit-border-radius: 5px;
3223
+ -moz-border-radius: 5px;
3224
+ border-radius: 5px;
3225
+ }
3226
+ .nav-pills > .active > a,
3227
+ .nav-pills > .active > a:hover,
3228
+ .nav-pills > .active > a:focus {
3229
+ color: #ffffff;
3230
+ background-color: #0088cc;
3231
+ }
3232
+ .nav-stacked > li {
3233
+ float: none;
3234
+ }
3235
+ .nav-stacked > li > a {
3236
+ margin-right: 0;
3237
+ }
3238
+ .nav-tabs.nav-stacked {
3239
+ border-bottom: 0;
3240
+ }
3241
+ .nav-tabs.nav-stacked > li > a {
3242
+ border: 1px solid #ddd;
3243
+ -webkit-border-radius: 0;
3244
+ -moz-border-radius: 0;
3245
+ border-radius: 0;
3246
+ }
3247
+ .nav-tabs.nav-stacked > li:first-child > a {
3248
+ -webkit-border-top-right-radius: 4px;
3249
+ -moz-border-radius-topright: 4px;
3250
+ border-top-right-radius: 4px;
3251
+ -webkit-border-top-left-radius: 4px;
3252
+ -moz-border-radius-topleft: 4px;
3253
+ border-top-left-radius: 4px;
3254
+ }
3255
+ .nav-tabs.nav-stacked > li:last-child > a {
3256
+ -webkit-border-bottom-right-radius: 4px;
3257
+ -moz-border-radius-bottomright: 4px;
3258
+ border-bottom-right-radius: 4px;
3259
+ -webkit-border-bottom-left-radius: 4px;
3260
+ -moz-border-radius-bottomleft: 4px;
3261
+ border-bottom-left-radius: 4px;
3262
+ }
3263
+ .nav-tabs.nav-stacked > li > a:hover,
3264
+ .nav-tabs.nav-stacked > li > a:focus {
3265
+ border-color: #ddd;
3266
+ z-index: 2;
3267
+ }
3268
+ .nav-pills.nav-stacked > li > a {
3269
+ margin-bottom: 3px;
3270
+ }
3271
+ .nav-pills.nav-stacked > li:last-child > a {
3272
+ margin-bottom: 1px;
3273
+ }
3274
+ .nav-tabs .dropdown-menu {
3275
+ -webkit-border-radius: 0 0 6px 6px;
3276
+ -moz-border-radius: 0 0 6px 6px;
3277
+ border-radius: 0 0 6px 6px;
3278
+ }
3279
+ .nav-pills .dropdown-menu {
3280
+ -webkit-border-radius: 6px;
3281
+ -moz-border-radius: 6px;
3282
+ border-radius: 6px;
3283
+ }
3284
+ .nav .dropdown-toggle .caret {
3285
+ border-top-color: #0088cc;
3286
+ border-bottom-color: #0088cc;
3287
+ margin-top: 6px;
3288
+ }
3289
+ .nav .dropdown-toggle:hover .caret,
3290
+ .nav .dropdown-toggle:focus .caret {
3291
+ border-top-color: #005580;
3292
+ border-bottom-color: #005580;
3293
+ }
3294
+ /* move down carets for tabs */
3295
+ .nav-tabs .dropdown-toggle .caret {
3296
+ margin-top: 8px;
3297
+ }
3298
+ .nav .active .dropdown-toggle .caret {
3299
+ border-top-color: #fff;
3300
+ border-bottom-color: #fff;
3301
+ }
3302
+ .nav-tabs .active .dropdown-toggle .caret {
3303
+ border-top-color: #555555;
3304
+ border-bottom-color: #555555;
3305
+ }
3306
+ .nav > .dropdown.active > a:hover,
3307
+ .nav > .dropdown.active > a:focus {
3308
+ cursor: pointer;
3309
+ }
3310
+ .nav-tabs .open .dropdown-toggle,
3311
+ .nav-pills .open .dropdown-toggle,
3312
+ .nav > li.dropdown.open.active > a:hover,
3313
+ .nav > li.dropdown.open.active > a:focus {
3314
+ color: #ffffff;
3315
+ background-color: #999999;
3316
+ border-color: #999999;
3317
+ }
3318
+ .nav li.dropdown.open .caret,
3319
+ .nav li.dropdown.open.active .caret,
3320
+ .nav li.dropdown.open a:hover .caret,
3321
+ .nav li.dropdown.open a:focus .caret {
3322
+ border-top-color: #ffffff;
3323
+ border-bottom-color: #ffffff;
3324
+ opacity: 1;
3325
+ filter: alpha(opacity=100);
3326
+ }
3327
+ .tabs-stacked .open > a:hover,
3328
+ .tabs-stacked .open > a:focus {
3329
+ border-color: #999999;
3330
+ }
3331
+ .tabbable {
3332
+ *zoom: 1;
3333
+ }
3334
+ .tabbable:before,
3335
+ .tabbable:after {
3336
+ display: table;
3337
+ content: "";
3338
+ line-height: 0;
3339
+ }
3340
+ .tabbable:after {
3341
+ clear: both;
3342
+ }
3343
+ .tab-content {
3344
+ overflow: auto;
3345
+ }
3346
+ .tabs-below > .nav-tabs,
3347
+ .tabs-right > .nav-tabs,
3348
+ .tabs-left > .nav-tabs {
3349
+ border-bottom: 0;
3350
+ }
3351
+ .tab-content > .tab-pane,
3352
+ .pill-content > .pill-pane {
3353
+ display: none;
3354
+ }
3355
+ .tab-content > .active,
3356
+ .pill-content > .active {
3357
+ display: block;
3358
+ }
3359
+ .tabs-below > .nav-tabs {
3360
+ border-top: 1px solid #ddd;
3361
+ }
3362
+ .tabs-below > .nav-tabs > li {
3363
+ margin-top: -1px;
3364
+ margin-bottom: 0;
3365
+ }
3366
+ .tabs-below > .nav-tabs > li > a {
3367
+ -webkit-border-radius: 0 0 4px 4px;
3368
+ -moz-border-radius: 0 0 4px 4px;
3369
+ border-radius: 0 0 4px 4px;
3370
+ }
3371
+ .tabs-below > .nav-tabs > li > a:hover,
3372
+ .tabs-below > .nav-tabs > li > a:focus {
3373
+ border-bottom-color: transparent;
3374
+ border-top-color: #ddd;
3375
+ }
3376
+ .tabs-below > .nav-tabs > .active > a,
3377
+ .tabs-below > .nav-tabs > .active > a:hover,
3378
+ .tabs-below > .nav-tabs > .active > a:focus {
3379
+ border-color: transparent #ddd #ddd #ddd;
3380
+ }
3381
+ .tabs-left > .nav-tabs > li,
3382
+ .tabs-right > .nav-tabs > li {
3383
+ float: none;
3384
+ }
3385
+ .tabs-left > .nav-tabs > li > a,
3386
+ .tabs-right > .nav-tabs > li > a {
3387
+ min-width: 74px;
3388
+ margin-right: 0;
3389
+ margin-bottom: 3px;
3390
+ }
3391
+ .tabs-left > .nav-tabs {
3392
+ float: left;
3393
+ margin-right: 19px;
3394
+ border-right: 1px solid #ddd;
3395
+ }
3396
+ .tabs-left > .nav-tabs > li > a {
3397
+ margin-right: -1px;
3398
+ -webkit-border-radius: 4px 0 0 4px;
3399
+ -moz-border-radius: 4px 0 0 4px;
3400
+ border-radius: 4px 0 0 4px;
3401
+ }
3402
+ .tabs-left > .nav-tabs > li > a:hover,
3403
+ .tabs-left > .nav-tabs > li > a:focus {
3404
+ border-color: #eeeeee #dddddd #eeeeee #eeeeee;
3405
+ }
3406
+ .tabs-left > .nav-tabs .active > a,
3407
+ .tabs-left > .nav-tabs .active > a:hover,
3408
+ .tabs-left > .nav-tabs .active > a:focus {
3409
+ border-color: #ddd transparent #ddd #ddd;
3410
+ *border-right-color: #ffffff;
3411
+ }
3412
+ .tabs-right > .nav-tabs {
3413
+ float: right;
3414
+ margin-left: 19px;
3415
+ border-left: 1px solid #ddd;
3416
+ }
3417
+ .tabs-right > .nav-tabs > li > a {
3418
+ margin-left: -1px;
3419
+ -webkit-border-radius: 0 4px 4px 0;
3420
+ -moz-border-radius: 0 4px 4px 0;
3421
+ border-radius: 0 4px 4px 0;
3422
+ }
3423
+ .tabs-right > .nav-tabs > li > a:hover,
3424
+ .tabs-right > .nav-tabs > li > a:focus {
3425
+ border-color: #eeeeee #eeeeee #eeeeee #dddddd;
3426
+ }
3427
+ .tabs-right > .nav-tabs .active > a,
3428
+ .tabs-right > .nav-tabs .active > a:hover,
3429
+ .tabs-right > .nav-tabs .active > a:focus {
3430
+ border-color: #ddd #ddd #ddd transparent;
3431
+ *border-left-color: #ffffff;
3432
+ }
3433
+ .nav > .disabled > a {
3434
+ color: #999999;
3435
+ }
3436
+ .nav > .disabled > a:hover,
3437
+ .nav > .disabled > a:focus {
3438
+ text-decoration: none;
3439
+ background-color: transparent;
3440
+ cursor: default;
3441
+ }
3442
+ .navbar {
3443
+ overflow: visible;
3444
+ margin-bottom: 20px;
3445
+ *position: relative;
3446
+ *z-index: 2;
3447
+ }
3448
+ .navbar-inner {
3449
+ min-height: 40px;
3450
+ padding-left: 20px;
3451
+ padding-right: 20px;
3452
+ background-color: #fafafa;
3453
+ background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);
3454
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));
3455
+ background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);
3456
+ background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);
3457
+ background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);
3458
+ background-repeat: repeat-x;
3459
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);
3460
+ border: 1px solid #d4d4d4;
3461
+ -webkit-border-radius: 4px;
3462
+ -moz-border-radius: 4px;
3463
+ border-radius: 4px;
3464
+ -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
3465
+ -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
3466
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
3467
+ *zoom: 1;
3468
+ }
3469
+ .navbar-inner:before,
3470
+ .navbar-inner:after {
3471
+ display: table;
3472
+ content: "";
3473
+ line-height: 0;
3474
+ }
3475
+ .navbar-inner:after {
3476
+ clear: both;
3477
+ }
3478
+ .navbar .container {
3479
+ width: auto;
3480
+ }
3481
+ .nav-collapse.collapse {
3482
+ height: auto;
3483
+ overflow: visible;
3484
+ }
3485
+ .navbar .brand {
3486
+ float: left;
3487
+ display: block;
3488
+ padding: 10px 20px 10px;
3489
+ margin-left: -20px;
3490
+ font-size: 20px;
3491
+ font-weight: 200;
3492
+ color: #777777;
3493
+ text-shadow: 0 1px 0 #ffffff;
3494
+ }
3495
+ .navbar .brand:hover,
3496
+ .navbar .brand:focus {
3497
+ text-decoration: none;
3498
+ }
3499
+ .navbar-text {
3500
+ margin-bottom: 0;
3501
+ line-height: 40px;
3502
+ color: #777777;
3503
+ }
3504
+ .navbar-link {
3505
+ color: #777777;
3506
+ }
3507
+ .navbar-link:hover,
3508
+ .navbar-link:focus {
3509
+ color: #333333;
3510
+ }
3511
+ .navbar .divider-vertical {
3512
+ height: 40px;
3513
+ margin: 0 9px;
3514
+ border-left: 1px solid #f2f2f2;
3515
+ border-right: 1px solid #ffffff;
3516
+ }
3517
+ .navbar .btn,
3518
+ .navbar .btn-group {
3519
+ margin-top: 5px;
3520
+ }
3521
+ .navbar .btn-group .btn,
3522
+ .navbar .input-prepend .btn,
3523
+ .navbar .input-append .btn,
3524
+ .navbar .input-prepend .btn-group,
3525
+ .navbar .input-append .btn-group {
3526
+ margin-top: 0;
3527
+ }
3528
+ .navbar-form {
3529
+ margin-bottom: 0;
3530
+ *zoom: 1;
3531
+ }
3532
+ .navbar-form:before,
3533
+ .navbar-form:after {
3534
+ display: table;
3535
+ content: "";
3536
+ line-height: 0;
3537
+ }
3538
+ .navbar-form:after {
3539
+ clear: both;
3540
+ }
3541
+ .navbar-form input,
3542
+ .navbar-form select,
3543
+ .navbar-form .radio,
3544
+ .navbar-form .checkbox {
3545
+ margin-top: 5px;
3546
+ }
3547
+ .navbar-form input,
3548
+ .navbar-form select,
3549
+ .navbar-form .btn {
3550
+ display: inline-block;
3551
+ margin-bottom: 0;
3552
+ }
3553
+ .navbar-form input[type="image"],
3554
+ .navbar-form input[type="checkbox"],
3555
+ .navbar-form input[type="radio"] {
3556
+ margin-top: 3px;
3557
+ }
3558
+ .navbar-form .input-append,
3559
+ .navbar-form .input-prepend {
3560
+ margin-top: 5px;
3561
+ white-space: nowrap;
3562
+ }
3563
+ .navbar-form .input-append input,
3564
+ .navbar-form .input-prepend input {
3565
+ margin-top: 0;
3566
+ }
3567
+ .navbar-search {
3568
+ position: relative;
3569
+ float: left;
3570
+ margin-top: 5px;
3571
+ margin-bottom: 0;
3572
+ }
3573
+ .navbar-search .search-query {
3574
+ margin-bottom: 0;
3575
+ padding: 4px 14px;
3576
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
3577
+ font-size: 13px;
3578
+ font-weight: normal;
3579
+ line-height: 1;
3580
+ -webkit-border-radius: 15px;
3581
+ -moz-border-radius: 15px;
3582
+ border-radius: 15px;
3583
+ }
3584
+ .navbar-static-top {
3585
+ position: static;
3586
+ margin-bottom: 0;
3587
+ }
3588
+ .navbar-static-top .navbar-inner {
3589
+ -webkit-border-radius: 0;
3590
+ -moz-border-radius: 0;
3591
+ border-radius: 0;
3592
+ }
3593
+ .navbar-fixed-top,
3594
+ .navbar-fixed-bottom {
3595
+ position: fixed;
3596
+ right: 0;
3597
+ left: 0;
3598
+ z-index: 1030;
3599
+ margin-bottom: 0;
3600
+ }
3601
+ .navbar-fixed-top .navbar-inner,
3602
+ .navbar-static-top .navbar-inner {
3603
+ border-width: 0 0 1px;
3604
+ }
3605
+ .navbar-fixed-bottom .navbar-inner {
3606
+ border-width: 1px 0 0;
3607
+ }
3608
+ .navbar-fixed-top .navbar-inner,
3609
+ .navbar-fixed-bottom .navbar-inner {
3610
+ padding-left: 0;
3611
+ padding-right: 0;
3612
+ -webkit-border-radius: 0;
3613
+ -moz-border-radius: 0;
3614
+ border-radius: 0;
3615
+ }
3616
+ .navbar-static-top .container,
3617
+ .navbar-fixed-top .container,
3618
+ .navbar-fixed-bottom .container {
3619
+ width: 940px;
3620
+ }
3621
+ .navbar-fixed-top {
3622
+ top: 0;
3623
+ }
3624
+ .navbar-fixed-top .navbar-inner,
3625
+ .navbar-static-top .navbar-inner {
3626
+ -webkit-box-shadow: 0 1px 10px rgba(0,0,0,.1);
3627
+ -moz-box-shadow: 0 1px 10px rgba(0,0,0,.1);
3628
+ box-shadow: 0 1px 10px rgba(0,0,0,.1);
3629
+ }
3630
+ .navbar-fixed-bottom {
3631
+ bottom: 0;
3632
+ }
3633
+ .navbar-fixed-bottom .navbar-inner {
3634
+ -webkit-box-shadow: 0 -1px 10px rgba(0,0,0,.1);
3635
+ -moz-box-shadow: 0 -1px 10px rgba(0,0,0,.1);
3636
+ box-shadow: 0 -1px 10px rgba(0,0,0,.1);
3637
+ }
3638
+ .navbar .nav {
3639
+ position: relative;
3640
+ left: 0;
3641
+ display: block;
3642
+ float: left;
3643
+ margin: 0 10px 0 0;
3644
+ }
3645
+ .navbar .nav.pull-right {
3646
+ float: right;
3647
+ margin-right: 0;
3648
+ }
3649
+ .navbar .nav > li {
3650
+ float: left;
3651
+ }
3652
+ .navbar .nav > li > a {
3653
+ float: none;
3654
+ padding: 10px 15px 10px;
3655
+ color: #777777;
3656
+ text-decoration: none;
3657
+ text-shadow: 0 1px 0 #ffffff;
3658
+ }
3659
+ .navbar .nav .dropdown-toggle .caret {
3660
+ margin-top: 8px;
3661
+ }
3662
+ .navbar .nav > li > a:focus,
3663
+ .navbar .nav > li > a:hover {
3664
+ background-color: transparent;
3665
+ color: #333333;
3666
+ text-decoration: none;
3667
+ }
3668
+ .navbar .nav > .active > a,
3669
+ .navbar .nav > .active > a:hover,
3670
+ .navbar .nav > .active > a:focus {
3671
+ color: #555555;
3672
+ text-decoration: none;
3673
+ background-color: #e5e5e5;
3674
+ -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);
3675
+ -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);
3676
+ box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);
3677
+ }
3678
+ .navbar .btn-navbar {
3679
+ display: none;
3680
+ float: right;
3681
+ padding: 7px 10px;
3682
+ margin-left: 5px;
3683
+ margin-right: 5px;
3684
+ color: #ffffff;
3685
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
3686
+ background-color: #ededed;
3687
+ background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);
3688
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));
3689
+ background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);
3690
+ background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);
3691
+ background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);
3692
+ background-repeat: repeat-x;
3693
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);
3694
+ border-color: #e5e5e5 #e5e5e5 #bfbfbf;
3695
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
3696
+ *background-color: #e5e5e5;
3697
+ /* Darken IE7 buttons by default so they stand out more given they won't have borders */
3698
+
3699
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
3700
+ -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075);
3701
+ -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075);
3702
+ box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075);
3703
+ }
3704
+ .navbar .btn-navbar:hover,
3705
+ .navbar .btn-navbar:focus,
3706
+ .navbar .btn-navbar:active,
3707
+ .navbar .btn-navbar.active,
3708
+ .navbar .btn-navbar.disabled,
3709
+ .navbar .btn-navbar[disabled] {
3710
+ color: #ffffff;
3711
+ background-color: #e5e5e5;
3712
+ *background-color: #d9d9d9;
3713
+ }
3714
+ .navbar .btn-navbar:active,
3715
+ .navbar .btn-navbar.active {
3716
+ background-color: #cccccc \9;
3717
+ }
3718
+ .navbar .btn-navbar .icon-bar {
3719
+ display: block;
3720
+ width: 18px;
3721
+ height: 2px;
3722
+ background-color: #f5f5f5;
3723
+ -webkit-border-radius: 1px;
3724
+ -moz-border-radius: 1px;
3725
+ border-radius: 1px;
3726
+ -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
3727
+ -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
3728
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
3729
+ }
3730
+ .btn-navbar .icon-bar + .icon-bar {
3731
+ margin-top: 3px;
3732
+ }
3733
+ .navbar .nav > li > .dropdown-menu:before {
3734
+ content: '';
3735
+ display: inline-block;
3736
+ border-left: 7px solid transparent;
3737
+ border-right: 7px solid transparent;
3738
+ border-bottom: 7px solid #ccc;
3739
+ border-bottom-color: rgba(0, 0, 0, 0.2);
3740
+ position: absolute;
3741
+ top: -7px;
3742
+ left: 9px;
3743
+ }
3744
+ .navbar .nav > li > .dropdown-menu:after {
3745
+ content: '';
3746
+ display: inline-block;
3747
+ border-left: 6px solid transparent;
3748
+ border-right: 6px solid transparent;
3749
+ border-bottom: 6px solid #ffffff;
3750
+ position: absolute;
3751
+ top: -6px;
3752
+ left: 10px;
3753
+ }
3754
+ .navbar-fixed-bottom .nav > li > .dropdown-menu:before {
3755
+ border-top: 7px solid #ccc;
3756
+ border-top-color: rgba(0, 0, 0, 0.2);
3757
+ border-bottom: 0;
3758
+ bottom: -7px;
3759
+ top: auto;
3760
+ }
3761
+ .navbar-fixed-bottom .nav > li > .dropdown-menu:after {
3762
+ border-top: 6px solid #ffffff;
3763
+ border-bottom: 0;
3764
+ bottom: -6px;
3765
+ top: auto;
3766
+ }
3767
+ .navbar .nav li.dropdown > a:hover .caret,
3768
+ .navbar .nav li.dropdown > a:focus .caret {
3769
+ border-top-color: #333333;
3770
+ border-bottom-color: #333333;
3771
+ }
3772
+ .navbar .nav li.dropdown.open > .dropdown-toggle,
3773
+ .navbar .nav li.dropdown.active > .dropdown-toggle,
3774
+ .navbar .nav li.dropdown.open.active > .dropdown-toggle {
3775
+ background-color: #e5e5e5;
3776
+ color: #555555;
3777
+ }
3778
+ .navbar .nav li.dropdown > .dropdown-toggle .caret {
3779
+ border-top-color: #777777;
3780
+ border-bottom-color: #777777;
3781
+ }
3782
+ .navbar .nav li.dropdown.open > .dropdown-toggle .caret,
3783
+ .navbar .nav li.dropdown.active > .dropdown-toggle .caret,
3784
+ .navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {
3785
+ border-top-color: #555555;
3786
+ border-bottom-color: #555555;
3787
+ }
3788
+ .navbar .pull-right > li > .dropdown-menu,
3789
+ .navbar .nav > li > .dropdown-menu.pull-right {
3790
+ left: auto;
3791
+ right: 0;
3792
+ }
3793
+ .navbar .pull-right > li > .dropdown-menu:before,
3794
+ .navbar .nav > li > .dropdown-menu.pull-right:before {
3795
+ left: auto;
3796
+ right: 12px;
3797
+ }
3798
+ .navbar .pull-right > li > .dropdown-menu:after,
3799
+ .navbar .nav > li > .dropdown-menu.pull-right:after {
3800
+ left: auto;
3801
+ right: 13px;
3802
+ }
3803
+ .navbar .pull-right > li > .dropdown-menu .dropdown-menu,
3804
+ .navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {
3805
+ left: auto;
3806
+ right: 100%;
3807
+ margin-left: 0;
3808
+ margin-right: -1px;
3809
+ -webkit-border-radius: 6px 0 6px 6px;
3810
+ -moz-border-radius: 6px 0 6px 6px;
3811
+ border-radius: 6px 0 6px 6px;
3812
+ }
3813
+ .navbar-inverse .navbar-inner {
3814
+ background-color: #1b1b1b;
3815
+ background-image: -moz-linear-gradient(top, #222222, #111111);
3816
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));
3817
+ background-image: -webkit-linear-gradient(top, #222222, #111111);
3818
+ background-image: -o-linear-gradient(top, #222222, #111111);
3819
+ background-image: linear-gradient(to bottom, #222222, #111111);
3820
+ background-repeat: repeat-x;
3821
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);
3822
+ border-color: #252525;
3823
+ }
3824
+ .navbar-inverse .brand,
3825
+ .navbar-inverse .nav > li > a {
3826
+ color: #999999;
3827
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
3828
+ }
3829
+ .navbar-inverse .brand:hover,
3830
+ .navbar-inverse .nav > li > a:hover,
3831
+ .navbar-inverse .brand:focus,
3832
+ .navbar-inverse .nav > li > a:focus {
3833
+ color: #ffffff;
3834
+ }
3835
+ .navbar-inverse .brand {
3836
+ color: #999999;
3837
+ }
3838
+ .navbar-inverse .navbar-text {
3839
+ color: #999999;
3840
+ }
3841
+ .navbar-inverse .nav > li > a:focus,
3842
+ .navbar-inverse .nav > li > a:hover {
3843
+ background-color: transparent;
3844
+ color: #ffffff;
3845
+ }
3846
+ .navbar-inverse .nav .active > a,
3847
+ .navbar-inverse .nav .active > a:hover,
3848
+ .navbar-inverse .nav .active > a:focus {
3849
+ color: #ffffff;
3850
+ background-color: #111111;
3851
+ }
3852
+ .navbar-inverse .navbar-link {
3853
+ color: #999999;
3854
+ }
3855
+ .navbar-inverse .navbar-link:hover,
3856
+ .navbar-inverse .navbar-link:focus {
3857
+ color: #ffffff;
3858
+ }
3859
+ .navbar-inverse .divider-vertical {
3860
+ border-left-color: #111111;
3861
+ border-right-color: #222222;
3862
+ }
3863
+ .navbar-inverse .nav li.dropdown.open > .dropdown-toggle,
3864
+ .navbar-inverse .nav li.dropdown.active > .dropdown-toggle,
3865
+ .navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {
3866
+ background-color: #111111;
3867
+ color: #ffffff;
3868
+ }
3869
+ .navbar-inverse .nav li.dropdown > a:hover .caret,
3870
+ .navbar-inverse .nav li.dropdown > a:focus .caret {
3871
+ border-top-color: #ffffff;
3872
+ border-bottom-color: #ffffff;
3873
+ }
3874
+ .navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {
3875
+ border-top-color: #999999;
3876
+ border-bottom-color: #999999;
3877
+ }
3878
+ .navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,
3879
+ .navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,
3880
+ .navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {
3881
+ border-top-color: #ffffff;
3882
+ border-bottom-color: #ffffff;
3883
+ }
3884
+ .navbar-inverse .navbar-search .search-query {
3885
+ color: #ffffff;
3886
+ background-color: #515151;
3887
+ border-color: #111111;
3888
+ -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15);
3889
+ -moz-box-shadow: inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15);
3890
+ box-shadow: inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15);
3891
+ -webkit-transition: none;
3892
+ -moz-transition: none;
3893
+ -o-transition: none;
3894
+ transition: none;
3895
+ }
3896
+ .navbar-inverse .navbar-search .search-query:-moz-placeholder {
3897
+ color: #cccccc;
3898
+ }
3899
+ .navbar-inverse .navbar-search .search-query:-ms-input-placeholder {
3900
+ color: #cccccc;
3901
+ }
3902
+ .navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {
3903
+ color: #cccccc;
3904
+ }
3905
+ .navbar-inverse .navbar-search .search-query:focus,
3906
+ .navbar-inverse .navbar-search .search-query.focused {
3907
+ padding: 5px 15px;
3908
+ color: #333333;
3909
+ text-shadow: 0 1px 0 #ffffff;
3910
+ background-color: #ffffff;
3911
+ border: 0;
3912
+ -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
3913
+ -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
3914
+ box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
3915
+ outline: 0;
3916
+ }
3917
+ .navbar-inverse .btn-navbar {
3918
+ color: #ffffff;
3919
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
3920
+ background-color: #0e0e0e;
3921
+ background-image: -moz-linear-gradient(top, #151515, #040404);
3922
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));
3923
+ background-image: -webkit-linear-gradient(top, #151515, #040404);
3924
+ background-image: -o-linear-gradient(top, #151515, #040404);
3925
+ background-image: linear-gradient(to bottom, #151515, #040404);
3926
+ background-repeat: repeat-x;
3927
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);
3928
+ border-color: #040404 #040404 #000000;
3929
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
3930
+ *background-color: #040404;
3931
+ /* Darken IE7 buttons by default so they stand out more given they won't have borders */
3932
+
3933
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
3934
+ }
3935
+ .navbar-inverse .btn-navbar:hover,
3936
+ .navbar-inverse .btn-navbar:focus,
3937
+ .navbar-inverse .btn-navbar:active,
3938
+ .navbar-inverse .btn-navbar.active,
3939
+ .navbar-inverse .btn-navbar.disabled,
3940
+ .navbar-inverse .btn-navbar[disabled] {
3941
+ color: #ffffff;
3942
+ background-color: #040404;
3943
+ *background-color: #000000;
3944
+ }
3945
+ .navbar-inverse .btn-navbar:active,
3946
+ .navbar-inverse .btn-navbar.active {
3947
+ background-color: #000000 \9;
3948
+ }
3949
+ .breadcrumb {
3950
+ padding: 8px 15px;
3951
+ margin: 0 0 20px;
3952
+ list-style: none;
3953
+ background-color: #f5f5f5;
3954
+ -webkit-border-radius: 4px;
3955
+ -moz-border-radius: 4px;
3956
+ border-radius: 4px;
3957
+ }
3958
+ .breadcrumb > li {
3959
+ display: inline-block;
3960
+ *display: inline;
3961
+ /* IE7 inline-block hack */
3962
+
3963
+ *zoom: 1;
3964
+ text-shadow: 0 1px 0 #ffffff;
3965
+ }
3966
+ .breadcrumb > li > .divider {
3967
+ padding: 0 5px;
3968
+ color: #ccc;
3969
+ }
3970
+ .breadcrumb > .active {
3971
+ color: #999999;
3972
+ }
3973
+ .pagination {
3974
+ margin: 20px 0;
3975
+ }
3976
+ .pagination ul {
3977
+ display: inline-block;
3978
+ *display: inline;
3979
+ /* IE7 inline-block hack */
3980
+
3981
+ *zoom: 1;
3982
+ margin-left: 0;
3983
+ margin-bottom: 0;
3984
+ -webkit-border-radius: 4px;
3985
+ -moz-border-radius: 4px;
3986
+ border-radius: 4px;
3987
+ -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
3988
+ -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
3989
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
3990
+ }
3991
+ .pagination ul > li {
3992
+ display: inline;
3993
+ }
3994
+ .pagination ul > li > a,
3995
+ .pagination ul > li > span {
3996
+ float: left;
3997
+ padding: 4px 12px;
3998
+ line-height: 20px;
3999
+ text-decoration: none;
4000
+ background-color: #ffffff;
4001
+ border: 1px solid #dddddd;
4002
+ border-left-width: 0;
4003
+ }
4004
+ .pagination ul > li > a:hover,
4005
+ .pagination ul > li > a:focus,
4006
+ .pagination ul > .active > a,
4007
+ .pagination ul > .active > span {
4008
+ background-color: #f5f5f5;
4009
+ }
4010
+ .pagination ul > .active > a,
4011
+ .pagination ul > .active > span {
4012
+ color: #999999;
4013
+ cursor: default;
4014
+ }
4015
+ .pagination ul > .disabled > span,
4016
+ .pagination ul > .disabled > a,
4017
+ .pagination ul > .disabled > a:hover,
4018
+ .pagination ul > .disabled > a:focus {
4019
+ color: #999999;
4020
+ background-color: transparent;
4021
+ cursor: default;
4022
+ }
4023
+ .pagination ul > li:first-child > a,
4024
+ .pagination ul > li:first-child > span {
4025
+ border-left-width: 1px;
4026
+ -webkit-border-top-left-radius: 4px;
4027
+ -moz-border-radius-topleft: 4px;
4028
+ border-top-left-radius: 4px;
4029
+ -webkit-border-bottom-left-radius: 4px;
4030
+ -moz-border-radius-bottomleft: 4px;
4031
+ border-bottom-left-radius: 4px;
4032
+ }
4033
+ .pagination ul > li:last-child > a,
4034
+ .pagination ul > li:last-child > span {
4035
+ -webkit-border-top-right-radius: 4px;
4036
+ -moz-border-radius-topright: 4px;
4037
+ border-top-right-radius: 4px;
4038
+ -webkit-border-bottom-right-radius: 4px;
4039
+ -moz-border-radius-bottomright: 4px;
4040
+ border-bottom-right-radius: 4px;
4041
+ }
4042
+ .pagination-centered {
4043
+ text-align: center;
4044
+ }
4045
+ .pagination-right {
4046
+ text-align: right;
4047
+ }
4048
+ .pagination-large ul > li > a,
4049
+ .pagination-large ul > li > span {
4050
+ padding: 11px 19px;
4051
+ font-size: 17.5px;
4052
+ }
4053
+ .pagination-large ul > li:first-child > a,
4054
+ .pagination-large ul > li:first-child > span {
4055
+ -webkit-border-top-left-radius: 6px;
4056
+ -moz-border-radius-topleft: 6px;
4057
+ border-top-left-radius: 6px;
4058
+ -webkit-border-bottom-left-radius: 6px;
4059
+ -moz-border-radius-bottomleft: 6px;
4060
+ border-bottom-left-radius: 6px;
4061
+ }
4062
+ .pagination-large ul > li:last-child > a,
4063
+ .pagination-large ul > li:last-child > span {
4064
+ -webkit-border-top-right-radius: 6px;
4065
+ -moz-border-radius-topright: 6px;
4066
+ border-top-right-radius: 6px;
4067
+ -webkit-border-bottom-right-radius: 6px;
4068
+ -moz-border-radius-bottomright: 6px;
4069
+ border-bottom-right-radius: 6px;
4070
+ }
4071
+ .pagination-mini ul > li:first-child > a,
4072
+ .pagination-small ul > li:first-child > a,
4073
+ .pagination-mini ul > li:first-child > span,
4074
+ .pagination-small ul > li:first-child > span {
4075
+ -webkit-border-top-left-radius: 3px;
4076
+ -moz-border-radius-topleft: 3px;
4077
+ border-top-left-radius: 3px;
4078
+ -webkit-border-bottom-left-radius: 3px;
4079
+ -moz-border-radius-bottomleft: 3px;
4080
+ border-bottom-left-radius: 3px;
4081
+ }
4082
+ .pagination-mini ul > li:last-child > a,
4083
+ .pagination-small ul > li:last-child > a,
4084
+ .pagination-mini ul > li:last-child > span,
4085
+ .pagination-small ul > li:last-child > span {
4086
+ -webkit-border-top-right-radius: 3px;
4087
+ -moz-border-radius-topright: 3px;
4088
+ border-top-right-radius: 3px;
4089
+ -webkit-border-bottom-right-radius: 3px;
4090
+ -moz-border-radius-bottomright: 3px;
4091
+ border-bottom-right-radius: 3px;
4092
+ }
4093
+ .pagination-small ul > li > a,
4094
+ .pagination-small ul > li > span {
4095
+ padding: 2px 10px;
4096
+ font-size: 11.9px;
4097
+ }
4098
+ .pagination-mini ul > li > a,
4099
+ .pagination-mini ul > li > span {
4100
+ padding: 0 6px;
4101
+ font-size: 10.5px;
4102
+ }
4103
+ .pager {
4104
+ margin: 20px 0;
4105
+ list-style: none;
4106
+ text-align: center;
4107
+ *zoom: 1;
4108
+ }
4109
+ .pager:before,
4110
+ .pager:after {
4111
+ display: table;
4112
+ content: "";
4113
+ line-height: 0;
4114
+ }
4115
+ .pager:after {
4116
+ clear: both;
4117
+ }
4118
+ .pager li {
4119
+ display: inline;
4120
+ }
4121
+ .pager li > a,
4122
+ .pager li > span {
4123
+ display: inline-block;
4124
+ padding: 5px 14px;
4125
+ background-color: #fff;
4126
+ border: 1px solid #ddd;
4127
+ -webkit-border-radius: 15px;
4128
+ -moz-border-radius: 15px;
4129
+ border-radius: 15px;
4130
+ }
4131
+ .pager li > a:hover,
4132
+ .pager li > a:focus {
4133
+ text-decoration: none;
4134
+ background-color: #f5f5f5;
4135
+ }
4136
+ .pager .next > a,
4137
+ .pager .next > span {
4138
+ float: right;
4139
+ }
4140
+ .pager .previous > a,
4141
+ .pager .previous > span {
4142
+ float: left;
4143
+ }
4144
+ .pager .disabled > a,
4145
+ .pager .disabled > a:hover,
4146
+ .pager .disabled > a:focus,
4147
+ .pager .disabled > span {
4148
+ color: #999999;
4149
+ background-color: #fff;
4150
+ cursor: default;
4151
+ }
4152
+ .thumbnails {
4153
+ margin-left: -20px;
4154
+ list-style: none;
4155
+ *zoom: 1;
4156
+ }
4157
+ .thumbnails:before,
4158
+ .thumbnails:after {
4159
+ display: table;
4160
+ content: "";
4161
+ line-height: 0;
4162
+ }
4163
+ .thumbnails:after {
4164
+ clear: both;
4165
+ }
4166
+ .row-fluid .thumbnails {
4167
+ margin-left: 0;
4168
+ }
4169
+ .thumbnails > li {
4170
+ float: left;
4171
+ margin-bottom: 20px;
4172
+ margin-left: 20px;
4173
+ }
4174
+ .thumbnail {
4175
+ display: block;
4176
+ padding: 4px;
4177
+ line-height: 20px;
4178
+ border: 1px solid #ddd;
4179
+ -webkit-border-radius: 4px;
4180
+ -moz-border-radius: 4px;
4181
+ border-radius: 4px;
4182
+ -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);
4183
+ -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);
4184
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);
4185
+ -webkit-transition: all 0.2s ease-in-out;
4186
+ -moz-transition: all 0.2s ease-in-out;
4187
+ -o-transition: all 0.2s ease-in-out;
4188
+ transition: all 0.2s ease-in-out;
4189
+ }
4190
+ a.thumbnail:hover,
4191
+ a.thumbnail:focus {
4192
+ border-color: #0088cc;
4193
+ -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
4194
+ -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
4195
+ box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
4196
+ }
4197
+ .thumbnail > img {
4198
+ display: block;
4199
+ max-width: 100%;
4200
+ margin-left: auto;
4201
+ margin-right: auto;
4202
+ }
4203
+ .thumbnail .caption {
4204
+ padding: 9px;
4205
+ color: #555555;
4206
+ }
4207
+ .alert {
4208
+ padding: 8px 35px 8px 14px;
4209
+ margin-bottom: 20px;
4210
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
4211
+ background-color: #fcf8e3;
4212
+ border: 1px solid #fbeed5;
4213
+ -webkit-border-radius: 4px;
4214
+ -moz-border-radius: 4px;
4215
+ border-radius: 4px;
4216
+ }
4217
+ .alert,
4218
+ .alert h4 {
4219
+ color: #c09853;
4220
+ }
4221
+ .alert h4 {
4222
+ margin: 0;
4223
+ }
4224
+ .alert .close {
4225
+ position: relative;
4226
+ top: -2px;
4227
+ right: -21px;
4228
+ line-height: 20px;
4229
+ }
4230
+ .alert-success {
4231
+ background-color: #dff0d8;
4232
+ border-color: #d6e9c6;
4233
+ color: #468847;
4234
+ }
4235
+ .alert-success h4 {
4236
+ color: #468847;
4237
+ }
4238
+ .alert-danger,
4239
+ .alert-error {
4240
+ background-color: #f2dede;
4241
+ border-color: #eed3d7;
4242
+ color: #b94a48;
4243
+ }
4244
+ .alert-danger h4,
4245
+ .alert-error h4 {
4246
+ color: #b94a48;
4247
+ }
4248
+ .alert-info {
4249
+ background-color: #d9edf7;
4250
+ border-color: #bce8f1;
4251
+ color: #3a87ad;
4252
+ }
4253
+ .alert-info h4 {
4254
+ color: #3a87ad;
4255
+ }
4256
+ .alert-block {
4257
+ padding-top: 14px;
4258
+ padding-bottom: 14px;
4259
+ }
4260
+ .alert-block > p,
4261
+ .alert-block > ul {
4262
+ margin-bottom: 0;
4263
+ }
4264
+ .alert-block p + p {
4265
+ margin-top: 5px;
4266
+ }
4267
+ @-webkit-keyframes progress-bar-stripes {
4268
+ from {
4269
+ background-position: 40px 0;
4270
+ }
4271
+ to {
4272
+ background-position: 0 0;
4273
+ }
4274
+ }
4275
+ @-moz-keyframes progress-bar-stripes {
4276
+ from {
4277
+ background-position: 40px 0;
4278
+ }
4279
+ to {
4280
+ background-position: 0 0;
4281
+ }
4282
+ }
4283
+ @-ms-keyframes progress-bar-stripes {
4284
+ from {
4285
+ background-position: 40px 0;
4286
+ }
4287
+ to {
4288
+ background-position: 0 0;
4289
+ }
4290
+ }
4291
+ @-o-keyframes progress-bar-stripes {
4292
+ from {
4293
+ background-position: 0 0;
4294
+ }
4295
+ to {
4296
+ background-position: 40px 0;
4297
+ }
4298
+ }
4299
+ @keyframes progress-bar-stripes {
4300
+ from {
4301
+ background-position: 40px 0;
4302
+ }
4303
+ to {
4304
+ background-position: 0 0;
4305
+ }
4306
+ }
4307
+ .progress {
4308
+ overflow: hidden;
4309
+ height: 20px;
4310
+ margin-bottom: 20px;
4311
+ background-color: #f7f7f7;
4312
+ background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);
4313
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));
4314
+ background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);
4315
+ background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);
4316
+ background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);
4317
+ background-repeat: repeat-x;
4318
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);
4319
+ -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
4320
+ -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
4321
+ box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
4322
+ -webkit-border-radius: 4px;
4323
+ -moz-border-radius: 4px;
4324
+ border-radius: 4px;
4325
+ }
4326
+ .progress .bar {
4327
+ width: 0%;
4328
+ height: 100%;
4329
+ color: #ffffff;
4330
+ float: left;
4331
+ font-size: 12px;
4332
+ text-align: center;
4333
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
4334
+ background-color: #0e90d2;
4335
+ background-image: -moz-linear-gradient(top, #149bdf, #0480be);
4336
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));
4337
+ background-image: -webkit-linear-gradient(top, #149bdf, #0480be);
4338
+ background-image: -o-linear-gradient(top, #149bdf, #0480be);
4339
+ background-image: linear-gradient(to bottom, #149bdf, #0480be);
4340
+ background-repeat: repeat-x;
4341
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);
4342
+ -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
4343
+ -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
4344
+ box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
4345
+ -webkit-box-sizing: border-box;
4346
+ -moz-box-sizing: border-box;
4347
+ box-sizing: border-box;
4348
+ -webkit-transition: width 0.6s ease;
4349
+ -moz-transition: width 0.6s ease;
4350
+ -o-transition: width 0.6s ease;
4351
+ transition: width 0.6s ease;
4352
+ }
4353
+ .progress .bar + .bar {
4354
+ -webkit-box-shadow: inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15);
4355
+ -moz-box-shadow: inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15);
4356
+ box-shadow: inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15);
4357
+ }
4358
+ .progress-striped .bar {
4359
+ background-color: #149bdf;
4360
+ background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
4361
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4362
+ background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4363
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4364
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4365
+ -webkit-background-size: 40px 40px;
4366
+ -moz-background-size: 40px 40px;
4367
+ -o-background-size: 40px 40px;
4368
+ background-size: 40px 40px;
4369
+ }
4370
+ .progress.active .bar {
4371
+ -webkit-animation: progress-bar-stripes 2s linear infinite;
4372
+ -moz-animation: progress-bar-stripes 2s linear infinite;
4373
+ -ms-animation: progress-bar-stripes 2s linear infinite;
4374
+ -o-animation: progress-bar-stripes 2s linear infinite;
4375
+ animation: progress-bar-stripes 2s linear infinite;
4376
+ }
4377
+ .progress-danger .bar,
4378
+ .progress .bar-danger {
4379
+ background-color: #dd514c;
4380
+ background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);
4381
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));
4382
+ background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);
4383
+ background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);
4384
+ background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);
4385
+ background-repeat: repeat-x;
4386
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);
4387
+ }
4388
+ .progress-danger.progress-striped .bar,
4389
+ .progress-striped .bar-danger {
4390
+ background-color: #ee5f5b;
4391
+ background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
4392
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4393
+ background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4394
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4395
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4396
+ }
4397
+ .progress-success .bar,
4398
+ .progress .bar-success {
4399
+ background-color: #5eb95e;
4400
+ background-image: -moz-linear-gradient(top, #62c462, #57a957);
4401
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));
4402
+ background-image: -webkit-linear-gradient(top, #62c462, #57a957);
4403
+ background-image: -o-linear-gradient(top, #62c462, #57a957);
4404
+ background-image: linear-gradient(to bottom, #62c462, #57a957);
4405
+ background-repeat: repeat-x;
4406
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);
4407
+ }
4408
+ .progress-success.progress-striped .bar,
4409
+ .progress-striped .bar-success {
4410
+ background-color: #62c462;
4411
+ background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
4412
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4413
+ background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4414
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4415
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4416
+ }
4417
+ .progress-info .bar,
4418
+ .progress .bar-info {
4419
+ background-color: #4bb1cf;
4420
+ background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);
4421
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));
4422
+ background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);
4423
+ background-image: -o-linear-gradient(top, #5bc0de, #339bb9);
4424
+ background-image: linear-gradient(to bottom, #5bc0de, #339bb9);
4425
+ background-repeat: repeat-x;
4426
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);
4427
+ }
4428
+ .progress-info.progress-striped .bar,
4429
+ .progress-striped .bar-info {
4430
+ background-color: #5bc0de;
4431
+ background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
4432
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4433
+ background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4434
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4435
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4436
+ }
4437
+ .progress-warning .bar,
4438
+ .progress .bar-warning {
4439
+ background-color: #faa732;
4440
+ background-image: -moz-linear-gradient(top, #fbb450, #f89406);
4441
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));
4442
+ background-image: -webkit-linear-gradient(top, #fbb450, #f89406);
4443
+ background-image: -o-linear-gradient(top, #fbb450, #f89406);
4444
+ background-image: linear-gradient(to bottom, #fbb450, #f89406);
4445
+ background-repeat: repeat-x;
4446
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);
4447
+ }
4448
+ .progress-warning.progress-striped .bar,
4449
+ .progress-striped .bar-warning {
4450
+ background-color: #fbb450;
4451
+ background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
4452
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4453
+ background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4454
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4455
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4456
+ }
4457
+ .hero-unit {
4458
+ padding: 60px;
4459
+ margin-bottom: 30px;
4460
+ font-size: 18px;
4461
+ font-weight: 200;
4462
+ line-height: 30px;
4463
+ color: inherit;
4464
+ background-color: #eeeeee;
4465
+ -webkit-border-radius: 6px;
4466
+ -moz-border-radius: 6px;
4467
+ border-radius: 6px;
4468
+ }
4469
+ .hero-unit h1 {
4470
+ margin-bottom: 0;
4471
+ font-size: 60px;
4472
+ line-height: 1;
4473
+ color: inherit;
4474
+ letter-spacing: -1px;
4475
+ }
4476
+ .hero-unit li {
4477
+ line-height: 30px;
4478
+ }
4479
+ .tooltip {
4480
+ position: absolute;
4481
+ z-index: 1030;
4482
+ display: block;
4483
+ visibility: visible;
4484
+ font-size: 11px;
4485
+ line-height: 1.4;
4486
+ opacity: 0;
4487
+ filter: alpha(opacity=0);
4488
+ }
4489
+ .tooltip.in {
4490
+ opacity: 0.8;
4491
+ filter: alpha(opacity=80);
4492
+ }
4493
+ .tooltip.top {
4494
+ margin-top: -3px;
4495
+ padding: 5px 0;
4496
+ }
4497
+ .tooltip.right {
4498
+ margin-left: 3px;
4499
+ padding: 0 5px;
4500
+ }
4501
+ .tooltip.bottom {
4502
+ margin-top: 3px;
4503
+ padding: 5px 0;
4504
+ }
4505
+ .tooltip.left {
4506
+ margin-left: -3px;
4507
+ padding: 0 5px;
4508
+ }
4509
+ .tooltip-inner {
4510
+ max-width: 200px;
4511
+ padding: 8px;
4512
+ color: #ffffff;
4513
+ text-align: center;
4514
+ text-decoration: none;
4515
+ background-color: #000000;
4516
+ -webkit-border-radius: 4px;
4517
+ -moz-border-radius: 4px;
4518
+ border-radius: 4px;
4519
+ }
4520
+ .tooltip-arrow {
4521
+ position: absolute;
4522
+ width: 0;
4523
+ height: 0;
4524
+ border-color: transparent;
4525
+ border-style: solid;
4526
+ }
4527
+ .tooltip.top .tooltip-arrow {
4528
+ bottom: 0;
4529
+ left: 50%;
4530
+ margin-left: -5px;
4531
+ border-width: 5px 5px 0;
4532
+ border-top-color: #000000;
4533
+ }
4534
+ .tooltip.right .tooltip-arrow {
4535
+ top: 50%;
4536
+ left: 0;
4537
+ margin-top: -5px;
4538
+ border-width: 5px 5px 5px 0;
4539
+ border-right-color: #000000;
4540
+ }
4541
+ .tooltip.left .tooltip-arrow {
4542
+ top: 50%;
4543
+ right: 0;
4544
+ margin-top: -5px;
4545
+ border-width: 5px 0 5px 5px;
4546
+ border-left-color: #000000;
4547
+ }
4548
+ .tooltip.bottom .tooltip-arrow {
4549
+ top: 0;
4550
+ left: 50%;
4551
+ margin-left: -5px;
4552
+ border-width: 0 5px 5px;
4553
+ border-bottom-color: #000000;
4554
+ }
4555
+ .popover {
4556
+ position: absolute;
4557
+ top: 0;
4558
+ left: 0;
4559
+ z-index: 1010;
4560
+ display: none;
4561
+ max-width: 276px;
4562
+ padding: 1px;
4563
+ text-align: left;
4564
+ background-color: #ffffff;
4565
+ -webkit-background-clip: padding-box;
4566
+ -moz-background-clip: padding;
4567
+ background-clip: padding-box;
4568
+ border: 1px solid #ccc;
4569
+ border: 1px solid rgba(0, 0, 0, 0.2);
4570
+ -webkit-border-radius: 6px;
4571
+ -moz-border-radius: 6px;
4572
+ border-radius: 6px;
4573
+ -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
4574
+ -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
4575
+ box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
4576
+ white-space: normal;
4577
+ }
4578
+ .popover.top {
4579
+ margin-top: -10px;
4580
+ }
4581
+ .popover.right {
4582
+ margin-left: 10px;
4583
+ }
4584
+ .popover.bottom {
4585
+ margin-top: 10px;
4586
+ }
4587
+ .popover.left {
4588
+ margin-left: -10px;
4589
+ }
4590
+ .popover-title {
4591
+ margin: 0;
4592
+ padding: 8px 14px;
4593
+ font-size: 14px;
4594
+ font-weight: normal;
4595
+ line-height: 18px;
4596
+ background-color: #f7f7f7;
4597
+ border-bottom: 1px solid #ebebeb;
4598
+ -webkit-border-radius: 5px 5px 0 0;
4599
+ -moz-border-radius: 5px 5px 0 0;
4600
+ border-radius: 5px 5px 0 0;
4601
+ }
4602
+ .popover-title:empty {
4603
+ display: none;
4604
+ }
4605
+ .popover-content {
4606
+ padding: 9px 14px;
4607
+ }
4608
+ .popover .arrow,
4609
+ .popover .arrow:after {
4610
+ position: absolute;
4611
+ display: block;
4612
+ width: 0;
4613
+ height: 0;
4614
+ border-color: transparent;
4615
+ border-style: solid;
4616
+ }
4617
+ .popover .arrow {
4618
+ border-width: 11px;
4619
+ }
4620
+ .popover .arrow:after {
4621
+ border-width: 10px;
4622
+ content: "";
4623
+ }
4624
+ .popover.top .arrow {
4625
+ left: 50%;
4626
+ margin-left: -11px;
4627
+ border-bottom-width: 0;
4628
+ border-top-color: #999;
4629
+ border-top-color: rgba(0, 0, 0, 0.25);
4630
+ bottom: -11px;
4631
+ }
4632
+ .popover.top .arrow:after {
4633
+ bottom: 1px;
4634
+ margin-left: -10px;
4635
+ border-bottom-width: 0;
4636
+ border-top-color: #ffffff;
4637
+ }
4638
+ .popover.right .arrow {
4639
+ top: 50%;
4640
+ left: -11px;
4641
+ margin-top: -11px;
4642
+ border-left-width: 0;
4643
+ border-right-color: #999;
4644
+ border-right-color: rgba(0, 0, 0, 0.25);
4645
+ }
4646
+ .popover.right .arrow:after {
4647
+ left: 1px;
4648
+ bottom: -10px;
4649
+ border-left-width: 0;
4650
+ border-right-color: #ffffff;
4651
+ }
4652
+ .popover.bottom .arrow {
4653
+ left: 50%;
4654
+ margin-left: -11px;
4655
+ border-top-width: 0;
4656
+ border-bottom-color: #999;
4657
+ border-bottom-color: rgba(0, 0, 0, 0.25);
4658
+ top: -11px;
4659
+ }
4660
+ .popover.bottom .arrow:after {
4661
+ top: 1px;
4662
+ margin-left: -10px;
4663
+ border-top-width: 0;
4664
+ border-bottom-color: #ffffff;
4665
+ }
4666
+ .popover.left .arrow {
4667
+ top: 50%;
4668
+ right: -11px;
4669
+ margin-top: -11px;
4670
+ border-right-width: 0;
4671
+ border-left-color: #999;
4672
+ border-left-color: rgba(0, 0, 0, 0.25);
4673
+ }
4674
+ .popover.left .arrow:after {
4675
+ right: 1px;
4676
+ border-right-width: 0;
4677
+ border-left-color: #ffffff;
4678
+ bottom: -10px;
4679
+ }
4680
+ .modal-backdrop {
4681
+ position: fixed;
4682
+ top: 0;
4683
+ right: 0;
4684
+ bottom: 0;
4685
+ left: 0;
4686
+ z-index: 1040;
4687
+ background-color: #000000;
4688
+ }
4689
+ .modal-backdrop.fade {
4690
+ opacity: 0;
4691
+ }
4692
+ .modal-backdrop,
4693
+ .modal-backdrop.fade.in {
4694
+ opacity: 0.8;
4695
+ filter: alpha(opacity=80);
4696
+ }
4697
+ .modal {
4698
+ position: fixed;
4699
+ top: 10%;
4700
+ left: 50%;
4701
+ z-index: 1050;
4702
+ width: 560px;
4703
+ margin-left: -280px;
4704
+ background-color: #ffffff;
4705
+ border: 1px solid #999;
4706
+ border: 1px solid rgba(0, 0, 0, 0.3);
4707
+ *border: 1px solid #999;
4708
+ /* IE6-7 */
4709
+
4710
+ -webkit-border-radius: 6px;
4711
+ -moz-border-radius: 6px;
4712
+ border-radius: 6px;
4713
+ -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
4714
+ -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
4715
+ box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
4716
+ -webkit-background-clip: padding-box;
4717
+ -moz-background-clip: padding-box;
4718
+ background-clip: padding-box;
4719
+ outline: none;
4720
+ }
4721
+ .modal.fade {
4722
+ -webkit-transition: opacity .3s linear, top .3s ease-out;
4723
+ -moz-transition: opacity .3s linear, top .3s ease-out;
4724
+ -o-transition: opacity .3s linear, top .3s ease-out;
4725
+ transition: opacity .3s linear, top .3s ease-out;
4726
+ top: -25%;
4727
+ }
4728
+ .modal.fade.in {
4729
+ top: 10%;
4730
+ }
4731
+ .modal-header {
4732
+ padding: 9px 15px;
4733
+ border-bottom: 1px solid #eee;
4734
+ }
4735
+ .modal-header .close {
4736
+ margin-top: 2px;
4737
+ }
4738
+ .modal-header h3 {
4739
+ margin: 0;
4740
+ line-height: 30px;
4741
+ }
4742
+ .modal-body {
4743
+ position: relative;
4744
+ overflow-y: auto;
4745
+ max-height: 400px;
4746
+ padding: 15px;
4747
+ }
4748
+ .modal-form {
4749
+ margin-bottom: 0;
4750
+ }
4751
+ .modal-footer {
4752
+ padding: 14px 15px 15px;
4753
+ margin-bottom: 0;
4754
+ text-align: right;
4755
+ background-color: #f5f5f5;
4756
+ border-top: 1px solid #ddd;
4757
+ -webkit-border-radius: 0 0 6px 6px;
4758
+ -moz-border-radius: 0 0 6px 6px;
4759
+ border-radius: 0 0 6px 6px;
4760
+ -webkit-box-shadow: inset 0 1px 0 #ffffff;
4761
+ -moz-box-shadow: inset 0 1px 0 #ffffff;
4762
+ box-shadow: inset 0 1px 0 #ffffff;
4763
+ *zoom: 1;
4764
+ }
4765
+ .modal-footer:before,
4766
+ .modal-footer:after {
4767
+ display: table;
4768
+ content: "";
4769
+ line-height: 0;
4770
+ }
4771
+ .modal-footer:after {
4772
+ clear: both;
4773
+ }
4774
+ .modal-footer .btn + .btn {
4775
+ margin-left: 5px;
4776
+ margin-bottom: 0;
4777
+ }
4778
+ .modal-footer .btn-group .btn + .btn {
4779
+ margin-left: -1px;
4780
+ }
4781
+ .modal-footer .btn-block + .btn-block {
4782
+ margin-left: 0;
4783
+ }
4784
+ .dropup,
4785
+ .dropdown {
4786
+ position: relative;
4787
+ }
4788
+ .dropdown-toggle {
4789
+ *margin-bottom: -3px;
4790
+ }
4791
+ .dropdown-toggle:active,
4792
+ .open .dropdown-toggle {
4793
+ outline: 0;
4794
+ }
4795
+ .caret {
4796
+ display: inline-block;
4797
+ width: 0;
4798
+ height: 0;
4799
+ vertical-align: top;
4800
+ border-top: 4px solid #000000;
4801
+ border-right: 4px solid transparent;
4802
+ border-left: 4px solid transparent;
4803
+ content: "";
4804
+ }
4805
+ .dropdown .caret {
4806
+ margin-top: 8px;
4807
+ margin-left: 2px;
4808
+ }
4809
+ .dropdown-menu {
4810
+ position: absolute;
4811
+ top: 100%;
4812
+ left: 0;
4813
+ z-index: 1000;
4814
+ display: none;
4815
+ float: left;
4816
+ min-width: 160px;
4817
+ padding: 5px 0;
4818
+ margin: 2px 0 0;
4819
+ list-style: none;
4820
+ background-color: #ffffff;
4821
+ border: 1px solid #ccc;
4822
+ border: 1px solid rgba(0, 0, 0, 0.2);
4823
+ *border-right-width: 2px;
4824
+ *border-bottom-width: 2px;
4825
+ -webkit-border-radius: 6px;
4826
+ -moz-border-radius: 6px;
4827
+ border-radius: 6px;
4828
+ -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
4829
+ -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
4830
+ box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
4831
+ -webkit-background-clip: padding-box;
4832
+ -moz-background-clip: padding;
4833
+ background-clip: padding-box;
4834
+ }
4835
+ .dropdown-menu.pull-right {
4836
+ right: 0;
4837
+ left: auto;
4838
+ }
4839
+ .dropdown-menu .divider {
4840
+ *width: 100%;
4841
+ height: 1px;
4842
+ margin: 9px 1px;
4843
+ *margin: -5px 0 5px;
4844
+ overflow: hidden;
4845
+ background-color: #e5e5e5;
4846
+ border-bottom: 1px solid #ffffff;
4847
+ }
4848
+ .dropdown-menu > li > a {
4849
+ display: block;
4850
+ padding: 3px 20px;
4851
+ clear: both;
4852
+ font-weight: normal;
4853
+ line-height: 20px;
4854
+ color: #333333;
4855
+ white-space: nowrap;
4856
+ }
4857
+ .dropdown-menu > li > a:hover,
4858
+ .dropdown-menu > li > a:focus,
4859
+ .dropdown-submenu:hover > a,
4860
+ .dropdown-submenu:focus > a {
4861
+ text-decoration: none;
4862
+ color: #ffffff;
4863
+ background-color: #0081c2;
4864
+ background-image: -moz-linear-gradient(top, #0088cc, #0077b3);
4865
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));
4866
+ background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);
4867
+ background-image: -o-linear-gradient(top, #0088cc, #0077b3);
4868
+ background-image: linear-gradient(to bottom, #0088cc, #0077b3);
4869
+ background-repeat: repeat-x;
4870
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);
4871
+ }
4872
+ .dropdown-menu > .active > a,
4873
+ .dropdown-menu > .active > a:hover,
4874
+ .dropdown-menu > .active > a:focus {
4875
+ color: #ffffff;
4876
+ text-decoration: none;
4877
+ outline: 0;
4878
+ background-color: #0081c2;
4879
+ background-image: -moz-linear-gradient(top, #0088cc, #0077b3);
4880
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));
4881
+ background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);
4882
+ background-image: -o-linear-gradient(top, #0088cc, #0077b3);
4883
+ background-image: linear-gradient(to bottom, #0088cc, #0077b3);
4884
+ background-repeat: repeat-x;
4885
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);
4886
+ }
4887
+ .dropdown-menu > .disabled > a,
4888
+ .dropdown-menu > .disabled > a:hover,
4889
+ .dropdown-menu > .disabled > a:focus {
4890
+ color: #999999;
4891
+ }
4892
+ .dropdown-menu > .disabled > a:hover,
4893
+ .dropdown-menu > .disabled > a:focus {
4894
+ text-decoration: none;
4895
+ background-color: transparent;
4896
+ background-image: none;
4897
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
4898
+ cursor: default;
4899
+ }
4900
+ .open {
4901
+ *z-index: 1000;
4902
+ }
4903
+ .open > .dropdown-menu {
4904
+ display: block;
4905
+ }
4906
+ .pull-right > .dropdown-menu {
4907
+ right: 0;
4908
+ left: auto;
4909
+ }
4910
+ .dropup .caret,
4911
+ .navbar-fixed-bottom .dropdown .caret {
4912
+ border-top: 0;
4913
+ border-bottom: 4px solid #000000;
4914
+ content: "";
4915
+ }
4916
+ .dropup .dropdown-menu,
4917
+ .navbar-fixed-bottom .dropdown .dropdown-menu {
4918
+ top: auto;
4919
+ bottom: 100%;
4920
+ margin-bottom: 1px;
4921
+ }
4922
+ .dropdown-submenu {
4923
+ position: relative;
4924
+ }
4925
+ .dropdown-submenu > .dropdown-menu {
4926
+ top: 0;
4927
+ left: 100%;
4928
+ margin-top: -6px;
4929
+ margin-left: -1px;
4930
+ -webkit-border-radius: 0 6px 6px 6px;
4931
+ -moz-border-radius: 0 6px 6px 6px;
4932
+ border-radius: 0 6px 6px 6px;
4933
+ }
4934
+ .dropdown-submenu:hover > .dropdown-menu {
4935
+ display: block;
4936
+ }
4937
+ .dropup .dropdown-submenu > .dropdown-menu {
4938
+ top: auto;
4939
+ bottom: 0;
4940
+ margin-top: 0;
4941
+ margin-bottom: -2px;
4942
+ -webkit-border-radius: 5px 5px 5px 0;
4943
+ -moz-border-radius: 5px 5px 5px 0;
4944
+ border-radius: 5px 5px 5px 0;
4945
+ }
4946
+ .dropdown-submenu > a:after {
4947
+ display: block;
4948
+ content: " ";
4949
+ float: right;
4950
+ width: 0;
4951
+ height: 0;
4952
+ border-color: transparent;
4953
+ border-style: solid;
4954
+ border-width: 5px 0 5px 5px;
4955
+ border-left-color: #cccccc;
4956
+ margin-top: 5px;
4957
+ margin-right: -10px;
4958
+ }
4959
+ .dropdown-submenu:hover > a:after {
4960
+ border-left-color: #ffffff;
4961
+ }
4962
+ .dropdown-submenu.pull-left {
4963
+ float: none;
4964
+ }
4965
+ .dropdown-submenu.pull-left > .dropdown-menu {
4966
+ left: -100%;
4967
+ margin-left: 10px;
4968
+ -webkit-border-radius: 6px 0 6px 6px;
4969
+ -moz-border-radius: 6px 0 6px 6px;
4970
+ border-radius: 6px 0 6px 6px;
4971
+ }
4972
+ .dropdown .dropdown-menu .nav-header {
4973
+ padding-left: 20px;
4974
+ padding-right: 20px;
4975
+ }
4976
+ .typeahead {
4977
+ z-index: 1051;
4978
+ margin-top: 2px;
4979
+ -webkit-border-radius: 4px;
4980
+ -moz-border-radius: 4px;
4981
+ border-radius: 4px;
4982
+ }
4983
+ .accordion {
4984
+ margin-bottom: 20px;
4985
+ }
4986
+ .accordion-group {
4987
+ margin-bottom: 2px;
4988
+ border: 1px solid #e5e5e5;
4989
+ -webkit-border-radius: 4px;
4990
+ -moz-border-radius: 4px;
4991
+ border-radius: 4px;
4992
+ }
4993
+ .accordion-heading {
4994
+ border-bottom: 0;
4995
+ }
4996
+ .accordion-heading .accordion-toggle {
4997
+ display: block;
4998
+ padding: 8px 15px;
4999
+ }
5000
+ .accordion-toggle {
5001
+ cursor: pointer;
5002
+ }
5003
+ .accordion-inner {
5004
+ padding: 9px 15px;
5005
+ border-top: 1px solid #e5e5e5;
5006
+ }
5007
+ .carousel {
5008
+ position: relative;
5009
+ margin-bottom: 20px;
5010
+ line-height: 1;
5011
+ }
5012
+ .carousel-inner {
5013
+ overflow: hidden;
5014
+ width: 100%;
5015
+ position: relative;
5016
+ }
5017
+ .carousel-inner > .item {
5018
+ display: none;
5019
+ position: relative;
5020
+ -webkit-transition: 0.6s ease-in-out left;
5021
+ -moz-transition: 0.6s ease-in-out left;
5022
+ -o-transition: 0.6s ease-in-out left;
5023
+ transition: 0.6s ease-in-out left;
5024
+ }
5025
+ .carousel-inner > .item > img,
5026
+ .carousel-inner > .item > a > img {
5027
+ display: block;
5028
+ line-height: 1;
5029
+ }
5030
+ .carousel-inner > .active,
5031
+ .carousel-inner > .next,
5032
+ .carousel-inner > .prev {
5033
+ display: block;
5034
+ }
5035
+ .carousel-inner > .active {
5036
+ left: 0;
5037
+ }
5038
+ .carousel-inner > .next,
5039
+ .carousel-inner > .prev {
5040
+ position: absolute;
5041
+ top: 0;
5042
+ width: 100%;
5043
+ }
5044
+ .carousel-inner > .next {
5045
+ left: 100%;
5046
+ }
5047
+ .carousel-inner > .prev {
5048
+ left: -100%;
5049
+ }
5050
+ .carousel-inner > .next.left,
5051
+ .carousel-inner > .prev.right {
5052
+ left: 0;
5053
+ }
5054
+ .carousel-inner > .active.left {
5055
+ left: -100%;
5056
+ }
5057
+ .carousel-inner > .active.right {
5058
+ left: 100%;
5059
+ }
5060
+ .carousel-control {
5061
+ position: absolute;
5062
+ top: 40%;
5063
+ left: 15px;
5064
+ width: 40px;
5065
+ height: 40px;
5066
+ margin-top: -20px;
5067
+ font-size: 60px;
5068
+ font-weight: 100;
5069
+ line-height: 30px;
5070
+ color: #ffffff;
5071
+ text-align: center;
5072
+ background: #222222;
5073
+ border: 3px solid #ffffff;
5074
+ -webkit-border-radius: 23px;
5075
+ -moz-border-radius: 23px;
5076
+ border-radius: 23px;
5077
+ opacity: 0.5;
5078
+ filter: alpha(opacity=50);
5079
+ }
5080
+ .carousel-control.right {
5081
+ left: auto;
5082
+ right: 15px;
5083
+ }
5084
+ .carousel-control:hover,
5085
+ .carousel-control:focus {
5086
+ color: #ffffff;
5087
+ text-decoration: none;
5088
+ opacity: 0.9;
5089
+ filter: alpha(opacity=90);
5090
+ }
5091
+ .carousel-indicators {
5092
+ position: absolute;
5093
+ top: 15px;
5094
+ right: 15px;
5095
+ z-index: 5;
5096
+ margin: 0;
5097
+ list-style: none;
5098
+ }
5099
+ .carousel-indicators li {
5100
+ display: block;
5101
+ float: left;
5102
+ width: 10px;
5103
+ height: 10px;
5104
+ margin-left: 5px;
5105
+ text-indent: -999px;
5106
+ background-color: #ccc;
5107
+ background-color: rgba(255, 255, 255, 0.25);
5108
+ border-radius: 5px;
5109
+ }
5110
+ .carousel-indicators .active {
5111
+ background-color: #fff;
5112
+ }
5113
+ .carousel-caption {
5114
+ position: absolute;
5115
+ left: 0;
5116
+ right: 0;
5117
+ bottom: 0;
5118
+ padding: 15px;
5119
+ background: #333333;
5120
+ background: rgba(0, 0, 0, 0.75);
5121
+ }
5122
+ .carousel-caption h4,
5123
+ .carousel-caption p {
5124
+ color: #ffffff;
5125
+ line-height: 20px;
5126
+ }
5127
+ .carousel-caption h4 {
5128
+ margin: 0 0 5px;
5129
+ }
5130
+ .carousel-caption p {
5131
+ margin-bottom: 0;
5132
+ }
5133
+ .well {
5134
+ min-height: 20px;
5135
+ padding: 19px;
5136
+ margin-bottom: 20px;
5137
+ background-color: #f5f5f5;
5138
+ border: 1px solid #e3e3e3;
5139
+ -webkit-border-radius: 4px;
5140
+ -moz-border-radius: 4px;
5141
+ border-radius: 4px;
5142
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
5143
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
5144
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
5145
+ }
5146
+ .well blockquote {
5147
+ border-color: #ddd;
5148
+ border-color: rgba(0, 0, 0, 0.15);
5149
+ }
5150
+ .well-large {
5151
+ padding: 24px;
5152
+ -webkit-border-radius: 6px;
5153
+ -moz-border-radius: 6px;
5154
+ border-radius: 6px;
5155
+ }
5156
+ .well-small {
5157
+ padding: 9px;
5158
+ -webkit-border-radius: 3px;
5159
+ -moz-border-radius: 3px;
5160
+ border-radius: 3px;
5161
+ }
5162
+ .close {
5163
+ float: right;
5164
+ font-size: 20px;
5165
+ font-weight: bold;
5166
+ line-height: 20px;
5167
+ color: #000000;
5168
+ text-shadow: 0 1px 0 #ffffff;
5169
+ opacity: 0.2;
5170
+ filter: alpha(opacity=20);
5171
+ }
5172
+ .close:hover,
5173
+ .close:focus {
5174
+ color: #000000;
5175
+ text-decoration: none;
5176
+ cursor: pointer;
5177
+ opacity: 0.4;
5178
+ filter: alpha(opacity=40);
5179
+ }
5180
+ button.close {
5181
+ padding: 0;
5182
+ cursor: pointer;
5183
+ background: transparent;
5184
+ border: 0;
5185
+ -webkit-appearance: none;
5186
+ }
5187
+ .pull-right {
5188
+ float: right;
5189
+ }
5190
+ .pull-left {
5191
+ float: left;
5192
+ }
5193
+ .hide {
5194
+ display: none;
5195
+ }
5196
+ .show {
5197
+ display: block;
5198
+ }
5199
+ .invisible {
5200
+ visibility: hidden;
5201
+ }
5202
+ .affix {
5203
+ position: fixed;
5204
+ }
5205
+ .fade {
5206
+ opacity: 0;
5207
+ -webkit-transition: opacity 0.15s linear;
5208
+ -moz-transition: opacity 0.15s linear;
5209
+ -o-transition: opacity 0.15s linear;
5210
+ transition: opacity 0.15s linear;
5211
+ }
5212
+ .fade.in {
5213
+ opacity: 1;
5214
+ }
5215
+ .collapse {
5216
+ position: relative;
5217
+ height: 0;
5218
+ overflow: hidden;
5219
+ -webkit-transition: height 0.35s ease;
5220
+ -moz-transition: height 0.35s ease;
5221
+ -o-transition: height 0.35s ease;
5222
+ transition: height 0.35s ease;
5223
+ }
5224
+ .collapse.in {
5225
+ height: auto;
5226
+ }
5227
+ @-ms-viewport {
5228
+ width: device-width;
5229
+ }
5230
+ .hidden {
5231
+ display: none;
5232
+ visibility: hidden;
5233
+ }
5234
+ .visible-phone {
5235
+ display: none !important;
5236
+ }
5237
+ .visible-tablet {
5238
+ display: none !important;
5239
+ }
5240
+ .hidden-desktop {
5241
+ display: none !important;
5242
+ }
5243
+ .visible-desktop {
5244
+ display: inherit !important;
5245
+ }
5246
+ @media (min-width: 768px) and (max-width: 979px) {
5247
+ .hidden-desktop {
5248
+ display: inherit !important;
5249
+ }
5250
+ .visible-desktop {
5251
+ display: none !important ;
5252
+ }
5253
+ .visible-tablet {
5254
+ display: inherit !important;
5255
+ }
5256
+ .hidden-tablet {
5257
+ display: none !important;
5258
+ }
5259
+ }
5260
+ @media (max-width: 767px) {
5261
+ .hidden-desktop {
5262
+ display: inherit !important;
5263
+ }
5264
+ .visible-desktop {
5265
+ display: none !important;
5266
+ }
5267
+ .visible-phone {
5268
+ display: inherit !important;
5269
+ }
5270
+ .hidden-phone {
5271
+ display: none !important;
5272
+ }
5273
+ }
5274
+ .visible-print {
5275
+ display: none !important;
5276
+ }
5277
+ @media print {
5278
+ .visible-print {
5279
+ display: inherit !important;
5280
+ }
5281
+ .hidden-print {
5282
+ display: none !important;
5283
+ }
5284
+ }
5285
+ @media (max-width: 767px) {
5286
+ body {
5287
+ padding-left: 20px;
5288
+ padding-right: 20px;
5289
+ }
5290
+ .navbar-fixed-top,
5291
+ .navbar-fixed-bottom,
5292
+ .navbar-static-top {
5293
+ margin-left: -20px;
5294
+ margin-right: -20px;
5295
+ }
5296
+ .container-fluid {
5297
+ padding: 0;
5298
+ }
5299
+ .dl-horizontal dt {
5300
+ float: none;
5301
+ clear: none;
5302
+ width: auto;
5303
+ text-align: left;
5304
+ }
5305
+ .dl-horizontal dd {
5306
+ margin-left: 0;
5307
+ }
5308
+ .container {
5309
+ width: auto;
5310
+ }
5311
+ .row-fluid {
5312
+ width: 100%;
5313
+ }
5314
+ .row,
5315
+ .thumbnails {
5316
+ margin-left: 0;
5317
+ }
5318
+ .thumbnails > li {
5319
+ float: none;
5320
+ margin-left: 0;
5321
+ }
5322
+ [class*="span"],
5323
+ .uneditable-input[class*="span"],
5324
+ .row-fluid [class*="span"] {
5325
+ float: none;
5326
+ display: block;
5327
+ width: 100%;
5328
+ margin-left: 0;
5329
+ -webkit-box-sizing: border-box;
5330
+ -moz-box-sizing: border-box;
5331
+ box-sizing: border-box;
5332
+ }
5333
+ .span12,
5334
+ .row-fluid .span12 {
5335
+ width: 100%;
5336
+ -webkit-box-sizing: border-box;
5337
+ -moz-box-sizing: border-box;
5338
+ box-sizing: border-box;
5339
+ }
5340
+ .row-fluid [class*="offset"]:first-child {
5341
+ margin-left: 0;
5342
+ }
5343
+ .input-large,
5344
+ .input-xlarge,
5345
+ .input-xxlarge,
5346
+ input[class*="span"],
5347
+ select[class*="span"],
5348
+ textarea[class*="span"],
5349
+ .uneditable-input {
5350
+ display: block;
5351
+ width: 100%;
5352
+ min-height: 30px;
5353
+ -webkit-box-sizing: border-box;
5354
+ -moz-box-sizing: border-box;
5355
+ box-sizing: border-box;
5356
+ }
5357
+ .input-prepend input,
5358
+ .input-append input,
5359
+ .input-prepend input[class*="span"],
5360
+ .input-append input[class*="span"] {
5361
+ display: inline-block;
5362
+ width: auto;
5363
+ }
5364
+ .controls-row [class*="span"] + [class*="span"] {
5365
+ margin-left: 0;
5366
+ }
5367
+ .modal {
5368
+ position: fixed;
5369
+ top: 20px;
5370
+ left: 20px;
5371
+ right: 20px;
5372
+ width: auto;
5373
+ margin: 0;
5374
+ }
5375
+ .modal.fade {
5376
+ top: -100px;
5377
+ }
5378
+ .modal.fade.in {
5379
+ top: 20px;
5380
+ }
5381
+ }
5382
+ @media (max-width: 480px) {
5383
+ .nav-collapse {
5384
+ -webkit-transform: translate3d(0, 0, 0);
5385
+ }
5386
+ .page-header h1 small {
5387
+ display: block;
5388
+ line-height: 20px;
5389
+ }
5390
+ input[type="checkbox"],
5391
+ input[type="radio"] {
5392
+ border: 1px solid #ccc;
5393
+ }
5394
+ .form-horizontal .control-label {
5395
+ float: none;
5396
+ width: auto;
5397
+ padding-top: 0;
5398
+ text-align: left;
5399
+ }
5400
+ .form-horizontal .controls {
5401
+ margin-left: 0;
5402
+ }
5403
+ .form-horizontal .control-list {
5404
+ padding-top: 0;
5405
+ }
5406
+ .form-horizontal .form-actions {
5407
+ padding-left: 10px;
5408
+ padding-right: 10px;
5409
+ }
5410
+ .media .pull-left,
5411
+ .media .pull-right {
5412
+ float: none;
5413
+ display: block;
5414
+ margin-bottom: 10px;
5415
+ }
5416
+ .media-object {
5417
+ margin-right: 0;
5418
+ margin-left: 0;
5419
+ }
5420
+ .modal {
5421
+ top: 10px;
5422
+ left: 10px;
5423
+ right: 10px;
5424
+ }
5425
+ .modal-header .close {
5426
+ padding: 10px;
5427
+ margin: -10px;
5428
+ }
5429
+ .carousel-caption {
5430
+ position: static;
5431
+ }
5432
+ }
5433
+ @media (min-width: 768px) and (max-width: 979px) {
5434
+ .row {
5435
+ margin-left: -20px;
5436
+ *zoom: 1;
5437
+ }
5438
+ .row:before,
5439
+ .row:after {
5440
+ display: table;
5441
+ content: "";
5442
+ line-height: 0;
5443
+ }
5444
+ .row:after {
5445
+ clear: both;
5446
+ }
5447
+ [class*="span"] {
5448
+ float: left;
5449
+ min-height: 1px;
5450
+ margin-left: 20px;
5451
+ }
5452
+ .container,
5453
+ .navbar-static-top .container,
5454
+ .navbar-fixed-top .container,
5455
+ .navbar-fixed-bottom .container {
5456
+ width: 724px;
5457
+ }
5458
+ .span12 {
5459
+ width: 724px;
5460
+ }
5461
+ .span11 {
5462
+ width: 662px;
5463
+ }
5464
+ .span10 {
5465
+ width: 600px;
5466
+ }
5467
+ .span9 {
5468
+ width: 538px;
5469
+ }
5470
+ .span8 {
5471
+ width: 476px;
5472
+ }
5473
+ .span7 {
5474
+ width: 414px;
5475
+ }
5476
+ .span6 {
5477
+ width: 352px;
5478
+ }
5479
+ .span5 {
5480
+ width: 290px;
5481
+ }
5482
+ .span4 {
5483
+ width: 228px;
5484
+ }
5485
+ .span3 {
5486
+ width: 166px;
5487
+ }
5488
+ .span2 {
5489
+ width: 104px;
5490
+ }
5491
+ .span1 {
5492
+ width: 42px;
5493
+ }
5494
+ .offset12 {
5495
+ margin-left: 764px;
5496
+ }
5497
+ .offset11 {
5498
+ margin-left: 702px;
5499
+ }
5500
+ .offset10 {
5501
+ margin-left: 640px;
5502
+ }
5503
+ .offset9 {
5504
+ margin-left: 578px;
5505
+ }
5506
+ .offset8 {
5507
+ margin-left: 516px;
5508
+ }
5509
+ .offset7 {
5510
+ margin-left: 454px;
5511
+ }
5512
+ .offset6 {
5513
+ margin-left: 392px;
5514
+ }
5515
+ .offset5 {
5516
+ margin-left: 330px;
5517
+ }
5518
+ .offset4 {
5519
+ margin-left: 268px;
5520
+ }
5521
+ .offset3 {
5522
+ margin-left: 206px;
5523
+ }
5524
+ .offset2 {
5525
+ margin-left: 144px;
5526
+ }
5527
+ .offset1 {
5528
+ margin-left: 82px;
5529
+ }
5530
+ .row-fluid {
5531
+ width: 100%;
5532
+ *zoom: 1;
5533
+ }
5534
+ .row-fluid:before,
5535
+ .row-fluid:after {
5536
+ display: table;
5537
+ content: "";
5538
+ line-height: 0;
5539
+ }
5540
+ .row-fluid:after {
5541
+ clear: both;
5542
+ }
5543
+ .row-fluid [class*="span"] {
5544
+ display: block;
5545
+ width: 100%;
5546
+ min-height: 30px;
5547
+ -webkit-box-sizing: border-box;
5548
+ -moz-box-sizing: border-box;
5549
+ box-sizing: border-box;
5550
+ float: left;
5551
+ margin-left: 2.7624309392265194%;
5552
+ *margin-left: 2.709239449864817%;
5553
+ }
5554
+ .row-fluid [class*="span"]:first-child {
5555
+ margin-left: 0;
5556
+ }
5557
+ .row-fluid .controls-row [class*="span"] + [class*="span"] {
5558
+ margin-left: 2.7624309392265194%;
5559
+ }
5560
+ .row-fluid .span12 {
5561
+ width: 100%;
5562
+ *width: 99.94680851063829%;
5563
+ }
5564
+ .row-fluid .span11 {
5565
+ width: 91.43646408839778%;
5566
+ *width: 91.38327259903608%;
5567
+ }
5568
+ .row-fluid .span10 {
5569
+ width: 82.87292817679558%;
5570
+ *width: 82.81973668743387%;
5571
+ }
5572
+ .row-fluid .span9 {
5573
+ width: 74.30939226519337%;
5574
+ *width: 74.25620077583166%;
5575
+ }
5576
+ .row-fluid .span8 {
5577
+ width: 65.74585635359117%;
5578
+ *width: 65.69266486422946%;
5579
+ }
5580
+ .row-fluid .span7 {
5581
+ width: 57.18232044198895%;
5582
+ *width: 57.12912895262725%;
5583
+ }
5584
+ .row-fluid .span6 {
5585
+ width: 48.61878453038674%;
5586
+ *width: 48.56559304102504%;
5587
+ }
5588
+ .row-fluid .span5 {
5589
+ width: 40.05524861878453%;
5590
+ *width: 40.00205712942283%;
5591
+ }
5592
+ .row-fluid .span4 {
5593
+ width: 31.491712707182323%;
5594
+ *width: 31.43852121782062%;
5595
+ }
5596
+ .row-fluid .span3 {
5597
+ width: 22.92817679558011%;
5598
+ *width: 22.87498530621841%;
5599
+ }
5600
+ .row-fluid .span2 {
5601
+ width: 14.3646408839779%;
5602
+ *width: 14.311449394616199%;
5603
+ }
5604
+ .row-fluid .span1 {
5605
+ width: 5.801104972375691%;
5606
+ *width: 5.747913483013988%;
5607
+ }
5608
+ .row-fluid .offset12 {
5609
+ margin-left: 105.52486187845304%;
5610
+ *margin-left: 105.41847889972962%;
5611
+ }
5612
+ .row-fluid .offset12:first-child {
5613
+ margin-left: 102.76243093922652%;
5614
+ *margin-left: 102.6560479605031%;
5615
+ }
5616
+ .row-fluid .offset11 {
5617
+ margin-left: 96.96132596685082%;
5618
+ *margin-left: 96.8549429881274%;
5619
+ }
5620
+ .row-fluid .offset11:first-child {
5621
+ margin-left: 94.1988950276243%;
5622
+ *margin-left: 94.09251204890089%;
5623
+ }
5624
+ .row-fluid .offset10 {
5625
+ margin-left: 88.39779005524862%;
5626
+ *margin-left: 88.2914070765252%;
5627
+ }
5628
+ .row-fluid .offset10:first-child {
5629
+ margin-left: 85.6353591160221%;
5630
+ *margin-left: 85.52897613729868%;
5631
+ }
5632
+ .row-fluid .offset9 {
5633
+ margin-left: 79.8342541436464%;
5634
+ *margin-left: 79.72787116492299%;
5635
+ }
5636
+ .row-fluid .offset9:first-child {
5637
+ margin-left: 77.07182320441989%;
5638
+ *margin-left: 76.96544022569647%;
5639
+ }
5640
+ .row-fluid .offset8 {
5641
+ margin-left: 71.2707182320442%;
5642
+ *margin-left: 71.16433525332079%;
5643
+ }
5644
+ .row-fluid .offset8:first-child {
5645
+ margin-left: 68.50828729281768%;
5646
+ *margin-left: 68.40190431409427%;
5647
+ }
5648
+ .row-fluid .offset7 {
5649
+ margin-left: 62.70718232044199%;
5650
+ *margin-left: 62.600799341718584%;
5651
+ }
5652
+ .row-fluid .offset7:first-child {
5653
+ margin-left: 59.94475138121547%;
5654
+ *margin-left: 59.838368402492065%;
5655
+ }
5656
+ .row-fluid .offset6 {
5657
+ margin-left: 54.14364640883978%;
5658
+ *margin-left: 54.037263430116376%;
5659
+ }
5660
+ .row-fluid .offset6:first-child {
5661
+ margin-left: 51.38121546961326%;
5662
+ *margin-left: 51.27483249088986%;
5663
+ }
5664
+ .row-fluid .offset5 {
5665
+ margin-left: 45.58011049723757%;
5666
+ *margin-left: 45.47372751851417%;
5667
+ }
5668
+ .row-fluid .offset5:first-child {
5669
+ margin-left: 42.81767955801105%;
5670
+ *margin-left: 42.71129657928765%;
5671
+ }
5672
+ .row-fluid .offset4 {
5673
+ margin-left: 37.01657458563536%;
5674
+ *margin-left: 36.91019160691196%;
5675
+ }
5676
+ .row-fluid .offset4:first-child {
5677
+ margin-left: 34.25414364640884%;
5678
+ *margin-left: 34.14776066768544%;
5679
+ }
5680
+ .row-fluid .offset3 {
5681
+ margin-left: 28.45303867403315%;
5682
+ *margin-left: 28.346655695309746%;
5683
+ }
5684
+ .row-fluid .offset3:first-child {
5685
+ margin-left: 25.69060773480663%;
5686
+ *margin-left: 25.584224756083227%;
5687
+ }
5688
+ .row-fluid .offset2 {
5689
+ margin-left: 19.88950276243094%;
5690
+ *margin-left: 19.783119783707537%;
5691
+ }
5692
+ .row-fluid .offset2:first-child {
5693
+ margin-left: 17.12707182320442%;
5694
+ *margin-left: 17.02068884448102%;
5695
+ }
5696
+ .row-fluid .offset1 {
5697
+ margin-left: 11.32596685082873%;
5698
+ *margin-left: 11.219583872105325%;
5699
+ }
5700
+ .row-fluid .offset1:first-child {
5701
+ margin-left: 8.56353591160221%;
5702
+ *margin-left: 8.457152932878806%;
5703
+ }
5704
+ input,
5705
+ textarea,
5706
+ .uneditable-input {
5707
+ margin-left: 0;
5708
+ }
5709
+ .controls-row [class*="span"] + [class*="span"] {
5710
+ margin-left: 20px;
5711
+ }
5712
+ input.span12,
5713
+ textarea.span12,
5714
+ .uneditable-input.span12 {
5715
+ width: 710px;
5716
+ }
5717
+ input.span11,
5718
+ textarea.span11,
5719
+ .uneditable-input.span11 {
5720
+ width: 648px;
5721
+ }
5722
+ input.span10,
5723
+ textarea.span10,
5724
+ .uneditable-input.span10 {
5725
+ width: 586px;
5726
+ }
5727
+ input.span9,
5728
+ textarea.span9,
5729
+ .uneditable-input.span9 {
5730
+ width: 524px;
5731
+ }
5732
+ input.span8,
5733
+ textarea.span8,
5734
+ .uneditable-input.span8 {
5735
+ width: 462px;
5736
+ }
5737
+ input.span7,
5738
+ textarea.span7,
5739
+ .uneditable-input.span7 {
5740
+ width: 400px;
5741
+ }
5742
+ input.span6,
5743
+ textarea.span6,
5744
+ .uneditable-input.span6 {
5745
+ width: 338px;
5746
+ }
5747
+ input.span5,
5748
+ textarea.span5,
5749
+ .uneditable-input.span5 {
5750
+ width: 276px;
5751
+ }
5752
+ input.span4,
5753
+ textarea.span4,
5754
+ .uneditable-input.span4 {
5755
+ width: 214px;
5756
+ }
5757
+ input.span3,
5758
+ textarea.span3,
5759
+ .uneditable-input.span3 {
5760
+ width: 152px;
5761
+ }
5762
+ input.span2,
5763
+ textarea.span2,
5764
+ .uneditable-input.span2 {
5765
+ width: 90px;
5766
+ }
5767
+ input.span1,
5768
+ textarea.span1,
5769
+ .uneditable-input.span1 {
5770
+ width: 28px;
5771
+ }
5772
+ }
5773
+ @media (min-width: 1200px) {
5774
+ .row {
5775
+ margin-left: -30px;
5776
+ *zoom: 1;
5777
+ }
5778
+ .row:before,
5779
+ .row:after {
5780
+ display: table;
5781
+ content: "";
5782
+ line-height: 0;
5783
+ }
5784
+ .row:after {
5785
+ clear: both;
5786
+ }
5787
+ [class*="span"] {
5788
+ float: left;
5789
+ min-height: 1px;
5790
+ margin-left: 30px;
5791
+ }
5792
+ .container,
5793
+ .navbar-static-top .container,
5794
+ .navbar-fixed-top .container,
5795
+ .navbar-fixed-bottom .container {
5796
+ width: 1170px;
5797
+ }
5798
+ .span12 {
5799
+ width: 1170px;
5800
+ }
5801
+ .span11 {
5802
+ width: 1070px;
5803
+ }
5804
+ .span10 {
5805
+ width: 970px;
5806
+ }
5807
+ .span9 {
5808
+ width: 870px;
5809
+ }
5810
+ .span8 {
5811
+ width: 770px;
5812
+ }
5813
+ .span7 {
5814
+ width: 670px;
5815
+ }
5816
+ .span6 {
5817
+ width: 570px;
5818
+ }
5819
+ .span5 {
5820
+ width: 470px;
5821
+ }
5822
+ .span4 {
5823
+ width: 370px;
5824
+ }
5825
+ .span3 {
5826
+ width: 270px;
5827
+ }
5828
+ .span2 {
5829
+ width: 170px;
5830
+ }
5831
+ .span1 {
5832
+ width: 70px;
5833
+ }
5834
+ .offset12 {
5835
+ margin-left: 1230px;
5836
+ }
5837
+ .offset11 {
5838
+ margin-left: 1130px;
5839
+ }
5840
+ .offset10 {
5841
+ margin-left: 1030px;
5842
+ }
5843
+ .offset9 {
5844
+ margin-left: 930px;
5845
+ }
5846
+ .offset8 {
5847
+ margin-left: 830px;
5848
+ }
5849
+ .offset7 {
5850
+ margin-left: 730px;
5851
+ }
5852
+ .offset6 {
5853
+ margin-left: 630px;
5854
+ }
5855
+ .offset5 {
5856
+ margin-left: 530px;
5857
+ }
5858
+ .offset4 {
5859
+ margin-left: 430px;
5860
+ }
5861
+ .offset3 {
5862
+ margin-left: 330px;
5863
+ }
5864
+ .offset2 {
5865
+ margin-left: 230px;
5866
+ }
5867
+ .offset1 {
5868
+ margin-left: 130px;
5869
+ }
5870
+ .row-fluid {
5871
+ width: 100%;
5872
+ *zoom: 1;
5873
+ }
5874
+ .row-fluid:before,
5875
+ .row-fluid:after {
5876
+ display: table;
5877
+ content: "";
5878
+ line-height: 0;
5879
+ }
5880
+ .row-fluid:after {
5881
+ clear: both;
5882
+ }
5883
+ .row-fluid [class*="span"] {
5884
+ display: block;
5885
+ width: 100%;
5886
+ min-height: 30px;
5887
+ -webkit-box-sizing: border-box;
5888
+ -moz-box-sizing: border-box;
5889
+ box-sizing: border-box;
5890
+ float: left;
5891
+ margin-left: 2.564102564102564%;
5892
+ *margin-left: 2.5109110747408616%;
5893
+ }
5894
+ .row-fluid [class*="span"]:first-child {
5895
+ margin-left: 0;
5896
+ }
5897
+ .row-fluid .controls-row [class*="span"] + [class*="span"] {
5898
+ margin-left: 2.564102564102564%;
5899
+ }
5900
+ .row-fluid .span12 {
5901
+ width: 100%;
5902
+ *width: 99.94680851063829%;
5903
+ }
5904
+ .row-fluid .span11 {
5905
+ width: 91.45299145299145%;
5906
+ *width: 91.39979996362975%;
5907
+ }
5908
+ .row-fluid .span10 {
5909
+ width: 82.90598290598291%;
5910
+ *width: 82.8527914166212%;
5911
+ }
5912
+ .row-fluid .span9 {
5913
+ width: 74.35897435897436%;
5914
+ *width: 74.30578286961266%;
5915
+ }
5916
+ .row-fluid .span8 {
5917
+ width: 65.81196581196582%;
5918
+ *width: 65.75877432260411%;
5919
+ }
5920
+ .row-fluid .span7 {
5921
+ width: 57.26495726495726%;
5922
+ *width: 57.21176577559556%;
5923
+ }
5924
+ .row-fluid .span6 {
5925
+ width: 48.717948717948715%;
5926
+ *width: 48.664757228587014%;
5927
+ }
5928
+ .row-fluid .span5 {
5929
+ width: 40.17094017094017%;
5930
+ *width: 40.11774868157847%;
5931
+ }
5932
+ .row-fluid .span4 {
5933
+ width: 31.623931623931625%;
5934
+ *width: 31.570740134569924%;
5935
+ }
5936
+ .row-fluid .span3 {
5937
+ width: 23.076923076923077%;
5938
+ *width: 23.023731587561375%;
5939
+ }
5940
+ .row-fluid .span2 {
5941
+ width: 14.52991452991453%;
5942
+ *width: 14.476723040552828%;
5943
+ }
5944
+ .row-fluid .span1 {
5945
+ width: 5.982905982905983%;
5946
+ *width: 5.929714493544281%;
5947
+ }
5948
+ .row-fluid .offset12 {
5949
+ margin-left: 105.12820512820512%;
5950
+ *margin-left: 105.02182214948171%;
5951
+ }
5952
+ .row-fluid .offset12:first-child {
5953
+ margin-left: 102.56410256410257%;
5954
+ *margin-left: 102.45771958537915%;
5955
+ }
5956
+ .row-fluid .offset11 {
5957
+ margin-left: 96.58119658119658%;
5958
+ *margin-left: 96.47481360247316%;
5959
+ }
5960
+ .row-fluid .offset11:first-child {
5961
+ margin-left: 94.01709401709402%;
5962
+ *margin-left: 93.91071103837061%;
5963
+ }
5964
+ .row-fluid .offset10 {
5965
+ margin-left: 88.03418803418803%;
5966
+ *margin-left: 87.92780505546462%;
5967
+ }
5968
+ .row-fluid .offset10:first-child {
5969
+ margin-left: 85.47008547008548%;
5970
+ *margin-left: 85.36370249136206%;
5971
+ }
5972
+ .row-fluid .offset9 {
5973
+ margin-left: 79.48717948717949%;
5974
+ *margin-left: 79.38079650845607%;
5975
+ }
5976
+ .row-fluid .offset9:first-child {
5977
+ margin-left: 76.92307692307693%;
5978
+ *margin-left: 76.81669394435352%;
5979
+ }
5980
+ .row-fluid .offset8 {
5981
+ margin-left: 70.94017094017094%;
5982
+ *margin-left: 70.83378796144753%;
5983
+ }
5984
+ .row-fluid .offset8:first-child {
5985
+ margin-left: 68.37606837606839%;
5986
+ *margin-left: 68.26968539734497%;
5987
+ }
5988
+ .row-fluid .offset7 {
5989
+ margin-left: 62.393162393162385%;
5990
+ *margin-left: 62.28677941443899%;
5991
+ }
5992
+ .row-fluid .offset7:first-child {
5993
+ margin-left: 59.82905982905982%;
5994
+ *margin-left: 59.72267685033642%;
5995
+ }
5996
+ .row-fluid .offset6 {
5997
+ margin-left: 53.84615384615384%;
5998
+ *margin-left: 53.739770867430444%;
5999
+ }
6000
+ .row-fluid .offset6:first-child {
6001
+ margin-left: 51.28205128205128%;
6002
+ *margin-left: 51.175668303327875%;
6003
+ }
6004
+ .row-fluid .offset5 {
6005
+ margin-left: 45.299145299145295%;
6006
+ *margin-left: 45.1927623204219%;
6007
+ }
6008
+ .row-fluid .offset5:first-child {
6009
+ margin-left: 42.73504273504273%;
6010
+ *margin-left: 42.62865975631933%;
6011
+ }
6012
+ .row-fluid .offset4 {
6013
+ margin-left: 36.75213675213675%;
6014
+ *margin-left: 36.645753773413354%;
6015
+ }
6016
+ .row-fluid .offset4:first-child {
6017
+ margin-left: 34.18803418803419%;
6018
+ *margin-left: 34.081651209310785%;
6019
+ }
6020
+ .row-fluid .offset3 {
6021
+ margin-left: 28.205128205128204%;
6022
+ *margin-left: 28.0987452264048%;
6023
+ }
6024
+ .row-fluid .offset3:first-child {
6025
+ margin-left: 25.641025641025642%;
6026
+ *margin-left: 25.53464266230224%;
6027
+ }
6028
+ .row-fluid .offset2 {
6029
+ margin-left: 19.65811965811966%;
6030
+ *margin-left: 19.551736679396257%;
6031
+ }
6032
+ .row-fluid .offset2:first-child {
6033
+ margin-left: 17.094017094017094%;
6034
+ *margin-left: 16.98763411529369%;
6035
+ }
6036
+ .row-fluid .offset1 {
6037
+ margin-left: 11.11111111111111%;
6038
+ *margin-left: 11.004728132387708%;
6039
+ }
6040
+ .row-fluid .offset1:first-child {
6041
+ margin-left: 8.547008547008547%;
6042
+ *margin-left: 8.440625568285142%;
6043
+ }
6044
+ input,
6045
+ textarea,
6046
+ .uneditable-input {
6047
+ margin-left: 0;
6048
+ }
6049
+ .controls-row [class*="span"] + [class*="span"] {
6050
+ margin-left: 30px;
6051
+ }
6052
+ input.span12,
6053
+ textarea.span12,
6054
+ .uneditable-input.span12 {
6055
+ width: 1156px;
6056
+ }
6057
+ input.span11,
6058
+ textarea.span11,
6059
+ .uneditable-input.span11 {
6060
+ width: 1056px;
6061
+ }
6062
+ input.span10,
6063
+ textarea.span10,
6064
+ .uneditable-input.span10 {
6065
+ width: 956px;
6066
+ }
6067
+ input.span9,
6068
+ textarea.span9,
6069
+ .uneditable-input.span9 {
6070
+ width: 856px;
6071
+ }
6072
+ input.span8,
6073
+ textarea.span8,
6074
+ .uneditable-input.span8 {
6075
+ width: 756px;
6076
+ }
6077
+ input.span7,
6078
+ textarea.span7,
6079
+ .uneditable-input.span7 {
6080
+ width: 656px;
6081
+ }
6082
+ input.span6,
6083
+ textarea.span6,
6084
+ .uneditable-input.span6 {
6085
+ width: 556px;
6086
+ }
6087
+ input.span5,
6088
+ textarea.span5,
6089
+ .uneditable-input.span5 {
6090
+ width: 456px;
6091
+ }
6092
+ input.span4,
6093
+ textarea.span4,
6094
+ .uneditable-input.span4 {
6095
+ width: 356px;
6096
+ }
6097
+ input.span3,
6098
+ textarea.span3,
6099
+ .uneditable-input.span3 {
6100
+ width: 256px;
6101
+ }
6102
+ input.span2,
6103
+ textarea.span2,
6104
+ .uneditable-input.span2 {
6105
+ width: 156px;
6106
+ }
6107
+ input.span1,
6108
+ textarea.span1,
6109
+ .uneditable-input.span1 {
6110
+ width: 56px;
6111
+ }
6112
+ .thumbnails {
6113
+ margin-left: -30px;
6114
+ }
6115
+ .thumbnails > li {
6116
+ margin-left: 30px;
6117
+ }
6118
+ .row-fluid .thumbnails {
6119
+ margin-left: 0;
6120
+ }
6121
+ }
6122
+ @media (max-width: 979px) {
6123
+ body {
6124
+ padding-top: 0;
6125
+ }
6126
+ .navbar-fixed-top,
6127
+ .navbar-fixed-bottom {
6128
+ position: static;
6129
+ }
6130
+ .navbar-fixed-top {
6131
+ margin-bottom: 20px;
6132
+ }
6133
+ .navbar-fixed-bottom {
6134
+ margin-top: 20px;
6135
+ }
6136
+ .navbar-fixed-top .navbar-inner,
6137
+ .navbar-fixed-bottom .navbar-inner {
6138
+ padding: 5px;
6139
+ }
6140
+ .navbar .container {
6141
+ width: auto;
6142
+ padding: 0;
6143
+ }
6144
+ .navbar .brand {
6145
+ padding-left: 10px;
6146
+ padding-right: 10px;
6147
+ margin: 0 0 0 -5px;
6148
+ }
6149
+ .nav-collapse {
6150
+ clear: both;
6151
+ }
6152
+ .nav-collapse .nav {
6153
+ float: none;
6154
+ margin: 0 0 10px;
6155
+ }
6156
+ .nav-collapse .nav > li {
6157
+ float: none;
6158
+ }
6159
+ .nav-collapse .nav > li > a {
6160
+ margin-bottom: 2px;
6161
+ }
6162
+ .nav-collapse .nav > .divider-vertical {
6163
+ display: none;
6164
+ }
6165
+ .nav-collapse .nav .nav-header {
6166
+ color: #777777;
6167
+ text-shadow: none;
6168
+ }
6169
+ .nav-collapse .nav > li > a,
6170
+ .nav-collapse .dropdown-menu a {
6171
+ padding: 9px 15px;
6172
+ font-weight: bold;
6173
+ color: #777777;
6174
+ -webkit-border-radius: 3px;
6175
+ -moz-border-radius: 3px;
6176
+ border-radius: 3px;
6177
+ }
6178
+ .nav-collapse .btn {
6179
+ padding: 4px 10px 4px;
6180
+ font-weight: normal;
6181
+ -webkit-border-radius: 4px;
6182
+ -moz-border-radius: 4px;
6183
+ border-radius: 4px;
6184
+ }
6185
+ .nav-collapse .dropdown-menu li + li a {
6186
+ margin-bottom: 2px;
6187
+ }
6188
+ .nav-collapse .nav > li > a:hover,
6189
+ .nav-collapse .nav > li > a:focus,
6190
+ .nav-collapse .dropdown-menu a:hover,
6191
+ .nav-collapse .dropdown-menu a:focus {
6192
+ background-color: #f2f2f2;
6193
+ }
6194
+ .navbar-inverse .nav-collapse .nav > li > a,
6195
+ .navbar-inverse .nav-collapse .dropdown-menu a {
6196
+ color: #999999;
6197
+ }
6198
+ .navbar-inverse .nav-collapse .nav > li > a:hover,
6199
+ .navbar-inverse .nav-collapse .nav > li > a:focus,
6200
+ .navbar-inverse .nav-collapse .dropdown-menu a:hover,
6201
+ .navbar-inverse .nav-collapse .dropdown-menu a:focus {
6202
+ background-color: #111111;
6203
+ }
6204
+ .nav-collapse.in .btn-group {
6205
+ margin-top: 5px;
6206
+ padding: 0;
6207
+ }
6208
+ .nav-collapse .dropdown-menu {
6209
+ position: static;
6210
+ top: auto;
6211
+ left: auto;
6212
+ float: none;
6213
+ display: none;
6214
+ max-width: none;
6215
+ margin: 0 15px;
6216
+ padding: 0;
6217
+ background-color: transparent;
6218
+ border: none;
6219
+ -webkit-border-radius: 0;
6220
+ -moz-border-radius: 0;
6221
+ border-radius: 0;
6222
+ -webkit-box-shadow: none;
6223
+ -moz-box-shadow: none;
6224
+ box-shadow: none;
6225
+ }
6226
+ .nav-collapse .open > .dropdown-menu {
6227
+ display: block;
6228
+ }
6229
+ .nav-collapse .dropdown-menu:before,
6230
+ .nav-collapse .dropdown-menu:after {
6231
+ display: none;
6232
+ }
6233
+ .nav-collapse .dropdown-menu .divider {
6234
+ display: none;
6235
+ }
6236
+ .nav-collapse .nav > li > .dropdown-menu:before,
6237
+ .nav-collapse .nav > li > .dropdown-menu:after {
6238
+ display: none;
6239
+ }
6240
+ .nav-collapse .navbar-form,
6241
+ .nav-collapse .navbar-search {
6242
+ float: none;
6243
+ padding: 10px 15px;
6244
+ margin: 10px 0;
6245
+ border-top: 1px solid #f2f2f2;
6246
+ border-bottom: 1px solid #f2f2f2;
6247
+ -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);
6248
+ -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);
6249
+ box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);
6250
+ }
6251
+ .navbar-inverse .nav-collapse .navbar-form,
6252
+ .navbar-inverse .nav-collapse .navbar-search {
6253
+ border-top-color: #111111;
6254
+ border-bottom-color: #111111;
6255
+ }
6256
+ .navbar .nav-collapse .nav.pull-right {
6257
+ float: none;
6258
+ margin-left: 0;
6259
+ }
6260
+ .nav-collapse,
6261
+ .nav-collapse.collapse {
6262
+ overflow: hidden;
6263
+ height: 0;
6264
+ }
6265
+ .navbar .btn-navbar {
6266
+ display: block;
6267
+ }
6268
+ .navbar-static .navbar-inner {
6269
+ padding-left: 10px;
6270
+ padding-right: 10px;
6271
+ }
6272
+ }
6273
+ @media (min-width: 980px) {
6274
+ .nav-collapse.collapse {
6275
+ height: auto !important;
6276
+ overflow: visible !important;
6277
+ }
6278
+ }
backend/resources/bootstrap/css/bootstrap.min.css ADDED
@@ -0,0 +1,865 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Bootstrap v2.3.1
3
+ *
4
+ * Copyright 2012 Twitter, Inc
5
+ * Licensed under the Apache License v2.0
6
+ * http://www.apache.org/licenses/LICENSE-2.0
7
+ *
8
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
9
+ */
10
+ .clearfix{*zoom:1;}.clearfix:before,.clearfix:after{display:table;content:"";line-height:0;}
11
+ .clearfix:after{clear:both;}
12
+ .hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0;}
13
+ .input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}
14
+ article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block;}
15
+ audio,canvas,video{display:inline-block;*display:inline;*zoom:1;}
16
+ audio:not([controls]){display:none;}
17
+ html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;}
18
+ a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}
19
+ a:hover,a:active{outline:0;}
20
+ sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline;}
21
+ sup{top:-0.5em;}
22
+ sub{bottom:-0.25em;}
23
+ img{max-width:100%;width:auto\9;height:auto;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic;}
24
+ #map_canvas img,.google-maps img{max-width:none;}
25
+ button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle;}
26
+ button,input{*overflow:visible;line-height:normal;}
27
+ button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0;}
28
+ button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;}
29
+ label,select,button,input[type="button"],input[type="reset"],input[type="submit"],input[type="radio"],input[type="checkbox"]{cursor:pointer;}
30
+ input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield;}
31
+ input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none;}
32
+ textarea{overflow:auto;vertical-align:top;}
33
+ @media print{*{text-shadow:none !important;color:#000 !important;background:transparent !important;box-shadow:none !important;} a,a:visited{text-decoration:underline;} a[href]:after{content:" (" attr(href) ")";} abbr[title]:after{content:" (" attr(title) ")";} .ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:"";} pre,blockquote{border:1px solid #999;page-break-inside:avoid;} thead{display:table-header-group;} tr,img{page-break-inside:avoid;} img{max-width:100% !important;} @page {margin:0.5cm;}p,h2,h3{orphans:3;widows:3;} h2,h3{page-break-after:avoid;}}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:20px;color:#333333;background-color:#ffffff;}
34
+ a{color:#0088cc;text-decoration:none;}
35
+ a:hover,a:focus{color:#005580;text-decoration:underline;}
36
+ .img-rounded{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;}
37
+ .img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.2);-webkit-box-shadow:0 1px 3px rgba(0, 0, 0, 0.1);-moz-box-shadow:0 1px 3px rgba(0, 0, 0, 0.1);box-shadow:0 1px 3px rgba(0, 0, 0, 0.1);}
38
+ .img-circle{-webkit-border-radius:500px;-moz-border-radius:500px;border-radius:500px;}
39
+ .row{margin-left:-20px;*zoom:1;}.row:before,.row:after{display:table;content:"";line-height:0;}
40
+ .row:after{clear:both;}
41
+ [class*="span"]{float:left;min-height:1px;margin-left:20px;}
42
+ .container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px;}
43
+ .span12{width:940px;}
44
+ .span11{width:860px;}
45
+ .span10{width:780px;}
46
+ .span9{width:700px;}
47
+ .span8{width:620px;}
48
+ .span7{width:540px;}
49
+ .span6{width:460px;}
50
+ .span5{width:380px;}
51
+ .span4{width:300px;}
52
+ .span3{width:220px;}
53
+ .span2{width:140px;}
54
+ .span1{width:60px;}
55
+ .offset12{margin-left:980px;}
56
+ .offset11{margin-left:900px;}
57
+ .offset10{margin-left:820px;}
58
+ .offset9{margin-left:740px;}
59
+ .offset8{margin-left:660px;}
60
+ .offset7{margin-left:580px;}
61
+ .offset6{margin-left:500px;}
62
+ .offset5{margin-left:420px;}
63
+ .offset4{margin-left:340px;}
64
+ .offset3{margin-left:260px;}
65
+ .offset2{margin-left:180px;}
66
+ .offset1{margin-left:100px;}
67
+ .row-fluid{width:100%;*zoom:1;}.row-fluid:before,.row-fluid:after{display:table;content:"";line-height:0;}
68
+ .row-fluid:after{clear:both;}
69
+ .row-fluid [class*="span"]{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;float:left;margin-left:2.127659574468085%;*margin-left:2.074468085106383%;}
70
+ .row-fluid [class*="span"]:first-child{margin-left:0;}
71
+ .row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.127659574468085%;}
72
+ .row-fluid .span12{width:100%;*width:99.94680851063829%;}
73
+ .row-fluid .span11{width:91.48936170212765%;*width:91.43617021276594%;}
74
+ .row-fluid .span10{width:82.97872340425532%;*width:82.92553191489361%;}
75
+ .row-fluid .span9{width:74.46808510638297%;*width:74.41489361702126%;}
76
+ .row-fluid .span8{width:65.95744680851064%;*width:65.90425531914893%;}
77
+ .row-fluid .span7{width:57.44680851063829%;*width:57.39361702127659%;}
78
+ .row-fluid .span6{width:48.93617021276595%;*width:48.88297872340425%;}
79
+ .row-fluid .span5{width:40.42553191489362%;*width:40.37234042553192%;}
80
+ .row-fluid .span4{width:31.914893617021278%;*width:31.861702127659576%;}
81
+ .row-fluid .span3{width:23.404255319148934%;*width:23.351063829787233%;}
82
+ .row-fluid .span2{width:14.893617021276595%;*width:14.840425531914894%;}
83
+ .row-fluid .span1{width:6.382978723404255%;*width:6.329787234042553%;}
84
+ .row-fluid .offset12{margin-left:104.25531914893617%;*margin-left:104.14893617021275%;}
85
+ .row-fluid .offset12:first-child{margin-left:102.12765957446808%;*margin-left:102.02127659574467%;}
86
+ .row-fluid .offset11{margin-left:95.74468085106382%;*margin-left:95.6382978723404%;}
87
+ .row-fluid .offset11:first-child{margin-left:93.61702127659574%;*margin-left:93.51063829787232%;}
88
+ .row-fluid .offset10{margin-left:87.23404255319149%;*margin-left:87.12765957446807%;}
89
+ .row-fluid .offset10:first-child{margin-left:85.1063829787234%;*margin-left:84.99999999999999%;}
90
+ .row-fluid .offset9{margin-left:78.72340425531914%;*margin-left:78.61702127659572%;}
91
+ .row-fluid .offset9:first-child{margin-left:76.59574468085106%;*margin-left:76.48936170212764%;}
92
+ .row-fluid .offset8{margin-left:70.2127659574468%;*margin-left:70.10638297872339%;}
93
+ .row-fluid .offset8:first-child{margin-left:68.08510638297872%;*margin-left:67.9787234042553%;}
94
+ .row-fluid .offset7{margin-left:61.70212765957446%;*margin-left:61.59574468085106%;}
95
+ .row-fluid .offset7:first-child{margin-left:59.574468085106375%;*margin-left:59.46808510638297%;}
96
+ .row-fluid .offset6{margin-left:53.191489361702125%;*margin-left:53.085106382978715%;}
97
+ .row-fluid .offset6:first-child{margin-left:51.063829787234035%;*margin-left:50.95744680851063%;}
98
+ .row-fluid .offset5{margin-left:44.68085106382979%;*margin-left:44.57446808510638%;}
99
+ .row-fluid .offset5:first-child{margin-left:42.5531914893617%;*margin-left:42.4468085106383%;}
100
+ .row-fluid .offset4{margin-left:36.170212765957444%;*margin-left:36.06382978723405%;}
101
+ .row-fluid .offset4:first-child{margin-left:34.04255319148936%;*margin-left:33.93617021276596%;}
102
+ .row-fluid .offset3{margin-left:27.659574468085104%;*margin-left:27.5531914893617%;}
103
+ .row-fluid .offset3:first-child{margin-left:25.53191489361702%;*margin-left:25.425531914893618%;}
104
+ .row-fluid .offset2{margin-left:19.148936170212764%;*margin-left:19.04255319148936%;}
105
+ .row-fluid .offset2:first-child{margin-left:17.02127659574468%;*margin-left:16.914893617021278%;}
106
+ .row-fluid .offset1{margin-left:10.638297872340425%;*margin-left:10.53191489361702%;}
107
+ .row-fluid .offset1:first-child{margin-left:8.51063829787234%;*margin-left:8.404255319148938%;}
108
+ [class*="span"].hide,.row-fluid [class*="span"].hide{display:none;}
109
+ [class*="span"].pull-right,.row-fluid [class*="span"].pull-right{float:right;}
110
+ .container{margin-right:auto;margin-left:auto;*zoom:1;}.container:before,.container:after{display:table;content:"";line-height:0;}
111
+ .container:after{clear:both;}
112
+ .container-fluid{padding-right:20px;padding-left:20px;*zoom:1;}.container-fluid:before,.container-fluid:after{display:table;content:"";line-height:0;}
113
+ .container-fluid:after{clear:both;}
114
+ p{margin:0 0 10px;}
115
+ .lead{margin-bottom:20px;font-size:21px;font-weight:200;line-height:30px;}
116
+ small{font-size:85%;}
117
+ strong{font-weight:bold;}
118
+ em{font-style:italic;}
119
+ cite{font-style:normal;}
120
+ .muted{color:#999999;}
121
+ a.muted:hover,a.muted:focus{color:#808080;}
122
+ .text-warning{color:#c09853;}
123
+ a.text-warning:hover,a.text-warning:focus{color:#a47e3c;}
124
+ .text-error{color:#b94a48;}
125
+ a.text-error:hover,a.text-error:focus{color:#953b39;}
126
+ .text-info{color:#3a87ad;}
127
+ a.text-info:hover,a.text-info:focus{color:#2d6987;}
128
+ .text-success{color:#468847;}
129
+ a.text-success:hover,a.text-success:focus{color:#356635;}
130
+ .text-left{text-align:left;}
131
+ .text-right{text-align:right;}
132
+ .text-center{text-align:center;}
133
+ h1,h2,h3,h4,h5,h6{margin:10px 0;font-family:inherit;font-weight:bold;line-height:20px;color:inherit;text-rendering:optimizelegibility;}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;line-height:1;color:#999999;}
134
+ h1,h2,h3{line-height:40px;}
135
+ h1{font-size:38.5px;}
136
+ h2{font-size:31.5px;}
137
+ h3{font-size:24.5px;}
138
+ h4{font-size:17.5px;}
139
+ h5{font-size:14px;}
140
+ h6{font-size:11.9px;}
141
+ h1 small{font-size:24.5px;}
142
+ h2 small{font-size:17.5px;}
143
+ h3 small{font-size:14px;}
144
+ h4 small{font-size:14px;}
145
+ .page-header{padding-bottom:9px;margin:20px 0 30px;border-bottom:1px solid #eeeeee;}
146
+ ul,ol{padding:0;margin:0 0 10px 25px;}
147
+ ul ul,ul ol,ol ol,ol ul{margin-bottom:0;}
148
+ li{line-height:20px;}
149
+ ul.unstyled,ol.unstyled{margin-left:0;list-style:none;}
150
+ ul.inline,ol.inline{margin-left:0;list-style:none;}ul.inline>li,ol.inline>li{display:inline-block;*display:inline;*zoom:1;padding-left:5px;padding-right:5px;}
151
+ dl{margin-bottom:20px;}
152
+ dt,dd{line-height:20px;}
153
+ dt{font-weight:bold;}
154
+ dd{margin-left:10px;}
155
+ .dl-horizontal{*zoom:1;}.dl-horizontal:before,.dl-horizontal:after{display:table;content:"";line-height:0;}
156
+ .dl-horizontal:after{clear:both;}
157
+ .dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
158
+ .dl-horizontal dd{margin-left:180px;}
159
+ hr{margin:20px 0;border:0;border-top:1px solid #eeeeee;border-bottom:1px solid #ffffff;}
160
+ abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999999;}
161
+ abbr.initialism{font-size:90%;text-transform:uppercase;}
162
+ blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eeeeee;}blockquote p{margin-bottom:0;font-size:17.5px;font-weight:300;line-height:1.25;}
163
+ blockquote small{display:block;line-height:20px;color:#999999;}blockquote small:before{content:'\2014 \00A0';}
164
+ blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eeeeee;border-left:0;}blockquote.pull-right p,blockquote.pull-right small{text-align:right;}
165
+ blockquote.pull-right small:before{content:'';}
166
+ blockquote.pull-right small:after{content:'\00A0 \2014';}
167
+ q:before,q:after,blockquote:before,blockquote:after{content:"";}
168
+ address{display:block;margin-bottom:20px;font-style:normal;line-height:20px;}
169
+ code,pre{padding:0 3px 2px;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;font-size:12px;color:#333333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
170
+ code{padding:2px 4px;color:#d14;background-color:#f7f7f9;border:1px solid #e1e1e8;white-space:nowrap;}
171
+ pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}pre.prettyprint{margin-bottom:20px;}
172
+ pre code{padding:0;color:inherit;white-space:pre;white-space:pre-wrap;background-color:transparent;border:0;}
173
+ .pre-scrollable{max-height:340px;overflow-y:scroll;}
174
+ .label,.badge{display:inline-block;padding:2px 4px;font-size:11.844px;font-weight:bold;line-height:14px;color:#ffffff;vertical-align:baseline;white-space:nowrap;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#999999;}
175
+ .label{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
176
+ .badge{padding-left:9px;padding-right:9px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px;}
177
+ .label:empty,.badge:empty{display:none;}
178
+ a.label:hover,a.label:focus,a.badge:hover,a.badge:focus{color:#ffffff;text-decoration:none;cursor:pointer;}
179
+ .label-important,.badge-important{background-color:#b94a48;}
180
+ .label-important[href],.badge-important[href]{background-color:#953b39;}
181
+ .label-warning,.badge-warning{background-color:#f89406;}
182
+ .label-warning[href],.badge-warning[href]{background-color:#c67605;}
183
+ .label-success,.badge-success{background-color:#468847;}
184
+ .label-success[href],.badge-success[href]{background-color:#356635;}
185
+ .label-info,.badge-info{background-color:#3a87ad;}
186
+ .label-info[href],.badge-info[href]{background-color:#2d6987;}
187
+ .label-inverse,.badge-inverse{background-color:#333333;}
188
+ .label-inverse[href],.badge-inverse[href]{background-color:#1a1a1a;}
189
+ .btn .label,.btn .badge{position:relative;top:-1px;}
190
+ .btn-mini .label,.btn-mini .badge{top:0;}
191
+ table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0;}
192
+ .table{width:100%;margin-bottom:20px;}.table th,.table td{padding:8px;line-height:20px;text-align:left;vertical-align:top;border-top:1px solid #dddddd;}
193
+ .table th{font-weight:bold;}
194
+ .table thead th{vertical-align:bottom;}
195
+ .table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child th,.table thead:first-child tr:first-child td{border-top:0;}
196
+ .table tbody+tbody{border-top:2px solid #dddddd;}
197
+ .table .table{background-color:#ffffff;}
198
+ .table-condensed th,.table-condensed td{padding:4px 5px;}
199
+ .table-bordered{border:1px solid #dddddd;border-collapse:separate;*border-collapse:collapse;border-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}.table-bordered th,.table-bordered td{border-left:1px solid #dddddd;}
200
+ .table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0;}
201
+ .table-bordered thead:first-child tr:first-child>th:first-child,.table-bordered tbody:first-child tr:first-child>td:first-child,.table-bordered tbody:first-child tr:first-child>th:first-child{-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px;}
202
+ .table-bordered thead:first-child tr:first-child>th:last-child,.table-bordered tbody:first-child tr:first-child>td:last-child,.table-bordered tbody:first-child tr:first-child>th:last-child{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;}
203
+ .table-bordered thead:last-child tr:last-child>th:first-child,.table-bordered tbody:last-child tr:last-child>td:first-child,.table-bordered tbody:last-child tr:last-child>th:first-child,.table-bordered tfoot:last-child tr:last-child>td:first-child,.table-bordered tfoot:last-child tr:last-child>th:first-child{-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px;}
204
+ .table-bordered thead:last-child tr:last-child>th:last-child,.table-bordered tbody:last-child tr:last-child>td:last-child,.table-bordered tbody:last-child tr:last-child>th:last-child,.table-bordered tfoot:last-child tr:last-child>td:last-child,.table-bordered tfoot:last-child tr:last-child>th:last-child{-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px;}
205
+ .table-bordered tfoot+tbody:last-child tr:last-child td:first-child{-webkit-border-bottom-left-radius:0;-moz-border-radius-bottomleft:0;border-bottom-left-radius:0;}
206
+ .table-bordered tfoot+tbody:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:0;-moz-border-radius-bottomright:0;border-bottom-right-radius:0;}
207
+ .table-bordered caption+thead tr:first-child th:first-child,.table-bordered caption+tbody tr:first-child td:first-child,.table-bordered colgroup+thead tr:first-child th:first-child,.table-bordered colgroup+tbody tr:first-child td:first-child{-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px;}
208
+ .table-bordered caption+thead tr:first-child th:last-child,.table-bordered caption+tbody tr:first-child td:last-child,.table-bordered colgroup+thead tr:first-child th:last-child,.table-bordered colgroup+tbody tr:first-child td:last-child{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;}
209
+ .table-striped tbody>tr:nth-child(odd)>td,.table-striped tbody>tr:nth-child(odd)>th{background-color:#f9f9f9;}
210
+ .table-hover tbody tr:hover>td,.table-hover tbody tr:hover>th{background-color:#f5f5f5;}
211
+ table td[class*="span"],table th[class*="span"],.row-fluid table td[class*="span"],.row-fluid table th[class*="span"]{display:table-cell;float:none;margin-left:0;}
212
+ .table td.span1,.table th.span1{float:none;width:44px;margin-left:0;}
213
+ .table td.span2,.table th.span2{float:none;width:124px;margin-left:0;}
214
+ .table td.span3,.table th.span3{float:none;width:204px;margin-left:0;}
215
+ .table td.span4,.table th.span4{float:none;width:284px;margin-left:0;}
216
+ .table td.span5,.table th.span5{float:none;width:364px;margin-left:0;}
217
+ .table td.span6,.table th.span6{float:none;width:444px;margin-left:0;}
218
+ .table td.span7,.table th.span7{float:none;width:524px;margin-left:0;}
219
+ .table td.span8,.table th.span8{float:none;width:604px;margin-left:0;}
220
+ .table td.span9,.table th.span9{float:none;width:684px;margin-left:0;}
221
+ .table td.span10,.table th.span10{float:none;width:764px;margin-left:0;}
222
+ .table td.span11,.table th.span11{float:none;width:844px;margin-left:0;}
223
+ .table td.span12,.table th.span12{float:none;width:924px;margin-left:0;}
224
+ .table tbody tr.success>td{background-color:#dff0d8;}
225
+ .table tbody tr.error>td{background-color:#f2dede;}
226
+ .table tbody tr.warning>td{background-color:#fcf8e3;}
227
+ .table tbody tr.info>td{background-color:#d9edf7;}
228
+ .table-hover tbody tr.success:hover>td{background-color:#d0e9c6;}
229
+ .table-hover tbody tr.error:hover>td{background-color:#ebcccc;}
230
+ .table-hover tbody tr.warning:hover>td{background-color:#faf2cc;}
231
+ .table-hover tbody tr.info:hover>td{background-color:#c4e3f3;}
232
+ form{margin:0 0 20px;}
233
+ fieldset{padding:0;margin:0;border:0;}
234
+ legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:40px;color:#333333;border:0;border-bottom:1px solid #e5e5e5;}legend small{font-size:15px;color:#999999;}
235
+ label,input,button,select,textarea{font-size:14px;font-weight:normal;line-height:20px;}
236
+ input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;}
237
+ label{display:block;margin-bottom:5px;}
238
+ select,textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{display:inline-block;height:20px;padding:4px 6px;margin-bottom:10px;font-size:14px;line-height:20px;color:#555555;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;vertical-align:middle;}
239
+ input,textarea,.uneditable-input{width:206px;}
240
+ textarea{height:auto;}
241
+ textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{background-color:#ffffff;border:1px solid #cccccc;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-webkit-transition:border linear .2s, box-shadow linear .2s;-moz-transition:border linear .2s, box-shadow linear .2s;-o-transition:border linear .2s, box-shadow linear .2s;transition:border linear .2s, box-shadow linear .2s;}textarea:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus{border-color:rgba(82, 168, 236, 0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);}
242
+ input[type="radio"],input[type="checkbox"]{margin:4px 0 0;*margin-top:0;margin-top:1px \9;line-height:normal;}
243
+ input[type="file"],input[type="image"],input[type="submit"],input[type="reset"],input[type="button"],input[type="radio"],input[type="checkbox"]{width:auto;}
244
+ select,input[type="file"]{height:30px;*margin-top:4px;line-height:30px;}
245
+ select{width:220px;border:1px solid #cccccc;background-color:#ffffff;}
246
+ select[multiple],select[size]{height:auto;}
247
+ select:focus,input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}
248
+ .uneditable-input,.uneditable-textarea{color:#999999;background-color:#fcfcfc;border-color:#cccccc;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);cursor:not-allowed;}
249
+ .uneditable-input{overflow:hidden;white-space:nowrap;}
250
+ .uneditable-textarea{width:auto;height:auto;}
251
+ input:-moz-placeholder,textarea:-moz-placeholder{color:#999999;}
252
+ input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#999999;}
253
+ input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#999999;}
254
+ .radio,.checkbox{min-height:20px;padding-left:20px;}
255
+ .radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-20px;}
256
+ .controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px;}
257
+ .radio.inline,.checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle;}
258
+ .radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px;}
259
+ .input-mini{width:60px;}
260
+ .input-small{width:90px;}
261
+ .input-medium{width:150px;}
262
+ .input-large{width:210px;}
263
+ .input-xlarge{width:270px;}
264
+ .input-xxlarge{width:530px;}
265
+ input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"]{float:none;margin-left:0;}
266
+ .input-append input[class*="span"],.input-append .uneditable-input[class*="span"],.input-prepend input[class*="span"],.input-prepend .uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"],.row-fluid .input-prepend [class*="span"],.row-fluid .input-append [class*="span"]{display:inline-block;}
267
+ input,textarea,.uneditable-input{margin-left:0;}
268
+ .controls-row [class*="span"]+[class*="span"]{margin-left:20px;}
269
+ input.span12,textarea.span12,.uneditable-input.span12{width:926px;}
270
+ input.span11,textarea.span11,.uneditable-input.span11{width:846px;}
271
+ input.span10,textarea.span10,.uneditable-input.span10{width:766px;}
272
+ input.span9,textarea.span9,.uneditable-input.span9{width:686px;}
273
+ input.span8,textarea.span8,.uneditable-input.span8{width:606px;}
274
+ input.span7,textarea.span7,.uneditable-input.span7{width:526px;}
275
+ input.span6,textarea.span6,.uneditable-input.span6{width:446px;}
276
+ input.span5,textarea.span5,.uneditable-input.span5{width:366px;}
277
+ input.span4,textarea.span4,.uneditable-input.span4{width:286px;}
278
+ input.span3,textarea.span3,.uneditable-input.span3{width:206px;}
279
+ input.span2,textarea.span2,.uneditable-input.span2{width:126px;}
280
+ input.span1,textarea.span1,.uneditable-input.span1{width:46px;}
281
+ .controls-row{*zoom:1;}.controls-row:before,.controls-row:after{display:table;content:"";line-height:0;}
282
+ .controls-row:after{clear:both;}
283
+ .controls-row [class*="span"],.row-fluid .controls-row [class*="span"]{float:left;}
284
+ .controls-row .checkbox[class*="span"],.controls-row .radio[class*="span"]{padding-top:5px;}
285
+ input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#eeeeee;}
286
+ input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"][readonly],input[type="checkbox"][readonly]{background-color:transparent;}
287
+ .control-group.warning .control-label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853;}
288
+ .control-group.warning .checkbox,.control-group.warning .radio,.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853;}
289
+ .control-group.warning input,.control-group.warning select,.control-group.warning textarea{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #dbc59e;-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #dbc59e;}
290
+ .control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853;}
291
+ .control-group.error .control-label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48;}
292
+ .control-group.error .checkbox,.control-group.error .radio,.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48;}
293
+ .control-group.error input,.control-group.error select,.control-group.error textarea{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #d59392;-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #d59392;}
294
+ .control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48;}
295
+ .control-group.success .control-label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847;}
296
+ .control-group.success .checkbox,.control-group.success .radio,.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847;}
297
+ .control-group.success input,.control-group.success select,.control-group.success textarea{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #7aba7b;-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #7aba7b;}
298
+ .control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847;}
299
+ .control-group.info .control-label,.control-group.info .help-block,.control-group.info .help-inline{color:#3a87ad;}
300
+ .control-group.info .checkbox,.control-group.info .radio,.control-group.info input,.control-group.info select,.control-group.info textarea{color:#3a87ad;}
301
+ .control-group.info input,.control-group.info select,.control-group.info textarea{border-color:#3a87ad;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);}.control-group.info input:focus,.control-group.info select:focus,.control-group.info textarea:focus{border-color:#2d6987;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #7ab5d3;-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #7ab5d3;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #7ab5d3;}
302
+ .control-group.info .input-prepend .add-on,.control-group.info .input-append .add-on{color:#3a87ad;background-color:#d9edf7;border-color:#3a87ad;}
303
+ input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#b94a48;border-color:#ee5f5b;}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7;}
304
+ .form-actions{padding:19px 20px 20px;margin-top:20px;margin-bottom:20px;background-color:#f5f5f5;border-top:1px solid #e5e5e5;*zoom:1;}.form-actions:before,.form-actions:after{display:table;content:"";line-height:0;}
305
+ .form-actions:after{clear:both;}
306
+ .help-block,.help-inline{color:#595959;}
307
+ .help-block{display:block;margin-bottom:10px;}
308
+ .help-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;padding-left:5px;}
309
+ .input-append,.input-prepend{display:inline-block;margin-bottom:10px;vertical-align:middle;font-size:0;white-space:nowrap;}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input,.input-append .dropdown-menu,.input-prepend .dropdown-menu,.input-append .popover,.input-prepend .popover{font-size:14px;}
310
+ .input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input{position:relative;margin-bottom:0;*margin-left:0;vertical-align:top;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0;}.input-append input:focus,.input-prepend input:focus,.input-append select:focus,.input-prepend select:focus,.input-append .uneditable-input:focus,.input-prepend .uneditable-input:focus{z-index:2;}
311
+ .input-append .add-on,.input-prepend .add-on{display:inline-block;width:auto;height:20px;min-width:16px;padding:4px 5px;font-size:14px;font-weight:normal;line-height:20px;text-align:center;text-shadow:0 1px 0 #ffffff;background-color:#eeeeee;border:1px solid #ccc;}
312
+ .input-append .add-on,.input-prepend .add-on,.input-append .btn,.input-prepend .btn,.input-append .btn-group>.dropdown-toggle,.input-prepend .btn-group>.dropdown-toggle{vertical-align:top;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
313
+ .input-append .active,.input-prepend .active{background-color:#a9dba9;border-color:#46a546;}
314
+ .input-prepend .add-on,.input-prepend .btn{margin-right:-1px;}
315
+ .input-prepend .add-on:first-child,.input-prepend .btn:first-child{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px;}
316
+ .input-append input,.input-append select,.input-append .uneditable-input{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px;}.input-append input+.btn-group .btn:last-child,.input-append select+.btn-group .btn:last-child,.input-append .uneditable-input+.btn-group .btn:last-child{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0;}
317
+ .input-append .add-on,.input-append .btn,.input-append .btn-group{margin-left:-1px;}
318
+ .input-append .add-on:last-child,.input-append .btn:last-child,.input-append .btn-group:last-child>.dropdown-toggle{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0;}
319
+ .input-prepend.input-append input,.input-prepend.input-append select,.input-prepend.input-append .uneditable-input{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}.input-prepend.input-append input+.btn-group .btn,.input-prepend.input-append select+.btn-group .btn,.input-prepend.input-append .uneditable-input+.btn-group .btn{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0;}
320
+ .input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px;}
321
+ .input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0;}
322
+ .input-prepend.input-append .btn-group:first-child{margin-left:0;}
323
+ input.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px;}
324
+ .form-search .input-append .search-query,.form-search .input-prepend .search-query{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
325
+ .form-search .input-append .search-query{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px;}
326
+ .form-search .input-append .btn{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0;}
327
+ .form-search .input-prepend .search-query{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0;}
328
+ .form-search .input-prepend .btn{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px;}
329
+ .form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input,.form-search .input-prepend,.form-inline .input-prepend,.form-horizontal .input-prepend,.form-search .input-append,.form-inline .input-append,.form-horizontal .input-append{display:inline-block;*display:inline;*zoom:1;margin-bottom:0;vertical-align:middle;}
330
+ .form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none;}
331
+ .form-search label,.form-inline label,.form-search .btn-group,.form-inline .btn-group{display:inline-block;}
332
+ .form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{margin-bottom:0;}
333
+ .form-search .radio,.form-search .checkbox,.form-inline .radio,.form-inline .checkbox{padding-left:0;margin-bottom:0;vertical-align:middle;}
334
+ .form-search .radio input[type="radio"],.form-search .checkbox input[type="checkbox"],.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:left;margin-right:3px;margin-left:0;}
335
+ .control-group{margin-bottom:10px;}
336
+ legend+.control-group{margin-top:20px;-webkit-margin-top-collapse:separate;}
337
+ .form-horizontal .control-group{margin-bottom:20px;*zoom:1;}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;content:"";line-height:0;}
338
+ .form-horizontal .control-group:after{clear:both;}
339
+ .form-horizontal .control-label{float:left;width:160px;padding-top:5px;text-align:right;}
340
+ .form-horizontal .controls{*display:inline-block;*padding-left:20px;margin-left:180px;*margin-left:0;}.form-horizontal .controls:first-child{*padding-left:180px;}
341
+ .form-horizontal .help-block{margin-bottom:0;}
342
+ .form-horizontal input+.help-block,.form-horizontal select+.help-block,.form-horizontal textarea+.help-block,.form-horizontal .uneditable-input+.help-block,.form-horizontal .input-prepend+.help-block,.form-horizontal .input-append+.help-block{margin-top:10px;}
343
+ .form-horizontal .form-actions{padding-left:180px;}
344
+ .btn{display:inline-block;*display:inline;*zoom:1;padding:4px 12px;margin-bottom:0;font-size:14px;line-height:20px;text-align:center;vertical-align:middle;cursor:pointer;color:#333333;text-shadow:0 1px 1px rgba(255, 255, 255, 0.75);background-color:#f5f5f5;background-image:-moz-linear-gradient(top, #ffffff, #e6e6e6);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));background-image:-webkit-linear-gradient(top, #ffffff, #e6e6e6);background-image:-o-linear-gradient(top, #ffffff, #e6e6e6);background-image:linear-gradient(to bottom, #ffffff, #e6e6e6);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#e6e6e6;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);border:1px solid #cccccc;*border:0;border-bottom-color:#b3b3b3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*margin-left:.3em;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);}.btn:hover,.btn:focus,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{color:#333333;background-color:#e6e6e6;*background-color:#d9d9d9;}
345
+ .btn:active,.btn.active{background-color:#cccccc \9;}
346
+ .btn:first-child{*margin-left:0;}
347
+ .btn:hover,.btn:focus{color:#333333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position 0.1s linear;-moz-transition:background-position 0.1s linear;-o-transition:background-position 0.1s linear;transition:background-position 0.1s linear;}
348
+ .btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}
349
+ .btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);}
350
+ .btn.disabled,.btn[disabled]{cursor:default;background-image:none;opacity:0.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
351
+ .btn-large{padding:11px 19px;font-size:17.5px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;}
352
+ .btn-large [class^="icon-"],.btn-large [class*=" icon-"]{margin-top:4px;}
353
+ .btn-small{padding:2px 10px;font-size:11.9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
354
+ .btn-small [class^="icon-"],.btn-small [class*=" icon-"]{margin-top:0;}
355
+ .btn-mini [class^="icon-"],.btn-mini [class*=" icon-"]{margin-top:-1px;}
356
+ .btn-mini{padding:0 6px;font-size:10.5px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
357
+ .btn-block{display:block;width:100%;padding-left:0;padding-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}
358
+ .btn-block+.btn-block{margin-top:5px;}
359
+ input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%;}
360
+ .btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255, 255, 255, 0.75);}
361
+ .btn-primary{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#006dcc;background-image:-moz-linear-gradient(top, #0088cc, #0044cc);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));background-image:-webkit-linear-gradient(top, #0088cc, #0044cc);background-image:-o-linear-gradient(top, #0088cc, #0044cc);background-image:linear-gradient(to bottom, #0088cc, #0044cc);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);border-color:#0044cc #0044cc #002a80;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#0044cc;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{color:#ffffff;background-color:#0044cc;*background-color:#003bb3;}
362
+ .btn-primary:active,.btn-primary.active{background-color:#003399 \9;}
363
+ .btn-warning{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#faa732;background-image:-moz-linear-gradient(top, #fbb450, #f89406);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));background-image:-webkit-linear-gradient(top, #fbb450, #f89406);background-image:-o-linear-gradient(top, #fbb450, #f89406);background-image:linear-gradient(to bottom, #fbb450, #f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);border-color:#f89406 #f89406 #ad6704;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#f89406;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{color:#ffffff;background-color:#f89406;*background-color:#df8505;}
364
+ .btn-warning:active,.btn-warning.active{background-color:#c67605 \9;}
365
+ .btn-danger{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#da4f49;background-image:-moz-linear-gradient(top, #ee5f5b, #bd362f);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));background-image:-webkit-linear-gradient(top, #ee5f5b, #bd362f);background-image:-o-linear-gradient(top, #ee5f5b, #bd362f);background-image:linear-gradient(to bottom, #ee5f5b, #bd362f);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);border-color:#bd362f #bd362f #802420;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#bd362f;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{color:#ffffff;background-color:#bd362f;*background-color:#a9302a;}
366
+ .btn-danger:active,.btn-danger.active{background-color:#942a25 \9;}
367
+ .btn-success{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#5bb75b;background-image:-moz-linear-gradient(top, #62c462, #51a351);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));background-image:-webkit-linear-gradient(top, #62c462, #51a351);background-image:-o-linear-gradient(top, #62c462, #51a351);background-image:linear-gradient(to bottom, #62c462, #51a351);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);border-color:#51a351 #51a351 #387038;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#51a351;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{color:#ffffff;background-color:#51a351;*background-color:#499249;}
368
+ .btn-success:active,.btn-success.active{background-color:#408140 \9;}
369
+ .btn-info{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#49afcd;background-image:-moz-linear-gradient(top, #5bc0de, #2f96b4);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));background-image:-webkit-linear-gradient(top, #5bc0de, #2f96b4);background-image:-o-linear-gradient(top, #5bc0de, #2f96b4);background-image:linear-gradient(to bottom, #5bc0de, #2f96b4);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#2f96b4;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{color:#ffffff;background-color:#2f96b4;*background-color:#2a85a0;}
370
+ .btn-info:active,.btn-info.active{background-color:#24748c \9;}
371
+ .btn-inverse{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#363636;background-image:-moz-linear-gradient(top, #444444, #222222);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));background-image:-webkit-linear-gradient(top, #444444, #222222);background-image:-o-linear-gradient(top, #444444, #222222);background-image:linear-gradient(to bottom, #444444, #222222);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);border-color:#222222 #222222 #000000;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#222222;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-inverse:hover,.btn-inverse:focus,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{color:#ffffff;background-color:#222222;*background-color:#151515;}
372
+ .btn-inverse:active,.btn-inverse.active{background-color:#080808 \9;}
373
+ button.btn,input[type="submit"].btn{*padding-top:3px;*padding-bottom:3px;}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0;}
374
+ button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px;}
375
+ button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px;}
376
+ button.btn.btn-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px;}
377
+ .btn-link,.btn-link:active,.btn-link[disabled]{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
378
+ .btn-link{border-color:transparent;cursor:pointer;color:#0088cc;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
379
+ .btn-link:hover,.btn-link:focus{color:#005580;text-decoration:underline;background-color:transparent;}
380
+ .btn-link[disabled]:hover,.btn-link[disabled]:focus{color:#333333;text-decoration:none;}
381
+ [class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat;margin-top:1px;}
382
+ .icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:focus>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>li>a:focus>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:focus>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"],.dropdown-submenu:focus>a>[class*=" icon-"]{background-image:url("../img/glyphicons-halflings-white.png");}
383
+ .icon-glass{background-position:0 0;}
384
+ .icon-music{background-position:-24px 0;}
385
+ .icon-search{background-position:-48px 0;}
386
+ .icon-envelope{background-position:-72px 0;}
387
+ .icon-heart{background-position:-96px 0;}
388
+ .icon-star{background-position:-120px 0;}
389
+ .icon-star-empty{background-position:-144px 0;}
390
+ .icon-user{background-position:-168px 0;}
391
+ .icon-film{background-position:-192px 0;}
392
+ .icon-th-large{background-position:-216px 0;}
393
+ .icon-th{background-position:-240px 0;}
394
+ .icon-th-list{background-position:-264px 0;}
395
+ .icon-ok{background-position:-288px 0;}
396
+ .icon-remove{background-position:-312px 0;}
397
+ .icon-zoom-in{background-position:-336px 0;}
398
+ .icon-zoom-out{background-position:-360px 0;}
399
+ .icon-off{background-position:-384px 0;}
400
+ .icon-signal{background-position:-408px 0;}
401
+ .icon-cog{background-position:-432px 0;}
402
+ .icon-trash{background-position:-456px 0;}
403
+ .icon-home{background-position:0 -24px;}
404
+ .icon-file{background-position:-24px -24px;}
405
+ .icon-time{background-position:-48px -24px;}
406
+ .icon-road{background-position:-72px -24px;}
407
+ .icon-download-alt{background-position:-96px -24px;}
408
+ .icon-download{background-position:-120px -24px;}
409
+ .icon-upload{background-position:-144px -24px;}
410
+ .icon-inbox{background-position:-168px -24px;}
411
+ .icon-play-circle{background-position:-192px -24px;}
412
+ .icon-repeat{background-position:-216px -24px;}
413
+ .icon-refresh{background-position:-240px -24px;}
414
+ .icon-list-alt{background-position:-264px -24px;}
415
+ .icon-lock{background-position:-287px -24px;}
416
+ .icon-flag{background-position:-312px -24px;}
417
+ .icon-headphones{background-position:-336px -24px;}
418
+ .icon-volume-off{background-position:-360px -24px;}
419
+ .icon-volume-down{background-position:-384px -24px;}
420
+ .icon-volume-up{background-position:-408px -24px;}
421
+ .icon-qrcode{background-position:-432px -24px;}
422
+ .icon-barcode{background-position:-456px -24px;}
423
+ .icon-tag{background-position:0 -48px;}
424
+ .icon-tags{background-position:-25px -48px;}
425
+ .icon-book{background-position:-48px -48px;}
426
+ .icon-bookmark{background-position:-72px -48px;}
427
+ .icon-print{background-position:-96px -48px;}
428
+ .icon-camera{background-position:-120px -48px;}
429
+ .icon-font{background-position:-144px -48px;}
430
+ .icon-bold{background-position:-167px -48px;}
431
+ .icon-italic{background-position:-192px -48px;}
432
+ .icon-text-height{background-position:-216px -48px;}
433
+ .icon-text-width{background-position:-240px -48px;}
434
+ .icon-align-left{background-position:-264px -48px;}
435
+ .icon-align-center{background-position:-288px -48px;}
436
+ .icon-align-right{background-position:-312px -48px;}
437
+ .icon-align-justify{background-position:-336px -48px;}
438
+ .icon-list{background-position:-360px -48px;}
439
+ .icon-indent-left{background-position:-384px -48px;}
440
+ .icon-indent-right{background-position:-408px -48px;}
441
+ .icon-facetime-video{background-position:-432px -48px;}
442
+ .icon-picture{background-position:-456px -48px;}
443
+ .icon-pencil{background-position:0 -72px;}
444
+ .icon-map-marker{background-position:-24px -72px;}
445
+ .icon-adjust{background-position:-48px -72px;}
446
+ .icon-tint{background-position:-72px -72px;}
447
+ .icon-edit{background-position:-96px -72px;}
448
+ .icon-share{background-position:-120px -72px;}
449
+ .icon-check{background-position:-144px -72px;}
450
+ .icon-move{background-position:-168px -72px;}
451
+ .icon-step-backward{background-position:-192px -72px;}
452
+ .icon-fast-backward{background-position:-216px -72px;}
453
+ .icon-backward{background-position:-240px -72px;}
454
+ .icon-play{background-position:-264px -72px;}
455
+ .icon-pause{background-position:-288px -72px;}
456
+ .icon-stop{background-position:-312px -72px;}
457
+ .icon-forward{background-position:-336px -72px;}
458
+ .icon-fast-forward{background-position:-360px -72px;}
459
+ .icon-step-forward{background-position:-384px -72px;}
460
+ .icon-eject{background-position:-408px -72px;}
461
+ .icon-chevron-left{background-position:-432px -72px;}
462
+ .icon-chevron-right{background-position:-456px -72px;}
463
+ .icon-plus-sign{background-position:0 -96px;}
464
+ .icon-minus-sign{background-position:-24px -96px;}
465
+ .icon-remove-sign{background-position:-48px -96px;}
466
+ .icon-ok-sign{background-position:-72px -96px;}
467
+ .icon-question-sign{background-position:-96px -96px;}
468
+ .icon-info-sign{background-position:-120px -96px;}
469
+ .icon-screenshot{background-position:-144px -96px;}
470
+ .icon-remove-circle{background-position:-168px -96px;}
471
+ .icon-ok-circle{background-position:-192px -96px;}
472
+ .icon-ban-circle{background-position:-216px -96px;}
473
+ .icon-arrow-left{background-position:-240px -96px;}
474
+ .icon-arrow-right{background-position:-264px -96px;}
475
+ .icon-arrow-up{background-position:-289px -96px;}
476
+ .icon-arrow-down{background-position:-312px -96px;}
477
+ .icon-share-alt{background-position:-336px -96px;}
478
+ .icon-resize-full{background-position:-360px -96px;}
479
+ .icon-resize-small{background-position:-384px -96px;}
480
+ .icon-plus{background-position:-408px -96px;}
481
+ .icon-minus{background-position:-433px -96px;}
482
+ .icon-asterisk{background-position:-456px -96px;}
483
+ .icon-exclamation-sign{background-position:0 -120px;}
484
+ .icon-gift{background-position:-24px -120px;}
485
+ .icon-leaf{background-position:-48px -120px;}
486
+ .icon-fire{background-position:-72px -120px;}
487
+ .icon-eye-open{background-position:-96px -120px;}
488
+ .icon-eye-close{background-position:-120px -120px;}
489
+ .icon-warning-sign{background-position:-144px -120px;}
490
+ .icon-plane{background-position:-168px -120px;}
491
+ .icon-calendar{background-position:-192px -120px;}
492
+ .icon-random{background-position:-216px -120px;width:16px;}
493
+ .icon-comment{background-position:-240px -120px;}
494
+ .icon-magnet{background-position:-264px -120px;}
495
+ .icon-chevron-up{background-position:-288px -120px;}
496
+ .icon-chevron-down{background-position:-313px -119px;}
497
+ .icon-retweet{background-position:-336px -120px;}
498
+ .icon-shopping-cart{background-position:-360px -120px;}
499
+ .icon-folder-close{background-position:-384px -120px;width:16px;}
500
+ .icon-folder-open{background-position:-408px -120px;width:16px;}
501
+ .icon-resize-vertical{background-position:-432px -119px;}
502
+ .icon-resize-horizontal{background-position:-456px -118px;}
503
+ .icon-hdd{background-position:0 -144px;}
504
+ .icon-bullhorn{background-position:-24px -144px;}
505
+ .icon-bell{background-position:-48px -144px;}
506
+ .icon-certificate{background-position:-72px -144px;}
507
+ .icon-thumbs-up{background-position:-96px -144px;}
508
+ .icon-thumbs-down{background-position:-120px -144px;}
509
+ .icon-hand-right{background-position:-144px -144px;}
510
+ .icon-hand-left{background-position:-168px -144px;}
511
+ .icon-hand-up{background-position:-192px -144px;}
512
+ .icon-hand-down{background-position:-216px -144px;}
513
+ .icon-circle-arrow-right{background-position:-240px -144px;}
514
+ .icon-circle-arrow-left{background-position:-264px -144px;}
515
+ .icon-circle-arrow-up{background-position:-288px -144px;}
516
+ .icon-circle-arrow-down{background-position:-312px -144px;}
517
+ .icon-globe{background-position:-336px -144px;}
518
+ .icon-wrench{background-position:-360px -144px;}
519
+ .icon-tasks{background-position:-384px -144px;}
520
+ .icon-filter{background-position:-408px -144px;}
521
+ .icon-briefcase{background-position:-432px -144px;}
522
+ .icon-fullscreen{background-position:-456px -144px;}
523
+ .btn-group{position:relative;display:inline-block;*display:inline;*zoom:1;font-size:0;vertical-align:middle;white-space:nowrap;*margin-left:.3em;}.btn-group:first-child{*margin-left:0;}
524
+ .btn-group+.btn-group{margin-left:5px;}
525
+ .btn-toolbar{font-size:0;margin-top:10px;margin-bottom:10px;}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group{margin-left:5px;}
526
+ .btn-group>.btn{position:relative;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
527
+ .btn-group>.btn+.btn{margin-left:-1px;}
528
+ .btn-group>.btn,.btn-group>.dropdown-menu,.btn-group>.popover{font-size:14px;}
529
+ .btn-group>.btn-mini{font-size:10.5px;}
530
+ .btn-group>.btn-small{font-size:11.9px;}
531
+ .btn-group>.btn-large{font-size:17.5px;}
532
+ .btn-group>.btn:first-child{margin-left:0;-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px;}
533
+ .btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px;}
534
+ .btn-group>.btn.large:first-child{margin-left:0;-webkit-border-top-left-radius:6px;-moz-border-radius-topleft:6px;border-top-left-radius:6px;-webkit-border-bottom-left-radius:6px;-moz-border-radius-bottomleft:6px;border-bottom-left-radius:6px;}
535
+ .btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;-moz-border-radius-topright:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;-moz-border-radius-bottomright:6px;border-bottom-right-radius:6px;}
536
+ .btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2;}
537
+ .btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0;}
538
+ .btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);*padding-top:5px;*padding-bottom:5px;}
539
+ .btn-group>.btn-mini+.dropdown-toggle{padding-left:5px;padding-right:5px;*padding-top:2px;*padding-bottom:2px;}
540
+ .btn-group>.btn-small+.dropdown-toggle{*padding-top:5px;*padding-bottom:4px;}
541
+ .btn-group>.btn-large+.dropdown-toggle{padding-left:12px;padding-right:12px;*padding-top:7px;*padding-bottom:7px;}
542
+ .btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);}
543
+ .btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6;}
544
+ .btn-group.open .btn-primary.dropdown-toggle{background-color:#0044cc;}
545
+ .btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406;}
546
+ .btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f;}
547
+ .btn-group.open .btn-success.dropdown-toggle{background-color:#51a351;}
548
+ .btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4;}
549
+ .btn-group.open .btn-inverse.dropdown-toggle{background-color:#222222;}
550
+ .btn .caret{margin-top:8px;margin-left:0;}
551
+ .btn-large .caret{margin-top:6px;}
552
+ .btn-large .caret{border-left-width:5px;border-right-width:5px;border-top-width:5px;}
553
+ .btn-mini .caret,.btn-small .caret{margin-top:8px;}
554
+ .dropup .btn-large .caret{border-bottom-width:5px;}
555
+ .btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#ffffff;border-bottom-color:#ffffff;}
556
+ .btn-group-vertical{display:inline-block;*display:inline;*zoom:1;}
557
+ .btn-group-vertical>.btn{display:block;float:none;max-width:100%;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
558
+ .btn-group-vertical>.btn+.btn{margin-left:0;margin-top:-1px;}
559
+ .btn-group-vertical>.btn:first-child{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0;}
560
+ .btn-group-vertical>.btn:last-child{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;}
561
+ .btn-group-vertical>.btn-large:first-child{-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:6px 6px 0 0;}
562
+ .btn-group-vertical>.btn-large:last-child{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;}
563
+ .nav{margin-left:0;margin-bottom:20px;list-style:none;}
564
+ .nav>li>a{display:block;}
565
+ .nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eeeeee;}
566
+ .nav>li>a>img{max-width:none;}
567
+ .nav>.pull-right{float:right;}
568
+ .nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:20px;color:#999999;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);text-transform:uppercase;}
569
+ .nav li+.nav-header{margin-top:9px;}
570
+ .nav-list{padding-left:15px;padding-right:15px;margin-bottom:0;}
571
+ .nav-list>li>a,.nav-list .nav-header{margin-left:-15px;margin-right:-15px;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);}
572
+ .nav-list>li>a{padding:3px 15px;}
573
+ .nav-list>.active>a,.nav-list>.active>a:hover,.nav-list>.active>a:focus{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.2);background-color:#0088cc;}
574
+ .nav-list [class^="icon-"],.nav-list [class*=" icon-"]{margin-right:2px;}
575
+ .nav-list .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #ffffff;}
576
+ .nav-tabs,.nav-pills{*zoom:1;}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;content:"";line-height:0;}
577
+ .nav-tabs:after,.nav-pills:after{clear:both;}
578
+ .nav-tabs>li,.nav-pills>li{float:left;}
579
+ .nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px;}
580
+ .nav-tabs{border-bottom:1px solid #ddd;}
581
+ .nav-tabs>li{margin-bottom:-1px;}
582
+ .nav-tabs>li>a{padding-top:8px;padding-bottom:8px;line-height:20px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0;}.nav-tabs>li>a:hover,.nav-tabs>li>a:focus{border-color:#eeeeee #eeeeee #dddddd;}
583
+ .nav-tabs>.active>a,.nav-tabs>.active>a:hover,.nav-tabs>.active>a:focus{color:#555555;background-color:#ffffff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default;}
584
+ .nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;}
585
+ .nav-pills>.active>a,.nav-pills>.active>a:hover,.nav-pills>.active>a:focus{color:#ffffff;background-color:#0088cc;}
586
+ .nav-stacked>li{float:none;}
587
+ .nav-stacked>li>a{margin-right:0;}
588
+ .nav-tabs.nav-stacked{border-bottom:0;}
589
+ .nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
590
+ .nav-tabs.nav-stacked>li:first-child>a{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px;}
591
+ .nav-tabs.nav-stacked>li:last-child>a{-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px;}
592
+ .nav-tabs.nav-stacked>li>a:hover,.nav-tabs.nav-stacked>li>a:focus{border-color:#ddd;z-index:2;}
593
+ .nav-pills.nav-stacked>li>a{margin-bottom:3px;}
594
+ .nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px;}
595
+ .nav-tabs .dropdown-menu{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;}
596
+ .nav-pills .dropdown-menu{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;}
597
+ .nav .dropdown-toggle .caret{border-top-color:#0088cc;border-bottom-color:#0088cc;margin-top:6px;}
598
+ .nav .dropdown-toggle:hover .caret,.nav .dropdown-toggle:focus .caret{border-top-color:#005580;border-bottom-color:#005580;}
599
+ .nav-tabs .dropdown-toggle .caret{margin-top:8px;}
600
+ .nav .active .dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff;}
601
+ .nav-tabs .active .dropdown-toggle .caret{border-top-color:#555555;border-bottom-color:#555555;}
602
+ .nav>.dropdown.active>a:hover,.nav>.dropdown.active>a:focus{cursor:pointer;}
603
+ .nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:hover,.nav>li.dropdown.open.active>a:focus{color:#ffffff;background-color:#999999;border-color:#999999;}
604
+ .nav li.dropdown.open .caret,.nav li.dropdown.open.active .caret,.nav li.dropdown.open a:hover .caret,.nav li.dropdown.open a:focus .caret{border-top-color:#ffffff;border-bottom-color:#ffffff;opacity:1;filter:alpha(opacity=100);}
605
+ .tabs-stacked .open>a:hover,.tabs-stacked .open>a:focus{border-color:#999999;}
606
+ .tabbable{*zoom:1;}.tabbable:before,.tabbable:after{display:table;content:"";line-height:0;}
607
+ .tabbable:after{clear:both;}
608
+ .tab-content{overflow:auto;}
609
+ .tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0;}
610
+ .tab-content>.tab-pane,.pill-content>.pill-pane{display:none;}
611
+ .tab-content>.active,.pill-content>.active{display:block;}
612
+ .tabs-below>.nav-tabs{border-top:1px solid #ddd;}
613
+ .tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0;}
614
+ .tabs-below>.nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;}.tabs-below>.nav-tabs>li>a:hover,.tabs-below>.nav-tabs>li>a:focus{border-bottom-color:transparent;border-top-color:#ddd;}
615
+ .tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover,.tabs-below>.nav-tabs>.active>a:focus{border-color:transparent #ddd #ddd #ddd;}
616
+ .tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>li{float:none;}
617
+ .tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px;}
618
+ .tabs-left>.nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd;}
619
+ .tabs-left>.nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px;}
620
+ .tabs-left>.nav-tabs>li>a:hover,.tabs-left>.nav-tabs>li>a:focus{border-color:#eeeeee #dddddd #eeeeee #eeeeee;}
621
+ .tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover,.tabs-left>.nav-tabs .active>a:focus{border-color:#ddd transparent #ddd #ddd;*border-right-color:#ffffff;}
622
+ .tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd;}
623
+ .tabs-right>.nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0;}
624
+ .tabs-right>.nav-tabs>li>a:hover,.tabs-right>.nav-tabs>li>a:focus{border-color:#eeeeee #eeeeee #eeeeee #dddddd;}
625
+ .tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover,.tabs-right>.nav-tabs .active>a:focus{border-color:#ddd #ddd #ddd transparent;*border-left-color:#ffffff;}
626
+ .nav>.disabled>a{color:#999999;}
627
+ .nav>.disabled>a:hover,.nav>.disabled>a:focus{text-decoration:none;background-color:transparent;cursor:default;}
628
+ .navbar{overflow:visible;margin-bottom:20px;*position:relative;*z-index:2;}
629
+ .navbar-inner{min-height:40px;padding-left:20px;padding-right:20px;background-color:#fafafa;background-image:-moz-linear-gradient(top, #ffffff, #f2f2f2);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));background-image:-webkit-linear-gradient(top, #ffffff, #f2f2f2);background-image:-o-linear-gradient(top, #ffffff, #f2f2f2);background-image:linear-gradient(to bottom, #ffffff, #f2f2f2);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);border:1px solid #d4d4d4;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 4px rgba(0, 0, 0, 0.065);-moz-box-shadow:0 1px 4px rgba(0, 0, 0, 0.065);box-shadow:0 1px 4px rgba(0, 0, 0, 0.065);*zoom:1;}.navbar-inner:before,.navbar-inner:after{display:table;content:"";line-height:0;}
630
+ .navbar-inner:after{clear:both;}
631
+ .navbar .container{width:auto;}
632
+ .nav-collapse.collapse{height:auto;overflow:visible;}
633
+ .navbar .brand{float:left;display:block;padding:10px 20px 10px;margin-left:-20px;font-size:20px;font-weight:200;color:#777777;text-shadow:0 1px 0 #ffffff;}.navbar .brand:hover,.navbar .brand:focus{text-decoration:none;}
634
+ .navbar-text{margin-bottom:0;line-height:40px;color:#777777;}
635
+ .navbar-link{color:#777777;}.navbar-link:hover,.navbar-link:focus{color:#333333;}
636
+ .navbar .divider-vertical{height:40px;margin:0 9px;border-left:1px solid #f2f2f2;border-right:1px solid #ffffff;}
637
+ .navbar .btn,.navbar .btn-group{margin-top:5px;}
638
+ .navbar .btn-group .btn,.navbar .input-prepend .btn,.navbar .input-append .btn,.navbar .input-prepend .btn-group,.navbar .input-append .btn-group{margin-top:0;}
639
+ .navbar-form{margin-bottom:0;*zoom:1;}.navbar-form:before,.navbar-form:after{display:table;content:"";line-height:0;}
640
+ .navbar-form:after{clear:both;}
641
+ .navbar-form input,.navbar-form select,.navbar-form .radio,.navbar-form .checkbox{margin-top:5px;}
642
+ .navbar-form input,.navbar-form select,.navbar-form .btn{display:inline-block;margin-bottom:0;}
643
+ .navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px;}
644
+ .navbar-form .input-append,.navbar-form .input-prepend{margin-top:5px;white-space:nowrap;}.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0;}
645
+ .navbar-search{position:relative;float:left;margin-top:5px;margin-bottom:0;}.navbar-search .search-query{margin-bottom:0;padding:4px 14px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px;}
646
+ .navbar-static-top{position:static;margin-bottom:0;}.navbar-static-top .navbar-inner{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
647
+ .navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;margin-bottom:0;}
648
+ .navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{border-width:0 0 1px;}
649
+ .navbar-fixed-bottom .navbar-inner{border-width:1px 0 0;}
650
+ .navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding-left:0;padding-right:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
651
+ .navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px;}
652
+ .navbar-fixed-top{top:0;}
653
+ .navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{-webkit-box-shadow:0 1px 10px rgba(0,0,0,.1);-moz-box-shadow:0 1px 10px rgba(0,0,0,.1);box-shadow:0 1px 10px rgba(0,0,0,.1);}
654
+ .navbar-fixed-bottom{bottom:0;}.navbar-fixed-bottom .navbar-inner{-webkit-box-shadow:0 -1px 10px rgba(0,0,0,.1);-moz-box-shadow:0 -1px 10px rgba(0,0,0,.1);box-shadow:0 -1px 10px rgba(0,0,0,.1);}
655
+ .navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0;}
656
+ .navbar .nav.pull-right{float:right;margin-right:0;}
657
+ .navbar .nav>li{float:left;}
658
+ .navbar .nav>li>a{float:none;padding:10px 15px 10px;color:#777777;text-decoration:none;text-shadow:0 1px 0 #ffffff;}
659
+ .navbar .nav .dropdown-toggle .caret{margin-top:8px;}
660
+ .navbar .nav>li>a:focus,.navbar .nav>li>a:hover{background-color:transparent;color:#333333;text-decoration:none;}
661
+ .navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus{color:#555555;text-decoration:none;background-color:#e5e5e5;-webkit-box-shadow:inset 0 3px 8px rgba(0, 0, 0, 0.125);-moz-box-shadow:inset 0 3px 8px rgba(0, 0, 0, 0.125);box-shadow:inset 0 3px 8px rgba(0, 0, 0, 0.125);}
662
+ .navbar .btn-navbar{display:none;float:right;padding:7px 10px;margin-left:5px;margin-right:5px;color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#ededed;background-image:-moz-linear-gradient(top, #f2f2f2, #e5e5e5);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));background-image:-webkit-linear-gradient(top, #f2f2f2, #e5e5e5);background-image:-o-linear-gradient(top, #f2f2f2, #e5e5e5);background-image:linear-gradient(to bottom, #f2f2f2, #e5e5e5);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);border-color:#e5e5e5 #e5e5e5 #bfbfbf;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#e5e5e5;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075);}.navbar .btn-navbar:hover,.navbar .btn-navbar:focus,.navbar .btn-navbar:active,.navbar .btn-navbar.active,.navbar .btn-navbar.disabled,.navbar .btn-navbar[disabled]{color:#ffffff;background-color:#e5e5e5;*background-color:#d9d9d9;}
663
+ .navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color:#cccccc \9;}
664
+ .navbar .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0, 0, 0, 0.25);-moz-box-shadow:0 1px 0 rgba(0, 0, 0, 0.25);box-shadow:0 1px 0 rgba(0, 0, 0, 0.25);}
665
+ .btn-navbar .icon-bar+.icon-bar{margin-top:3px;}
666
+ .navbar .nav>li>.dropdown-menu:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0, 0, 0, 0.2);position:absolute;top:-7px;left:9px;}
667
+ .navbar .nav>li>.dropdown-menu:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #ffffff;position:absolute;top:-6px;left:10px;}
668
+ .navbar-fixed-bottom .nav>li>.dropdown-menu:before{border-top:7px solid #ccc;border-top-color:rgba(0, 0, 0, 0.2);border-bottom:0;bottom:-7px;top:auto;}
669
+ .navbar-fixed-bottom .nav>li>.dropdown-menu:after{border-top:6px solid #ffffff;border-bottom:0;bottom:-6px;top:auto;}
670
+ .navbar .nav li.dropdown>a:hover .caret,.navbar .nav li.dropdown>a:focus .caret{border-top-color:#333333;border-bottom-color:#333333;}
671
+ .navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{background-color:#e5e5e5;color:#555555;}
672
+ .navbar .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#777777;border-bottom-color:#777777;}
673
+ .navbar .nav li.dropdown.open>.dropdown-toggle .caret,.navbar .nav li.dropdown.active>.dropdown-toggle .caret,.navbar .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#555555;border-bottom-color:#555555;}
674
+ .navbar .pull-right>li>.dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right{left:auto;right:0;}.navbar .pull-right>li>.dropdown-menu:before,.navbar .nav>li>.dropdown-menu.pull-right:before{left:auto;right:12px;}
675
+ .navbar .pull-right>li>.dropdown-menu:after,.navbar .nav>li>.dropdown-menu.pull-right:after{left:auto;right:13px;}
676
+ .navbar .pull-right>li>.dropdown-menu .dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right .dropdown-menu{left:auto;right:100%;margin-left:0;margin-right:-1px;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px;}
677
+ .navbar-inverse .navbar-inner{background-color:#1b1b1b;background-image:-moz-linear-gradient(top, #222222, #111111);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));background-image:-webkit-linear-gradient(top, #222222, #111111);background-image:-o-linear-gradient(top, #222222, #111111);background-image:linear-gradient(to bottom, #222222, #111111);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);border-color:#252525;}
678
+ .navbar-inverse .brand,.navbar-inverse .nav>li>a{color:#999999;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);}.navbar-inverse .brand:hover,.navbar-inverse .nav>li>a:hover,.navbar-inverse .brand:focus,.navbar-inverse .nav>li>a:focus{color:#ffffff;}
679
+ .navbar-inverse .brand{color:#999999;}
680
+ .navbar-inverse .navbar-text{color:#999999;}
681
+ .navbar-inverse .nav>li>a:focus,.navbar-inverse .nav>li>a:hover{background-color:transparent;color:#ffffff;}
682
+ .navbar-inverse .nav .active>a,.navbar-inverse .nav .active>a:hover,.navbar-inverse .nav .active>a:focus{color:#ffffff;background-color:#111111;}
683
+ .navbar-inverse .navbar-link{color:#999999;}.navbar-inverse .navbar-link:hover,.navbar-inverse .navbar-link:focus{color:#ffffff;}
684
+ .navbar-inverse .divider-vertical{border-left-color:#111111;border-right-color:#222222;}
685
+ .navbar-inverse .nav li.dropdown.open>.dropdown-toggle,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle{background-color:#111111;color:#ffffff;}
686
+ .navbar-inverse .nav li.dropdown>a:hover .caret,.navbar-inverse .nav li.dropdown>a:focus .caret{border-top-color:#ffffff;border-bottom-color:#ffffff;}
687
+ .navbar-inverse .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#999999;border-bottom-color:#999999;}
688
+ .navbar-inverse .nav li.dropdown.open>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#ffffff;border-bottom-color:#ffffff;}
689
+ .navbar-inverse .navbar-search .search-query{color:#ffffff;background-color:#515151;border-color:#111111;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15);box-shadow:inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15);-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none;}.navbar-inverse .navbar-search .search-query:-moz-placeholder{color:#cccccc;}
690
+ .navbar-inverse .navbar-search .search-query:-ms-input-placeholder{color:#cccccc;}
691
+ .navbar-inverse .navbar-search .search-query::-webkit-input-placeholder{color:#cccccc;}
692
+ .navbar-inverse .navbar-search .search-query:focus,.navbar-inverse .navbar-search .search-query.focused{padding:5px 15px;color:#333333;text-shadow:0 1px 0 #ffffff;background-color:#ffffff;border:0;-webkit-box-shadow:0 0 3px rgba(0, 0, 0, 0.15);-moz-box-shadow:0 0 3px rgba(0, 0, 0, 0.15);box-shadow:0 0 3px rgba(0, 0, 0, 0.15);outline:0;}
693
+ .navbar-inverse .btn-navbar{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#0e0e0e;background-image:-moz-linear-gradient(top, #151515, #040404);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));background-image:-webkit-linear-gradient(top, #151515, #040404);background-image:-o-linear-gradient(top, #151515, #040404);background-image:linear-gradient(to bottom, #151515, #040404);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);border-color:#040404 #040404 #000000;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#040404;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.navbar-inverse .btn-navbar:hover,.navbar-inverse .btn-navbar:focus,.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active,.navbar-inverse .btn-navbar.disabled,.navbar-inverse .btn-navbar[disabled]{color:#ffffff;background-color:#040404;*background-color:#000000;}
694
+ .navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active{background-color:#000000 \9;}
695
+ .breadcrumb{padding:8px 15px;margin:0 0 20px;list-style:none;background-color:#f5f5f5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}.breadcrumb>li{display:inline-block;*display:inline;*zoom:1;text-shadow:0 1px 0 #ffffff;}.breadcrumb>li>.divider{padding:0 5px;color:#ccc;}
696
+ .breadcrumb>.active{color:#999999;}
697
+ .pagination{margin:20px 0;}
698
+ .pagination ul{display:inline-block;*display:inline;*zoom:1;margin-left:0;margin-bottom:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);}
699
+ .pagination ul>li{display:inline;}
700
+ .pagination ul>li>a,.pagination ul>li>span{float:left;padding:4px 12px;line-height:20px;text-decoration:none;background-color:#ffffff;border:1px solid #dddddd;border-left-width:0;}
701
+ .pagination ul>li>a:hover,.pagination ul>li>a:focus,.pagination ul>.active>a,.pagination ul>.active>span{background-color:#f5f5f5;}
702
+ .pagination ul>.active>a,.pagination ul>.active>span{color:#999999;cursor:default;}
703
+ .pagination ul>.disabled>span,.pagination ul>.disabled>a,.pagination ul>.disabled>a:hover,.pagination ul>.disabled>a:focus{color:#999999;background-color:transparent;cursor:default;}
704
+ .pagination ul>li:first-child>a,.pagination ul>li:first-child>span{border-left-width:1px;-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px;}
705
+ .pagination ul>li:last-child>a,.pagination ul>li:last-child>span{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px;}
706
+ .pagination-centered{text-align:center;}
707
+ .pagination-right{text-align:right;}
708
+ .pagination-large ul>li>a,.pagination-large ul>li>span{padding:11px 19px;font-size:17.5px;}
709
+ .pagination-large ul>li:first-child>a,.pagination-large ul>li:first-child>span{-webkit-border-top-left-radius:6px;-moz-border-radius-topleft:6px;border-top-left-radius:6px;-webkit-border-bottom-left-radius:6px;-moz-border-radius-bottomleft:6px;border-bottom-left-radius:6px;}
710
+ .pagination-large ul>li:last-child>a,.pagination-large ul>li:last-child>span{-webkit-border-top-right-radius:6px;-moz-border-radius-topright:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;-moz-border-radius-bottomright:6px;border-bottom-right-radius:6px;}
711
+ .pagination-mini ul>li:first-child>a,.pagination-small ul>li:first-child>a,.pagination-mini ul>li:first-child>span,.pagination-small ul>li:first-child>span{-webkit-border-top-left-radius:3px;-moz-border-radius-topleft:3px;border-top-left-radius:3px;-webkit-border-bottom-left-radius:3px;-moz-border-radius-bottomleft:3px;border-bottom-left-radius:3px;}
712
+ .pagination-mini ul>li:last-child>a,.pagination-small ul>li:last-child>a,.pagination-mini ul>li:last-child>span,.pagination-small ul>li:last-child>span{-webkit-border-top-right-radius:3px;-moz-border-radius-topright:3px;border-top-right-radius:3px;-webkit-border-bottom-right-radius:3px;-moz-border-radius-bottomright:3px;border-bottom-right-radius:3px;}
713
+ .pagination-small ul>li>a,.pagination-small ul>li>span{padding:2px 10px;font-size:11.9px;}
714
+ .pagination-mini ul>li>a,.pagination-mini ul>li>span{padding:0 6px;font-size:10.5px;}
715
+ .pager{margin:20px 0;list-style:none;text-align:center;*zoom:1;}.pager:before,.pager:after{display:table;content:"";line-height:0;}
716
+ .pager:after{clear:both;}
717
+ .pager li{display:inline;}
718
+ .pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px;}
719
+ .pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#f5f5f5;}
720
+ .pager .next>a,.pager .next>span{float:right;}
721
+ .pager .previous>a,.pager .previous>span{float:left;}
722
+ .pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999999;background-color:#fff;cursor:default;}
723
+ .thumbnails{margin-left:-20px;list-style:none;*zoom:1;}.thumbnails:before,.thumbnails:after{display:table;content:"";line-height:0;}
724
+ .thumbnails:after{clear:both;}
725
+ .row-fluid .thumbnails{margin-left:0;}
726
+ .thumbnails>li{float:left;margin-bottom:20px;margin-left:20px;}
727
+ .thumbnail{display:block;padding:4px;line-height:20px;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 3px rgba(0, 0, 0, 0.055);-moz-box-shadow:0 1px 3px rgba(0, 0, 0, 0.055);box-shadow:0 1px 3px rgba(0, 0, 0, 0.055);-webkit-transition:all 0.2s ease-in-out;-moz-transition:all 0.2s ease-in-out;-o-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out;}
728
+ a.thumbnail:hover,a.thumbnail:focus{border-color:#0088cc;-webkit-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);-moz-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);}
729
+ .thumbnail>img{display:block;max-width:100%;margin-left:auto;margin-right:auto;}
730
+ .thumbnail .caption{padding:9px;color:#555555;}
731
+ .alert{padding:8px 35px 8px 14px;margin-bottom:20px;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
732
+ .alert,.alert h4{color:#c09853;}
733
+ .alert h4{margin:0;}
734
+ .alert .close{position:relative;top:-2px;right:-21px;line-height:20px;}
735
+ .alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#468847;}
736
+ .alert-success h4{color:#468847;}
737
+ .alert-danger,.alert-error{background-color:#f2dede;border-color:#eed3d7;color:#b94a48;}
738
+ .alert-danger h4,.alert-error h4{color:#b94a48;}
739
+ .alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#3a87ad;}
740
+ .alert-info h4{color:#3a87ad;}
741
+ .alert-block{padding-top:14px;padding-bottom:14px;}
742
+ .alert-block>p,.alert-block>ul{margin-bottom:0;}
743
+ .alert-block p+p{margin-top:5px;}
744
+ @-webkit-keyframes progress-bar-stripes{from{background-position:40px 0;} to{background-position:0 0;}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0;} to{background-position:0 0;}}@-ms-keyframes progress-bar-stripes{from{background-position:40px 0;} to{background-position:0 0;}}@-o-keyframes progress-bar-stripes{from{background-position:0 0;} to{background-position:40px 0;}}@keyframes progress-bar-stripes{from{background-position:40px 0;} to{background-position:0 0;}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f7f7f7;background-image:-moz-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));background-image:-webkit-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-o-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:linear-gradient(to bottom, #f5f5f5, #f9f9f9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
745
+ .progress .bar{width:0%;height:100%;color:#ffffff;float:left;font-size:12px;text-align:center;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top, #149bdf, #0480be);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));background-image:-webkit-linear-gradient(top, #149bdf, #0480be);background-image:-o-linear-gradient(top, #149bdf, #0480be);background-image:linear-gradient(to bottom, #149bdf, #0480be);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width 0.6s ease;-moz-transition:width 0.6s ease;-o-transition:width 0.6s ease;transition:width 0.6s ease;}
746
+ .progress .bar+.bar{-webkit-box-shadow:inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15);-moz-box-shadow:inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15);}
747
+ .progress-striped .bar{background-color:#149bdf;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px;}
748
+ .progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite;}
749
+ .progress-danger .bar,.progress .bar-danger{background-color:#dd514c;background-image:-moz-linear-gradient(top, #ee5f5b, #c43c35);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));background-image:-webkit-linear-gradient(top, #ee5f5b, #c43c35);background-image:-o-linear-gradient(top, #ee5f5b, #c43c35);background-image:linear-gradient(to bottom, #ee5f5b, #c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);}
750
+ .progress-danger.progress-striped .bar,.progress-striped .bar-danger{background-color:#ee5f5b;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);}
751
+ .progress-success .bar,.progress .bar-success{background-color:#5eb95e;background-image:-moz-linear-gradient(top, #62c462, #57a957);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));background-image:-webkit-linear-gradient(top, #62c462, #57a957);background-image:-o-linear-gradient(top, #62c462, #57a957);background-image:linear-gradient(to bottom, #62c462, #57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);}
752
+ .progress-success.progress-striped .bar,.progress-striped .bar-success{background-color:#62c462;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);}
753
+ .progress-info .bar,.progress .bar-info{background-color:#4bb1cf;background-image:-moz-linear-gradient(top, #5bc0de, #339bb9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));background-image:-webkit-linear-gradient(top, #5bc0de, #339bb9);background-image:-o-linear-gradient(top, #5bc0de, #339bb9);background-image:linear-gradient(to bottom, #5bc0de, #339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);}
754
+ .progress-info.progress-striped .bar,.progress-striped .bar-info{background-color:#5bc0de;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);}
755
+ .progress-warning .bar,.progress .bar-warning{background-color:#faa732;background-image:-moz-linear-gradient(top, #fbb450, #f89406);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));background-image:-webkit-linear-gradient(top, #fbb450, #f89406);background-image:-o-linear-gradient(top, #fbb450, #f89406);background-image:linear-gradient(to bottom, #fbb450, #f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);}
756
+ .progress-warning.progress-striped .bar,.progress-striped .bar-warning{background-color:#fbb450;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);}
757
+ .hero-unit{padding:60px;margin-bottom:30px;font-size:18px;font-weight:200;line-height:30px;color:inherit;background-color:#eeeeee;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;color:inherit;letter-spacing:-1px;}
758
+ .hero-unit li{line-height:30px;}
759
+ .tooltip{position:absolute;z-index:1030;display:block;visibility:visible;font-size:11px;line-height:1.4;opacity:0;filter:alpha(opacity=0);}.tooltip.in{opacity:0.8;filter:alpha(opacity=80);}
760
+ .tooltip.top{margin-top:-3px;padding:5px 0;}
761
+ .tooltip.right{margin-left:3px;padding:0 5px;}
762
+ .tooltip.bottom{margin-top:3px;padding:5px 0;}
763
+ .tooltip.left{margin-left:-3px;padding:0 5px;}
764
+ .tooltip-inner{max-width:200px;padding:8px;color:#ffffff;text-align:center;text-decoration:none;background-color:#000000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
765
+ .tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid;}
766
+ .tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000000;}
767
+ .tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000000;}
768
+ .tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000000;}
769
+ .tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000000;}
770
+ .popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;background-color:#ffffff;-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);white-space:normal;}.popover.top{margin-top:-10px;}
771
+ .popover.right{margin-left:10px;}
772
+ .popover.bottom{margin-top:10px;}
773
+ .popover.left{margin-left:-10px;}
774
+ .popover-title{margin:0;padding:8px 14px;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0;}.popover-title:empty{display:none;}
775
+ .popover-content{padding:9px 14px;}
776
+ .popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid;}
777
+ .popover .arrow{border-width:11px;}
778
+ .popover .arrow:after{border-width:10px;content:"";}
779
+ .popover.top .arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0, 0, 0, 0.25);bottom:-11px;}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#ffffff;}
780
+ .popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0, 0, 0, 0.25);}.popover.right .arrow:after{left:1px;bottom:-10px;border-left-width:0;border-right-color:#ffffff;}
781
+ .popover.bottom .arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0, 0, 0, 0.25);top:-11px;}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#ffffff;}
782
+ .popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0, 0, 0, 0.25);}.popover.left .arrow:after{right:1px;border-right-width:0;border-left-color:#ffffff;bottom:-10px;}
783
+ .modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000000;}.modal-backdrop.fade{opacity:0;}
784
+ .modal-backdrop,.modal-backdrop.fade.in{opacity:0.8;filter:alpha(opacity=80);}
785
+ .modal{position:fixed;top:10%;left:50%;z-index:1050;width:560px;margin-left:-280px;background-color:#ffffff;border:1px solid #999;border:1px solid rgba(0, 0, 0, 0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;outline:none;}.modal.fade{-webkit-transition:opacity .3s linear, top .3s ease-out;-moz-transition:opacity .3s linear, top .3s ease-out;-o-transition:opacity .3s linear, top .3s ease-out;transition:opacity .3s linear, top .3s ease-out;top:-25%;}
786
+ .modal.fade.in{top:10%;}
787
+ .modal-header{padding:9px 15px;border-bottom:1px solid #eee;}.modal-header .close{margin-top:2px;}
788
+ .modal-header h3{margin:0;line-height:30px;}
789
+ .modal-body{position:relative;overflow-y:auto;max-height:400px;padding:15px;}
790
+ .modal-form{margin-bottom:0;}
791
+ .modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;-webkit-box-shadow:inset 0 1px 0 #ffffff;-moz-box-shadow:inset 0 1px 0 #ffffff;box-shadow:inset 0 1px 0 #ffffff;*zoom:1;}.modal-footer:before,.modal-footer:after{display:table;content:"";line-height:0;}
792
+ .modal-footer:after{clear:both;}
793
+ .modal-footer .btn+.btn{margin-left:5px;margin-bottom:0;}
794
+ .modal-footer .btn-group .btn+.btn{margin-left:-1px;}
795
+ .modal-footer .btn-block+.btn-block{margin-left:0;}
796
+ .dropup,.dropdown{position:relative;}
797
+ .dropdown-toggle{*margin-bottom:-3px;}
798
+ .dropdown-toggle:active,.open .dropdown-toggle{outline:0;}
799
+ .caret{display:inline-block;width:0;height:0;vertical-align:top;border-top:4px solid #000000;border-right:4px solid transparent;border-left:4px solid transparent;content:"";}
800
+ .dropdown .caret{margin-top:8px;margin-left:2px;}
801
+ .dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;background-color:#ffffff;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box;}.dropdown-menu.pull-right{right:0;left:auto;}
802
+ .dropdown-menu .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #ffffff;}
803
+ .dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:20px;color:#333333;white-space:nowrap;}
804
+ .dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus,.dropdown-submenu:hover>a,.dropdown-submenu:focus>a{text-decoration:none;color:#ffffff;background-color:#0081c2;background-image:-moz-linear-gradient(top, #0088cc, #0077b3);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));background-image:-webkit-linear-gradient(top, #0088cc, #0077b3);background-image:-o-linear-gradient(top, #0088cc, #0077b3);background-image:linear-gradient(to bottom, #0088cc, #0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);}
805
+ .dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#ffffff;text-decoration:none;outline:0;background-color:#0081c2;background-image:-moz-linear-gradient(top, #0088cc, #0077b3);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));background-image:-webkit-linear-gradient(top, #0088cc, #0077b3);background-image:-o-linear-gradient(top, #0088cc, #0077b3);background-image:linear-gradient(to bottom, #0088cc, #0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);}
806
+ .dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999999;}
807
+ .dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);cursor:default;}
808
+ .open{*z-index:1000;}.open>.dropdown-menu{display:block;}
809
+ .pull-right>.dropdown-menu{right:0;left:auto;}
810
+ .dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid #000000;content:"";}
811
+ .dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px;}
812
+ .dropdown-submenu{position:relative;}
813
+ .dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px;}
814
+ .dropdown-submenu:hover>.dropdown-menu{display:block;}
815
+ .dropup .dropdown-submenu>.dropdown-menu{top:auto;bottom:0;margin-top:0;margin-bottom:-2px;-webkit-border-radius:5px 5px 5px 0;-moz-border-radius:5px 5px 5px 0;border-radius:5px 5px 5px 0;}
816
+ .dropdown-submenu>a:after{display:block;content:" ";float:right;width:0;height:0;border-color:transparent;border-style:solid;border-width:5px 0 5px 5px;border-left-color:#cccccc;margin-top:5px;margin-right:-10px;}
817
+ .dropdown-submenu:hover>a:after{border-left-color:#ffffff;}
818
+ .dropdown-submenu.pull-left{float:none;}.dropdown-submenu.pull-left>.dropdown-menu{left:-100%;margin-left:10px;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px;}
819
+ .dropdown .dropdown-menu .nav-header{padding-left:20px;padding-right:20px;}
820
+ .typeahead{z-index:1051;margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
821
+ .accordion{margin-bottom:20px;}
822
+ .accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
823
+ .accordion-heading{border-bottom:0;}
824
+ .accordion-heading .accordion-toggle{display:block;padding:8px 15px;}
825
+ .accordion-toggle{cursor:pointer;}
826
+ .accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5;}
827
+ .carousel{position:relative;margin-bottom:20px;line-height:1;}
828
+ .carousel-inner{overflow:hidden;width:100%;position:relative;}
829
+ .carousel-inner>.item{display:none;position:relative;-webkit-transition:0.6s ease-in-out left;-moz-transition:0.6s ease-in-out left;-o-transition:0.6s ease-in-out left;transition:0.6s ease-in-out left;}.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;line-height:1;}
830
+ .carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block;}
831
+ .carousel-inner>.active{left:0;}
832
+ .carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%;}
833
+ .carousel-inner>.next{left:100%;}
834
+ .carousel-inner>.prev{left:-100%;}
835
+ .carousel-inner>.next.left,.carousel-inner>.prev.right{left:0;}
836
+ .carousel-inner>.active.left{left:-100%;}
837
+ .carousel-inner>.active.right{left:100%;}
838
+ .carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#ffffff;text-align:center;background:#222222;border:3px solid #ffffff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:0.5;filter:alpha(opacity=50);}.carousel-control.right{left:auto;right:15px;}
839
+ .carousel-control:hover,.carousel-control:focus{color:#ffffff;text-decoration:none;opacity:0.9;filter:alpha(opacity=90);}
840
+ .carousel-indicators{position:absolute;top:15px;right:15px;z-index:5;margin:0;list-style:none;}.carousel-indicators li{display:block;float:left;width:10px;height:10px;margin-left:5px;text-indent:-999px;background-color:#ccc;background-color:rgba(255, 255, 255, 0.25);border-radius:5px;}
841
+ .carousel-indicators .active{background-color:#fff;}
842
+ .carousel-caption{position:absolute;left:0;right:0;bottom:0;padding:15px;background:#333333;background:rgba(0, 0, 0, 0.75);}
843
+ .carousel-caption h4,.carousel-caption p{color:#ffffff;line-height:20px;}
844
+ .carousel-caption h4{margin:0 0 5px;}
845
+ .carousel-caption p{margin-bottom:0;}
846
+ .well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);}.well blockquote{border-color:#ddd;border-color:rgba(0, 0, 0, 0.15);}
847
+ .well-large{padding:24px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;}
848
+ .well-small{padding:9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
849
+ .close{float:right;font-size:20px;font-weight:bold;line-height:20px;color:#000000;text-shadow:0 1px 0 #ffffff;opacity:0.2;filter:alpha(opacity=20);}.close:hover,.close:focus{color:#000000;text-decoration:none;cursor:pointer;opacity:0.4;filter:alpha(opacity=40);}
850
+ button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none;}
851
+ .pull-right{float:right;}
852
+ .pull-left{float:left;}
853
+ .hide{display:none;}
854
+ .show{display:block;}
855
+ .invisible{visibility:hidden;}
856
+ .affix{position:fixed;}
857
+ .fade{opacity:0;-webkit-transition:opacity 0.15s linear;-moz-transition:opacity 0.15s linear;-o-transition:opacity 0.15s linear;transition:opacity 0.15s linear;}.fade.in{opacity:1;}
858
+ .collapse{position:relative;height:0;overflow:hidden;-webkit-transition:height 0.35s ease;-moz-transition:height 0.35s ease;-o-transition:height 0.35s ease;transition:height 0.35s ease;}.collapse.in{height:auto;}
859
+ @-ms-viewport{width:device-width;}.hidden{display:none;visibility:hidden;}
860
+ .visible-phone{display:none !important;}
861
+ .visible-tablet{display:none !important;}
862
+ .hidden-desktop{display:none !important;}
863
+ .visible-desktop{display:inherit !important;}
864
+ @media (min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit !important;} .visible-desktop{display:none !important ;} .visible-tablet{display:inherit !important;} .hidden-tablet{display:none !important;}}@media (max-width:767px){.hidden-desktop{display:inherit !important;} .visible-desktop{display:none !important;} .visible-phone{display:inherit !important;} .hidden-phone{display:none !important;}}.visible-print{display:none !important;}
865
+ @media print{.visible-print{display:inherit !important;} .hidden-print{display:none !important;}}@media (max-width:767px){body{padding-left:20px;padding-right:20px;} .navbar-fixed-top,.navbar-fixed-bottom,.navbar-static-top{margin-left:-20px;margin-right:-20px;} .container-fluid{padding:0;} .dl-horizontal dt{float:none;clear:none;width:auto;text-align:left;} .dl-horizontal dd{margin-left:0;} .container{width:auto;} .row-fluid{width:100%;} .row,.thumbnails{margin-left:0;} .thumbnails>li{float:none;margin-left:0;} [class*="span"],.uneditable-input[class*="span"],.row-fluid [class*="span"]{float:none;display:block;width:100%;margin-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;} .span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;} .row-fluid [class*="offset"]:first-child{margin-left:0;} .input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;} .input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto;} .controls-row [class*="span"]+[class*="span"]{margin-left:0;} .modal{position:fixed;top:20px;left:20px;right:20px;width:auto;margin:0;}.modal.fade{top:-100px;} .modal.fade.in{top:20px;}}@media (max-width:480px){.nav-collapse{-webkit-transform:translate3d(0, 0, 0);} .page-header h1 small{display:block;line-height:20px;} input[type="checkbox"],input[type="radio"]{border:1px solid #ccc;} .form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left;} .form-horizontal .controls{margin-left:0;} .form-horizontal .control-list{padding-top:0;} .form-horizontal .form-actions{padding-left:10px;padding-right:10px;} .media .pull-left,.media .pull-right{float:none;display:block;margin-bottom:10px;} .media-object{margin-right:0;margin-left:0;} .modal{top:10px;left:10px;right:10px;} .modal-header .close{padding:10px;margin:-10px;} .carousel-caption{position:static;}}@media (min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1;}.row:before,.row:after{display:table;content:"";line-height:0;} .row:after{clear:both;} [class*="span"]{float:left;min-height:1px;margin-left:20px;} .container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px;} .span12{width:724px;} .span11{width:662px;} .span10{width:600px;} .span9{width:538px;} .span8{width:476px;} .span7{width:414px;} .span6{width:352px;} .span5{width:290px;} .span4{width:228px;} .span3{width:166px;} .span2{width:104px;} .span1{width:42px;} .offset12{margin-left:764px;} .offset11{margin-left:702px;} .offset10{margin-left:640px;} .offset9{margin-left:578px;} .offset8{margin-left:516px;} .offset7{margin-left:454px;} .offset6{margin-left:392px;} .offset5{margin-left:330px;} .offset4{margin-left:268px;} .offset3{margin-left:206px;} .offset2{margin-left:144px;} .offset1{margin-left:82px;} .row-fluid{width:100%;*zoom:1;}.row-fluid:before,.row-fluid:after{display:table;content:"";line-height:0;} .row-fluid:after{clear:both;} .row-fluid [class*="span"]{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;float:left;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%;} .row-fluid [class*="span"]:first-child{margin-left:0;} .row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.7624309392265194%;} .row-fluid .span12{width:100%;*width:99.94680851063829%;} .row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%;} .row-fluid .span10{width:82.87292817679558%;*width:82.81973668743387%;} .row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%;} .row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%;} .row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%;} .row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%;} .row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%;} .row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%;} .row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%;} .row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%;} .row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%;} .row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%;} .row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%;} .row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%;} .row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margin-left:94.09251204890089%;} .row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%;} .row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%;} .row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%;} .row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%;} .row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%;} .row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%;} .row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%;} .row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%;} .row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%;} .row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%;} .row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.47372751851417%;} .row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%;} .row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%;} .row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%;} .row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%;} .row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%;} .row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%;} .row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%;} .row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%;} .row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%;} input,textarea,.uneditable-input{margin-left:0;} .controls-row [class*="span"]+[class*="span"]{margin-left:20px;} input.span12,textarea.span12,.uneditable-input.span12{width:710px;} input.span11,textarea.span11,.uneditable-input.span11{width:648px;} input.span10,textarea.span10,.uneditable-input.span10{width:586px;} input.span9,textarea.span9,.uneditable-input.span9{width:524px;} input.span8,textarea.span8,.uneditable-input.span8{width:462px;} input.span7,textarea.span7,.uneditable-input.span7{width:400px;} input.span6,textarea.span6,.uneditable-input.span6{width:338px;} input.span5,textarea.span5,.uneditable-input.span5{width:276px;} input.span4,textarea.span4,.uneditable-input.span4{width:214px;} input.span3,textarea.span3,.uneditable-input.span3{width:152px;} input.span2,textarea.span2,.uneditable-input.span2{width:90px;} input.span1,textarea.span1,.uneditable-input.span1{width:28px;}}@media (min-width:1200px){.row{margin-left:-30px;*zoom:1;}.row:before,.row:after{display:table;content:"";line-height:0;} .row:after{clear:both;} [class*="span"]{float:left;min-height:1px;margin-left:30px;} .container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px;} .span12{width:1170px;} .span11{width:1070px;} .span10{width:970px;} .span9{width:870px;} .span8{width:770px;} .span7{width:670px;} .span6{width:570px;} .span5{width:470px;} .span4{width:370px;} .span3{width:270px;} .span2{width:170px;} .span1{width:70px;} .offset12{margin-left:1230px;} .offset11{margin-left:1130px;} .offset10{margin-left:1030px;} .offset9{margin-left:930px;} .offset8{margin-left:830px;} .offset7{margin-left:730px;} .offset6{margin-left:630px;} .offset5{margin-left:530px;} .offset4{margin-left:430px;} .offset3{margin-left:330px;} .offset2{margin-left:230px;} .offset1{margin-left:130px;} .row-fluid{width:100%;*zoom:1;}.row-fluid:before,.row-fluid:after{display:table;content:"";line-height:0;} .row-fluid:after{clear:both;} .row-fluid [class*="span"]{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;float:left;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;} .row-fluid [class*="span"]:first-child{margin-left:0;} .row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.564102564102564%;} .row-fluid .span12{width:100%;*width:99.94680851063829%;} .row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%;} .row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%;} .row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%;} .row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%;} .row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%;} .row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%;} .row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%;} .row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%;} .row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%;} .row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%;} .row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%;} .row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%;} .row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%;} .row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%;} .row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%;} .row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%;} .row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%;} .row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%;} .row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%;} .row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%;} .row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%;} .row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%;} .row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%;} .row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%;} .row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%;} .row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%;} .row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%;} .row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%;} .row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%;} .row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%;} .row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%;} .row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%;} .row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%;} .row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%;} .row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%;} input,textarea,.uneditable-input{margin-left:0;} .controls-row [class*="span"]+[class*="span"]{margin-left:30px;} input.span12,textarea.span12,.uneditable-input.span12{width:1156px;} input.span11,textarea.span11,.uneditable-input.span11{width:1056px;} input.span10,textarea.span10,.uneditable-input.span10{width:956px;} input.span9,textarea.span9,.uneditable-input.span9{width:856px;} input.span8,textarea.span8,.uneditable-input.span8{width:756px;} input.span7,textarea.span7,.uneditable-input.span7{width:656px;} input.span6,textarea.span6,.uneditable-input.span6{width:556px;} input.span5,textarea.span5,.uneditable-input.span5{width:456px;} input.span4,textarea.span4,.uneditable-input.span4{width:356px;} input.span3,textarea.span3,.uneditable-input.span3{width:256px;} input.span2,textarea.span2,.uneditable-input.span2{width:156px;} input.span1,textarea.span1,.uneditable-input.span1{width:56px;} .thumbnails{margin-left:-30px;} .thumbnails>li{margin-left:30px;} .row-fluid .thumbnails{margin-left:0;}}@media (max-width:979px){body{padding-top:0;} .navbar-fixed-top,.navbar-fixed-bottom{position:static;} .navbar-fixed-top{margin-bottom:20px;} .navbar-fixed-bottom{margin-top:20px;} .navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px;} .navbar .container{width:auto;padding:0;} .navbar .brand{padding-left:10px;padding-right:10px;margin:0 0 0 -5px;} .nav-collapse{clear:both;} .nav-collapse .nav{float:none;margin:0 0 10px;} .nav-collapse .nav>li{float:none;} .nav-collapse .nav>li>a{margin-bottom:2px;} .nav-collapse .nav>.divider-vertical{display:none;} .nav-collapse .nav .nav-header{color:#777777;text-shadow:none;} .nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777777;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;} .nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} .nav-collapse .dropdown-menu li+li a{margin-bottom:2px;} .nav-collapse .nav>li>a:hover,.nav-collapse .nav>li>a:focus,.nav-collapse .dropdown-menu a:hover,.nav-collapse .dropdown-menu a:focus{background-color:#f2f2f2;} .navbar-inverse .nav-collapse .nav>li>a,.navbar-inverse .nav-collapse .dropdown-menu a{color:#999999;} .navbar-inverse .nav-collapse .nav>li>a:hover,.navbar-inverse .nav-collapse .nav>li>a:focus,.navbar-inverse .nav-collapse .dropdown-menu a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:focus{background-color:#111111;} .nav-collapse.in .btn-group{margin-top:5px;padding:0;} .nav-collapse .dropdown-menu{position:static;top:auto;left:auto;float:none;display:none;max-width:none;margin:0 15px;padding:0;background-color:transparent;border:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} .nav-collapse .open>.dropdown-menu{display:block;} .nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none;} .nav-collapse .dropdown-menu .divider{display:none;} .nav-collapse .nav>li>.dropdown-menu:before,.nav-collapse .nav>li>.dropdown-menu:after{display:none;} .nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);} .navbar-inverse .nav-collapse .navbar-form,.navbar-inverse .nav-collapse .navbar-search{border-top-color:#111111;border-bottom-color:#111111;} .navbar .nav-collapse .nav.pull-right{float:none;margin-left:0;} .nav-collapse,.nav-collapse.collapse{overflow:hidden;height:0;} .navbar .btn-navbar{display:block;} .navbar-static .navbar-inner{padding-left:10px;padding-right:10px;}}@media (min-width:980px){.nav-collapse.collapse{height:auto !important;overflow:visible !important;}}
backend/resources/bootstrap/img/clear.png ADDED
Binary file
backend/resources/bootstrap/img/glyphicons-halflings-white.png ADDED
Binary file
backend/resources/bootstrap/img/glyphicons-halflings.png ADDED
Binary file
backend/resources/bootstrap/img/loading.gif ADDED
Binary file
backend/resources/bootstrap/js/bootstrap-editable.min.js ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ /*! X-editable - v1.5.0
2
+ * In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery
3
+ * http://github.com/vitalets/x-editable
4
+ * Copyright (c) 2013 Vitaliy Potapov; Licensed MIT */
5
+ !function(a){"use strict";var b=function(b,c){this.options=a.extend({},a.fn.editableform.defaults,c),this.$div=a(b),this.options.scope||(this.options.scope=this)};b.prototype={constructor:b,initInput:function(){this.input=this.options.input,this.value=this.input.str2value(this.options.value),this.input.prerender()},initTemplate:function(){this.$form=a(a.fn.editableform.template)},initButtons:function(){var b=this.$form.find(".editable-buttons");b.append(a.fn.editableform.buttons),"bottom"===this.options.showbuttons&&b.addClass("editable-buttons-bottom")},render:function(){this.$loading=a(a.fn.editableform.loading),this.$div.empty().append(this.$loading),this.initTemplate(),this.options.showbuttons?this.initButtons():this.$form.find(".editable-buttons").remove(),this.showLoading(),this.isSaving=!1,this.$div.triggerHandler("rendering"),this.initInput(),this.$form.find("div.editable-input").append(this.input.$tpl),this.$div.append(this.$form),a.when(this.input.render()).then(a.proxy(function(){if(this.options.showbuttons||this.input.autosubmit(),this.$form.find(".editable-cancel").click(a.proxy(this.cancel,this)),this.input.error)this.error(this.input.error),this.$form.find(".editable-submit").attr("disabled",!0),this.input.$input.attr("disabled",!0),this.$form.submit(function(a){a.preventDefault()});else{this.error(!1),this.input.$input.removeAttr("disabled"),this.$form.find(".editable-submit").removeAttr("disabled");var b=null===this.value||void 0===this.value||""===this.value?this.options.defaultValue:this.value;this.input.value2input(b),this.$form.submit(a.proxy(this.submit,this))}this.$div.triggerHandler("rendered"),this.showForm(),this.input.postrender&&this.input.postrender()},this))},cancel:function(){this.$div.triggerHandler("cancel")},showLoading:function(){var a,b;this.$form?(a=this.$form.outerWidth(),b=this.$form.outerHeight(),a&&this.$loading.width(a),b&&this.$loading.height(b),this.$form.hide()):(a=this.$loading.parent().width(),a&&this.$loading.width(a)),this.$loading.show()},showForm:function(a){this.$loading.hide(),this.$form.show(),a!==!1&&this.input.activate(),this.$div.triggerHandler("show")},error:function(b){var c,d=this.$form.find(".control-group"),e=this.$form.find(".editable-error-block");if(b===!1)d.removeClass(a.fn.editableform.errorGroupClass),e.removeClass(a.fn.editableform.errorBlockClass).empty().hide();else{if(b){c=b.split("\n");for(var f=0;f<c.length;f++)c[f]=a("<div>").text(c[f]).html();b=c.join("<br>")}d.addClass(a.fn.editableform.errorGroupClass),e.addClass(a.fn.editableform.errorBlockClass).html(b).show()}},submit:function(b){b.stopPropagation(),b.preventDefault();var c,d=this.input.input2value();if(c=this.validate(d))return this.error(c),this.showForm(),void 0;if(!this.options.savenochange&&this.input.value2str(d)==this.input.value2str(this.value))return this.$div.triggerHandler("nochange"),void 0;var e=this.input.value2submit(d);this.isSaving=!0,a.when(this.save(e)).done(a.proxy(function(a){this.isSaving=!1;var b="function"==typeof this.options.success?this.options.success.call(this.options.scope,a,d):null;return b===!1?(this.error(!1),this.showForm(!1),void 0):"string"==typeof b?(this.error(b),this.showForm(),void 0):(b&&"object"==typeof b&&b.hasOwnProperty("newValue")&&(d=b.newValue),this.error(!1),this.value=d,this.$div.triggerHandler("save",{newValue:d,submitValue:e,response:a}),void 0)},this)).fail(a.proxy(function(a){this.isSaving=!1;var b;b="function"==typeof this.options.error?this.options.error.call(this.options.scope,a,d):"string"==typeof a?a:a.responseText||a.statusText||"Unknown error!",this.error(b),this.showForm()},this))},save:function(b){this.options.pk=a.fn.editableutils.tryParseJson(this.options.pk,!0);var c,d="function"==typeof this.options.pk?this.options.pk.call(this.options.scope):this.options.pk,e=!!("function"==typeof this.options.url||this.options.url&&("always"===this.options.send||"auto"===this.options.send&&null!==d&&void 0!==d));return e?(this.showLoading(),c={name:this.options.name||"",value:b,pk:d},"function"==typeof this.options.params?c=this.options.params.call(this.options.scope,c):(this.options.params=a.fn.editableutils.tryParseJson(this.options.params,!0),a.extend(c,this.options.params)),"function"==typeof this.options.url?this.options.url.call(this.options.scope,c):a.ajax(a.extend({url:this.options.url,data:c,type:"POST"},this.options.ajaxOptions))):void 0},validate:function(a){return void 0===a&&(a=this.value),"function"==typeof this.options.validate?this.options.validate.call(this.options.scope,a):void 0},option:function(a,b){a in this.options&&(this.options[a]=b),"value"===a&&this.setValue(b)},setValue:function(a,b){this.value=b?this.input.str2value(a):a,this.$form&&this.$form.is(":visible")&&this.input.value2input(this.value)}},a.fn.editableform=function(c){var d=arguments;return this.each(function(){var e=a(this),f=e.data("editableform"),g="object"==typeof c&&c;f||e.data("editableform",f=new b(this,g)),"string"==typeof c&&f[c].apply(f,Array.prototype.slice.call(d,1))})},a.fn.editableform.Constructor=b,a.fn.editableform.defaults={type:"text",url:null,params:null,name:null,pk:null,value:null,defaultValue:null,send:"auto",validate:null,success:null,error:null,ajaxOptions:null,showbuttons:!0,scope:null,savenochange:!1},a.fn.editableform.template='<form class="form-inline editableform"><div class="control-group"><div><div class="editable-input"></div><div class="editable-buttons"></div></div><div class="editable-error-block"></div></div></form>',a.fn.editableform.loading='<div class="editableform-loading"></div>',a.fn.editableform.buttons='<button type="submit" class="editable-submit">ok</button><button type="button" class="editable-cancel">cancel</button>',a.fn.editableform.errorGroupClass=null,a.fn.editableform.errorBlockClass="editable-error",a.fn.editableform.engine="jquery"}(window.jQuery),function(a){"use strict";a.fn.editableutils={inherit:function(a,b){var c=function(){};c.prototype=b.prototype,a.prototype=new c,a.prototype.constructor=a,a.superclass=b.prototype},setCursorPosition:function(a,b){if(a.setSelectionRange)a.setSelectionRange(b,b);else if(a.createTextRange){var c=a.createTextRange();c.collapse(!0),c.moveEnd("character",b),c.moveStart("character",b),c.select()}},tryParseJson:function(a,b){if("string"==typeof a&&a.length&&a.match(/^[\{\[].*[\}\]]$/))if(b)try{a=new Function("return "+a)()}catch(c){}finally{return a}else a=new Function("return "+a)();return a},sliceObj:function(b,c,d){var e,f,g={};if(!a.isArray(c)||!c.length)return g;for(var h=0;h<c.length;h++)e=c[h],b.hasOwnProperty(e)&&(g[e]=b[e]),d!==!0&&(f=e.toLowerCase(),b.hasOwnProperty(f)&&(g[e]=b[f]));return g},getConfigData:function(b){var c={};return a.each(b.data(),function(a,b){("object"!=typeof b||b&&"object"==typeof b&&(b.constructor===Object||b.constructor===Array))&&(c[a]=b)}),c},objectKeys:function(a){if(Object.keys)return Object.keys(a);if(a!==Object(a))throw new TypeError("Object.keys called on a non-object");var b,c=[];for(b in a)Object.prototype.hasOwnProperty.call(a,b)&&c.push(b);return c},escape:function(b){return a("<div>").text(b).html()},itemsByValue:function(b,c,d){if(!c||null===b)return[];if("function"!=typeof d){var e=d||"value";d=function(a){return a[e]}}var f=a.isArray(b),g=[],h=this;return a.each(c,function(c,e){if(e.children)g=g.concat(h.itemsByValue(b,e.children,d));else if(f)a.grep(b,function(a){return a==(e&&"object"==typeof e?d(e):e)}).length&&g.push(e);else{var i=e&&"object"==typeof e?d(e):e;b==i&&g.push(e)}}),g},createInput:function(b){var c,d,e,f=b.type;return"date"===f&&("inline"===b.mode?a.fn.editabletypes.datefield?f="datefield":a.fn.editabletypes.dateuifield&&(f="dateuifield"):a.fn.editabletypes.date?f="date":a.fn.editabletypes.dateui&&(f="dateui"),"date"!==f||a.fn.editabletypes.date||(f="combodate")),"datetime"===f&&"inline"===b.mode&&(f="datetimefield"),"wysihtml5"!==f||a.fn.editabletypes[f]||(f="textarea"),"function"==typeof a.fn.editabletypes[f]?(c=a.fn.editabletypes[f],d=this.sliceObj(b,this.objectKeys(c.defaults)),e=new c(d)):(a.error("Unknown type: "+f),!1)},supportsTransitions:function(){var a=document.body||document.documentElement,b=a.style,c="transition",d=["Moz","Webkit","Khtml","O","ms"];if("string"==typeof b[c])return!0;c=c.charAt(0).toUpperCase()+c.substr(1);for(var e=0;e<d.length;e++)if("string"==typeof b[d[e]+c])return!0;return!1}}}(window.jQuery),function(a){"use strict";var b=function(a,b){this.init(a,b)},c=function(a,b){this.init(a,b)};b.prototype={containerName:null,containerDataName:null,innerCss:null,containerClass:"editable-container editable-popup",defaults:{},init:function(c,d){this.$element=a(c),this.options=a.extend({},a.fn.editableContainer.defaults,d),this.splitOptions(),this.formOptions.scope=this.$element[0],this.initContainer(),this.delayedHide=!1,this.$element.on("destroyed",a.proxy(function(){this.destroy()},this)),a(document).data("editable-handlers-attached")||(a(document).on("keyup.editable",function(b){27===b.which&&a(".editable-open").editableContainer("hide")}),a(document).on("click.editable",function(c){var d,e=a(c.target),f=[".editable-container",".ui-datepicker-header",".datepicker",".modal-backdrop",".bootstrap-wysihtml5-insert-image-modal",".bootstrap-wysihtml5-insert-link-modal"];if(a.contains(document.documentElement,c.target)&&!e.is(document)){for(d=0;d<f.length;d++)if(e.is(f[d])||e.parents(f[d]).length)return;b.prototype.closeOthers(c.target)}}),a(document).data("editable-handlers-attached",!0))},splitOptions:function(){if(this.containerOptions={},this.formOptions={},!a.fn[this.containerName])throw new Error(this.containerName+" not found. Have you included corresponding js file?");for(var b in this.options)b in this.defaults?this.containerOptions[b]=this.options[b]:this.formOptions[b]=this.options[b]},tip:function(){return this.container()?this.container().$tip:null},container:function(){var a;return this.containerDataName&&(a=this.$element.data(this.containerDataName))?a:a=this.$element.data(this.containerName)},call:function(){this.$element[this.containerName].apply(this.$element,arguments)},initContainer:function(){this.call(this.containerOptions)},renderForm:function(){this.$form.editableform(this.formOptions).on({save:a.proxy(this.save,this),nochange:a.proxy(function(){this.hide("nochange")},this),cancel:a.proxy(function(){this.hide("cancel")},this),show:a.proxy(function(){this.delayedHide?(this.hide(this.delayedHide.reason),this.delayedHide=!1):this.setPosition()},this),rendering:a.proxy(this.setPosition,this),resize:a.proxy(this.setPosition,this),rendered:a.proxy(function(){this.$element.triggerHandler("shown",a(this.options.scope).data("editable"))},this)}).editableform("render")},show:function(b){this.$element.addClass("editable-open"),b!==!1&&this.closeOthers(this.$element[0]),this.innerShow(),this.tip().addClass(this.containerClass),this.$form,this.$form=a("<div>"),this.tip().is(this.innerCss)?this.tip().append(this.$form):this.tip().find(this.innerCss).append(this.$form),this.renderForm()},hide:function(a){if(this.tip()&&this.tip().is(":visible")&&this.$element.hasClass("editable-open")){if(this.$form.data("editableform").isSaving)return this.delayedHide={reason:a},void 0;this.delayedHide=!1,this.$element.removeClass("editable-open"),this.innerHide(),this.$element.triggerHandler("hidden",a||"manual")}},innerShow:function(){},innerHide:function(){},toggle:function(a){this.container()&&this.tip()&&this.tip().is(":visible")?this.hide():this.show(a)},setPosition:function(){},save:function(a,b){this.$element.triggerHandler("save",b),this.hide("save")},option:function(a,b){this.options[a]=b,a in this.containerOptions?(this.containerOptions[a]=b,this.setContainerOption(a,b)):(this.formOptions[a]=b,this.$form&&this.$form.editableform("option",a,b))},setContainerOption:function(a,b){this.call("option",a,b)},destroy:function(){this.hide(),this.innerDestroy(),this.$element.off("destroyed"),this.$element.removeData("editableContainer")},innerDestroy:function(){},closeOthers:function(b){a(".editable-open").each(function(c,d){if(d!==b&&!a(d).find(b).length){var e=a(d),f=e.data("editableContainer");f&&("cancel"===f.options.onblur?e.data("editableContainer").hide("onblur"):"submit"===f.options.onblur&&e.data("editableContainer").tip().find("form").submit())}})},activate:function(){this.tip&&this.tip().is(":visible")&&this.$form&&this.$form.data("editableform").input.activate()}},a.fn.editableContainer=function(d){var e=arguments;return this.each(function(){var f=a(this),g="editableContainer",h=f.data(g),i="object"==typeof d&&d,j="inline"===i.mode?c:b;h||f.data(g,h=new j(this,i)),"string"==typeof d&&h[d].apply(h,Array.prototype.slice.call(e,1))})},a.fn.editableContainer.Popup=b,a.fn.editableContainer.Inline=c,a.fn.editableContainer.defaults={value:null,placement:"top",autohide:!0,onblur:"cancel",anim:!1,mode:"popup"},jQuery.event.special.destroyed={remove:function(a){a.handler&&a.handler()}}}(window.jQuery),function(a){"use strict";a.extend(a.fn.editableContainer.Inline.prototype,a.fn.editableContainer.Popup.prototype,{containerName:"editableform",innerCss:".editable-inline",containerClass:"editable-container editable-inline",initContainer:function(){this.$tip=a("<span></span>"),this.options.anim||(this.options.anim=0)},splitOptions:function(){this.containerOptions={},this.formOptions=this.options},tip:function(){return this.$tip},innerShow:function(){this.$element.hide(),this.tip().insertAfter(this.$element).show()},innerHide:function(){this.$tip.hide(this.options.anim,a.proxy(function(){this.$element.show(),this.innerDestroy()},this))},innerDestroy:function(){this.tip()&&this.tip().empty().remove()}})}(window.jQuery),function(a){"use strict";var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.editable.defaults,c,a.fn.editableutils.getConfigData(this.$element)),this.options.selector?this.initLive():this.init(),this.options.highlight&&!a.fn.editableutils.supportsTransitions()&&(this.options.highlight=!1)};b.prototype={constructor:b,init:function(){var b,c=!1;if(this.options.name=this.options.name||this.$element.attr("id"),this.options.scope=this.$element[0],this.input=a.fn.editableutils.createInput(this.options),this.input){switch(void 0===this.options.value||null===this.options.value?(this.value=this.input.html2value(a.trim(this.$element.html())),c=!0):(this.options.value=a.fn.editableutils.tryParseJson(this.options.value,!0),this.value="string"==typeof this.options.value?this.input.str2value(this.options.value):this.options.value),this.$element.addClass("editable"),"textarea"===this.input.type&&this.$element.addClass("editable-pre-wrapped"),"manual"!==this.options.toggle?(this.$element.addClass("editable-click"),this.$element.on(this.options.toggle+".editable",a.proxy(function(a){if(this.options.disabled||a.preventDefault(),"mouseenter"===this.options.toggle)this.show();else{var b="click"!==this.options.toggle;this.toggle(b)}},this))):this.$element.attr("tabindex",-1),"function"==typeof this.options.display&&(this.options.autotext="always"),this.options.autotext){case"always":b=!0;break;case"auto":b=!a.trim(this.$element.text()).length&&null!==this.value&&void 0!==this.value&&!c;break;default:b=!1}a.when(b?this.render():!0).then(a.proxy(function(){this.options.disabled?this.disable():this.enable(),this.$element.triggerHandler("init",this)},this))}},initLive:function(){var b=this.options.selector;this.options.selector=!1,this.options.autotext="never",this.$element.on(this.options.toggle+".editable",b,a.proxy(function(b){var c=a(b.target);c.data("editable")||(c.hasClass(this.options.emptyclass)&&c.empty(),c.editable(this.options).trigger(b))},this))},render:function(a){return this.options.display!==!1?this.input.value2htmlFinal?this.input.value2html(this.value,this.$element[0],this.options.display,a):"function"==typeof this.options.display?this.options.display.call(this.$element[0],this.value,a):this.input.value2html(this.value,this.$element[0]):void 0},enable:function(){this.options.disabled=!1,this.$element.removeClass("editable-disabled"),this.handleEmpty(this.isEmpty),"manual"!==this.options.toggle&&"-1"===this.$element.attr("tabindex")&&this.$element.removeAttr("tabindex")},disable:function(){this.options.disabled=!0,this.hide(),this.$element.addClass("editable-disabled"),this.handleEmpty(this.isEmpty),this.$element.attr("tabindex",-1)},toggleDisabled:function(){this.options.disabled?this.enable():this.disable()},option:function(b,c){return b&&"object"==typeof b?(a.each(b,a.proxy(function(b,c){this.option(a.trim(b),c)},this)),void 0):(this.options[b]=c,"disabled"===b?c?this.disable():this.enable():("value"===b&&this.setValue(c),this.container&&this.container.option(b,c),this.input.option&&this.input.option(b,c),void 0))},handleEmpty:function(b){this.options.display!==!1&&(this.isEmpty=void 0!==b?b:"function"==typeof this.input.isEmpty?this.input.isEmpty(this.$element):""===a.trim(this.$element.html()),this.options.disabled?this.isEmpty&&(this.$element.empty(),this.options.emptyclass&&this.$element.removeClass(this.options.emptyclass)):this.isEmpty?(this.$element.html(this.options.emptytext),this.options.emptyclass&&this.$element.addClass(this.options.emptyclass)):this.options.emptyclass&&this.$element.removeClass(this.options.emptyclass))},show:function(b){if(!this.options.disabled){if(this.container){if(this.container.tip().is(":visible"))return}else{var c=a.extend({},this.options,{value:this.value,input:this.input});this.$element.editableContainer(c),this.$element.on("save.internal",a.proxy(this.save,this)),this.container=this.$element.data("editableContainer")}this.container.show(b)}},hide:function(){this.container&&this.container.hide()},toggle:function(a){this.container&&this.container.tip().is(":visible")?this.hide():this.show(a)},save:function(a,b){if(this.options.unsavedclass){var c=!1;c=c||"function"==typeof this.options.url,c=c||this.options.display===!1,c=c||void 0!==b.response,c=c||this.options.savenochange&&this.input.value2str(this.value)!==this.input.value2str(b.newValue),c?this.$element.removeClass(this.options.unsavedclass):this.$element.addClass(this.options.unsavedclass)}if(this.options.highlight){var d=this.$element,e=d.css("background-color");d.css("background-color",this.options.highlight),setTimeout(function(){"transparent"===e&&(e=""),d.css("background-color",e),d.addClass("editable-bg-transition"),setTimeout(function(){d.removeClass("editable-bg-transition")},1700)},10)}this.setValue(b.newValue,!1,b.response)},validate:function(){return"function"==typeof this.options.validate?this.options.validate.call(this,this.value):void 0},setValue:function(b,c,d){this.value=c?this.input.str2value(b):b,this.container&&this.container.option("value",this.value),a.when(this.render(d)).then(a.proxy(function(){this.handleEmpty()},this))},activate:function(){this.container&&this.container.activate()},destroy:function(){this.disable(),this.container&&this.container.destroy(),this.input.destroy(),"manual"!==this.options.toggle&&(this.$element.removeClass("editable-click"),this.$element.off(this.options.toggle+".editable")),this.$element.off("save.internal"),this.$element.removeClass("editable editable-open editable-disabled"),this.$element.removeData("editable")}},a.fn.editable=function(c){var d={},e=arguments,f="editable";switch(c){case"validate":return this.each(function(){var b,c=a(this),e=c.data(f);e&&(b=e.validate())&&(d[e.options.name]=b)}),d;case"getValue":return 2===arguments.length&&arguments[1]===!0?d=this.eq(0).data(f).value:this.each(function(){var b=a(this),c=b.data(f);c&&void 0!==c.value&&null!==c.value&&(d[c.options.name]=c.input.value2submit(c.value))}),d;case"submit":var g,h=arguments[1]||{},i=this,j=this.editable("validate");return a.isEmptyObject(j)?(g=this.editable("getValue"),h.data&&a.extend(g,h.data),a.ajax(a.extend({url:h.url,data:g,type:"POST"},h.ajaxOptions)).success(function(a){"function"==typeof h.success&&h.success.call(i,a,h)}).error(function(){"function"==typeof h.error&&h.error.apply(i,arguments)})):"function"==typeof h.error&&h.error.call(i,j),this}return this.each(function(){var d=a(this),g=d.data(f),h="object"==typeof c&&c;return h&&h.selector?(g=new b(this,h),void 0):(g||d.data(f,g=new b(this,h)),"string"==typeof c&&g[c].apply(g,Array.prototype.slice.call(e,1)),void 0)})},a.fn.editable.defaults={type:"text",disabled:!1,toggle:"click",emptytext:"Empty",autotext:"auto",value:null,display:null,emptyclass:"editable-empty",unsavedclass:"editable-unsaved",selector:null,highlight:"#FFFF80"}}(window.jQuery),function(a){"use strict";a.fn.editabletypes={};var b=function(){};b.prototype={init:function(b,c,d){this.type=b,this.options=a.extend({},d,c)},prerender:function(){this.$tpl=a(this.options.tpl),this.$input=this.$tpl,this.$clear=null,this.error=null},render:function(){},value2html:function(b,c){a(c)[this.options.escape?"text":"html"](a.trim(b))},html2value:function(b){return a("<div>").html(b).text()},value2str:function(a){return a},str2value:function(a){return a},value2submit:function(a){return a},value2input:function(a){this.$input.val(a)},input2value:function(){return this.$input.val()},activate:function(){this.$input.is(":visible")&&this.$input.focus()},clear:function(){this.$input.val(null)},escape:function(b){return a("<div>").text(b).html()},autosubmit:function(){},destroy:function(){},setClass:function(){this.options.inputclass&&this.$input.addClass(this.options.inputclass)},setAttr:function(a){void 0!==this.options[a]&&null!==this.options[a]&&this.$input.attr(a,this.options[a])},option:function(a,b){this.options[a]=b}},b.defaults={tpl:"",inputclass:null,escape:!0,scope:null,showbuttons:!0},a.extend(a.fn.editabletypes,{abstractinput:b})}(window.jQuery),function(a){"use strict";var b=function(){};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){var b=a.Deferred();return this.error=null,this.onSourceReady(function(){this.renderList(),b.resolve()},function(){this.error=this.options.sourceError,b.resolve()}),b.promise()},html2value:function(){return null},value2html:function(b,c,d,e){var f=a.Deferred(),g=function(){"function"==typeof d?d.call(c,b,this.sourceData,e):this.value2htmlFinal(b,c),f.resolve()};return null===b?g.call(this):this.onSourceReady(g,function(){f.resolve()}),f.promise()},onSourceReady:function(b,c){var d;if(a.isFunction(this.options.source)?(d=this.options.source.call(this.options.scope),this.sourceData=null):d=this.options.source,this.options.sourceCache&&a.isArray(this.sourceData))return b.call(this),void 0;try{d=a.fn.editableutils.tryParseJson(d,!1)}catch(e){return c.call(this),void 0}if("string"==typeof d){if(this.options.sourceCache){var f,g=d;if(a(document).data(g)||a(document).data(g,{}),f=a(document).data(g),f.loading===!1&&f.sourceData)return this.sourceData=f.sourceData,this.doPrepend(),b.call(this),void 0;if(f.loading===!0)return f.callbacks.push(a.proxy(function(){this.sourceData=f.sourceData,this.doPrepend(),b.call(this)},this)),f.err_callbacks.push(a.proxy(c,this)),void 0;f.loading=!0,f.callbacks=[],f.err_callbacks=[]}var h=a.extend({url:d,type:"get",cache:!1,dataType:"json",success:a.proxy(function(d){f&&(f.loading=!1),this.sourceData=this.makeArray(d),a.isArray(this.sourceData)?(f&&(f.sourceData=this.sourceData,a.each(f.callbacks,function(){this.call()})),this.doPrepend(),b.call(this)):(c.call(this),f&&a.each(f.err_callbacks,function(){this.call()}))},this),error:a.proxy(function(){c.call(this),f&&(f.loading=!1,a.each(f.err_callbacks,function(){this.call()}))},this)},this.options.sourceOptions);a.ajax(h)}else this.sourceData=this.makeArray(d),a.isArray(this.sourceData)?(this.doPrepend(),b.call(this)):c.call(this)},doPrepend:function(){null!==this.options.prepend&&void 0!==this.options.prepend&&(a.isArray(this.prependData)||(a.isFunction(this.options.prepend)&&(this.options.prepend=this.options.prepend.call(this.options.scope)),this.options.prepend=a.fn.editableutils.tryParseJson(this.options.prepend,!0),"string"==typeof this.options.prepend&&(this.options.prepend={"":this.options.prepend}),this.prependData=this.makeArray(this.options.prepend)),a.isArray(this.prependData)&&a.isArray(this.sourceData)&&(this.sourceData=this.prependData.concat(this.sourceData)))},renderList:function(){},value2htmlFinal:function(){},makeArray:function(b){var c,d,e,f,g=[];if(!b||"string"==typeof b)return null;if(a.isArray(b)){f=function(a,b){return d={value:a,text:b},c++>=2?!1:void 0};for(var h=0;h<b.length;h++)e=b[h],"object"==typeof e?(c=0,a.each(e,f),1===c?g.push(d):c>1&&(e.children&&(e.children=this.makeArray(e.children)),g.push(e))):g.push({value:e,text:e})}else a.each(b,function(a,b){g.push({value:a,text:b})});return g},option:function(a,b){this.options[a]=b,"source"===a&&(this.sourceData=null),"prepend"===a&&(this.prependData=null)}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{source:null,prepend:!1,sourceError:"Error when loading list",sourceCache:!0,sourceOptions:null}),a.fn.editabletypes.list=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("text",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){this.renderClear(),this.setClass(),this.setAttr("placeholder")},activate:function(){this.$input.is(":visible")&&(this.$input.focus(),a.fn.editableutils.setCursorPosition(this.$input.get(0),this.$input.val().length),this.toggleClear&&this.toggleClear())},renderClear:function(){this.options.clear&&(this.$clear=a('<span class="editable-clear-x"></span>'),this.$input.after(this.$clear).css("padding-right",24).keyup(a.proxy(function(b){if(!~a.inArray(b.keyCode,[40,38,9,13,27])){clearTimeout(this.t);var c=this;this.t=setTimeout(function(){c.toggleClear(b)},100)}},this)).parent().css("position","relative"),this.$clear.click(a.proxy(this.clear,this)))},postrender:function(){},toggleClear:function(){if(this.$clear){var a=this.$input.val().length,b=this.$clear.is(":visible");a&&!b&&this.$clear.show(),!a&&b&&this.$clear.hide()}},clear:function(){this.$clear.hide(),this.$input.val("").focus()}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<input type="text">',placeholder:null,clear:!0}),a.fn.editabletypes.text=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("textarea",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){this.setClass(),this.setAttr("placeholder"),this.setAttr("rows"),this.$input.keydown(function(b){b.ctrlKey&&13===b.which&&a(this).closest("form").submit()})},activate:function(){a.fn.editabletypes.text.prototype.activate.call(this)}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:"<textarea></textarea>",inputclass:"input-large",placeholder:null,rows:7}),a.fn.editabletypes.textarea=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("select",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.list),a.extend(b.prototype,{renderList:function(){this.$input.empty();var b=function(c,d){var e;if(a.isArray(d))for(var f=0;f<d.length;f++)e={},d[f].children?(e.label=d[f].text,c.append(b(a("<optgroup>",e),d[f].children))):(e.value=d[f].value,d[f].disabled&&(e.disabled=!0),c.append(a("<option>",e).text(d[f].text)));return c};b(this.$input,this.sourceData),this.setClass(),this.$input.on("keydown.editable",function(b){13===b.which&&a(this).closest("form").submit()})},value2htmlFinal:function(b,c){var d="",e=a.fn.editableutils.itemsByValue(b,this.sourceData);e.length&&(d=e[0].text),a.fn.editabletypes.abstractinput.prototype.value2html.call(this,d,c)},autosubmit:function(){this.$input.off("keydown.editable").on("change.editable",function(){a(this).closest("form").submit()})}}),b.defaults=a.extend({},a.fn.editabletypes.list.defaults,{tpl:"<select></select>"}),a.fn.editabletypes.select=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("checklist",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.list),a.extend(b.prototype,{renderList:function(){var b;if(this.$tpl.empty(),a.isArray(this.sourceData)){for(var c=0;c<this.sourceData.length;c++)b=a("<label>").append(a("<input>",{type:"checkbox",value:this.sourceData[c].value})).append(a("<span>").text(" "+this.sourceData[c].text)),a("<div>").append(b).appendTo(this.$tpl);this.$input=this.$tpl.find('input[type="checkbox"]'),this.setClass()}},value2str:function(b){return a.isArray(b)?b.sort().join(a.trim(this.options.separator)):""},str2value:function(b){var c,d=null;return"string"==typeof b&&b.length?(c=new RegExp("\\s*"+a.trim(this.options.separator)+"\\s*"),d=b.split(c)):d=a.isArray(b)?b:[b],d},value2input:function(b){this.$input.prop("checked",!1),a.isArray(b)&&b.length&&this.$input.each(function(c,d){var e=a(d);a.each(b,function(a,b){e.val()==b&&e.prop("checked",!0)})})},input2value:function(){var b=[];return this.$input.filter(":checked").each(function(c,d){b.push(a(d).val())}),b},value2htmlFinal:function(b,c){var d=[],e=a.fn.editableutils.itemsByValue(b,this.sourceData),f=this.options.escape;e.length?(a.each(e,function(b,c){var e=f?a.fn.editableutils.escape(c.text):c.text;d.push(e)}),a(c).html(d.join("<br>"))):a(c).empty()},activate:function(){this.$input.first().focus()},autosubmit:function(){this.$input.on("keydown",function(b){13===b.which&&a(this).closest("form").submit()})}}),b.defaults=a.extend({},a.fn.editabletypes.list.defaults,{tpl:'<div class="editable-checklist"></div>',inputclass:null,separator:","}),a.fn.editabletypes.checklist=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("password",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.text),a.extend(b.prototype,{value2html:function(b,c){b?a(c).text("[hidden]"):a(c).empty()},html2value:function(){return null}}),b.defaults=a.extend({},a.fn.editabletypes.text.defaults,{tpl:'<input type="password">'}),a.fn.editabletypes.password=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("email",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.text),b.defaults=a.extend({},a.fn.editabletypes.text.defaults,{tpl:'<input type="email">'}),a.fn.editabletypes.email=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("url",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.text),b.defaults=a.extend({},a.fn.editabletypes.text.defaults,{tpl:'<input type="url">'}),a.fn.editabletypes.url=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("tel",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.text),b.defaults=a.extend({},a.fn.editabletypes.text.defaults,{tpl:'<input type="tel">'}),a.fn.editabletypes.tel=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("number",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.text),a.extend(b.prototype,{render:function(){b.superclass.render.call(this),this.setAttr("min"),this.setAttr("max"),this.setAttr("step")},postrender:function(){this.$clear&&this.$clear.css({right:24})}}),b.defaults=a.extend({},a.fn.editabletypes.text.defaults,{tpl:'<input type="number">',inputclass:"input-mini",min:null,max:null,step:null}),a.fn.editabletypes.number=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("range",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.number),a.extend(b.prototype,{render:function(){this.$input=this.$tpl.filter("input"),this.setClass(),this.setAttr("min"),this.setAttr("max"),this.setAttr("step"),this.$input.on("input",function(){a(this).siblings("output").text(a(this).val())})},activate:function(){this.$input.focus()}}),b.defaults=a.extend({},a.fn.editabletypes.number.defaults,{tpl:'<input type="range"><output style="width: 30px; display: inline-block"></output>',inputclass:"input-medium"}),a.fn.editabletypes.range=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("time",a,b.defaults)
6
+ };a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){this.setClass()}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<input type="time">'}),a.fn.editabletypes.time=b}(window.jQuery),function(a){"use strict";var b=function(c){if(this.init("select2",c,b.defaults),c.select2=c.select2||{},this.sourceData=null,c.placeholder&&(c.select2.placeholder=c.placeholder),!c.select2.tags&&c.source){var d=c.source;a.isFunction(c.source)&&(d=c.source.call(c.scope)),"string"==typeof d?(c.select2.ajax=c.select2.ajax||{},c.select2.ajax.data||(c.select2.ajax.data=function(a){return{query:a}}),c.select2.ajax.results||(c.select2.ajax.results=function(a){return{results:a}}),c.select2.ajax.url=d):(this.sourceData=this.convertSource(d),c.select2.data=this.sourceData)}if(this.options.select2=a.extend({},b.defaults.select2,c.select2),this.isMultiple=this.options.select2.tags||this.options.select2.multiple,this.isRemote="ajax"in this.options.select2,this.idFunc=this.options.select2.id,"function"!=typeof this.idFunc){var e=this.idFunc||"id";this.idFunc=function(a){return a[e]}}this.formatSelection=this.options.select2.formatSelection,"function"!=typeof this.formatSelection&&(this.formatSelection=function(a){return a.text})};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){this.setClass(),this.isRemote&&this.$input.on("select2-loaded",a.proxy(function(a){this.sourceData=a.items.results},this)),this.isMultiple&&this.$input.on("change",function(){a(this).closest("form").parent().triggerHandler("resize")})},value2html:function(c,d){var e,f="",g=this;this.options.select2.tags?e=c:this.sourceData&&(e=a.fn.editableutils.itemsByValue(c,this.sourceData,this.idFunc)),a.isArray(e)?(f=[],a.each(e,function(a,b){f.push(b&&"object"==typeof b?g.formatSelection(b):b)})):e&&(f=g.formatSelection(e)),f=a.isArray(f)?f.join(this.options.viewseparator):f,b.superclass.value2html.call(this,f,d)},html2value:function(a){return this.options.select2.tags?this.str2value(a,this.options.viewseparator):null},value2input:function(b){if(this.$input.data("select2")?this.$input.val(b).trigger("change",!0):(this.$input.val(b),this.$input.select2(this.options.select2)),this.isRemote&&!this.isMultiple&&!this.options.select2.initSelection){var c=this.options.select2.id,d=this.options.select2.formatSelection;if(!c&&!d){var e={id:b,text:a(this.options.scope).text()};this.$input.select2("data",e)}}},input2value:function(){return this.$input.select2("val")},str2value:function(b,c){if("string"!=typeof b||!this.isMultiple)return b;c=c||this.options.select2.separator||a.fn.select2.defaults.separator;var d,e,f;if(null===b||b.length<1)return null;for(d=b.split(c),e=0,f=d.length;f>e;e+=1)d[e]=a.trim(d[e]);return d},autosubmit:function(){this.$input.on("change",function(b,c){c||a(this).closest("form").submit()})},convertSource:function(b){if(a.isArray(b)&&b.length&&void 0!==b[0].value)for(var c=0;c<b.length;c++)void 0!==b[c].value&&(b[c].id=b[c].value,delete b[c].value);return b},destroy:function(){this.$input.data("select2")&&this.$input.select2("destroy")}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<input type="hidden">',select2:null,placeholder:null,source:null,viewseparator:", "}),a.fn.editabletypes.select2=b}(window.jQuery),function(a){var b=function(b,c){return this.$element=a(b),this.$element.is("input")?(this.options=a.extend({},a.fn.combodate.defaults,c,this.$element.data()),this.init(),void 0):(a.error("Combodate should be applied to INPUT element"),void 0)};b.prototype={constructor:b,init:function(){this.map={day:["D","date"],month:["M","month"],year:["Y","year"],hour:["[Hh]","hours"],minute:["m","minutes"],second:["s","seconds"],ampm:["[Aa]",""]},this.$widget=a('<span class="combodate"></span>').html(this.getTemplate()),this.initCombos(),this.$widget.on("change","select",a.proxy(function(){this.$element.val(this.getValue())},this)),this.$widget.find("select").css("width","auto"),this.$element.hide().after(this.$widget),this.setValue(this.$element.val()||this.options.value)},getTemplate:function(){var b=this.options.template;return a.each(this.map,function(a,c){c=c[0];var d=new RegExp(c+"+"),e=c.length>1?c.substring(1,2):c;b=b.replace(d,"{"+e+"}")}),b=b.replace(/ /g,"&nbsp;"),a.each(this.map,function(a,c){c=c[0];var d=c.length>1?c.substring(1,2):c;b=b.replace("{"+d+"}",'<select class="'+a+'"></select>')}),b},initCombos:function(){var b=this;a.each(this.map,function(a){var c,d,e=b.$widget.find("."+a);e.length&&(b["$"+a]=e,c="fill"+a.charAt(0).toUpperCase()+a.slice(1),d=b[c](),b["$"+a].html(b.renderItems(d)))})},initItems:function(a){var b,c=[];if("name"===this.options.firstItem){b=moment.relativeTime||moment.langData()._relativeTime;var d="function"==typeof b[a]?b[a](1,!0,a,!1):b[a];d=d.split(" ").reverse()[0],c.push(["",d])}else"empty"===this.options.firstItem&&c.push(["",""]);return c},renderItems:function(a){for(var b=[],c=0;c<a.length;c++)b.push('<option value="'+a[c][0]+'">'+a[c][1]+"</option>");return b.join("\n")},fillDay:function(){var a,b,c=this.initItems("d"),d=-1!==this.options.template.indexOf("DD");for(b=1;31>=b;b++)a=d?this.leadZero(b):b,c.push([b,a]);return c},fillMonth:function(){var a,b,c=this.initItems("M"),d=-1!==this.options.template.indexOf("MMMM"),e=-1!==this.options.template.indexOf("MMM"),f=-1!==this.options.template.indexOf("MM");for(b=0;11>=b;b++)a=d?moment().date(1).month(b).format("MMMM"):e?moment().date(1).month(b).format("MMM"):f?this.leadZero(b+1):b+1,c.push([b,a]);return c},fillYear:function(){var a,b,c=[],d=-1!==this.options.template.indexOf("YYYY");for(b=this.options.maxYear;b>=this.options.minYear;b--)a=d?b:(b+"").substring(2),c[this.options.yearDescending?"push":"unshift"]([b,a]);return c=this.initItems("y").concat(c)},fillHour:function(){var a,b,c=this.initItems("h"),d=-1!==this.options.template.indexOf("h"),e=(-1!==this.options.template.indexOf("H"),-1!==this.options.template.toLowerCase().indexOf("hh")),f=d?1:0,g=d?12:23;for(b=f;g>=b;b++)a=e?this.leadZero(b):b,c.push([b,a]);return c},fillMinute:function(){var a,b,c=this.initItems("m"),d=-1!==this.options.template.indexOf("mm");for(b=0;59>=b;b+=this.options.minuteStep)a=d?this.leadZero(b):b,c.push([b,a]);return c},fillSecond:function(){var a,b,c=this.initItems("s"),d=-1!==this.options.template.indexOf("ss");for(b=0;59>=b;b+=this.options.secondStep)a=d?this.leadZero(b):b,c.push([b,a]);return c},fillAmpm:function(){var a=-1!==this.options.template.indexOf("a"),b=(-1!==this.options.template.indexOf("A"),[["am",a?"am":"AM"],["pm",a?"pm":"PM"]]);return b},getValue:function(b){var c,d={},e=this,f=!1;return a.each(this.map,function(a){if("ampm"!==a){var b="day"===a?1:0;return d[a]=e["$"+a]?parseInt(e["$"+a].val(),10):b,isNaN(d[a])?(f=!0,!1):void 0}}),f?"":(this.$ampm&&(d.hour=12===d.hour?"am"===this.$ampm.val()?0:12:"am"===this.$ampm.val()?d.hour:d.hour+12),c=moment([d.year,d.month,d.day,d.hour,d.minute,d.second]),this.highlight(c),b=void 0===b?this.options.format:b,null===b?c.isValid()?c:null:c.isValid()?c.format(b):"")},setValue:function(b){function c(b,c){var d={};return b.children("option").each(function(b,e){var f,g=a(e).attr("value");""!==g&&(f=Math.abs(g-c),("undefined"==typeof d.distance||f<d.distance)&&(d={value:g,distance:f}))}),d.value}if(b){var d="string"==typeof b?moment(b,this.options.format):moment(b),e=this,f={};d.isValid()&&(a.each(this.map,function(a,b){"ampm"!==a&&(f[a]=d[b[1]]())}),this.$ampm&&(f.hour>=12?(f.ampm="pm",f.hour>12&&(f.hour-=12)):(f.ampm="am",0===f.hour&&(f.hour=12))),a.each(f,function(a,b){e["$"+a]&&("minute"===a&&e.options.minuteStep>1&&e.options.roundTime&&(b=c(e["$"+a],b)),"second"===a&&e.options.secondStep>1&&e.options.roundTime&&(b=c(e["$"+a],b)),e["$"+a].val(b))}),this.$element.val(d.format(this.options.format)))}},highlight:function(a){a.isValid()?this.options.errorClass?this.$widget.removeClass(this.options.errorClass):this.$widget.find("select").css("border-color",this.borderColor):this.options.errorClass?this.$widget.addClass(this.options.errorClass):(this.borderColor||(this.borderColor=this.$widget.find("select").css("border-color")),this.$widget.find("select").css("border-color","red"))},leadZero:function(a){return 9>=a?"0"+a:a},destroy:function(){this.$widget.remove(),this.$element.removeData("combodate").show()}},a.fn.combodate=function(c){var d,e=Array.apply(null,arguments);return e.shift(),"getValue"===c&&this.length&&(d=this.eq(0).data("combodate"))?d.getValue.apply(d,e):this.each(function(){var d=a(this),f=d.data("combodate"),g="object"==typeof c&&c;f||d.data("combodate",f=new b(this,g)),"string"==typeof c&&"function"==typeof f[c]&&f[c].apply(f,e)})},a.fn.combodate.defaults={format:"DD-MM-YYYY HH:mm",template:"D / MMM / YYYY H : mm",value:null,minYear:1970,maxYear:2015,yearDescending:!0,minuteStep:5,secondStep:1,firstItem:"empty",errorClass:null,roundTime:!0}}(window.jQuery),function(a){"use strict";var b=function(c){this.init("combodate",c,b.defaults),this.options.viewformat||(this.options.viewformat=this.options.format),c.combodate=a.fn.editableutils.tryParseJson(c.combodate,!0),this.options.combodate=a.extend({},b.defaults.combodate,c.combodate,{format:this.options.format,template:this.options.template})};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){this.$input.combodate(this.options.combodate),"bs3"===a.fn.editableform.engine&&this.$input.siblings().find("select").addClass("form-control"),this.options.inputclass&&this.$input.siblings().find("select").addClass(this.options.inputclass)},value2html:function(a,c){var d=a?a.format(this.options.viewformat):"";b.superclass.value2html.call(this,d,c)},html2value:function(a){return a?moment(a,this.options.viewformat):null},value2str:function(a){return a?a.format(this.options.format):""},str2value:function(a){return a?moment(a,this.options.format):null},value2submit:function(a){return this.value2str(a)},value2input:function(a){this.$input.combodate("setValue",a)},input2value:function(){return this.$input.combodate("getValue",null)},activate:function(){this.$input.siblings(".combodate").find("select").eq(0).focus()},autosubmit:function(){}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<input type="text">',inputclass:null,format:"YYYY-MM-DD",viewformat:null,template:"D / MMM / YYYY",combodate:null}),a.fn.editabletypes.combodate=b}(window.jQuery),function(a){"use strict";var b=a.fn.editableform.Constructor.prototype.initInput;a.extend(a.fn.editableform.Constructor.prototype,{initTemplate:function(){this.$form=a(a.fn.editableform.template),this.$form.find(".editable-error-block").addClass("help-block")},initInput:function(){b.apply(this);var c=null===this.input.options.inputclass||this.input.options.inputclass===!1,d="input-medium",e="text,select,textarea,password,email,url,tel,number,range,time".split(",");~a.inArray(this.input.type,e)&&c&&(this.input.options.inputclass=d,this.input.$input.addClass(d))}}),a.fn.editableform.buttons='<button type="submit" class="btn btn-primary editable-submit"><i class="icon-ok icon-white"></i></button><button type="button" class="btn editable-cancel"><i class="icon-remove"></i></button>',a.fn.editableform.errorGroupClass="error",a.fn.editableform.errorBlockClass=null,a.fn.editableform.engine="bs2"}(window.jQuery),function(a){"use strict";a.extend(a.fn.editableContainer.Popup.prototype,{containerName:"popover",innerCss:a.fn.popover&&a(a.fn.popover.defaults.template).find("p").length?".popover-content p":".popover-content",defaults:a.fn.popover.defaults,initContainer:function(){a.extend(this.containerOptions,{trigger:"manual",selector:!1,content:" ",template:this.defaults.template});var b;this.$element.data("template")&&(b=this.$element.data("template"),this.$element.removeData("template")),this.call(this.containerOptions),b&&this.$element.data("template",b)},innerShow:function(){this.call("show")},innerHide:function(){this.call("hide")},innerDestroy:function(){this.call("destroy")},setContainerOption:function(a,b){this.container().options[a]=b},setPosition:function(){!function(){var b,c,d,e,f,g,h,i,j,k,l=this.tip();switch(f="function"==typeof this.options.placement?this.options.placement.call(this,l[0],this.$element[0]):this.options.placement,b=/in/.test(f),l.removeClass("top right bottom left").css({top:0,left:0,display:"block"}),c=this.getPosition(b),d=l[0].offsetWidth,e=l[0].offsetHeight,f=b?f.split(" ")[1]:f,i={top:c.top+c.height,left:c.left+c.width/2-d/2},h={top:c.top-e,left:c.left+c.width/2-d/2},j={top:c.top+c.height/2-e/2,left:c.left-d},k={top:c.top+c.height/2-e/2,left:c.left+c.width},f){case"bottom":i.top+e>a(window).scrollTop()+a(window).height()&&(f=h.top>a(window).scrollTop()?"top":k.left+d<a(window).scrollLeft()+a(window).width()?"right":j.left>a(window).scrollLeft()?"left":"right");break;case"top":h.top<a(window).scrollTop()&&(f=i.top+e<a(window).scrollTop()+a(window).height()?"bottom":k.left+d<a(window).scrollLeft()+a(window).width()?"right":j.left>a(window).scrollLeft()?"left":"right");break;case"left":j.left<a(window).scrollLeft()&&(f=k.left+d<a(window).scrollLeft()+a(window).width()?"right":h.top>a(window).scrollTop()?"top":h.top>a(window).scrollTop()?"bottom":"right");break;case"right":k.left+d>a(window).scrollLeft()+a(window).width()&&(j.left>a(window).scrollLeft()?f="left":h.top>a(window).scrollTop()?f="top":h.top>a(window).scrollTop()&&(f="bottom"))}switch(f){case"bottom":g=i;break;case"top":g=h;break;case"left":g=j;break;case"right":g=k}l.offset(g).addClass(f).addClass("in")}.call(this.container())}})}(window.jQuery),function(a){function b(){return new Date(Date.UTC.apply(Date,arguments))}function c(b,c){var d,e=a(b).data(),f={},g=new RegExp("^"+c.toLowerCase()+"([A-Z])"),c=new RegExp("^"+c.toLowerCase());for(var h in e)c.test(h)&&(d=h.replace(g,function(a,b){return b.toLowerCase()}),f[d]=e[h]);return f}function d(b){var c={};if(k[b]||(b=b.split("-")[0],k[b])){var d=k[b];return a.each(j,function(a,b){b in d&&(c[b]=d[b])}),c}}var e=function(b,c){this._process_options(c),this.element=a(b),this.isInline=!1,this.isInput=this.element.is("input"),this.component=this.element.is(".date")?this.element.find(".add-on, .btn"):!1,this.hasInput=this.component&&this.element.find("input").length,this.component&&0===this.component.length&&(this.component=!1),this.picker=a(l.template),this._buildEvents(),this._attachEvents(),this.isInline?this.picker.addClass("datepicker-inline").appendTo(this.element):this.picker.addClass("datepicker-dropdown dropdown-menu"),this.o.rtl&&(this.picker.addClass("datepicker-rtl"),this.picker.find(".prev i, .next i").toggleClass("icon-arrow-left icon-arrow-right")),this.viewMode=this.o.startView,this.o.calendarWeeks&&this.picker.find("tfoot th.today").attr("colspan",function(a,b){return parseInt(b)+1}),this._allow_update=!1,this.setStartDate(this.o.startDate),this.setEndDate(this.o.endDate),this.setDaysOfWeekDisabled(this.o.daysOfWeekDisabled),this.fillDow(),this.fillMonths(),this._allow_update=!0,this.update(),this.showMode(),this.isInline&&this.show()};e.prototype={constructor:e,_process_options:function(b){this._o=a.extend({},this._o,b);var c=this.o=a.extend({},this._o),d=c.language;switch(k[d]||(d=d.split("-")[0],k[d]||(d=i.language)),c.language=d,c.startView){case 2:case"decade":c.startView=2;break;case 1:case"year":c.startView=1;break;default:c.startView=0}switch(c.minViewMode){case 1:case"months":c.minViewMode=1;break;case 2:case"years":c.minViewMode=2;break;default:c.minViewMode=0}c.startView=Math.max(c.startView,c.minViewMode),c.weekStart%=7,c.weekEnd=(c.weekStart+6)%7;var e=l.parseFormat(c.format);c.startDate!==-1/0&&(c.startDate=l.parseDate(c.startDate,e,c.language)),1/0!==c.endDate&&(c.endDate=l.parseDate(c.endDate,e,c.language)),c.daysOfWeekDisabled=c.daysOfWeekDisabled||[],a.isArray(c.daysOfWeekDisabled)||(c.daysOfWeekDisabled=c.daysOfWeekDisabled.split(/[,\s]*/)),c.daysOfWeekDisabled=a.map(c.daysOfWeekDisabled,function(a){return parseInt(a,10)})},_events:[],_secondaryEvents:[],_applyEvents:function(a){for(var b,c,d=0;d<a.length;d++)b=a[d][0],c=a[d][1],b.on(c)},_unapplyEvents:function(a){for(var b,c,d=0;d<a.length;d++)b=a[d][0],c=a[d][1],b.off(c)},_buildEvents:function(){this.isInput?this._events=[[this.element,{focus:a.proxy(this.show,this),keyup:a.proxy(this.update,this),keydown:a.proxy(this.keydown,this)}]]:this.component&&this.hasInput?this._events=[[this.element.find("input"),{focus:a.proxy(this.show,this),keyup:a.proxy(this.update,this),keydown:a.proxy(this.keydown,this)}],[this.component,{click:a.proxy(this.show,this)}]]:this.element.is("div")?this.isInline=!0:this._events=[[this.element,{click:a.proxy(this.show,this)}]],this._secondaryEvents=[[this.picker,{click:a.proxy(this.click,this)}],[a(window),{resize:a.proxy(this.place,this)}],[a(document),{mousedown:a.proxy(function(a){this.element.is(a.target)||this.element.find(a.target).size()||this.picker.is(a.target)||this.picker.find(a.target).size()||this.hide()},this)}]]},_attachEvents:function(){this._detachEvents(),this._applyEvents(this._events)},_detachEvents:function(){this._unapplyEvents(this._events)},_attachSecondaryEvents:function(){this._detachSecondaryEvents(),this._applyEvents(this._secondaryEvents)},_detachSecondaryEvents:function(){this._unapplyEvents(this._secondaryEvents)},_trigger:function(b,c){var d=c||this.date,e=new Date(d.getTime()+6e4*d.getTimezoneOffset());this.element.trigger({type:b,date:e,format:a.proxy(function(a){var b=a||this.o.format;return l.formatDate(d,b,this.o.language)},this)})},show:function(a){this.isInline||this.picker.appendTo("body"),this.picker.show(),this.height=this.component?this.component.outerHeight():this.element.outerHeight(),this.place(),this._attachSecondaryEvents(),a&&a.preventDefault(),this._trigger("show")},hide:function(){this.isInline||this.picker.is(":visible")&&(this.picker.hide().detach(),this._detachSecondaryEvents(),this.viewMode=this.o.startView,this.showMode(),this.o.forceParse&&(this.isInput&&this.element.val()||this.hasInput&&this.element.find("input").val())&&this.setValue(),this._trigger("hide"))},remove:function(){this.hide(),this._detachEvents(),this._detachSecondaryEvents(),this.picker.remove(),delete this.element.data().datepicker,this.isInput||delete this.element.data().date},getDate:function(){var a=this.getUTCDate();return new Date(a.getTime()+6e4*a.getTimezoneOffset())},getUTCDate:function(){return this.date},setDate:function(a){this.setUTCDate(new Date(a.getTime()-6e4*a.getTimezoneOffset()))},setUTCDate:function(a){this.date=a,this.setValue()},setValue:function(){var a=this.getFormattedDate();this.isInput?this.element.val(a):this.component&&this.element.find("input").val(a)},getFormattedDate:function(a){return void 0===a&&(a=this.o.format),l.formatDate(this.date,a,this.o.language)},setStartDate:function(a){this._process_options({startDate:a}),this.update(),this.updateNavArrows()},setEndDate:function(a){this._process_options({endDate:a}),this.update(),this.updateNavArrows()},setDaysOfWeekDisabled:function(a){this._process_options({daysOfWeekDisabled:a}),this.update(),this.updateNavArrows()},place:function(){if(!this.isInline){var b=parseInt(this.element.parents().filter(function(){return"auto"!=a(this).css("z-index")}).first().css("z-index"))+10,c=this.component?this.component.parent().offset():this.element.offset(),d=this.component?this.component.outerHeight(!0):this.element.outerHeight(!0);this.picker.css({top:c.top+d,left:c.left,zIndex:b})}},_allow_update:!0,update:function(){if(this._allow_update){var a,b=!1;arguments&&arguments.length&&("string"==typeof arguments[0]||arguments[0]instanceof Date)?(a=arguments[0],b=!0):(a=this.isInput?this.element.val():this.element.data("date")||this.element.find("input").val(),delete this.element.data().date),this.date=l.parseDate(a,this.o.format,this.o.language),b&&this.setValue(),this.viewDate=this.date<this.o.startDate?new Date(this.o.startDate):this.date>this.o.endDate?new Date(this.o.endDate):new Date(this.date),this.fill()}},fillDow:function(){var a=this.o.weekStart,b="<tr>";if(this.o.calendarWeeks){var c='<th class="cw">&nbsp;</th>';b+=c,this.picker.find(".datepicker-days thead tr:first-child").prepend(c)}for(;a<this.o.weekStart+7;)b+='<th class="dow">'+k[this.o.language].daysMin[a++%7]+"</th>";b+="</tr>",this.picker.find(".datepicker-days thead").append(b)},fillMonths:function(){for(var a="",b=0;12>b;)a+='<span class="month">'+k[this.o.language].monthsShort[b++]+"</span>";this.picker.find(".datepicker-months td").html(a)},setRange:function(b){b&&b.length?this.range=a.map(b,function(a){return a.valueOf()}):delete this.range,this.fill()},getClassNames:function(b){var c=[],d=this.viewDate.getUTCFullYear(),e=this.viewDate.getUTCMonth(),f=this.date.valueOf(),g=new Date;return b.getUTCFullYear()<d||b.getUTCFullYear()==d&&b.getUTCMonth()<e?c.push("old"):(b.getUTCFullYear()>d||b.getUTCFullYear()==d&&b.getUTCMonth()>e)&&c.push("new"),this.o.todayHighlight&&b.getUTCFullYear()==g.getFullYear()&&b.getUTCMonth()==g.getMonth()&&b.getUTCDate()==g.getDate()&&c.push("today"),f&&b.valueOf()==f&&c.push("active"),(b.valueOf()<this.o.startDate||b.valueOf()>this.o.endDate||-1!==a.inArray(b.getUTCDay(),this.o.daysOfWeekDisabled))&&c.push("disabled"),this.range&&(b>this.range[0]&&b<this.range[this.range.length-1]&&c.push("range"),-1!=a.inArray(b.valueOf(),this.range)&&c.push("selected")),c},fill:function(){var c,d=new Date(this.viewDate),e=d.getUTCFullYear(),f=d.getUTCMonth(),g=this.o.startDate!==-1/0?this.o.startDate.getUTCFullYear():-1/0,h=this.o.startDate!==-1/0?this.o.startDate.getUTCMonth():-1/0,i=1/0!==this.o.endDate?this.o.endDate.getUTCFullYear():1/0,j=1/0!==this.o.endDate?this.o.endDate.getUTCMonth():1/0;this.date&&this.date.valueOf(),this.picker.find(".datepicker-days thead th.datepicker-switch").text(k[this.o.language].months[f]+" "+e),this.picker.find("tfoot th.today").text(k[this.o.language].today).toggle(this.o.todayBtn!==!1),this.picker.find("tfoot th.clear").text(k[this.o.language].clear).toggle(this.o.clearBtn!==!1),this.updateNavArrows(),this.fillMonths();var m=b(e,f-1,28,0,0,0,0),n=l.getDaysInMonth(m.getUTCFullYear(),m.getUTCMonth());m.setUTCDate(n),m.setUTCDate(n-(m.getUTCDay()-this.o.weekStart+7)%7);var o=new Date(m);o.setUTCDate(o.getUTCDate()+42),o=o.valueOf();for(var p,q=[];m.valueOf()<o;){if(m.getUTCDay()==this.o.weekStart&&(q.push("<tr>"),this.o.calendarWeeks)){var r=new Date(+m+864e5*((this.o.weekStart-m.getUTCDay()-7)%7)),s=new Date(+r+864e5*((11-r.getUTCDay())%7)),t=new Date(+(t=b(s.getUTCFullYear(),0,1))+864e5*((11-t.getUTCDay())%7)),u=(s-t)/864e5/7+1;q.push('<td class="cw">'+u+"</td>")}p=this.getClassNames(m),p.push("day");var v=this.o.beforeShowDay(m);void 0===v?v={}:"boolean"==typeof v?v={enabled:v}:"string"==typeof v&&(v={classes:v}),v.enabled===!1&&p.push("disabled"),v.classes&&(p=p.concat(v.classes.split(/\s+/))),v.tooltip&&(c=v.tooltip),p=a.unique(p),q.push('<td class="'+p.join(" ")+'"'+(c?' title="'+c+'"':"")+">"+m.getUTCDate()+"</td>"),m.getUTCDay()==this.o.weekEnd&&q.push("</tr>"),m.setUTCDate(m.getUTCDate()+1)}this.picker.find(".datepicker-days tbody").empty().append(q.join(""));var w=this.date&&this.date.getUTCFullYear(),x=this.picker.find(".datepicker-months").find("th:eq(1)").text(e).end().find("span").removeClass("active");w&&w==e&&x.eq(this.date.getUTCMonth()).addClass("active"),(g>e||e>i)&&x.addClass("disabled"),e==g&&x.slice(0,h).addClass("disabled"),e==i&&x.slice(j+1).addClass("disabled"),q="",e=10*parseInt(e/10,10);var y=this.picker.find(".datepicker-years").find("th:eq(1)").text(e+"-"+(e+9)).end().find("td");e-=1;for(var z=-1;11>z;z++)q+='<span class="year'+(-1==z?" old":10==z?" new":"")+(w==e?" active":"")+(g>e||e>i?" disabled":"")+'">'+e+"</span>",e+=1;y.html(q)},updateNavArrows:function(){if(this._allow_update){var a=new Date(this.viewDate),b=a.getUTCFullYear(),c=a.getUTCMonth();switch(this.viewMode){case 0:this.o.startDate!==-1/0&&b<=this.o.startDate.getUTCFullYear()&&c<=this.o.startDate.getUTCMonth()?this.picker.find(".prev").css({visibility:"hidden"}):this.picker.find(".prev").css({visibility:"visible"}),1/0!==this.o.endDate&&b>=this.o.endDate.getUTCFullYear()&&c>=this.o.endDate.getUTCMonth()?this.picker.find(".next").css({visibility:"hidden"}):this.picker.find(".next").css({visibility:"visible"});break;case 1:case 2:this.o.startDate!==-1/0&&b<=this.o.startDate.getUTCFullYear()?this.picker.find(".prev").css({visibility:"hidden"}):this.picker.find(".prev").css({visibility:"visible"}),1/0!==this.o.endDate&&b>=this.o.endDate.getUTCFullYear()?this.picker.find(".next").css({visibility:"hidden"}):this.picker.find(".next").css({visibility:"visible"})}}},click:function(c){c.preventDefault();var d=a(c.target).closest("span, td, th");if(1==d.length)switch(d[0].nodeName.toLowerCase()){case"th":switch(d[0].className){case"datepicker-switch":this.showMode(1);break;case"prev":case"next":var e=l.modes[this.viewMode].navStep*("prev"==d[0].className?-1:1);switch(this.viewMode){case 0:this.viewDate=this.moveMonth(this.viewDate,e);break;case 1:case 2:this.viewDate=this.moveYear(this.viewDate,e)}this.fill();break;case"today":var f=new Date;f=b(f.getFullYear(),f.getMonth(),f.getDate(),0,0,0),this.showMode(-2);var g="linked"==this.o.todayBtn?null:"view";this._setDate(f,g);break;case"clear":var h;this.isInput?h=this.element:this.component&&(h=this.element.find("input")),h&&h.val("").change(),this._trigger("changeDate"),this.update(),this.o.autoclose&&this.hide()}break;case"span":if(!d.is(".disabled")){if(this.viewDate.setUTCDate(1),d.is(".month")){var i=1,j=d.parent().find("span").index(d),k=this.viewDate.getUTCFullYear();this.viewDate.setUTCMonth(j),this._trigger("changeMonth",this.viewDate),1===this.o.minViewMode&&this._setDate(b(k,j,i,0,0,0,0))}else{var k=parseInt(d.text(),10)||0,i=1,j=0;this.viewDate.setUTCFullYear(k),this._trigger("changeYear",this.viewDate),2===this.o.minViewMode&&this._setDate(b(k,j,i,0,0,0,0))}this.showMode(-1),this.fill()}break;case"td":if(d.is(".day")&&!d.is(".disabled")){var i=parseInt(d.text(),10)||1,k=this.viewDate.getUTCFullYear(),j=this.viewDate.getUTCMonth();d.is(".old")?0===j?(j=11,k-=1):j-=1:d.is(".new")&&(11==j?(j=0,k+=1):j+=1),this._setDate(b(k,j,i,0,0,0,0))}}},_setDate:function(a,b){b&&"date"!=b||(this.date=new Date(a)),b&&"view"!=b||(this.viewDate=new Date(a)),this.fill(),this.setValue(),this._trigger("changeDate");var c;this.isInput?c=this.element:this.component&&(c=this.element.find("input")),c&&(c.change(),!this.o.autoclose||b&&"date"!=b||this.hide())},moveMonth:function(a,b){if(!b)return a;var c,d,e=new Date(a.valueOf()),f=e.getUTCDate(),g=e.getUTCMonth(),h=Math.abs(b);if(b=b>0?1:-1,1==h)d=-1==b?function(){return e.getUTCMonth()==g}:function(){return e.getUTCMonth()!=c},c=g+b,e.setUTCMonth(c),(0>c||c>11)&&(c=(c+12)%12);else{for(var i=0;h>i;i++)e=this.moveMonth(e,b);c=e.getUTCMonth(),e.setUTCDate(f),d=function(){return c!=e.getUTCMonth()}}for(;d();)e.setUTCDate(--f),e.setUTCMonth(c);return e},moveYear:function(a,b){return this.moveMonth(a,12*b)},dateWithinRange:function(a){return a>=this.o.startDate&&a<=this.o.endDate},keydown:function(a){if(this.picker.is(":not(:visible)"))return 27==a.keyCode&&this.show(),void 0;var b,c,d,e=!1;switch(a.keyCode){case 27:this.hide(),a.preventDefault();break;case 37:case 39:if(!this.o.keyboardNavigation)break;b=37==a.keyCode?-1:1,a.ctrlKey?(c=this.moveYear(this.date,b),d=this.moveYear(this.viewDate,b)):a.shiftKey?(c=this.moveMonth(this.date,b),d=this.moveMonth(this.viewDate,b)):(c=new Date(this.date),c.setUTCDate(this.date.getUTCDate()+b),d=new Date(this.viewDate),d.setUTCDate(this.viewDate.getUTCDate()+b)),this.dateWithinRange(c)&&(this.date=c,this.viewDate=d,this.setValue(),this.update(),a.preventDefault(),e=!0);break;case 38:case 40:if(!this.o.keyboardNavigation)break;b=38==a.keyCode?-1:1,a.ctrlKey?(c=this.moveYear(this.date,b),d=this.moveYear(this.viewDate,b)):a.shiftKey?(c=this.moveMonth(this.date,b),d=this.moveMonth(this.viewDate,b)):(c=new Date(this.date),c.setUTCDate(this.date.getUTCDate()+7*b),d=new Date(this.viewDate),d.setUTCDate(this.viewDate.getUTCDate()+7*b)),this.dateWithinRange(c)&&(this.date=c,this.viewDate=d,this.setValue(),this.update(),a.preventDefault(),e=!0);break;case 13:this.hide(),a.preventDefault();break;case 9:this.hide()}if(e){this._trigger("changeDate");var f;this.isInput?f=this.element:this.component&&(f=this.element.find("input")),f&&f.change()}},showMode:function(a){a&&(this.viewMode=Math.max(this.o.minViewMode,Math.min(2,this.viewMode+a))),this.picker.find(">div").hide().filter(".datepicker-"+l.modes[this.viewMode].clsName).css("display","block"),this.updateNavArrows()}};var f=function(b,c){this.element=a(b),this.inputs=a.map(c.inputs,function(a){return a.jquery?a[0]:a}),delete c.inputs,a(this.inputs).datepicker(c).bind("changeDate",a.proxy(this.dateUpdated,this)),this.pickers=a.map(this.inputs,function(b){return a(b).data("datepicker")}),this.updateDates()};f.prototype={updateDates:function(){this.dates=a.map(this.pickers,function(a){return a.date}),this.updateRanges()},updateRanges:function(){var b=a.map(this.dates,function(a){return a.valueOf()});a.each(this.pickers,function(a,c){c.setRange(b)})},dateUpdated:function(b){var c=a(b.target).data("datepicker"),d=c.getUTCDate(),e=a.inArray(b.target,this.inputs),f=this.inputs.length;if(-1!=e){if(d<this.dates[e])for(;e>=0&&d<this.dates[e];)this.pickers[e--].setUTCDate(d);else if(d>this.dates[e])for(;f>e&&d>this.dates[e];)this.pickers[e++].setUTCDate(d);this.updateDates()}},remove:function(){a.map(this.pickers,function(a){a.remove()}),delete this.element.data().datepicker}};var g=a.fn.datepicker,h=a.fn.datepicker=function(b){var g=Array.apply(null,arguments);g.shift();var h;return this.each(function(){var j=a(this),k=j.data("datepicker"),l="object"==typeof b&&b;if(!k){var m=c(this,"date"),n=a.extend({},i,m,l),o=d(n.language),p=a.extend({},i,o,m,l);if(j.is(".input-daterange")||p.inputs){var q={inputs:p.inputs||j.find("input").toArray()};j.data("datepicker",k=new f(this,a.extend(p,q)))}else j.data("datepicker",k=new e(this,p))}return"string"==typeof b&&"function"==typeof k[b]&&(h=k[b].apply(k,g),void 0!==h)?!1:void 0}),void 0!==h?h:this},i=a.fn.datepicker.defaults={autoclose:!1,beforeShowDay:a.noop,calendarWeeks:!1,clearBtn:!1,daysOfWeekDisabled:[],endDate:1/0,forceParse:!0,format:"mm/dd/yyyy",keyboardNavigation:!0,language:"en",minViewMode:0,rtl:!1,startDate:-1/0,startView:0,todayBtn:!1,todayHighlight:!1,weekStart:0},j=a.fn.datepicker.locale_opts=["format","rtl","weekStart"];a.fn.datepicker.Constructor=e;var k=a.fn.datepicker.dates={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa","Su"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",clear:"Clear"}},l={modes:[{clsName:"days",navFnc:"Month",navStep:1},{clsName:"months",navFnc:"FullYear",navStep:1},{clsName:"years",navFnc:"FullYear",navStep:10}],isLeapYear:function(a){return 0===a%4&&0!==a%100||0===a%400},getDaysInMonth:function(a,b){return[31,l.isLeapYear(a)?29:28,31,30,31,30,31,31,30,31,30,31][b]},validParts:/dd?|DD?|mm?|MM?|yy(?:yy)?/g,nonpunctuation:/[^ -\/:-@\[\u3400-\u9fff-`{-~\t\n\r]+/g,parseFormat:function(a){var b=a.replace(this.validParts,"\0").split("\0"),c=a.match(this.validParts);if(!b||!b.length||!c||0===c.length)throw new Error("Invalid date format.");return{separators:b,parts:c}},parseDate:function(c,d,f){if(c instanceof Date)return c;if("string"==typeof d&&(d=l.parseFormat(d)),/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(c)){var g,h,i=/([\-+]\d+)([dmwy])/,j=c.match(/([\-+]\d+)([dmwy])/g);c=new Date;for(var m=0;m<j.length;m++)switch(g=i.exec(j[m]),h=parseInt(g[1]),g[2]){case"d":c.setUTCDate(c.getUTCDate()+h);
7
+ break;case"m":c=e.prototype.moveMonth.call(e.prototype,c,h);break;case"w":c.setUTCDate(c.getUTCDate()+7*h);break;case"y":c=e.prototype.moveYear.call(e.prototype,c,h)}return b(c.getUTCFullYear(),c.getUTCMonth(),c.getUTCDate(),0,0,0)}var n,o,g,j=c&&c.match(this.nonpunctuation)||[],c=new Date,p={},q=["yyyy","yy","M","MM","m","mm","d","dd"],r={yyyy:function(a,b){return a.setUTCFullYear(b)},yy:function(a,b){return a.setUTCFullYear(2e3+b)},m:function(a,b){for(b-=1;0>b;)b+=12;for(b%=12,a.setUTCMonth(b);a.getUTCMonth()!=b;)a.setUTCDate(a.getUTCDate()-1);return a},d:function(a,b){return a.setUTCDate(b)}};r.M=r.MM=r.mm=r.m,r.dd=r.d,c=b(c.getFullYear(),c.getMonth(),c.getDate(),0,0,0);var s=d.parts.slice();if(j.length!=s.length&&(s=a(s).filter(function(b,c){return-1!==a.inArray(c,q)}).toArray()),j.length==s.length){for(var m=0,t=s.length;t>m;m++){if(n=parseInt(j[m],10),g=s[m],isNaN(n))switch(g){case"MM":o=a(k[f].months).filter(function(){var a=this.slice(0,j[m].length),b=j[m].slice(0,a.length);return a==b}),n=a.inArray(o[0],k[f].months)+1;break;case"M":o=a(k[f].monthsShort).filter(function(){var a=this.slice(0,j[m].length),b=j[m].slice(0,a.length);return a==b}),n=a.inArray(o[0],k[f].monthsShort)+1}p[g]=n}for(var u,m=0;m<q.length;m++)u=q[m],u in p&&!isNaN(p[u])&&r[u](c,p[u])}return c},formatDate:function(b,c,d){"string"==typeof c&&(c=l.parseFormat(c));var e={d:b.getUTCDate(),D:k[d].daysShort[b.getUTCDay()],DD:k[d].days[b.getUTCDay()],m:b.getUTCMonth()+1,M:k[d].monthsShort[b.getUTCMonth()],MM:k[d].months[b.getUTCMonth()],yy:b.getUTCFullYear().toString().substring(2),yyyy:b.getUTCFullYear()};e.dd=(e.d<10?"0":"")+e.d,e.mm=(e.m<10?"0":"")+e.m;for(var b=[],f=a.extend([],c.separators),g=0,h=c.parts.length;h>=g;g++)f.length&&b.push(f.shift()),b.push(e[c.parts[g]]);return b.join("")},headTemplate:'<thead><tr><th class="prev"><i class="icon-arrow-left"/></th><th colspan="5" class="datepicker-switch"></th><th class="next"><i class="icon-arrow-right"/></th></tr></thead>',contTemplate:'<tbody><tr><td colspan="7"></td></tr></tbody>',footTemplate:'<tfoot><tr><th colspan="7" class="today"></th></tr><tr><th colspan="7" class="clear"></th></tr></tfoot>'};l.template='<div class="datepicker"><div class="datepicker-days"><table class=" table-condensed">'+l.headTemplate+"<tbody></tbody>"+l.footTemplate+"</table>"+"</div>"+'<div class="datepicker-months">'+'<table class="table-condensed">'+l.headTemplate+l.contTemplate+l.footTemplate+"</table>"+"</div>"+'<div class="datepicker-years">'+'<table class="table-condensed">'+l.headTemplate+l.contTemplate+l.footTemplate+"</table>"+"</div>"+"</div>",a.fn.datepicker.DPGlobal=l,a.fn.datepicker.noConflict=function(){return a.fn.datepicker=g,this},a(document).on("focus.datepicker.data-api click.datepicker.data-api",'[data-provide="datepicker"]',function(b){var c=a(this);c.data("datepicker")||(b.preventDefault(),h.call(c,"show"))}),a(function(){h.call(a('[data-provide="datepicker-inline"]'))})}(window.jQuery),function(a){"use strict";a.fn.bdatepicker=a.fn.datepicker.noConflict(),a.fn.datepicker||(a.fn.datepicker=a.fn.bdatepicker);var b=function(a){this.init("date",a,b.defaults),this.initPicker(a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{initPicker:function(b,c){this.options.viewformat||(this.options.viewformat=this.options.format),b.datepicker=a.fn.editableutils.tryParseJson(b.datepicker,!0),this.options.datepicker=a.extend({},c.datepicker,b.datepicker,{format:this.options.viewformat}),this.options.datepicker.language=this.options.datepicker.language||"en",this.dpg=a.fn.bdatepicker.DPGlobal,this.parsedFormat=this.dpg.parseFormat(this.options.format),this.parsedViewFormat=this.dpg.parseFormat(this.options.viewformat)},render:function(){this.$input.bdatepicker(this.options.datepicker),this.options.clear&&(this.$clear=a('<a href="#"></a>').html(this.options.clear).click(a.proxy(function(a){a.preventDefault(),a.stopPropagation(),this.clear()},this)),this.$tpl.parent().append(a('<div class="editable-clear">').append(this.$clear)))},value2html:function(a,c){var d=a?this.dpg.formatDate(a,this.parsedViewFormat,this.options.datepicker.language):"";b.superclass.value2html.call(this,d,c)},html2value:function(a){return this.parseDate(a,this.parsedViewFormat)},value2str:function(a){return a?this.dpg.formatDate(a,this.parsedFormat,this.options.datepicker.language):""},str2value:function(a){return this.parseDate(a,this.parsedFormat)},value2submit:function(a){return this.value2str(a)},value2input:function(a){this.$input.bdatepicker("update",a)},input2value:function(){return this.$input.data("datepicker").date},activate:function(){},clear:function(){this.$input.data("datepicker").date=null,this.$input.find(".active").removeClass("active"),this.options.showbuttons||this.$input.closest("form").submit()},autosubmit:function(){this.$input.on("mouseup",".day",function(b){if(!a(b.currentTarget).is(".old")&&!a(b.currentTarget).is(".new")){var c=a(this).closest("form");setTimeout(function(){c.submit()},200)}})},parseDate:function(a,b){var c,d=null;return a&&(d=this.dpg.parseDate(a,b,this.options.datepicker.language),"string"==typeof a&&(c=this.dpg.formatDate(d,b,this.options.datepicker.language),a!==c&&(d=null))),d}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<div class="editable-date well"></div>',inputclass:null,format:"yyyy-mm-dd",viewformat:null,datepicker:{weekStart:0,startView:0,minViewMode:0,autoclose:!1},clear:"&times; clear"}),a.fn.editabletypes.date=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("datefield",a,b.defaults),this.initPicker(a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.date),a.extend(b.prototype,{render:function(){this.$input=this.$tpl.find("input"),this.setClass(),this.setAttr("placeholder"),this.$tpl.bdatepicker(this.options.datepicker),this.$input.off("focus keydown"),this.$input.keyup(a.proxy(function(){this.$tpl.removeData("date"),this.$tpl.bdatepicker("update")},this))},value2input:function(a){this.$input.val(a?this.dpg.formatDate(a,this.parsedViewFormat,this.options.datepicker.language):""),this.$tpl.bdatepicker("update")},input2value:function(){return this.html2value(this.$input.val())},activate:function(){a.fn.editabletypes.text.prototype.activate.call(this)},autosubmit:function(){}}),b.defaults=a.extend({},a.fn.editabletypes.date.defaults,{tpl:'<div class="input-append date"><input type="text"/><span class="add-on"><i class="icon-th"></i></span></div>',inputclass:"input-small",datepicker:{weekStart:0,startView:0,minViewMode:0,autoclose:!0}}),a.fn.editabletypes.datefield=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("datetime",a,b.defaults),this.initPicker(a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{initPicker:function(b,c){this.options.viewformat||(this.options.viewformat=this.options.format),b.datetimepicker=a.fn.editableutils.tryParseJson(b.datetimepicker,!0),this.options.datetimepicker=a.extend({},c.datetimepicker,b.datetimepicker,{format:this.options.viewformat}),this.options.datetimepicker.language=this.options.datetimepicker.language||"en",this.dpg=a.fn.datetimepicker.DPGlobal,this.parsedFormat=this.dpg.parseFormat(this.options.format,this.options.formatType),this.parsedViewFormat=this.dpg.parseFormat(this.options.viewformat,this.options.formatType)},render:function(){this.$input.datetimepicker(this.options.datetimepicker),this.$input.on("changeMode",function(){var b=a(this).closest("form").parent();setTimeout(function(){b.triggerHandler("resize")},0)}),this.options.clear&&(this.$clear=a('<a href="#"></a>').html(this.options.clear).click(a.proxy(function(a){a.preventDefault(),a.stopPropagation(),this.clear()},this)),this.$tpl.parent().append(a('<div class="editable-clear">').append(this.$clear)))},value2html:function(a,c){var d=a?this.dpg.formatDate(this.toUTC(a),this.parsedViewFormat,this.options.datetimepicker.language,this.options.formatType):"";return c?(b.superclass.value2html.call(this,d,c),void 0):d},html2value:function(a){var b=this.parseDate(a,this.parsedViewFormat);return b?this.fromUTC(b):null},value2str:function(a){return a?this.dpg.formatDate(this.toUTC(a),this.parsedFormat,this.options.datetimepicker.language,this.options.formatType):""},str2value:function(a){var b=this.parseDate(a,this.parsedFormat);return b?this.fromUTC(b):null},value2submit:function(a){return this.value2str(a)},value2input:function(a){a&&this.$input.data("datetimepicker").setDate(a)},input2value:function(){var a=this.$input.data("datetimepicker");return a.date?a.getDate():null},activate:function(){},clear:function(){this.$input.data("datetimepicker").date=null,this.$input.find(".active").removeClass("active"),this.options.showbuttons||this.$input.closest("form").submit()},autosubmit:function(){this.$input.on("mouseup",".minute",function(){var b=a(this).closest("form");setTimeout(function(){b.submit()},200)})},toUTC:function(a){return a?new Date(a.valueOf()-6e4*a.getTimezoneOffset()):a},fromUTC:function(a){return a?new Date(a.valueOf()+6e4*a.getTimezoneOffset()):a},parseDate:function(a,b){var c,d=null;return a&&(d=this.dpg.parseDate(a,b,this.options.datetimepicker.language,this.options.formatType),"string"==typeof a&&(c=this.dpg.formatDate(d,b,this.options.datetimepicker.language,this.options.formatType),a!==c&&(d=null))),d}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<div class="editable-date well"></div>',inputclass:null,format:"yyyy-mm-dd hh:ii",formatType:"standard",viewformat:null,datetimepicker:{todayHighlight:!1,autoclose:!1},clear:"&times; clear"}),a.fn.editabletypes.datetime=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("datetimefield",a,b.defaults),this.initPicker(a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.datetime),a.extend(b.prototype,{render:function(){this.$input=this.$tpl.find("input"),this.setClass(),this.setAttr("placeholder"),this.$tpl.datetimepicker(this.options.datetimepicker),this.$input.off("focus keydown"),this.$input.keyup(a.proxy(function(){this.$tpl.removeData("date"),this.$tpl.datetimepicker("update")},this))},value2input:function(a){this.$input.val(this.value2html(a)),this.$tpl.datetimepicker("update")},input2value:function(){return this.html2value(this.$input.val())},activate:function(){a.fn.editabletypes.text.prototype.activate.call(this)},autosubmit:function(){}}),b.defaults=a.extend({},a.fn.editabletypes.datetime.defaults,{tpl:'<div class="input-append date"><input type="text"/><span class="add-on"><i class="icon-th"></i></span></div>',inputclass:"input-medium",datetimepicker:{todayHighlight:!1,autoclose:!0}}),a.fn.editabletypes.datetimefield=b}(window.jQuery),function(a){"use strict";var b=function(c){this.init("typeahead",c,b.defaults),this.options.typeahead=a.extend({},b.defaults.typeahead,