From 8b11d513ad0e1193f9e79c93358b36fd4d930fb2 Mon Sep 17 00:00:00 2001 From: david Date: Mon, 11 Apr 2011 17:43:47 +0000 Subject: [PATCH] =?UTF-8?q?-=20Adaptaci=C3=B3n=20de=20los=20formularios=20?= =?UTF-8?q?a=20iOS=20(iPhone=20/=20iPod)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: https://192.168.0.254/svn/Proyectos.Incam_FormulariosCalidad/trunk@20 e2c41b2c-0c6f-0149-8b81-50b1a9191bb3 --- includes/mobile-view-functions.php | 276 ++++++------- mobile/apple/css/forms.css | 9 + mobile/apple/css/spinningwheel.css | 92 +++++ mobile/apple/images/sw-alpha.png | Bin 0 -> 2249 bytes mobile/apple/images/sw-button-cancel.png | Bin 0 -> 538 bytes mobile/apple/images/sw-button-done.png | Bin 0 -> 767 bytes mobile/apple/images/sw-header.png | Bin 0 -> 682 bytes mobile/apple/images/sw-slot-border.png | Bin 0 -> 126 bytes mobile/apple/javascript/calendar.js | 77 ++++ mobile/apple/javascript/spinningwheel.js | 492 +++++++++++++++++++++++ 10 files changed, 789 insertions(+), 157 deletions(-) create mode 100644 mobile/apple/css/spinningwheel.css create mode 100644 mobile/apple/images/sw-alpha.png create mode 100644 mobile/apple/images/sw-button-cancel.png create mode 100644 mobile/apple/images/sw-button-done.png create mode 100644 mobile/apple/images/sw-header.png create mode 100644 mobile/apple/images/sw-slot-border.png create mode 100644 mobile/apple/javascript/calendar.js create mode 100644 mobile/apple/javascript/spinningwheel.js diff --git a/includes/mobile-view-functions.php b/includes/mobile-view-functions.php index f564b01..38a3efc 100644 --- a/includes/mobile-view-functions.php +++ b/includes/mobile-view-functions.php @@ -156,14 +156,13 @@ EOT; //Website function mobile_display_url($element){ //check for error - $error_class = ''; $error_message = ''; $span_required = ''; $guidelines = ''; + global $lang; if(!empty($element->is_error)){ - $error_class = 'class="error"'; - $error_message = "

{$element->error_message}

"; + $error_message = "

{$element->error_message}

"; } //check for required @@ -173,7 +172,7 @@ EOT; //check for guidelines if(!empty($element->guidelines)){ - $guidelines = "

id}\">{$element->guidelines}

"; + $guidelines = "

id}\">{$element->guidelines}

"; } //check for default value @@ -187,12 +186,14 @@ EOT; } $element_markup = << - -
- -
{$guidelines} {$error_message} - + {$element->title} {$span_required} + {$error_message} + {$guidelines} + EOT; return $element_markup; @@ -201,14 +202,13 @@ EOT; //Email function mobile_display_email($element){ //check for error - $error_class = ''; $error_message = ''; $span_required = ''; $guidelines = ''; + global $lang; if(!empty($element->is_error)){ - $error_class = 'class="error"'; - $error_message = "

{$element->error_message}

"; + $error_message = "

{$element->error_message}

"; } //check for required @@ -218,7 +218,7 @@ EOT; //check for guidelines if(!empty($element->guidelines)){ - $guidelines = "

id}\">{$element->guidelines}

"; + $guidelines = "

id}\">{$element->guidelines}

"; } //check for populated value, if exist, use it instead default_value @@ -227,12 +227,14 @@ EOT; } $element_markup = << - -
- -
{$guidelines} {$error_message} - + {$element->title} {$span_required} + {$error_message} + {$guidelines} +
    +
  • + +
  • +
EOT; return $element_markup; @@ -309,14 +311,13 @@ EOT; //Phone - Simple function mobile_display_simple_phone($element){ //check for error - $error_class = ''; $error_message = ''; $span_required = ''; $guidelines = ''; + global $lang; if(!empty($element->is_error)){ - $error_class = 'class="error"'; - $error_message = "

{$element->error_message}

"; + $error_message = "

{$element->error_message}

"; } //check for required @@ -326,7 +327,7 @@ EOT; //check for guidelines if(!empty($element->guidelines)){ - $guidelines = "

id}\">{$element->guidelines}

"; + $guidelines = "

id}\">{$element->guidelines}

"; } //check for populated value @@ -335,12 +336,14 @@ EOT; } $element_markup = << - -
- -
{$guidelines} {$error_message} - + {$element->title} {$span_required} + {$error_message} + {$guidelines} +
    +
  • + +
  • +
EOT; return $element_markup; @@ -351,15 +354,13 @@ EOT; //Date - Normal function mobile_display_date($element){ //check for error - $error_class = ''; $error_message = ''; $span_required = ''; $guidelines = ''; global $lang; if(!empty($element->is_error)){ - $error_class = 'class="error"'; - $error_message = "

