diff --git a/.DS_Store b/.DS_Store index a154cb0..a646d0a 100755 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/.gitignore b/.gitignore index 0cece3a..46422b1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,13 @@ +.DS_Store + +scripts/ + +# The local config file should be specific to the machine running the app. +local_config.py *.pyc -# The settings.cfg file should be specific to the machine running the app. -settings.cfg + +app.wsgi +runserver.py + +*.log +application.log diff --git a/departmentArray.py b/departmentArray.py index 9eb3d95..2bc2f4f 100644 --- a/departmentArray.py +++ b/departmentArray.py @@ -17,7 +17,8 @@ def combineShortAndLong(depts_list): for dept in depts_list: short_name = dept[0] long_name = dept[1] - combined_list.append(short_name + "-" + long_name) + combined_list.append(short_name.lower() + "-" + long_name.lower()) + print combined_list return combined_list ## diff --git a/runserver.py b/runserver.py index ca42c79..113c369 100644 --- a/runserver.py +++ b/runserver.py @@ -11,4 +11,4 @@ from study_buddy import app print "Starting server..." -app.run(debug=True) \ No newline at end of file +app.run(debug=True) diff --git a/study_buddy/__init__.py b/study_buddy/__init__.py old mode 100644 new mode 100755 index f918ffd..b4ca97b --- a/study_buddy/__init__.py +++ b/study_buddy/__init__.py @@ -1,72 +1,60 @@ -from flask import Flask -from flask.ext.sqlalchemy import SQLAlchemy -from flask.ext.security import Security, SQLAlchemyUserDatastore -from flask.ext.social import Social, SQLAlchemyConnectionDatastore, \ - login_failed -from mongokit import * -from models import * +from flask import Flask, render_template, request, session, abort -app = Flask(__name__) +# from flask.ext.wtf.csrf import CsrfProtect +from flask.ext.assets import Environment, Bundle +from flask.ext.mail import Mail, Message -# TODO: move all configs into external file. -app.config['SOCIAL_FACEBOOK'] = { - 'consumer_key': '804807199563793', - 'consumer_secret': 'e7d68bbbd3b828743dc3d6fff7cc9406' -} +from itsdangerous import URLSafeTimedSerializer +from inflection import titleize -app.config['SOCIAL_GOOGLE'] = { - 'consumer_key': '967982158206-146hbl8954b0oa45e71ii9efuuaj4fj0.apps.googleusercontent.com', - 'consumer_secret': 'JFYgnNsq8FR6qfjSC-uDHFEl' -} +import os, binascii, logging, sys -app.config['SECURITY_POST_LOGIN'] = '/profile' +logging.basicConfig(level=logging.DEBUG, + streamHandler=sys.stderr, + format='[%(levelname)s] <%(asctime)s> %(message)s') -## -# STAGE FOR DELETE -################################################# -app.config.update( - SECRET_KEY='Tieng3us3Xie5meiyae6iKKHVUIUDF', - GOOGLE_LOGIN_CLIENT_ID='1002179078501-mdq5hvm940d0hbuhqltr0o1qhsr7sduc.apps.googleusercontent.com', - GOOGLE_LOGIN_CLIENT_SECRET='O1kpQ8Is9s2pD3eOpxRfh-7x', - GOOGLE_LOGIN_REDIRECT_URI='http://127.0.0.1:5000/oauth2callback', -) -################################################# +app = Flask(__name__) -db = SQLAlchemy(app) +app.config.from_object('study_buddy.base_config') +app.config.from_object('study_buddy.local_config') -connection = Connection() -connection.register([StudySession]) -mongo_db = connection.succor +APP_ROOT = os.path.dirname(os.path.abspath(__file__)) -print "Running app..." +def output_time(result): + format = "%a, %-d at %-I:%M %p" + return result.strftime(format) -from . import views, models +def generate_csrf_token(): + if '_csrf_token' not in session: + session['_csrf_token'] = binascii.hexlify(os.urandom(24)) + return session['_csrf_token'] -# security_ds = SQLAlchemyUserDatastore(db, models.User, models.Role) -# social_ds = SQLAlchemyConnectionDatastore(db, models.Connection) +# assets = Environment(app) +# scss = Bundle('', filters='pyscss', output='all.css') +# assets.register('scss_all', scss) -# app.security = Security(app, security_ds) -# app.social = Social(app, social_ds) +# csrf = CsrfProtect() +# csrf.init_app(app) -# class SocialLoginError(Exception): -# def __init__(self, provider): -# self.provider = provider +ts = URLSafeTimedSerializer(app.config["SECRET_KEY"]) + +mail = Mail(app) + +print "Running app..." +app.jinja_env.globals.update(output_time=output_time) +app.jinja_env.globals.update(titleize=titleize) +app.jinja_env.globals['csrf_token'] = generate_csrf_token -# @app.before_first_request -# def before_first_request(): -# try: -# models.db.create_all() -# except Exception, e: -# app.logger.error(str(e)) +from study_buddy import views, models -# @login_failed.connect_via(app) -# def on_login_failed(sender, provider, oauth_response): -# app.logger.debug('Social Login Failed via %s; ' -# '&oauth_response=%s' % (provider.name, oauth_response)) +@app.errorhandler(404) +def page_not_found(e): + return render_template('404.html'), 404 -# # Save the oauth response in the session so we can make the connection -# # later after the user possibly registers -# session['failed_login_connection'] = \ -# get_connection_values_from_oauth_response(provider, oauth_response) +@app.before_request +def csrf_protect(): + if request.method == "POST": + token = session.pop('_csrf_token', None) + if not token or token != request.form.get('_csrf_token'): + abort(403) -# raise SocialLoginError(provider) \ No newline at end of file diff --git a/study_buddy/backup/department_names.json b/study_buddy/backup/department_names.json new file mode 100644 index 0000000..009f721 --- /dev/null +++ b/study_buddy/backup/department_names.json @@ -0,0 +1 @@ +{department_name:"Computer Science",school:"Wesleyan University",names:"[comp, compsci, computer]"} diff --git a/study_buddy/backup/slangscommand b/study_buddy/backup/slangscommand new file mode 100644 index 0000000..c529f66 --- /dev/null +++ b/study_buddy/backup/slangscommand @@ -0,0 +1,4 @@ +#mongoimport --db succor --collection slangs --type json --file backup/department_names.json --jsonArray +#Copy paste this command after running mongod on the terminal and adding to the +# file department_names located in backup folder. MAKE SURE TO COPY THE FORMAT or else +# it won't import diff --git a/study_buddy/base_config.py b/study_buddy/base_config.py new file mode 100644 index 0000000..03da528 --- /dev/null +++ b/study_buddy/base_config.py @@ -0,0 +1,10 @@ +SECURITY_POST_LOGIN = '/profile' + +MAIL_SERVER = 'smtp.gmail.com' +MAIL_PORT = 587 +MAIL_USE_TLS = True +MAIL_USE_SSL = False +ADMINS = ['succorapp@gmail.com'] + +DB_HOST = 'localhost' +DB_PORT = 27017 \ No newline at end of file diff --git a/study_buddy/forms.py b/study_buddy/forms.py index c0f40f4..0c82996 100644 --- a/study_buddy/forms.py +++ b/study_buddy/forms.py @@ -1,35 +1,101 @@ -from flask import current_app from flask.ext.wtf import Form -from wtforms import TextField, PasswordField, ValidationError -from wtforms.validators import Required, Email, Length, Regexp, EqualTo - -class UniqueUser(object): - def __init__(self, message="User exists"): - self.message = message - - def __call__(self, form, field): - if current_app.security.datastore.find_user(email=field.data): - raise ValidationError(self.message) - - -validators = { - 'email': [ - Required(), - Email(), - UniqueUser(message='Email address is associated with ' - 'an existing account') - ], - 'password': [ - Required(), - Length(min=6, max=50), - EqualTo('confirm', message='Passwords must match'), - Regexp(r'[A-Za-z0-9@#$%^&+=]', - message='Password contains invalid characters') - ] -} - - -class RegisterForm(Form): - email = TextField('Email', validators['email']) - password = PasswordField('Password', validators['password'], ) +from wtforms import TextField, PasswordField, ValidationError, BooleanField, IntegerField, DateTimeField, HiddenField, validators +from init_db import mongo_db +from werkzeug.security import check_password_hash +import re + +class EmailForm(Form): + email = TextField('Email', validators = [validators.Email(), validators.Required()]) + + def validate_email(self, field): + if self.get_user() is None: + raise validators.ValidationError('There is no account with this email') + + def get_user(self): + return mongo_db.users.User.find_one({'email' : self.email.data}) + + +class PasswordForm(Form): + password = PasswordField('New Password', validators = [validators.Required()]) + +class GroupForm(Form): + email = TextField('Contact') + department = TextField('Department', [ + validators.Required() + ]) + course_no = IntegerField('Course Number', [ + validators.Required(), + ]) + datetime = DateTimeField('Date and time', format="%Y/%m/%d %H:%M") + where = TextField('Where', [ + validators.Required() + ]) + assignment = TextField('Assignment', [ + validators.Required() + ]) + + school = TextField('School') + details = TextField('Details') + geo_location = HiddenField() + #all_nighter=BooleanField('All nighter') + + def validate_course_no(self, field): + if not self.course_no.data < 1000 or len(str(self.course_no.data)) != 3: + raise validators.ValidationError('Please enter a 3 digit course number') + + def validate_email(self, field): + if self.email.data and '.edu' not in self.email.data: + raise validators.ValidationError('Please use a .edu email') + +class EditUserForm(Form): + first_name = TextField('First Name', [ + #validators.Regexp(r'^[A-Za-z0-9.]+$', message= u'That\'s not a valid first name'), + validators.Required() + ]) + last_name = TextField('Last Name', [ + validators.Required() + ]) + course = TextField('Class') + + +class LoginForm(Form): + email = TextField('Email', [ + validators.Required() + ]) + + password = PasswordField('Password') + + remember = BooleanField('Remember me') + + def validate_password(self, field): + user = self.get_user() + + if user is None: + raise validators.ValidationError('Email does not exist') + + if not check_password_hash(user.password, self.password.data): + raise validators.ValidationError('Invalid password') + + def get_user(self): + return mongo_db.users.User.find_one({'email' : self.email.data}) + + +class RegistrationForm(Form): + email = TextField('Email', [ + validators.Required(), + validators.length(min=6, max=50), + validators.Email() + ]) + + def validate_email(self, field): + if '.edu' not in self.email.data: + raise validators.ValidationError('Please use a .edu email') + + if mongo_db.users.User.find({'email' : self.email.data}).count() > 0: + raise validators.ValidationError('Account with that email already exists') + + password = PasswordField('Password', [ + validators.Required(), + validators.EqualTo('confirm', message='Passwords must match') + ]) confirm = PasswordField('Confirm Password') \ No newline at end of file diff --git a/study_buddy/helpers.py b/study_buddy/helpers.py new file mode 100644 index 0000000..34f897a --- /dev/null +++ b/study_buddy/helpers.py @@ -0,0 +1,141 @@ +from study_buddy import app, ts +from flask import url_for, render_template +from pymongo import MongoClient +from json import dumps + +import boto.ses +import re + +## +# Given a wtf form object, return a json representation of the data +# in that form. +# +# @param form WTF form object +# +# @return Returns a JSON representation of the data in form +## +def json_from_form(form): + form_dict = {} + for field_name, value, in form.data.items(): + form_dict[field_name] = value + return form_dict + +## +# Given a search term for a department, determines what the user +# meant to search for. +# +# @param search_term The user-input search term. +# @param school The school in which we are searching for a department. +# +# @return Returns the term most closely matching the term the user input. +## +def smart_search(search_term, school): + client = MongoClient() + conn = client.succor.smart_search + search_term_processed = search_term.replace(" ", "").lower() + if school: + school = school.lower() + result = conn.find_one( + {'school' : school, + 'alternative_names' : {'$in' : [search_term_processed]}} + ) + else: + result = conn.find_one( + {'alternative_names' : {'$in' : [search_term_processed]}} + ) + if result: + return result['department_name'] + else: + return search_term + +## +# Finds the school name based on the email domain name given. +# +# @param email_ending The email domain name of the users email address. +# +# @return Returns the school name based on the email address given. +## +def school_name_from_email(email_ending): + client = MongoClient() + conn = client.succor.schools + result = conn.find_one({'email' : email_ending}) + if result: + return result['school'] + else: + return email_ending + +## +# Sends an email to a user who has just registered, with +# with instructions on how to verify account. +# +# @param email Email address to send verification link to. +## +def send_verification_email(user): + token = ts.dumps(user.email, salt='email-confirm-key') + confirm_url = url_for('verify', token=token, _external=True) + send_email( + "Vefiry your account with Succor", + app.config['FROM_EMAIL_ADDRESS'], + [user.email], + render_template("email/verify.txt", url=confirm_url, user=user), + render_template("email/verify.html", url=confirm_url, user=user) + ) + +def send_email(subject, sender, recipients, text_body, html_body): + conn = boto.ses.connect_to_region( + 'us-west-2', + aws_access_key_id=app.config['AWS_ACCESS_KEY_ID'], + aws_secret_access_key=app.config['AWS_SECRET_KEY_ACCESS'] + ) + + conn.send_email( + sender, + subject, + None, + recipients, + text_body=text_body, + html_body=html_body + ) + +## +# @returns returns True if c is a number +## +def is_number(c): + try: + float(c) + return True + except ValueError: + return False + +## +# Given a string, query, this function parses it to find a +# department and a course number and returns a tuple of the two. +# @returns return (department : string, course_number : string) +## +def parse_new_find(query): + is_digit = False + department_end = -1 + number_end = -1 + for i in range(1, len(query)+1): + c = query[len(query) - i] + if is_number(c) and is_digit: + continue + if is_number(c): + is_digit = True + number_end = (len(query) + 1) - i + if not is_number(c): + is_digit = False + department_end = (len(query) + 1) - i + break + + if department_end >= 0 and number_end >= 0: + course_number = query[department_end : number_end] + department_name = query[0 : department_end] + elif department_end >= 0: + department_name = query[0 : department_end] + course_number = '' + else: + department_name = '' + course_number = '' + + return (department_name.strip(), course_number.strip()) diff --git a/study_buddy/init_db.py b/study_buddy/init_db.py new file mode 100644 index 0000000..4d5e74d --- /dev/null +++ b/study_buddy/init_db.py @@ -0,0 +1,29 @@ +from study_buddy import app + +from models import StudySession, User + +from pymongo import GEOSPHERE +from mongokit import Connection, ObjectId + +from flask import redirect, url_for +from flask.ext.login import LoginManager + +connection = Connection(host=app.config['DB_HOST'], port=app.config['DB_PORT']) +connection.register([StudySession, User]) +mongo_db = connection[app.config['DB_NAME']] +# mongo_db.study_sessions.ensure_index([('geo_location', GEOSPHERE)]) + +login_manager = LoginManager() +login_manager.init_app(app) +login_manager.login_view = 'login' + +@login_manager.user_loader +def load_user(user_id): + return mongo_db.users.User.find_one({'_id' : ObjectId(user_id)}) + +# @login_manager.unauthorized_handler +# def unauthorized(): +# flash("Please log in to access this page") +# session['next'] = request. +# return redirect(url_for('login')) + diff --git a/study_buddy/models.py b/study_buddy/models.py index cb3d8e6..c3ab73f 100644 --- a/study_buddy/models.py +++ b/study_buddy/models.py @@ -1,23 +1,61 @@ -from flask.ext.security import UserMixin, RoleMixin +from study_buddy import app -from mongokit import Document +from flask.ext.login import UserMixin + +from mongokit import Document, Connection import datetime +class User(Document, UserMixin): + __database__ = app.config['DB_NAME'] + __collection__ = 'users' + + structure = { + 'date_creation' : datetime.datetime, + 'email' : basestring, + 'password' : basestring, + 'school' : basestring, + 'verified' : bool, + 'name' : { + 'first' : basestring, + 'last' : basestring, + 'full' : basestring + }, + 'classes' : [basestring], + 'groups_joined' : [basestring] + } + + default_values = { + 'date_creation' : datetime.datetime.utcnow + } + + required_fields = ['email', 'password'] + + use_dot_notation = True + + def get_id(self): + return str(self._id) + class StudySession(Document): - __database__ = 'succor' + __database__ = app.config['DB_NAME'] __collection__ = 'study_sessions' structure = { 'date_creation': datetime.datetime, 'department': basestring, 'course_no': basestring, - 'time': basestring, + 'time': datetime.datetime, 'location': basestring, 'description': basestring, 'contact_info': basestring, - 'details': basestring - } + 'details': basestring, + 'name': basestring, + 'geo_location' : dict, + 'school' : basestring, + 'participants' : [basestring] + # _id : ObjectId - mongo gives this to you automatically + } + required_fields = ['department', 'course_no', 'time', 'location'] @@ -27,48 +65,14 @@ class StudySession(Document): use_dot_notation = True -# roles_users = db.Table('roles_users', -# db.Column('user_id', db.Integer(), db.ForeignKey('users.id')), -# db.Column('role_id', db.Integer(), db.ForeignKey('roles.id'))) - -# class Role(db.Model, RoleMixin): - -# __tablename__ = "roles" - -# id = db.Column(db.Integer(), primary_key=True) -# name = db.Column(db.String(80), unique=True) -# description = db.Column(db.String(255)) - -# class User(db.Model, UserMixin): - -# __tablename__ = "users" - -# id = db.Column(db.Integer, primary_key=True) -# email = db.Column(db.String(255), unique=True) -# password = db.Column(db.String(120)) -# active = db.Column(db.Boolean()) -# last_login_at = db.Column(db.DateTime()) -# current_login_at = db.Column(db.DateTime()) -# last_login_ip = db.Column(db.String(100)) -# current_login_ip = db.Column(db.String(100)) -# login_count = db.Column(db.Integer) -# roles = db.relationship('Role', secondary=roles_users, -# backref=db.backref('users', lazy='dynamic')) -# connections = db.relationship('Connection', -# backref=db.backref('user', lazy='joined'), cascade="all") - -# class Connection(db.Model): - -# __tablename__ = "connections" - -# id = db.Column(db.Integer, primary_key=True) -# user_id = db.Column(db.Integer, db.ForeignKey('users.id')) -# provider_id = db.Column(db.String(255)) -# provider_user_id = db.Column(db.String(255)) -# access_token = db.Column(db.String(255)) -# secret = db.Column(db.String(255)) -# display_name = db.Column(db.String(255)) -# full_name = db.Column(db.String(255)) -# profile_url = db.Column(db.String(512)) -# image_url = db.Column(db.String(512)) -# rank = db.Column(db.Integer) \ No newline at end of file +class Slangs(Document): + __database__ = 'succor' + __collection__ = 'smart_search' + + structure = { + 'school' : basestring, + 'department_name': basestring, + 'alternative_names' : [basestring] + } + + use_dot_notation = True diff --git a/study_buddy/people_bios.json b/study_buddy/people_bios.json new file mode 100644 index 0000000..bc971a8 --- /dev/null +++ b/study_buddy/people_bios.json @@ -0,0 +1,26 @@ +{ + "Katya Sapozhnina" : {"picture" : "katya.png", + "name" : "Katya Sapozhnina", + "position" : "CEO", + "bio" : "Katya is the Founder and President of the Wesleyan Entrepreneurship Society. She founded the society her freshman year to spearhead entrepreneurship culture at Wesleyan and since it has grown to a popular and active society at Wesleyan. Katya will co-lead a for-credit class on Entrepreneurship this Spring for the second year in a row. She is also a Peer Advisor for the Patricelli Center of Social Entrepreneurship. She advises many startups on campus. She came up with the idea for Succor her freshman year and is excited that it is now a tool Wesleyan student use. She wishes Succor existed her freshman year when she was studying for her Biology tests. She currently uses Succor to study with friends for Statistics."}, + + "Aaron Rosen" : {"picture" : "aaron.png", + "name" : "Aaron Rosen", + "position" : "CTO", + "bio" : "Aaron is a former Google engineering intern and has been the lead engineer on several startups at Wesleyan to date. Some of his favorite projects have been involved with environmentalism at Wesleyan. Aaron loves to hike, travel, and cook and dreams of one day learning how to fly planes. He has been using Succor to advertise all of his study sessions for finals!"}, + + "Hora" : {"picture" : "hora.png", + "name" : "Hora", + "position" : "VP of Engineering", + "bio" : "Hora is currently a part of the Varsity Crew team at Wesleyan. In addition to Succor, he is involved with research in Physics and is a course assistant for the Physics department. In the future, he wants to explore the field of machine learning. Hora likes to play the drums, travel and do physical activity."}, + + "Denise Fransisco" : {"picture" : "denise.png", + "name" : "Denise Fransisco", + "position" : "VP of Engineering", + "bio" : "Denise is a Junior at Wesleyan University majoring in Computer Science. She is currently involved with two dance groups on campus and is a Programmer for Instructional Media Services. She is currently interested in Web Development. She helped create the front end of Succor in September 2014 during the Wesleyan Hackathon. She hopes that Succor will be widely used on campus and will continue making studying more convenient for everyone."}, + + "Aditya Gupta" : {"picture" : "adii.png", + "name" : "Aditya Gupta", + "position" : "Engineer", + "bio" : "Aditya is a Computer Science major. He hopes to improve his programming skills while helping people through ventures such as Succor. He is a big Liverpool F.C. fan and likes to play chess. He hopes to become an internationally rated chess player soon. He has been using Succor to create study groups as he does not want to leave the comfort of his room but also wants to study with other people."} +} \ No newline at end of file diff --git a/study_buddy/people_bios.txt b/study_buddy/people_bios.txt new file mode 100644 index 0000000..c21eaa7 --- /dev/null +++ b/study_buddy/people_bios.txt @@ -0,0 +1,21 @@ +{"people" : [ + {"name" : "Yekaterina Sapozhnina", + "position" : "CEO", + "bio" : "Katya is the Founder and President of the Wesleyan Entrepreneurship Society. She founded the society her freshman year to spearhead entrepreneurship culture at Wesleyan and since it has grown to a popular and active society at Wesleyan. Katya will co-lead a for-credit class on Entrepreneurship this Spring for the second year in a row. She is also a Peer Advisor for the Patricelli Center of Social Entrepreneurship. She advises many startups on campus. She came up with the idea for Succor her freshman year and is excited that it is now a tool Wesleyan student use. She wishes Succor existed her freshman year when she was studying for her Biology tests. She currently uses Succor to study with friends for Statistics."}, + + {"name" : "Aaron Rosen", + "position" : "CTO", + "bio" : "Aaron is a former Google engineering intern and has been the lead engineer on several startups at Wesleyan to date. Some of his favorite projects have been involved with environmentalism at Wesleyan. Aaron loves to hike, travel, and cook and dreams of one day learning how to fly planes. He has been using Succor to advertise all of his study sessions for finals!"}, + + {"name" : "Hora", + "position" : "VP of Engineering", + "bio" : "He is currently a part of the Varsity Crew team at Wesleyan. In addition to Succor, he is involved with research in Physics and is a course assistant for the Physics department. In the future, he wants to explore the field of machine learning. Hora likes to play the drums, travel and do physical activity."}, + + {"name" : "Denise Francisco", + "position" : "VP of Engineering", + "bio" : "Denise is a Junior at Wesleyan University majoring in Computer Science. She is currently involved with two dance groups on campus and is a Programmer for Instructional Media Services. She is currently interested in Web Development. She helped create the front end of Succor in September 2014 during the Wesleyan Hackathon. She hopes that Succor will be widely used on campus and will continue making studying more convenient for everyone."}, + + {"name" : "Aditya Gupta", + "position" : "Engineer", + "bio" : "Aditya is a Computer Science major. He hopes to improve his programming skills while helping people through ventures such as Succor. He is a big Liverpool F.C. fan and likes to play chess. He hopes to become an internationally rated chess player soon. He has been using Succor to create study groups as he does not want to leave the comfort of his room but also wants to study with other people."} +]} \ No newline at end of file diff --git a/study_buddy/static/.DS_Store b/study_buddy/static/.DS_Store new file mode 100644 index 0000000..b6bfae5 Binary files /dev/null and b/study_buddy/static/.DS_Store differ diff --git a/study_buddy/static/old_styles.css b/study_buddy/static/old_styles.css new file mode 100755 index 0000000..3bc1135 --- /dev/null +++ b/study_buddy/static/old_styles.css @@ -0,0 +1,283 @@ +/* +* +* Grey: #C7D0D5; +* Blue: #93B1C6; +* White: #F5F5F5; +* Orange: #FF7148; +* Red: #EC583A; +*/ + +@font-face { + font-family: josefinslab; + src: url(josefinslab-bold-webfont.woff); +} + +html { + font-family: josefinslab; +} +html, body { + height: 100%; +} +body { + width: 100%; + background: url(resources/images/wesleyan.jpg) !important; + background-color: #E0E0D1; + background-size: cover !important; + background-repeat: no-repeat; + background-attachment: fixed; +} + +.center-elmt { + margin-left: auto; + margin-right: auto; +} + +.center-txt { + text-align: center; +} + +.search-row-odd { + padding-bottom: 5px; + padding-top: 5px; + margin-bottom: 2px; + background-color: rgba(51, 51, 51, 0.7); + color: white; +} + +.search-row-even { + padding-bottom: 2px; + padding-top: 5px; + margin-bottom: 2px; + background-color: rgba(0, 51, 102, 0.7); + color: white; +} + +#search-results-container { + color: white; +} + +#no-search-results { + margin: 15px 0; +} + +#ui-datepicker-div { + width: 20%; + text-decoration: none; + list-style-type: none; + margin-left: auto; + margin-right: auto; +} + +/*class for centering*/ +.center { + width: 100%; + text-align: center; + margin-top: 100px; +} +.custom-title { + font-size: 500%; + text-align: center; + margin-top: 100px; + font-weight: bold; + color: beige; + min-width: 500px; + text-shadow: 3px 3px #000000; +} +.create-forms { + margin-top: 120px; +} +.ui-helper-hidden-accessible { + visibility: hidden; +} +.ui-menu-item:hover{ + background-color: #99D6FF; +} +.ui-menu-item { + padding-left: 10px; +} +.ui-widget-content { + width: 73%; + border: 1px solid black; + color: #222222; + background-color: white; + text-decoration: none; + list-style-type: none; + margin-left: auto; + margin-right: auto; + font-size: 12px; +} + +nav.top-bar { + opacity: 0.8; +} + +.top-bar-section ul li > h1 { + width: 100%; + color: white; + font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; + font-size: 0.8125rem; + font-weight: normal; + text-transform: none; + padding-top: 11px; +} + +#text-background { + /*background-color: rgba(51,51,51,0.5);*/ + margin-left: 30%; + margin-right: 30%; + padding: 5px; + line-height: initial; + border-radius: 25px; + text-shadow: 3px 3px #000000; + font-family:josefinslab; +} +.columns input { + width: 100% !important; +} +#intro { + font-size: 200%; + text-align: center; + margin-top: 65px; + margin-bottom: 50px; + color: beige; + /*background-color: rgba(51,51,51,0.5);*/ + line-height: initial; + margin-left: 22%; + margin-right: 22%; + padding: 10px; + border-radius: 10px; + text-shadow: 2px 2px #000000; + font-family:josefinslab; +} + +#text-input { + margin-bottom: 15px; + text-align: center; + + padding-left: 8px; + padding-right: 8px; +} + +#text-input input { + padding-top: 8px; + padding-bottom: 8px; + padding-left: 8px; + padding-right: 8px; + font-size: 25px; + margin-left: auto; + margin-right: auto; +} + +#searchresults { + width: 80%; + margin-left: 10%; +} +#searchbar { + width: 20%; + float: right; + margin-right: 20%; +} +#front-page-buttons { + margin-left: auto; + margin-right: auto; + text-align: center; +} +.container { + display: none; +} +.click { + cursor: pointer; +} + +#login-button a { + color: white; +} +#login-button { + margin-left: auto; + margin-right: auto; + text-align: center; +} +#button-wrapper { + width: 100%; + text-align: center; + margin-top: 100px; +} +#about-panel { + width: 75%; + margin-right: auto; + margin-left: auto; + margin-top: 65px; + background-color: rgba(255, 255, 255, 0.5); + font-size: 32px; +} +#about-panel p { + font-size: 20px; + margin-top: 7px; +} + + +#course { + width: 35.5%; +} + + +#page-header{ + width:90%; + margin-top: 8%; + margin-left: 10%; + margin-bottom: none; + display: inline-block; +} +#create-group { + width: 60%; + margin-left: auto; + margin-right: auto; +} +#search-input { + width: 50%; + margin-left: 10%; + display: inline-block; +} +.students-table { + width: 30%; + display: inline-block; +} +.notes { + display: inline-block; + width: 60%; + float: right; + height: 100%; + overflow: auto; +} +/*footer stuff*/ + +.footer { + margin-left: auto; + margin-right: auto; + text-shadow: 0.7px 0.7px #000000; + position: fixed; + bottom: 0; +} +#bot { + font-size: 16px; + text-align: center; + color: beige; + margin-bottom: 0; + +} + +.wrapper { + min-height: 95%; + height: auto !important; + height: 95%; + margin: ;0 + 0 auto -2em; +} +.footer, .push { + height: 2em; +} +#errors{ + margin-top: 5%; + +} + diff --git a/study_buddy/static/resources/.DS_Store b/study_buddy/static/resources/.DS_Store new file mode 100644 index 0000000..cd3a2cf Binary files /dev/null and b/study_buddy/static/resources/.DS_Store differ diff --git a/study_buddy/static/resources/fonts/Bitstream-Vera-Sans/Bitstream Vera License.txt b/study_buddy/static/resources/fonts/Bitstream-Vera-Sans/Bitstream Vera License.txt new file mode 100755 index 0000000..cf00835 --- /dev/null +++ b/study_buddy/static/resources/fonts/Bitstream-Vera-Sans/Bitstream Vera License.txt @@ -0,0 +1,123 @@ +Bitstream Vera Fonts Copyright + +The fonts have a generous copyright, allowing derivative works (as +long as "Bitstream" or "Vera" are not in the names), and full +redistribution (so long as they are not *sold* by themselves). They +can be be bundled, redistributed and sold with any software. + +The fonts are distributed under the following copyright: + +Copyright +========= + +Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream +Vera is a trademark of Bitstream, Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of the fonts accompanying this license ("Fonts") and associated +documentation files (the "Font Software"), to reproduce and distribute +the Font Software, including without limitation the rights to use, +copy, merge, publish, distribute, and/or sell copies of the Font +Software, and to permit persons to whom the Font Software is furnished +to do so, subject to the following conditions: + +The above copyright and trademark notices and this permission notice +shall be included in all copies of one or more of the Font Software +typefaces. + +The Font Software may be modified, altered, or added to, and in +particular the designs of glyphs or characters in the Fonts may be +modified and additional glyphs or characters may be added to the +Fonts, only if the fonts are renamed to names not containing either +the words "Bitstream" or the word "Vera". + +This License becomes null and void to the extent applicable to Fonts +or Font Software that has been modified and is distributed under the +"Bitstream Vera" names. + +The Font Software may be sold as part of a larger software package but +no copy of one or more of the Font Software typefaces may be sold by +itself. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL +BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, +OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT +SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. + +Except as contained in this notice, the names of Gnome, the Gnome +Foundation, and Bitstream Inc., shall not be used in advertising or +otherwise to promote the sale, use or other dealings in this Font +Software without prior written authorization from the Gnome Foundation +or Bitstream Inc., respectively. For further information, contact: +fonts at gnome dot org. + +Copyright FAQ +============= + + 1. I don't understand the resale restriction... What gives? + + Bitstream is giving away these fonts, but wishes to ensure its + competitors can't just drop the fonts as is into a font sale system + and sell them as is. It seems fair that if Bitstream can't make money + from the Bitstream Vera fonts, their competitors should not be able to + do so either. You can sell the fonts as part of any software package, + however. + + 2. I want to package these fonts separately for distribution and + sale as part of a larger software package or system. Can I do so? + + Yes. A RPM or Debian package is a "larger software package" to begin + with, and you aren't selling them independently by themselves. + See 1. above. + + 3. Are derivative works allowed? + Yes! + + 4. Can I change or add to the font(s)? + Yes, but you must change the name(s) of the font(s). + + 5. Under what terms are derivative works allowed? + + You must change the name(s) of the fonts. This is to ensure the + quality of the fonts, both to protect Bitstream and Gnome. We want to + ensure that if an application has opened a font specifically of these + names, it gets what it expects (though of course, using fontconfig, + substitutions could still could have occurred during font + opening). You must include the Bitstream copyright. Additional + copyrights can be added, as per copyright law. Happy Font Hacking! + + 6. If I have improvements for Bitstream Vera, is it possible they might get + adopted in future versions? + + Yes. The contract between the Gnome Foundation and Bitstream has + provisions for working with Bitstream to ensure quality additions to + the Bitstream Vera font family. Please contact us if you have such + additions. Note, that in general, we will want such additions for the + entire family, not just a single font, and that you'll have to keep + both Gnome and Jim Lyles, Vera's designer, happy! To make sense to add + glyphs to the font, they must be stylistically in keeping with Vera's + design. Vera cannot become a "ransom note" font. Jim Lyles will be + providing a document describing the design elements used in Vera, as a + guide and aid for people interested in contributing to Vera. + + 7. I want to sell a software package that uses these fonts: Can I do so? + + Sure. Bundle the fonts with your software and sell your software + with the fonts. That is the intent of the copyright. + + 8. If applications have built the names "Bitstream Vera" into them, + can I override this somehow to use fonts of my choosing? + + This depends on exact details of the software. Most open source + systems and software (e.g., Gnome, KDE, etc.) are now converting to + use fontconfig (see www.fontconfig.org) to handle font configuration, + selection and substitution; it has provisions for overriding font + names and subsituting alternatives. An example is provided by the + supplied local.conf file, which chooses the family Bitstream Vera for + "sans", "serif" and "monospace". Other software (e.g., the XFree86 + core server) has other mechanisms for font substitution. \ No newline at end of file diff --git a/study_buddy/static/resources/fonts/Bitstream-Vera-Sans/Vera-Bold-Italic.ttf b/study_buddy/static/resources/fonts/Bitstream-Vera-Sans/Vera-Bold-Italic.ttf new file mode 100755 index 0000000..b55eee3 Binary files /dev/null and b/study_buddy/static/resources/fonts/Bitstream-Vera-Sans/Vera-Bold-Italic.ttf differ diff --git a/study_buddy/static/resources/fonts/Bitstream-Vera-Sans/Vera-Bold.ttf b/study_buddy/static/resources/fonts/Bitstream-Vera-Sans/Vera-Bold.ttf new file mode 100755 index 0000000..51d6111 Binary files /dev/null and b/study_buddy/static/resources/fonts/Bitstream-Vera-Sans/Vera-Bold.ttf differ diff --git a/study_buddy/static/resources/fonts/Bitstream-Vera-Sans/Vera-Italic.ttf b/study_buddy/static/resources/fonts/Bitstream-Vera-Sans/Vera-Italic.ttf new file mode 100755 index 0000000..cc23c9e Binary files /dev/null and b/study_buddy/static/resources/fonts/Bitstream-Vera-Sans/Vera-Italic.ttf differ diff --git a/study_buddy/static/resources/fonts/Bitstream-Vera-Sans/Vera.ttf b/study_buddy/static/resources/fonts/Bitstream-Vera-Sans/Vera.ttf new file mode 100755 index 0000000..58cd6b5 Binary files /dev/null and b/study_buddy/static/resources/fonts/Bitstream-Vera-Sans/Vera.ttf differ diff --git a/study_buddy/static/resources/fonts/asap/Asap-Bold.otf b/study_buddy/static/resources/fonts/asap/Asap-Bold.otf new file mode 100755 index 0000000..06aca04 Binary files /dev/null and b/study_buddy/static/resources/fonts/asap/Asap-Bold.otf differ diff --git a/study_buddy/static/resources/fonts/asap/Asap-BoldItalic.otf b/study_buddy/static/resources/fonts/asap/Asap-BoldItalic.otf new file mode 100755 index 0000000..c369040 Binary files /dev/null and b/study_buddy/static/resources/fonts/asap/Asap-BoldItalic.otf differ diff --git a/study_buddy/static/resources/fonts/asap/Asap-Italic.otf b/study_buddy/static/resources/fonts/asap/Asap-Italic.otf new file mode 100755 index 0000000..28b0e1f Binary files /dev/null and b/study_buddy/static/resources/fonts/asap/Asap-Italic.otf differ diff --git a/study_buddy/static/resources/fonts/asap/Asap-Regular.otf b/study_buddy/static/resources/fonts/asap/Asap-Regular.otf new file mode 100755 index 0000000..fba028b Binary files /dev/null and b/study_buddy/static/resources/fonts/asap/Asap-Regular.otf differ diff --git a/study_buddy/static/resources/fonts/asap/SIL Open Font License.txt b/study_buddy/static/resources/fonts/asap/SIL Open Font License.txt new file mode 100755 index 0000000..c9d69b5 --- /dev/null +++ b/study_buddy/static/resources/fonts/asap/SIL Open Font License.txt @@ -0,0 +1,44 @@ +Copyright (c) 2011, Omnibus-Type (www.omnibus-type.com|omnibus.type@gmail.com), +with Reserved Font Name "Asap". + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. + +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). + +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. + +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. + +5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. \ No newline at end of file diff --git a/study_buddy/static/resources/images/aaron.png b/study_buddy/static/resources/images/aaron.png new file mode 100644 index 0000000..eb035f6 Binary files /dev/null and b/study_buddy/static/resources/images/aaron.png differ diff --git a/study_buddy/static/resources/images/adii.png b/study_buddy/static/resources/images/adii.png new file mode 100644 index 0000000..c9f9eb8 Binary files /dev/null and b/study_buddy/static/resources/images/adii.png differ diff --git a/study_buddy/static/resources/images/congruent_pentagon.png b/study_buddy/static/resources/images/congruent_pentagon.png new file mode 100644 index 0000000..c712660 Binary files /dev/null and b/study_buddy/static/resources/images/congruent_pentagon.png differ diff --git a/study_buddy/static/resources/images/denise.png b/study_buddy/static/resources/images/denise.png new file mode 100644 index 0000000..2e522dc Binary files /dev/null and b/study_buddy/static/resources/images/denise.png differ diff --git a/study_buddy/static/resources/images/diamond_upholstery.png b/study_buddy/static/resources/images/diamond_upholstery.png new file mode 100644 index 0000000..1c4701a Binary files /dev/null and b/study_buddy/static/resources/images/diamond_upholstery.png differ diff --git a/study_buddy/static/resources/images/hora.png b/study_buddy/static/resources/images/hora.png new file mode 100644 index 0000000..c4a4b45 Binary files /dev/null and b/study_buddy/static/resources/images/hora.png differ diff --git a/study_buddy/static/resources/images/katya.png b/study_buddy/static/resources/images/katya.png new file mode 100644 index 0000000..bc51240 Binary files /dev/null and b/study_buddy/static/resources/images/katya.png differ diff --git a/study_buddy/static/resources/images/logos/succor_finals-01.png b/study_buddy/static/resources/images/logos/succor_finals-01.png new file mode 100644 index 0000000..d81178d Binary files /dev/null and b/study_buddy/static/resources/images/logos/succor_finals-01.png differ diff --git a/study_buddy/static/resources/images/logos/succor_finals-02.png b/study_buddy/static/resources/images/logos/succor_finals-02.png new file mode 100644 index 0000000..d8d19d1 Binary files /dev/null and b/study_buddy/static/resources/images/logos/succor_finals-02.png differ diff --git a/study_buddy/static/resources/images/logos/succor_finals-03.png b/study_buddy/static/resources/images/logos/succor_finals-03.png new file mode 100644 index 0000000..0cd2518 Binary files /dev/null and b/study_buddy/static/resources/images/logos/succor_finals-03.png differ diff --git a/study_buddy/static/resources/images/logos/succor_finals-04.png b/study_buddy/static/resources/images/logos/succor_finals-04.png new file mode 100644 index 0000000..032d595 Binary files /dev/null and b/study_buddy/static/resources/images/logos/succor_finals-04.png differ diff --git a/study_buddy/static/resources/images/logos/succor_finals.svg b/study_buddy/static/resources/images/logos/succor_finals.svg new file mode 100644 index 0000000..aeba67e --- /dev/null +++ b/study_buddy/static/resources/images/logos/succor_finals.svg @@ -0,0 +1,1337 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +succor + + + + + + + + + + +succor + + + + + + + + + + + diff --git a/study_buddy/static/resources/images/placeholder.png b/study_buddy/static/resources/images/placeholder.png new file mode 100644 index 0000000..175a72d Binary files /dev/null and b/study_buddy/static/resources/images/placeholder.png differ diff --git a/study_buddy/static/resources/images/succor-favicon.ico b/study_buddy/static/resources/images/succor-favicon.ico new file mode 100644 index 0000000..99f5be6 Binary files /dev/null and b/study_buddy/static/resources/images/succor-favicon.ico differ diff --git a/study_buddy/static/resources/images/thumbnail.png b/study_buddy/static/resources/images/thumbnail.png new file mode 100644 index 0000000..b96801b Binary files /dev/null and b/study_buddy/static/resources/images/thumbnail.png differ diff --git a/study_buddy/static/resources/js/datetimepicker/bower.json b/study_buddy/static/resources/js/datetimepicker/bower.json index 9c913ee..8350605 100755 --- a/study_buddy/static/resources/js/datetimepicker/bower.json +++ b/study_buddy/static/resources/js/datetimepicker/bower.json @@ -1,6 +1,6 @@ { "name":"datetimepicker", - "version":"2.3.4", + "version":"2.4.1", "main": [ "jquery.datetimepicker.js", "jquery.datetimepicker.css" @@ -12,7 +12,8 @@ "**/*.txt", "**/*.md", "**/*.html", - "**/*.tpl" + "**/*.tpl", + "**/jquery.js" ], "keywords": [ "calendar", diff --git a/study_buddy/static/resources/js/datetimepicker/datetimepicker.jquery.json b/study_buddy/static/resources/js/datetimepicker/datetimepicker.jquery.json index 8a05bd8..9cdff03 100755 --- a/study_buddy/static/resources/js/datetimepicker/datetimepicker.jquery.json +++ b/study_buddy/static/resources/js/datetimepicker/datetimepicker.jquery.json @@ -1,47 +1,47 @@ -{ - "name": "datetimepicker", - "version": "2.3.4", - "title": "jQuery Date and Time picker", - "description": "jQuery plugin for date, time, or datetime manipulation in form", - "keywords": [ - "calendar", - "date", - "time", - "form", - "datetime", - "datepicker", - "timepicker", - "datetimepicker", - "validation", - "ui", - "scroller", - "picker", - "i18n", - "input", - "jquery", - "touch" - ], - "author": { - "name": "Chupurnov Valeriy", - "email": "chupurnov@gmail.com", - "url": "http://xdsoft.net/contacts.html" - }, - "maintainers": [{ - "name": "Chupurnov Valeriy", - "email": "chupurnov@gmail.com", - "url": "http://xdsoft.net" - }], - "licenses": [ - { - "type": "MIT", - "url": "https://github.com/xdan/datetimepicker/blob/master/MIT-LICENSE.txt" - } - ], - "bugs": "https://github.com/xdan/datetimepicker/issues", - "homepage": "http://xdsoft.net/jqplugins/datetimepicker/", - "docs": "http://xdsoft.net/jqplugins/datetimepicker/", - "download": "https://github.com/xdan/datetimepicker/archive/master.zip", - "dependencies": { - "jquery": ">=1.7" - } +{ + "name": "datetimepicker", + "version": "2.4.1", + "title": "jQuery Date and Time picker", + "description": "jQuery plugin for date, time, or datetime manipulation in form", + "keywords": [ + "calendar", + "date", + "time", + "form", + "datetime", + "datepicker", + "timepicker", + "datetimepicker", + "validation", + "ui", + "scroller", + "picker", + "i18n", + "input", + "jquery", + "touch" + ], + "author": { + "name": "Chupurnov Valeriy", + "email": "chupurnov@gmail.com", + "url": "http://xdsoft.net/contacts.html" + }, + "maintainers": [{ + "name": "Chupurnov Valeriy", + "email": "chupurnov@gmail.com", + "url": "http://xdsoft.net" + }], + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/xdan/datetimepicker/blob/master/MIT-LICENSE.txt" + } + ], + "bugs": "https://github.com/xdan/datetimepicker/issues", + "homepage": "http://xdsoft.net/jqplugins/datetimepicker/", + "docs": "http://xdsoft.net/jqplugins/datetimepicker/", + "download": "https://github.com/xdan/datetimepicker/archive/master.zip", + "dependencies": { + "jquery": ">=1.7" + } } \ No newline at end of file diff --git a/study_buddy/static/resources/js/datetimepicker/index.html b/study_buddy/static/resources/js/datetimepicker/index.html index b75560d..9e5bc62 100755 --- a/study_buddy/static/resources/js/datetimepicker/index.html +++ b/study_buddy/static/resources/js/datetimepicker/index.html @@ -12,6 +12,7 @@ +

