├── docs └── 2b.png ├── percentage ├── index__.html └── index.html ├── .gitignore ├── requirements.txt ├── appengine_config.py ├── css ├── footer.css ├── main.css └── bootstrap-select.min.css ├── db.py ├── app.yaml ├── index.yaml ├── js ├── urlparam.js ├── chart.js ├── bootstrap-select.min.js ├── calculator.js ├── bootstrap.min.js └── allSubjects.js ├── README.md ├── main.py └── LICENSE /docs/2b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NSITulator/NSITulatorWeb/HEAD/docs/2b.png -------------------------------------------------------------------------------- /percentage/index__.html: -------------------------------------------------------------------------------- 1 | 2 | There was a glitch in the calculator. Working on a fix. 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | # don't include third-party dependencies. 3 | lib/ 4 | !lib/README.md 5 | .DS_Store 6 | percentage/server.js 7 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # This requirements file lists all third-party dependencies for this project. 2 | # 3 | # Run 'pip install -r requirements.txt -t lib/' to install these dependencies 4 | # in `lib/` subdirectory. 5 | # 6 | # Note: The `lib` directory is added to `sys.path` by `appengine_config.py`. 7 | Flask==1.0 8 | -------------------------------------------------------------------------------- /appengine_config.py: -------------------------------------------------------------------------------- 1 | """`appengine_config` gets loaded when starting a new application instance.""" 2 | 3 | import sys 4 | import os.path 5 | # add `lib` subdirectory to `sys.path`, so our `main` module can load 6 | # third-party libraries. 7 | sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'lib')) 8 | 9 | -------------------------------------------------------------------------------- /css/footer.css: -------------------------------------------------------------------------------- 1 | html { 2 | position: relative; 3 | min-height: 100%; 4 | } 5 | body { 6 | /* Margin bottom by footer height */ 7 | margin-bottom: 60px; 8 | } 9 | .footer { 10 | position: absolute; 11 | bottom: 0; 12 | width: 100%; 13 | /* Set the fixed height of the footer here */ 14 | height: 60px; 15 | background-color: #f5f5f5; 16 | margin-top: 5%; 17 | } -------------------------------------------------------------------------------- /db.py: -------------------------------------------------------------------------------- 1 | from google.appengine.ext import ndb 2 | 3 | 4 | class Data(ndb.Model): 5 | num_sems = ndb.IntegerProperty() 6 | branch = ndb.StringProperty() 7 | section = ndb.IntegerProperty() 8 | marks = ndb.JsonProperty() 9 | marks_string = ndb.StringProperty(indexed=False) 10 | date = ndb.DateTimeProperty(auto_now_add=True) 11 | ip_address = ndb.StringProperty() 12 | -------------------------------------------------------------------------------- /app.yaml: -------------------------------------------------------------------------------- 1 | # application: nsitpercentage 2 | # version: 1 3 | runtime: python27 4 | api_version: 1 5 | threadsafe: yes 6 | 7 | handlers: 8 | 9 | - url: /js 10 | static_dir: js 11 | 12 | - url: /css 13 | static_dir: css 14 | 15 | - url: /(.+) 16 | script: main.app 17 | 18 | - url: / 19 | static_files: percentage/index.html 20 | upload: percentage/index.html 21 | 22 | 23 | 24 | libraries: 25 | - name: jinja2 26 | version: "2.6" 27 | - name: markupsafe 28 | version: "0.15" 29 | 30 | -------------------------------------------------------------------------------- /index.yaml: -------------------------------------------------------------------------------- 1 | indexes: 2 | 3 | # AUTOGENERATED 4 | 5 | # This index.yaml is automatically updated whenever the dev_appserver 6 | # detects that a new type of query is run. If you want to manage the 7 | # index.yaml file manually, remove the above marker line (the line 8 | # saying "# AUTOGENERATED"). If you want to manage some indexes 9 | # manually, move them above the marker line. The index.yaml file is 10 | # automatically uploaded to the admin console when you next deploy 11 | # your application using appcfg.py. 12 | 13 | - kind: Data 14 | properties: 15 | - name: branch 16 | - name: num_sems 17 | - name: date 18 | -------------------------------------------------------------------------------- /js/urlparam.js: -------------------------------------------------------------------------------- 1 | function getUrlParameter(sParam) { 2 | var sPageURL = window.location.search.substring(1); 3 | var sURLVariables = sPageURL.split('&'); 4 | for (var i = 0; i < sURLVariables.length; i++) { 5 | var sParameterName = sURLVariables[i].split('='); 6 | if (sParameterName[0] == sParam) { 7 | return sParameterName[1]; 8 | } 9 | } 10 | } 11 | var numberOfSems = getUrlParameter('sems'); 12 | var branchName = getUrlParameter('branch'); 13 | if (branchName && numberOfSems) { 14 | // document.getElementById('optionsContainer').style.display = 'none'; 15 | loadForm(); 16 | } 17 | var debug = getUrlParameter('debug') || false; 18 | -------------------------------------------------------------------------------- /js/chart.js: -------------------------------------------------------------------------------- 1 | function drawChart(data) { 2 | var semesters = []; 3 | for(var i = 0; i < data[0].length; i++) semesters.push("Sem" + (i + 1)); 4 | 5 | $('#chart').highcharts({ 6 | title: { 7 | text: 'Percentage Throughout The Semesters', 8 | x: -20 //center 9 | }, 10 | xAxis: { 11 | categories: semesters 12 | }, 13 | yAxis: { 14 | plotLines: [{ 15 | value: 0, 16 | width: 1, 17 | color: '#808080' 18 | }] 19 | }, 20 | tooltip: { 21 | valueSuffix: '%' 22 | }, 23 | legend: { 24 | layout: 'vertical', 25 | align: 'right', 26 | verticalAlign: 'middle', 27 | borderWidth: 0 28 | }, 29 | series: [ 30 | { name: "Percentage", data: data[0]}, 31 | { name: "Aggregate", data: data[1] } 32 | ] 33 | }); 34 | } 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | About 2 | ===== 3 | 4 | NSITulator is a web-based tool used to calculate percentages for NSIT curriculum. 5 | 6 | Changelog 7 | ========= 8 | 9 | ## Version 2.0b 10 | 11 | Divjot Singh (COE 2012-2016) joins the new team and adds some neat features as follows : 12 | 13 | * [x] Graphical representation of percentages throughout the semesters. 14 | * [x] Better responsive UI. 15 | * [x] Cleaner layout with less scrolling required. 16 | 17 | ![Screenshot](docs/2b.png) 18 | 19 | ## Version 2.0a 20 | 21 | Udit Arora (COE 2012-2016) rewrites everything in much better way offering features like 22 | 23 | * [x] Import/Export marks. 24 | * [x] Store results in local storage of browser. 25 | * [x] Find appropriate drop subjects. 26 | * [x] Clean representation of every subject with their name, code and credits. 27 | 28 | ## Version 1.1 29 | 30 | Updated version released by Manraj Singh (ICE 2012-2016) and Anshuman Mishra (ECE 2013-2017) having improvements like: 31 | 32 | * [x] Improved user interface 33 | * [x] Revamped code 34 | * [x] Mobile friendly 35 | * [x] Clean representation of every subject with their name, code and credits 36 | 37 | You can still try it out here: http://anshuman.collegespace.in/nsitulator/ 38 | 39 | ## Version 1.0 40 | 41 | Initial version released by Pulkit Aggarwal (IT 2012-2016) and Divjot Singh (COE 2012-2016). You can still try it out here : http://divjot.collegespace.in/o/NSITulatorJS 42 | 43 | * [x] Pure HTML5 app 44 | * [x] Calculate % for any semester of any branch 45 | * [x] Somewhat mobile friendly 46 | 47 | Todo 48 | ==== 49 | 50 | * [ ] Give user checkboxes to choose which subject to drop out of the suggestions. 51 | * [ ] Use data analysis to give recommendations to user for the current semesters. 52 | * [ ] Add option to calculate percentage required in future semesters to achieve specified targets. 53 | * [ ] Expand to other colleges. 54 | -------------------------------------------------------------------------------- /css/main.css: -------------------------------------------------------------------------------- 1 | html { 2 | /* Currently supported in Firefox & Chrome [with flags] only */ 3 | scroll-behavior: smooth; 4 | } 5 | .jumbotron { 6 | padding: 5px 0px !important; 7 | } 8 | .index-item { 9 | list-style: none; 10 | padding: 5px; 11 | cursor: pointer; 12 | } 13 | .index-item:hover { 14 | background-color: #E4E4E4; 15 | } 16 | .index-item.active { 17 | background-color: #02749C; 18 | color: white; 19 | margin-left: 0; 20 | } 21 | .mainContainerButtons { 22 | margin: 5px; 23 | } 24 | #containers { 25 | margin: 10px 0px 60px 0px; 26 | padding-top: 10px; 27 | } 28 | #mainContainer, #dataContainer { 29 | display:none; 30 | border: 1px #e4e4e4 solid; 31 | overflow: auto; 32 | } 33 | .container-header { 34 | background-color: rgb(203, 33, 14); 35 | color: white; 36 | margin: 0px -15px 12px; 37 | } 38 | 39 | /* Animate export button */ 40 | @-webkit-keyframes tada { 41 | 0% { 42 | -webkit-transform:scale3d(1,1,1); 43 | transform:scale3d(1,1,1) 44 | } 45 | 10%,20% { 46 | -webkit-transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg); 47 | transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg) 48 | } 49 | 30%,50%,70%,90% { 50 | -webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg); 51 | transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg) 52 | } 53 | 40%,60%,80% { 54 | -webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg); 55 | transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg) 56 | } 57 | 100% { 58 | -webkit-transform:scale3d(1,1,1); 59 | transform:scale3d(1,1,1) 60 | } 61 | } 62 | @keyframes tada { 63 | 0% { 64 | -webkit-transform:scale3d(1,1,1); 65 | transform:scale3d(1,1,1) 66 | } 67 | 10%,20% { 68 | -webkit-transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg); 69 | transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg) 70 | } 71 | 30%,50%,70%,90% { 72 | -webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg); 73 | transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg) 74 | } 75 | 40%,60%,80% { 76 | -webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg); 77 | transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg) 78 | } 79 | 100% { 80 | -webkit-transform:scale3d(1,1,1); 81 | transform:scale3d(1,1,1) 82 | } 83 | } 84 | .highlight-button { 85 | -webkit-animation-name: tada linear 2s infinite; 86 | animation: tada linear 2s infinite; 87 | } -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, request 2 | from db import * 3 | import json 4 | app = Flask(__name__) 5 | # app.config['DEBUG'] = True 6 | 7 | # Note: We don't need to call run() since our application is embedded within 8 | # the App Engine WSGI application server. 9 | 10 | 11 | """`main` is the top level module for your Flask application.""" 12 | 13 | # Import the Flask Framework 14 | from flask import Flask 15 | app = Flask(__name__) 16 | # Note: We don't need to call run() since our application is embedded within 17 | # the App Engine WSGI application server. 18 | 19 | 20 | @app.route('/') 21 | def hello(): 22 | """Return a friendly HTTP greeting.""" 23 | return 'Hello World!' 24 | 25 | @app.route('/store_marks', methods=['POST']) 26 | def store_marks(): 27 | # num_semesters = request.form['num_semesters'] 28 | # branch = request.form['branch'] 29 | # section = request.form['section'] 30 | # marks = request.form['marks'] 31 | data = Data(num_sems = int(request.form['num_sems']), branch = request.form['branch'], \ 32 | section = int(request.form['section']), marks = request.form['marks'], \ 33 | marks_string = request.form['marks'], ip_address = request.remote_addr) 34 | data.put() 35 | return 'Success!' 36 | 37 | @app.route('/test') 38 | def test(): 39 | data = Data.query(ndb.AND(Data.branch == "coe", Data.num_sems == 5)) 40 | # return str(data.fetch()) 41 | average, unique, marks_list = get_average_marks(data.fetch()) 42 | return "Average marks in English in COE: " + str(average) + "
\nNumber of entries: " + str(data.count()) + "
\nNumber of unique entries: " + str(unique) + "
\nList of marks: " + str(marks_list) 43 | 44 | @app.route('/test_marks/') 45 | def test_marks(num_sems): 46 | num_sems = int(num_sems) 47 | data = Data.query(ndb.AND(Data.branch == "coe", Data.num_sems == num_sems)).order(Data.date) 48 | output_str = "Number of entities: "+str(data.count())+"


