| @ -0,0 +1,53 @@ | |||||
|  | .. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg | ||||
|  |     :target: https://www.gnu.org/licenses/agpl-3.0-standalone.html | ||||
|  |     :alt: License: AGPL-3 | ||||
|  | ================= | ||||
|  | Field Time Picker | ||||
|  | ================= | ||||
|  | 
 | ||||
|  | Time picker for fields, using Wickedpicker. | ||||
|  | 
 | ||||
|  | Installation & Configuration | ||||
|  | ============================ | ||||
|  | 
 | ||||
|  | After installing the module, you can use character fields for reading time input with the help of a time picker. | ||||
|  |  When you define the fields in xml, use 'widget="timepicker"' for those fields which you need to use as time fields. | ||||
|  | 
 | ||||
|  | Company | ||||
|  | ------- | ||||
|  | * `Cybrosys Techno Solutions <https://cybrosys.com/>`__ | ||||
|  | 
 | ||||
|  | License | ||||
|  | ------- | ||||
|  | General Public License, Version 3 (AGPL v3). | ||||
|  | (https://www.gnu.org/licenses/agpl-3.0-standalone.html) | ||||
|  | 
 | ||||
|  | Credits | ||||
|  | ------- | ||||
|  | Developer: (V14) Mruthul Raj, Contact: odoo@cybrosys.com | ||||
|  | 
 | ||||
|  | Bug Tracker | ||||
|  | =========== | ||||
|  | Contact odoo@cybrosys.com | ||||
|  | 
 | ||||
|  | Contributors | ||||
|  | ------------ | ||||
|  | 
 | ||||
|  | * Mruthul Raj <mruthul@cybrosys.info> | ||||
|  | 
 | ||||
|  | Contacts | ||||
|  | -------- | ||||
|  | * Mail Contact : odoo@cybrosys.com | ||||
|  | * Website : https://cybrosys.com | ||||
|  | 
 | ||||
|  | Maintainer | ||||
|  | ========== | ||||
|  | .. image:: https://cybrosys.com/images/logo.png | ||||
|  |    :target: https://cybrosys.com | ||||
|  | 
 | ||||
|  | This module is maintained by Cybrosys Technologies. | ||||
|  | For support and more information, please visit `Our Website <https://cybrosys.com/>`__ | ||||
|  | 
 | ||||
|  | Further information | ||||
|  | =================== | ||||
|  | HTML Description: `<static/description/index.html>`__ | ||||
| @ -0,0 +1,21 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ############################################################################### | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | ||||
|  | #    Author: Mruthul Raj (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU AFFERO | ||||
|  | #    GENERAL PUBLIC LICENSE (AGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE | ||||
|  | #    (AGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ############################################################################### | ||||
| @ -0,0 +1,45 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ############################################################################### | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | ||||
|  | #    Author: Mruthul Raj (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU AFFERO | ||||
|  | #    GENERAL PUBLIC LICENSE (AGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE | ||||
|  | #    (AGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ############################################################################### | ||||
|  | { | ||||
|  |     'name': 'Field Time Picker', | ||||
|  |     'version': '14.0.1.0.0', | ||||
|  |     'category': 'Extra Tools', | ||||
|  |     'summary': 'We can use the TimePicker widget in Odoo', | ||||
|  |     'description': 'We Can Add Time Picker Widget That Can Be Used With ' | ||||
|  |                    'Character Type Fields In Odoo', | ||||
|  |     'author': 'Cybrosys Techno Solutions', | ||||
|  |     'company': 'Cybrosys Techno Solutions', | ||||
|  |     'maintainer': 'Cybrosys Techno Solutions', | ||||
|  |     'website': 'https://www.cybrosys.com/', | ||||
|  |     'depends': ['base'], | ||||
|  |     'data': [ | ||||
|  |         'views/web_templates.xml', | ||||
|  |     ], | ||||
|  |     'qweb': [ | ||||
|  |         "static/src/xml/timepicker.xml", | ||||
|  |     ], | ||||
|  |     'images': ['static/description/banner.jpg'], | ||||
|  |     'license': 'AGPL-3', | ||||
|  |     'installable': True, | ||||
|  |     'auto_install': False, | ||||
|  |     'application': False, | ||||
|  | } | ||||
| @ -0,0 +1,7 @@ | |||||
|  | ## Module <field_timepicker> | ||||
|  | 
 | ||||
|  | #### 31.08.2023 | ||||
|  | #### Version 14.0.1.0.0 | ||||
|  | #### ADD | ||||
|  | 
 | ||||
|  |  - Initial Commit for Field Time Picker | ||||
| After Width: | Height: | Size: 3.6 KiB | 
| After Width: | Height: | Size: 310 B | 
| After Width: | Height: | Size: 1.3 KiB | 
| After Width: | Height: | Size: 1.4 KiB | 
| After Width: | Height: | Size: 576 B | 
| After Width: | Height: | Size: 733 B | 
| After Width: | Height: | Size: 911 B | 
| After Width: | Height: | Size: 1.1 KiB | 
| After Width: | Height: | Size: 1.2 KiB | 
| After Width: | Height: | Size: 3.4 KiB | 
| After Width: | Height: | Size: 673 B | 
| After Width: | Height: | Size: 878 B | 
| After Width: | Height: | Size: 653 B | 
| After Width: | Height: | Size: 905 B | 
| After Width: | Height: | Size: 839 B | 
| After Width: | Height: | Size: 427 B | 
| After Width: | Height: | Size: 627 B | 
| After Width: | Height: | Size: 1.2 KiB | 
| After Width: | Height: | Size: 988 B | 
| After Width: | Height: | Size: 1.2 KiB | 
| After Width: | Height: | Size: 60 KiB | 
| After Width: | Height: | Size: 59 KiB | 
| After Width: | Height: | Size: 57 KiB | 
| After Width: | Height: | Size: 58 KiB | 
| After Width: | Height: | Size: 56 KiB | 
| After Width: | Height: | Size: 58 KiB | 
| After Width: | Height: | Size: 89 KiB | 
| After Width: | Height: | Size: 88 KiB | 
| After Width: | Height: | Size: 46 KiB | 
| After Width: | Height: | Size: 8.7 KiB | 
| @ -0,0 +1,550 @@ | |||||
|  | <div class="container" style="padding: 1rem !important; margin-bottom: 1rem !important;"> | ||||
|  |     <div class="row"> | ||||
|  |         <div class="col-sm-12 col-md-12 col-lg-12 d-flex justify-content-between" | ||||
|  |             style="border-bottom: 1px solid #d5d5d5;"> | ||||
|  |             <div class="my-3"> | ||||
|  |                 <img src="./assets/icons/logo.png" style="width: auto !important; height: 40px !important;"> | ||||
|  |             </div> | ||||
|  |             <div class="my-3 d-flex align-items-center"> | ||||
|  |                 <div | ||||
|  |                     style="background-color: #7C7BAD !important; color: #fff !important; font-weight: 600 !important; padding: 5px 15px 8px !important; margin: 0 5px !important;"> | ||||
|  |                     <i class="fa fa-check mr-1"></i>Community | ||||
|  |                 </div> | ||||
|  |                 <div | ||||
|  |                     style="background-color: #875A7B !important; color: #fff !important; font-weight: 600 !important; padding: 5px 15px 8px !important; margin: 0 5px !important;"> | ||||
|  |                     <i class="fa fa-check mr-1"></i>Enterprise | ||||
|  |                 </div> | ||||
|  | 
 | ||||
|  |             </div> | ||||
|  |         </div> | ||||
|  |     </div> | ||||
|  | </div> | ||||
|  | 
 | ||||
|  | <div class="container" style="padding: 0rem 1.5rem 4rem !important"> | ||||
|  |     <div class="row" style="height: 900px !important;"> | ||||
|  |         <div class="col-sm-12 col-md-12 col-lg-12" | ||||
|  |             style="padding: 4rem 1rem !important; background-color: #714B67 !important; height: 600px !important; border-radius: 20px !important;"> | ||||
|  |             <h1 | ||||
|  |                 style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #FFFFFF !important;  font-size: 3.5rem !important; text-align: center !important;"> | ||||
|  |                 Field Time Picker</h1> | ||||
|  |             <p | ||||
|  |                 style="font-family: 'Montserrat', sans-serif !important; font-weight: 300 !important; color: #FFFFFF !important;  font-size: 1.4rem !important; text-align: center !important;"> | ||||
|  |                 Add Time Picker Widget That Can Be Used With Character Type Fields In Odoo | ||||
|  |             </p> | ||||
|  |             <img src="./assets/screenshots/hero1.png" class="img-responsive" width="100%" height="auto" /> | ||||
|  |         </div> | ||||
|  |     </div> | ||||
|  | 
 | ||||
|  |     <div class="row"> | ||||
|  |         <div class="col-md-12" style="border-bottom: 1px solid #d5d5d5 !important; margin-bottom: 2rem !important"> | ||||
|  |             <h2 | ||||
|  |                 style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.5rem !important;"> | ||||
|  |                 <i class="fa fa-compass mr-2"></i>Explore this module | ||||
|  |             </h2> | ||||
|  |         </div> | ||||
|  |         <div class="col-md-6"> | ||||
|  |             <a href="#overview" style="text-decoration: none !important;"> | ||||
|  |                 <div class="row" | ||||
|  |                     style="background-color: #f5f2f5 !important; border-radius: 10px !important; margin: 1rem !important; padding: 1.5em !important; height: 100px !important;"> | ||||
|  |                     <div class="col-8"> | ||||
|  |                         <h3 | ||||
|  |                             style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.2rem !important;"> | ||||
|  |                             Overview</h3> | ||||
|  |                         <p | ||||
|  |                             style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #714B67 !important; font-size: 0.9rem !important;"> | ||||
|  |                             Learn more about this module</p> | ||||
|  |                     </div> | ||||
|  |                     <div class="col-4 text-right d-flex justify-content-end align-items-center"> | ||||
|  |                         <i class="fa fa-chevron-right" style="color: #714B67 !important;"></i> | ||||
|  |                     </div> | ||||
|  |                 </div> | ||||
|  |             </a> | ||||
|  |         </div> | ||||
|  |         <div class="col-md-6"> | ||||
|  |             <a href="#features" style="text-decoration: none !important;"> | ||||
|  |                 <div class="row" | ||||
|  |                     style="background-color: #f5f2f5 !important; border-radius: 10px !important; margin: 1rem !important; padding: 1.5em !important; height: 100px !important;"> | ||||
|  |                     <div class="col-8"> | ||||
|  |                         <h3 | ||||
|  |                             style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.2rem !important;"> | ||||
|  |                             Features</h3> | ||||
|  |                         <p | ||||
|  |                             style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #714B67 !important; font-size: 0.9rem !important;"> | ||||
|  |                             View features of this module</p> | ||||
|  |                     </div> | ||||
|  |                     <div class="col-4 text-right d-flex justify-content-end align-items-center"> | ||||
|  |                         <i class="fa fa-chevron-right" style="color: #714B67 !important;"></i> | ||||
|  |                     </div> | ||||
|  |                 </div> | ||||
|  |             </a> | ||||
|  |         </div> | ||||
|  |         <div class="col-md-6"> | ||||
|  |             <a href="#screenshots" style="text-decoration: none !important;"> | ||||
|  |                 <div class="row" | ||||
|  |                     style="background-color: #f5f2f5 !important; border-radius: 10px !important; margin: 1rem !important; padding: 1.5em !important; height: 100px !important;"> | ||||
|  |                     <div class="col-8"> | ||||
|  |                         <h3 | ||||
|  |                             style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.2rem !important;"> | ||||
|  |                             Screenshots</h3> | ||||
|  |                         <p | ||||
|  |                             style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #714B67 !important; font-size: 0.9rem !important;"> | ||||
|  |                             See key screenshots of this module</p> | ||||
|  |                     </div> | ||||
|  |                     <div class="col-4 text-right d-flex justify-content-end align-items-center"> | ||||
|  |                         <i class="fa fa-chevron-right" style="color: #714B67 !important;"></i> | ||||
|  |                     </div> | ||||
|  |                 </div> | ||||
|  |             </a> | ||||
|  |         </div> | ||||
|  |     </div> | ||||
|  | 
 | ||||
|  | 
 | ||||
|  |     <div class="row" id="overview"> | ||||
|  |         <div class="col-md-12" style="border-bottom: 1px solid #d5d5d5 !important; margin: 2rem 0 !important"> | ||||
|  |             <h2 | ||||
|  |                 style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.5rem !important;"> | ||||
|  |                 <i class="fa fa-pie-chart mr-2"></i>Overview | ||||
|  |             </h2> | ||||
|  |         </div> | ||||
|  | 
 | ||||
|  |         <div class="col-mg-12 pl-3"> | ||||
|  |             <p | ||||
|  |                 style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important; line-height: 30px !important;"> | ||||
|  |                 The module allows the user to add time picker widget that can be used with character type fields in | ||||
|  |                 Odoo | ||||
|  |                 using the jQuery plugin 'Wickedpicker'. | ||||
|  |             </p> | ||||
|  | 
 | ||||
|  |         </div> | ||||
|  |     </div> | ||||
|  | 
 | ||||
|  | 
 | ||||
|  |     <div class="row" id="features"> | ||||
|  |         <div class="col-md-12" style="border-bottom: 1px solid #d5d5d5 !important; margin: 2rem 0 !important"> | ||||
|  |             <h2 | ||||
|  |                 style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.5rem !important;"> | ||||
|  |                 <i class="fa fa-star mr-2"></i>Features | ||||
|  |             </h2> | ||||
|  |         </div> | ||||
|  | 
 | ||||
|  |         <div class="col-md-6 pl-3 d-flex"> | ||||
|  |             <div> | ||||
|  |                 <img src="assets/icons/check.png"> | ||||
|  |             </div> | ||||
|  |             <div> | ||||
|  |                 <h4 | ||||
|  |                     style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> | ||||
|  |                     We can use timepicker widget in Char field</h4> | ||||
|  |             </div> | ||||
|  |         </div> | ||||
|  | 
 | ||||
|  |         <div class="col-md-6 pl-3 d-flex"> | ||||
|  |             <div> | ||||
|  |                 <img src="assets/icons/check.png"> | ||||
|  |             </div> | ||||
|  |             <div> | ||||
|  |                 <h4 | ||||
|  |                     style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> | ||||
|  |                     The timepicker widget is in a 24-hour format</h4> | ||||
|  |             </div> | ||||
|  |         </div> | ||||
|  | 
 | ||||
|  |     </div> | ||||
|  | 
 | ||||
|  |     <div class="row" id="screenshots"> | ||||
|  |         <div class="col-md-12" style="border-bottom: 1px solid #d5d5d5 !important; margin: 2rem 0 !important"> | ||||
|  |             <h2 | ||||
|  |                 style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.5rem !important;"> | ||||
|  |                 <i class="fa fa-image mr-2"></i>Screenshots | ||||
|  |             </h2> | ||||
|  |         </div> | ||||
|  |         <div class="col-lg-12 my-2"> | ||||
|  |             <h4 class="mt-2" | ||||
|  |                 style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> | ||||
|  |                 Field Time Picker</h4> | ||||
|  |             <p | ||||
|  |                 style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> | ||||
|  |                 Once the widget is linked with the field, you will see a picker for time selection. Note that the | ||||
|  |                 picker will be in 24 hours format. | ||||
|  |             </p> | ||||
|  |             <img src="assets/screenshots/time_picker.png" class="img-responsive img-thumbnail border" width="100%" | ||||
|  |                 height="auto" /> | ||||
|  |         </div> | ||||
|  |     </div> | ||||
|  | 
 | ||||
|  |     <!-- SUGGESTED PRODUCTS --> | ||||
|  |     <div class="row"> | ||||
|  |         <div class="col-lg-12 d-flex flex-column justify-content-center" | ||||
|  |             style="text-align: center; padding: 2.5rem 1rem !important;"> | ||||
|  |             <h2 style="color: #212529 !important;">Suggested Products</h2> | ||||
|  |             <hr | ||||
|  |                 style="border: 3px solid #714B67 !important; background-color: #714B67 !important; width: 80px !important; margin-bottom: 2rem !important;" /> | ||||
|  | 
 | ||||
|  |             <div id="demo1" class="row carousel slide" data-ride="carousel"> | ||||
|  |                 <!-- The slideshow --> | ||||
|  |                 <div class="carousel-inner"> | ||||
|  |                     <div class="carousel-item active" style="min-height:0px"> | ||||
|  |                         <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left"> | ||||
|  |                             <a href="https://apps.odoo.com/apps/modules/14.0/employee_orientation/" target="_blank"> | ||||
|  |                                 <div style="border-radius:10px"> | ||||
|  |                                     <img class="img img-responsive center-block" | ||||
|  |                                         style="border-top-left-radius:10px; border-top-right-radius:10px" | ||||
|  |                                         src="./assets/modules/1.png"> | ||||
|  |                                 </div> | ||||
|  |                             </a> | ||||
|  |                         </div> | ||||
|  |                         <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left"> | ||||
|  |                             <a href="https://apps.odoo.com/apps/modules/14.0/employee_documents_expiry/" | ||||
|  |                                 target="_blank"> | ||||
|  |                                 <div style="border-radius:10px"> | ||||
|  |                                     <img class="img img-responsive center-block" | ||||
|  |                                         style="border-top-left-radius:10px; border-top-right-radius:10px" | ||||
|  |                                         src="./assets/modules/2.png"> | ||||
|  |                                 </div> | ||||
|  |                             </a> | ||||
|  |                         </div> | ||||
|  |                         <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left"> | ||||
|  |                             <a href="https://apps.odoo.com/apps/modules/14.0/automatic_payroll/" target="_blank"> | ||||
|  |                                 <div style="border-radius:10px"> | ||||
|  |                                     <img class="img img-responsive center-block" | ||||
|  |                                         style="border-top-left-radius:10px; border-top-right-radius:10px" | ||||
|  |                                         src="./assets/modules/3.png"> | ||||
|  |                                 </div> | ||||
|  |                             </a> | ||||
|  |                         </div> | ||||
|  |                     </div> | ||||
|  |                     <div class="carousel-item" style="min-height:0px"> | ||||
|  |                         <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left"> | ||||
|  |                             <a href="https://apps.odoo.com/apps/modules/14.0/product_return_pos/" target="_blank"> | ||||
|  |                                 <div style="border-radius:10px"> | ||||
|  |                                     <img class="img img-responsive center-block" | ||||
|  |                                         style="border-top-left-radius:10px; border-top-right-radius:10px" | ||||
|  |                                         src="./assets/modules/4.png"> | ||||
|  |                                 </div> | ||||
|  |                             </a> | ||||
|  |                         </div> | ||||
|  |                         <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left"> | ||||
|  |                             <a href="https://apps.odoo.com/apps/modules/14.0/point_of_sale_logo" target="_blank"> | ||||
|  |                                 <div style="border-radius:10px"> | ||||
|  |                                     <img class="img img-responsive center-block" | ||||
|  |                                         style="border-top-left-radius:10px; border-top-right-radius:10px" | ||||
|  |                                         src="./assets/modules/5.png"> | ||||
|  |                                 </div> | ||||
|  |                             </a> | ||||
|  |                         </div> | ||||
|  |                         <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left"> | ||||
|  |                             <a href="https://apps.odoo.com/apps/modules/14.0/invoice_format_editor/" target="_blank"> | ||||
|  |                                 <div style="border-radius:10px"> | ||||
|  |                                     <img class="img img-responsive center-block" | ||||
|  |                                         style="border-top-left-radius:10px; border-top-right-radius:10px" | ||||
|  |                                         src="./assets/modules/6.png"> | ||||
|  |                                 </div> | ||||
|  |                             </a> | ||||
|  |                         </div> | ||||
|  |                     </div> | ||||
|  |                 </div> | ||||
|  |                 <!-- Left and right controls --> | ||||
|  |                 <a class="carousel-control-prev" href="#demo1" data-slide="prev" | ||||
|  |                     style="left:-25px;width: 35px;color: #000;"> <span class="carousel-control-prev-icon"><i | ||||
|  |                             class="fa fa-chevron-left" style="font-size:24px"></i></span> </a> <a | ||||
|  |                     class="carousel-control-next" href="#demo1" data-slide="next" | ||||
|  |                     style="right:-25px;width: 35px;color: #000;"> | ||||
|  |                     <span class="carousel-control-next-icon"><i class="fa fa-chevron-right" | ||||
|  |                             style="font-size:24px"></i></span> | ||||
|  |                 </a> | ||||
|  |             </div> | ||||
|  |         </div> | ||||
|  |     </div> | ||||
|  |     <!-- END OF SUGGESTED PRODUCTS --> | ||||
|  | 
 | ||||
|  |     <!-- OUR SERVICES --> | ||||
|  |     <section class="container" style="margin-top: 6rem !important;"> | ||||
|  |         <div class="row"> | ||||
|  |             <div class="col-lg-12 d-flex flex-column justify-content-center align-items-center"> | ||||
|  |                 <h2 style="color: #212529 !important;">Our Services</h2> | ||||
|  |                 <hr | ||||
|  |                     style="border: 3px solid #714B67 !important; background-color: #714B67 !important; width: 80px !important; margin-bottom: 2rem !important;" /> | ||||
|  |             </div> | ||||
|  | 
 | ||||
|  |             <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> | ||||
|  |                 <div class="d-flex justify-content-center align-items-center mx-3 my-3" | ||||
|  |                     style="background-color: #1dd1a1 !important; border-radius: 15px !important; height: 80px; width: 80px;"> | ||||
|  |                     <img src="assets/icons/cogs.png" class="img-responsive" height="48px" width="48px"> | ||||
|  |                 </div> | ||||
|  |                 <h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> | ||||
|  |                     Odoo | ||||
|  |                     Customization</h6> | ||||
|  |             </div> | ||||
|  | 
 | ||||
|  |             <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> | ||||
|  |                 <div class="d-flex justify-content-center align-items-center mx-3 my-3" | ||||
|  |                     style="background-color: #ff6b6b !important; border-radius: 15px !important; height: 80px; width: 80px;"> | ||||
|  |                     <img src="assets/icons/wrench.png" class="img-responsive" height="48px" width="48px"> | ||||
|  |                 </div> | ||||
|  |                 <h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> | ||||
|  |                     Odoo | ||||
|  |                     Implementation</h6> | ||||
|  |             </div> | ||||
|  | 
 | ||||
|  |             <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> | ||||
|  |                 <div class="d-flex justify-content-center align-items-center mx-3 my-3" | ||||
|  |                     style="background-color: #6462CD !important; border-radius: 15px !important; height: 80px; width: 80px;"> | ||||
|  |                     <img src="assets/icons/lifebuoy.png" class="img-responsive" height="48px" width="48px"> | ||||
|  |                 </div> | ||||
|  |                 <h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> | ||||
|  |                     Odoo | ||||
|  |                     Support</h6> | ||||
|  |             </div> | ||||
|  | 
 | ||||
|  | 
 | ||||
|  |             <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> | ||||
|  |                 <div class="d-flex justify-content-center align-items-center mx-3 my-3" | ||||
|  |                     style="background-color: #ffa801 !important; border-radius: 15px !important; height: 80px; width: 80px;"> | ||||
|  |                     <img src="assets/icons/user.png" class="img-responsive" height="48px" width="48px"> | ||||
|  |                 </div> | ||||
|  |                 <h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> | ||||
|  |                     Hire | ||||
|  |                     Odoo | ||||
|  |                     Developer</h6> | ||||
|  |             </div> | ||||
|  | 
 | ||||
|  |             <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> | ||||
|  |                 <div class="d-flex justify-content-center align-items-center mx-3 my-3" | ||||
|  |                     style="background-color: #54a0ff  !important; border-radius: 15px !important; height: 80px; width: 80px;"> | ||||
|  |                     <img src="assets/icons/puzzle.png" class="img-responsive" height="48px" width="48px"> | ||||
|  |                 </div> | ||||
|  |                 <h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> | ||||
|  |                     Odoo | ||||
|  |                     Integration</h6> | ||||
|  |             </div> | ||||
|  | 
 | ||||
|  |             <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> | ||||
|  |                 <div class="d-flex justify-content-center align-items-center mx-3 my-3" | ||||
|  |                     style="background-color: #6d7680 !important; border-radius: 15px !important; height: 80px; width: 80px;"> | ||||
|  |                     <img src="assets/icons/update.png" class="img-responsive" height="48px" width="48px"> | ||||
|  |                 </div> | ||||
|  |                 <h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> | ||||
|  |                     Odoo | ||||
|  |                     Migration</h6> | ||||
|  |             </div> | ||||
|  | 
 | ||||
|  | 
 | ||||
|  |             <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> | ||||
|  |                 <div class="d-flex justify-content-center align-items-center mx-3 my-3" | ||||
|  |                     style="background-color: #786fa6 !important; border-radius: 15px !important; height: 80px; width: 80px;"> | ||||
|  |                     <img src="assets/icons/consultation.png" class="img-responsive" height="48px" width="48px"> | ||||
|  |                 </div> | ||||
|  |                 <h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> | ||||
|  |                     Odoo | ||||
|  |                     Consultancy</h6> | ||||
|  |             </div> | ||||
|  | 
 | ||||
|  |             <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> | ||||
|  |                 <div class="d-flex justify-content-center align-items-center mx-3 my-3" | ||||
|  |                     style="background-color: #f8a5c2 !important; border-radius: 15px !important; height: 80px; width: 80px;"> | ||||
|  |                     <img src="assets/icons/training.png" class="img-responsive" height="48px" width="48px"> | ||||
|  |                 </div> | ||||
|  |                 <h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> | ||||
|  |                     Odoo | ||||
|  |                     Implementation</h6> | ||||
|  |             </div> | ||||
|  | 
 | ||||
|  |             <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> | ||||
|  |                 <div class="d-flex justify-content-center align-items-center mx-3 my-3" | ||||
|  |                     style="background-color: #e6be26 !important; border-radius: 15px !important; height: 80px; width: 80px;"> | ||||
|  |                     <img src="assets/icons/license.png" class="img-responsive" height="48px" width="48px"> | ||||
|  |                 </div> | ||||
|  |                 <h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> | ||||
|  |                     Odoo | ||||
|  |                     Licensing Consultancy</h6> | ||||
|  |             </div> | ||||
|  |         </div> | ||||
|  |     </section> | ||||
|  |     <!-- END OF END OF OUR SERVICES --> | ||||
|  | 
 | ||||
|  |     <!-- OUR INDUSTRIES --> | ||||
|  |     <section class="container" style="margin-top: 6rem !important;"> | ||||
|  |         <div class="row"> | ||||
|  |             <div class="col-lg-12 d-flex flex-column justify-content-center align-items-center"> | ||||
|  |                 <h2 style="color: #212529 !important;">Our Industries</h2> | ||||
|  |                 <hr | ||||
|  |                     style="border: 3px solid #714B67 !important; background-color: #714B67 !important; width: 80px !important; margin-bottom: 2rem !important;" /> | ||||
|  |             </div> | ||||
|  | 
 | ||||
|  |             <div class="col-lg-3"> | ||||
|  |                 <div class="my-4 d-flex flex-column justify-content-center" | ||||
|  |                     style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;"> | ||||
|  |                     <img src="./assets/icons/trading-black.png" class="img-responsive mb-3" height="48px" width="48px"> | ||||
|  |                     <h5 | ||||
|  |                         style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> | ||||
|  |                         Trading | ||||
|  |                     </h5> | ||||
|  |                     <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | ||||
|  |                         Easily procure | ||||
|  |                         and | ||||
|  |                         sell your products</p> | ||||
|  |                 </div> | ||||
|  |             </div> | ||||
|  | 
 | ||||
|  |             <div class="col-lg-3"> | ||||
|  |                 <div class="my-4 d-flex flex-column justify-content-center" | ||||
|  |                     style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;"> | ||||
|  |                     <img src="./assets/icons/pos-black.png" class="img-responsive mb-3" height="48px" width="48px"> | ||||
|  |                     <h5 | ||||
|  |                         style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> | ||||
|  |                         POS | ||||
|  |                     </h5> | ||||
|  |                     <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | ||||
|  |                         Easy | ||||
|  |                         configuration | ||||
|  |                         and convivial experience</p> | ||||
|  |                 </div> | ||||
|  |             </div> | ||||
|  | 
 | ||||
|  |             <div class="col-lg-3"> | ||||
|  |                 <div class="my-4 d-flex flex-column justify-content-center" | ||||
|  |                     style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;"> | ||||
|  |                     <img src="./assets/icons/education-black.png" class="img-responsive mb-3" height="48px" | ||||
|  |                         width="48px"> | ||||
|  |                     <h5 | ||||
|  |                         style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> | ||||
|  |                         Education | ||||
|  |                     </h5> | ||||
|  |                     <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | ||||
|  |                         A platform for | ||||
|  |                         educational management</p> | ||||
|  |                 </div> | ||||
|  |             </div> | ||||
|  | 
 | ||||
|  |             <div class="col-lg-3"> | ||||
|  |                 <div class="my-4 d-flex flex-column justify-content-center" | ||||
|  |                     style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;"> | ||||
|  |                     <img src="./assets/icons/manufacturing-black.png" class="img-responsive mb-3" height="48px" | ||||
|  |                         width="48px"> | ||||
|  |                     <h5 | ||||
|  |                         style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> | ||||
|  |                         Manufacturing | ||||
|  |                     </h5> | ||||
|  |                     <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | ||||
|  |                         Plan, track and | ||||
|  |                         schedule your operations</p> | ||||
|  |                 </div> | ||||
|  |             </div> | ||||
|  | 
 | ||||
|  |             <div class="col-lg-3"> | ||||
|  |                 <div class="my-4 d-flex flex-column justify-content-center" | ||||
|  |                     style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;"> | ||||
|  |                     <img src="./assets/icons/ecom-black.png" class="img-responsive mb-3" height="48px" width="48px"> | ||||
|  |                     <h5 | ||||
|  |                         style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> | ||||
|  |                         E-commerce & Website | ||||
|  |                     </h5> | ||||
|  |                     <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | ||||
|  |                         Mobile | ||||
|  |                         friendly, | ||||
|  |                         awe-inspiring product pages</p> | ||||
|  |                 </div> | ||||
|  |             </div> | ||||
|  | 
 | ||||
|  |             <div class="col-lg-3"> | ||||
|  |                 <div class="my-4 d-flex flex-column justify-content-center" | ||||
|  |                     style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;"> | ||||
|  |                     <img src="./assets/icons/service-black.png" class="img-responsive mb-3" height="48px" width="48px"> | ||||
|  |                     <h5 | ||||
|  |                         style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> | ||||
|  |                         Service Management | ||||
|  |                     </h5> | ||||
|  |                     <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | ||||
|  |                         Keep track of | ||||
|  |                         services and invoice</p> | ||||
|  |                 </div> | ||||
|  |             </div> | ||||
|  | 
 | ||||
|  |             <div class="col-lg-3"> | ||||
|  |                 <div class="my-4 d-flex flex-column justify-content-center" | ||||
|  |                     style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;"> | ||||
|  |                     <img src="./assets/icons/restaurant-black.png" class="img-responsive mb-3" height="48px" | ||||
|  |                         width="48px"> | ||||
|  |                     <h5 | ||||
|  |                         style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> | ||||
|  |                         Restaurant | ||||
|  |                     </h5> | ||||
|  |                     <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | ||||
|  |                         Run your bar or | ||||
|  |                         restaurant methodically</p> | ||||
|  |                 </div> | ||||
|  |             </div> | ||||
|  | 
 | ||||
|  |             <div class="col-lg-3"> | ||||
|  |                 <div class="my-4 d-flex flex-column justify-content-center" | ||||
|  |                     style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;"> | ||||
|  |                     <img src="./assets/icons/hotel-black.png" class="img-responsive mb-3" height="48px" width="48px"> | ||||
|  |                     <h5 | ||||
|  |                         style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> | ||||
|  |                         Hotel Management | ||||
|  |                     </h5> | ||||
|  |                     <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | ||||
|  |                         An | ||||
|  |                         all-inclusive | ||||
|  |                         hotel management application</p> | ||||
|  |                 </div> | ||||
|  |             </div> | ||||
|  | 
 | ||||
|  |         </div> | ||||
|  |     </section> | ||||
|  | 
 | ||||
|  |     <!-- END OF END OF OUR INDUSTRIES --> | ||||
|  | 
 | ||||
|  |     <!-- FOOTER --> | ||||
|  |     <!-- Footer Section --> | ||||
|  |     <section class="container" style="margin: 5rem auto 2rem;"> | ||||
|  |         <div class="row" style="max-width:1540px;"> | ||||
|  |             <div class="col-lg-12 d-flex flex-column justify-content-center align-items-center"> | ||||
|  |                 <h2 style="color: #212529 !important;">Need Help?</h2> | ||||
|  |                 <hr | ||||
|  |                     style="border: 3px solid #714B67 !important; background-color: #714B67 !important; width: 80px !important; margin-bottom: 2rem !important;" /> | ||||
|  |             </div> | ||||
|  |         </div> | ||||
|  | 
 | ||||
|  |         <!-- Contact Cards --> | ||||
|  |         <div class="row d-flex justify-content-center align-items-center" | ||||
|  |             style="max-width:1540px; margin: 0 auto 2rem auto;"> | ||||
|  | 
 | ||||
|  |             <div class="col-lg-12" style="padding: 0rem 3rem 2rem; border-radius: 10px; margin-right: 3rem; "> | ||||
|  | 
 | ||||
|  |                 <div class="row mt-4"> | ||||
|  |                     <div class="col-lg-6"> | ||||
|  |                         <a href="mailto:odoo@cybrosys.com" target="_blank" class="btn btn-block mb-2 deep_hover" | ||||
|  |                             style="text-decoration: none;  background-color: #4d4d4d; color: #FFF;  border-radius: 4px;"><i | ||||
|  |                                 class="fa fa-envelope mr-2"></i>odoo@cybrosys.com</a> | ||||
|  |                     </div> | ||||
|  |                     <div class="col-lg-6"> | ||||
|  |                         <a href="https://api.whatsapp.com/send?phone=918606827707" target="_blank" | ||||
|  |                             class="btn btn-block mb-2 deep_hover" | ||||
|  |                             style="text-decoration: none;  background-color: #25D366; color: #FFF;  border-radius: 4px;"><i | ||||
|  |                                 class="fa fa-whatsapp mr-2"></i>WhatsApp</a> | ||||
|  |                     </div> | ||||
|  |                 </div> | ||||
|  |             </div> | ||||
|  | 
 | ||||
|  |         </div> | ||||
|  |         <!-- End of Contact Cards --> | ||||
|  |     </section> | ||||
|  |     <!-- Footer --> | ||||
|  |     <section class="oe_container" style="padding: 2rem 3rem 1rem;"> | ||||
|  |         <div class="row" style="max-width:1540px; margin: 0 auto; margin-right: 3rem; "> | ||||
|  |             <!-- Logo --> | ||||
|  |             <div class="col-lg-12 d-flex justify-content-center align-items-center" style="margin-top: 3rem;"> | ||||
|  |                 <img src="https://www.cybrosys.com/images/logo.png" width="200px" height="auto" /> | ||||
|  |             </div> | ||||
|  |             <!-- End of Logo --> | ||||
|  |             <div class="col-lg-12"> | ||||
|  |                 <hr | ||||
|  |                     style="margin-top: 3rem;background: linear-gradient(90deg, rgba(2,0,36,0) 0%, rgba(229,229,229,1) 33%, rgba(229,229,229,1) 58%, rgba(0,212,255,0) 100%); height: 2px; border-style: none;"> | ||||
|  |                 <!-- End of Footer Section --> | ||||
|  |             </div> | ||||
|  |         </div> | ||||
|  |     </section> | ||||
|  |     <!-- END OF FOOTER --> | ||||
|  | 
 | ||||
|  | </div> | ||||
| @ -0,0 +1,83 @@ | |||||
|  | odoo.define('field_timepicker.timepicker', function(require) { | ||||
|  |     "use strict"; | ||||
|  | 
 | ||||
|  |     var basic_fields = require('web.basic_fields'); | ||||
|  |     var field_registry = require('web.field_registry'); | ||||
|  |     var global_show_time = null; | ||||
|  |     var FieldChar = require('web.basic_fields').FieldChar; | ||||
|  |     var Dialog = require('web.Dialog'); | ||||
|  | 
 | ||||
|  |     /** | ||||
|  |      * Custom field for time selection. | ||||
|  |      */ | ||||
|  |     var FieldTimePicker = FieldChar.extend({ | ||||
|  |         template: 'FieldTimePicker', | ||||
|  |         widget_class: 'oe_form_field_time', | ||||
|  | 
 | ||||
|  |         /** | ||||
|  |          * Renders the field in read-only mode. | ||||
|  |          */ | ||||
|  |         _renderReadonly: function() { | ||||
|  |             var show_value = this._formatValue(this.value); | ||||
|  |             this.$el.text(show_value); | ||||
|  |             global_show_time = show_value; | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         /** | ||||
|  |          * Gets the current value of the field. | ||||
|  |          * | ||||
|  |          * @returns {string} The field value. | ||||
|  |          */ | ||||
|  |         _getValue: function() { | ||||
|  |             var $input = this.$el.find('input'); | ||||
|  |             return $input.val(); | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         /** | ||||
|  |          * Renders the field in edit mode. | ||||
|  |          */ | ||||
|  |         _renderEdit: function() { | ||||
|  |             this._super.apply(this, arguments); | ||||
|  |             var show_value = this._formatValue(this.value); | ||||
|  |             this.$el.find('input')[0].value=show_value; | ||||
|  |             var self = this; | ||||
|  |             this.$el.on('click', '.timepickerg', function() { | ||||
|  |                 self._onClickTimePicker(); | ||||
|  |             }); | ||||
|  |             /** | ||||
|  |             * Call the click function. | ||||
|  |             */ | ||||
|  |              setTimeout(function() { | ||||
|  |                 self._onClickTimePicker(); | ||||
|  |             }, 50); | ||||
|  |         }, | ||||
|  |         _onClickTimePicker: function() { | ||||
|  |             /** | ||||
|  |              * Function to be executed when the "timepicker" class is clicked. | ||||
|  |              * It renders the field as an editable timepicker widget if the formatType is "char". | ||||
|  |              */ | ||||
|  |             if (this.formatType === "char") { | ||||
|  |                 var $input = this.$el.find('input'); | ||||
|  |                 var options = { | ||||
|  |                     twentyFour: true, | ||||
|  |                     title: 'Timepicker', | ||||
|  |                     showSeconds: true, | ||||
|  |                 }; | ||||
|  |                 if (global_show_time) { | ||||
|  |                     options['now'] = global_show_time; | ||||
|  |                 } | ||||
|  |                 $input.wickedpicker(options); | ||||
|  |             } else { | ||||
|  |                 Dialog.alert(this, "Timepicker widget only works with 'Char' field type"); | ||||
|  |                 return false; | ||||
|  |             } | ||||
|  |         }, | ||||
|  |     }); | ||||
|  | 
 | ||||
|  |     // Register the FieldTimePicker in the field registry
 | ||||
|  |     field_registry.add('timepicker', FieldTimePicker); | ||||
|  | 
 | ||||
|  |     return { | ||||
|  |         FieldTimePicker: FieldTimePicker | ||||
|  |     }; | ||||
|  | }); | ||||
| @ -0,0 +1,21 @@ | |||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||
|  | <!--Template for timepicker--> | ||||
|  | <templates id="timepicker"> | ||||
|  |     <t t-name="FieldTimePicker"> | ||||
|  |         <span t-if="widget.mode !== 'readonly'"> | ||||
|  |             <div class="input-group timepicker-component"> | ||||
|  |                 <input type="text" | ||||
|  |                        t-att-id="widget.id_for_label" | ||||
|  |                        t-att-tabindex="widget.attrs.tabindex" | ||||
|  |                        t-att-autofocus="widget.attrs.autofocus" | ||||
|  |                        t-att-placeholder="widget.attrs.placeholder" | ||||
|  |                        t-att-maxlength="widget.field.size" | ||||
|  |                        class="timepickerg form-control" | ||||
|  |                 /> | ||||
|  |                 <span class="input-group-addon" style="display:none;"> | ||||
|  |                 </span> | ||||
|  |             </div> | ||||
|  |         </span> | ||||
|  |         <span t-if="widget.mode === 'readonly'"/> | ||||
|  |     </t> | ||||
|  | </templates> | ||||
| @ -0,0 +1,11 @@ | |||||
|  | .sass-cache | ||||
|  | *.html | ||||
|  | jquery-1.11.3.min.js | ||||
|  | .idea | ||||
|  | sass | ||||
|  | jasmine | ||||
|  | spec | ||||
|  | node_modules | ||||
|  | node_module/* | ||||
|  | gulpfile.js | ||||
|  | package.json | ||||
| @ -0,0 +1,21 @@ | |||||
|  | The MIT License | ||||
|  | 
 | ||||
|  | Copyright (c) 2015-2016 Eric Gagnon http://ericjgagnon.github.io/wickedpicker/ | ||||
|  | 
 | ||||
|  | Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  | of this software and associated documentation files (the "Software"), to deal | ||||
|  | in the Software without restriction, including without limitation the rights | ||||
|  | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  | copies of the Software, and to permit persons to whom the Software is | ||||
|  | furnished to do so, subject to the following conditions: | ||||
|  | 
 | ||||
|  | The above copyright notice and this permission notice shall be included in | ||||
|  | all copies or substantial portions of the Software. | ||||
|  | 
 | ||||
|  | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  | THE SOFTWARE. | ||||
| @ -0,0 +1,79 @@ | |||||
|  | # Wickedpicker | ||||
|  | 
 | ||||
|  | ## wickedpicker.js - A simple jQuery timepicker | ||||
|  | 
 | ||||
|  | ## Requirements | ||||
|  | 
 | ||||
|  | * [jQuery](http://jquery.com/download/) (>= 1.9) | ||||
|  | 
 | ||||
|  | ## Installation | ||||
|  | ```shell | ||||
|  |     $ bower install wickedpicker | ||||
|  | ``` | ||||
|  | 
 | ||||
|  | ## Usage | ||||
|  | 
 | ||||
|  | #### In your HTML | ||||
|  |  ```html | ||||
|  |  <body> | ||||
|  |  .... | ||||
|  |  <input type="text" name="timepicker" class="timepicker"/> | ||||
|  |  .... | ||||
|  |  <script type="text/javascript" src="jquery-1.11.3.min.js"></script> | ||||
|  |   <script type="text/javascript" src="wickedpicker.js"></script> | ||||
|  |  </body> | ||||
|  |  ``` | ||||
|  | 
 | ||||
|  | #### In your JavaScript file | ||||
|  |  ```javascript | ||||
|  |      $('.timepicker').wickedpicker(); | ||||
|  |  ``` | ||||
|  | 
 | ||||
|  | #### Options | ||||
|  | ```javascript | ||||
|  |     var options = { | ||||
|  |         now: "12:35", //hh:mm 24 hour format only, defaults to current time | ||||
|  |         twentyFour: false,  //Display 24 hour format, defaults to false | ||||
|  |         upArrow: 'wickedpicker__controls__control-up',  //The up arrow class selector to use, for custom CSS | ||||
|  |         downArrow: 'wickedpicker__controls__control-down', //The down arrow class selector to use, for custom CSS | ||||
|  |         close: 'wickedpicker__close', //The close class selector to use, for custom CSS | ||||
|  |         hoverState: 'hover-state', //The hover state class to use, for custom CSS | ||||
|  |         title: 'Timepicker', //The Wickedpicker's title, | ||||
|  |         showSeconds: false, //Whether or not to show seconds, | ||||
|  |         timeSeparator: ' : ', // The string to put in between hours and minutes (and seconds) | ||||
|  |         secondsInterval: 1, //Change interval for seconds, defaults to 1, | ||||
|  |         minutesInterval: 1, //Change interval for minutes, defaults to 1 | ||||
|  |         beforeShow: null, //A function to be called before the Wickedpicker is shown | ||||
|  |         afterShow: null, //A function to be called after the Wickedpicker is closed/hidden | ||||
|  |         show: null, //A function to be called when the Wickedpicker is shown | ||||
|  |         clearable: false, //Make the picker's input clearable (has clickable "x") | ||||
|  |     }; | ||||
|  |     $('.timepicker').wickedpicker(options); | ||||
|  | ``` | ||||
|  | 
 | ||||
|  | #### Methods | ||||
|  | 
 | ||||
|  | 'time' get the current time inside of the input element that has a wickedpicker attached to it. | ||||
|  | ```javascript | ||||
|  |     $('.timepicker').wickedpicker('time'); | ||||
|  | ``` | ||||
|  | 
 | ||||
|  |   If multiple input fields have the same class and instantiate a wickedpicker then pass the index of the timepicker | ||||
|  |   you'd like to select | ||||
|  |  ```javascript | ||||
|  |     $('.timepicker').wickedpicker('time', 0); | ||||
|  |  ``` | ||||
|  | 
 | ||||
|  | #### Functionality | ||||
|  |     The Wickedpicker opens when the bound input is clicked, or focused on (try tabbing), and it can be closed by either | ||||
|  |     clicking the X, by clicking outside of it, or by pressing esc. The arrows icons increase or decrease their | ||||
|  |     associated time values or toggle the meridiem.  The values can also be changed using the up and down keys when | ||||
|  |     focused on. To move to the next value just press the left or right arrow key. | ||||
|  | 
 | ||||
|  | For more checkout | ||||
|  | [Wickedpicker gh-pages](http://ericjgagnon.github.io/wickedpicker/) | ||||
|  | 
 | ||||
|  | ## License | ||||
|  | 
 | ||||
|  |  Copyright (c) 2015-2016 Eric Gagnon Licensed under the MIT license. | ||||
|  | 
 | ||||
| @ -0,0 +1,29 @@ | |||||
|  | { | ||||
|  |   "name": "wickedpicker", | ||||
|  |   "version": "0.0.4", | ||||
|  |   "description": "A simple jQuery timepicker plugin.", | ||||
|  |   "main": [ | ||||
|  |     "./dist/wickedpicker.min.js", | ||||
|  |     "./dist/wickedpicker.min.css" | ||||
|  |   ], | ||||
|  |   "authors": [ | ||||
|  |     "Eric Gagnon", | ||||
|  |     "Ruben Seyferth" | ||||
|  |   ], | ||||
|  |   "moduleType": "globals", | ||||
|  |   "license": "MIT", | ||||
|  |   "keywords": [ | ||||
|  |     "jQuery", | ||||
|  |     "timepicker", | ||||
|  |     "wickedpicker" | ||||
|  |   ], | ||||
|  |   "homepage": "http://ericjgagnon.github.io/wickedpicker/", | ||||
|  |   "repository": { | ||||
|  |     "type": "git", | ||||
|  |     "url": "git://github.com/ericjgagnon/wickedpicker.git" | ||||
|  |   }, | ||||
|  |   "dependencies": { | ||||
|  |     "jquery": ">= 1.9.0" | ||||
|  |   }, | ||||
|  |   "private": false | ||||
|  | } | ||||
| After Width: | Height: | Size: 1.2 KiB | 
| @ -0,0 +1,624 @@ | |||||
|  | /** | ||||
|  |  * wickedpicker v0.4.1 - A simple jQuery timepicker. | ||||
|  |  * Copyright (c) 2015-2016 Eric Gagnon - http://github.com/wickedRidge/wickedpicker
 | ||||
|  |  * License: MIT | ||||
|  |  */ | ||||
|  | 
 | ||||
|  | (function ($, window, document) { | ||||
|  | 
 | ||||
|  |     "use strict"; | ||||
|  | 
 | ||||
|  |     if (typeof String.prototype.endsWith != 'function') { | ||||
|  |         /* | ||||
|  |          * Checks if this string end ends with another string | ||||
|  |          * | ||||
|  |          * @param {string} the string to be checked | ||||
|  |          * | ||||
|  |          * @return {bool} | ||||
|  |          */ | ||||
|  |         String.prototype.endsWith = function (string) { | ||||
|  |             return string.length > 0 && this.substring(this.length - string.length, this.length) === string; | ||||
|  |         } | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     /* | ||||
|  |      * Returns if the user agent is mobile | ||||
|  |      * | ||||
|  |      * @return {bool} | ||||
|  |      */ | ||||
|  |     var isMobile = function () { | ||||
|  |         return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); | ||||
|  |     }; | ||||
|  | 
 | ||||
|  |     var today = new Date(); | ||||
|  | 
 | ||||
|  |     var pluginName = "wickedpicker", | ||||
|  |         defaults = { | ||||
|  |             now: today.getHours() + ':' + today.getMinutes(), | ||||
|  |             twentyFour: false, | ||||
|  |             upArrow: 'wickedpicker__controls__control-up', | ||||
|  |             downArrow: 'wickedpicker__controls__control-down', | ||||
|  |             close: 'wickedpicker__close', | ||||
|  |             hoverState: 'hover-state', | ||||
|  |             title: 'Timepicker', | ||||
|  |             showSeconds: false, | ||||
|  |             timeSeparator: ' : ', | ||||
|  |             secondsInterval: 1, | ||||
|  |             minutesInterval: 1, | ||||
|  |             beforeShow: null, | ||||
|  |             afterShow: null, | ||||
|  |             show: null, | ||||
|  |             clearable: false, | ||||
|  |             closeOnClickOutside: true, | ||||
|  |             onClickOutside: function() {}, | ||||
|  |         }; | ||||
|  | 
 | ||||
|  |     /* | ||||
|  |      * @param {object} The input object the timepicker is attached to. | ||||
|  |      * @param {object} The object containing options | ||||
|  |      */ | ||||
|  |     function Wickedpicker(element, options) { | ||||
|  |         this.element = $(element); | ||||
|  |         this.options = $.extend({}, defaults, options); | ||||
|  | 
 | ||||
|  |         this.element.addClass('hasWickedpicker'); | ||||
|  |         this.element.attr('onkeypress', 'return false;'); | ||||
|  |         this.element.attr('aria-showingpicker', 'false'); | ||||
|  |         this.createPicker(); | ||||
|  |         this.timepicker = $('.wickedpicker'); | ||||
|  |         this.up = $('.' + this.options.upArrow.split(/\s+/).join('.')); | ||||
|  |         this.down = $('.' + this.options.downArrow.split(/\s+/).join('.')); | ||||
|  |         this.separator = $('.wickedpicker__controls__control--separator'); | ||||
|  |         this.hoursElem = $('.wickedpicker__controls__control--hours'); | ||||
|  |         this.minutesElem = $('.wickedpicker__controls__control--minutes'); | ||||
|  |         this.secondsElem = $('.wickedpicker__controls__control--seconds'); | ||||
|  |         this.meridiemElem = $('.wickedpicker__controls__control--meridiem'); | ||||
|  |         this.close = $('.' + this.options.close.split(/\s+/).join('.')); | ||||
|  | 
 | ||||
|  |         //Create a new Date object based on the default or passing in now value
 | ||||
|  |         var time = this.timeArrayFromString(this.options.now); | ||||
|  |         this.options.now = new Date(today.getFullYear(), today.getMonth(), today.getDate(), time[0], time[1], time[2]); | ||||
|  |         this.selectedHour = this.parseHours(this.options.now.getHours()); | ||||
|  |         this.selectedMin = this.parseSecMin(this.options.now.getMinutes()); | ||||
|  |         this.selectedSec = this.parseSecMin(this.options.now.getSeconds()); | ||||
|  |         this.selectedMeridiem = this.parseMeridiem(this.options.now.getHours()); | ||||
|  |         this.setHoverState(); | ||||
|  |         this.attach(element); | ||||
|  |         this.setText(element); | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     $.extend(Wickedpicker.prototype, { | ||||
|  | 
 | ||||
|  |         /* | ||||
|  |          * Show given input's timepicker | ||||
|  |          * | ||||
|  |          * @param {object} The input being clicked | ||||
|  |          */ | ||||
|  |         showPicker: function (element) { | ||||
|  |             //If there is a beforeShow function, then call it with the input calling the timepicker and the
 | ||||
|  |             // timepicker itself
 | ||||
|  |             if (typeof this.options.beforeShow === 'function') { | ||||
|  |                 this.options.beforeShow(element, this.timepicker); | ||||
|  |             } | ||||
|  |             var timepickerPos = $(element).offset(); | ||||
|  | 
 | ||||
|  |             $(element).attr({'aria-showingpicker': 'true', 'tabindex': -1}); | ||||
|  |             this.setText(element); | ||||
|  |             this.showHideMeridiemControl(); | ||||
|  |             if (this.getText(element) !== this.getTime()) { | ||||
|  | 
 | ||||
|  |                 // Check meridiem 
 | ||||
|  |                 var text = this.getText(element); | ||||
|  |                 var re = /\s[ap]m$/i; | ||||
|  |                 var meridiem = re.test(text) ? text.substr(-2, 2) : null; | ||||
|  |                 var inputTime = text.replace(re, '').split(this.options.timeSeparator); | ||||
|  |                 var newTime = {}; | ||||
|  |                 newTime.hours = inputTime[0]; | ||||
|  |                 newTime.minutes = inputTime[1]; | ||||
|  |                 newTime.meridiem = meridiem; | ||||
|  |                 if (this.options.showSeconds) { | ||||
|  |                     newTime.seconds = inputTime[2]; | ||||
|  |                 } | ||||
|  |                 this.setTime(newTime); | ||||
|  |             } | ||||
|  |             this.timepicker.css({ | ||||
|  |                 'z-index': this.element.css('z-index') + 1, | ||||
|  |                 position: 'absolute', | ||||
|  |                 left: timepickerPos.left, | ||||
|  |                 top: timepickerPos.top + $(element)[0].offsetHeight | ||||
|  |             }).show(); | ||||
|  |             //If there is a show function, then call it with the input calling the timepicker and the
 | ||||
|  |             // timepicker itself
 | ||||
|  |             if (typeof this.options.show === 'function') { | ||||
|  |                 this.options.show(element, this.timepicker); | ||||
|  |             } | ||||
|  | 
 | ||||
|  |             this.handleTimeAdjustments(element); | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         /* | ||||
|  |          * Hides the timepicker that is currently shown if it is not part of the timepicker | ||||
|  |          * | ||||
|  |          * @param {Object} The DOM object being clicked on the page | ||||
|  |          *  | ||||
|  |          * BeinnLora: added trigger function to call on closing/hiding timepicker.  | ||||
|  |          */ | ||||
|  |         hideTimepicker: function (element) { | ||||
|  |             this.timepicker.hide(); | ||||
|  |             if (typeof this.options.afterShow === 'function') { | ||||
|  |                 this.options.afterShow(element, this.timepicker); | ||||
|  |             } | ||||
|  |             var pickerHidden = { | ||||
|  |                 start: function () { | ||||
|  |                     var setShowPickerFalse = $.Deferred(); | ||||
|  |                     $('[aria-showingpicker="true"]').attr('aria-showingpicker', 'false'); | ||||
|  |                     return setShowPickerFalse.promise(); | ||||
|  |                 } | ||||
|  |             }; | ||||
|  | 
 | ||||
|  |             function setTabIndex(index) { | ||||
|  |                 setTimeout(function () { | ||||
|  |                     $('[aria-showingpicker="false"]').attr('tabindex', index); | ||||
|  |                 }, 400); | ||||
|  |             } | ||||
|  | 
 | ||||
|  |             pickerHidden.start().then(setTabIndex(0)); | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         /* | ||||
|  |          * Create a new timepicker. A single timepicker per page | ||||
|  |          */ | ||||
|  |         createPicker: function () { | ||||
|  |             if ($('.wickedpicker').length === 0) { | ||||
|  |                 var picker = '<div class="wickedpicker"><p class="wickedpicker__title">' + this.options.title + '<span class="wickedpicker__close"></span></p><ul class="wickedpicker__controls"><li class="wickedpicker__controls__control"><span class="' + this.options.upArrow + '"></span><span class="wickedpicker__controls__control--hours" tabindex="-1">00</span><span class="' + this.options.downArrow + '"></span></li><li class="wickedpicker__controls__control--separator"><span class="wickedpicker__controls__control--separator-inner">:</span></li><li class="wickedpicker__controls__control"><span class="' + this.options.upArrow + '"></span><span class="wickedpicker__controls__control--minutes" tabindex="-1">00</span><span class="' + this.options.downArrow + '"></span></li>'; | ||||
|  |                 if (this.options.showSeconds) { | ||||
|  |                     picker += '<li class="wickedpicker__controls__control--separator"><span class="wickedpicker__controls__control--separator-inner">:</span></li><li class="wickedpicker__controls__control"><span class="' + this.options.upArrow + '"></span><span class="wickedpicker__controls__control--seconds" tabindex="-1">00</span><span class="' + this.options.downArrow + '"></span> </li>'; | ||||
|  |                 } | ||||
|  |                 picker += '<li class="wickedpicker__controls__control"><span class="' + this.options.upArrow + '"></span><span class="wickedpicker__controls__control--meridiem" tabindex="-1">AM</span><span class="' + this.options.downArrow + '"></span></li></ul></div>'; | ||||
|  |                 $('body').append(picker); | ||||
|  |                 this.attachKeyboardEvents(); | ||||
|  |             } | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         /* | ||||
|  |          * Hides the meridiem control if this timepicker is a 24 hour clock | ||||
|  |          */ | ||||
|  |         showHideMeridiemControl: function () { | ||||
|  |             if (this.options.twentyFour === false) { | ||||
|  |                 $(this.meridiemElem).parent().show(); | ||||
|  |             } | ||||
|  |             else { | ||||
|  |                 $(this.meridiemElem).parent().hide(); | ||||
|  |             } | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         /* | ||||
|  |          * Hides the seconds control if this timepicker has showSeconds set to true | ||||
|  |          */ | ||||
|  |         showHideSecondsControl: function () { | ||||
|  |             if (this.options.showSeconds) { | ||||
|  |                 $(this.secondsElem).parent().show(); | ||||
|  |             } | ||||
|  |             else { | ||||
|  |                 $(this.secondsElem).parent().hide(); | ||||
|  |             } | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         /* | ||||
|  |          * Bind the click events to the input | ||||
|  |          * | ||||
|  |          * @param {object} The input element | ||||
|  |          */ | ||||
|  |         attach: function (element) { | ||||
|  |             var self = this; | ||||
|  | 
 | ||||
|  |             if (this.options.clearable) { | ||||
|  |                 self.makePickerInputClearable(element); | ||||
|  |             } | ||||
|  | 
 | ||||
|  |             $(element).attr('tabindex', 0); | ||||
|  |             $(element).on('click focus', function (event) { | ||||
|  |                 //Prevent multiple firings
 | ||||
|  |                 if ($(self.timepicker).is(':hidden')) { | ||||
|  |                   self.showPicker($(this)); | ||||
|  |                   window.lastTimePickerControl = $(this); //Put the reference on this timepicker into global scope for unsing that in afterShow function
 | ||||
|  |                   $(self.hoursElem).focus(); | ||||
|  |                 } | ||||
|  |             }); | ||||
|  | 
 | ||||
|  | 
 | ||||
|  |             //Handle click events for closing Wickedpicker
 | ||||
|  |             var clickHandler = function (event) { //TODO: Fix double firing
 | ||||
|  |                 //Only fire the hide event when you have to
 | ||||
|  |                 if ($(self.timepicker).is(':visible')) { | ||||
|  |                     //Clicking the X
 | ||||
|  |                     if ($(event.target).is(self.close)) { | ||||
|  |                       self.hideTimepicker(window.lastTimePickerControl); | ||||
|  |                     } else if ($(event.target).closest(self.timepicker).length || $(event.target).closest($('.hasWickedpicker')).length) { //Clicking the Wickedpicker or one of it's inputs
 | ||||
|  |                       event.stopPropagation(); | ||||
|  |                     } else {   //Everything else
 | ||||
|  |                       if (typeof self.options.onClickOutside === 'function') { | ||||
|  |                         self.options.onClickOutside(); | ||||
|  |                       } | ||||
|  |                       else { | ||||
|  |                         console.warn("Type of onClickOutside must be a function"); | ||||
|  |                       } | ||||
|  | 
 | ||||
|  |                       if (!self.options.closeOnClickOutside) { | ||||
|  |                         return; | ||||
|  |                       } | ||||
|  |                       self.hideTimepicker(window.lastTimePickerControl); | ||||
|  |                     } | ||||
|  |                     window.lastTimePickerControl = null; | ||||
|  |                 } | ||||
|  |             }; | ||||
|  |             $(document).off('click', clickHandler).on('click', clickHandler); | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         /** | ||||
|  |          * Added keyboard functionality to improve usabil | ||||
|  |          */ | ||||
|  |         attachKeyboardEvents: function () { | ||||
|  |             $(document).on('keydown', $.proxy(function (event) { | ||||
|  |                 switch (event.keyCode) { | ||||
|  |                     case 9: | ||||
|  |                         if (event.target.className !== 'hasWickedpicker') { | ||||
|  |                             $(this.close).trigger('click'); | ||||
|  |                         } | ||||
|  |                         break; | ||||
|  |                     case 27: | ||||
|  |                         $(this.close).trigger('click'); | ||||
|  |                         break; | ||||
|  |                     case 37: //Left arrow
 | ||||
|  |                         if (event.target.className !== this.hoursElem[0].className) { | ||||
|  |                             $(event.target).parent().prevAll('li').not(this.separator.selector).first().children()[1].focus(); | ||||
|  |                         } else { | ||||
|  |                             $(event.target).parent().siblings(':last').children()[1].focus(); | ||||
|  |                         } | ||||
|  |                         break; | ||||
|  |                     case 39: //Right arrow
 | ||||
|  |                         if (event.target.className !== this.meridiemElem[0].className) { | ||||
|  |                             $(event.target).parent().nextAll('li').not(this.separator.selector).first().children()[1].focus(); | ||||
|  |                         } else { | ||||
|  |                             $(event.target).parent().siblings(':first').children()[1].focus(); | ||||
|  |                         } | ||||
|  |                         break; | ||||
|  |                     case 38: //Up arrow
 | ||||
|  |                         $(':focus').prev().trigger('click'); | ||||
|  |                         break; | ||||
|  |                     case 40: //Down arrow
 | ||||
|  |                         $(':focus').next().trigger('click'); | ||||
|  |                         break; | ||||
|  |                     default: | ||||
|  |                         break; | ||||
|  |                 } | ||||
|  |             }, this)); | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         /* | ||||
|  |          * Set the time on the timepicker | ||||
|  |          * | ||||
|  |          * @param {object} The date being set | ||||
|  |          */ | ||||
|  |         setTime: function (time) { | ||||
|  |             this.setHours(time.hours); | ||||
|  |             this.setMinutes(time.minutes); | ||||
|  |             this.setMeridiem(time.meridiem); | ||||
|  |             if (this.options.showSeconds) { | ||||
|  |                 this.setSeconds(time.seconds); | ||||
|  |             } | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         /* | ||||
|  |          * Get the time from the timepicker | ||||
|  |          */ | ||||
|  |         getTime: function () { | ||||
|  |             return [this.formatTime(this.getHours(), this.getMinutes(), this.getMeridiem(), this.getSeconds())]; | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         /* | ||||
|  |          * Set the timpicker's hour(s) value | ||||
|  |          * | ||||
|  |          * @param {string} hours | ||||
|  |          */ | ||||
|  |         setHours: function (hours) { | ||||
|  |             var hour = new Date(); | ||||
|  |             hour.setHours(hours); | ||||
|  |             var hoursText = this.parseHours(hour.getHours()); | ||||
|  |             this.hoursElem.text(hoursText); | ||||
|  |             this.selectedHour = hoursText; | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         /* | ||||
|  |          * Get the hour(s) value from the timepicker | ||||
|  |          * | ||||
|  |          * @return {integer} | ||||
|  |          */ | ||||
|  |         getHours: function () { | ||||
|  |             var hours = new Date(); | ||||
|  |             hours.setHours(this.hoursElem.text()); | ||||
|  |             return hours.getHours(); | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         /* | ||||
|  |          * Returns the correct hour value based on the type of clock, 12 or 24 hour | ||||
|  |          * | ||||
|  |          * @param {integer} The hours value before parsing | ||||
|  |          * | ||||
|  |          * @return {string|integer} | ||||
|  |          */ | ||||
|  |         parseHours: function (hours) { | ||||
|  |             return (this.options.twentyFour === false) ? ((hours + 11) % 12) + 1 : (hours < 10) ? '0' + hours : hours; | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         /* | ||||
|  |          * Sets the timpicker's minutes value | ||||
|  |          * | ||||
|  |          * @param {string} minutes | ||||
|  |          */ | ||||
|  |         setMinutes: function (minutes) { | ||||
|  |             var minute = new Date(); | ||||
|  |             minute.setMinutes(minutes); | ||||
|  |             var minutesText = minute.getMinutes(); | ||||
|  |             var min = this.parseSecMin(minutesText); | ||||
|  |             this.minutesElem.text(min); | ||||
|  |             this.selectedMin = min; | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         /* | ||||
|  |          * Get the minutes value from the timepicker | ||||
|  |          * | ||||
|  |          * @return {integer} | ||||
|  |          */ | ||||
|  |         getMinutes: function () { | ||||
|  |             var minutes = new Date(); | ||||
|  |             minutes.setMinutes(this.minutesElem.text()); | ||||
|  |             return minutes.getMinutes(); | ||||
|  |         }, | ||||
|  | 
 | ||||
|  | 
 | ||||
|  |         /* | ||||
|  |          * Return a human-readable minutes/seconds value | ||||
|  |          * | ||||
|  |          * @param {string} value seconds or minutes | ||||
|  |          * | ||||
|  |          * @return {string|integer} | ||||
|  |          */ | ||||
|  |         parseSecMin: function (value) { | ||||
|  |             return ((value < 10) ? '0' : '') + value; | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         /* | ||||
|  |          * Set the timepicker's meridiem value, AM or PM | ||||
|  |          * | ||||
|  |          * @param {string} The new meridiem | ||||
|  |          */ | ||||
|  |         setMeridiem: function (inputMeridiem) { | ||||
|  |             var newMeridiem = ''; | ||||
|  |             if (inputMeridiem === undefined) { | ||||
|  |                 var meridiem = this.getMeridiem(); | ||||
|  |                 newMeridiem = (meridiem === 'PM') ? 'AM' : 'PM'; | ||||
|  |             } else { | ||||
|  |                 newMeridiem = inputMeridiem; | ||||
|  |             } | ||||
|  |             this.meridiemElem.text(newMeridiem); | ||||
|  |             this.selectedMeridiem = newMeridiem; | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         /* | ||||
|  |          * Get the timepicker's meridiem value, AM or PM | ||||
|  |          * | ||||
|  |          * @return {string} | ||||
|  |          */ | ||||
|  |         getMeridiem: function () { | ||||
|  |             return this.meridiemElem.text(); | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         /* | ||||
|  |          * Set the timepicker's seconds value | ||||
|  |          * | ||||
|  |          * @param {string} seconds | ||||
|  |          */ | ||||
|  |         setSeconds: function (seconds) { | ||||
|  |             var second = new Date(); | ||||
|  |             second.setSeconds(seconds); | ||||
|  |             var secondsText = second.getSeconds(); | ||||
|  |             var sec = this.parseSecMin(secondsText); | ||||
|  |             this.secondsElem.text(sec); | ||||
|  |             this.selectedSec = sec; | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         /* | ||||
|  |          * Get the timepicker's seconds value | ||||
|  |          * | ||||
|  |          * return {string} | ||||
|  |          */ | ||||
|  |         getSeconds: function () { | ||||
|  |             var seconds = new Date(); | ||||
|  |             seconds.setSeconds(this.secondsElem.text()); | ||||
|  |             return seconds.getSeconds(); | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         /* | ||||
|  |          * Get the correct meridiem based on the hours given | ||||
|  |          * | ||||
|  |          * @param {string|integer} hours | ||||
|  |          * | ||||
|  |          * @return {string} | ||||
|  |          */ | ||||
|  |         parseMeridiem: function (hours) { | ||||
|  |             return (hours > 11) ? 'PM' : 'AM'; | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         /* | ||||
|  |          * Handles time incrementing and decrementing and passes | ||||
|  |          * the operator, '+' or '-', the input to be set after the change | ||||
|  |          * and the current arrow clicked, to decipher if hours, ninutes, or meridiem. | ||||
|  |          * | ||||
|  |          * @param {object} The input element | ||||
|  |          */ | ||||
|  |         handleTimeAdjustments: function (element) { | ||||
|  |             var timeOut = 0; | ||||
|  |             //Click and click and hold timepicker incrementer and decrementer
 | ||||
|  |             $(this.up).add(this.down).off('mousedown click touchstart').on('mousedown click', { | ||||
|  |                 'Wickedpicker': this, | ||||
|  |                 'input': element | ||||
|  |             }, function (event) { | ||||
|  |                 if(event.which!=1) return false; | ||||
|  |                 var operator = (this.className.indexOf('up') > -1) ? '+' : '-'; | ||||
|  |                 var passedData = event.data; | ||||
|  |                 if (event.type == 'mousedown') { | ||||
|  |                     timeOut = setInterval($.proxy(function (args) { | ||||
|  |                         args.Wickedpicker.changeValue(operator, args.input, this); | ||||
|  |                     }, this, {'Wickedpicker': passedData.Wickedpicker, 'input': passedData.input}), 200); | ||||
|  |                 } else { | ||||
|  |                     passedData.Wickedpicker.changeValue(operator, passedData.input, this); | ||||
|  |                 } | ||||
|  |             }).bind('mouseup touchend', function () { | ||||
|  |                 clearInterval(timeOut); | ||||
|  |             }); | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         /* | ||||
|  |          * Change the timepicker's time base on what is clicked | ||||
|  |          * | ||||
|  |          * @param {string} The + or - operator | ||||
|  |          * @param {object} The timepicker's associated input to be set post change | ||||
|  |          * @param {object} The DOM arrow object clicked, determines if it is hours, | ||||
|  |          * minutes, or meridiem base on the operator and its siblings | ||||
|  |          */ | ||||
|  |         changeValue: function (operator, input, clicked) { | ||||
|  |             var target = (operator === '+') ? clicked.nextSibling : clicked.previousSibling; | ||||
|  |             var targetClass = $(target).attr('class'); | ||||
|  |             if (targetClass.endsWith('hours')) { | ||||
|  |                 this.setHours(eval(this.getHours() + operator + 1)); | ||||
|  |             } else if (targetClass.endsWith('minutes')) { | ||||
|  |                 this.setMinutes(eval(this.getMinutes() + operator + this.options.minutesInterval)); | ||||
|  |             } else if (targetClass.endsWith('seconds')) { | ||||
|  |                 this.setSeconds(eval(this.getSeconds() + operator + this.options.secondsInterval)); | ||||
|  |             } else { | ||||
|  |                 this.setMeridiem(); | ||||
|  |             } | ||||
|  |             this.setText(input); | ||||
|  |         }, | ||||
|  | 
 | ||||
|  | 
 | ||||
|  |         /* | ||||
|  |          * Sets the give input's text to the current timepicker's time | ||||
|  |          * | ||||
|  |          * @param {object} The input element | ||||
|  |          */ | ||||
|  |         setText: function (input) { | ||||
|  |             $(input).val(this.formatTime(this.selectedHour, this.selectedMin, this.selectedMeridiem, this.selectedSec)).change(); | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         /* | ||||
|  |          * Get the given input's value | ||||
|  |          * | ||||
|  |          * @param {object} The input element | ||||
|  |          * | ||||
|  |          * @return {string} | ||||
|  |          */ | ||||
|  |         getText: function (input) { | ||||
|  |             return $(input).val(); | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         /* | ||||
|  |          * Returns the correct time format as a string | ||||
|  |          * | ||||
|  |          * @param {string} hour | ||||
|  |          * @param {string} minutes | ||||
|  |          * @param {string} meridiem | ||||
|  |          * | ||||
|  |          * @return {string} | ||||
|  |          */ | ||||
|  |         formatTime: function (hour, min, meridiem, seconds) { | ||||
|  |             var formattedTime = hour + this.options.timeSeparator + min; | ||||
|  |             if (this.options.showSeconds) { | ||||
|  |                 formattedTime += this.options.timeSeparator  + seconds; | ||||
|  |             } | ||||
|  |             if (this.options.twentyFour === false) { | ||||
|  |                 formattedTime += ' ' + meridiem; | ||||
|  |             } | ||||
|  |             return formattedTime; | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         /** | ||||
|  |          *  Apply the hover class to the arrows and close icon fonts | ||||
|  |          */ | ||||
|  |         setHoverState: function () { | ||||
|  |             var self = this; | ||||
|  |             if (!isMobile()) { | ||||
|  |                 $(this.up).add(this.down).add(this.close).hover(function () { | ||||
|  |                     $(this).toggleClass(self.options.hoverState); | ||||
|  |                 }); | ||||
|  |             } | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         /** | ||||
|  |          * Wrapping the given input field with the clearable container | ||||
|  |          * , add a span that will contain the x, and bind the clear | ||||
|  |          * input event to the span | ||||
|  |          * | ||||
|  |          * @param input | ||||
|  |          */ | ||||
|  |         makePickerInputClearable: function(input) { | ||||
|  |             $(input).wrap('<div class="clearable-picker"></div>').after('<span data-clear-picker>×</span>'); | ||||
|  | 
 | ||||
|  |             //When the x is clicked, clear its sibling input field
 | ||||
|  |             $('[data-clear-picker]').on('click', function(event) { | ||||
|  |                $(this).siblings('.hasWickedpicker').val(''); | ||||
|  |             }); | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         /** | ||||
|  |          * Convert the options time string format | ||||
|  |          * to an array | ||||
|  |          * | ||||
|  |          * returns => [hours, minutes, seconds] | ||||
|  |          * | ||||
|  |          * @param stringTime | ||||
|  |          * @returns {*} | ||||
|  |          */ | ||||
|  |         timeArrayFromString: function (stringTime) { | ||||
|  |             if (stringTime.length) { | ||||
|  |                 var time = stringTime.split(':'); | ||||
|  |                 time[2] = (time.length < 3) ? '00' : time[2]; | ||||
|  |                 return time; | ||||
|  |             } | ||||
|  |             return false; | ||||
|  |         }, | ||||
|  | 
 | ||||
|  |         //public functions
 | ||||
|  |         /* | ||||
|  |          * Returns the requested input element's value | ||||
|  |          */ | ||||
|  |         _time: function () { | ||||
|  |             var inputValue = $(this.element).val(); | ||||
|  |             return (inputValue === '') ? this.formatTime(this.selectedHour, this.selectedMin, this.selectedMeridiem, this.selectedSec) : inputValue; | ||||
|  |         }, | ||||
|  |         _hide: function() { | ||||
|  |             this.hideTimepicker(this.element); | ||||
|  |         } | ||||
|  |     }); | ||||
|  | 
 | ||||
|  |     //optional index if multiple inputs share the same class
 | ||||
|  |     $.fn[pluginName] = function (options, index) { | ||||
|  |         if (!$.isFunction(Wickedpicker.prototype['_' + options])) { | ||||
|  |             return this.each(function () { | ||||
|  |                 if (!$.data(this, "plugin_" + pluginName)) { | ||||
|  |                     $.data(this, "plugin_" + pluginName, new Wickedpicker(this, options)); | ||||
|  |                 } | ||||
|  |             }); | ||||
|  |         } | ||||
|  |         else if ($(this).hasClass('hasWickedpicker')) { | ||||
|  |             if (index !== undefined) { | ||||
|  |                 return $.data($(this)[index], 'plugin_' + pluginName)['_' + options](); | ||||
|  |             } | ||||
|  |             else { | ||||
|  |                 return $.data($(this)[0], 'plugin_' + pluginName)['_' + options](); | ||||
|  |             } | ||||
|  |         } | ||||
|  |     }; | ||||
|  | 
 | ||||
|  | })(jQuery, window, document); | ||||
| @ -0,0 +1,90 @@ | |||||
|  | .wickedpicker { | ||||
|  |   -webkit-user-select: none; | ||||
|  |   -moz-user-select: none; | ||||
|  |   -ms-user-select: none; | ||||
|  |   user-select: none; | ||||
|  |   box-shadow: 0 0 0 1px rgba(14, 41, 57, 0.12), 0 2px 5px rgba(14, 41, 57, 0.44), inset 0 -1px 2px rgba(14, 41, 57, 0.15); | ||||
|  |   background: #fefefe; | ||||
|  |   margin: 0 auto; | ||||
|  |   border-radius: 0.1px; | ||||
|  |   width: 270px; | ||||
|  |   height: 130px; | ||||
|  |   font-size: 14px; | ||||
|  |   display: none; } | ||||
|  |   .wickedpicker__title { | ||||
|  |     background-image: -webkit-linear-gradient(top, #ffffff 0%, #f2f2f2 100%); | ||||
|  |     background-image: linear-gradient(to bottom, #ffffff 0%, #f2f2f2 100%); | ||||
|  |     position: relative; | ||||
|  |     background: #f2f2f2; | ||||
|  |     margin: 0 auto; | ||||
|  |     border-bottom: 1px solid #e5e5e5; | ||||
|  |     padding: 12px 11px 10px 15px; | ||||
|  |     color: #4C4C4C; | ||||
|  |     font-size: inherit; } | ||||
|  |   .wickedpicker__close { | ||||
|  |     -webkit-transform: translateY(-25%); | ||||
|  |     -moz-transform: translateY(-25%); | ||||
|  |     -ms-transform: translateY(-25%); | ||||
|  |     -o-transform: translateY(-25%); | ||||
|  |     transform: translateY(-25%); | ||||
|  |     position: absolute; | ||||
|  |     top: 25%; | ||||
|  |     right: 10px; | ||||
|  |     color: #34495e; | ||||
|  |     cursor: pointer; } | ||||
|  |     .wickedpicker__close:before { | ||||
|  |       content: '\00d7'; } | ||||
|  |   .wickedpicker__controls { | ||||
|  |     padding: 10px 0; | ||||
|  |     line-height: normal; | ||||
|  |     margin: 0; } | ||||
|  |     .wickedpicker__controls__control, .wickedpicker__controls__control--separator { | ||||
|  |       vertical-align: middle; | ||||
|  |       display: inline-block; | ||||
|  |       font-size: inherit; | ||||
|  |       margin: 0 auto; | ||||
|  |       width: 35px; | ||||
|  |       letter-spacing: 1.3px; } | ||||
|  |       .wickedpicker__controls__control-up, .wickedpicker__controls__control-down { | ||||
|  |         color: #34495e; | ||||
|  |         position: relative; | ||||
|  |         display: block; | ||||
|  |         margin: 3px auto; | ||||
|  |         font-size: 18px; | ||||
|  |         cursor: pointer; } | ||||
|  |       .wickedpicker__controls__control-up:before { | ||||
|  |         content: '\e800'; } | ||||
|  |       .wickedpicker__controls__control-down:after { | ||||
|  |         content: '\e801'; } | ||||
|  |       .wickedpicker__controls__control--separator { | ||||
|  |         width: 5px; } | ||||
|  | 
 | ||||
|  | .text-center, .wickedpicker__title, .wickedpicker__controls, .wickedpicker__controls__control, .wickedpicker__controls__control--separator, .wickedpicker__controls__control-up, .wickedpicker__controls__control-down { | ||||
|  |   text-align: center; } | ||||
|  | 
 | ||||
|  | .hover-state { | ||||
|  |   color: #3498db; } | ||||
|  | 
 | ||||
|  | @font-face { | ||||
|  |   font-family: 'fontello'; | ||||
|  |   src: url("../fonts/fontello.eot?52602240"); | ||||
|  |   src: url("../fonts/fontello.eot?52602240#iefix") format("embedded-opentype"), url("../fonts/fontello.woff?52602240") format("woff"), url("../fonts/fontello.ttf?52602240") format("truetype"), url("../fonts/fontello.svg?52602240#fontello") format("svg"); | ||||
|  |   font-weight: normal; | ||||
|  |   font-style: normal; } | ||||
|  | 
 | ||||
|  | .fontello:before, .wickedpicker__controls__control-up:before, .fontello-after:after, .wickedpicker__controls__control-down:after { | ||||
|  |   font-family: 'fontello'; | ||||
|  |   font-style: normal; | ||||
|  |   font-weight: normal; | ||||
|  |   speak: none; | ||||
|  |   display: inline-block; | ||||
|  |   text-decoration: inherit; | ||||
|  |   width: 1em; | ||||
|  |   margin-right: .2em; | ||||
|  |   text-align: center; | ||||
|  |   font-variant: normal; | ||||
|  |   text-transform: none; | ||||
|  |   line-height: 1em; | ||||
|  |   margin-left: .2em; | ||||
|  |   -webkit-font-smoothing: antialiased; | ||||
|  |   -moz-osx-font-smoothing: grayscale; } | ||||
| @ -0,0 +1,17 @@ | |||||
|  | <?xml version="1.0" encoding="utf-8" ?> | ||||
|  | <odoo> | ||||
|  |     <!--    This XML code is part of an Odoo module's manifest file and is used to enhance the web interface--> | ||||
|  |     <!--    of the Odoo application by adding custom assets for a time picker widget.--> | ||||
|  |     <template id="asset_backend" inherit_id="web.assets_backend"> | ||||
|  |         <xpath expr="." position="inside"> | ||||
|  |             <link href='/field_timepicker/static/wickedpicker/dist/wickedpicker.min.css' | ||||
|  |                   rel='stylesheet'/> | ||||
|  |             <script type="text/javascript" | ||||
|  |                     src='/field_timepicker/static/wickedpicker/dist/wickedpicker.min.js'/> | ||||
|  |             <script type="text/javascript" | ||||
|  |                     src='/field_timepicker/static/wickedpicker/src/wickedpicker.js'/> | ||||
|  |             <script type="text/javascript" | ||||
|  |                     src='/field_timepicker/static/src/js/time_widget.js'/> | ||||
|  |         </xpath> | ||||
|  |     </template> | ||||
|  | </odoo> | ||||