Homepage

DateTimePicker



@@ -22,6 +23,7 @@

TimePicker

DatePicker



Inline DateTimePicker

+

Button Trigger

@@ -49,13 +51,20 @@

Disable Specific Dates

Custom Date Styling

Make the background of the date 2 days from now bright red.

+

Dark theme

+

thank for this https://github.com/lampslave

+ - diff --git a/study_buddy/static/resources/js/datetimepicker/jquery.datetimepicker.css b/study_buddy/static/resources/js/datetimepicker/jquery.datetimepicker.css index e99412a..198041d 100755 --- a/study_buddy/static/resources/js/datetimepicker/jquery.datetimepicker.css +++ b/study_buddy/static/resources/js/datetimepicker/jquery.datetimepicker.css @@ -1,5 +1,5 @@ .xdsoft_datetimepicker{ - box-shadow: 0px 5px 15px -5px rgba(0, 0, 0, 0.506); + box-shadow: 0 5px 15px -5px rgba(0, 0, 0, 0.506); background: #FFFFFF; border-bottom: 1px solid #BBBBBB; border-left: 1px solid #CCCCCC; @@ -8,7 +8,7 @@ color: #333333; font-family: "Helvetica Neue", "Helvetica", "Arial", sans-serif; padding: 8px; - padding-left: 0px; + padding-left: 0; padding-top: 2px; position: absolute; z-index: 9999; @@ -50,8 +50,8 @@ .xdsoft_datetimepicker *{ -moz-box-sizing: border-box; box-sizing: border-box; - padding:0px; - margin:0px; + padding: 0; + margin: 0; } .xdsoft_datetimepicker .xdsoft_datepicker, .xdsoft_datetimepicker .xdsoft_timepicker{ display:none; @@ -72,7 +72,7 @@ float:left; text-align:center; margin-left:8px; - margin-top:0px; + margin-top: 0; } .xdsoft_datetimepicker .xdsoft_datepicker.active+.xdsoft_timepicker{ margin-top:8px; @@ -83,36 +83,51 @@ text-align: center; } -.xdsoft_datetimepicker .xdsoft_prev, .xdsoft_datetimepicker .xdsoft_next,.xdsoft_datetimepicker .xdsoft_today_button{ - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAAAeCAYAAACsYQl4AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDozQjRCQjRGREU4MkNFMzExQjRDQkIyRDJDOTdBRUI1MCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpCQjg0OUYyNTZDODAxMUUzQjMwM0IwMERBNUU0ODQ5NSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpCQjg0OUYyNDZDODAxMUUzQjMwM0IwMERBNUU0ODQ5NSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChXaW5kb3dzKSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkI5NzE3MjFBN0E2Q0UzMTFBQjJEQjgzMDk5RTNBNTdBIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjNCNEJCNEZERTgyQ0UzMTFCNENCQjJEMkM5N0FFQjUwIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+aQvATgAAAfVJREFUeNrsmr1OwzAQxzGtkPjYEAuvVGAvfQIGRKADE49gdLwDDwBiZ2RhQUKwICQkWLsgFiRQuIBTucFJ/XFp4+hO+quqnZ4uvzj2nV2RpukCW/22yAgYNINmc7du7DcghCjrkqgOKjF1znpt6rZ0AGWQj7TvCU8d9UM+QAGDrhdyc2Bnc1WVVPBev9V8lBnY+rDwncWZThG4xk4lmxtJy2AHgoY/FySgbSBPwPZ8mEXbQx3aDERb0EbYAYFC7pcAtAvkMWwC0D3NX58S9D/YnoGC7nPWr3Dg9JTbtuHhDShBT8D2CBSK/iIEvVXxpuxSgh7DdgwUTL4iA92zmJb6lKB/YTsECmV+IgK947AGDIqgQ/LojsO135Hn51l2cWlov0JdGNrPUceueXRwilSVgkUyom9Rd6gbLfYTDeO+1v6orn0InTogYDGUkYLO3/wc9BdqqTCKP1Tfi+oTIaCBIL2TES+GTyruT9S61p6BHam+99DFEAgLFklYsIBHwSI9QY80H5ta+1rB/6ovaKihBJeEJbgLbBlQgl+j3lDPqA2tfQV1j3pVn8s+oKHGTSVJ+FqDLeR5bCqJ2E/BCycsoLZETXaKGs7rhKVt+9HZScrZNMi88V8P7LlDbvOZYaJVpMMmBCT4n0o8dTBoNgbdWPsRYACs3r7XyNfbnAAAAABJRU5ErkJggg=='); +.xdsoft_datetimepicker .xdsoft_label i, +.xdsoft_datetimepicker .xdsoft_prev, +.xdsoft_datetimepicker .xdsoft_next, +.xdsoft_datetimepicker .xdsoft_today_button{ + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAAeCAYAAADaW7vzAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6Q0NBRjI1NjM0M0UwMTFFNDk4NkFGMzJFQkQzQjEwRUIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6Q0NBRjI1NjQ0M0UwMTFFNDk4NkFGMzJFQkQzQjEwRUIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpDQ0FGMjU2MTQzRTAxMUU0OTg2QUYzMkVCRDNCMTBFQiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpDQ0FGMjU2MjQzRTAxMUU0OTg2QUYzMkVCRDNCMTBFQiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PoNEP54AAAIOSURBVHja7Jq9TsMwEMcxrZD4WpBYeKUCe+kTMCACHZh4BFfHO/AAIHZGFhYkBBsSEqxsLCAgXKhbXYOTxh9pfJVP+qutnZ5s/5Lz2Y5I03QhWji2GIcgAokWgfCxNvcOCCGKqiSqhUp0laHOne05vdEyGMfkdxJDVjgwDlEQgYQBgx+ULJaWSXXS6r/ER5FBVR8VfGftTKcITNs+a1XpcFoExREIDF14AVIFxgQUS+h520cdud6wNkC0UBw6BCO/HoCYwBhD8QCkQ/x1mwDyD4plh4D6DDV0TAGyo4HcawLIBBSLDkHeH0Mg2yVP3l4TQMZQDDsEOl/MgHQqhMNuE0D+oBh0CIr8MAKyazBH9WyBuKxDWgbXfjNf32TZ1KWm/Ap1oSk/R53UtQ5xTh3LUlMmT8gt6g51Q9p+SobxgJQ/qmsfZhWywGFSl0yBjCLJCMgXail3b7+rumdVJ2YRss4cN+r6qAHDkPWjPjdJCF4n9RmAD/V9A/Wp4NQassDjwlB6XBiCxcJQWmZZb8THFilfy/lfrTvLghq2TqTHrRMTKNJ0sIhdo15RT+RpyWwFdY96UZ/LdQKBGjcXpcc1AlSFEfLmouD+1knuxBDUVrvOBmoOC/rEcN7OQxKVeJTCiAdUzUJhA2Oez9QTkp72OTVcxDcXY8iKNkxGAJXmJCOQwOa6dhyXsOa6XwEGAKdeb5ET3rQdAAAAAElFTkSuQmCC); +} + +.xdsoft_datetimepicker .xdsoft_label i{ + opacity:0.5; + background-position:-92px -19px; + display: inline-block; + width: 9px; + height: 20px; + vertical-align: middle; } + .xdsoft_datetimepicker .xdsoft_prev{ float: left; - background-position:-20px 0px; + background-position:-20px 0; } .xdsoft_datetimepicker .xdsoft_today_button{ float: left; - background-position:-70px 0px; + background-position:-70px 0; margin-left:5px; } .xdsoft_datetimepicker .xdsoft_next{ float: right; - background-position:0px 0px; -} -.xdsoft_datetimepicker .xdsoft_next:active,.xdsoft_datetimepicker .xdsoft_prev:active{ + background-position: 0 0; } -.xdsoft_datetimepicker .xdsoft_next,.xdsoft_datetimepicker .xdsoft_prev ,.xdsoft_datetimepicker .xdsoft_today_button{ + +.xdsoft_datetimepicker .xdsoft_next, +.xdsoft_datetimepicker .xdsoft_prev , +.xdsoft_datetimepicker .xdsoft_today_button{ background-color: transparent; background-repeat: no-repeat; - border: 0px none currentColor; + border: 0 none currentColor; cursor: pointer; display: block; height: 30px; opacity: 0.5; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; outline: medium none currentColor; overflow: hidden; - padding: 0px; + padding: 0; position: relative; text-indent: 100%; white-space: nowrap; @@ -129,9 +144,9 @@ margin-top:7px; } .xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_prev{ - background-position:-40px 0px; + background-position:-40px 0; margin-bottom:7px; - margin-top:0px; + margin-top: 0; } .xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box{ height:151px; @@ -146,18 +161,19 @@ text-align: center; border-collapse:collapse; cursor:pointer; - border-bottom-width:0px; + border-bottom-width: 0; height:25px; line-height:25px; } .xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box >div > div:first-child{ - border-top-width:0px; + border-top-width: 0; } .xdsoft_datetimepicker .xdsoft_today_button:hover, .xdsoft_datetimepicker .xdsoft_next:hover, .xdsoft_datetimepicker .xdsoft_prev:hover { opacity: 1; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; } .xdsoft_datetimepicker .xdsoft_label{ display: inline; @@ -174,13 +190,16 @@ text-align:center; cursor:pointer; } -.xdsoft_datetimepicker .xdsoft_label:hover{ +.xdsoft_datetimepicker .xdsoft_label:hover>span{ text-decoration:underline; } +.xdsoft_datetimepicker .xdsoft_label:hover i{ + opacity:1.0; +} .xdsoft_datetimepicker .xdsoft_label > .xdsoft_select{ border:1px solid #ccc; position:absolute; - right:0px; + right: 0; top:30px; z-index:101; display:none; @@ -195,23 +214,25 @@ background: #ff8000; } .xdsoft_datetimepicker .xdsoft_label > .xdsoft_select > div > .xdsoft_option{ - padding:2px 10px 2px 5px; + padding:2px 10px 2px 5px; + text-decoration:none !important; } .xdsoft_datetimepicker .xdsoft_label > .xdsoft_select > div > .xdsoft_option.xdsoft_current{ background: #33AAFF; - box-shadow: #178FE5 0px 1px 3px 0px inset; + box-shadow: #178FE5 0 1px 3px 0 inset; color:#fff; font-weight: 700; } .xdsoft_datetimepicker .xdsoft_month{ - width:90px; + width:100px; text-align:right; } .xdsoft_datetimepicker .xdsoft_calendar{ clear:both; } .xdsoft_datetimepicker .xdsoft_year{ - width:56px; + width: 48px; + margin-left: 5px; } .xdsoft_datetimepicker .xdsoft_calendar table{ border-collapse:collapse; @@ -231,7 +252,8 @@ color: #666666; font-size: 12px; text-align: right; - padding:0px; + vertical-align: middle; + padding: 0; border-collapse:collapse; cursor:pointer; height: 25px; @@ -249,7 +271,7 @@ .xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_current, .xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box >div >div.xdsoft_current{ background: #33AAFF; - box-shadow: #178FE5 0px 1px 3px 0px inset; + box-shadow: #178FE5 0 1px 3px 0 inset; color:#fff; font-weight: 700; } @@ -257,9 +279,11 @@ .xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_disabled, .xdsoft_datetimepicker .xdsoft_time_box >div >div.xdsoft_disabled{ opacity:0.5; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; } .xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_other_month.xdsoft_disabled{ opacity:0.2; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=20)"; } .xdsoft_datetimepicker .xdsoft_calendar td:hover, .xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box >div >div:hover{ @@ -296,11 +320,99 @@ .xdsoft_scrollbar{ position:absolute; width:7px; - right:0px; - top:0px; - bottom:0px; + right: 0; + top: 0; + bottom: 0; cursor:pointer; } .xdsoft_scroller_box{ position:relative; } + + +.xdsoft_datetimepicker.xdsoft_dark{ + box-shadow: 0 5px 15px -5px rgba(255, 255, 255, 0.506); + background: #000000; + border-bottom: 1px solid #444444; + border-left: 1px solid #333333; + border-right: 1px solid #333333; + border-top: 1px solid #333333; + color: #cccccc; +} + +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_timepicker .xdsoft_time_box{ + border-bottom:1px solid #222222; +} +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_timepicker .xdsoft_time_box >div >div{ + background: #0a0a0a; + border-top:1px solid #222222; + color: #999999; +} + +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_label{ + background-color: #000; +} +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_label > .xdsoft_select{ + border:1px solid #333; + background:#000; +} + +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_label > .xdsoft_select > div > .xdsoft_option:hover{ + color: #000; + background: #007fff; +} + +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_label > .xdsoft_select > div > .xdsoft_option.xdsoft_current{ + background: #cc5500; + box-shadow: #b03e00 0 1px 3px 0 inset; + color:#000; +} + +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_label i, +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_prev, +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_next, +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_today_button{ + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAAeCAYAAADaW7vzAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QUExQUUzOTA0M0UyMTFFNDlBM0FFQTJENTExRDVBODYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QUExQUUzOTE0M0UyMTFFNDlBM0FFQTJENTExRDVBODYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBQTFBRTM4RTQzRTIxMUU0OUEzQUVBMkQ1MTFENUE4NiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpBQTFBRTM4RjQzRTIxMUU0OUEzQUVBMkQ1MTFENUE4NiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pp0VxGEAAAIASURBVHja7JrNSgMxEMebtgh+3MSLr1T1Xn2CHoSKB08+QmR8Bx9A8e7RixdB9CKCoNdexIugxFlJa7rNZneTbLIpM/CnNLsdMvNjM8l0mRCiQ9Ye61IKCAgZAUnH+mU3MMZaHYChBnJUDzWOFZdVfc5+ZFLbrWDeXPwbxIqrLLfaeS0hEBVGIRQCEiZoHQwtlGSByCCdYBl8g8egTTAWoKQMRBRBcZxYlhzhKegqMOageErsCHVkk3hXIFooDgHB1KkHIHVgzKB4ADJQ/A1jAFmAYhkQqA5TOBtocrKrgXwQA8gcFIuAIO8sQSA7hidvPwaQGZSaAYHOUWJABhWWw2EMIH9QagQERU4SArJXo0ZZL18uvaxejXt/Em8xjVBXmvFr1KVm/AJ10tRe2XnraNqaJvKE3KHuUbfK1E+VHB0q40/y3sdQSxY4FHWeKJCunP8UyDdqJZenT3ntVV5jIYCAh20vT7ioP8tpf6E2lfEMwERe+whV1MHjwZB7PBiCxcGQWwKZKD62lfGNnP/1poFAA60T7rF1UgcKd2id3KDeUS+oLWV8DfWAepOfq00CgQabi9zjcgJVYVD7PVzQUAUGAQkbNJTBICDhgwYTjDYD6XeW08ZKh+A4pYkzenOxXUbvZcWz7E8ykRMnIHGX1XPl+1m2vPYpL+2qdb8CDAARlKFEz/ZVkAAAAABJRU5ErkJggg==); +} + +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar td, +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar th{ + background: #0a0a0a; + border:1px solid #222222; + color: #999999; +} + +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar th{ + background: #0e0e0e; +} +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar td.xdsoft_today{ + color:#cc5500; +} +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar td.xdsoft_default, +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar td.xdsoft_current, +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_timepicker .xdsoft_time_box >div >div.xdsoft_current{ + background: #cc5500; + box-shadow: #b03e00 0 1px 3px 0 inset; + color:#000; +} + +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar td:hover, +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_timepicker .xdsoft_time_box >div >div:hover{ + color: #000 !important; + background: #007fff !important; +} + +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_calendar th{ + color: #666; +} +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_copyright{ color:#333 !important;} +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_copyright a{ color:#111 !important;} +.xdsoft_datetimepicker.xdsoft_dark .xdsoft_copyright a:hover{ color:#555 !important;} + + +.xdsoft_dark .xdsoft_time_box{ + border:1px solid #333; +} +.xdsoft_dark .xdsoft_scrollbar >.xdsoft_scroller{ + background:#333 !important; +} diff --git a/study_buddy/static/resources/js/datetimepicker/jquery.datetimepicker.js b/study_buddy/static/resources/js/datetimepicker/jquery.datetimepicker.js index 99008e5..b0d3de1 100755 --- a/study_buddy/static/resources/js/datetimepicker/jquery.datetimepicker.js +++ b/study_buddy/static/resources/js/datetimepicker/jquery.datetimepicker.js @@ -1,12 +1,13 @@ /** - * @preserve jQuery DateTimePicker plugin v2.3.4 + * @preserve jQuery DateTimePicker plugin v2.4.1 * @homepage http://xdsoft.net/jqplugins/datetimepicker/ * (c) 2014, Chupurnov Valeriy. */ -(function( $ ) { +/*global document,window,jQuery,setTimeout,clearTimeout*/ +(function ($) { 'use strict'; var default_options = { - i18n:{ + i18n: { ar: { // Arabic months: [ "كانون الثاني", "شباط", "آذار", "نيسان", "مايو", "حزيران", "تموز", "آب", "أيلول", "تشرين الأول", "تشرين الثاني", "كانون الأول" @@ -31,39 +32,39 @@ "Sen", "Sel", "Rab", "Kam", "Jum", "Sab", "Min" ] }, - bg:{ // Bulgarian - months:[ + bg: { // Bulgarian + months: [ "Януари", "Февруари", "Март", "Април", "Май", "Юни", "Юли", "Август", "Септември", "Октомври", "Ноември", "Декември" ], - dayOfWeek:[ + dayOfWeek: [ "Нд", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб" ] }, - fa:{ // Persian/Farsi - months:[ + fa: { // Persian/Farsi + months: [ 'فروردین', 'اردیبهشت', 'خرداد', 'تیر', 'مرداد', 'شهریور', 'مهر', 'آبان', 'آذر', 'دی', 'بهمن', 'اسفند' ], - dayOfWeek:[ + dayOfWeek: [ 'یکشنبه', 'دوشنبه', 'سه شنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه' ] }, - ru:{ // Russian - months:[ - 'Январь','Февраль','Март','Апрель','Май','Июнь','Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь' + ru: { // Russian + months: [ + 'Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь' ], - dayOfWeek:[ + dayOfWeek: [ "Вск", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб" ] }, - uk:{ // Ukrainian - months:[ - 'Січень','Лютий','Березень','Квітень','Травень','Червень','Липень','Серпень','Вересень','Жовтень','Листопад','Грудень' + uk: { // Ukrainian + months: [ + 'Січень', 'Лютий', 'Березень', 'Квітень', 'Травень', 'Червень', 'Липень', 'Серпень', 'Вересень', 'Жовтень', 'Листопад', 'Грудень' ], - dayOfWeek:[ + dayOfWeek: [ "Ндл", "Пнд", "Втр", "Срд", "Чтв", "Птн", "Сбт" ] }, - en:{ // English + en: { // English months: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ], @@ -71,7 +72,7 @@ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ] }, - el:{ // Ελληνικά + el: { // Ελληνικά months: [ "Ιανουάριος", "Φεβρουάριος", "Μάρτιος", "Απρίλιος", "Μάιος", "Ιούνιος", "Ιούλιος", "Αύγουστος", "Σεπτέμβριος", "Οκτώβριος", "Νοέμβριος", "Δεκέμβριος" ], @@ -79,39 +80,39 @@ "Κυρ", "Δευ", "Τρι", "Τετ", "Πεμ", "Παρ", "Σαβ" ] }, - de:{ // German - months:[ - 'Januar','Februar','März','April','Mai','Juni','Juli','August','September','Oktober','November','Dezember' + de: { // German + months: [ + 'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember' ], - dayOfWeek:[ + dayOfWeek: [ "So", "Mo", "Di", "Mi", "Do", "Fr", "Sa" ] }, - nl:{ // Dutch - months:[ + nl: { // Dutch + months: [ "januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december" ], - dayOfWeek:[ + dayOfWeek: [ "zo", "ma", "di", "wo", "do", "vr", "za" ] }, - tr:{ // Turkish - months:[ + tr: { // Turkish + months: [ "Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık" ], - dayOfWeek:[ + dayOfWeek: [ "Paz", "Pts", "Sal", "Çar", "Per", "Cum", "Cts" ] }, - fr:{ //French - months:[ - "Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre" + fr: { //French + months: [ + "Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre" ], - dayOfWeek:[ + dayOfWeek: [ "Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam" ] }, - es:{ // Spanish + es: { // Spanish months: [ "Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre" ], @@ -119,15 +120,15 @@ "Dom", "Lun", "Mar", "Mié", "Jue", "Vie", "Sáb" ] }, - th:{ // Thai - months:[ - 'มกราคม','กุมภาพันธ์','มีนาคม','เมษายน','พฤษภาคม','มิถุนายน','กรกฎาคม','สิงหาคม','กันยายน','ตุลาคม','พฤศจิกายน','ธันวาคม' + th: { // Thai + months: [ + 'มกราคม', 'กุมภาพันธ์', 'มีนาคม', 'เมษายน', 'พฤษภาคม', 'มิถุนายน', 'กรกฎาคม', 'สิงหาคม', 'กันยายน', 'ตุลาคม', 'พฤศจิกายน', 'ธันวาคม' ], - dayOfWeek:[ - 'อา.','จ.','อ.','พ.','พฤ.','ศ.','ส.' + dayOfWeek: [ + 'อา.', 'จ.', 'อ.', 'พ.', 'พฤ.', 'ศ.', 'ส.' ] }, - pl:{ // Polish + pl: { // Polish months: [ "styczeń", "luty", "marzec", "kwiecień", "maj", "czerwiec", "lipiec", "sierpień", "wrzesień", "październik", "listopad", "grudzień" ], @@ -135,7 +136,7 @@ "nd", "pn", "wt", "śr", "cz", "pt", "sb" ] }, - pt:{ // Portuguese + pt: { // Portuguese months: [ "Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro" ], @@ -143,23 +144,23 @@ "Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sab" ] }, - ch:{ // Simplified Chinese + ch: { // Simplified Chinese months: [ - "一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月" + "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月" ], dayOfWeek: [ - "日", "一","二","三","四","五","六" + "日", "一", "二", "三", "四", "五", "六" ] }, - se:{ // Swedish + se: { // Swedish months: [ - "Januari", "Februari", "Mars", "April", "Maj", "Juni", "Juli", "Augusti", "September","Oktober", "November", "December" + "Januari", "Februari", "Mars", "April", "Maj", "Juni", "Juli", "Augusti", "September", "Oktober", "November", "December" ], dayOfWeek: [ "Sön", "Mån", "Tis", "Ons", "Tor", "Fre", "Lör" ] }, - kr:{ // Korean + kr: { // Korean months: [ "1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월" ], @@ -167,7 +168,7 @@ "일", "월", "화", "수", "목", "금", "토" ] }, - it:{ // Italian + it: { // Italian months: [ "Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre" ], @@ -175,7 +176,7 @@ "Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab" ] }, - da:{ // Dansk + da: { // Dansk months: [ "January", "Februar", "Marts", "April", "Maj", "Juni", "July", "August", "September", "Oktober", "November", "December" ], @@ -183,7 +184,7 @@ "Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør" ] }, - no:{ // Norwegian + no: { // Norwegian months: [ "Januar", "Februar", "Mars", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Desember" ], @@ -191,7 +192,7 @@ "Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør" ] }, - ja:{ // Japanese + ja: { // Japanese months: [ "1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月" ], @@ -199,7 +200,7 @@ "日", "月", "火", "水", "木", "金", "土" ] }, - vi:{ // Vietnamese + vi: { // Vietnamese months: [ "Tháng 1", "Tháng 2", "Tháng 3", "Tháng 4", "Tháng 5", "Tháng 6", "Tháng 7", "Tháng 8", "Tháng 9", "Tháng 10", "Tháng 11", "Tháng 12" ], @@ -207,7 +208,7 @@ "CN", "T2", "T3", "T4", "T5", "T6", "T7" ] }, - sl:{ // Slovenščina + sl: { // Slovenščina months: [ "Januar", "Februar", "Marec", "April", "Maj", "Junij", "Julij", "Avgust", "September", "Oktober", "November", "December" ], @@ -215,7 +216,7 @@ "Ned", "Pon", "Tor", "Sre", "Čet", "Pet", "Sob" ] }, - cs:{ // Čeština + cs: { // Čeština months: [ "Leden", "Únor", "Březen", "Duben", "Květen", "Červen", "Červenec", "Srpen", "Září", "Říjen", "Listopad", "Prosinec" ], @@ -223,210 +224,446 @@ "Ne", "Po", "Út", "St", "Čt", "Pá", "So" ] }, - hu:{ // Hungarian - months: [ + hu: { // Hungarian + months: [ "Január", "Február", "Március", "Április", "Május", "Június", "Július", "Augusztus", "Szeptember", "Október", "November", "December" - ], - dayOfWeek: [ + ], + dayOfWeek: [ "Va", "Hé", "Ke", "Sze", "Cs", "Pé", "Szo" - ] + ] + }, + az: { //Azerbaijanian (Azeri) + months: [ + "Yanvar", "Fevral", "Mart", "Aprel", "May", "Iyun", "Iyul", "Avqust", "Sentyabr", "Oktyabr", "Noyabr", "Dekabr" + ], + dayOfWeek: [ + "B", "Be", "Ça", "Ç", "Ca", "C", "Ş" + ] + }, + bs: { //Bosanski + months: [ + "Januar", "Februar", "Mart", "April", "Maj", "Jun", "Jul", "Avgust", "Septembar", "Oktobar", "Novembar", "Decembar" + ], + dayOfWeek: [ + "Ned", "Pon", "Uto", "Sri", "Čet", "Pet", "Sub" + ] + }, + ca: { //Català + months: [ + "Gener", "Febrer", "Març", "Abril", "Maig", "Juny", "Juliol", "Agost", "Setembre", "Octubre", "Novembre", "Desembre" + ], + dayOfWeek: [ + "Dg", "Dl", "Dt", "Dc", "Dj", "Dv", "Ds" + ] + }, + 'en-GB': { //English (British) + months: [ + "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" + ], + dayOfWeek: [ + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" + ] + }, + et: { //"Eesti" + months: [ + "Jaanuar", "Veebruar", "Märts", "Aprill", "Mai", "Juuni", "Juuli", "August", "September", "Oktoober", "November", "Detsember" + ], + dayOfWeek: [ + "P", "E", "T", "K", "N", "R", "L" + ] + }, + eu: { //Euskara + months: [ + "Urtarrila", "Otsaila", "Martxoa", "Apirila", "Maiatza", "Ekaina", "Uztaila", "Abuztua", "Iraila", "Urria", "Azaroa", "Abendua" + ], + dayOfWeek: [ + "Ig.", "Al.", "Ar.", "Az.", "Og.", "Or.", "La." + ] + }, + fi: { //Finnish (Suomi) + months: [ + "Tammikuu", "Helmikuu", "Maaliskuu", "Huhtikuu", "Toukokuu", "Kesäkuu", "Heinäkuu", "Elokuu", "Syyskuu", "Lokakuu", "Marraskuu", "Joulukuu" + ], + dayOfWeek: [ + "Su", "Ma", "Ti", "Ke", "To", "Pe", "La" + ] + }, + gl: { //Galego + months: [ + "Xan", "Feb", "Maz", "Abr", "Mai", "Xun", "Xul", "Ago", "Set", "Out", "Nov", "Dec" + ], + dayOfWeek: [ + "Dom", "Lun", "Mar", "Mer", "Xov", "Ven", "Sab" + ] + }, + hr: { //Hrvatski + months: [ + "Siječanj", "Veljača", "Ožujak", "Travanj", "Svibanj", "Lipanj", "Srpanj", "Kolovoz", "Rujan", "Listopad", "Studeni", "Prosinac" + ], + dayOfWeek: [ + "Ned", "Pon", "Uto", "Sri", "Čet", "Pet", "Sub" + ] + }, + ko: { //Korean (한국어) + months: [ + "1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월" + ], + dayOfWeek: [ + "일", "월", "화", "수", "목", "금", "토" + ] + }, + lt: { //Lithuanian (lietuvių) + months: [ + "Sausio", "Vasario", "Kovo", "Balandžio", "Gegužės", "Birželio", "Liepos", "Rugpjūčio", "Rugsėjo", "Spalio", "Lapkričio", "Gruodžio" + ], + dayOfWeek: [ + "Sek", "Pir", "Ant", "Tre", "Ket", "Pen", "Šeš" + ] + }, + lv: { //Latvian (Latviešu) + months: [ + "Janvāris", "Februāris", "Marts", "Aprīlis ", "Maijs", "Jūnijs", "Jūlijs", "Augusts", "Septembris", "Oktobris", "Novembris", "Decembris" + ], + dayOfWeek: [ + "Sv", "Pr", "Ot", "Tr", "Ct", "Pk", "St" + ] + }, + mk: { //Macedonian (Македонски) + months: [ + "јануари", "февруари", "март", "април", "мај", "јуни", "јули", "август", "септември", "октомври", "ноември", "декември" + ], + dayOfWeek: [ + "нед", "пон", "вто", "сре", "чет", "пет", "саб" + ] + }, + mn: { //Mongolian (Монгол) + months: [ + "1-р сар", "2-р сар", "3-р сар", "4-р сар", "5-р сар", "6-р сар", "7-р сар", "8-р сар", "9-р сар", "10-р сар", "11-р сар", "12-р сар" + ], + dayOfWeek: [ + "Дав", "Мяг", "Лха", "Пүр", "Бсн", "Бям", "Ням" + ] + }, + 'pt-BR': { //Português(Brasil) + months: [ + "Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro" + ], + dayOfWeek: [ + "Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb" + ] + }, + sk: { //Slovenčina + months: [ + "Január", "Február", "Marec", "Apríl", "Máj", "Jún", "Júl", "August", "September", "Október", "November", "December" + ], + dayOfWeek: [ + "Ne", "Po", "Ut", "St", "Št", "Pi", "So" + ] + }, + sq: { //Albanian (Shqip) + months: [ + "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" + ], + dayOfWeek: [ + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" + ] + }, + 'sr-YU': { //Serbian (Srpski) + months: [ + "Januar", "Februar", "Mart", "April", "Maj", "Jun", "Jul", "Avgust", "Septembar", "Oktobar", "Novembar", "Decembar" + ], + dayOfWeek: [ + "Ned", "Pon", "Uto", "Sre", "čet", "Pet", "Sub" + ] + }, + sr: { //Serbian Cyrillic (Српски) + months: [ + "јануар", "фебруар", "март", "април", "мај", "јун", "јул", "август", "септембар", "октобар", "новембар", "децембар" + ], + dayOfWeek: [ + "нед", "пон", "уто", "сре", "чет", "пет", "суб" + ] + }, + sv: { //Svenska + months: [ + "Januari", "Februari", "Mars", "April", "Maj", "Juni", "Juli", "Augusti", "September", "Oktober", "November", "December" + ], + dayOfWeek: [ + "Sön", "Mån", "Tis", "Ons", "Tor", "Fre", "Lör" + ] + }, + 'zh-TW': { //Traditional Chinese (繁體中文) + months: [ + "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月" + ], + dayOfWeek: [ + "日", "一", "二", "三", "四", "五", "六" + ] + }, + zh: { //Simplified Chinese (简体中文) + months: [ + "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月" + ], + dayOfWeek: [ + "日", "一", "二", "三", "四", "五", "六" + ] + }, + he: { //Hebrew (עברית) + months: [ + 'ינואר', 'פברואר', 'מרץ', 'אפריל', 'מאי', 'יוני', 'יולי', 'אוגוסט', 'ספטמבר', 'אוקטובר', 'נובמבר', 'דצמבר' + ], + dayOfWeek: [ + 'א\'', 'ב\'', 'ג\'', 'ד\'', 'ה\'', 'ו\'', 'שבת' + ] } }, - value:'', - lang:'en', - + value: '', + lang: 'en', + format: 'Y/m/d H:i', formatTime: 'H:i', formatDate: 'Y/m/d', - - startDate: false, // new Date(), '1986/12/08', '-1970/01/05','-1970/01/05', - - step:60, - monthChangeSpinner:true, - closeOnDateSelect:false, - closeOnWithoutClick:true, + + startDate: false, // new Date(), '1986/12/08', '-1970/01/05','-1970/01/05', + step: 60, + monthChangeSpinner: true, + + closeOnDateSelect: false, + closeOnWithoutClick: true, closeOnInputClick: true, - - timepicker:true, - datepicker:true, - weeks:false, - - defaultTime:false, // use formatTime format (ex. '10:00' for formatTime: 'H:i') - defaultDate:false, // use formatDate format (ex new Date() or '1986/12/08' or '-1970/01/05' or '-1970/01/05') - - minDate:false, - maxDate:false, - minTime:false, - maxTime:false, - - allowTimes:[], - opened:false, - initTime:true, - inline:false, - - onSelectDate:function() {}, - onSelectTime:function() {}, - onChangeMonth:function() {}, - onChangeDateTime:function() {}, - onShow:function() {}, - onClose:function() {}, - onGenerate:function() {}, - - withoutCopyright:true, - - inverseButton:false, - hours12:false, + + timepicker: true, + datepicker: true, + weeks: false, + + defaultTime: false, // use formatTime format (ex. '10:00' for formatTime: 'H:i') + defaultDate: false, // use formatDate format (ex new Date() or '1986/12/08' or '-1970/01/05' or '-1970/01/05') + + minDate: false, + maxDate: false, + minTime: false, + maxTime: false, + + allowTimes: [], + opened: false, + initTime: true, + inline: false, + theme: '', + + onSelectDate: function () {}, + onSelectTime: function () {}, + onChangeMonth: function () {}, + onChangeYear: function () {}, + onChangeDateTime: function () {}, + onShow: function () {}, + onClose: function () {}, + onGenerate: function () {}, + + withoutCopyright: true, + inverseButton: false, + hours12: false, next: 'xdsoft_next', prev : 'xdsoft_prev', - dayOfWeekStart:0, - - timeHeightInTimePicker:25, - timepickerScrollbar:true, - - todayButton:true, // 2.1.0 - defaultSelect:true, // 2.1.0 - - scrollMonth:true, - scrollTime:true, - scrollInput:true, - - lazyInit:false, - - mask:false, - validateOnBlur:true, - allowBlank:true, - - yearStart:1950, - yearEnd:2050, - - style:'', - id:'', - + dayOfWeekStart: 0, + parentID: 'body', + timeHeightInTimePicker: 25, + timepickerScrollbar: true, + todayButton: true, + defaultSelect: true, + + scrollMonth: true, + scrollTime: true, + scrollInput: true, + + lazyInit: false, + mask: false, + validateOnBlur: true, + allowBlank: true, + yearStart: 1950, + yearEnd: 2050, + style: '', + id: '', fixed: false, - - roundTime:'round', // ceil, floor - className:'', - - weekends : [], - yearOffset:0, - beforeShowDay: null + roundTime: 'round', // ceil, floor + className: '', + weekends: [], + disabledDates : [], + yearOffset: 0, + beforeShowDay: null, + + enterLikeTab: true }; - // fix for ie8 - if ( !Array.prototype.indexOf ) { - Array.prototype.indexOf = function(obj, start) { - for (var i = (start || 0), j = this.length; i < j; i++) { - if (this[i] === obj) { return i; } - } - return -1; - } + if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (obj, start) { + var i, j; + for (i = (start || 0), j = this.length; i < j; i += 1) { + if (this[i] === obj) { return i; } + } + return -1; + }; } - - Date.prototype.countDaysInMonth = function(){ - return new Date(this.getFullYear(), this.getMonth()+1, 0).getDate(); + Date.prototype.countDaysInMonth = function () { + return new Date(this.getFullYear(), this.getMonth() + 1, 0).getDate(); }; - - $.fn.xdsoftScroller = function( _percent ) { - return this.each(function() { - var timeboxparent = $(this); - if( !$(this).hasClass('xdsoft_scroller_box') ) { - var pointerEventToXY = function( e ) { - var out = {x:0, y:0}; - if( e.type == 'touchstart' || e.type == 'touchmove' || e.type == 'touchend' || e.type == 'touchcancel' ) { - var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0]; - out.x = touch.pageX; - out.y = touch.pageY; - }else if (e.type == 'mousedown' || e.type == 'mouseup' || e.type == 'mousemove' || e.type == 'mouseover'|| e.type=='mouseout' || e.type=='mouseenter' || e.type=='mouseleave') { - out.x = e.pageX; - out.y = e.pageY; - } - return out; - }, - move = 0, - timebox = timeboxparent.children().eq(0), - parentHeight = timeboxparent[0].clientHeight, - height = timebox[0].offsetHeight, - scrollbar = $('
'), - scroller = $('
'), - maximumOffset = 100, - start = false; - + $.fn.xdsoftScroller = function (percent) { + return this.each(function () { + var timeboxparent = $(this), + pointerEventToXY = function (e) { + var out = {x: 0, y: 0}, + touch; + if (e.type === 'touchstart' || e.type === 'touchmove' || e.type === 'touchend' || e.type === 'touchcancel') { + touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0]; + out.x = touch.clientX; + out.y = touch.clientY; + } else if (e.type === 'mousedown' || e.type === 'mouseup' || e.type === 'mousemove' || e.type === 'mouseover' || e.type === 'mouseout' || e.type === 'mouseenter' || e.type === 'mouseleave') { + out.x = e.clientX; + out.y = e.clientY; + } + return out; + }, + move = 0, + timebox, + parentHeight, + height, + scrollbar, + scroller, + maximumOffset = 100, + start = false, + startY = 0, + startTop = 0, + h1 = 0, + touchStart = false, + startTopScroll = 0, + calcOffset = function () {}; + if (percent === 'hide') { + timeboxparent.find('.xdsoft_scrollbar').hide(); + return; + } + if (!$(this).hasClass('xdsoft_scroller_box')) { + timebox = timeboxparent.children().eq(0); + parentHeight = timeboxparent[0].clientHeight; + height = timebox[0].offsetHeight; + scrollbar = $('
'); + scroller = $('
'); scrollbar.append(scroller); timeboxparent.addClass('xdsoft_scroller_box').append(scrollbar); - scroller.on('mousedown.xdsoft_scroller',function ( event ) { - if( !parentHeight ) - timeboxparent.trigger('resize_scroll.xdsoft_scroller',[_percent]); - var pageY = event.pageY, - top = parseInt(scroller.css('margin-top')), + calcOffset = function calcOffset(event) { + var offset = pointerEventToXY(event).y - startY + startTopScroll; + if (offset < 0) { + offset = 0; + } + if (offset + scroller[0].offsetHeight > h1) { + offset = h1 - scroller[0].offsetHeight; + } + timeboxparent.trigger('scroll_element.xdsoft_scroller', [maximumOffset ? offset / maximumOffset : 0]); + }; + + scroller + .on('touchstart.xdsoft_scroller mousedown.xdsoft_scroller', function (event) { + if (!parentHeight) { + timeboxparent.trigger('resize_scroll.xdsoft_scroller', [percent]); + } + + startY = pointerEventToXY(event).y; + startTopScroll = parseInt(scroller.css('margin-top'), 10); h1 = scrollbar[0].offsetHeight; - $(document.body).addClass('xdsoft_noselect'); - $([document.body,window]).on('mouseup.xdsoft_scroller',function arguments_callee() { - $([document.body,window]).off('mouseup.xdsoft_scroller',arguments_callee) - .off('mousemove.xdsoft_scroller',move) - .removeClass('xdsoft_noselect'); - }); - $(document.body).on('mousemove.xdsoft_scroller',move = function(event) { - var offset = event.pageY-pageY+top; - if( offset<0 ) - offset = 0; - if( offset+scroller[0].offsetHeight>h1 ) - offset = h1-scroller[0].offsetHeight; - timeboxparent.trigger('scroll_element.xdsoft_scroller',[maximumOffset?offset/maximumOffset:0]); + + if (event.type === 'mousedown') { + if (document) { + $(document.body).addClass('xdsoft_noselect'); + } + $([document.body, window]).on('mouseup.xdsoft_scroller', function arguments_callee() { + $([document.body, window]).off('mouseup.xdsoft_scroller', arguments_callee) + .off('mousemove.xdsoft_scroller', calcOffset) + .removeClass('xdsoft_noselect'); + }); + $(document.body).on('mousemove.xdsoft_scroller', calcOffset); + } else { + touchStart = true; + event.stopPropagation(); + event.preventDefault(); + } + }) + .on('touchmove', function (event) { + if (touchStart) { + event.preventDefault(); + calcOffset(event); + } + }) + .on('touchend touchcancel', function (event) { + touchStart = false; + startTopScroll = 0; }); - }); timeboxparent - .on('scroll_element.xdsoft_scroller',function( event,percent ) { - if( !parentHeight ) - timeboxparent.trigger('resize_scroll.xdsoft_scroller',[percent,true]); - percent = percent>1?1:(percent<0||isNaN(percent))?0:percent; - scroller.css('margin-top',maximumOffset*percent); - setTimeout(function(){ - timebox.css('marginTop',-parseInt((timebox[0].offsetHeight-parentHeight)*percent)) - },10); + .on('scroll_element.xdsoft_scroller', function (event, percentage) { + if (!parentHeight) { + timeboxparent.trigger('resize_scroll.xdsoft_scroller', [percentage, true]); + } + percentage = percentage > 1 ? 1 : (percentage < 0 || isNaN(percentage)) ? 0 : percentage; + + scroller.css('margin-top', maximumOffset * percentage); + + setTimeout(function () { + timebox.css('marginTop', -parseInt((timebox[0].offsetHeight - parentHeight) * percentage, 10)); + }, 10); }) - .on('resize_scroll.xdsoft_scroller',function( event,_percent,noTriggerScroll ) { + .on('resize_scroll.xdsoft_scroller', function (event, percentage, noTriggerScroll) { + var percent, sh; parentHeight = timeboxparent[0].clientHeight; height = timebox[0].offsetHeight; - var percent = parentHeight/height, - sh = percent*scrollbar[0].offsetHeight; - if( percent>1 ) + percent = parentHeight / height; + sh = percent * scrollbar[0].offsetHeight; + if (percent > 1) { scroller.hide(); - else{ + } else { scroller.show(); - scroller.css('height',parseInt(sh>10?sh:10)); - maximumOffset = scrollbar[0].offsetHeight-scroller[0].offsetHeight; - if( noTriggerScroll!==true ) - timeboxparent.trigger('scroll_element.xdsoft_scroller',[_percent?_percent:Math.abs(parseInt(timebox.css('marginTop')))/(height-parentHeight)]); + scroller.css('height', parseInt(sh > 10 ? sh : 10, 10)); + maximumOffset = scrollbar[0].offsetHeight - scroller[0].offsetHeight; + if (noTriggerScroll !== true) { + timeboxparent.trigger('scroll_element.xdsoft_scroller', [percentage || Math.abs(parseInt(timebox.css('marginTop'), 10)) / (height - parentHeight)]); + } } }); - timeboxparent.mousewheel&&timeboxparent.mousewheel(function(event, delta, deltaX, deltaY) { - var top = Math.abs(parseInt(timebox.css('marginTop'))); - timeboxparent.trigger('scroll_element.xdsoft_scroller',[(top-delta*20)/(height-parentHeight)]); + + timeboxparent.on('mousewheel', function (event) { + var top = Math.abs(parseInt(timebox.css('marginTop'), 10)); + + top = top - (event.deltaY * 20); + if (top < 0) { + top = 0; + } + + timeboxparent.trigger('scroll_element.xdsoft_scroller', [top / (height - parentHeight)]); event.stopPropagation(); return false; }); - timeboxparent.on('touchstart',function( event ) { + + timeboxparent.on('touchstart', function (event) { start = pointerEventToXY(event); + startTop = Math.abs(parseInt(timebox.css('marginTop'), 10)); }); - timeboxparent.on('touchmove',function( event ) { - if( start ) { - var coord = pointerEventToXY(event), top = Math.abs(parseInt(timebox.css('marginTop'))); - timeboxparent.trigger('scroll_element.xdsoft_scroller',[(top-(coord.y-start.y))/(height-parentHeight)]); - event.stopPropagation(); + + timeboxparent.on('touchmove', function (event) { + if (start) { event.preventDefault(); - start = pointerEventToXY(event); + var coord = pointerEventToXY(event); + timeboxparent.trigger('scroll_element.xdsoft_scroller', [(startTop - (coord.y - start.y)) / (height - parentHeight)]); } }); - timeboxparent.on('touchend touchcancel',function( event ) { + + timeboxparent.on('touchend touchcancel', function (event) { start = false; + startTop = 0; }); } - timeboxparent.trigger('resize_scroll.xdsoft_scroller',[_percent]); + timeboxparent.trigger('resize_scroll.xdsoft_scroller', [percent]); }); }; - $.fn.datetimepicker = function( opt ) { + + $.fn.datetimepicker = function (opt) { var KEY0 = 48, KEY9 = 57, _KEY0 = 96, @@ -448,1042 +685,1151 @@ ZKEY = 90, YKEY = 89, ctrlDown = false, - options = ($.isPlainObject(opt)||!opt)?$.extend(true,{},default_options,opt):$.extend({},default_options), + options = ($.isPlainObject(opt) || !opt) ? $.extend(true, {}, default_options, opt) : $.extend(true, {}, default_options), lazyInitTimer = 0, + createDateTimePicker, + destroyDateTimePicker, + _xdsoft_datetime, - lazyInit = function( input ){ + lazyInit = function (input) { input - .on('open.xdsoft focusin.xdsoft mousedown.xdsoft',function initOnActionCallback(event) { - if( input.is(':disabled')||input.is(':hidden')||!input.is(':visible')||input.data( 'xdsoft_datetimepicker') ) + .on('open.xdsoft focusin.xdsoft mousedown.xdsoft', function initOnActionCallback(event) { + if (input.is(':disabled') || input.is(':hidden') || !input.is(':visible') || input.data('xdsoft_datetimepicker')) { return; - + } clearTimeout(lazyInitTimer); - - lazyInitTimer = setTimeout(function() { + lazyInitTimer = setTimeout(function () { - if( !input.data( 'xdsoft_datetimepicker') ) + if (!input.data('xdsoft_datetimepicker')) { createDateTimePicker(input); - + } input - .off('open.xdsoft focusin.xdsoft mousedown.xdsoft',initOnActionCallback) + .off('open.xdsoft focusin.xdsoft mousedown.xdsoft', initOnActionCallback) .trigger('open.xdsoft'); - },100); - + }, 100); }); - }, - - createDateTimePicker = function( input ) { - - var datetimepicker = $('
'), - xdsoft_copyright = $(''), - datepicker = $('
'), - mounth_picker = $('
'), - calendar = $('
'), - timepicker = $('
'), - timeboxparent = timepicker.find('.xdsoft_time_box').eq(0), - timebox = $('
'), - scrollbar = $('
'), - scroller = $('
'), - monthselect =$('
'), - yearselect =$('
'); - - //constructor lego - mounth_picker - .find('.xdsoft_month span') - .after(monthselect); - mounth_picker - .find('.xdsoft_year span') - .after(yearselect); + }; - mounth_picker - .find('.xdsoft_month,.xdsoft_year') - .on('mousedown.xdsoft',function(event) { - mounth_picker - .find('.xdsoft_select') - .hide(); - - var select = $(this).find('.xdsoft_select').eq(0), - val = 0, - top = 0; - - if( _xdsoft_datetime.currentTime ) - val = _xdsoft_datetime.currentTime[$(this).hasClass('xdsoft_month')?'getMonth':'getFullYear'](); - - select.show(); - - for(var items = select.find('div.xdsoft_option'),i = 0;i'), + xdsoft_copyright = $(''), + datepicker = $('
'), + mounth_picker = $('
' + + '
' + + '
' + + '
'), + calendar = $('
'), + timepicker = $('
'), + timeboxparent = timepicker.find('.xdsoft_time_box').eq(0), + timebox = $('
'), + /*scrollbar = $('
'), + scroller = $('
'),*/ + monthselect = $('
'), + yearselect = $('
'), + triggerAfterOpen = false, + XDSoft_datetime, + //scroll_element, + xchangeTimer, + timerclick, + current_time_index, + setPos, + timer = 0, + timer1 = 0; + + mounth_picker + .find('.xdsoft_month span') + .after(monthselect); + mounth_picker + .find('.xdsoft_year span') + .after(yearselect); + + mounth_picker + .find('.xdsoft_month,.xdsoft_year') + .on('mousedown.xdsoft', function (event) { + var select = $(this).find('.xdsoft_select').eq(0), + val = 0, + top = 0, + visible = select.is(':visible'), + items, + i; - select.xdsoftScroller(top/(select.children()[0].offsetHeight-(select[0].clientHeight))); - event.stopPropagation(); - - return false; - }); + mounth_picker + .find('.xdsoft_select') + .hide(); + if (_xdsoft_datetime.currentTime) { + val = _xdsoft_datetime.currentTime[$(this).hasClass('xdsoft_month') ? 'getMonth' : 'getFullYear'](); + } - mounth_picker - .find('.xdsoft_select') - .xdsoftScroller() - .on('mousedown.xdsoft',function( event ) { - event.stopPropagation(); - event.preventDefault(); - }) - .on('mousedown.xdsoft','.xdsoft_option',function( event ) { - if( _xdsoft_datetime&&_xdsoft_datetime.currentTime ) - _xdsoft_datetime.currentTime[$(this).parent().parent().hasClass('xdsoft_monthselect')?'setMonth':'setFullYear']($(this).data('value')); - - $(this).parent().parent().hide(); - - datetimepicker.trigger('xchange.xdsoft'); - options.onChangeMonth&&options.onChangeMonth.call&&options.onChangeMonth.call(datetimepicker,_xdsoft_datetime.currentTime,datetimepicker.data('input')); - }); + select[visible ? 'hide' : 'show'](); + for (items = select.find('div.xdsoft_option'), i = 0; i < items.length; i += 1) { + if (items.eq(i).data('value') === val) { + break; + } else { + top += items[0].offsetHeight; + } + } + select.xdsoftScroller(top / (select.children()[0].offsetHeight - (select[0].clientHeight))); + event.stopPropagation(); + return false; + }); - // set options - datetimepicker.setOptions = function( _options ) { - options = $.extend(true,{},options,_options); - - if( _options.allowTimes && $.isArray(_options.allowTimes) && _options.allowTimes.length ){ - options['allowTimes'] = $.extend(true,[],_options.allowTimes); - } - - if( _options.weekends && $.isArray(_options.weekends) && _options.weekends.length ){ - options['weekends'] = $.extend(true,[],_options.weekends); - } - - if( (options.open||options.opened)&&(!options.inline) ) { - input.trigger('open.xdsoft'); + mounth_picker + .find('.xdsoft_select') + .xdsoftScroller() + .on('mousedown.xdsoft', function (event) { + event.stopPropagation(); + event.preventDefault(); + }) + .on('mousedown.xdsoft', '.xdsoft_option', function (event) { + var year = _xdsoft_datetime.currentTime.getFullYear(); + if (_xdsoft_datetime && _xdsoft_datetime.currentTime) { + _xdsoft_datetime.currentTime[$(this).parent().parent().hasClass('xdsoft_monthselect') ? 'setMonth' : 'setFullYear']($(this).data('value')); } - if( options.inline ) { - triggerAfterOpen = true; - datetimepicker.addClass('xdsoft_inline'); - input.after(datetimepicker).hide(); + $(this).parent().parent().hide(); + + datetimepicker.trigger('xchange.xdsoft'); + if (options.onChangeMonth && $.isFunction(options.onChangeMonth)) { + options.onChangeMonth.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input')); } - if( options.inverseButton ) { - options.next = 'xdsoft_prev'; - options.prev = 'xdsoft_next'; + if (year !== _xdsoft_datetime.currentTime.getFullYear() && $.isFunction(options.onChangeYear)) { + options.onChangeYear.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input')); } + }); - if( options.datepicker ) - datepicker.addClass('active'); - else - datepicker.removeClass('active'); + datetimepicker.setOptions = function (_options) { + options = $.extend(true, {}, options, _options); - if( options.timepicker ) - timepicker.addClass('active'); - else - timepicker.removeClass('active'); + if (_options.allowTimes && $.isArray(_options.allowTimes) && _options.allowTimes.length) { + options.allowTimes = $.extend(true, [], _options.allowTimes); + } - if( options.value ){ - input&&input.val&&input.val(options.value); - _xdsoft_datetime.setCurrentTime(options.value); - } + if (_options.weekends && $.isArray(_options.weekends) && _options.weekends.length) { + options.weekends = $.extend(true, [], _options.weekends); + } - if( isNaN(options.dayOfWeekStart) ) - options.dayOfWeekStart = 0; - else - options.dayOfWeekStart = parseInt(options.dayOfWeekStart)%7; + if (_options.disabledDates && $.isArray(_options.disabledDates) && _options.disabledDates.length) { + options.disabledDates = $.extend(true, [], _options.disabledDates); + } - if( !options.timepickerScrollbar ) - scrollbar.hide(); - - if( options.minDate && /^-(.*)$/.test(options.minDate) ){ - options.minDate = _xdsoft_datetime.strToDateTime(options.minDate).dateFormat( options.formatDate ); - } - - if( options.maxDate && /^\+(.*)$/.test(options.maxDate) ) { - options.maxDate = _xdsoft_datetime.strToDateTime(options.maxDate).dateFormat( options.formatDate ); + if ((options.open || options.opened) && (!options.inline)) { + input.trigger('open.xdsoft'); + } + + if (options.inline) { + triggerAfterOpen = true; + datetimepicker.addClass('xdsoft_inline'); + input.after(datetimepicker).hide(); + } + + if (options.inverseButton) { + options.next = 'xdsoft_prev'; + options.prev = 'xdsoft_next'; + } + + if (options.datepicker) { + datepicker.addClass('active'); + } else { + datepicker.removeClass('active'); + } + + if (options.timepicker) { + timepicker.addClass('active'); + } else { + timepicker.removeClass('active'); + } + + if (options.value) { + if (input && input.val) { + input.val(options.value); } - - mounth_picker - .find('.xdsoft_today_button') - .css('visibility',!options.todayButton?'hidden':'visible'); - - if( options.mask ) { - var e, - getCaretPos = function ( input ) { - try{ - if ( document.selection && document.selection.createRange ) { - var range = document.selection.createRange(); - return range.getBookmark().charCodeAt(2) - 2; - }else - if ( input.setSelectionRange ) - return input.selectionStart; - }catch(e) { - return 0; + _xdsoft_datetime.setCurrentTime(options.value); + } + + if (isNaN(options.dayOfWeekStart)) { + options.dayOfWeekStart = 0; + } else { + options.dayOfWeekStart = parseInt(options.dayOfWeekStart, 10) % 7; + } + + if (!options.timepickerScrollbar) { + timeboxparent.xdsoftScroller('hide'); + } + + if (options.minDate && /^-(.*)$/.test(options.minDate)) { + options.minDate = _xdsoft_datetime.strToDateTime(options.minDate).dateFormat(options.formatDate); + } + + if (options.maxDate && /^\+(.*)$/.test(options.maxDate)) { + options.maxDate = _xdsoft_datetime.strToDateTime(options.maxDate).dateFormat(options.formatDate); + } + + mounth_picker + .find('.xdsoft_today_button') + .css('visibility', !options.todayButton ? 'hidden' : 'visible'); + + if (options.mask) { + var e, + getCaretPos = function (input) { + try { + if (document.selection && document.selection.createRange) { + var range = document.selection.createRange(); + return range.getBookmark().charCodeAt(2) - 2; } - }, - setCaretPos = function ( node,pos ) { - node = (typeof node == "string" || node instanceof String) ? document.getElementById(node) : node; - if(!node) { - return false; - }else if(node.createTextRange) { - var textRange = node.createTextRange(); - textRange.collapse(true); - textRange.moveEnd(pos); - textRange.moveStart(pos); - textRange.select(); - return true; - }else if(node.setSelectionRange) { - node.setSelectionRange(pos,pos); - return true; + if (input.setSelectionRange) { + return input.selectionStart; } + } catch (e) { + return 0; + } + }, + setCaretPos = function (node, pos) { + node = (typeof node === "string" || node instanceof String) ? document.getElementById(node) : node; + if (!node) { return false; - }, - isValidValue = function ( mask,value ) { - var reg = mask - .replace(/([\[\]\/\{\}\(\)\-\.\+]{1})/g,'\\$1') - .replace(/_/g,'{digit+}') - .replace(/([0-9]{1})/g,'{digit$1}') - .replace(/\{digit([0-9]{1})\}/g,'[0-$1_]{1}') - .replace(/\{digit[\+]\}/g,'[0-9_]{1}'); - return RegExp(reg).test(value); - }; - input.off('keydown.xdsoft'); - switch(true) { - case ( options.mask===true ): - - options.mask = options.format - .replace(/Y/g,'9999') - .replace(/F/g,'9999') - .replace(/m/g,'19') - .replace(/d/g,'39') - .replace(/H/g,'29') - .replace(/i/g,'59') - .replace(/s/g,'59'); - - case ( $.type(options.mask) == 'string' ): - - if( !isValidValue( options.mask,input.val() ) ) - input.val(options.mask.replace(/[0-9]/g,'_')); - - input.on('keydown.xdsoft',function( event ) { - var val = this.value, - key = event.which; - - switch(true) { - case (( key>=KEY0&&key<=KEY9 )||( key>=_KEY0&&key<=_KEY9 ))||(key==BACKSPACE||key==DEL): - var pos = getCaretPos(this), - digit = ( key!=BACKSPACE&&key!=DEL )?String.fromCharCode((_KEY0 <= key && key <= _KEY9)? key-KEY0 : key):'_'; - - if( (key==BACKSPACE||key==DEL)&&pos ) { - pos--; - digit='_'; - } - - while( /[^0-9_]/.test(options.mask.substr(pos,1))&&pos0 ) - pos+=( key==BACKSPACE||key==DEL )?-1:1; - - val = val.substr(0,pos)+digit+val.substr(pos+1); - if( $.trim(val)=='' ){ - val = options.mask.replace(/[0-9]/g,'_'); - }else{ - if( pos==options.mask.length ) - break; - } - - pos+=(key==BACKSPACE||key==DEL)?0:1; - while( /[^0-9_]/.test(options.mask.substr(pos,1))&&pos0 ) - pos+=(key==BACKSPACE||key==DEL)?-1:1; - - if( isValidValue( options.mask,val ) ) { - this.value = val; - setCaretPos(this,pos); - }else if( $.trim(val)=='' ) - this.value = options.mask.replace(/[0-9]/g,'_'); - else{ - input.trigger('error_input.xdsoft'); - } - break; - case ( !!~([AKEY,CKEY,VKEY,ZKEY,YKEY].indexOf(key))&&ctrlDown ): - case !!~([ESC,ARROWUP,ARROWDOWN,ARROWLEFT,ARROWRIGHT,F5,CTRLKEY,TAB,ENTER].indexOf(key)): - return true; - } - event.preventDefault(); - return false; - }); - break; - } - } - if( options.validateOnBlur ) { - input - .off('blur.xdsoft') - .on('blur.xdsoft', function() { - if( options.allowBlank && !$.trim($(this).val()).length ) { - $(this).val(null); - datetimepicker.data('xdsoft_datetime').empty(); - }else if( !Date.parseDate( $(this).val(), options.format ) ) { - $(this).val((_xdsoft_datetime.now()).dateFormat( options.format )); - datetimepicker.data('xdsoft_datetime').setCurrentTime($(this).val()); - } - else{ - datetimepicker.data('xdsoft_datetime').setCurrentTime($(this).val()); - } - datetimepicker.trigger('changedatetime.xdsoft'); - }); + } + if (node.createTextRange) { + var textRange = node.createTextRange(); + textRange.collapse(true); + textRange.moveEnd('character', pos); + textRange.moveStart('character', pos); + textRange.select(); + return true; + } + if (node.setSelectionRange) { + node.setSelectionRange(pos, pos); + return true; + } + return false; + }, + isValidValue = function (mask, value) { + var reg = mask + .replace(/([\[\]\/\{\}\(\)\-\.\+]{1})/g, '\\$1') + .replace(/_/g, '{digit+}') + .replace(/([0-9]{1})/g, '{digit$1}') + .replace(/\{digit([0-9]{1})\}/g, '[0-$1_]{1}') + .replace(/\{digit[\+]\}/g, '[0-9_]{1}'); + return (new RegExp(reg)).test(value); + }; + input.off('keydown.xdsoft'); + + if (options.mask === true) { + options.mask = options.format + .replace(/Y/g, '9999') + .replace(/F/g, '9999') + .replace(/m/g, '19') + .replace(/d/g, '39') + .replace(/H/g, '29') + .replace(/i/g, '59') + .replace(/s/g, '59'); } - options.dayOfWeekStartPrev = (options.dayOfWeekStart==0)?6:options.dayOfWeekStart-1; - - datetimepicker - .trigger('xchange.xdsoft') - .trigger('afterOpen.xdsoft') - }; + + if ($.type(options.mask) === 'string') { + if (!isValidValue(options.mask, input.val())) { + input.val(options.mask.replace(/[0-9]/g, '_')); + } + + input.on('keydown.xdsoft', function (event) { + var val = this.value, + key = event.which, + pos, + digit; + + if (((key >= KEY0 && key <= KEY9) || (key >= _KEY0 && key <= _KEY9)) || (key === BACKSPACE || key === DEL)) { + pos = getCaretPos(this); + digit = (key !== BACKSPACE && key !== DEL) ? String.fromCharCode((_KEY0 <= key && key <= _KEY9) ? key - KEY0 : key) : '_'; + + if ((key === BACKSPACE || key === DEL) && pos) { + pos -= 1; + digit = '_'; + } + + while (/[^0-9_]/.test(options.mask.substr(pos, 1)) && pos < options.mask.length && pos > 0) { + pos += (key === BACKSPACE || key === DEL) ? -1 : 1; + } + + val = val.substr(0, pos) + digit + val.substr(pos + 1); + if ($.trim(val) === '') { + val = options.mask.replace(/[0-9]/g, '_'); + } else { + if (pos === options.mask.length) { + event.preventDefault(); + return false; + } + } + + pos += (key === BACKSPACE || key === DEL) ? 0 : 1; + while (/[^0-9_]/.test(options.mask.substr(pos, 1)) && pos < options.mask.length && pos > 0) { + pos += (key === BACKSPACE || key === DEL) ? -1 : 1; + } + + if (isValidValue(options.mask, val)) { + this.value = val; + setCaretPos(this, pos); + } else if ($.trim(val) === '') { + this.value = options.mask.replace(/[0-9]/g, '_'); + } else { + input.trigger('error_input.xdsoft'); + } + } else { + if (([AKEY, CKEY, VKEY, ZKEY, YKEY].indexOf(key) !== -1 && ctrlDown) || [ESC, ARROWUP, ARROWDOWN, ARROWLEFT, ARROWRIGHT, F5, CTRLKEY, TAB, ENTER].indexOf(key) !== -1) { + return true; + } + } + + event.preventDefault(); + return false; + }); + } + } + if (options.validateOnBlur) { + input + .off('blur.xdsoft') + .on('blur.xdsoft', function () { + if (options.allowBlank && !$.trim($(this).val()).length) { + $(this).val(null); + datetimepicker.data('xdsoft_datetime').empty(); + } else if (!Date.parseDate($(this).val(), options.format)) { + $(this).val((_xdsoft_datetime.now()).dateFormat(options.format)); + datetimepicker.data('xdsoft_datetime').setCurrentTime($(this).val()); + } else { + datetimepicker.data('xdsoft_datetime').setCurrentTime($(this).val()); + } + datetimepicker.trigger('changedatetime.xdsoft'); + }); + } + options.dayOfWeekStartPrev = (options.dayOfWeekStart === 0) ? 6 : options.dayOfWeekStart - 1; datetimepicker - .data('options',options) - .on('mousedown.xdsoft',function( event ) { - event.stopPropagation(); - event.preventDefault(); - yearselect.hide(); - monthselect.hide(); - return false; - }); + .trigger('xchange.xdsoft') + .trigger('afterOpen.xdsoft'); + }; - var scroll_element = timepicker.find('.xdsoft_time_box'); - scroll_element.append(timebox); - scroll_element.xdsoftScroller(); - - datetimepicker.on('afterOpen.xdsoft',function() { - scroll_element.xdsoftScroller(); + datetimepicker + .data('options', options) + .on('mousedown.xdsoft', function (event) { + event.stopPropagation(); + event.preventDefault(); + yearselect.hide(); + monthselect.hide(); + return false; }); + //scroll_element = timepicker.find('.xdsoft_time_box'); + timeboxparent.append(timebox); + timeboxparent.xdsoftScroller(); + + datetimepicker.on('afterOpen.xdsoft', function () { + timeboxparent.xdsoftScroller(); + }); + + datetimepicker + .append(datepicker) + .append(timepicker); + + if (options.withoutCopyright !== true) { datetimepicker - .append(datepicker) - .append(timepicker); + .append(xdsoft_copyright); + } - if( options.withoutCopyright!==true ) - datetimepicker - .append(xdsoft_copyright); - - datepicker - .append(mounth_picker) - .append(calendar); - - $('body').append(datetimepicker); - - var _xdsoft_datetime = new function() { - var _this = this; - _this.now = function( norecursion ) { - var d = new Date(); - - if( !norecursion && options.defaultDate ){ - var date = _this.strToDate(options.defaultDate); - d.setFullYear( date.getFullYear() ); - d.setMonth( date.getMonth() ); - d.setDate( date.getDate() ); - } - - if( options.yearOffset ){ - d.setFullYear(d.getFullYear()+options.yearOffset); + datepicker + .append(mounth_picker) + .append(calendar); + + $(options.parentID) + .append(datetimepicker); + + XDSoft_datetime = function () { + var _this = this; + _this.now = function (norecursion) { + var d = new Date(), + date, + time; + + if (!norecursion && options.defaultDate) { + date = _this.strToDate(options.defaultDate); + d.setFullYear(date.getFullYear()); + d.setMonth(date.getMonth()); + d.setDate(date.getDate()); + } + + if (options.yearOffset) { + d.setFullYear(d.getFullYear() + options.yearOffset); + } + + if (!norecursion && options.defaultTime) { + time = _this.strtotime(options.defaultTime); + d.setHours(time.getHours()); + d.setMinutes(time.getMinutes()); + } + + return d; + }; + + _this.isValidDate = function (d) { + if (Object.prototype.toString.call(d) !== "[object Date]") { + return false; + } + return !isNaN(d.getTime()); + }; + + _this.setCurrentTime = function (dTime) { + _this.currentTime = (typeof dTime === 'string') ? _this.strToDateTime(dTime) : _this.isValidDate(dTime) ? dTime : _this.now(); + datetimepicker.trigger('xchange.xdsoft'); + }; + + _this.empty = function () { + _this.currentTime = null; + }; + + _this.getCurrentTime = function (dTime) { + return _this.currentTime; + }; + + _this.nextMonth = function () { + var month = _this.currentTime.getMonth() + 1, + year; + if (month === 12) { + _this.currentTime.setFullYear(_this.currentTime.getFullYear() + 1); + month = 0; + } + + year = _this.currentTime.getFullYear(); + + _this.currentTime.setDate( + Math.min( + new Date(_this.currentTime.getFullYear(), month + 1, 0).getDate(), + _this.currentTime.getDate() + ) + ); + _this.currentTime.setMonth(month); + + if (options.onChangeMonth && $.isFunction(options.onChangeMonth)) { + options.onChangeMonth.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input')); + } + + if (year !== _this.currentTime.getFullYear() && $.isFunction(options.onChangeYear)) { + options.onChangeYear.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input')); + } + + datetimepicker.trigger('xchange.xdsoft'); + return month; + }; + + _this.prevMonth = function () { + var month = _this.currentTime.getMonth() - 1; + if (month === -1) { + _this.currentTime.setFullYear(_this.currentTime.getFullYear() - 1); + month = 11; + } + _this.currentTime.setDate( + Math.min( + new Date(_this.currentTime.getFullYear(), month + 1, 0).getDate(), + _this.currentTime.getDate() + ) + ); + _this.currentTime.setMonth(month); + if (options.onChangeMonth && $.isFunction(options.onChangeMonth)) { + options.onChangeMonth.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input')); + } + datetimepicker.trigger('xchange.xdsoft'); + return month; + }; + + _this.getWeekOfYear = function (datetime) { + var onejan = new Date(datetime.getFullYear(), 0, 1); + return Math.ceil((((datetime - onejan) / 86400000) + onejan.getDay() + 1) / 7); + }; + + _this.strToDateTime = function (sDateTime) { + var tmpDate = [], timeOffset, currentTime; + + if (sDateTime && sDateTime instanceof Date && _this.isValidDate(sDateTime)) { + return sDateTime; + } + + tmpDate = /^(\+|\-)(.*)$/.exec(sDateTime); + if (tmpDate) { + tmpDate[2] = Date.parseDate(tmpDate[2], options.formatDate); + } + if (tmpDate && tmpDate[2]) { + timeOffset = tmpDate[2].getTime() - (tmpDate[2].getTimezoneOffset()) * 60000; + currentTime = new Date((_xdsoft_datetime.now()).getTime() + parseInt(tmpDate[1] + '1', 10) * timeOffset); + } else { + currentTime = sDateTime ? Date.parseDate(sDateTime, options.format) : _this.now(); + } + + if (!_this.isValidDate(currentTime)) { + currentTime = _this.now(); + } + + return currentTime; + }; + + _this.strToDate = function (sDate) { + if (sDate && sDate instanceof Date && _this.isValidDate(sDate)) { + return sDate; + } + + var currentTime = sDate ? Date.parseDate(sDate, options.formatDate) : _this.now(true); + if (!_this.isValidDate(currentTime)) { + currentTime = _this.now(true); + } + return currentTime; + }; + + _this.strtotime = function (sTime) { + if (sTime && sTime instanceof Date && _this.isValidDate(sTime)) { + return sTime; + } + var currentTime = sTime ? Date.parseDate(sTime, options.formatTime) : _this.now(true); + if (!_this.isValidDate(currentTime)) { + currentTime = _this.now(true); + } + return currentTime; + }; + + _this.str = function () { + return _this.currentTime.dateFormat(options.format); + }; + _this.currentTime = this.now(); + }; + + _xdsoft_datetime = new XDSoft_datetime(); + + mounth_picker + .find('.xdsoft_today_button') + .on('mousedown.xdsoft', function () { + datetimepicker.data('changed', true); + _xdsoft_datetime.setCurrentTime(0); + datetimepicker.trigger('afterOpen.xdsoft'); + }).on('dblclick.xdsoft', function () { + input.val(_xdsoft_datetime.str()); + datetimepicker.trigger('close.xdsoft'); + }); + mounth_picker + .find('.xdsoft_prev,.xdsoft_next') + .on('mousedown.xdsoft', function () { + var $this = $(this), + timer = 0, + stop = false; + + (function arguments_callee1(v) { + var month = _xdsoft_datetime.currentTime.getMonth(); + if ($this.hasClass(options.next)) { + _xdsoft_datetime.nextMonth(); + } else if ($this.hasClass(options.prev)) { + _xdsoft_datetime.prevMonth(); } - - if( !norecursion && options.defaultTime ){ - var time = _this.strtotime(options.defaultTime); - d.setHours( time.getHours() ); - d.setMinutes( time.getMinutes() ); + if (options.monthChangeSpinner) { + if (!stop) { + timer = setTimeout(arguments_callee1, v || 100); + } } - - return d; - }; + }(500)); - - _this.isValidDate = function (d) { - if ( Object.prototype.toString.call(d) !== "[object Date]" ) - return false; - return !isNaN(d.getTime()); - }; - - _this.setCurrentTime = function( dTime ) { - _this.currentTime = (typeof dTime == 'string')? _this.strToDateTime(dTime) : _this.isValidDate(dTime) ? dTime: _this.now(); - datetimepicker.trigger('xchange.xdsoft'); - }; - - _this.empty = function() { - _this.currentTime = null; - }; - - _this.getCurrentTime = function( dTime) { - return _this.currentTime; - }; - - _this.nextMonth = function() { - var month = _this.currentTime.getMonth()+1; - if( month==12 ) { - _this.currentTime.setFullYear(_this.currentTime.getFullYear()+1); - month = 0; + $([document.body, window]).on('mouseup.xdsoft', function arguments_callee2() { + clearTimeout(timer); + stop = true; + $([document.body, window]).off('mouseup.xdsoft', arguments_callee2); + }); + }); + + timepicker + .find('.xdsoft_prev,.xdsoft_next') + .on('mousedown.xdsoft', function () { + var $this = $(this), + timer = 0, + stop = false, + period = 110; + (function arguments_callee4(v) { + var pheight = timeboxparent[0].clientHeight, + height = timebox[0].offsetHeight, + top = Math.abs(parseInt(timebox.css('marginTop'), 10)); + if ($this.hasClass(options.next) && (height - pheight) - options.timeHeightInTimePicker >= top) { + timebox.css('marginTop', '-' + (top + options.timeHeightInTimePicker) + 'px'); + } else if ($this.hasClass(options.prev) && top - options.timeHeightInTimePicker >= 0) { + timebox.css('marginTop', '-' + (top - options.timeHeightInTimePicker) + 'px'); } - _this.currentTime.setDate( - Math.min( - // Day 0 is the last day in the previous month, but we want to know the number of days in the current month, so we need to evaluate the subsequent month (month+1) - new Date(_this.currentTime.getFullYear(), month+1, 0).getDate(), - _this.currentTime.getDate() - ) - ); - _this.currentTime.setMonth(month); - options.onChangeMonth&&options.onChangeMonth.call&&options.onChangeMonth.call(datetimepicker,_xdsoft_datetime.currentTime,datetimepicker.data('input')); - datetimepicker.trigger('xchange.xdsoft'); - return month; - }; - - _this.prevMonth = function() { - var month = _this.currentTime.getMonth()-1; - if( month==-1 ) { - _this.currentTime.setFullYear(_this.currentTime.getFullYear()-1); - month = 11; + timeboxparent.trigger('scroll_element.xdsoft_scroller', [Math.abs(parseInt(timebox.css('marginTop'), 10) / (height - pheight))]); + period = (period > 10) ? 10 : period - 10; + if (!stop) { + timer = setTimeout(arguments_callee4, v || period); } - _this.currentTime.setDate( - Math.min( - // Day 0 is the last day in the previous month, but we want to know the number of days in the current month, so we need to evaluate the subsequent month (month+1) - new Date(_this.currentTime.getFullYear(), month+1, 0).getDate(), - _this.currentTime.getDate() - ) - ); - _this.currentTime.setMonth(month); - options.onChangeMonth&&options.onChangeMonth.call&&options.onChangeMonth.call(datetimepicker,_xdsoft_datetime.currentTime,datetimepicker.data('input')); - datetimepicker.trigger('xchange.xdsoft'); - return month; - }; - - _this.strToDateTime = function( sDateTime ) { - if( sDateTime && sDateTime instanceof Date && _this.isValidDate(sDateTime) ) - return sDateTime; - - var tmpDate = [],timeOffset,currentTime; - - if( ( tmpDate = /^(\+|\-)(.*)$/.exec(sDateTime) ) && ( tmpDate[2]=Date.parseDate(tmpDate[2], options.formatDate) ) ) { - timeOffset = tmpDate[2].getTime()-(tmpDate[2].getTimezoneOffset())*60000; - currentTime = new Date((_xdsoft_datetime.now()).getTime()+parseInt(tmpDate[1]+'1')*timeOffset); - }else - currentTime = sDateTime?Date.parseDate(sDateTime, options.format):_this.now(); - - if( !_this.isValidDate(currentTime) ) - currentTime = _this.now(); - - return currentTime; - }; - - _this.strToDate = function( sDate ) { - if( sDate && sDate instanceof Date && _this.isValidDate(sDate) ) - return sDate; - - var currentTime = sDate?Date.parseDate(sDate, options.formatDate):_this.now(true); - if( !_this.isValidDate(currentTime) ) - currentTime = _this.now(true); - - return currentTime; - }; - - _this.strtotime = function( sTime ) { - if( sTime && sTime instanceof Date && _this.isValidDate(sTime) ) - return sTime; - - var currentTime = sTime?Date.parseDate(sTime, options.formatTime):_this.now(); - if( !_this.isValidDate(currentTime) ) - currentTime = _this.now(true); - - return currentTime; - }; - - _this.str = function() { - return _this.currentTime.dateFormat(options.format); - }; - - _this.currentTime = this.now(); - }; - mounth_picker - .find('.xdsoft_today_button') - .on('mousedown.xdsoft',function() { - datetimepicker.data('changed',true); - _xdsoft_datetime.setCurrentTime(0); - datetimepicker.trigger('afterOpen.xdsoft'); - }).on('dblclick.xdsoft',function(){ - input.val( _xdsoft_datetime.str() ); - datetimepicker.trigger('close.xdsoft'); - }); - mounth_picker - .find('.xdsoft_prev,.xdsoft_next') - .on('mousedown.xdsoft',function() { - var $this = $(this), - timer = 0, - stop = false; - - (function arguments_callee1(v) { - var month = _xdsoft_datetime.currentTime.getMonth(); - if( $this.hasClass( options.next ) ) { - _xdsoft_datetime.nextMonth(); - }else if( $this.hasClass( options.prev ) ) { - _xdsoft_datetime.prevMonth(); - } - if (options.monthChangeSpinner) { - !stop&&(timer = setTimeout(arguments_callee1,v?v:100)); - } - })(500); + }(500)); + $([document.body, window]).on('mouseup.xdsoft', function arguments_callee5() { + clearTimeout(timer); + stop = true; + $([document.body, window]) + .off('mouseup.xdsoft', arguments_callee5); + }); + }); - $([document.body,window]).on('mouseup.xdsoft',function arguments_callee2() { - clearTimeout(timer); - stop = true; - $([document.body,window]).off('mouseup.xdsoft',arguments_callee2); - }); - }); + xchangeTimer = 0; + // base handler - generating a calendar and timepicker + datetimepicker + .on('xchange.xdsoft', function (event) { + clearTimeout(xchangeTimer); + xchangeTimer = setTimeout(function () { + var table = '', + start = new Date(_xdsoft_datetime.currentTime.getFullYear(), _xdsoft_datetime.currentTime.getMonth(), 1, 12, 0, 0), + i = 0, + j, + today = _xdsoft_datetime.now(), + maxDate = false, + minDate = false, + d, + y, + m, + w, + classes = [], + customDateSettings, + newRow = true, + time = '', + h = '', + line_time; + + while (start.getDay() !== options.dayOfWeekStart) { + start.setDate(start.getDate() - 1); + } - timepicker - .find('.xdsoft_prev,.xdsoft_next') - .on('mousedown.xdsoft',function() { - var $this = $(this), - timer = 0, - stop = false, - period = 110; - (function arguments_callee4(v) { - var pheight = timeboxparent[0].clientHeight, - height = timebox[0].offsetHeight, - top = Math.abs(parseInt(timebox.css('marginTop'))); - if( $this.hasClass(options.next) && (height-pheight)- options.timeHeightInTimePicker>=top ) { - timebox.css('marginTop','-'+(top+options.timeHeightInTimePicker)+'px') - }else if( $this.hasClass(options.prev) && top-options.timeHeightInTimePicker>=0 ) { - timebox.css('marginTop','-'+(top-options.timeHeightInTimePicker)+'px') - } - timeboxparent.trigger('scroll_element.xdsoft_scroller',[Math.abs(parseInt(timebox.css('marginTop'))/(height-pheight))]); - period= ( period>10 )?10:period-10; - !stop&&(timer = setTimeout(arguments_callee4,v?v:period)); - })(500); - $([document.body,window]).on('mouseup.xdsoft',function arguments_callee5() { - clearTimeout(timer); - stop = true; - $([document.body,window]) - .off('mouseup.xdsoft',arguments_callee5); - }); - }); + table += ''; - var xchangeTimer = 0; - // base handler - generating a calendar and timepicker - datetimepicker - .on('xchange.xdsoft',function( event ) { - clearTimeout(xchangeTimer); - xchangeTimer = setTimeout(function(){ - var table = '', - start = new Date(_xdsoft_datetime.currentTime.getFullYear(),_xdsoft_datetime.currentTime.getMonth(),1, 12, 0, 0), - i = 0, - today = _xdsoft_datetime.now(); - - while( start.getDay()!=options.dayOfWeekStart ) - start.setDate(start.getDate()-1); - - //generate calendar - table+='
'; - - if(options.weeks) { - table+=''; - } + if (options.weeks) { + table += ''; + } - // days - for(var j = 0; j<7; j++) { - table+=''; - } + for (j = 0; j < 7; j += 1) { + table += ''; + } - table+=''; - table+=''; - var maxDate = false, minDate = false; - - if( options.maxDate!==false ) { - maxDate = _xdsoft_datetime.strToDate(options.maxDate); - maxDate = new Date(maxDate.getFullYear(),maxDate.getMonth(),maxDate.getDate(),23,59,59,999); - } - - if( options.minDate!==false ) { - minDate = _xdsoft_datetime.strToDate(options.minDate); - minDate = new Date(minDate.getFullYear(),minDate.getMonth(),minDate.getDate()); - } - - var d,y,m,w,classes = [],customDateSettings,newRow=true; - - while( i<_xdsoft_datetime.currentTime.countDaysInMonth()||start.getDay()!=options.dayOfWeekStart||_xdsoft_datetime.currentTime.getMonth()==start.getMonth() ) { - classes = []; - i++; + table += ''; + table += ''; - d = start.getDate(); y = start.getFullYear(); m = start.getMonth(); w = start.getWeekOfYear(); + if (options.maxDate !== false) { + maxDate = _xdsoft_datetime.strToDate(options.maxDate); + maxDate = new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate(), 23, 59, 59, 999); + } - classes.push('xdsoft_date'); + if (options.minDate !== false) { + minDate = _xdsoft_datetime.strToDate(options.minDate); + minDate = new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate()); + } - if ( options.beforeShowDay && options.beforeShowDay.call ) { - customDateSettings = options.beforeShowDay.call(datetimepicker, start); - } else { - customDateSettings = null; - } + while (i < _xdsoft_datetime.currentTime.countDaysInMonth() || start.getDay() !== options.dayOfWeekStart || _xdsoft_datetime.currentTime.getMonth() === start.getMonth()) { + classes = []; + i += 1; - if( ( maxDate!==false && start > maxDate )||( minDate!==false && start < minDate )||(customDateSettings && customDateSettings[0] === false) ){ - classes.push('xdsoft_disabled'); - } + d = start.getDate(); + y = start.getFullYear(); + m = start.getMonth(); + w = _xdsoft_datetime.getWeekOfYear(start); - if ( customDateSettings && customDateSettings[1] != "" ) { - classes.push(customDateSettings[1]); - } + classes.push('xdsoft_date'); - if( _xdsoft_datetime.currentTime.getMonth()!=m ) classes.push('xdsoft_other_month'); + if (options.beforeShowDay && $.isFunction(options.beforeShowDay.call)) { + customDateSettings = options.beforeShowDay.call(datetimepicker, start); + } else { + customDateSettings = null; + } - if( (options.defaultSelect||datetimepicker.data('changed')) && _xdsoft_datetime.currentTime.dateFormat( options.formatDate )==start.dateFormat( options.formatDate ) ) { - classes.push('xdsoft_current'); - } + if ((maxDate !== false && start > maxDate) || (minDate !== false && start < minDate) || (customDateSettings && customDateSettings[0] === false)) { + classes.push('xdsoft_disabled'); + } else if (options.disabledDates.indexOf(start.dateFormat(options.formatDate)) !== -1) { + classes.push('xdsoft_disabled'); + } - if( today.dateFormat( options.formatDate )==start.dateFormat( options.formatDate ) ) { - classes.push('xdsoft_today'); - } + if (customDateSettings && customDateSettings[1] !== "") { + classes.push(customDateSettings[1]); + } - if( start.getDay()==0||start.getDay()==6||~options.weekends.indexOf(start.dateFormat( options.formatDate )) ) { - classes.push('xdsoft_weekend'); - } + if (_xdsoft_datetime.currentTime.getMonth() !== m) { + classes.push('xdsoft_other_month'); + } - if(options.beforeShowDay && typeof options.beforeShowDay == 'function') { - classes.push(options.beforeShowDay(start)) - } + if ((options.defaultSelect || datetimepicker.data('changed')) && _xdsoft_datetime.currentTime.dateFormat(options.formatDate) === start.dateFormat(options.formatDate)) { + classes.push('xdsoft_current'); + } - if(newRow) { - table+=''; - newRow = false; - - if(options.weeks) { - table+=''; - } - } + if (today.dateFormat(options.formatDate) === start.dateFormat(options.formatDate)) { + classes.push('xdsoft_today'); + } - table+=''; + if (start.getDay() === 0 || start.getDay() === 6 || options.weekends.indexOf(start.dateFormat(options.formatDate)) === -1) { + classes.push('xdsoft_weekend'); + } - if( start.getDay()==options.dayOfWeekStartPrev ) { - table+=''; - newRow = true; - } + if (options.beforeShowDay && $.isFunction(options.beforeShowDay)) { + classes.push(options.beforeShowDay(start)); + } - start.setDate(d+1); - } - table+='
'+options.i18n[options.lang].dayOfWeek[(j+options.dayOfWeekStart)%7]+'' + options.i18n[options.lang].dayOfWeek[(j + options.dayOfWeekStart) % 7] + '
'+w+''+ - '
'+d+'
'+ - '
'; - - calendar.html(table); - - mounth_picker.find('.xdsoft_label span').eq(0).text(options.i18n[options.lang].months[_xdsoft_datetime.currentTime.getMonth()]); - mounth_picker.find('.xdsoft_label span').eq(1).text(_xdsoft_datetime.currentTime.getFullYear()); - - // generate timebox - var time = '', - h = '', - m ='', - line_time = function line_time( h,m ) { - var now = _xdsoft_datetime.now(); - now.setHours(h); - h = parseInt(now.getHours()); - now.setMinutes(m); - m = parseInt(now.getMinutes()); - - classes = []; - if( (options.maxTime!==false&&_xdsoft_datetime.strtotime(options.maxTime).getTime()now.getTime())) - classes.push('xdsoft_disabled'); - if( (options.initTime||options.defaultSelect||datetimepicker.data('changed')) && parseInt(_xdsoft_datetime.currentTime.getHours())==parseInt(h)&&(options.step>59||Math[options.roundTime](_xdsoft_datetime.currentTime.getMinutes()/options.step)*options.step==parseInt(m))) { - if( options.defaultSelect||datetimepicker.data('changed')) { - classes.push('xdsoft_current'); - } else if( options.initTime ) { - classes.push('xdsoft_init_time'); - } - } - if( parseInt(today.getHours())==parseInt(h)&&parseInt(today.getMinutes())==parseInt(m)) - classes.push('xdsoft_today'); - time+= '
'+now.dateFormat(options.formatTime)+'
'; - }; - - if( !options.allowTimes || !$.isArray(options.allowTimes) || !options.allowTimes.length ) { - for( var i=0,j=0;i<(options.hours12?12:24);i++ ) { - for( j=0;j<60;j+=options.step ) { - h = (i<10?'0':'')+i; - m = (j<10?'0':'')+j; - line_time( h,m ); - } - } - }else{ - for( var i=0;i'; } + } - timebox.html(time); + table += '' + + '
' + d + '
' + + ''; - var opt = '', - i = 0; + if (start.getDay() === options.dayOfWeekStartPrev) { + table += ''; + newRow = true; + } - for( i = parseInt(options.yearStart,10)+options.yearOffset;i<= parseInt(options.yearEnd,10)+options.yearOffset;i++ ) { - opt+='
'+i+'
'; + start.setDate(d + 1); + } + table += ''; + + calendar.html(table); + + mounth_picker.find('.xdsoft_label span').eq(0).text(options.i18n[options.lang].months[_xdsoft_datetime.currentTime.getMonth()]); + mounth_picker.find('.xdsoft_label span').eq(1).text(_xdsoft_datetime.currentTime.getFullYear()); + + // generate timebox + time = ''; + h = ''; + m = ''; + line_time = function line_time(h, m) { + var now = _xdsoft_datetime.now(); + now.setHours(h); + h = parseInt(now.getHours(), 10); + now.setMinutes(m); + m = parseInt(now.getMinutes(), 10); + + classes = []; + if ((options.maxTime !== false && _xdsoft_datetime.strtotime(options.maxTime).getTime() < now.getTime()) || (options.minTime !== false && _xdsoft_datetime.strtotime(options.minTime).getTime() > now.getTime())) { + classes.push('xdsoft_disabled'); + } + if ((options.initTime || options.defaultSelect || datetimepicker.data('changed')) && parseInt(_xdsoft_datetime.currentTime.getHours(), 10) === parseInt(h, 10) && (options.step > 59 || Math[options.roundTime](_xdsoft_datetime.currentTime.getMinutes() / options.step) * options.step === parseInt(m, 10))) { + if (options.defaultSelect || datetimepicker.data('changed')) { + classes.push('xdsoft_current'); + } else if (options.initTime) { + classes.push('xdsoft_init_time'); } - yearselect.children().eq(0) - .html(opt); - - for( i = 0,opt = '';i<= 11;i++ ) { - opt+='
'+options.i18n[options.lang].months[i]+'
'; + } + if (parseInt(today.getHours(), 10) === parseInt(h, 10) && parseInt(today.getMinutes(), 10) === parseInt(m, 10)) { + classes.push('xdsoft_today'); + } + time += '
' + now.dateFormat(options.formatTime) + '
'; + }; + + if (!options.allowTimes || !$.isArray(options.allowTimes) || !options.allowTimes.length) { + for (i = 0, j = 0; i < (options.hours12 ? 12 : 24); i += 1) { + for (j = 0; j < 60; j += options.step) { + h = (i < 10 ? '0' : '') + i; + m = (j < 10 ? '0' : '') + j; + line_time(h, m); } - monthselect.children().eq(0).html(opt); - $(datetimepicker) - .trigger('generate.xdsoft'); - },10); - event.stopPropagation(); - }) - .on('afterOpen.xdsoft',function() { - if( options.timepicker ) { - var classType; - if( timebox.find('.xdsoft_current').length ) { - classType = '.xdsoft_current'; - } else if( timebox.find('.xdsoft_init_time').length ) { - classType = '.xdsoft_init_time'; } - - if( classType ) { - var pheight = timeboxparent[0].clientHeight, - height = timebox[0].offsetHeight, - top = timebox.find(classType).index()*options.timeHeightInTimePicker+1; - if( (height-pheight)1||(options.closeOnDateSelect===true||( options.closeOnDateSelect===0&&!options.timepicker )))&&!options.inline ) { - datetimepicker.trigger('close.xdsoft'); + opt = ''; + i = 0; + + for (i = parseInt(options.yearStart, 10) + options.yearOffset; i <= parseInt(options.yearEnd, 10) + options.yearOffset; i += 1) { + opt += '
' + i + '
'; } + yearselect.children().eq(0) + .html(opt); - if( options.onSelectDate && options.onSelectDate.call ) { - options.onSelectDate.call(datetimepicker,_xdsoft_datetime.currentTime,datetimepicker.data('input')); + for (i = 0, opt = ''; i <= 11; i += 1) { + opt += '
' + options.i18n[options.lang].months[i] + '
'; } + monthselect.children().eq(0).html(opt); + $(datetimepicker) + .trigger('generate.xdsoft'); + }, 10); + event.stopPropagation(); + }) + .on('afterOpen.xdsoft', function () { + if (options.timepicker) { + var classType, pheight, height, top; + if (timebox.find('.xdsoft_current').length) { + classType = '.xdsoft_current'; + } else if (timebox.find('.xdsoft_init_time').length) { + classType = '.xdsoft_init_time'; + } + if (classType) { + pheight = timeboxparent[0].clientHeight; + height = timebox[0].offsetHeight; + top = timebox.find(classType).index() * options.timeHeightInTimePicker + 1; + if ((height - pheight) < top) { + top = height - pheight; + } + timeboxparent.trigger('scroll_element.xdsoft_scroller', [parseInt(top, 10) / (height - pheight)]); + } else { + timeboxparent.trigger('scroll_element.xdsoft_scroller', [0]); + } + } + }); - datetimepicker.data('changed',true); - datetimepicker.trigger('xchange.xdsoft'); - datetimepicker.trigger('changedatetime.xdsoft'); - setTimeout(function(){ - timerclick = 0; - },200); - }); + timerclick = 0; + calendar + .on('click.xdsoft', 'td', function (xdevent) { + xdevent.stopPropagation(); // Prevents closing of Pop-ups, Modals and Flyouts in Bootstrap + timerclick += 1; + var $this = $(this), + currentTime = _xdsoft_datetime.currentTime; + + if (currentTime === undefined || currentTime === null) { + _xdsoft_datetime.currentTime = _xdsoft_datetime.now(); + currentTime = _xdsoft_datetime.currentTime; + } - timebox - .on('click.xdsoft', 'div', function (xdevent) { - xdevent.stopPropagation(); // NAJ: Prevents closing of Pop-ups, Modals and Flyouts - var $this = $(this), - currentTime = _xdsoft_datetime.currentTime; - - if( currentTime===undefined||currentTime===null ){ - _xdsoft_datetime.currentTime = _xdsoft_datetime.now(); - currentTime = _xdsoft_datetime.currentTime; - } - - if( $this.hasClass('xdsoft_disabled') ) - return false; - currentTime.setHours($this.data('hour')); - currentTime.setMinutes($this.data('minute')); - datetimepicker.trigger('select.xdsoft',[currentTime]); + if ($this.hasClass('xdsoft_disabled')) { + return false; + } - datetimepicker.data('input').val( _xdsoft_datetime.str() ); + currentTime.setDate(1); + currentTime.setFullYear($this.data('year')); + currentTime.setMonth($this.data('month')); + currentTime.setDate($this.data('date')); - !options.inline&&datetimepicker.trigger('close.xdsoft'); + datetimepicker.trigger('select.xdsoft', [currentTime]); - if( options.onSelectTime&&options.onSelectTime.call ) { - options.onSelectTime.call(datetimepicker,_xdsoft_datetime.currentTime,datetimepicker.data('input')); - } - datetimepicker.data('changed',true); - datetimepicker.trigger('xchange.xdsoft'); - datetimepicker.trigger('changedatetime.xdsoft'); - }); + input.val(_xdsoft_datetime.str()); + if ((timerclick > 1 || (options.closeOnDateSelect === true || (options.closeOnDateSelect === 0 && !options.timepicker))) && !options.inline) { + datetimepicker.trigger('close.xdsoft'); + } + + if (options.onSelectDate && $.isFunction(options.onSelectDate)) { + options.onSelectDate.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'), xdevent); + } + + datetimepicker.data('changed', true); + datetimepicker.trigger('xchange.xdsoft'); + datetimepicker.trigger('changedatetime.xdsoft'); + setTimeout(function () { + timerclick = 0; + }, 200); + }); + + timebox + .on('click.xdsoft', 'div', function (xdevent) { + xdevent.stopPropagation(); + var $this = $(this), + currentTime = _xdsoft_datetime.currentTime; + + if (currentTime === undefined || currentTime === null) { + _xdsoft_datetime.currentTime = _xdsoft_datetime.now(); + currentTime = _xdsoft_datetime.currentTime; + } + + if ($this.hasClass('xdsoft_disabled')) { + return false; + } + currentTime.setHours($this.data('hour')); + currentTime.setMinutes($this.data('minute')); + datetimepicker.trigger('select.xdsoft', [currentTime]); - datetimepicker.mousewheel&&datepicker.mousewheel(function(event, delta, deltaX, deltaY) { - if( !options.scrollMonth ) + datetimepicker.data('input').val(_xdsoft_datetime.str()); + if (!options.inline) { + datetimepicker.trigger('close.xdsoft'); + } + + if (options.onSelectTime && $.isFunction(options.onSelectTime)) { + options.onSelectTime.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'), xdevent); + } + datetimepicker.data('changed', true); + datetimepicker.trigger('xchange.xdsoft'); + datetimepicker.trigger('changedatetime.xdsoft'); + }); + + + datepicker + .on('mousewheel.xdsoft', function (event) { + if (!options.scrollMonth) { return true; - if( delta<0 ) + } + if (event.deltaY < 0) { _xdsoft_datetime.nextMonth(); - else + } else { _xdsoft_datetime.prevMonth(); + } return false; }); - datetimepicker.mousewheel&&timeboxparent.unmousewheel().mousewheel(function(event, delta, deltaX, deltaY) { - if( !options.scrollTime ) + input + .on('mousewheel.xdsoft', function (event) { + if (!options.scrollInput) { return true; - var pheight = timeboxparent[0].clientHeight, - height = timebox[0].offsetHeight, - top = Math.abs(parseInt(timebox.css('marginTop'))), - fl = true; - if( delta<0 && (height-pheight)-options.timeHeightInTimePicker>=top ) { - timebox.css('marginTop','-'+(top+options.timeHeightInTimePicker)+'px'); - fl = false; - }else if( delta>0&&top-options.timeHeightInTimePicker>=0 ) { - timebox.css('marginTop','-'+(top-options.timeHeightInTimePicker)+'px'); - fl = false; } - timeboxparent.trigger('scroll_element.xdsoft_scroller',[Math.abs(parseInt(timebox.css('marginTop'))/(height-pheight))]); - event.stopPropagation(); - return fl; - }); - - var triggerAfterOpen = false; - datetimepicker - .on('changedatetime.xdsoft',function() { - if( options.onChangeDateTime&&options.onChangeDateTime.call ) { - var $input = datetimepicker.data('input'); - options.onChangeDateTime.call(datetimepicker, _xdsoft_datetime.currentTime, $input); - delete options.value; - $input.trigger('change'); + if (!options.datepicker && options.timepicker) { + current_time_index = timebox.find('.xdsoft_current').length ? timebox.find('.xdsoft_current').eq(0).index() : 0; + if (current_time_index + event.deltaY >= 0 && current_time_index + event.deltaY < timebox.children().length) { + current_time_index += event.deltaY; } - }) - .on('generate.xdsoft',function() { - if( options.onGenerate&&options.onGenerate.call ) - options.onGenerate.call(datetimepicker,_xdsoft_datetime.currentTime,datetimepicker.data('input')); - if( triggerAfterOpen ){ - datetimepicker.trigger('afterOpen.xdsoft'); - triggerAfterOpen = false; + if (timebox.children().eq(current_time_index).length) { + timebox.children().eq(current_time_index).trigger('mousedown'); } - }) - .on( 'click.xdsoft', function( xdevent ) - { - xdevent.stopPropagation(); // Prevents closing of Pop-ups, Modals and Flyouts in Bootstrap - }); - - var current_time_index = 0; - input.mousewheel&&input.mousewheel(function( event, delta, deltaX, deltaY ) { - if( !options.scrollInput ) - return true; - if( !options.datepicker && options.timepicker ) { - current_time_index = timebox.find('.xdsoft_current').length?timebox.find('.xdsoft_current').eq(0).index():0; - if( current_time_index+delta>=0&¤t_time_index+delta$(window).height()+$(window).scrollTop() ) - top = offset.top-datetimepicker[0].offsetHeight+1; - if (top < 0) - top = 0; - if( left+datetimepicker[0].offsetWidth>$(window).width() ) - left = offset.left-datetimepicker[0].offsetWidth+datetimepicker.data('input')[0].offsetWidth; + + datetimepicker + .on('changedatetime.xdsoft', function (event) { + if (options.onChangeDateTime && $.isFunction(options.onChangeDateTime)) { + var $input = datetimepicker.data('input'); + options.onChangeDateTime.call(datetimepicker, _xdsoft_datetime.currentTime, $input, event); + delete options.value; + $input.trigger('change'); } - datetimepicker.css({ - left:left, - top:top, - position: position - }); - }; - datetimepicker - .on('open.xdsoft', function() { - var onShow = true; - if( options.onShow&&options.onShow.call) { - onShow = options.onShow.call(datetimepicker,_xdsoft_datetime.currentTime,datetimepicker.data('input')); - } - if( onShow!==false ) { - datetimepicker.show(); - setPos(); - $(window) - .off('resize.xdsoft',setPos) - .on('resize.xdsoft',setPos); - - if( options.closeOnWithoutClick ) { - $([document.body,window]).on('mousedown.xdsoft',function arguments_callee6() { - datetimepicker.trigger('close.xdsoft'); - $([document.body,window]).off('mousedown.xdsoft',arguments_callee6); - }); - } - } - }) - .on('close.xdsoft', function( event ) { - var onClose = true; - if( options.onClose&&options.onClose.call ) { - onClose=options.onClose.call(datetimepicker,_xdsoft_datetime.currentTime,datetimepicker.data('input')); - } - if( onClose!==false&&!options.opened&&!options.inline ) { - datetimepicker.hide(); + }) + .on('generate.xdsoft', function () { + if (options.onGenerate && $.isFunction(options.onGenerate)) { + options.onGenerate.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input')); + } + if (triggerAfterOpen) { + datetimepicker.trigger('afterOpen.xdsoft'); + triggerAfterOpen = false; + } + }) + .on('click.xdsoft', function (xdevent) { + xdevent.stopPropagation(); + }); + + current_time_index = 0; + + setPos = function () { + var offset = datetimepicker.data('input').offset(), top = offset.top + datetimepicker.data('input')[0].offsetHeight - 1, left = offset.left, position = "absolute"; + if (options.fixed) { + top -= $(window).scrollTop(); + left -= $(window).scrollLeft(); + position = "fixed"; + } else { + if (top + datetimepicker[0].offsetHeight > $(window).height() + $(window).scrollTop()) { + top = offset.top - datetimepicker[0].offsetHeight + 1; + } + if (top < 0) { + top = 0; + } + if (left + datetimepicker[0].offsetWidth > $(window).width()) { + left = $(window).width() - datetimepicker[0].offsetWidth; + } + } + datetimepicker.css({ + left: left, + top: top, + position: position + }); + }; + datetimepicker + .on('open.xdsoft', function (event) { + var onShow = true; + if (options.onShow && $.isFunction(options.onShow)) { + onShow = options.onShow.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'), event); + } + if (onShow !== false) { + datetimepicker.show(); + setPos(); + $(window) + .off('resize.xdsoft', setPos) + .on('resize.xdsoft', setPos); + + if (options.closeOnWithoutClick) { + $([document.body, window]).on('mousedown.xdsoft', function arguments_callee6() { + datetimepicker.trigger('close.xdsoft'); + $([document.body, window]).off('mousedown.xdsoft', arguments_callee6); + }); } - event.stopPropagation(); - }) - .data('input',input); - - var timer = 0, - timer1 = 0; - - datetimepicker.data('xdsoft_datetime',_xdsoft_datetime); - datetimepicker.setOptions(options); - - function getCurrentValue(){ - - var ct = false; - - if ( options.startDate ) { - ct = _xdsoft_datetime.strToDate(options.startDate); - } else { - ct = options.value?options.value:(input&&input.val&&input.val())?input.val():''; - if( ct ) { - ct = _xdsoft_datetime.strToDateTime(ct); - } else if ( options.defaultDate ) { - ct = _xdsoft_datetime.strToDate(options.defaultDate); + } + }) + .on('close.xdsoft', function (event) { + var onClose = true; + mounth_picker + .find('.xdsoft_month,.xdsoft_year') + .find('.xdsoft_select') + .hide(); + if (options.onClose && $.isFunction(options.onClose)) { + onClose = options.onClose.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'), event); + } + if (onClose !== false && !options.opened && !options.inline) { + datetimepicker.hide(); + } + event.stopPropagation(); + }) + .on('toggle.xdsoft', function (event) { + if (datetimepicker.is(':visible')) { + datetimepicker.trigger('close.xdsoft'); + } else { + datetimepicker.trigger('open.xdsoft'); + } + }) + .data('input', input); + + timer = 0; + timer1 = 0; + + datetimepicker.data('xdsoft_datetime', _xdsoft_datetime); + datetimepicker.setOptions(options); + + function getCurrentValue() { + + var ct = false, time; + + if (options.startDate) { + ct = _xdsoft_datetime.strToDate(options.startDate); + } else { + ct = options.value || ((input && input.val && input.val()) ? input.val() : ''); + if (ct) { + ct = _xdsoft_datetime.strToDateTime(ct); + } else if (options.defaultDate) { + ct = _xdsoft_datetime.strToDate(options.defaultDate); + if (options.defaultTime) { + time = _xdsoft_datetime.strtotime(options.defaultTime); + ct.setHours(time.getHours()); + ct.setMinutes(time.getMinutes()); } - } + } + } - if ( ct && _xdsoft_datetime.isValidDate(ct) ) { - datetimepicker.data('changed',true); - } else { - ct = ''; - } - - return ct?ct:0; + if (ct && _xdsoft_datetime.isValidDate(ct)) { + datetimepicker.data('changed', true); + } else { + ct = ''; } - //debugger - _xdsoft_datetime.setCurrentTime( getCurrentValue() ); - input - .data( 'xdsoft_datetimepicker',datetimepicker ) - .on('open.xdsoft focusin.xdsoft mousedown.xdsoft',function(event) { - if( input.is(':disabled')||input.is(':hidden')||!input.is(':visible')||(input.data('xdsoft_datetimepicker').is(':visible') && options.closeOnInputClick) ) + return ct || 0; + } + + _xdsoft_datetime.setCurrentTime(getCurrentValue()); + + input + .data('xdsoft_datetimepicker', datetimepicker) + .on('open.xdsoft focusin.xdsoft mousedown.xdsoft', function (event) { + if (input.is(':disabled') || input.is(':hidden') || !input.is(':visible') || (input.data('xdsoft_datetimepicker').is(':visible') && options.closeOnInputClick)) { + return; + } + clearTimeout(timer); + timer = setTimeout(function () { + if (input.is(':disabled') || input.is(':hidden') || !input.is(':visible')) { return; - clearTimeout(timer); - timer = setTimeout(function() { - if( input.is(':disabled')||input.is(':hidden')||!input.is(':visible') ) - return; - - triggerAfterOpen = true; - _xdsoft_datetime.setCurrentTime(getCurrentValue()); - - datetimepicker.trigger('open.xdsoft'); - },100); - }) - .on('keydown.xdsoft',function( event ) { - var val = this.value, - key = event.which; - switch(true) { - case !!~([ENTER].indexOf(key)): - var elementSelector = $("input:visible,textarea:visible"); - datetimepicker.trigger('close.xdsoft'); - elementSelector.eq(elementSelector.index(this) + 1).focus(); - return false; - case !!~[TAB].indexOf(key): - datetimepicker.trigger('close.xdsoft'); - return true; } - }); - }, - destroyDateTimePicker = function( input ) { - var datetimepicker = input.data('xdsoft_datetimepicker'); - if( datetimepicker ) { - datetimepicker.data('xdsoft_datetime',null); - datetimepicker.remove(); - input - .data( 'xdsoft_datetimepicker',null ) - .off( 'open.xdsoft focusin.xdsoft focusout.xdsoft mousedown.xdsoft blur.xdsoft keydown.xdsoft' ); - $(window).off('resize.xdsoft'); - $([window,document.body]).off('mousedown.xdsoft'); - input.unmousewheel&&input.unmousewheel(); + + triggerAfterOpen = true; + _xdsoft_datetime.setCurrentTime(getCurrentValue()); + + datetimepicker.trigger('open.xdsoft'); + }, 100); + }) + .on('keydown.xdsoft', function (event) { + var val = this.value, elementSelector, + key = event.which; + if ([ENTER].indexOf(key) !== -1 && options.enterLikeTab) { + elementSelector = $("input:visible,textarea:visible"); + datetimepicker.trigger('close.xdsoft'); + elementSelector.eq(elementSelector.index(this) + 1).focus(); + return false; + } + if ([TAB].indexOf(key) !== -1) { + datetimepicker.trigger('close.xdsoft'); + return true; + } + }); + }; + destroyDateTimePicker = function (input) { + var datetimepicker = input.data('xdsoft_datetimepicker'); + if (datetimepicker) { + datetimepicker.data('xdsoft_datetime', null); + datetimepicker.remove(); + input + .data('xdsoft_datetimepicker', null) + .off('.xdsoft'); + $(window).off('resize.xdsoft'); + $([window, document.body]).off('mousedown.xdsoft'); + if (input.unmousewheel) { + input.unmousewheel(); } - }; + } + }; $(document) .off('keydown.xdsoftctrl keyup.xdsoftctrl') - .on('keydown.xdsoftctrl',function(e) { - if ( e.keyCode == CTRLKEY ) + .on('keydown.xdsoftctrl', function (e) { + if (e.keyCode === CTRLKEY) { ctrlDown = true; + } }) - .on('keyup.xdsoftctrl',function(e) { - if ( e.keyCode == CTRLKEY ) + .on('keyup.xdsoftctrl', function (e) { + if (e.keyCode === CTRLKEY) { ctrlDown = false; + } }); - return this.each(function() { - var datetimepicker; - if( datetimepicker = $(this).data('xdsoft_datetimepicker') ) { - if( $.type(opt) === 'string' ) { - switch(opt) { - case 'show': - $(this).select().focus(); - datetimepicker.trigger( 'open.xdsoft' ); + return this.each(function () { + var datetimepicker = $(this).data('xdsoft_datetimepicker'); + if (datetimepicker) { + if ($.type(opt) === 'string') { + switch (opt) { + case 'show': + $(this).select().focus(); + datetimepicker.trigger('open.xdsoft'); break; - case 'hide': - datetimepicker.trigger('close.xdsoft'); + case 'hide': + datetimepicker.trigger('close.xdsoft'); break; - case 'destroy': - destroyDateTimePicker($(this)); + case 'toggle': + datetimepicker.trigger('toggle.xdsoft'); break; - case 'reset': - this.value = this.defaultValue; - if(!this.value || !datetimepicker.data('xdsoft_datetime').isValidDate(Date.parseDate(this.value, options.format))) - datetimepicker.data('changed',false); - datetimepicker.data('xdsoft_datetime').setCurrentTime(this.value); + case 'destroy': + destroyDateTimePicker($(this)); + break; + case 'reset': + this.value = this.defaultValue; + if (!this.value || !datetimepicker.data('xdsoft_datetime').isValidDate(Date.parseDate(this.value, options.format))) { + datetimepicker.data('changed', false); + } + datetimepicker.data('xdsoft_datetime').setCurrentTime(this.value); break; } - }else{ + } else { datetimepicker .setOptions(opt); } return 0; - }else - if( ($.type(opt) !== 'string') ){ - if( !options.lazyInit||options.open||options.inline ){ - createDateTimePicker($(this)); - }else - lazyInit($(this)); + } + if ($.type(opt) !== 'string') { + if (!options.lazyInit || options.open || options.inline) { + createDateTimePicker($(this)); + } else { + lazyInit($(this)); } + } }); }; $.fn.datetimepicker.defaults = default_options; -})( jQuery ); +}(jQuery)); +(function () { -/* - * Copyright (c) 2013 Brandon Aaron (http://brandonaaron.net) - * +/*! Copyright (c) 2013 Brandon Aaron (http://brandon.aaron.sh) * Licensed under the MIT License (LICENSE.txt). * - * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers. - * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix. - * Thanks to: Seamus Leahy for adding deltaX and deltaY + * Version: 3.1.12 * - * Version: 3.1.3 - * - * Requires: 1.2.2+ + * Requires: jQuery 1.2.2+ */ -(function(factory) {if(typeof define==='function'&&define.amd) {define(['jquery'],factory)}else if(typeof exports==='object') {module.exports=factory}else{factory(jQuery)}}(function($) {var toFix=['wheel','mousewheel','DOMMouseScroll','MozMousePixelScroll'];var toBind='onwheel'in document||document.documentMode>=9?['wheel']:['mousewheel','DomMouseScroll','MozMousePixelScroll'];var lowestDelta,lowestDeltaXY;if($.event.fixHooks) {for(var i=toFix.length;i;) {$.event.fixHooks[toFix[--i]]=$.event.mouseHooks}}$.event.special.mousewheel={setup:function() {if(this.addEventListener) {for(var i=toBind.length;i;) {this.addEventListener(toBind[--i],handler,false)}}else{this.onmousewheel=handler}},teardown:function() {if(this.removeEventListener) {for(var i=toBind.length;i;) {this.removeEventListener(toBind[--i],handler,false)}}else{this.onmousewheel=null}}};$.fn.extend({mousewheel:function(fn) {return fn?this.bind("mousewheel",fn):this.trigger("mousewheel")},unmousewheel:function(fn) {return this.unbind("mousewheel",fn)}});function handler(event) {var orgEvent=event||window.event,args=[].slice.call(arguments,1),delta=0,deltaX=0,deltaY=0,absDelta=0,absDeltaXY=0,fn;event=$.event.fix(orgEvent);event.type="mousewheel";if(orgEvent.wheelDelta) {delta=orgEvent.wheelDelta}if(orgEvent.detail) {delta=orgEvent.detail*-1}if(orgEvent.deltaY) {deltaY=orgEvent.deltaY*-1;delta=deltaY}if(orgEvent.deltaX) {deltaX=orgEvent.deltaX;delta=deltaX*-1}if(orgEvent.wheelDeltaY!==undefined) {deltaY=orgEvent.wheelDeltaY}if(orgEvent.wheelDeltaX!==undefined) {deltaX=orgEvent.wheelDeltaX*-1}absDelta=Math.abs(delta);if(!lowestDelta||absDelta0?'floor':'ceil';delta=Math[fn](delta/lowestDelta);deltaX=Math[fn](deltaX/lowestDeltaXY);deltaY=Math[fn](deltaY/lowestDeltaXY);args.unshift(event,delta,deltaX,deltaY);return($.event.dispatch||$.event.handle).apply(this,args)}})); - +!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a:a(jQuery)}(function(a){function b(b){var g=b||window.event,h=i.call(arguments,1),j=0,l=0,m=0,n=0,o=0,p=0;if(b=a.event.fix(g),b.type="mousewheel","detail"in g&&(m=-1*g.detail),"wheelDelta"in g&&(m=g.wheelDelta),"wheelDeltaY"in g&&(m=g.wheelDeltaY),"wheelDeltaX"in g&&(l=-1*g.wheelDeltaX),"axis"in g&&g.axis===g.HORIZONTAL_AXIS&&(l=-1*m,m=0),j=0===m?l:m,"deltaY"in g&&(m=-1*g.deltaY,j=m),"deltaX"in g&&(l=g.deltaX,0===m&&(j=-1*l)),0!==m||0!==l){if(1===g.deltaMode){var q=a.data(this,"mousewheel-line-height");j*=q,m*=q,l*=q}else if(2===g.deltaMode){var r=a.data(this,"mousewheel-page-height");j*=r,m*=r,l*=r}if(n=Math.max(Math.abs(m),Math.abs(l)),(!f||f>n)&&(f=n,d(g,n)&&(f/=40)),d(g,n)&&(j/=40,l/=40,m/=40),j=Math[j>=1?"floor":"ceil"](j/f),l=Math[l>=1?"floor":"ceil"](l/f),m=Math[m>=1?"floor":"ceil"](m/f),k.settings.normalizeOffset&&this.getBoundingClientRect){var s=this.getBoundingClientRect();o=b.clientX-s.left,p=b.clientY-s.top}return b.deltaX=l,b.deltaY=m,b.deltaFactor=f,b.offsetX=o,b.offsetY=p,b.deltaMode=0,h.unshift(b,j,l,m),e&&clearTimeout(e),e=setTimeout(c,200),(a.event.dispatch||a.event.handle).apply(this,h)}}function c(){f=null}function d(a,b){return k.settings.adjustOldDeltas&&"mousewheel"===a.type&&b%120===0}var e,f,g=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],h="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],i=Array.prototype.slice;if(a.event.fixHooks)for(var j=g.length;j;)a.event.fixHooks[g[--j]]=a.event.mouseHooks;var k=a.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var c=h.length;c;)this.addEventListener(h[--c],b,!1);else this.onmousewheel=b;a.data(this,"mousewheel-line-height",k.getLineHeight(this)),a.data(this,"mousewheel-page-height",k.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var c=h.length;c;)this.removeEventListener(h[--c],b,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(b){var c=a(b),d=c["offsetParent"in a.fn?"offsetParent":"parent"]();return d.length||(d=a("body")),parseInt(d.css("fontSize"),10)||parseInt(c.css("fontSize"),10)||16},getPageHeight:function(b){return a(b).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})}); // Parse and Format Library //http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/ @@ -1500,3 +1846,4 @@ * details. */ Date.parseFunctions={count:0};Date.parseRegexes=[];Date.formatFunctions={count:0};Date.prototype.dateFormat=function(b){if(b=="unixtime"){return parseInt(this.getTime()/1000);}if(Date.formatFunctions[b]==null){Date.createNewFormat(b);}var a=Date.formatFunctions[b];return this[a]();};Date.createNewFormat=function(format){var funcName="format"+Date.formatFunctions.count++;Date.formatFunctions[format]=funcName;var code="Date.prototype."+funcName+" = function() {return ";var special=false;var ch="";for(var i=0;i 0) {";var regex="";var special=false;var ch="";for(var i=0;i 0 && z > 0){\nvar doyDate = new Date(y,0);\ndoyDate.setDate(z);\nm = doyDate.getMonth();\nd = doyDate.getDate();\n}";code+="if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n{return new Date(y, m, d, h, i, s);}\nelse if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n{return new Date(y, m, d, h, i);}\nelse if (y > 0 && m >= 0 && d > 0 && h >= 0)\n{return new Date(y, m, d, h);}\nelse if (y > 0 && m >= 0 && d > 0)\n{return new Date(y, m, d);}\nelse if (y > 0 && m >= 0)\n{return new Date(y, m);}\nelse if (y > 0)\n{return new Date(y);}\n}return null;}";Date.parseRegexes[regexNum]=new RegExp("^"+regex+"$");eval(code);};Date.formatCodeToRegex=function(b,a){switch(b){case"D":return{g:0,c:null,s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};case"j":case"d":return{g:1,c:"d = parseInt(results["+a+"], 10);\n",s:"(\\d{1,2})"};case"l":return{g:0,c:null,s:"(?:"+Date.dayNames.join("|")+")"};case"S":return{g:0,c:null,s:"(?:st|nd|rd|th)"};case"w":return{g:0,c:null,s:"\\d"};case"z":return{g:1,c:"z = parseInt(results["+a+"], 10);\n",s:"(\\d{1,3})"};case"W":return{g:0,c:null,s:"(?:\\d{2})"};case"F":return{g:1,c:"m = parseInt(Date.monthNumbers[results["+a+"].substring(0, 3)], 10);\n",s:"("+Date.monthNames.join("|")+")"};case"M":return{g:1,c:"m = parseInt(Date.monthNumbers[results["+a+"]], 10);\n",s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};case"n":case"m":return{g:1,c:"m = parseInt(results["+a+"], 10) - 1;\n",s:"(\\d{1,2})"};case"t":return{g:0,c:null,s:"\\d{1,2}"};case"L":return{g:0,c:null,s:"(?:1|0)"};case"Y":return{g:1,c:"y = parseInt(results["+a+"], 10);\n",s:"(\\d{4})"};case"y":return{g:1,c:"var ty = parseInt(results["+a+"], 10);\ny = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",s:"(\\d{1,2})"};case"a":return{g:1,c:"if (results["+a+"] == 'am') {\nif (h == 12) { h = 0; }\n} else { if (h < 12) { h += 12; }}",s:"(am|pm)"};case"A":return{g:1,c:"if (results["+a+"] == 'AM') {\nif (h == 12) { h = 0; }\n} else { if (h < 12) { h += 12; }}",s:"(AM|PM)"};case"g":case"G":case"h":case"H":return{g:1,c:"h = parseInt(results["+a+"], 10);\n",s:"(\\d{1,2})"};case"i":return{g:1,c:"i = parseInt(results["+a+"], 10);\n",s:"(\\d{2})"};case"s":return{g:1,c:"s = parseInt(results["+a+"], 10);\n",s:"(\\d{2})"};case"O":return{g:0,c:null,s:"[+-]\\d{4}"};case"T":return{g:0,c:null,s:"[A-Z]{3}"};case"Z":return{g:0,c:null,s:"[+-]\\d{1,5}"};default:return{g:0,c:null,s:String.escape(b)};}};Date.prototype.getTimezone=function(){return this.toString().replace(/^.*? ([A-Z]{3}) [0-9]{4}.*$/,"$1").replace(/^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/,"$1$2$3");};Date.prototype.getGMTOffset=function(){return(this.getTimezoneOffset()>0?"-":"+")+String.leftPad(Math.floor(Math.abs(this.getTimezoneOffset())/60),2,"0")+String.leftPad(Math.abs(this.getTimezoneOffset())%60,2,"0");};Date.prototype.getDayOfYear=function(){var a=0;Date.daysInMonth[1]=this.isLeapYear()?29:28;for(var b=0;b (http://xdsoft.net/)", + "license": "MIT", + "bugs": { + "url": "https://github.com/xdan/datetimepicker/issues" + }, + "homepage": "https://github.com/xdan/datetimepicker" +} diff --git a/study_buddy/static/study_buddy.js b/study_buddy/static/study_buddy.js index a891960..79b9f6e 100755 --- a/study_buddy/static/study_buddy.js +++ b/study_buddy/static/study_buddy.js @@ -12,16 +12,63 @@ var autocomplete_data = []; $(document).ready(function() { -}); + // init_geolocation_function(); + + // init_autocomplete("#search-bar"); + // init_autocomplete("#createdepartment"); + $('#datetime').datetimepicker(); + + $('#search-bar').on('input', function() { + if ($(this).val() != '') { + $('#main-search-button').attr('Value', 'Search'); + } else { + $('#main-search-button').attr('Value', 'Search All'); + } + }); + + $('#user-dropdown').hover(function() { + anchor = $(this).children()[0]; + name = $(anchor).attr('data-name'); + anchor.innerHTML = name + "'s profile"; + }, function() { + anchor = $(this).children()[0]; + name = $(anchor).attr('data-name'); + anchor.innerHTML = "Welcome, " + name; + }); + + $('.clickableRow').click(function() { + window.document.location = $(this).attr('href'); + }); -var search_page = { - create: function() { + $('.course-edit').click(function() { + window.document.location = '/find?new_find=' + $(this).attr('href'); + }); +}); +function init_geolocation_function() { + // Get location data. + if ("geolocation" in navigator) { + console.log("geolocation information available."); + var geo_success = function(position) { + console.log(position.coords.latitude + ',' + position.coords.longitude); + $('#geo_location').attr('value', position.coords.latitude + ',' + position.coords.longitude); + } + var geo_error = function() { + console.log("Could not determine location"); + } + var geo_options = { + enableHighAccuracy: true, + maximumAge: 3000, + timeout: 4500 + }; + navigator.geolocation.getCurrentPosition(geo_success, geo_error, geo_options); + } else { + console.log("Location information not available"); } } //Code that runs right after window has loaded -window.onload = function() { +function init_autocomplete(search_bar) { var data = [["AMST", "American Studies"], @@ -89,18 +136,17 @@ window.onload = function() { for (i in data) { var name_json = {}; var short_name = data[i][0]; - console.log(short_name); var long_name = data[i][1]; - console.log(long_name); name_json["label"] = short_name+"-"+long_name; autocomplete_data.push(name_json); } - $("#studysearch").autocomplete({ + $(search_bar).autocomplete({ source: autocomplete_data }); -}; + +} function parseJson(json) { @@ -111,9 +157,7 @@ function parseJson(json) { var time_of_meeting = item[TIME_TAG]; var study_location = item[LOCATION_TAG]; var list_of_partners = item[STUDY_PARTNER_TAG]; - - } - + } } // Return data in json form from url. @@ -134,7 +178,5 @@ function queryURL(url) { request.send(); } -$(function() { - $( "#datepicker" ).datepicker(); - }); + diff --git a/study_buddy/static/styles.css b/study_buddy/static/styles.css old mode 100755 new mode 100644 index 23af63e..3d78fc1 --- a/study_buddy/static/styles.css +++ b/study_buddy/static/styles.css @@ -1,244 +1,376 @@ @font-face { - font-family: josefinslab; - src: url(josefinslab-bold-webfont.woff); + font-family: josefinslab; + src: url(josefinslab-bold-webfont.woff); +} +@mixin vertical-align { + position: relative; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); } - html { - font-family: josefinslab; + font-family: bitstream-regular !important; } html, body { - height: 100%; + height: 100%; } body { - width: 100%; - background: url(resources/images/wesleyan.jpg) !important; - background-color: #E0E0D1; - background-size: cover !important; - background-repeat: no-repeat; - background-attachment: fixed; + width: 100%; + background-color: rgb(22, 160, 133); + background: linear-gradient(rgba(22, 160, 133, 0.8), rgba(22, 160, 133, 0.3)), url('resources/images/congruent_pentagon.png'); +/* background-size: cover !important; +*/ background-repeat: repeat-x repeat-y; + background-attachment: fixed; +} + +table tr td, table thead tr th { + color: #4ABA9A; +} +.time-subheader { + color: rgb(111,111,111); + font-size: 120%; + margin-bottom: 5px; +} +.center-elmt { + margin-left: auto; + margin-right: auto; +} +.center-txt { + text-align: center; +} +#search-results-container { + color: white; +} +#no-search-results { + margin: 15px 0; } - #ui-datepicker-div { - width: 20%; - text-decoration: none; - list-style-type: none; - margin-left: auto; - margin-right: auto; + width: 20%; + text-decoration: none; + list-style-type: none; + margin-left: auto; + margin-right: auto; } - /*class for centering*/ .center { - width: 100%; - text-align: center; - margin-top: 100px; + width: 100%; + text-align: center; + margin-top: 100px; } .custom-title { - font-size: 500%; - text-align: center; - margin-top: 100px; - font-weight: bold; - color: beige; - min-width: 500px; - text-shadow: 3px 3px #000000; + font-size: 500%; + text-align: center; + margin-top: 5vh; + font-weight: bold; + color: beige; } .create-forms { - margin-top: 120px; -} -.ui-helper-hidden-accessible { - visibility: hidden; -} -.ui-menu-item:hover{ - background-color: #99D6FF; -} -.ui-menu-item { - padding-left: 10px; -} -.ui-widget-content { - width: 73%; - border: 1px solid black; - color: #222222; - background-color: white; - text-decoration: none; - list-style-type: none; - margin-left: auto; - margin-right: auto; - font-size: 12px; + margin-top: 120px; } -nav.top-bar { - opacity: 0.8; +nav.top-bar section { + margin: 0 12px; } - -.top-bar-section ul { - float: right; +nav.top-bar a { + color: white; } - -.top-bar-section ul li > h1 { - width: 100%; - color: white; - font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; - font-size: 0.8125rem; - font-weight: normal; - text-transform: none; - padding-top: 11px; +nav.top-bar section a :hover { + color: rgb(22, 160, 133); } -#well { - padding-right: 14px; +.top-bar-section ul li > h1 { + width: 100%; + color: white; + font-size: 0.8125rem; + font-weight: normal; + text-transform: none; + padding-top: 11px; } -#text-background { - /*background-color: rgba(51,51,51,0.5);*/ - margin-left: 30%; - margin-right: 30%; - padding: 5px; - line-height: initial; - border-radius: 25px; - text-shadow: 3px 3px #000000; - font-family:josefinslab; -} .columns input { - width: 100% !important; + width: 100% !important; } #intro { - font-size: 200%; - text-align: center; - margin-top: 65px; - margin-bottom: 50px; - color: beige; - /*background-color: rgba(51,51,51,0.5);*/ - line-height: initial; - margin-left: 22%; - margin-right: 22%; - padding: 10px; - border-radius: 10px; - text-shadow: 2px 2px #000000; - font-family:josefinslab; + font-size: 100%; + font-family: josefinslab; + color: #fff; + /*background-color: rgba(51,51,51,0.5);*/ + line-height: 150%; + padding: 10px; + margin-top: 50px; + margin-bottom: 50px; } - #text-input { - margin-bottom: 15px; - text-align: center; - - padding-left: 8px; - padding-right: 8px; + margin-bottom: 15px; + text-align: center; + padding-left: 8px; + padding-right: 8px; } - #text-input input { - padding-top: 8px; - padding-bottom: 8px; - padding-left: 8px; - padding-right: 8px; - font-size: 25px; - margin-left: auto; - margin-right: auto; + padding-top: 8px; + padding-bottom: 8px; + padding-left: 8px; + padding-right: 8px; + font-size: 25px; + margin-left: auto; + margin-right: auto; } - - #searchresults { - width: 80%; - margin-left: 10%; + width: 80%; + margin-left: 10%; } #searchbar { - width: 20%; - float: right; - margin-right: 20%; + width: 20%; + float: right; + margin-right: 20%; } #front-page-buttons { - margin-left: auto; - margin-right: auto; - text-align: center; + margin-left: auto; + margin-right: auto; + text-align: center; } .container { - display: none; + display: none; } .click { - cursor: pointer; + cursor: pointer; } - #login-button a { - color: white; + color: white; } #login-button { - margin-left: auto; - margin-right: auto; - text-align: center; + margin-left: auto; + margin-right: auto; + text-align: center; } #button-wrapper { - width: 100%; - text-align: center; - margin-top: 100px; + width: 100%; + text-align: center; + margin-top: 100px; } #about-panel { - width: 75%; - margin-right: auto; - margin-left: auto; - margin-top: 65px; - background-color: rgba(255, 255, 255, 0.5); - font-size: 32px; + width: 75%; + margin-right: auto; + margin-left: auto; + margin-top: 65px; + background-color: rgba(255, 255, 255, 0.5); + font-size: 32px; } #about-panel p { - font-size: 20px; - margin-top: 7px; + font-size: 20px; + margin-top: 7px; } - - #course { - width: 35.5%; + width: 35.5%; } - - -#page-header{ - width:90%; - margin-top: 8%; - margin-left: 10%; - margin-bottom: none; - display: inline-block; +#page-header { + width: 90%; + margin-top: 8%; + margin-left: 10%; + margin-bottom: none; + display: inline-block; } #create-group { - width: 60%; - margin-left: auto; - margin-right: auto; + width: 60%; + margin-left: auto; + margin-right: auto; } #search-input { - width: 50%; - margin-left: 10%; - display: inline-block; + width: 50%; + margin-left: 10%; + display: inline-block; } .students-table { - width: 30%; - display: inline-block; + width: 30%; + display: inline-block; } .notes { - display: inline-block; - width: 60%; - float: right; - height: 100%; - overflow: auto; + display: inline-block; + width: 60%; + float: right; + height: 100%; + overflow: auto; } /*footer stuff*/ - .footer { - margin-left: auto; - margin-right: auto; - text-shadow: 0.7px 0.7px #000000; - + margin-left: auto; + margin-right: auto; + text-shadow: 0.7px 0.7px #000000; + position: fixed; + bottom: 0; } #bot { - font-size: 16px; + font-size: 16px; + text-align: center; + color: beige; + margin-bottom: 0; +} + +#errors { + margin-top: 5%; +} + +.button { + background-color: #1676a0 !important; +} +.header { + color: #FFFFFF !important; +} +.subheader { + color: #CDCDCD !important; +} + +.top-bar, .top-bar-section a, .top-bar-section li { + background-color: rgba(22, 118, 160, 1) !important; +} + +.remove-icon { + float: right; +} + +.remove-icon :hover { + cursor: pointer; +} + +.info-card { + background-color: rgba(255, 255, 255, 0.7); + margin-top: 100px !important; + margin: auto; + padding: 15px; + /*border-radius: 10px;*/ +} + +#reset-card { + width: 35%; +} + +.info-card h2, h3 { + color: #4aba9a; +} + +.course { + margin: 4px 0; + color: rgb(111, 111, 111); +} + +.course :hover { + color: #4aba9a; + cursor: pointer; +} + +.remove-icon { + background-color: rgba(0,0,0,0); + border-color: #1676a0; + color: #1676a0; +} + + +.flashes { + width: 35%; + margin: auto; + position: relative; + top: 40px; + list-style: none; + background-color: rgba(255, 255, 255, 0.7); + border-radius: 5px; + padding: 12px 0; + padding-left: 16px; + text-align: center; + color: #236E90; +} + +.errors { + color: #FA9F22; + margin: 0 auto 10 auto; + list-style: none; + background-color: rgba(255, 255, 255, 0.7); + border-radius: 5px; + padding: 8px 0; + padding-left: 16px; +} + +.top-bar-section .divider { + border-top: solid 2px #3587AB; /*#044A68;*/ +} + +.top-bar-section li :hover { + background-color: rgb(4, 74, 104) !important; +} + +#four-o-four { + font-size: 250pt; + line-height: 100% !important; + margin-bottom: 82px; + height: 200px; +} +.clickableRow :hover{ + cursor:pointer; +} + +.aboutheading{ text-align: center; - color: beige; - margin-bottom: 0; } -.wrapper { - min-height: 95%; - height: auto !important; - height: 95%; - margin: ;0 - 0 auto -2em; +.circular { + width: 200px; + height: 200px; + max-height: 200px; + border-radius: 150px; + -webkit-border-radius: 150px; + -moz-border-radius: 150px; +} + +.group-content { + max-width: 45%; +} + +#login-page, #register-page { + width: 35%; +} + +#about-content { + width: 80%; + margin-bottom: 30px; + color: beige; +} + +#logo-container { + margin:auto; + width: 480px; } -.footer, .push { - height: 2em; + + +#about-content > div { + margin-bottom: 45px; +} + +.about-card { + background-color: rgba(255, 255, 255, 0.7); + /*border-radius: 10px;*/ +} + +.about-row { + margin-top: 20px; +} + +.about-title-name { + color: beige; + font-weight: 500; + font-size: 36px; +} + +.about-title-position { + color: white; + font-weight: 200; + font-size: 24px; +} + +#reverify-text { + text-align: center; + margin-top: 100; + font-size: 64; + color: white; + font-weight: bold; } diff --git a/study_buddy/templates/404.html b/study_buddy/templates/404.html new file mode 100644 index 0000000..663a749 --- /dev/null +++ b/study_buddy/templates/404.html @@ -0,0 +1,15 @@ + + + Are you lost? + + + + + +
404
+