" 49 | result = data.fetch() 50 | for idx, entity in enumerate(result): 51 | # del entity['ip_address'] 52 | output_str += 'Entity '+str(idx)+":
" 53 | output_str += 'Date/time: '+str(entity.date)+'
' 54 | output_str += 'Number of sems: '+str(entity.num_sems)+'
' 55 | output_str += 'Section: '+str(entity.section)+'
' 56 | output_str += 'Marks:
'+str(entity.marks_string) 57 | # output_str += str(entity) 58 | output_str += '



' 59 | return output_str 60 | 61 | def get_average_marks(data): 62 | sum_marks = 0 63 | count = 0 64 | marks_list = {} 65 | for d in data: 66 | j = json.loads(d.marks_string) 67 | if d.ip_address not in marks_list: 68 | marks_list[d.ip_address] = int(j[0]["TH1"]) 69 | else: 70 | marks_list[d.ip_address] = max(marks_list[d.ip_address], int(j[0]["TH1"])) 71 | for marks in marks_list.values(): 72 | if marks == 0: 73 | continue 74 | sum_marks += marks 75 | count += 1 76 | return float(sum_marks)/count, count, marks_list.values() 77 | 78 | @app.errorhandler(404) 79 | def page_not_found(e): 80 | """Return a custom 404 error.""" 81 | return 'Sorry, Nothing at this URL. BulBULle', 404 82 | 83 | 84 | @app.errorhandler(500) 85 | def application_error(e): 86 | """Return a custom 500 error.""" 87 | return 'Sorry, unexpected error: {}'.format(e), 500 88 | -------------------------------------------------------------------------------- /css/bootstrap-select.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap-select v1.6.3 (http://silviomoreto.github.io/bootstrap-select/) 3 | * 4 | * Copyright 2013-2014 bootstrap-select 5 | * Licensed under MIT (https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE) 6 | */.bootstrap-select{width:220px \0}.bootstrap-select>.btn{width:100%;padding-right:25px}.error .bootstrap-select .btn{border:1px solid #b94a48}.control-group.error .bootstrap-select .dropdown-toggle{border-color:#b94a48}.bootstrap-select.fit-width{width:auto!important}.bootstrap-select:not([class*=col-]):not([class*=form-control]):not(.input-group-btn){width:220px}.bootstrap-select .btn:focus{outline:thin dotted #333!important;outline:5px auto -webkit-focus-ring-color!important;outline-offset:-2px}.bootstrap-select.form-control{margin-bottom:0;padding:0;border:none}.bootstrap-select.form-control:not([class*=col-]){width:100%}.bootstrap-select.btn-group:not(.input-group-btn),.bootstrap-select.btn-group[class*=col-]{float:none;display:inline-block;margin-left:0}.bootstrap-select.btn-group.dropdown-menu-right,.bootstrap-select.btn-group[class*=col-].dropdown-menu-right,.row-fluid .bootstrap-select.btn-group[class*=col-].dropdown-menu-right{float:right}.form-search .bootstrap-select.btn-group,.form-inline .bootstrap-select.btn-group,.form-horizontal .bootstrap-select.btn-group,.form-group .bootstrap-select.btn-group{margin-bottom:0}.form-group-lg .bootstrap-select.btn-group.form-control,.form-group-sm .bootstrap-select.btn-group.form-control{padding:0}.form-inline .bootstrap-select.btn-group .form-control{width:100%}.input-append .bootstrap-select.btn-group{margin-left:-1px}.input-prepend .bootstrap-select.btn-group{margin-right:-1px}.bootstrap-select.btn-group>.disabled{cursor:not-allowed}.bootstrap-select.btn-group>.disabled:focus{outline:0!important}.bootstrap-select.btn-group .btn .filter-option{display:inline-block;overflow:hidden;width:100%;text-align:left}.bootstrap-select.btn-group .btn .caret{position:absolute;top:50%;right:12px;margin-top:-2px;vertical-align:middle}.bootstrap-select.btn-group[class*=col-] .btn{width:100%}.bootstrap-select.btn-group .dropdown-menu{min-width:100%;z-index:1035;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bootstrap-select.btn-group .dropdown-menu.inner{position:static;border:0;padding:0;margin:0;border-radius:0;-webkit-box-shadow:none;box-shadow:none}.bootstrap-select.btn-group .dropdown-menu li{position:relative}.bootstrap-select.btn-group .dropdown-menu li:not(.disabled) a:hover small,.bootstrap-select.btn-group .dropdown-menu li:not(.disabled) a:focus small,.bootstrap-select.btn-group .dropdown-menu li.active:not(.disabled) a small{color:#64b1d8;color:rgba(100,177,216,.4)}.bootstrap-select.btn-group .dropdown-menu li.disabled a{cursor:not-allowed}.bootstrap-select.btn-group .dropdown-menu li a{cursor:pointer}.bootstrap-select.btn-group .dropdown-menu li a.opt{position:relative;padding-left:2.25em}.bootstrap-select.btn-group .dropdown-menu li a span.check-mark{display:none}.bootstrap-select.btn-group .dropdown-menu li a span.text{display:inline-block}.bootstrap-select.btn-group .dropdown-menu li small{padding-left:.5em}.bootstrap-select.btn-group .dropdown-menu .notify{position:absolute;bottom:5px;width:96%;margin:0 2%;min-height:26px;padding:3px 5px;background:#f5f5f5;border:1px solid #e3e3e3;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05);pointer-events:none;opacity:.9;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bootstrap-select.btn-group .no-results{padding:3px;background:#f5f5f5;margin:0 5px}.bootstrap-select.btn-group.fit-width .btn .filter-option{position:static}.bootstrap-select.btn-group.fit-width .btn .caret{position:static;top:auto;margin-top:-1px}.bootstrap-select.btn-group.show-tick .dropdown-menu li.selected a span.check-mark{position:absolute;display:inline-block;right:15px;margin-top:5px}.bootstrap-select.btn-group.show-tick .dropdown-menu li a span.text{margin-right:34px}.bootstrap-select.show-menu-arrow.open>.btn{z-index:1035+1}.bootstrap-select.show-menu-arrow .dropdown-toggle:before{content:'';border-left:7px solid transparent;border-right:7px solid transparent;border-bottom-width:7px;border-bottom-style:solid;border-bottom-color:#ccc;border-bottom-color:rgba(204,204,204,.2);position:absolute;bottom:-4px;left:9px;display:none}.bootstrap-select.show-menu-arrow .dropdown-toggle:after{content:'';border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute;bottom:-4px;left:10px;display:none}.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle:before{bottom:auto;top:-3px;border-bottom:0;border-top-width:7px;border-top-style:solid;border-top-color:#ccc;border-top-color:rgba(204,204,204,.2)}.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle:after{bottom:auto;top:-3px;border-top:6px solid #fff;border-bottom:0}.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle:before{right:12px;left:auto}.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle:after{right:13px;left:auto}.bootstrap-select.show-menu-arrow.open>.dropdown-toggle:before,.bootstrap-select.show-menu-arrow.open>.dropdown-toggle:after{display:block}.bs-searchbox,.bs-actionsbox{padding:4px 8px}.bs-actionsbox{float:left;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bs-actionsbox .btn-group button{width:50%}.bs-searchbox+.bs-actionsbox{padding:0 8px 4px}.bs-searchbox input.form-control{margin-bottom:0;width:100%}.mobile-device{position:absolute;top:0;left:0;display:block!important;width:100%;height:100%!important;opacity:0} -------------------------------------------------------------------------------- /percentage/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | NSITulator - The NSIT percentage calculator 11 | 12 | 13 |
14 |
15 |