{$element->error_message}

"; + $error_message = "

{$element->error_message}

"; } //check for required @@ -369,7 +370,12 @@ EOT; //check for guidelines if(!empty($element->guidelines)){ - $guidelines = "

id}\">{$element->guidelines}

"; + $guidelines = "

id}\">{$element->guidelines}

"; + } + + //check for populated value, if exist, use it instead default_value + if(!empty($element->populated_value['element_'.$element->id]['default_value'])){ + $element->default_value = $element->populated_value['element_'.$element->id]['default_value']; } $machform_path = ''; @@ -379,36 +385,19 @@ EOT; $element_markup = << - - - / - - - - / - - - - - - - - - Pick a date. - - - {$guidelines} {$error_message} - + {$element->title} {$span_required} + {$error_message} + {$guidelines} + EOT; return $element_markup; @@ -417,15 +406,13 @@ EOT; //Date - Normal function mobile_display_europe_date($element){ //check for error - $error_class = ''; $error_message = ''; $span_required = ''; $guidelines = ''; global $lang; if(!empty($element->is_error)){ - $error_class = 'class="error"'; - $error_message = "

{$element->error_message}

"; + $error_message = "

{$element->error_message}

"; } //check for required @@ -435,45 +422,29 @@ EOT; //check for guidelines if(!empty($element->guidelines)){ - $guidelines = "

id}\">{$element->guidelines}

"; + $guidelines = "

id}\">{$element->guidelines}

"; } - $machform_path = ''; - if(!empty($element->machform_path)){ - $machform_path = $element->machform_path; + //check for populated value, if exist, use it instead default_value + if(!empty($element->populated_value['element_'.$element->id]['default_value'])){ + $element->default_value = $element->populated_value['element_'.$element->id]['default_value']; } + $element_markup = << - - - / - - - - / - - - - - - - - - Pick a date. - - - {$guidelines} {$error_message} - + {$element->title} {$span_required} + {$error_message} + {$guidelines} + EOT; return $element_markup; @@ -483,14 +454,13 @@ EOT; //Multiple Choice function mobile_display_radio($element){ //check for error - $error_class = ''; $error_message = ''; $span_required = ''; $guidelines = ''; + global $lang; if(!empty($element->is_error)){ - $error_class = 'class="error"'; - $error_message = "

{$element->error_message}

"; + $error_message = "

{$element->error_message}

"; } //check for required @@ -500,7 +470,7 @@ EOT; //check for guidelines if(!empty($element->guidelines)){ - $guidelines = "

id}\">{$element->guidelines}

"; + $guidelines = "

id}\">{$element->guidelines}