Not all who wonder are lost...

+

But you are!

+

Go back to Succor

+ + + diff --git a/study_buddy/templates/_macros.html b/study_buddy/templates/_macros.html index 1b8b6a9..01a18b8 100644 --- a/study_buddy/templates/_macros.html +++ b/study_buddy/templates/_macros.html @@ -1,11 +1,52 @@ -{% macro render_field(field) %} - {{ field.label }} +{% macro render_field(field, is_hidden=False) %} + {% if not is_hidden: %} +
{{ field.label }}
+ {% endif %} +
{{ field(**kwargs)|safe }} {% if field.errors %} -
    +
      {% for error in field.errors %}
    • {{ error }}
    • {% endfor %}
    {% endif %} - {{ field(**kwargs)|safe }} -{% endmacro %} \ No newline at end of file +
+{% endmacro %} + +{% macro render_about_card_left(data) %} +
+
+
+
+ + {{ data['name'] }} + + + {{ data['position'] }} + +
+
+ {{ data['bio'] }} +
+
+{% endmacro %} + +{% macro render_about_card_right(data) %} +
+
+ + {{ data['name'] }} + + + {{ data['position'] }} + +
+
+ {{ data['bio'] }} +
+
+
+
+{% endmacro %} diff --git a/study_buddy/templates/_svg.html b/study_buddy/templates/_svg.html new file mode 100644 index 0000000..7ec90bc --- /dev/null +++ b/study_buddy/templates/_svg.html @@ -0,0 +1,21 @@ +{% macro heart() %} + + + + + + + + + +{% endmacro %} \ No newline at end of file diff --git a/study_buddy/templates/about.html b/study_buddy/templates/about.html new file mode 100644 index 0000000..1f90070 --- /dev/null +++ b/study_buddy/templates/about.html @@ -0,0 +1,50 @@ +{% extends "template.html" %} +{% block title %}About{% endblock %} +{% block head %} + {{ super() }} + +{% endblock %} +{% block content %} + {% from "_macros.html" import render_about_card_left, render_about_card_right %} +
+
+ +
+
+

