jQuery试卷自动排版系统
需求
根据提供的试卷题目(是一个干净的只有“数据”的HTML网页)生成一份多页的试卷,用户能执行翻页、具有答题时间限制,展示给用户的试卷中题目需要占用尽量少的空间(比如选择题中把两条较短的选项由两行合并到一行)、同一道题目不要跨页面显示以方便答题者,管理员能够改变试卷的样式(字体、颜色、行距、页面边距,像字处理软件一样……),题目之间可以插入一些说明性的文字(比如告知答题者作答的须知等等)。题目提干、选择题的选项、说明文字可以包含多媒体信息(文字、图片、列表、表格、视频等等……)。选择题选项数目不限、单选多选不限。翻页要有可订制的动画效果
提供的试卷样板类似如下(Input):
01 | < ol id = "olThePaper" > |
02 | < div class = "Desc" >选择题:说明文字。说明文字。说明文字。说明文字。说明文字。说明文字。说明文字。说明文字。说明文字。说明文字。说明文字。说明文字。说明文字。说明文字。</ div > |
03 | < div class = "Problem" id = "1" > |
04 | < li >1.你认为怎样的老师是好老师?</ li > |
05 | < div class = "Choices" > |
06 | < label >< input type = "radio" name = "prob1" value = "A" />和学生平等相处,能全面满足学生各种需要</ label > |
07 | < label >< input type = "radio" name = "prob1" value = "B" />所在教学班的成绩优于其他平行班</ label > |
08 | < label >< input type = "radio" name = "prob1" value = "C" />严格管理学生、所带的班级班风良好</ label > |
09 | < label >< input type = "radio" name = "prob1" value = "D" />父母般地关心学生的生活和情绪状态</ label > |
10 | </ div > |
11 | </ div > |
12 | < div class = "Problem" id = "2" > |
13 | < li >2.一位有15年教龄的英语教师,教了多年高三,可谓学校的核心骨干。一次接受邀请到外校介绍教学经验,台下有老师发表了观点并问到几个英语教法发面的问题,一下子把她给卡住了。这是因为</ li > |
14 | < div class = "Choices" > |
15 | < label >< input type = "radio" name = "prob2" value = "A" />她最近工作太累,注意力不够集中。</ label > |
16 | < label >< input type = "radio" name = "prob2" value = "B" />提问老师的观点和她的有很大不同。</ label > |
17 | < label >< input type = "radio" name = "prob2" value = "C" />由于长时间在教学一线拼搏,她对教学理论问题的关注度不高。</ label > |
18 | < label >< input type = "radio" name = "prob2" value = "D" />对学科教学的归纳和思考少,一时加工不过来。</ label > |
19 | </ div > |
20 | </ div > |
21 | < div class = "Problem" id = "3" > |
22 | < li >3.哪张图片最好看?</ li > |
23 | < div class = "Choices" > |
24 | < label >< input type = "radio" name = "prob3" value = "A" />这一张< img src = "img1.png" height = "300px" width = "400px" alt = "img1" />好看。</ label > |
25 | < label >< input type = "radio" name = "prob3" value = "B" />这一张< img src = "img2.png" height = "300px" width = "400px" alt = "img2" />好看。</ label > |
26 | < label >< input type = "radio" name = "prob3" value = "C" />这一张< img src = "img3.png" height = "300px" width = "400px" alt = "img3" />好看。</ label > |
27 | < label >< input type = "radio" name = "prob3" value = "D" />这一张< img src = "img4.png" height = "300px" width = "400px" alt = "img4" />好看。</ label > |
28 | < label >< input type = "radio" name = "prob3" value = "E" />不知道。</ label > |
29 | </ div > |
30 | </ div > |
31 | < div class = "Desc" >填空题和选择题:一大堆的说明文字。一大堆的说明文字。一大堆的说明文字。一大堆的说明文字。一大堆的说明文字。</ div > |
32 | < div class = "Problem" id = "4" > |
33 | < li >4.床前明月光,< input type = "text" name = "prob4" /></ li > |
34 | </ div > |
35 | < div class = "Problem" id = "5" > |
36 | < li >5.你认为怎样的老师是好老师?</ li > |
37 | < div class = "Choices" > |
38 | < label >< input type = "checkbox" name = "prob6" value = "D" />和</ label > |
39 | < label >< input type = "checkbox" name = "prob6" value = "A" />所</ label > |
40 | < label >< input type = "checkbox" name = "prob6" value = "B" />严</ label > |
41 | < label >< input type = "checkbox" name = "prob6" value = "C" />父</ label > |
42 | < label >< input type = "checkbox" name = "prob6" value = "E" />和班的成绩班的成绩班的成绩班的成绩班的成绩</ label > |
43 | < label >< input type = "checkbox" name = "prob6" value = "F" />所班的成绩班的成绩班的成绩</ label > |
44 | < label >< input type = "checkbox" name = "prob6" value = "G" />严班的班的成绩班的成绩班的成绩班的成绩</ label > |
45 | < label >< input type = "checkbox" name = "prob6" value = "H" />啊</ label > |
46 | </ div > |
47 | </ div > |
48 | </ ol > |
思路
面对这种需求该怎么办呢?使用JavaScript了,看来。后来决定用jQuery,Aptana作IDE(虽然jQuery支持库在Windows上死活装不上去,换了个OS就好了,奇怪),格式么就用CSS了。
具体步骤:
- 导入试卷题目HTML
- 对所有选择题进行排版,把一行划分为四个位置,使选项尽量适应一个位置、两个位置或四个位置(也就是一行四项、一行两项或者一行一项的效果)
- 对所有题目进行分页
思路还是清晰的,但是由于浏览器众多,还是比较麻烦的,并且我是新手,没接触过jQuery之前……
实现
页面文件(和例子不同,但是格式一样的)
001 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> |
002 | < html xmlns = "http://www.w3.org/1999/xhtml" > |
003 | < head > |
004 | < title >No title...</ title > |
005 | < meta http-equiv = "Content-Type" content = "text/html; charset=utf-8" /> |
006 | < script language = "JavaScript" src = "lib/jquery/jquery-1.4.2.js" type = "text/javascript" ></ script > |
007 | < script language = "JavaScript" src = "lib/countdown/jquery.countdown.pack.js" type = "text/javascript" ></ script > |
008 | < script language = "JavaScript" src = "TestPaperProcessor.js" type = "text/javascript" ></ script > |
009 | < link href = "style.css" rel = "stylesheet" type = "text/css" /> |
010 | </ head > |
011 | < body > |
012 | < div id = "divToolbar" > |
013 | < div id = "divPrev" >PrevPage</ div > |
014 | < div id = "divNext" >NextPage</ div > |
015 | < div id = "divPageInfo" >Loading the test...</ div > |
016 | < div id = "divTimer" ></ div > |
017 | </ div > |
018 | < form id = "formPaper" action = "demo.html" method = "post" accept-charset = "utf-8" > |
019 | < ul > |
020 | < div class = "Display" id = "divLeft" > |
021 | left <!--the left page--> |
022 | </ div > |
023 | < div class = "Display" id = "divRight" > |
024 | right <!--the right page--> |
025 | </ div > |
026 | </ ul > |
027 | < ol id = "olThePaper" > |
028 | < div class = "Desc" >选择题:说明文字。说明文字。说明文字。说明文字。说明文字。说明文字。说明文字。说明文字。说明文字。说明文字。说明文字。说明文字。说明文字。说明文字。</ div > |
029 | < div class = "Problem" id = "1" > |
030 | < li >1你认为怎样的老师是好老师?</ li > |
031 | < div class = "Choices" > |
032 | < label > |
033 | < input type = "radio" name = "prob1" value = "D" />和学生平等相处,能全面满足学生各种需要 |
034 | </ label > |
035 | < label > |
036 | < input type = "radio" name = "prob1" value = "A" />所在教学班的成绩优于其他平行班 |
037 | </ label > |
038 | < label > |
039 | < input type = "radio" name = "prob1" value = "B" />严格管理学生/所带的班级班风良好 |
040 | </ label > |
041 | < label > |
042 | < input type = "radio" name = "prob1" value = "C" />父母般地关心学生的生活和情绪状态 |
043 | </ label > |
044 | </ div > |
045 | </ div > |
046 | < div class = "Problem" id = "2" > |
047 | < li >2你认为怎样的老师是好老师?</ li > |
048 | < div class = "Choices" > |
049 | < label > |
050 | < input type = "radio" name = "prob2" value = "D" />和学生平jlsdjklsdf生各种需要 |
051 | </ label > |
052 | < label > |
053 | < input type = "radio" name = "prob2" value = "A" />所 |
054 | </ label > |
055 | < label > |
056 | < input type = "radio" name = "prob2" value = "B" />严格好 |
057 | </ label > |
058 | < label > |
059 | < input type = "radio" name = "prob2" value = "C" />父母关心学生的生活和情绪状态 |
060 | </ label > |
061 | </ div > |
062 | </ div > |
063 | < div class = "Problem" id = "3" > |
064 | < li >3你认为怎样的老师是好老师?</ li > |
065 | < div class = "Choices" > |
066 | < label > |
067 | < input type = "radio" name = "prob3" value = "D" />和学生平等相处,能全面满足学生各种需要 |
068 | </ label > |
069 | < label > |
070 | < input type = "radio" name = "prob3" value = "A" />所在教学班的成绩优于其他平行班 |
071 | </ label > |
072 | < label > |
073 | < input type = "radio" name = "prob3" value = "B" />严格管理学生/所带的班级班风良好 |
074 | </ label > |
075 | < label > |
076 | < input type = "radio" name = "prob3" value = "C" />父母般地关心学生的生活和情绪状态 |
077 | </ label > |
078 | </ div > |
079 | </ div > |
080 | < div class = "Problem" id = "4" > |
081 | < li >4你认为怎样的老师是好老师?</ li > |
082 | < div class = "Choices" > |
083 | < label > |
084 | < input type = "radio" name = "prob4" value = "D" />和学生平等相处,能全面满足学和学生平等相处,能全面满足学和学生平等相处,能全面满足学和学生平等相处,能全面满足学和学生平等相处,能全面满足学和学生平等相处,能全面满足学和学生平等相处,能全面满足学和学生平等相处,能全面满足学和学生平等相处,能全面满足学生各种需要 |
085 | </ label > |
086 | < label > |
087 | < input type = "radio" name = "prob4" value = "A" />所在教学班的成绩优于其他平行班 |
088 | </ label > |
089 | < label > |
090 | < input type = "radio" name = "prob4" value = "B" />严格管理学生/所带的班级班风良好 |
091 | </ label > |
092 | < label > |
093 | < input type = "radio" name = "prob4" value = "C" />父母般地关心学生的生活和情绪状态 |
094 | </ label > |
095 | </ div > |
096 | </ div > |
097 | < div class = "Desc" >还是选择题:一大堆的说明文字。一大堆的说明文字。一大堆的说明文字。一大堆的说明文字。一大堆的说明文字。</ div > |
098 | < div class = "Problem" id = "10" > |
099 | < li >5你认为怎样的老师是好老师?</ li > |
100 | < div class = "Choices" > |
101 | < label > |
102 | < input type = "radio" name = "prob5" value = "D" />和10学生平等相处,能全面满足学生各种需要 |
103 | </ label > |
104 | < label > |
105 | < input type = "radio" name = "prob5" value = "A" />所10在教学班的成绩优于其他平行班 |
106 | </ label > |
107 | < label > |
108 | < input type = "radio" name = "prob5" value = "B" />严10jhjhjhjhkljlkjjkljjkjjkllkjlkjljkjljlkj格管文字 |
109 | </ label > |
110 | < label > |
111 | < input type = "radio" name = "prob5" value = "C" />父10母般地关心学生的生活和情绪状态 |
112 | </ label > |
113 | </ div > |
114 | </ div > |
115 | < div class = "Problem" id = "5" > |
116 | < li >5你认为怎样的老师是好老师?</ li > |
117 | < div class = "Choices" > |
118 | < label > |
119 | < input type = "radio" name = "prob5" value = "D" />和学生平等相处,能全面满足学生各种需要 |
120 | </ label > |
121 | < label > |
122 | < input type = "radio" name = "prob5" value = "A" />所在教学班的成绩优于其他平行班 |
123 | </ label > |
124 | < label > |
125 | < input type = "radio" name = "prob5" value = "B" />严jhjhjhjhkljlkjjkljjkjjkllkjlkjljkjljlkj格管< img src = "aaaa9.jpg" height = "300px" width = "400px" alt = "pic" />文字 |
126 | </ label > |
127 | < label > |
128 | < input type = "radio" name = "prob5" value = "C" />父母般地关心学生的生活和情绪状态 |
129 | </ label > |
130 | </ div > |
131 | </ div > |
132 | < div class = "Problem" id = "6" > |
133 | < li >6你认为怎样的老师是好老师?</ li > |
134 | < div class = "Choices" > |
135 | < label > |
136 | < input type = "radio" name = "prob6" value = "D" />和 |
137 | </ label > |
138 | < label > |
139 | < input type = "radio" name = "prob6" value = "A" />所 |
140 | </ label > |
141 | < label > |
142 | < input type = "radio" name = "prob6" value = "B" />严 |
143 | </ label > |
144 | < label > |
145 | < input type = "radio" name = "prob6" value = "C" />父 |
146 | </ label > |
147 | < label > |
148 | < input type = "radio" name = "prob6" value = "E" />和班的成绩班的成绩班的成绩班的成绩班的成绩 |
149 | </ label > |
150 | < label > |
151 | < input type = "radio" name = "prob6" value = "F" />所班的成绩班的成绩班的成绩 |
152 | </ label > |
153 | < label > |
154 | < input type = "radio" name = "prob6" value = "G" />严班的班的成绩班的成绩班的成绩班的成绩 |
155 | </ label > |
156 | < label > |
157 | < input type = "radio" name = "prob6" value = "H" />父 |
158 | </ label > |
159 | </ div > |
160 | </ div > |
161 | </ ol > |
162 | </ form > |
163 | </ body > |
164 | </ html > |
样式文件(CSS)
01 | /* YahooUI CSS Reset */ |
02 | body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,td { padding: 0; margin: 0; } |
03 | table { border-collapse: collapse; border-spacing: 0; } |
04 | fieldset,img { border: 0; } |
05 | address,caption,cite,code,dfn,em,strong,th,var { font-weight: normal; font-style: normal; } |
06 | ol,ul { list-style: none; } |
07 | caption,th { text-align: left; } |
08 | h1,h2,h3,h4,h5,h6 { font-weight: normal; font-size: 100%; } |
09 | q:before,q:after { content:''; } |
10 | abbr,acronym { border: 0;} |
11 | |
12 | label { padding: 0; margin: 0; } |
13 | |
14 | /* My css */ |
15 | .Choices { line-height: 150%; margin: 5px 0; } |
16 | .Page { height: 500px; border: solid 1px gray; } |
17 | #olThePaper, .Display { padding: 0; width: 500px; } |
18 | /* NOTICE: the width of .Display and #olThePaper should be the SAME. */ |
19 | .Display { float: left; } |
20 | |
21 | #divToolbar { height: 35px; } |
22 | #divPrev, #divNext { float: left; width: 100px; height: 30px; border: solid 1px green; background-color: #999999; } |
23 | #divPageInfo { float: left; width: 100px; height: 30px; } |
24 | #divTimer { float: left; width: 500px; height: 30px; } |
25 | |
26 | |
27 | /*for debugging... perhaps for non-IE only*/ |
28 | /**label { outline: dotted 1px red; background-color: gray; }**/ |
29 | /**div {outline: dashed 1px blue;}**/ |
下面是重点,TTestPaperProcessor.js:
001 | /** |
002 | * |
003 | * @param {String} PaperOlId the id value of the ol tags indicating pages. |
004 | * @param {String} ProblemClass the css class name for problem area. |
005 | * @param {String} DescClass the css class name for description area. |
006 | * @param {String} ChoicesClass the css class name for choices area. |
007 | * @param {String} LeftPageId the id of the left page. |
008 | * @param {String} RightPageId the id of the right page. |
009 | * @author ExSystem<exsystemchina@gmail.com> |
010 | */ |
011 | function TTestPaperProcessor(PaperOlId, ProblemClass, DescClass, ChoicesClass, LeftPageId, RightPageId) { |
012 | this .FPaperOlId = PaperOlId; |
013 | this .FProblemClass = ProblemClass; |
014 | this .FDescClass = DescClass; |
015 | this .FChoicesClass = ChoicesClass; |
016 | this .FLeftPageId = LeftPageId; |
017 | this .FRightPageId =RightPageId; |
018 | $( '#' + this .FLeftPageId).html( '' ); |
019 | $( '#' + this .FRightPageId).html( '' ); |
020 | this ._FormatProblemOptions(); |
021 | this ._DivideIntoPages(); |
022 | this .setCurrPage(1); |
023 | } |
024 | |
025 | TTestPaperProcessor.prototype = { |
026 | FPaperOlId: '' , //the id property of the ol tag contains the whole test paper. |
027 | FProblemClass: '' , //the css class name for problem area. |
028 | FDescClass: '' , //the css class name for description area. |
029 | FChoicesClass: '' , //the css class name for choices area. |
030 | FLeftPageId: '' , //the left page. |
031 | FRightPageId: '' , //the right page. |
032 | CPageClass: 'Page' , |
033 | FIsDisplayTableSupported: null , //whether the browser is the EVIL M$IE6,7 that does not support display: table(-cell). |
034 | FCurrPage: 0, //start from 1, 0 for no page has been displayed yet. |
035 | FPageCount: 0, //page count. |
036 | // /** |
037 | // * Get external css stylesheet info. |
038 | // * @param {String} Selector The selector in the css style sheet. |
039 | // * @param {String} Property The property name. |
040 | // * @return {String} The value of the property, or null for undefined property. |
041 | // */ |
042 | // _GetCssInfo: function(Selector, Property) { |
043 | // var mCss = document.styleSheets[0].cssRules || document.styleSheets[0].rules; |
044 | // for (var mIndex = 0; mIndex < mCss.length; ++mIndex) { |
045 | // if (mCss[mIndex].selectorText.toLowerCase() == Selector) { |
046 | // return mCss[mIndex].style[Property]; |
047 | // } |
048 | // } |
049 | // return null; |
050 | // }, |
051 | |
052 | /** |
053 | * @return {Boolean} |
054 | */ |
055 | _IsDisplayTableSupported: function () { |
056 | if ( this .FIsDisplayTableSupported != null ) { |
057 | return this .FIsDisplayTableSupported; |
058 | } |
059 | |
060 | this .FIsDisplayTableSupported = !(jQuery.browser.msie && jQuery.browser.version < 8.0); |
061 | return this .FIsDisplayTableSupported; |
062 | }, |
063 | |
064 | /** |
065 | * Formats radios and checkboxes for the Choices quiz. |
066 | */ |
067 | _FormatProblemOptions: function () { |
068 | var mThis = this ; |
069 | var mSelector = '.' + this .FProblemClass + ' .' + this .FChoicesClass; |
070 | $(mSelector).each( function () { |
071 | //Rearrange the options for each problem ordered by offsetWidth of the label tag. |
072 | var mLabels = new Array(); |
073 | mLabels = jQuery.makeArray($( 'label' , this )); |
074 | mLabels.sort( function (First, Second) { |
075 | return $(Second).outerWidth( true ) > $(First).outerWidth( true ); |
076 | }); |
077 | $(mLabels).appendTo( this ); |
078 | |
079 | //Layout the options into the appropreate form. |
080 | var mSlots = -1; //Force to create a new row, inside the while() loop. |
081 | var mSlotWidth = $(mSelector).width() / 4.0; |
082 | var mCellSize = 0; |
083 | if (mThis._IsDisplayTableSupported()) { |
084 | while (mLabels.length > 0) { |
085 | //alert($(mLabels[0]).outerWidth(true) + '::' + $(mLabels[0]).outerHeight(true) + '::' + $(mLabels[0]).html()); |
086 | if (mSlots <= 0) { //If no empty slot, create a new row. |
087 | mCurrRow = $( '<div class="___table" style="display: table;"></div>' ); |
088 | mCurrRow.appendTo( this ); |
089 | mSlots = 4; |
090 | mCellSize = 0; |
091 | |
092 | var mRealCellWidth = $(mLabels[0]).outerWidth( true ); |
093 | if (mRealCellWidth < mSlotWidth) { |
094 | mCellSize = 1; |
095 | } |
096 | if (mRealCellWidth >= mSlotWidth && mRealCellWidth < mSlotWidth * 2) { |
097 | mCellSize = 2; |
098 | } |
099 | if (mRealCellWidth >= mSlotWidth * 2) { |
100 | mCellSize = 4; |
101 | } |
102 | } |
103 | mSlots -= mCellSize; |
104 | if (mSlots >= 0) { //If empty slots exists, put the cell into the row. |
105 | mLabel = mLabels.shift(); |
106 | $(mLabel).addClass( '___cell' ); |
107 | $(mLabel).css( 'display' , 'table-cell' ); |
108 | $(mLabel).appendTo(mCurrRow); |
109 | } |
110 | } |
111 | $( '.___table' ).each( function () { //Align all the tables and cells. |
112 | $( this ).css( 'width' , '100%' ); |
113 | var mCellWidth = 100 / $( '.___cell' , this ).length; |
114 | $( '.___cell' , this ).css( 'width' , mCellWidth + '%' ); |
115 | }); |
116 | } |
117 | else { // for the evil M$IE6, use table, tr, td tags. |
118 | while (mLabels.length > 0) { |
119 | if (mSlots <= 0) { //If no empty slot, create a new row. |
120 | mCurrRow = $( '<table class="___table" cellspacing="0" cellpadding="0"></table>' ); |
121 | mRow = $( '<tr></tr>' ); |
122 | mRow.appendTo(mCurrRow); |
123 | mCurrRow.appendTo( this ); |
124 | mSlots = 4; |
125 | mCellSize = 0; |
126 | |
127 | var mRealCellWidth = $(mLabels[0]).attr( 'offsetWidth' ); |
128 | //The EVIL IE only: |
129 | //be sure to use this css reset: table { border-collapse: collapse; border-spacing: 0; } |
130 | //otherwise, 2 lines will be occupied by some long problem options instead of 1. |
131 | //or use this code instead: var mRealCellWidth = $(mLabels[0]).attr('offsetWidth') * 1.3; |
132 | if (mRealCellWidth <= mSlotWidth) { |
133 | mCellSize = 1; |
134 | } |
135 | if (mRealCellWidth > mSlotWidth && mRealCellWidth <= mSlotWidth * 2) { |
136 | mCellSize = 2; |
137 | } |
138 | if (mRealCellWidth > mSlotWidth * 2) { |
139 | mCellSize = 4; |
140 | } |
141 | } |
142 | mSlots -= mCellSize; |
143 | if (mSlots >= 0) { //If empty slots exists, put the cell into the row. |
144 | mLabel = mLabels.shift(); |
145 | mCell = $( '<td class="___cell"></td>' ); |
146 | $(mLabel).appendTo(mCell); |
147 | mCell.appendTo($( 'tr' , mCurrRow)[0]); |
148 | } |
149 | } |
150 | $( '.___table' ).each( function () { //Align all the tables and cells. |
151 | $( this ).css( 'width' , '100%' ); |
152 | var mCellWidth = 100 / $( 'tbody tr .___cell' , this ).length; |
153 | $( 'tbody tr .___cell' , this ).css( 'width' , mCellWidth + '%' ); |
154 | }); |
155 | } |
156 | }); |
157 | }, |
158 | |
159 | /** |
160 | * Create a new page, and add it to the paper. |
161 | * @return {jQuery} the new page. |
162 | */ |
163 | _CreateNewPage: function () { |
164 | ++ this .FPageCount; |
165 | |
166 | mPage = $( '<div class="' + this .CPageClass + '" id="___page_' + this .FPageCount + '"></div>' ); |
167 | mPage.appendTo($( '#' + this .FPaperOlId)); |
168 | |
169 | return mPage; |
170 | }, |
171 | |
172 | /** |
173 | * |
174 | * @param {Number} PageNumber |
175 | * @return {jQuery} |
176 | */ |
177 | _GetPage: function (PageNumber) { |
178 | if (PageNumber < 1 || PageNumber > this .FPageCount) { |
179 | throw new Error( 'invalid page number: ' + PageNumber + '.' ); |
180 | } |
181 | return $( '#___page_' + PageNumber); |
182 | }, |
183 | |
184 | /** |
185 | * |
186 | */ |
187 | _DivideIntoPages: function () { |
188 | var mProblems = $( '.' + this .FProblemClass + ', .' + this .FDescClass); |
189 | var mProblemsCount = mProblems.length; |
190 | var mCurrPage = this ._CreateNewPage(); |
191 | //var mPageHeight = mCurrPage.attr('offsetHeight'); chrome: sometimes 0. safari: always 0, IF PUTTED IN $(window).ready(). |
192 | var mPageHeight = mCurrPage.outerHeight( true ); //the same as the code above. FIX: PUT IT INTO $(window).load(). |
193 | var mUsedPageHeight = 0; |
194 | for ( var mCurrProblem = 0; mCurrProblem < mProblemsCount; ++mCurrProblem) { |
195 | if (mUsedPageHeight + $(mProblems[mCurrProblem]).outerHeight( true ) > mPageHeight) { |
196 | mCurrPage.hide(); |
197 | mCurrPage = this ._CreateNewPage(); |
198 | mPageHeight = mCurrPage.outerHeight( true ); |
199 | mUsedPageHeight = 0; |
200 | } |
201 | $(mProblems[mCurrProblem]).appendTo(mCurrPage); |
202 | mUsedPageHeight += $(mProblems[mCurrProblem]).outerHeight( true ); |
203 | } |
204 | mCurrPage.hide(); |
205 | }, |
206 | /** |
207 | * Get the current page of the left side, started from 1. |
208 | * @return {Number} The current page. |
209 | */ |
210 | getCurrPage: function () { |
211 | if ( this .FPageCount == 0) { |
212 | throw new Error( 'No page has been created yet.' ); |
213 | } |
214 | return this .FCurrPage; |
215 | }, |
216 | /** |
217 | * Trun to a specific page in the left side. |
218 | * @param {Number} Value The page number. |
219 | */ |
220 | setCurrPage: function (Value) { |
221 | if (Value < 1 || Value > this .FPageCount) { |
222 | throw new Error( 'No such page: ' + Value + '.' ); |
223 | } |
224 | this .FCurrPage = parseInt(Value / 2) * 2 + 1; // to get an odd number. |
225 | $( '#' + this .FLeftPageId + ' .' + this .CPageClass).hide(); |
226 | $( '#' + this .FRightPageId + ' .' + this .CPageClass).hide(); |
227 | if ( this .FCurrPage >= 0) { |
228 | $( '#___page_' + this .FCurrPage).appendTo($( '#' + this .FLeftPageId)); |
229 | $( '#___page_' + this .FCurrPage).show( 'fast' ); |
230 | if ( this .FCurrPage < this .FPageCount) { |
231 | ++ this .FCurrPage; |
232 | $( '#___page_' + this .FCurrPage).appendTo($( '#' + this .FRightPageId)); |
233 | $( '#___page_' + this .FCurrPage).show( 'fast' ); |
234 | -- this .FCurrPage; |
235 | } |
236 | } |
237 | }, |
238 | /** |
239 | * @retrun {Number} |
240 | */ |
241 | getPageCount: function () { |
242 | return this .FPageCount; |
243 | }, |
244 | /** |
245 | * |
246 | */ |
247 | Prev: function () { |
248 | this .setCurrPage( this .FCurrPage - 2); |
249 | }, |
250 | /** |
251 | * |
252 | */ |
253 | Next: function () { |
254 | this .setCurrPage( this .FCurrPage + 2); |
255 | } |
256 | }; |
257 | |
258 | //client code goes here... |
259 | $(window).load( function () { |
260 | var obj = new TTestPaperProcessor( 'olThePaper' , 'Problem' , 'Desc' , 'Choices' , 'divLeft' , 'divRight' ); |
261 | $( '#divPrev' ).click( function () { |
262 | try { |
263 | obj.Prev(); |
264 | $( '#divPageInfo' ).text(obj.getCurrPage() + ' of ' + obj.getPageCount()); |
265 | } |
266 | catch (e) { |
267 | alert( 'No such page!' ); |
268 | } |
269 | }); |
270 | $( '#divNext' ).click( function () { |
271 | try { |
272 | obj.Next(); |
273 | $( '#divPageInfo' ).text(obj.getCurrPage() + ' of ' + obj.getPageCount()); |
274 | } |
275 | catch (e) { |
276 | alert( 'No such page!' ); |
277 | } |
278 | }); |
279 | //USAGE: http://keith-wood.name/countdown.html |
280 | function TimeUp() { |
281 | $( '#formPaper' ).submit(); |
282 | } |
283 | $( '#divTimer' ).countdown({ |
284 | until: '+90m' , |
285 | compact: true , |
286 | format: 'HMS' , |
287 | description: '' , |
288 | onExpiry: TimeUp |
289 | }); |
290 | $( '#divPageInfo' ).text(obj.getCurrPage() + ' of ' + obj.getPageCount()); |
291 | }); |