NSITulator v2.0.0b

16 |
17 |
The requirement of specifying your section has been added so that your rank within your section can be calculated. Anonymous data may be collected for analysis purposes.
18 |
Pro Tip: You can calculate percentage of individual semesters too by 19 | entering the marks of that semester only.
20 |
Due to the unavailability of subject category data for 7th and 8th semesters of ICE and ECE, the calculation of post-drop percentage for these branches might not be accurate.
21 |
22 |
Developed by Udit Arora, in collaboration with CollegeSpace
23 |
24 |
25 |
26 |
27 | 28 | 36 | 37 | 43 | 44 | 54 |

55 | 56 |
57 |
58 |
59 |
60 |
61 |
62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /js/bootstrap-select.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap-select v1.6.3 (http://silviomoreto.github.io/bootstrap-select/) 3 | * 4 | * Copyright 2013-2014 bootstrap-select 5 | * Licensed under MIT (https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE) 6 | */ 7 | !function(a){"use strict";function b(a,b){return a.toUpperCase().indexOf(b.toUpperCase())>-1}function c(b){var c=[{re:/[\xC0-\xC6]/g,ch:"A"},{re:/[\xE0-\xE6]/g,ch:"a"},{re:/[\xC8-\xCB]/g,ch:"E"},{re:/[\xE8-\xEB]/g,ch:"e"},{re:/[\xCC-\xCF]/g,ch:"I"},{re:/[\xEC-\xEF]/g,ch:"i"},{re:/[\xD2-\xD6]/g,ch:"O"},{re:/[\xF2-\xF6]/g,ch:"o"},{re:/[\xD9-\xDC]/g,ch:"U"},{re:/[\xF9-\xFC]/g,ch:"u"},{re:/[\xC7-\xE7]/g,ch:"c"},{re:/[\xD1]/g,ch:"N"},{re:/[\xF1]/g,ch:"n"}];return a.each(c,function(){b=b.replace(this.re,this.ch)}),b}function d(a){var b={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},c="(?:"+Object.keys(b).join("|")+")",d=new RegExp(c),e=new RegExp(c,"g"),f=null==a?"":""+a;return d.test(f)?f.replace(e,function(a){return b[a]}):f}function e(b,c){var d=arguments,e=b,b=d[0],c=d[1];[].shift.apply(d),"undefined"==typeof b&&(b=e);var g,h=this.each(function(){var e=a(this);if(e.is("select")){var h=e.data("selectpicker"),i="object"==typeof b&&b;if(h){if(i)for(var j in i)i.hasOwnProperty(j)&&(h.options[j]=i[j])}else{var k=a.extend({},f.DEFAULTS,a.fn.selectpicker.defaults||{},e.data(),i);e.data("selectpicker",h=new f(this,k,c))}"string"==typeof b&&(g=h[b]instanceof Function?h[b].apply(h,d):h.options[b])}});return"undefined"!=typeof g?g:h}a.expr[":"].icontains=function(c,d,e){return b(a(c).text(),e[3])},a.expr[":"].aicontains=function(c,d,e){return b(a(c).data("normalizedText")||a(c).text(),e[3])};var f=function(b,c,d){d&&(d.stopPropagation(),d.preventDefault()),this.$element=a(b),this.$newElement=null,this.$button=null,this.$menu=null,this.$lis=null,this.options=c,null===this.options.title&&(this.options.title=this.$element.attr("title")),this.val=f.prototype.val,this.render=f.prototype.render,this.refresh=f.prototype.refresh,this.setStyle=f.prototype.setStyle,this.selectAll=f.prototype.selectAll,this.deselectAll=f.prototype.deselectAll,this.destroy=f.prototype.remove,this.remove=f.prototype.remove,this.show=f.prototype.show,this.hide=f.prototype.hide,this.init()};f.VERSION="1.6.3",f.DEFAULTS={noneSelectedText:"Nothing selected",noneResultsText:"No results match",countSelectedText:function(a){return 1==a?"{0} item selected":"{0} items selected"},maxOptionsText:function(a,b){var c=[];return c[0]=1==a?"Limit reached ({n} item max)":"Limit reached ({n} items max)",c[1]=1==b?"Group limit reached ({n} item max)":"Group limit reached ({n} items max)",c},selectAllText:"Select All",deselectAllText:"Deselect All",multipleSeparator:", ",style:"btn-default",size:"auto",title:null,selectedTextFormat:"values",width:!1,container:!1,hideDisabled:!1,showSubtext:!1,showIcon:!0,showContent:!0,dropupAuto:!0,header:!1,liveSearch:!1,actionsBox:!1,iconBase:"glyphicon",tickIcon:"glyphicon-ok",maxOptions:!1,mobile:!1,selectOnTab:!1,dropdownAlignRight:!1,searchAccentInsensitive:!1},f.prototype={constructor:f,init:function(){var b=this,c=this.$element.attr("id");this.$element.hide(),this.multiple=this.$element.prop("multiple"),this.autofocus=this.$element.prop("autofocus"),this.$newElement=this.createView(),this.$element.after(this.$newElement),this.$menu=this.$newElement.find("> .dropdown-menu"),this.$button=this.$newElement.find("> button"),this.$searchbox=this.$newElement.find("input"),this.options.dropdownAlignRight&&this.$menu.addClass("dropdown-menu-right"),"undefined"!=typeof c&&(this.$button.attr("data-id",c),a('label[for="'+c+'"]').click(function(a){a.preventDefault(),b.$button.focus()})),this.checkDisabled(),this.clickListener(),this.options.liveSearch&&this.liveSearchListener(),this.render(),this.liHeight(),this.setStyle(),this.setWidth(),this.options.container&&this.selectPosition(),this.$menu.data("this",this),this.$newElement.data("this",this),this.options.mobile&&this.mobile()},createDropdown:function(){var b=this.multiple?" show-tick":"",c=this.$element.parent().hasClass("input-group")?" input-group-btn":"",d=this.autofocus?" autofocus":"",e=this.$element.parents().hasClass("form-group-lg")?" btn-lg":this.$element.parents().hasClass("form-group-sm")?" btn-sm":"",f=this.options.header?'
'+this.options.header+"
":"",g=this.options.liveSearch?'':"",h=this.options.actionsBox?'
":"",i='
';return a(i)},createView:function(){var a=this.createDropdown(),b=this.createLi();return a.find("ul").append(b),a},reloadLi:function(){this.destroyLi();var a=this.createLi();this.$menu.find("ul").append(a)},destroyLi:function(){this.$menu.find("li").remove()},createLi:function(){var b=this,e=[],f=0,g=function(a,b,c){return""+a+""},h=function(a,e,f,g){var h=c(d(a));return''+a+''};return this.$element.find("option").each(function(){var c=a(this),d=c.attr("class")||"",i=c.attr("style"),j=c.data("content")?c.data("content"):c.html(),k="undefined"!=typeof c.data("subtext")?''+c.data("subtext")+"":"",l="undefined"!=typeof c.data("icon")?' ':"",m=c.is(":disabled")||c.parent().is(":disabled"),n=c[0].index;if(""!==l&&m&&(l=""+l+""),c.data("content")||(j=l+''+j+k+""),!b.options.hideDisabled||!m)if(c.parent().is("optgroup")&&c.data("divider")!==!0){if(0===c.index()){f+=1;var o=c.parent().attr("label"),p="undefined"!=typeof c.parent().data("subtext")?''+c.parent().data("subtext")+"":"",q=c.parent().data("icon")?' ':"";o=q+''+o+p+"",0!==n&&e.length>0&&e.push(g("",null,"divider")),e.push(g(o,null,"dropdown-header"))}e.push(g(h(j,"opt "+d,i,f),n))}else e.push(c.data("divider")===!0?g("",n,"divider"):c.data("hidden")===!0?g(h(j,d,i),n,"hide is-hidden"):g(h(j,d,i),n))}),this.multiple||0!==this.$element.find("option:selected").length||this.options.title||this.$element.find("option").eq(0).prop("selected",!0).attr("selected","selected"),a(e.join(""))},findLis:function(){return null==this.$lis&&(this.$lis=this.$menu.find("li")),this.$lis},render:function(b){var c=this;b!==!1&&this.$element.find("option").each(function(b){c.setDisabled(b,a(this).is(":disabled")||a(this).parent().is(":disabled")),c.setSelected(b,a(this).is(":selected"))}),this.tabIndex();var e=this.options.hideDisabled?":not([disabled])":"",f=this.$element.find("option:selected"+e).map(function(){var b,d=a(this),e=d.data("icon")&&c.options.showIcon?' ':"";return b=c.options.showSubtext&&d.attr("data-subtext")&&!c.multiple?' '+d.data("subtext")+"":"",d.data("content")&&c.options.showContent?d.data("content"):"undefined"!=typeof d.attr("title")?d.attr("title"):e+d.html()+b}).toArray(),g=this.multiple?f.join(this.options.multipleSeparator):f[0];if(this.multiple&&this.options.selectedTextFormat.indexOf("count")>-1){var h=this.options.selectedTextFormat.split(">");if(h.length>1&&f.length>h[1]||1==h.length&&f.length>=2){e=this.options.hideDisabled?", [disabled]":"";var i=this.$element.find("option").not('[data-divider="true"], [data-hidden="true"]'+e).length,j="function"==typeof this.options.countSelectedText?this.options.countSelectedText(f.length,i):this.options.countSelectedText;g=j.replace("{0}",f.length.toString()).replace("{1}",i.toString())}}this.options.title=this.$element.attr("title"),"static"==this.options.selectedTextFormat&&(g=this.options.title),g||(g="undefined"!=typeof this.options.title?this.options.title:this.options.noneSelectedText),this.$button.attr("title",d(g)),this.$newElement.find(".filter-option").html(g)},setStyle:function(a,b){this.$element.attr("class")&&this.$newElement.addClass(this.$element.attr("class").replace(/selectpicker|mobile-device|validate\[.*\]/gi,""));var c=a?a:this.options.style;"add"==b?this.$button.addClass(c):"remove"==b?this.$button.removeClass(c):(this.$button.removeClass(this.options.style),this.$button.addClass(c))},liHeight:function(){if(this.options.size!==!1){var a=this.$menu.parent().clone().find("> .dropdown-toggle").prop("autofocus",!1).end().appendTo("body"),b=a.addClass("open").find("> .dropdown-menu"),c=b.find("li").not(".divider").not(".dropdown-header").filter(":visible").children("a").outerHeight(),d=this.options.header?b.find(".popover-title").outerHeight():0,e=this.options.liveSearch?b.find(".bs-searchbox").outerHeight():0,f=this.options.actionsBox?b.find(".bs-actionsbox").outerHeight():0;a.remove(),this.$newElement.data("liHeight",c).data("headerHeight",d).data("searchHeight",e).data("actionsHeight",f)}},setSize:function(){this.findLis();var b,c,d,e=this,f=this.$menu,g=f.find(".inner"),h=this.$newElement.outerHeight(),i=this.$newElement.data("liHeight"),j=this.$newElement.data("headerHeight"),k=this.$newElement.data("searchHeight"),l=this.$newElement.data("actionsHeight"),m=this.$lis.filter(".divider").outerHeight(!0),n=parseInt(f.css("padding-top"))+parseInt(f.css("padding-bottom"))+parseInt(f.css("border-top-width"))+parseInt(f.css("border-bottom-width")),o=this.options.hideDisabled?", .disabled":"",p=a(window),q=n+parseInt(f.css("margin-top"))+parseInt(f.css("margin-bottom"))+2,r=function(){c=e.$newElement.offset().top-p.scrollTop(),d=p.height()-c-h};if(r(),this.options.header&&f.css("padding-top",0),"auto"==this.options.size){var s=function(){var a,h=e.$lis.not(".hide");r(),b=d-q,e.options.dropupAuto&&e.$newElement.toggleClass("dropup",c>d&&b-q3?3*i+q-2:0,f.css({"max-height":b+"px",overflow:"hidden","min-height":a+j+k+l+"px"}),g.css({"max-height":b-j-k-l-n+"px","overflow-y":"auto","min-height":Math.max(a-n,0)+"px"})};s(),this.$searchbox.off("input.getSize propertychange.getSize").on("input.getSize propertychange.getSize",s),a(window).off("resize.getSize").on("resize.getSize",s),a(window).off("scroll.getSize").on("scroll.getSize",s)}else if(this.options.size&&"auto"!=this.options.size&&f.find("li"+o).length>this.options.size){var t=this.$lis.not(".divider"+o).find(" > *").slice(0,this.options.size).last().parent().index(),u=this.$lis.slice(0,t+1).filter(".divider").length;b=i*this.options.size+u*m+n,e.options.dropupAuto&&this.$newElement.toggleClass("dropup",c>d&&b .dropdown-menu").css("width"),c=a.css("width","auto").find("> button").css("width");a.remove(),this.$newElement.css("width",Math.max(parseInt(b),parseInt(c))+"px")}else"fit"==this.options.width?(this.$menu.css("min-width",""),this.$newElement.css("width","").addClass("fit-width")):this.options.width?(this.$menu.css("min-width",""),this.$newElement.css("width",this.options.width)):(this.$menu.css("min-width",""),this.$newElement.css("width",""));this.$newElement.hasClass("fit-width")&&"fit"!==this.options.width&&this.$newElement.removeClass("fit-width")},selectPosition:function(){var b,c,d=this,e="
",f=a(e),g=function(a){f.addClass(a.attr("class").replace(/form-control/gi,"")).toggleClass("dropup",a.hasClass("dropup")),b=a.offset(),c=a.hasClass("dropup")?0:a[0].offsetHeight,f.css({top:b.top+c,left:b.left,width:a[0].offsetWidth,position:"absolute"})};this.$newElement.on("click",function(){d.isDisabled()||(g(a(this)),f.appendTo(d.options.container),f.toggleClass("open",!a(this).hasClass("open")),f.append(d.$menu))}),a(window).resize(function(){g(d.$newElement)}),a(window).on("scroll",function(){g(d.$newElement)}),a("html").on("click",function(b){a(b.target).closest(d.$newElement).length<1&&f.removeClass("open")})},setSelected:function(a,b){this.findLis(),this.$lis.filter('[data-original-index="'+a+'"]').toggleClass("selected",b)},setDisabled:function(a,b){this.findLis(),b?this.$lis.filter('[data-original-index="'+a+'"]').addClass("disabled").find("a").attr("href","#").attr("tabindex",-1):this.$lis.filter('[data-original-index="'+a+'"]').removeClass("disabled").find("a").removeAttr("href").attr("tabindex",0)},isDisabled:function(){return this.$element.is(":disabled")},checkDisabled:function(){var a=this;this.isDisabled()?this.$button.addClass("disabled").attr("tabindex",-1):(this.$button.hasClass("disabled")&&this.$button.removeClass("disabled"),-1==this.$button.attr("tabindex")&&(this.$element.data("tabindex")||this.$button.removeAttr("tabindex"))),this.$button.click(function(){return!a.isDisabled()})},tabIndex:function(){this.$element.is("[tabindex]")&&(this.$element.data("tabindex",this.$element.attr("tabindex")),this.$button.attr("tabindex",this.$element.data("tabindex")))},clickListener:function(){var b=this;this.$newElement.on("touchstart.dropdown",".dropdown-menu",function(a){a.stopPropagation()}),this.$newElement.on("click",function(){b.setSize(),b.options.liveSearch||b.multiple||setTimeout(function(){b.$menu.find(".selected a").focus()},10)}),this.$menu.on("click","li a",function(c){var d=a(this),e=d.parent().data("originalIndex"),f=b.$element.val(),g=b.$element.prop("selectedIndex");if(b.multiple&&c.stopPropagation(),c.preventDefault(),!b.isDisabled()&&!d.parent().hasClass("disabled")){var h=b.$element.find("option"),i=h.eq(e),j=i.prop("selected"),k=i.parent("optgroup"),l=b.options.maxOptions,m=k.data("maxOptions")||!1;if(b.multiple){if(i.prop("selected",!j),b.setSelected(e,!j),d.blur(),l!==!1||m!==!1){var n=l
');q[2]&&(r=r.replace("{var}",q[2][l>1?0:1]),s=s.replace("{var}",q[2][m>1?0:1])),i.prop("selected",!1),b.$menu.append(t),l&&n&&(t.append(a("
"+r+"
")),b.$element.trigger("maxReached.bs.select")),m&&o&&(t.append(a("
"+s+"
")),b.$element.trigger("maxReachedGrp.bs.select")),setTimeout(function(){b.setSelected(e,!1)},10),t.delay(750).fadeOut(300,function(){a(this).remove()})}}}else h.prop("selected",!1),i.prop("selected",!0),b.$menu.find(".selected").removeClass("selected"),b.setSelected(e,!0);b.multiple?b.options.liveSearch&&b.$searchbox.focus():b.$button.focus(),(f!=b.$element.val()&&b.multiple||g!=b.$element.prop("selectedIndex")&&!b.multiple)&&b.$element.change()}}),this.$menu.on("click","li.disabled a, .popover-title, .popover-title :not(.close)",function(a){a.target==this&&(a.preventDefault(),a.stopPropagation(),b.options.liveSearch?b.$searchbox.focus():b.$button.focus())}),this.$menu.on("click","li.divider, li.dropdown-header",function(a){a.preventDefault(),a.stopPropagation(),b.options.liveSearch?b.$searchbox.focus():b.$button.focus()}),this.$menu.on("click",".popover-title .close",function(){b.$button.focus()}),this.$searchbox.on("click",function(a){a.stopPropagation()}),this.$menu.on("click",".actions-btn",function(c){b.options.liveSearch?b.$searchbox.focus():b.$button.focus(),c.preventDefault(),c.stopPropagation(),a(this).is(".bs-select-all")?b.selectAll():b.deselectAll(),b.$element.change()}),this.$element.change(function(){b.render(!1)})},liveSearchListener:function(){var b=this,e=a('
  • ');this.$newElement.on("click.dropdown.data-api touchstart.dropdown.data-api",function(){b.$menu.find(".active").removeClass("active"),b.$searchbox.val()&&(b.$searchbox.val(""),b.$lis.not(".is-hidden").removeClass("hide"),e.parent().length&&e.remove()),b.multiple||b.$menu.find(".selected").addClass("active"),setTimeout(function(){b.$searchbox.focus()},10)}),this.$searchbox.on("click.dropdown.data-api focus.dropdown.data-api touchend.dropdown.data-api",function(a){a.stopPropagation()}),this.$searchbox.on("input propertychange",function(){b.$searchbox.val()?(b.options.searchAccentInsensitive?b.$lis.not(".is-hidden").removeClass("hide").find("a").not(":aicontains("+c(b.$searchbox.val())+")").parent().addClass("hide"):b.$lis.not(".is-hidden").removeClass("hide").find("a").not(":icontains("+b.$searchbox.val()+")").parent().addClass("hide"),b.$menu.find("li").filter(":visible:not(.no-results)").length?e.parent().length&&e.remove():(e.parent().length&&e.remove(),e.html(b.options.noneResultsText+' "'+d(b.$searchbox.val())+'"').show(),b.$menu.find("li").last().after(e))):(b.$lis.not(".is-hidden").removeClass("hide"),e.parent().length&&e.remove()),b.$menu.find("li.active").removeClass("active"),b.$menu.find("li").filter(":visible:not(.divider)").eq(0).addClass("active").find("a").focus(),a(this).focus()})},val:function(a){return"undefined"!=typeof a?(this.$element.val(a),this.render(),this.$element):this.$element.val()},selectAll:function(){this.findLis(),this.$lis.not(".divider").not(".disabled").not(".selected").filter(":visible").find("a").click()},deselectAll:function(){this.findLis(),this.$lis.not(".divider").not(".disabled").filter(".selected").filter(":visible").find("a").click()},keydown:function(b){var d,e,f,g,h,i,j,k,l,m=a(this),n=m.is("input")?m.parent().parent():m.parent(),o=n.data("this"),p={32:" ",48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",59:";",65:"a",66:"b",67:"c",68:"d",69:"e",70:"f",71:"g",72:"h",73:"i",74:"j",75:"k",76:"l",77:"m",78:"n",79:"o",80:"p",81:"q",82:"r",83:"s",84:"t",85:"u",86:"v",87:"w",88:"x",89:"y",90:"z",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9"};if(o.options.liveSearch&&(n=m.parent().parent()),o.options.container&&(n=o.$menu),d=a("[role=menu] li a",n),l=o.$menu.parent().hasClass("open"),!l&&/([0-9]|[A-z])/.test(String.fromCharCode(b.keyCode))&&(o.options.container?o.$newElement.trigger("click"):(o.setSize(),o.$menu.parent().addClass("open"),l=!0),o.$searchbox.focus()),o.options.liveSearch&&(/(^9$|27)/.test(b.keyCode.toString(10))&&l&&0===o.$menu.find(".active").length&&(b.preventDefault(),o.$menu.parent().removeClass("open"),o.$button.focus()),d=a("[role=menu] li:not(.divider):not(.dropdown-header):visible",n),m.val()||/(38|40)/.test(b.keyCode.toString(10))||0===d.filter(".active").length&&(d=o.$newElement.find("li").filter(o.options.searchAccentInsensitive?":aicontains("+c(p[b.keyCode])+")":":icontains("+p[b.keyCode]+")"))),d.length){if(/(38|40)/.test(b.keyCode.toString(10)))e=d.index(d.filter(":focus")),g=d.parent(":not(.disabled):visible").first().index(),h=d.parent(":not(.disabled):visible").last().index(),f=d.eq(e).parent().nextAll(":not(.disabled):visible").eq(0).index(),i=d.eq(e).parent().prevAll(":not(.disabled):visible").eq(0).index(),j=d.eq(f).parent().prevAll(":not(.disabled):visible").eq(0).index(),o.options.liveSearch&&(d.each(function(b){a(this).is(":not(.disabled)")&&a(this).data("index",b)}),e=d.index(d.filter(".active")),g=d.filter(":not(.disabled):visible").first().data("index"),h=d.filter(":not(.disabled):visible").last().data("index"),f=d.eq(e).nextAll(":not(.disabled):visible").eq(0).data("index"),i=d.eq(e).prevAll(":not(.disabled):visible").eq(0).data("index"),j=d.eq(f).prevAll(":not(.disabled):visible").eq(0).data("index")),k=m.data("prevIndex"),38==b.keyCode&&(o.options.liveSearch&&(e-=1),e!=j&&e>i&&(e=i),g>e&&(e=g),e==k&&(e=h)),40==b.keyCode&&(o.options.liveSearch&&(e+=1),-1==e&&(e=0),e!=j&&f>e&&(e=f),e>h&&(e=h),e==k&&(e=g)),m.data("prevIndex",e),o.options.liveSearch?(b.preventDefault(),m.is(".dropdown-toggle")||(d.removeClass("active"),d.eq(e).addClass("active").find("a").focus(),m.focus())):d.eq(e).focus();else if(!m.is("input")){var q,r,s=[];d.each(function(){a(this).parent().is(":not(.disabled)")&&a.trim(a(this).text().toLowerCase()).substring(0,1)==p[b.keyCode]&&s.push(a(this).parent().index())}),q=a(document).data("keycount"),q++,a(document).data("keycount",q),r=a.trim(a(":focus").text().toLowerCase()).substring(0,1),r!=p[b.keyCode]?(q=1,a(document).data("keycount",q)):q>=s.length&&(a(document).data("keycount",0),q>s.length&&(q=1)),d.eq(s[q-1]).focus()}(/(13|32)/.test(b.keyCode.toString(10))||/(^9$)/.test(b.keyCode.toString(10))&&o.options.selectOnTab)&&l&&(/(32)/.test(b.keyCode.toString(10))||b.preventDefault(),o.options.liveSearch?/(32)/.test(b.keyCode.toString(10))||(o.$menu.find(".active a").click(),m.focus()):a(":focus").click(),a(document).data("keycount",0)),(/(^9$|27)/.test(b.keyCode.toString(10))&&l&&(o.multiple||o.options.liveSearch)||/(27)/.test(b.keyCode.toString(10))&&!l)&&(o.$menu.parent().removeClass("open"),o.$button.focus())}},mobile:function(){this.$element.addClass("mobile-device").appendTo(this.$newElement),this.options.container&&this.$menu.hide()},refresh:function(){this.$lis=null,this.reloadLi(),this.render(),this.setWidth(),this.setStyle(),this.checkDisabled(),this.liHeight()},update:function(){this.reloadLi(),this.setWidth(),this.setStyle(),this.checkDisabled(),this.liHeight()},hide:function(){this.$newElement.hide()},show:function(){this.$newElement.show()},remove:function(){this.$newElement.remove(),this.$element.remove()}};var g=a.fn.selectpicker;a.fn.selectpicker=e,a.fn.selectpicker.Constructor=f,a.fn.selectpicker.noConflict=function(){return a.fn.selectpicker=g,this},a(document).data("keycount",0).on("keydown",".bootstrap-select [data-toggle=dropdown], .bootstrap-select [role=menu], .bs-searchbox input",f.prototype.keydown).on("focusin.modal",".bootstrap-select [data-toggle=dropdown], .bootstrap-select [role=menu], .bs-searchbox input",function(a){a.stopPropagation()}),a(window).on("load.bs.select.data-api",function(){a(".selectpicker").each(function(){var b=a(this);e.call(b,b.data())})})}(jQuery); 8 | //# sourceMappingURL=bootstrap-select.js.map -------------------------------------------------------------------------------- /js/calculator.js: -------------------------------------------------------------------------------- 1 | var branchName, numberOfSems, sectionId; 2 | var $branchSelect = document.getElementById('branchSelect'); 3 | var $semSelect = document.getElementById('semSelect'); 4 | var $sectionSelect = document.getElementById('sectionSelect'); 5 | var $mainContainer = document.getElementById('mainContainer'); 6 | var $dataContainer = document.getElementById('dataContainer'); 7 | 8 | var showForm = function() { 9 | branchName = $branchSelect.options[$branchSelect.selectedIndex].value; 10 | numberOfSems = $semSelect.options[$semSelect.selectedIndex].value; 11 | sectionId = $sectionSelect.options[$sectionSelect.selectedIndex].value; 12 | 13 | if (sectionId == 0) { 14 | alert("Please choose your section."); 15 | } else 16 | loadForm(); 17 | }; 18 | 19 | var loadForm = function() { 20 | $dataContainer.style.display = 'none'; 21 | $mainContainer.innerHTML = ""; 22 | 23 | var html; 24 | if(numberOfSems > 1) { 25 | html = "
    Please enter your marks
    "+ 26 | "
    "+ "
    "; 27 | for(var semNum = 1; semNum <= numberOfSems; semNum++) html += "
  • Semester " + semNum + "
  • "; 28 | html += '
    '; 29 | } else { 30 | html = "
    Please enter your marks
    "; 31 | } 32 | 33 | for (var semNum = 1; semNum <= numberOfSems; semNum++) { 34 | html += ''; 36 | for (var i = 0; i < branches[branchName][semNum-1].subjects.theory.length; i++) { 37 | html += '' + 38 | '' + 39 | '' + 40 | '' + 41 | '' + 42 | '' + 43 | ''; 44 | } 45 | for (var i = 0; i < branches[branchName][semNum-1].subjects.practical.length; i++) { 46 | html += '' + 47 | '' + 48 | '' + 49 | '' + 50 | '' + 51 | '' + 52 | ''; 53 | } 54 | html += '
    Semester'+semNum+ 35 | '
    #CodeNameCreditsMarks
    '+branches[branchName][semNum-1].subjects.theory[i].sno+''+branchName.toUpperCase()+branches[branchName][semNum-1].subjects.theory[i].code+''+branches[branchName][semNum-1].subjects.theory[i].name+''+branches[branchName][semNum-1].subjects.theory[i].credits+'
    '+branches[branchName][semNum-1].subjects.practical[i].sno+''+branchName.toUpperCase()+branches[branchName][semNum-1].subjects.practical[i].code+''+branches[branchName][semNum-1].subjects.practical[i].name+''+branches[branchName][semNum-1].subjects.practical[i].credits+'
    '; 55 | } 56 | html += "
    "; 57 | $mainContainer.innerHTML += (html + '
    '+ 58 | '' + 59 | '' + 60 | '' + 61 | '
    '); 62 | 63 | $mainContainer.style.display = 'block'; 64 | window.scrollTo(0, $mainContainer.offsetTop - 20); 65 | if(numberOfSems > 1) { 66 | $('.sem-marks').css('display', 'none'); 67 | $('#marksOf1').css('display', 'table'); 68 | $('.index-item:first-child').addClass('active'); 69 | $('#toggleIndex').on('click', function(e) { 70 | var $e = e.currentTarget; 71 | if($e.innerHTML === '<') { 72 | $e.innerHTML = '>'; 73 | $('.index').hide('fast'); 74 | $('.sem-marks').css('display', 'table'); 75 | $('.index-item.active').removeClass('active'); 76 | } else { 77 | $e.innerHTML = '<'; 78 | $('.index').show('fast'); 79 | $('.sem-marks').css('display', 'none'); 80 | $('#marksOf1').css('display', 'table'); 81 | $('.index-item:first-child').addClass('active'); 82 | } 83 | }); 84 | $('.index-item').on('click', function(e) { 85 | var $e = $(e.currentTarget); 86 | $('.sem-marks').css('display', 'none'); 87 | $($e.attr('data-target')).css('display', 'block'); 88 | $('.index-item.active').removeClass('active'); 89 | $e.addClass('active'); 90 | window.scrollTo(0, $mainContainer.offsetTop - 20); 91 | }); 92 | } 93 | //html = '
    '+ 94 | //'
    Overall
    '+ 95 | //'
    '+ 96 | //'
    '+ 97 | //'
    '; 98 | //$dataContainer.innerHTML = html; 99 | }; 100 | 101 | var calculate = function(option) { 102 | var htmlString = '
    Report Card
    ' + 107 | ''; 108 | 109 | // var marks = [], percentage = []; 110 | var semPercentages = [], aggregatePercentages = []; 111 | var totalMarks=0, totalCredits=0; 112 | var minMarksIn = { A : { code : 0, name : "", marks : 100 }, C : { code : 0, name : "", marks : 100 }, H : { code : 0, name : "", marks : 100 } }; 113 | 114 | //for all sems in range 115 | for (var sem = 0; sem < numberOfSems; sem++) { 116 | var semMarks = 0; //store the total marks for current sem 117 | for (var i = 0; i < branches[branchName][sem].subjects.theory.length; i++) //iterate over the theory subjects for current sem 118 | { 119 | //get value from input field or local file based on choice 120 | var value, sno; 121 | if (option == 1) { // when calculate button is pressed 122 | value = document.getElementById(''+(sem+1)+''+branches[branchName][sem].subjects.theory[i].sno).value; 123 | } 124 | else { 125 | sno = branches[branchName][sem].subjects.theory[i].sno; 126 | value = myMarks[sem][sno]; 127 | // console.log("sno: " + sno + ", value: " + value); 128 | } 129 | if (value < 0 || value > 100) { 130 | alert("Invalid marks for subject: "+branchName.toUpperCase()+""+branches[branchName][sem].subjects.theory[i].code+".\nMarks should be within the range [0,100]."); 131 | return; 132 | } 133 | 134 | // if (debug && value == 0) 135 | // value = Math.random()*100; 136 | 137 | semMarks += branches[branchName][sem].subjects.theory[i].credits*value; 138 | 139 | //find minimum marks for each category 140 | if (branches[branchName][sem].subjects.theory[i].category == 'A') { 141 | if (value < minMarksIn.A.marks) { 142 | minMarksIn.A.marks = value; 143 | minMarksIn.A.name = branches[branchName][sem].subjects.theory[i].name; 144 | minMarksIn.A.code = branchName.toUpperCase() + "-" + branches[branchName][sem].subjects.theory[i].code; 145 | } 146 | } 147 | else if (branches[branchName][sem].subjects.theory[i].category == 'C') { 148 | if (value < minMarksIn.C.marks) { 149 | minMarksIn.C.marks = value; 150 | minMarksIn.C.name = branches[branchName][sem].subjects.theory[i].name; 151 | minMarksIn.C.code = branchName.toUpperCase() + "-" + branches[branchName][sem].subjects.theory[i].code; 152 | } 153 | } 154 | else if (branches[branchName][sem].subjects.theory[i].category == 'H') { 155 | if (value < minMarksIn.H.marks) { 156 | minMarksIn.H.marks = value; 157 | minMarksIn.H.name = branches[branchName][sem].subjects.theory[i].name; 158 | minMarksIn.H.code = branchName.toUpperCase() + "-" + branches[branchName][sem].subjects.theory[i].code; 159 | } 160 | } 161 | } 162 | for (var i = 0; i < branches[branchName][sem].subjects.practical.length; i++) //iterate over the practical subjects 163 | { 164 | var value, sno; 165 | if (option == 1) { // when calculate button is pressed 166 | value = document.getElementById(''+(sem+1)+''+branches[branchName][sem].subjects.practical[i].sno).value; 167 | } 168 | else { 169 | sno = branches[branchName][sem].subjects.practical[i].sno; 170 | value = myMarks[sem][sno]; 171 | } 172 | if (value < 0 || value > 100) { 173 | alert("Invalid marks for subject: "+branchName.toUpperCase()+""+branches[branchName][sem].subjects.practical[i].code+".\nMarks should be within the range [0,100]."); 174 | return; 175 | } 176 | 177 | // if (debug && value == 0) 178 | // value = Math.random()*100; 179 | 180 | semMarks += branches[branchName][sem].subjects.practical[i].credits*value; 181 | } 182 | // marks[sem] = semMarks; 183 | var semPercent = semMarks/branches[branchName][sem].totalCredits; //percentage for current sem 184 | // percentage[sem] = semPercent; 185 | semPercentages.push(semPercent); 186 | 187 | totalMarks += semMarks; //store total weighted marks 188 | totalCredits += branches[branchName][sem].totalCredits; //store total credits 189 | 190 | aggregatePercentages.push(totalMarks/totalCredits); 191 | 192 | htmlString += ''; 194 | console.log("Sem "+(sem+1)+" Marks: " + semMarks); 195 | console.log("Percent: " + semPercent); 196 | //var $semContainer = document.getElementById('sem'+(sem+1)+'PanelBody'); 197 | //$semContainer.innerHTML = ''; 198 | //$semContainer.innerHTML += '

    Sem ' +(sem+1)+ ' Total Marks: ' +semMarks+ '

    '; 199 | //$semContainer.innerHTML += '

    Sem ' +(sem+1)+ ' Credits: ' +branches[branchName][sem].totalCredits+ '

    '; 200 | //$semContainer.innerHTML += '

    Sem ' +(sem+1)+ ' Percentage: ' +semPercent+ '

    '; 201 | } 202 | 203 | // totalMarks = 9848; 204 | var netPercentage = totalMarks/totalCredits; //find net percentage 205 | // console.log("Total Marks: " + totalMarks); 206 | // console.log("Net Percentage: " + netPercentage); 207 | 208 | //var $dataContainer = document.getElementById('overallPanelBody'); 209 | htmlString += '
    SemesterMarksCreditsPercentage
    ' + (sem + 1) + '' + semMarks + '' + branches[branchName][sem].totalCredits + 193 | '' + semPercent+ '
    Before Dropping' + 210 | JSON2DL({'Overall Total Marks' : totalMarks, 'Overall Credits' : totalCredits, 'Overall Percentage' : netPercentage}); 211 | 212 | //$dataContainer.innerHTML += '

    Overall Total Marks: ' +totalMarks+ '

    '; 213 | //$dataContainer.innerHTML += '

    Overall Credits: ' +totalCredits+ '

    '; 214 | //$dataContainer.innerHTML += '

    Overall Percentage: ' +netPercentage+ '

    '; 215 | 216 | // minMarksIn.H.marks = 51; minMarksIn.A.marks = 54; minMarksIn.C.marks = 49; 217 | 218 | if (minMarksIn.H.marks == 100) { 219 | minMarksIn.H.marks = 0; 220 | totalCredits += 4; 221 | } 222 | if (minMarksIn.A.marks == 100) { 223 | minMarksIn.A.marks = 0; 224 | totalCredits += 4; 225 | } 226 | if (minMarksIn.C.marks == 100) { 227 | totalCredits += 4; 228 | minMarksIn.C.marks = 0; 229 | } 230 | 231 | for(var type in minMarksIn) { 232 | if(minMarksIn[type].marks > netPercentage) { 233 | minMarksIn[type].name = '*' + minMarksIn[type].name + ''; 234 | } 235 | } 236 | 237 | //dataContainer = document.getElementById('dropPanelBody'); 238 | //dataContainer.innerHTML = ''; 239 | //dataContainer.innerHTML += "
    Dropping:
    Humanities- "+minMarksIn.H.name+", "+minMarksIn.H.marks+ 240 | //"
    Applied- "+minMarksIn.A.name+", "+minMarksIn.A.marks+ "
    Core- "+minMarksIn.C.name+", "+minMarksIn.C.marks+ "

    "; 241 | // console.log("Dropping - H: "+minMarksIn.H.name+", "+minMarksIn.H.marks+ ". A: "+minMarksIn.A.name+", "+minMarksIn.A.marks+ ". C: "+minMarksIn.C.name+", "+minMarksIn.C.marks); 242 | 243 | //drop the subjects with minimum marks 244 | console.log("Total marks: "+totalMarks); 245 | totalMarks = totalMarks - (minMarksIn.H.marks*4); 246 | totalMarks = totalMarks - (minMarksIn.A.marks*4); 247 | totalMarks = totalMarks - (minMarksIn.C.marks*4); 248 | 249 | // totalMarks = totalMarks - ((minMarksIn.H.marks+minMarksIn.A.marks+minMarksIn.C.marks)*4); 250 | console.log("After drop marks: " + totalMarks); 251 | totalCredits = totalCredits - 12; 252 | netPercentage = totalMarks/totalCredits; 253 | // console.log("After Dropping - Total Marks: " + totalMarks); 254 | // console.log("Net Percentage: " + netPercentage); 255 | 256 | //dataContainer.innerHTML += '

    Overall Total Marks (after dropping): ' +totalMarks+ '


    '; 257 | //dataContainer.innerHTML += '

    Overall Credits (after dropping): ' +totalCredits+ '


    '; 258 | //dataContainer.innerHTML += '

    Percentage (after dropping): ' +netPercentage+ '

    '; 259 | 260 | htmlString += "Dropping following Subjects" + 261 | JSON2DL({ 'Humanities' : minMarksIn.H.name + ' ' + minMarksIn.H.code + ' (' + minMarksIn.H.marks + ')', 262 | 'Applied' : minMarksIn.A.name + ' '+ minMarksIn.A.code + ' (' + minMarksIn.A.marks + ')', 263 | 'Core' : minMarksIn.C.name + ' ' + minMarksIn.C.code + ' (' + minMarksIn.C.marks + ')' }); 264 | 265 | htmlString += 'After Dropping'+ 266 | JSON2DL({'Overall Total Marks' : totalMarks, 'Overall Credits' : totalCredits, 'Overall Percentage' : netPercentage, 'CGPA (%age + 7.5) / 10': (netPercentage + 7.5) / 10}) + 267 | '*Note: Above dropped subjects have lowest marks in respective category.' + 268 | ' You may get a better percentage without dropping a subject if the marks scored in it are greater than your aggregate.'; 269 | 270 | if(branchName == "ece" && numberOfSems > 5){ 271 | htmlString+='
    *Note: The post-drop calculation might not be accurate because of the unavailability of subject categories'+ 272 | ' of 6th, 7th and 8th sem of ECE.'; 273 | } 274 | else if (branchName == "ice" && numberOfSems > 6) { 275 | htmlString+='
    *Note: The post-drop calculation might not be accurate because of the unavailability of subject categories'+ 276 | ' of 7th and 8th sem of ICE.'; 277 | } 278 | 279 | $dataContainer.innerHTML = htmlString; 280 | document.getElementById('dataContainer').style.display = 'block'; 281 | if(numberOfSems > 3) { 282 | drawChart([semPercentages, aggregatePercentages]); 283 | } 284 | if (option == 1) // on click of calculate button 285 | saveToLocal(true); 286 | window.scrollTo(0, $dataContainer.offsetTop - 20); 287 | }; 288 | 289 | var saveToLocal = function(serverFlag) { 290 | var userMarks = [ 291 | {"sem" : 1, "TH1" : 0, "TH2" : 0, "TH3" : 0, "TH4" : 0, "TH5" : 0, 292 | "PR1" : 0, "PR2" : 0, "PR3" : 0, "PR4" : 0, "PR5" : 0, "VS1" : 0, "VS2" : 0}, 293 | {"sem" : 2, "TH1" : 0, "TH2" : 0, "TH3" : 0, "TH4" : 0, "TH5" : 0, 294 | "PR1" : 0, "PR2" : 0, "PR3" : 0, "PR4" : 0, "PR5" : 0, "VS1" : 0, "VS2" : 0}, 295 | {"sem" : 3, "TH1" : 0, "TH2" : 0, "TH3" : 0, "TH4" : 0, "TH5" : 0, 296 | "PR1" : 0, "PR2" : 0, "PR3" : 0, "PR4" : 0, "PR5" : 0, "VS1" : 0, "VS2" : 0}, 297 | {"sem" : 4, "TH1" : 0, "TH2" : 0, "TH3" : 0, "TH4" : 0, "TH5" : 0, 298 | "PR1" : 0, "PR2" : 0, "PR3" : 0, "PR4" : 0, "PR5" : 0, "VS1" : 0, "VS2" : 0}, 299 | {"sem" : 5, "TH1" : 0, "TH2" : 0, "TH3" : 0, "TH4" : 0, "TH5" : 0, 300 | "PR1" : 0, "PR2" : 0, "PR3" : 0, "PR4" : 0, "PR5" : 0, "VS1" : 0, "VS2" : 0}, 301 | {"sem" : 6, "TH1" : 0, "TH2" : 0, "TH3" : 0, "TH4" : 0, "TH5" : 0, 302 | "PR1" : 0, "PR2" : 0, "PR3" : 0, "PR4" : 0, "PR5" : 0, "VS1" : 0, "VS2" : 0}, 303 | {"sem" : 7, "TH1" : 0, "TH2" : 0, "TH3" : 0, "TH4" : 0, "TH5" : 0, 304 | "PR1" : 0, "PR2" : 0, "PR3" : 0, "PR4" : 0, "PR5" : 0, "VS1" : 0, "VS2" : 0}, 305 | {"sem" : 8, "TH1" : 0, "TH2" : 0, "TH3" : 0, "TH4" : 0, "TH5" : 0, 306 | "PR1" : 0, "PR2" : 0, "PR3" : 0, "PR4" : 0, "PR5" : 0, "VS1" : 0, "VS2" : 0} 307 | ]; 308 | for (var sem = 0; sem < numberOfSems; sem++) { 309 | var value, sno; 310 | for (var i = 0; i < branches[branchName][sem].subjects.theory.length; i++) //iterate over the theory subjects for current sem 311 | { 312 | sno = branches[branchName][sem].subjects.theory[i].sno; 313 | value = document.getElementById(''+(sem+1)+''+branches[branchName][sem].subjects.theory[i].sno).value; 314 | if (value == "") 315 | value = 0; 316 | userMarks[sem][sno] = parseInt(value); 317 | } 318 | for (var i = 0; i < branches[branchName][sem].subjects.practical.length; i++) //iterate over the practical subjects 319 | { 320 | sno = branches[branchName][sem].subjects.practical[i].sno; 321 | value = document.getElementById(''+(sem+1)+''+branches[branchName][sem].subjects.practical[i].sno).value; 322 | if (value == "") 323 | value = 0; 324 | userMarks[sem][sno] = parseInt(value); 325 | } 326 | } 327 | console.log(userMarks); 328 | var jsonString = JSON.stringify(userMarks); 329 | window.localStorage.setItem('userMarks_'+branchName, jsonString); 330 | if (serverFlag) 331 | sendToServer(jsonString); 332 | }; 333 | 334 | var loadFromLocal = function() { 335 | myMarks = JSON.parse(window.localStorage.getItem('userMarks_'+branchName)); 336 | if (!myMarks) { 337 | alert("No saved data found for selected branch!"); 338 | return; 339 | } 340 | for (var sem = 0; sem < numberOfSems; sem++) { 341 | var value, sno; 342 | for (var i = 0; i < branches[branchName][sem].subjects.theory.length; i++) //iterate over the theory subjects for current sem 343 | { 344 | sno = branches[branchName][sem].subjects.theory[i].sno; 345 | document.getElementById(''+(sem+1)+''+branches[branchName][sem].subjects.theory[i].sno).value = myMarks[sem][sno]; 346 | } 347 | for (var i = 0; i < branches[branchName][sem].subjects.practical.length; i++) //iterate over the practical subjects 348 | { 349 | sno = branches[branchName][sem].subjects.practical[i].sno; 350 | document.getElementById(''+(sem+1)+''+branches[branchName][sem].subjects.practical[i].sno).value = myMarks[sem][sno]; 351 | } 352 | } 353 | calculate(0); 354 | }; 355 | 356 | var sendToServer = function(userMarks) { 357 | var postData = {"num_sems": parseInt(numberOfSems), "branch": branchName, "section": parseInt(sectionId), "marks": userMarks}; 358 | $.ajax({ 359 | type: "POST", 360 | url: '/store_marks', 361 | data: postData, 362 | success: function(data) { 363 | console.log("Stored marks: " + data); 364 | }, 365 | dataType: 'json' 366 | }); 367 | }; 368 | 369 | var exportToLocal = function() { 370 | // Remove animation class from Export button if it is being animated 371 | if (!window.localStorage.getItem('exportedAtLeastOnce')) 372 | document.getElementById('exportButton').classList.remove('highlight-button'); 373 | myMarks = window.localStorage.getItem('userMarks_'+branchName); 374 | if (!myMarks) { 375 | alert("No saved data found for selected branch!"); 376 | return; 377 | } 378 | var data = "text/json;charset=utf-8," + encodeURIComponent(myMarks); 379 | $('').appendTo('#mainContainer'); 380 | $('#exportJSON')[0].click(); 381 | $('#exportJSON').remove(); 382 | // Mark this flag to stop Export button animation 383 | window.localStorage.setItem('exportedAtLeastOnce', true); 384 | }; 385 | 386 | var importFromLocal = function() { 387 | $('#fileElem').click(); 388 | }; 389 | 390 | var importJSON = function(files) { 391 | var jsonFile = files[0]; 392 | if (jsonFile) { 393 | var reader = new FileReader(); 394 | reader.onload = function(e) { 395 | // Reset the file input box value to allow loading of same file again 396 | document.getElementById('fileElem').value = ''; 397 | console.log("Loaded file - name: "+jsonFile.name+", size: "+jsonFile.size+", type: "+jsonFile.type); 398 | // This is not working on Ubuntu 399 | // if (jsonFile.type.indexOf('json') == -1) { 400 | // alert("Invalid file format. Please import correct file"); 401 | // return; 402 | // } 403 | var fileContent = e.target.result; 404 | if (verifyJSONFile(fileContent) == false) { 405 | alert("Invalid file contents. Please import correct file"); 406 | return; 407 | } 408 | myMarks = JSON.parse(fileContent); 409 | for (var sem = 0; sem < numberOfSems; sem++) { 410 | var value, sno; 411 | for (var i = 0; i < branches[branchName][sem].subjects.theory.length; i++) //iterate over the theory subjects for current sem 412 | { 413 | sno = branches[branchName][sem].subjects.theory[i].sno; 414 | document.getElementById(''+(sem+1)+''+branches[branchName][sem].subjects.theory[i].sno).value = myMarks[sem][sno]; 415 | } 416 | for (var i = 0; i < branches[branchName][sem].subjects.practical.length; i++) //iterate over the practical subjects 417 | { 418 | sno = branches[branchName][sem].subjects.practical[i].sno; 419 | document.getElementById(''+(sem+1)+''+branches[branchName][sem].subjects.practical[i].sno).value = myMarks[sem][sno]; 420 | } 421 | } 422 | calculate(2); 423 | window.localStorage.setItem('userMarks_'+branchName, JSON.stringify(myMarks)); 424 | } 425 | reader.readAsText(jsonFile); 426 | } 427 | else { 428 | alert("Failed to load file"); 429 | } 430 | }; 431 | 432 | // Check if the JSON file contains all the keys corresponding to all subjects 433 | var verifyJSONFile = function(content) { 434 | var json = JSON.parse(content); 435 | var userMarks = [ 436 | {"sem" : 1, "TH1" : 0, "TH2" : 0, "TH3" : 0, "TH4" : 0, "TH5" : 0, 437 | "PR1" : 0, "PR2" : 0, "PR3" : 0, "PR4" : 0, "PR5" : 0, "VS1" : 0, "VS2" : 0}, 438 | {"sem" : 2, "TH1" : 0, "TH2" : 0, "TH3" : 0, "TH4" : 0, "TH5" : 0, 439 | "PR1" : 0, "PR2" : 0, "PR3" : 0, "PR4" : 0, "PR5" : 0, "VS1" : 0, "VS2" : 0}, 440 | {"sem" : 3, "TH1" : 0, "TH2" : 0, "TH3" : 0, "TH4" : 0, "TH5" : 0, 441 | "PR1" : 0, "PR2" : 0, "PR3" : 0, "PR4" : 0, "PR5" : 0, "VS1" : 0, "VS2" : 0}, 442 | {"sem" : 4, "TH1" : 0, "TH2" : 0, "TH3" : 0, "TH4" : 0, "TH5" : 0, 443 | "PR1" : 0, "PR2" : 0, "PR3" : 0, "PR4" : 0, "PR5" : 0, "VS1" : 0, "VS2" : 0}, 444 | {"sem" : 5, "TH1" : 0, "TH2" : 0, "TH3" : 0, "TH4" : 0, "TH5" : 0, 445 | "PR1" : 0, "PR2" : 0, "PR3" : 0, "PR4" : 0, "PR5" : 0, "VS1" : 0, "VS2" : 0}, 446 | {"sem" : 6, "TH1" : 0, "TH2" : 0, "TH3" : 0, "TH4" : 0, "TH5" : 0, 447 | "PR1" : 0, "PR2" : 0, "PR3" : 0, "PR4" : 0, "PR5" : 0, "VS1" : 0, "VS2" : 0}, 448 | {"sem" : 7, "TH1" : 0, "TH2" : 0, "TH3" : 0, "TH4" : 0, "TH5" : 0, 449 | "PR1" : 0, "PR2" : 0, "PR3" : 0, "PR4" : 0, "PR5" : 0, "VS1" : 0, "VS2" : 0}, 450 | {"sem" : 8, "TH1" : 0, "TH2" : 0, "TH3" : 0, "TH4" : 0, "TH5" : 0, 451 | "PR1" : 0, "PR2" : 0, "PR3" : 0, "PR4" : 0, "PR5" : 0, "VS1" : 0, "VS2" : 0} 452 | ]; 453 | for (sem in userMarks) { 454 | for (key in userMarks[sem]) { 455 | // console.log("key: "+key); 456 | if (!json[sem].hasOwnProperty(key)) 457 | return false; 458 | } 459 | } 460 | return true; 461 | }; 462 | 463 | function JSON2DL(data) { 464 | var html = "
    "; 465 | for(var key in data) { 466 | html += '
    ' + key + '
    ' + data[key] + '
    '; 467 | } 468 | return html + "
    "; 469 | }; 470 | -------------------------------------------------------------------------------- /js/bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.1 (http://getbootstrap.com) 3 | * Copyright 2011-2014 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.1",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a(f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.1",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active"));a&&this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),c.preventDefault()}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.1",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c="prev"==a?-1:1,d=this.getItemIndex(b),e=(d+c)%this.$items.length;return this.$items.eq(e)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));return a>this.$items.length-1||0>a?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i="next"==b?"first":"last",j=this;if(!f.length){if(!this.options.wrap)return;f=this.$element.find(".item")[i]()}if(f.hasClass("active"))return this.sliding=!1;var k=f[0],l=a.Event("slide.bs.carousel",{relatedTarget:k,direction:h});if(this.$element.trigger(l),!l.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var m=a(this.$indicators.children()[this.getItemIndex(f)]);m&&m.addClass("active")}var n=a.Event("slid.bs.carousel",{relatedTarget:k,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),j.sliding=!1,setTimeout(function(){j.$element.trigger(n)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(n)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&"show"==b&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a(this.options.trigger).filter('[href="#'+b.id+'"], [data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.1",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0,trigger:'[data-toggle="collapse"]'},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.find("> .panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":a.extend({},e.data(),{trigger:this});c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){b&&3===b.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=c(d),f={relatedTarget:this};e.hasClass("open")&&(e.trigger(b=a.Event("hide.bs.dropdown",f)),b.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger("hidden.bs.dropdown",f)))}))}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.1",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('