What is Succor?

+
+ Succor connects students to classmates who are studying for the same tests. Students can create new study groups or find existing study groups by simply searching through their classes. +
+
+
+

Our story

+
+ Katya had the Idea for Succor her freshman year. She wanted to meet more people in her classes and realized that the best way to do that is through studying with them. Succor was born out of the Wesleyan Hackathon. Katya brought the idea to us, we liked it, submitted it and it was selected . We built an initial product in a weekend and then struggled through a semester of rebuilding from the ground up to make a prettier, more robust version, which we now call Succor. +
+
+
+

Our Mission

+
+ The first thing you usually ask a new person that you meet in school is about his/her classes. We are interested in each other’s academic life, and that connection is even more special when we find out that this random person whom we’ve just met is in one of our classes. With Succor, our mission is to connect students through this dynamic. +
+
+

Our People

+
+ {{ render_about_card_left(people_data['Katya Sapozhnina']) }} +
+
+ {{ render_about_card_right(people_data['Aaron Rosen']) }} +
+
+ {{ render_about_card_left(people_data['Hora']) }} +
+
+ {{ render_about_card_right(people_data['Denise Fransisco']) }} +
+
+ {{ render_about_card_left(people_data['Aditya Gupta']) }} +
+
+{% endblock %} \ No newline at end of file diff --git a/study_buddy/templates/create.html b/study_buddy/templates/create.html index e9c1d2f..b052907 100755 --- a/study_buddy/templates/create.html +++ b/study_buddy/templates/create.html @@ -7,47 +7,62 @@ {% endblock %} +{% from '_macros.html' import render_field %} + {% block content %} -
-
-
Create a New Group
+
+
Create a New Group
+
+ {% if results %} +
+