"; } $option_markup = ''; @@ -527,17 +497,19 @@ EOT; } } - $option_markup .= "id}_{$option->id}\" name=\"element_{$element->id}\" class=\"element radio\" type=\"radio\" value=\"{$option->id}\" {$checked} />\n"; - $option_markup .= "\n"; + $option_markup .= "
  • \n"; + $option_markup .= "".$option->option."\n"; + $option_markup .= "id}_{$option->id}\" name=\"element_{$element->id}\" type=\"radio\" value=\"{$option->id}\" {$checked} />\n"; + $option_markup .= "
  • \n"; } $element_markup = << - - + {$element->title} {$span_required} + {$error_message} + {$guidelines} +
      {$option_markup} - {$guidelines} {$error_message} - +
    EOT; return $element_markup; @@ -626,14 +598,13 @@ EOT; //Dropdown function mobile_display_select($element){ //check for error - $error_class = ''; $error_message = ''; $span_required = ''; $guidelines = ''; + global $lang; if(!empty($element->is_error)){ - $error_class = 'class="error"'; - $error_message = "

    {$element->error_message}

    "; + $error_message = "

    {$element->error_message}

    "; } //check for required @@ -643,10 +614,10 @@ EOT; //check for guidelines if(!empty($element->guidelines)){ - $guidelines = "

    id}\">{$element->guidelines}

    "; + $guidelines = "

    id}\">{$element->guidelines}

    "; } - $option_markup = ''; + $option_markup = "
  • \n"; + $element_markup = << - -
    - -
    {$guidelines} {$error_message} - + EOT; return $element_markup; @@ -801,15 +765,13 @@ EOT; //Time function mobile_display_time($element){ //check for error - $error_class = ''; $error_message = ''; $span_required = ''; $guidelines = ''; global $lang; if(!empty($element->is_error)){ - $error_class = 'class="error"'; - $error_message = "

    {$element->error_message}

    "; + $error_message = "

    {$element->error_message}

    "; } //check for required @@ -819,9 +781,10 @@ EOT; //check for guidelines if(!empty($element->guidelines)){ - $guidelines = "

    id}\">{$element->guidelines}

    "; + $guidelines = "

    id}\">{$element->guidelines}

    "; } + if(!empty($element->populated_value['element_'.$element->id.'_4']['default_value'])){ if($element->populated_value['element_'.$element->id.'_4']['default_value'] == 'AM'){ $selected_am = 'selected'; @@ -844,25 +807,20 @@ EOT; } $element_markup = << - - - : - - - - {$seconds_separator} - - - {$seconds_markup} - - - - {$guidelines} {$error_message} - + {$element->title} {$span_required} + {$error_message} + {$guidelines} +
      +
    • + {$element->title} + HH:MM:SS + + + + + +
    • +
    EOT; return $element_markup; @@ -1931,7 +1889,7 @@ EOT; //If you would like to remove the "Powered by MachForm" link, please contact us at customer.service@appnitro.com before doing so $form_markup = << + @@ -1940,7 +1898,10 @@ EOT; + + + {$form->name} @@ -2334,7 +2295,7 @@ EOT; } $form_markup = << + @@ -2344,6 +2305,7 @@ EOT; + {$form->name} @@ -2494,7 +2456,7 @@ EOT; } $form_markup = << + diff --git a/mobile/apple/css/forms.css b/mobile/apple/css/forms.css index d5d8145..a00237d 100644 --- a/mobile/apple/css/forms.css +++ b/mobile/apple/css/forms.css @@ -70,3 +70,12 @@ textarea.large width:98%; height:7.5em; } + + +.datefield { + color:blue; + float:right; + position:relative; + top:12px; + right:10px; +} diff --git a/mobile/apple/css/spinningwheel.css b/mobile/apple/css/spinningwheel.css new file mode 100644 index 0000000..53c5df3 --- /dev/null +++ b/mobile/apple/css/spinningwheel.css @@ -0,0 +1,92 @@ +#sw-wrapper { + position:absolute; z-index:1000; + left:0; + width:100%; + font-family:helvetica, sans-serif; + background:rgba(0,0,0,0.7); + text-align:left; +} + +#sw-header { + position:relative; + width:100%; height:43px; + border-top:1px solid #000; border-bottom:1px solid #000; + background:url(../images/sw-header.png) 0 0 repeat-x; + opacity: 0.9; +} + +#sw-cancel, #sw-done { + position:absolute; + top:7px; + height:20px; line-height:20px; + padding:0 5px; margin:0; + border-width:5px; + font-size:12px; font-weight:bold; + text-shadow:rgba(0,0,0,0.8) 0 -1px 0; + color:#fff; +} + +#sw-cancel { + left:7px; + float:left; + -webkit-border-image:url(../images/sw-button-cancel.png) 5; +} + +#sw-done { + right:7px; + float:right; + -webkit-border-image:url(../images/sw-button-done.png) 5; +} + +.sw-pressed { opacity:0.4; } + +#sw-slots-wrapper { + position:relative; z-index:999; + display:block; + height:215px; + padding:0 11px; + overflow:hidden; +} + +#sw-slots { + display:table; + width:100%; + background:#fcfcfc; +} + +#sw-slots div { + display:table-cell; + height:100%; + padding-top:86px; + border-left:2px solid #0d0e0f; + background-color:#fcfcfc; + background-image: url(../images/sw-slot-border.png); + background-position: 0 0, 100% 0; + background-repeat: repeat-y; +} + +#sw-slots div:first-child { border:0; } + +#sw-slots ul { + padding:0 0 85px 0; margin:0; + list-style:none; +} + +#sw-slots .sw-right { text-align:right; } +#sw-slots .sw-shrink { width:1%; } +#sw-slots .sw-readonly { background:#ddd; } + +#sw-slots li { + padding:0 8px; + height:44px; + overflow:hidden; + font:bold 24px/44px Helvetica,sans-serif; +} + +#sw-frame { + position:absolute; z-index:1000; + left:0; right:0; bottom:0; + height:183px; + border-width:16px; + -webkit-border-image:url(../images/sw-alpha.png) 16; +} \ No newline at end of file diff --git a/mobile/apple/images/sw-alpha.png b/mobile/apple/images/sw-alpha.png new file mode 100644 index 0000000000000000000000000000000000000000..b80659ac92c8f4796635d414aa00579fbd6229e5 GIT binary patch literal 2249 zcmV;)2sZbLP)XN-h!kW)9@^INd#*d%cso`9TgI3tlGSCQ7Z7CjU1R3_AcOW|gM-TVcY7hMS zxb;S)TD?D){`iL83$ zu5nt71Guml=e%Q%RI1lF1LI&EU1g@MgK^!=xFywXilu;ASS>?$~bCVNCw7OI+D-%qSt%ce5X#G-1vU>>^WIi>2{Nq zzegKNI$7JnM=JWh_VeeH81Rjobuvzl^dXs@>l8AcPkfRY+(N)jeD8pZBv_!RJeKH=RX4Ao?#dqubF)E=@(8T7gzTfLO=Sp-FIi4i~TE$z|RxfT$ zPMo-Ux#~1F*U`3(Xs@fZfEP>%7MVdUPT*oDcyOIZ1OuR~Z>@bd?xzBI_DQvZ6HLGMtHU>;N?`&KlR*v%IiWcrsBzRdY8*9=2&~2dT#Ss%k*YX@=7i>i zpgEyA!GL$M0Vl$$ajw8Yx$drU3yVwXuS=hi+QcOINM`lo^yx3Zy>Uh7 zuuzrsYP&e!kFRfitC3vY#>D>}sjXoTNw02sQ!wBg<5o$pI&zM{$zF=oAiL^fsbawE zBsT=uB+q1SeQT0lUGwd~#4CGQnDp}Z6_i;M!k3%YzkrUhlE;8T% z7YK6Fm)jzh>UKcq%n86Lca;J=AetJf45Y1;z7z?@soOYeT!dt^YB%o#oW7BB1Ww1; z6UrgzD#0uhvGiTzSn>+2#tE0a08YKDbd*YiQU=zXxYjsBR~e~PTIWd#eXaDrA6Z6mj!k(u8SEbv;#0M96NxIixD{(7iWnRA3+B=ZNe!%+85x0X-=>M zff;b;=0sHG08Sk|b_crM4p8HQVw=+L0Ki4ZIGPg}M`X`9nv>WVhaCuwajcvK2%ih% zWH0_hDwQ#_N*k##E)cPl9$kQOVJM|LY<&pvvdB> zoFut?DwoCnrm;gQq3@Gwe{t;H<3qa#2g?^OUY1CuqgCbX(^IMp?d=&E9qk+3Gr0Zy`9I9m)U@;8FGx1P)3M3=TXW7>!2V`KcC# zXdWJk`TlovB6xPBu?gAL#LXQG9%C43yg+k8s4-3=m4+f0WsyTFkxBxoL@J*f{|GPu Xj+YYl&3Z7z00000NkvXXu0mjft{Gwl literal 0 HcmV?d00001 diff --git a/mobile/apple/images/sw-button-cancel.png b/mobile/apple/images/sw-button-cancel.png new file mode 100644 index 0000000000000000000000000000000000000000..cea9e385042e50f0438bc61ab004ede850f9700c GIT binary patch literal 538 zcmV+#0_FXQP)ccdjO;G1u%jVv4*m&^GYS3)5`uAM^FP3_@FO86P1wqhdf!WHDz>rIy75ik zz02M8bML(#M=cB#~*F!h4C&8Hq$$Nbu5ASC7oSh9a z9F0aNj8B|0#zYz}_4<~+-G_IR#W`bq!69}7bo(JcHFd7D`UlJ|c96)tHevu8hT#k9 z7P)f`{A#r#)YP?}K_#HhNPm-8q)vgyK>kaluIZ!k8>#Q~cY%5xF=wZV zv;nDyq81cQFU5jV1&>v7QZI^sKoJircoET)h!;T+j{&jx7eqm!UTS+NN)<5_#L}WM zX<`#&c6WR;+f6o`O}c3_;pHte^S<}J_h#NMfsHYB{pS6-g-@4CrQ!fL3_o}rgwlVJ zh`N$II+A|$@WCxPC;n0wuV(Va%Ea(U687#(KwwAED<)L`mSJ`IJAC>00d}ca)v6d~NE-9)aLIRM2MfRNe`*{`4XFkj!!!B8ZM-njJGLdBx%fx5u) z1=Ixd2P0u13^d)4UWK`3Vm*^K`Q*+$h~p2dAx5YV!@!Ucv=>9*F~P8=8J?nbuGbmc z=5#C^6S>rT#8QIl96@y*^Qn7`&4sF?XyS-54Vh}&WNP=LVJex(f!53Lxdp0u1a&)O zj&mprB@(+;rs6&k{8?J&R2B-6t?Ju1Z8?0w^!M62(A-+jaw_r6RFOJ;()Ln%AIu)E zGe2H(+FDBj%+Ai4)6JZ?&5Ql4epH0wL_SO1!LZXYGnsbkbG7XQ~h-hwu5;7+eKhE`DQ9;3$OTXdP{cS?zM}*xe;r!Ro;O^NgsqvXpW64*z xwn!Qd`2eaRlqibQO}9fSpkxtnMNIq`U;u;zQKbchSo#0}002ovPDHLkV1lg2X)*u+ literal 0 HcmV?d00001 diff --git a/mobile/apple/images/sw-header.png b/mobile/apple/images/sw-header.png new file mode 100644 index 0000000000000000000000000000000000000000..db4ec279a18d342112b00985b69bc539487a7bbd GIT binary patch literal 682 zcmV;b0#*HqP)o%AsrnZBO@ay zC@5Q7TO}nWJ3Bk0qoWxa859&07Z(>C92^=N8W zE=^5M6%`d89v(I}HdR$sA0Hn-KR;7bQ!OnmFfcG)US2&tJxfbVLPA0>FE3zVU_(Pg zR#sL?Nl8aXM>jV&VPRoKMMY6jQC(eKL_|bNN=hIgATu*FJUl!sEG#}gK2lOrG&D3+ zR8&k%Oe-rZI5;?0S67WnzCi#00fR|IK~#9!Y|-m-qCgY`;5MMkE-N5c1r#+A?{`En zX5as@_RJZ9q>8V)s(a4g!Jk&xFWG*%XG{6UY0ggb6PwF7ezn3nj@R*;#jpKu9V3b3 zBuKT|O?12DY2ccC%$P7!_8B!|Jf2 z$QEeeyjYwUXG+rqlRKN-C*Rz0d#~NzZ;S?hx57?}c2V>deNiHsJ48`5hz2!!h@i}} zGAqkLDbLv;6OhhWI!oD1z7YgL8l;rqJ52L@non6??;LnO@dSIr8%6XJe_LVnlQ;4x zBY2+I_xg-R1^tHAw-^mrx^C$fMYcc#rmma1NoktEHfy$NznHL%nr&2P1BR*^syx%E zAXL>*4Jl2F^LRWC$04O@0_A#Du1bv_0u~-wg3PC literal 0 HcmV?d00001 diff --git a/mobile/apple/images/sw-slot-border.png b/mobile/apple/images/sw-slot-border.png new file mode 100644 index 0000000000000000000000000000000000000000..d9f60260abf8025e872b53cdbd75fce67c042701 GIT binary patch literal 126 zcmeAS@N?(olHy`uVBq!ia0vp^%plAGA``#4_5vx%64!{5;QX|b^2DN42FH~Aq*MjZ z+{E 11) { ap = "PM"; } + if (results.keys[0] > 12) { results.keys[0] = results.keys[0] - 12; } + if (results.keys[0] == 0) { results.keys[0] = 12; } + + document.getElementById(elem1).innerHTML = results.values.join(' '); + document.getElementById(elem2).value = results.keys.join(' '); + document.getElementById(elem3).value = results.keys[0]; + document.getElementById(elem4).value = results.keys[1]; + document.getElementById(elem5).value = results.keys[2]; + document.getElementById(elem6).value = ap; + }); + + SpinningWheel.open(); +} + +function openCalendar(elem1,elem2,elem3,elem4,elem5) { + var now = new Date(); + var days = { }; + var years = { }; + var months = { 1: 'Ene', 2: 'Feb', 3: 'Mar', 4: 'Abr', 5: 'May', 6: 'Jun', 7: 'Jul', 8: 'Ago', 9: 'Sep', 10: 'Oct', 11: 'Nov', 12: 'Dic' }; + + for( var i = 1; i < 32; i += 1 ) { + days[i] = i; + } + + for( i = now.getFullYear()-10; i < now.getFullYear()+10; i += 1 ) { + years[i] = i; + } + + SpinningWheel.addSlot(days, 'right', now.getDate()); + SpinningWheel.addSlot(months, '', now.getMonth()); + SpinningWheel.addSlot(years, 'right', now.getFullYear()); + + SpinningWheel.setCancelAction(function(){ + //document.getElementById(elem1).innerHTML = "cancelled"; + }); + SpinningWheel.setDoneAction(function(){ + var results = SpinningWheel.getSelectedValues(); + document.getElementById(elem1).innerHTML = results.values.join(' '); + document.getElementById(elem2).value = results.keys.join(' '); + document.getElementById(elem3).value = results.keys[0]; + document.getElementById(elem4).value = results.keys[1]; + document.getElementById(elem5).value = results.keys[2]; + }); + + SpinningWheel.open(); +} + diff --git a/mobile/apple/javascript/spinningwheel.js b/mobile/apple/javascript/spinningwheel.js new file mode 100644 index 0000000..c71d5e6 --- /dev/null +++ b/mobile/apple/javascript/spinningwheel.js @@ -0,0 +1,492 @@ +/** + * + * Find more about the Spinning Wheel function at + * http://cubiq.org/spinning-wheel-on-webkit-for-iphone-ipod-touch/11 + * + * Copyright (c) 2009 Matteo Spinelli, http://cubiq.org/ + * Released under MIT license + * http://cubiq.org/dropbox/mit-license.txt + * + * Version 1.4 - Last updated: 2009.07.09 + * + */ + +var SpinningWheel = { + cellHeight: 44, + friction: 0.003, + slotData: [], + + + /** + * + * Event handler + * + */ + + handleEvent: function (e) { + if (e.type == 'touchstart') { + this.lockScreen(e); + if (e.currentTarget.id == 'sw-cancel' || e.currentTarget.id == 'sw-done') { + this.tapDown(e); + } else if (e.currentTarget.id == 'sw-frame') { + this.scrollStart(e); + } + } else if (e.type == 'touchmove') { + this.lockScreen(e); + + if (e.currentTarget.id == 'sw-cancel' || e.currentTarget.id == 'sw-done') { + this.tapCancel(e); + } else if (e.currentTarget.id == 'sw-frame') { + this.scrollMove(e); + } + } else if (e.type == 'touchend') { + if (e.currentTarget.id == 'sw-cancel' || e.currentTarget.id == 'sw-done') { + this.tapUp(e); + } else if (e.currentTarget.id == 'sw-frame') { + this.scrollEnd(e); + } + } else if (e.type == 'webkitTransitionEnd') { + if (e.target.id == 'sw-wrapper') { + this.destroy(); + } else { + this.backWithinBoundaries(e); + } + } else if (e.type == 'orientationchange') { + this.onOrientationChange(e); + } else if (e.type == 'scroll') { + this.onScroll(e); + } + }, + + + /** + * + * Global events + * + */ + + onOrientationChange: function (e) { + window.scrollTo(0, 0); + this.swWrapper.style.top = window.innerHeight + window.pageYOffset + 'px'; + this.calculateSlotsWidth(); + }, + + onScroll: function (e) { + this.swWrapper.style.top = window.innerHeight + window.pageYOffset + 'px'; + }, + + lockScreen: function (e) { + e.preventDefault(); + e.stopPropagation(); + }, + + + /** + * + * Initialization + * + */ + + reset: function () { + this.slotEl = []; + + this.activeSlot = null; + + this.swWrapper = undefined; + this.swSlotWrapper = undefined; + this.swSlots = undefined; + this.swFrame = undefined; + }, + + calculateSlotsWidth: function () { + var div = this.swSlots.getElementsByTagName('div'); + for (var i = 0; i < div.length; i += 1) { + this.slotEl[i].slotWidth = div[i].offsetWidth; + } + }, + + create: function () { + var i, l, out, ul, div; + + this.reset(); // Initialize object variables + + // Create the Spinning Wheel main wrapper + div = document.createElement('div'); + div.id = 'sw-wrapper'; + div.style.top = window.innerHeight + window.pageYOffset + 'px'; // Place the SW down the actual viewing screen + div.style.webkitTransitionProperty = '-webkit-transform'; + div.innerHTML = '
    Cancelar
    Guardar
    '; + + document.body.appendChild(div); + + this.swWrapper = div; // The SW wrapper + this.swSlotWrapper = document.getElementById('sw-slots-wrapper'); // Slots visible area + this.swSlots = document.getElementById('sw-slots'); // Pseudo table element (inner wrapper) + this.swFrame = document.getElementById('sw-frame'); // The scrolling controller + + // Create HTML slot elements + for (l = 0; l < this.slotData.length; l += 1) { + // Create the slot + ul = document.createElement('ul'); + out = ''; + for (i in this.slotData[l].values) { + out += '
  • ' + this.slotData[l].values[i] + '<' + '/li>'; + } + ul.innerHTML = out; + + div = document.createElement('div'); // Create slot container + div.className = this.slotData[l].style; // Add styles to the container + div.appendChild(ul); + + // Append the slot to the wrapper + this.swSlots.appendChild(div); + + ul.slotPosition = l; // Save the slot position inside the wrapper + ul.slotYPosition = 0; + ul.slotWidth = 0; + ul.slotMaxScroll = this.swSlotWrapper.clientHeight - ul.clientHeight - 86; + ul.style.webkitTransitionTimingFunction = 'cubic-bezier(0, 0, 0.2, 1)'; // Add default transition + + this.slotEl.push(ul); // Save the slot for later use + + // Place the slot to its default position (if other than 0) + if (this.slotData[l].defaultValue) { + this.scrollToValue(l, this.slotData[l].defaultValue); + } + } + + this.calculateSlotsWidth(); + + // Global events + document.addEventListener('touchstart', this, false); // Prevent page scrolling + document.addEventListener('touchmove', this, false); // Prevent page scrolling + window.addEventListener('orientationchange', this, true); // Optimize SW on orientation change + window.addEventListener('scroll', this, true); // Reposition SW on page scroll + + // Cancel/Done buttons events + document.getElementById('sw-cancel').addEventListener('touchstart', this, false); + document.getElementById('sw-done').addEventListener('touchstart', this, false); + + // Add scrolling to the slots + this.swFrame.addEventListener('touchstart', this, false); + }, + + open: function () { + this.create(); + + this.swWrapper.style.webkitTransitionTimingFunction = 'ease-out'; + this.swWrapper.style.webkitTransitionDuration = '400ms'; + this.swWrapper.style.webkitTransform = 'translate3d(0, -260px, 0)'; + }, + + + /** + * + * Unload + * + */ + + destroy: function () { + this.swWrapper.removeEventListener('webkitTransitionEnd', this, false); + + this.swFrame.removeEventListener('touchstart', this, false); + + document.getElementById('sw-cancel').removeEventListener('touchstart', this, false); + document.getElementById('sw-done').removeEventListener('touchstart', this, false); + + document.removeEventListener('touchstart', this, false); + document.removeEventListener('touchmove', this, false); + window.removeEventListener('orientationchange', this, true); + window.removeEventListener('scroll', this, true); + + this.slotData = []; + this.cancelAction = function () { + return false; + }; + + this.cancelDone = function () { + return true; + }; + + this.reset(); + + document.body.removeChild(document.getElementById('sw-wrapper')); + }, + + close: function () { + this.swWrapper.style.webkitTransitionTimingFunction = 'ease-in'; + this.swWrapper.style.webkitTransitionDuration = '400ms'; + this.swWrapper.style.webkitTransform = 'translate3d(0, 0, 0)'; + + this.swWrapper.addEventListener('webkitTransitionEnd', this, false); + }, + + + /** + * + * Generic methods + * + */ + + addSlot: function (values, style, defaultValue) { + if (!style) { + style = ''; + } + + style = style.split(' '); + + for (var i = 0; i < style.length; i += 1) { + style[i] = 'sw-' + style[i]; + } + + style = style.join(' '); + + var obj = { 'values': values, 'style': style, 'defaultValue': defaultValue }; + this.slotData.push(obj); + }, + + getSelectedValues: function () { + var index, count, + i, l, + keys = [], values = []; + + for (i in this.slotEl) { + // Remove any residual animation + this.slotEl[i].removeEventListener('webkitTransitionEnd', this, false); + this.slotEl[i].style.webkitTransitionDuration = '0'; + + if (this.slotEl[i].slotYPosition > 0) { + this.setPosition(i, 0); + } else if (this.slotEl[i].slotYPosition < this.slotEl[i].slotMaxScroll) { + this.setPosition(i, this.slotEl[i].slotMaxScroll); + } + + index = -Math.round(this.slotEl[i].slotYPosition / this.cellHeight); + + count = 0; + for (l in this.slotData[i].values) { + if (count == index) { + keys.push(l); + values.push(this.slotData[i].values[l]); + break; + } + + count += 1; + } + } + + return { 'keys': keys, 'values': values }; + }, + + + /** + * + * Rolling slots + * + */ + + setPosition: function (slot, pos) { + this.slotEl[slot].slotYPosition = pos; + this.slotEl[slot].style.webkitTransform = 'translate3d(0, ' + pos + 'px, 0)'; + }, + + scrollStart: function (e) { + // Find the clicked slot + var xPos = e.targetTouches[0].clientX - this.swSlots.offsetLeft; // Clicked position minus left offset (should be 11px) + + // Find tapped slot + var slot = 0; + for (var i = 0; i < this.slotEl.length; i += 1) { + slot += this.slotEl[i].slotWidth; + + if (xPos < slot) { + this.activeSlot = i; + break; + } + } + + // If slot is readonly do nothing + if (this.slotData[this.activeSlot].style.match('readonly')) { + this.swFrame.removeEventListener('touchmove', this, false); + this.swFrame.removeEventListener('touchend', this, false); + return false; + } + + this.slotEl[this.activeSlot].removeEventListener('webkitTransitionEnd', this, false); // Remove transition event (if any) + this.slotEl[this.activeSlot].style.webkitTransitionDuration = '0'; // Remove any residual transition + + // Stop and hold slot position + var theTransform = window.getComputedStyle(this.slotEl[this.activeSlot]).webkitTransform; + theTransform = new WebKitCSSMatrix(theTransform).m42; + if (theTransform != this.slotEl[this.activeSlot].slotYPosition) { + this.setPosition(this.activeSlot, theTransform); + } + + this.startY = e.targetTouches[0].clientY; + this.scrollStartY = this.slotEl[this.activeSlot].slotYPosition; + this.scrollStartTime = e.timeStamp; + + this.swFrame.addEventListener('touchmove', this, false); + this.swFrame.addEventListener('touchend', this, false); + + return true; + }, + + scrollMove: function (e) { + var topDelta = e.targetTouches[0].clientY - this.startY; + + if (this.slotEl[this.activeSlot].slotYPosition > 0 || this.slotEl[this.activeSlot].slotYPosition < this.slotEl[this.activeSlot].slotMaxScroll) { + topDelta /= 2; + } + + this.setPosition(this.activeSlot, this.slotEl[this.activeSlot].slotYPosition + topDelta); + this.startY = e.targetTouches[0].clientY; + + // Prevent slingshot effect + if (e.timeStamp - this.scrollStartTime > 80) { + this.scrollStartY = this.slotEl[this.activeSlot].slotYPosition; + this.scrollStartTime = e.timeStamp; + } + }, + + scrollEnd: function (e) { + this.swFrame.removeEventListener('touchmove', this, false); + this.swFrame.removeEventListener('touchend', this, false); + + // If we are outside of the boundaries, let's go back to the sheepfold + if (this.slotEl[this.activeSlot].slotYPosition > 0 || this.slotEl[this.activeSlot].slotYPosition < this.slotEl[this.activeSlot].slotMaxScroll) { + this.scrollTo(this.activeSlot, this.slotEl[this.activeSlot].slotYPosition > 0 ? 0 : this.slotEl[this.activeSlot].slotMaxScroll); + return false; + } + + // Lame formula to calculate a fake deceleration + var scrollDistance = this.slotEl[this.activeSlot].slotYPosition - this.scrollStartY; + + // The drag session was too short + if (scrollDistance < this.cellHeight / 1.5 && scrollDistance > -this.cellHeight / 1.5) { + if (this.slotEl[this.activeSlot].slotYPosition % this.cellHeight) { + this.scrollTo(this.activeSlot, Math.round(this.slotEl[this.activeSlot].slotYPosition / this.cellHeight) * this.cellHeight, '100ms'); + } + + return false; + } + + var scrollDuration = e.timeStamp - this.scrollStartTime; + + var newDuration = (2 * scrollDistance / scrollDuration) / this.friction; + var newScrollDistance = (this.friction / 2) * (newDuration * newDuration); + + if (newDuration < 0) { + newDuration = -newDuration; + newScrollDistance = -newScrollDistance; + } + + var newPosition = this.slotEl[this.activeSlot].slotYPosition + newScrollDistance; + + if (newPosition > 0) { + // Prevent the slot to be dragged outside the visible area (top margin) + newPosition /= 2; + newDuration /= 3; + + if (newPosition > this.swSlotWrapper.clientHeight / 4) { + newPosition = this.swSlotWrapper.clientHeight / 4; + } + } else if (newPosition < this.slotEl[this.activeSlot].slotMaxScroll) { + // Prevent the slot to be dragged outside the visible area (bottom margin) + newPosition = (newPosition - this.slotEl[this.activeSlot].slotMaxScroll) / 2 + this.slotEl[this.activeSlot].slotMaxScroll; + newDuration /= 3; + + if (newPosition < this.slotEl[this.activeSlot].slotMaxScroll - this.swSlotWrapper.clientHeight / 4) { + newPosition = this.slotEl[this.activeSlot].slotMaxScroll - this.swSlotWrapper.clientHeight / 4; + } + } else { + newPosition = Math.round(newPosition / this.cellHeight) * this.cellHeight; + } + + this.scrollTo(this.activeSlot, Math.round(newPosition), Math.round(newDuration) + 'ms'); + + return true; + }, + + scrollTo: function (slotNum, dest, runtime) { + this.slotEl[slotNum].style.webkitTransitionDuration = runtime ? runtime : '100ms'; + this.setPosition(slotNum, dest ? dest : 0); + + // If we are outside of the boundaries go back to the sheepfold + if (this.slotEl[slotNum].slotYPosition > 0 || this.slotEl[slotNum].slotYPosition < this.slotEl[slotNum].slotMaxScroll) { + this.slotEl[slotNum].addEventListener('webkitTransitionEnd', this, false); + } + }, + + scrollToValue: function (slot, value) { + var yPos, count, i; + + this.slotEl[slot].removeEventListener('webkitTransitionEnd', this, false); + this.slotEl[slot].style.webkitTransitionDuration = '0'; + + count = 0; + for (i in this.slotData[slot].values) { + if (i == value) { + yPos = count * this.cellHeight; + this.setPosition(slot, yPos); + break; + } + + count -= 1; + } + }, + + backWithinBoundaries: function (e) { + e.target.removeEventListener('webkitTransitionEnd', this, false); + + this.scrollTo(e.target.slotPosition, e.target.slotYPosition > 0 ? 0 : e.target.slotMaxScroll, '150ms'); + return false; + }, + + + /** + * + * Buttons + * + */ + + tapDown: function (e) { + e.currentTarget.addEventListener('touchmove', this, false); + e.currentTarget.addEventListener('touchend', this, false); + e.currentTarget.className = 'sw-pressed'; + }, + + tapCancel: function (e) { + e.currentTarget.removeEventListener('touchmove', this, false); + e.currentTarget.removeEventListener('touchend', this, false); + e.currentTarget.className = ''; + }, + + tapUp: function (e) { + this.tapCancel(e); + + if (e.currentTarget.id == 'sw-cancel') { + this.cancelAction(); + } else { + this.doneAction(); + } + + this.close(); + }, + + setCancelAction: function (action) { + this.cancelAction = action; + }, + + setDoneAction: function (action) { + this.doneAction = action; + }, + + cancelAction: function () { + return false; + }, + + cancelDone: function () { + return true; + } +}; \ No newline at end of file