The following error(s) occured:

+ {% for error in results %} +
  • {{error}}
  • + {% endfor %}
    -
    + {% endif %} + + + {{ render_field(form.geo_location, is_hidden=True) }}
    -
    - +
    + {{ render_field(form.department) }}
    -
    - +
    + {{ render_field(form.course_no) }}
    -
    - +
    + {{ render_field(form.datetime) }}
    -
    - +
    + {{ render_field(form.where) }}
    -
    - -
    -
    - +
    + {{ render_field(form.assignment) }}
    -
    - +
    + {{ render_field(form.details) }}
    + {% if not current_user.is_authenticated(): %} +
    +
    + {{ render_field(form.school) }} +
    +
    + {{ render_field(form.email, placeholder='Optional') }} +
    +
    + {% endif %}
    -
    -
    {% endblock %} diff --git a/study_buddy/templates/edit_user.html b/study_buddy/templates/edit_user.html new file mode 100644 index 0000000..5cb225a --- /dev/null +++ b/study_buddy/templates/edit_user.html @@ -0,0 +1,56 @@ +{% from '_macros.html' import render_field %} + +{% extends 'template.html' %} + +{% block title %}Profile{% endblock %} + +{% block content %} +
    +
    + +
    +
    Name:
    + {% if user.name.first: %} +
    + +
    + {% else: %} +
    + +
    + {% endif %} + {% if user.name.last: %} +
    + +
    + {% else: %} +
    + +
    + {% endif %} +
    +
    +
    + +
    +
    +
    + {% for class in user.classes: %} +
    +
    + {{ titleize(class) }} + +
    + + +
    +
    +
    +
    + {% endfor %} +
    + + +
    +
    +{% endblock %} \ No newline at end of file diff --git a/study_buddy/templates/email/recover.html b/study_buddy/templates/email/recover.html new file mode 100644 index 0000000..46c1251 --- /dev/null +++ b/study_buddy/templates/email/recover.html @@ -0,0 +1,371 @@ + + + + + + + + + +
    +
    + + +
    +
    + + +
    + + + + +
    + + Password Recovery +
    +
    +
    + + +
    + + + +
    +

    Uh Oh!

    +

    It looks like you forgot your password. That's okay we've got your back.

    +
    +
    + + + +
    +

    Click here to reset it.

    +
    +
    + diff --git a/study_buddy/templates/email/recover.txt b/study_buddy/templates/email/recover.txt new file mode 100644 index 0000000..516ef22 --- /dev/null +++ b/study_buddy/templates/email/recover.txt @@ -0,0 +1,5 @@ +Uh Oh! + +It looks like you forgot your password. That's okay we've got your back. + +Follow this link to reset your password: {{ url }} \ No newline at end of file diff --git a/study_buddy/templates/email/verify.html b/study_buddy/templates/email/verify.html new file mode 100644 index 0000000..fde9df5 --- /dev/null +++ b/study_buddy/templates/email/verify.html @@ -0,0 +1,401 @@ + + + + + + + + + +
    +
    + + +
    +
    + + +
    + + + + +
    + + Welcome! +
    +
    +
    + + +
    + + + +
    +

    Hi Newest Study Buddy!

    +

    Welcome to Succor, your new favorite + study tool!

    +

    You have just joined a growing social network designed by students, for students. Succor allows you to easily find groups of students in your classes who are studying the same thing that you are. Congratulations!

    + +

    With your new account you can:

    +
    • Keep track of which classes you're taking.
    • +
    • More easily search for study sessions happening around you.
    • +
    • Add some basic info about yourself
    • +
    +
    + + + +
    +

    But first! Click here to verify your account!

    +
    + +
    +
    + diff --git a/study_buddy/templates/email/verify.txt b/study_buddy/templates/email/verify.txt new file mode 100644 index 0000000..6817884 --- /dev/null +++ b/study_buddy/templates/email/verify.txt @@ -0,0 +1,21 @@ +Hi Newest Study Buddy! + +Welcome to Succor, your new favorite study tool! + +You have just joined a growing social network designed by students, for students. Succor allows you to easily find groups of students in your classes who are studying the same thing that you are. Congratulations! + +With your new account you can: + +Keep track of which classes you're taking. +More easily search for study sessions happening around you. +Add some basic info about yourself + +To finish signing up you must verify your email address by clicking {{ url }}! + +Connect with us on + +Facebook: https://www.facebook.com/WeSuccor + +Twitter: https://twitter.com/WeSuccor + +Email: succorapp@gmail.com \ No newline at end of file diff --git a/study_buddy/templates/group.html b/study_buddy/templates/group.html new file mode 100644 index 0000000..c7781f3 --- /dev/null +++ b/study_buddy/templates/group.html @@ -0,0 +1,61 @@ +{% extends "template.html" %} +{% block title %}Group{% endblock %} +{% block head %} + {{ super() }} + +{% endblock %} + +{% block content %} +
    +
    +
    +
    +

    {{ group.department }} {{ group.course_no }}

    +
    {{ output_time(group.time) }}
    +
    +
    +

    Location: {{ group.location }}

    +
    +
    +

    Description: {{ group.description }}

    +
    +
    +

    Contact: {{ group.contact_info }}

    +
    +
    +

    Details: {{ group.details }}

    +
    + Back +
    +
    +
    +
    +
    + + +
    + {% for participant in participants: %} + + {% endfor %} +
    +
    +
    +{% endblock %} \ No newline at end of file diff --git a/study_buddy/templates/index.html b/study_buddy/templates/index.html index 276a0e0..0f6a148 100644 --- a/study_buddy/templates/index.html +++ b/study_buddy/templates/index.html @@ -6,51 +6,63 @@ .important { color: #336699; } {% endblock %} - + {% block content %} -
    - -
    Study Buddy
    - -
    - Find friends to study with! +
    +
    +
    - -
    -
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    - -
    -
    -
    - +
    Succor
    +
    +
    +
    + /ˈsəkər/ [noun] assistance and support in times of hardship and distress. We bring succor to students by connecting them with study groups. [verb] give assistance or aid to. I used Succor to search and organize a study session with my classmates. I was succored, relieved of stress, and even made new friends! +
    +
    -
    -
    +
    +
    +
    +
    -
    - - - +
    +
    +
    + +
    +
    + +
    +
    -
    -
    - -
    +
    +
    -
    +
    +
    +
    +
    +
    + +
    +
    + +
    + + {% endblock %} + diff --git a/study_buddy/templates/login.html b/study_buddy/templates/login.html index 783c139..f5e5d38 100644 --- a/study_buddy/templates/login.html +++ b/study_buddy/templates/login.html @@ -2,32 +2,25 @@ {% extends 'template.html' %} -{% macro social_login(provider_id, display_name) %} -
    - -
    -{% endmacro %} +{% block title %}Login{% endblock %} {% block content %} - -
    -
    -
    - {{ form.hidden_tag() }} - {{ render_field(form.email) }} - {{ render_field(form.password) }} - - +
    + +
    + + {{ render_field(form.email) }} + {{ render_field(form.password) }} + Forgot your password? Click here. + {% if not verified: %} +
    + You haven't verified your account! Click + here to resend a verification email. +
    + {% endif %} +
    +

    +
    Don't have an account? Sign up here!
    -
    -

    OR

    -
    -
    - {{ social_login('google', 'Google' )}} - {{ social_login('facebook', 'Facebook' )}} -
    -
    {% endblock %} diff --git a/study_buddy/templates/no_email_verification.html b/study_buddy/templates/no_email_verification.html new file mode 100644 index 0000000..1583586 --- /dev/null +++ b/study_buddy/templates/no_email_verification.html @@ -0,0 +1,21 @@ + + + You couldn't be verified! + + + + + + {% from '_macros.html' import render_field %} +
    Send me a new verification link!
    +
    +
    +
    + + {{ render_field(form.email) }} +
    +

    +

    +
    + + \ No newline at end of file diff --git a/study_buddy/templates/profile.html b/study_buddy/templates/profile.html new file mode 100644 index 0000000..e316277 --- /dev/null +++ b/study_buddy/templates/profile.html @@ -0,0 +1,26 @@ +{% from '_macros.html' import render_field %} + +{% extends 'template.html' %} + +{% block title %}Profile{% endblock %} + +{% block content %} +
    +
    +
    + {% if user.name.full: %} +

    {{ user.name.full }}

    + {% else: %} + + {% endif %} +
    +
    + {% for class in user.classes: %} +
    +
    + {{ titleize(class) }} +
    +
    + {% endfor %} +
    +{% endblock %} \ No newline at end of file diff --git a/study_buddy/templates/register.html b/study_buddy/templates/register.html index a1c0bec..3e1f419 100644 --- a/study_buddy/templates/register.html +++ b/study_buddy/templates/register.html @@ -1,38 +1,23 @@ -{% from '_macros.html' import render_field %} - -{% extends 'template.html' %} - -{% macro social_register(provider_id, display_name) %} -
    - -
    -{% endmacro %} +{% extends "template.html" %} +{% block title %}Register{% endblock %} +{% block head %} + {{ super() }} + +{% endblock %} {% block content %} - -{% if login_failed %} -

    Register with your {{ provider.name }} account: {{ connection_values['display_name'] }}

    -{% endif %} -
    -
    -
    - {{ form.hidden_tag() }} - {{ render_field(form.email) }} - {{ render_field(form.password) }} - {{ render_field(form.confirm) }} - + {% from "_macros.html" import render_field %} +
    + +
    + + {{ render_field(form.email) }} + {{ render_field(form.password) }} + {{ render_field(form.confirm) }} +
    +

    - {% if not login_failed %} -
    -

    OR

    -
    -
    - {{ social_register('google', 'Google' )}} - {{ social_register('facebook', 'Facebook' )}} -
    - {% endif %} -
    {% endblock %} \ No newline at end of file diff --git a/study_buddy/templates/reset.html b/study_buddy/templates/reset.html new file mode 100644 index 0000000..06867b7 --- /dev/null +++ b/study_buddy/templates/reset.html @@ -0,0 +1,17 @@ +{% from '_macros.html' import render_field %} + +{% extends 'template.html' %} + +{% block title %}Reset Password{% endblock %} + +{% block content %} +
    +
    +
    + + {{ render_field(form.email) }} +
    +

    +

    +
    +{% endblock %} \ No newline at end of file diff --git a/study_buddy/templates/reset_with_token.html b/study_buddy/templates/reset_with_token.html new file mode 100644 index 0000000..d6ee653 --- /dev/null +++ b/study_buddy/templates/reset_with_token.html @@ -0,0 +1,17 @@ +{% from '_macros.html' import render_field %} + +{% extends 'template.html' %} + +{% block title %}Reset Password{% endblock %} + +{% block content %} +
    +
    +
    + + {{ render_field(form.password) }} +
    +

    +

    +
    +{% endblock %} \ No newline at end of file diff --git a/study_buddy/templates/search_results.html b/study_buddy/templates/search_results.html index 5966eaf..665f8bd 100755 --- a/study_buddy/templates/search_results.html +++ b/study_buddy/templates/search_results.html @@ -7,77 +7,90 @@ {% endblock %} {% block content %} -