From a643e25591c2447edd308956893f49b166e10393 Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Mon, 2 Sep 2013 22:16:51 -0400 Subject: [PATCH] Image capture support for non WebRTC compliant browsers, via Flash. --- lms/static/js/vendor/jpegcam/webcam.min.js | 12 -- lms/static/js/vendor/jpegcam/webcam.swf | Bin 6141 -> 0 bytes lms/static/js/verify_student/CameraCapture.as | 103 ++++++++++ .../js/verify_student/CameraCapture.swf | Bin 0 -> 2272 bytes lms/static/js/verify_student/photocapture.js | 193 ++++++++++++++++++ .../verify_student/photo_verification.html | 161 +-------------- 6 files changed, 298 insertions(+), 171 deletions(-) delete mode 100644 lms/static/js/vendor/jpegcam/webcam.min.js delete mode 100755 lms/static/js/vendor/jpegcam/webcam.swf create mode 100644 lms/static/js/verify_student/CameraCapture.as create mode 100644 lms/static/js/verify_student/CameraCapture.swf create mode 100644 lms/static/js/verify_student/photocapture.js diff --git a/lms/static/js/vendor/jpegcam/webcam.min.js b/lms/static/js/vendor/jpegcam/webcam.min.js deleted file mode 100644 index f1118ef9be..0000000000 --- a/lms/static/js/vendor/jpegcam/webcam.min.js +++ /dev/null @@ -1,12 +0,0 @@ -/* JPEGCam v1.0.11 *//* Webcam library for capturing JPEG images and submitting to a server *//* Copyright (c) 2008 - 2009 Joseph Huckaby *//* Licensed under the GNU Lesser Public License *//* http://www.gnu.org/licenses/lgpl.html *//* Usage: - - Take Snapshot -*/// Everything is under a 'webcam' Namespace -window.webcam={version:"1.0.11",ie:!!navigator.userAgent.match(/MSIE/),protocol:location.protocol.match(/https/i)?"https":"http",callback:null,swf_url:"webcam.swf",shutter_url:"shutter.mp3",api_url:"",loaded:false,quality:90,shutter_sound:true,stealth:true,hooks:{onLoad:null,onAllow:null,onComplete:null,onError:null},set_hook:function(a,b){this.hooks[a]=b},fire_hook:function(a,b){if(this.hooks[a]){if(typeof this.hooks[a]==="function"){this.hooks[a](b)}else if(typeof this.hooks[a]==="array"){this.hooks[a][0][this.hooks[a][1]](b)}else if(window[this.hooks[a]]){window[this.hooks[a]](b)}return true}return false},set_api_url:function(a){this.api_url=a},set_swf_url:function(a){this.swf_url=a},get_html:function(a,b,c,d){if(!c){c=a}if(!d){d=b}var e="";var f="shutter_enabled="+(this.shutter_sound?1:0)+"&shutter_url="+encodeURIComponent(this.shutter_url)+"&width="+a+"&height="+b+"&server_width="+c+"&server_height="+d;if(this.ie){e+=''}else{e+=''}this.loaded=false;return e},get_movie:function(){if(!this.loaded){return false}var a=document.getElementById("webcam_movie");if(!a){return false}return a},set_stealth:function(a){this.stealth=a},snap:function(a,b,c){if(b){this.set_hook("onComplete",b)}if(a){this.set_api_url(a)}if(typeof c!=="undefined"){this.set_stealth(c)}this.get_movie()._snap(this.api_url,this.quality,this.shutter_sound?1:0,this.stealth?1:0)},freeze:function(){this.get_movie()._snap("",this.quality,this.shutter_sound?1:0,0)},upload:function(a,b){if(b){this.set_hook("onComplete",b)}if(a){this.set_api_url(a)}this.get_movie()._upload(this.api_url)},reset:function(){this.get_movie()._reset()},configure:function(a){if(!a){a="camera"}this.get_movie()._configure(a)},set_quality:function(a){this.quality=a},set_shutter_sound:function(a,b){this.shutter_sound=a;this.shutter_url=b?b:"shutter.mp3"},flash_notify:function(a,b){switch(a){case"security":var c=b=="Camera.Unmuted";this.fire_hook("onAllow",c);break;case"flashLoadComplete":this.loaded=true;this.fire_hook("onLoad",b);break;case"error":if(!this.fire_hook("onError",b)){}break;case"success":this.fire_hook("onComplete",b.toString());break;default:break}}} \ No newline at end of file diff --git a/lms/static/js/vendor/jpegcam/webcam.swf b/lms/static/js/vendor/jpegcam/webcam.swf deleted file mode 100755 index c21b7153556e960964efa516b22f4dd1e85f0740..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6141 zcmVoXt9Ebd<-DUGp71m!#1(2yqS29}KcU;<5o_gwTPI1%uH6 zBA(HA%r}~`M>Fyq98R2Ik~p?wC%%ny*h0j2Y{!msItj6I*iQD)NDIpG-frUEB%9rR zFWGE1yPF?7Tm5|_ArA9i@^;@_JymygbyanBRds#cf>GiaCu?mM*g^|#+`dFRNto~m#9W{da8cfQ>5 z#P`nrvHeLF-gxdTv3`Em!t`!d_~B2^jvhUqdSmkSvy(u?Bk4p`NThO7YbK)|_ZjJt zby_s7o9hxI+OU~*?Mmc&bD2bHSl*W((alU*EU9JV>!OM5Xi_`w#_17lv|Y<-9(y96 zOC(Y1c+RvG$|Ye#8!}9>9?3hZqcRIZJWn(I5B)!8MRR&`XwYf*{R0(=R3dj%UQ6Yy z`K&zH-Zs?Lhx}GA54M(uR$qw=j^=Y_S3VXS(NcYSvM!s84n>WjWPT)((o%*wl*;h+ zvkNYpIHD!H_M;K`Drw4ZL+A!EZAe&b7 z>n}@;xwI9MW=g>Q$_GsylThv*<+`OKiKv+_rR<0qO=!{pr%+p8M#!e3Qg1q+ic%x4 zrBY_nYmM4UgIh+;;i22|S`yROW9b??nuzA&UK@{_iQ#z8n>8~>%#1x#RvOq-a+`G? z1bt*wwvP}+G>XSa$Y+u?n=`d!F7C;ix!F}*MmiNs4Cgaug;qK@U0N!dG&5p0rHx9w z*&ydflW8sLOs9IVGoxi$>o}DdrHqLR#l2cCzC51Gjc#jdvVDf$YijM?*tDU!`PwEu zpGf8sDYxyLVKY4<#ggfCM$Gdnk>Or&51YCDiDPDR;|9svoLt(lEt5Tt_K!GwO(T!K zJ`N2YEtyOoZBLJAsMoSAvnLfxiDUrUPDWo zd-k$Iy(C#jSqzp?U>ura*(^vW1(G^52X~k zAS+|m4(H;v{k^*aR$>O)(4ef1yU_i1{y1CP`t}U$=^ONE(Wqr*Pa?|?W=8JqYwhdr z^=i4CX2eU}$kY~3B%`ur;vu^m1T@9uHIb)THKI3~$2)l-ERW&Qp-AKVDYyDu0<#Mp zlPoX!=ooUPv}9#R39-atnqf*qJSjbVRZIX~Gj4Sc&1EqivU61)va+%w8_(xZZpcjW zx*T=)ALuz?-iB2w=b4?tlOb}E>Z8_CUT3X8ltPPQ$1AM?&#g8r*-1H)HqsSG=r31QkoJH&Fh#TumjPQafK5Z^2~f?S#dO< zjf=dl%v)%$nTw~R;{H%?pFCpWZmViGalIZ~4>Ks&cYM@zwuScY@9F64sLYzFD7OGh zeGbjo7Ff}5#fh85LlP)0i_VRvjr<5ISXX<2#S-IIYzs8)OXuRH&Da^x7#PXpw4sgW zFfRgHDqvX?h$S-F+&Za)hsdF8VjQ<5;5xEhF=);%nDU6_S(;DXno1u{$vG{9=YwYR z2LEh`))y^XDn%8SoaC~L4t?ciCBlE@%CguGe#!6jyZz;LH4>?7soNzHe}_aCNKVbK z*Vp(Hh=c#O`d#&z`fPo!K3{*t{~(AS3SLK9d4(X#K5$gHp{lxE5^G$w{snal>t6>7 z4hjMVkve1wlnO3t$xx|+NxB1#uix`fiDlrEz* zK2^wQps<6&P719Qc2S{?y4$Izle%|PcNg{Sq3&+#xskeisCzGU z@1yPzb?>L{GU~aBx(`sHm%96?yPvuTC>*44h`I+U9H#I-3O7>-Q;1L)qM$B9PZ+LN zaP34SN}-v8Ng+mIm_poD<#5RkT6qhFBo#&|q$s2*jJk#eS6py~1lN9a;ZZ6aqi~$U z?NoR_g%41;gTe8sdl2qL_&CCS2=^m=0^ySg z4**^C5cZFN>lDVS<_U0pipT8JNP80DDTFbE&mlYuRD2F-#q)^2fbb&Fn$IJ=1g@7s zaJ|6gz6i9ONB&Dl|1$PpLHH`d*Ad=8_%^~g(CU6#{U&x32;V{YF2eT^zK_#ygX>FN z)enG5e*skZON75d_-k0fFa7`yLL7o15c_2UoFta$mrOdq;kdxYL6QVP;?n}id=7|2 zoB#q)nY`x@5R21^oMixj?oVn4M%Eug?hGjFa1QgI!S zO0mr4BsGpLmfEdWyX|_Hi!4~Mosb*I4nn-7g^-=3m5^Pe4H-x~Z#sC>$(!B0=^|tg z=_cex(nE+$_M#WbK0XlwQnw$-!kd899{{qb7s%p1AWQmzEFA!{>>%*%R-==ID)3?i zYC#kUEQf6(I98zJ1yPu6#x-E4OOzfGCz}~LADm&ta55kBFgLb!EXX#p8<@9&m9uJA z&$hAc>^j8DN|Rez2it<A%=x+fmquGL-uuZQvhvRhX`(47h{8Av0EhCU}?lR_P#k>m$jQG#0i0~ zQqbktp#QC6ahf^CvojO2E;FD1Bag%NILLYSVaeY04cdiVjT`EJ}Cd9tyFo+4F_imWOf0G_E)m4l|g3x-$&VRbg$6tWsBT zin^MUo{z7ZesdS{*3O@yecFz;%r2??)3B(w&?YZ$@K zM>$Ddg=l0oqw&>|Rg9oEM(Xah48l)?cOTZ_f{r-)koOe(vHZ-Xq|L@$iCQ0{<>(xm0H97P$8?Dm4 zmg-8~tyki>hWBVst-V9NR`->b60E^#djMm4jb2rnq1J#Kv4A zr}_UhKEe6%shb}k=lu9=nT^lHY-BQ4WcA@h7|}a zuFHWH*TlozuvQE;K)8YVc(;ai+a;pY?)F?XB6bHCbr!J!M-6k`94E2sg4-d8(k<3v zlFe3WvpFr7EnGi&p4dm-)0w< zz=}d_5GfN-K==Ghu~^bFkHdEf2QJ_hae>Djvnx=0g>m8H6@0e*!h%(aN-BJ{zs8UL z1?}}0w0r#a`o4?h7hP3;@tnMJ8vOr!(FRHimRwcA(#s8~yjXtORpkSh8i4*O{S_8os75 z)p?BrFEaL3s+xbu*Q@3HR)nV(TRa~8Qna)77saBwo~xKXoi*GxnxE0#jMU&0B^<;r zHc~=C@G*O6UkLEz^BWJ+!$JGYZ&7f}S`3d*<`*WRuX>U!N18)W3g z%6IV=g!CGhrBOzq=`Os$IDHRsF=y8B`tVWansB0s(-LW@LXB&%@OWOXM2ivep3XL) z2YeL`{Nibp``kP>L7k$uiE^x1ICsWM4y;40;<-)-WQ{Upkoe5Fy$f6anDskvD|2M7 z%gI;u$1Iaus_8tF38|1gqV$e+591fu+`LaezfB@YzA^hgEBo%}g=z{5^fXrGPSt_j zVF|CJKI>}HDFN1bi{QLKaB;%i$gOVF#U}L7c#~UqjgK{Xbocm}assd}s+(}i%csh$ zsd7Gr z#I9vE_;Om#Rf zXSV?HiimF(^+hUY(aK2GELs&=$Vh`_GT_671DS<^%J{-ay|p0+nk`z}LQkW~Zsr;A z#_J=CxUd5mga&J)0+Sk;*kG%?0~IWaEG~%?oUTL_Rk)k=tQA#NrV1LdQj+y%<#|wE0Od7Mz6i?epnM6GFN5+GP`(Pv*FgC?C=;N32bAxE z@;y+#56WAhyba1bp!@)oDNv?C`5REqfpQ*{8Bl%%%8x<$2`E1Y%I`t>cToNS%71|JpP>8~D1U^3afmODEa8C?<|2O~ z`WU$-k)>A&{nE&?+0Z+9zy&MIB`fw8?I@~P775I$sI-*u(94(ttr&WW!M_cYV1*TW z)Lnx?w-TTfdKad_MhyRNc^2@<7r=@;W1Dd6Ou-$_<-mmu_}`5GN%;Ss0#}Lu)q@|1 ztOyHhUAzXYh^(ANS4P&)R)+PFjkD;+$fj9zQ)Kfjx_NRBDKJtdT7SeiS76a{jz;t6 z7&%{H8@zZe2s@O!R~OFk@5p&yg*AQ~?*@+X(-tYbJhYsIS%{Hv^;D>uf3quPrzqX! zu)hug{#}kJVcJbeT(RGt_B#}B3~qi^Xbd%y@Vd}C5?)(~X@!^`TI&cmg_=mXIn+!T z$)87I;9Xs{y=2$&<|( z4II_Z@<(lcSP~bJ><4hVZ2kqZ5^qIG)oi>q6oc^aWGo&_bPhx8 zmJ?;?BJKDvC4{UNno z?d&|_(2iPz4s|yl9Aia{%gGsaPwaT?_LGL_tLK+398JgG-}qsu!5hPL_Pj2hoSA+Q zK^JTPu2`I6#d5rqMY_~IVdqq*6FNTt@h+dsCUt&*#Jkk4K(zuy?NVK_JJg#(A9Nt< ziG4^NKs2&Fe8ZeUbH;Sv;D~Qmx2s*D69C~mLERp@6M%EQWM7~--%C|Bgdh`A&uAx+ zhZE0eALiKh7=Dq8<2HGFOw&FBY8TeMXy~JW%QJWAF4Wg``O0i*=wl!tM>KRda@+%r z4}*FjbT3LF{wS#XXYt2C?VH6P2lXJw3$c#_gBo;Pq$Rwwdnbvvs4e09pb)zsy6*!B zeF7lT#tz5ZxYTE$@v~?|?33_V=m8M8zrzng<7o&zXfKTno1|AyW%N4Ne3IwH=7VRK}Q_CI|U;G z@9%>Vk@ru)h-AX@lOwX#QWFXzXiwDvOincVl?$o$N>wKzCg65D)!n!OO9c0TW)n*= zNpYtAjJjLxI1~C5;BrY>?csE5GoJ=I!bdXh9Nqbf<<7{CuvcyC_CkDz3F;2Dr}H}C zrgDxi0CGEGw_DM{rA|TPtI+rwbe{r8X&;zI$YZ5ZX-7#h_8CqSLZ9VANltQTPgWMh&*3?O@v^YG#@4n zGY!qxi~#5T<|R4$EifHi787-eQ{a!!3v*}f{DmJnW*k3td=8!l`V8=YTY46VgOcZf z2&aHN4@A5V$O}LuH1S0s7>myX!J@NN#Pr%Z+1&URoIGDRd8DBViE9e6mw@B05*~XQ zj_^SVKY6}nz&kKiIzG#|p0%@jj@Z#I#9l!;najO$LFk8bLIDR@LTYyve>OhO6A}|J z(jAC*M|uMBp3ABf3N6Qi?_53EY!Y7ZzW~kZs|c?ld=cS#{5|AYV*SLoA$v=;r}U3) P_Wyq(I}!aKI&bj}|8?Ge diff --git a/lms/static/js/verify_student/CameraCapture.as b/lms/static/js/verify_student/CameraCapture.as new file mode 100644 index 0000000000..0f5d5acae1 --- /dev/null +++ b/lms/static/js/verify_student/CameraCapture.as @@ -0,0 +1,103 @@ +/** + * Simple Camera Capture application meant to be used where WebRTC is not supported + * (e.g. Safari, Internet Explorer, Opera). All orchestration is assumed to happen + * in JavaScript. The only function this application has is to capture a snapshot + * and allow a 640x480 PNG of that snapshot to be made available to the JS as a + * base64 encoded data URL. + * + * There are really only three methods: + * snap() freezes the video and returns a PNG file as a data URL string. You can + * assign this return value to an img's src attribute. + * reset() restarts the the video. + * imageDataUrl() returns the same thing as snap() -- + */ + +package +{ + import flash.display.BitmapData; + import flash.display.PNGEncoderOptions; + import flash.display.Sprite; + import flash.events.Event; + import flash.external.ExternalInterface; + import flash.geom.Rectangle; + import flash.media.Camera; + import flash.media.Video; + import flash.utils.ByteArray; + import mx.utils.Base64Encoder; + + [SWF(width="640", height="480")] + public class CameraCapture extends Sprite + { + // We pick these values because that's captured by the WebRTC spec + private const VIDEO_WIDTH:int = 640; + private const VIDEO_HEIGHT:int = 480; + + private var camera:Camera; + private var video:Video; + private var b64EncodedImage:String = null; + + public function CameraCapture() + { + addEventListener(Event.ADDED_TO_STAGE, init); + } + + protected function init(e:Event):void { + camera = Camera.getCamera(); + camera.setMode(VIDEO_WIDTH, VIDEO_HEIGHT, 30); + + video = new Video(VIDEO_WIDTH, VIDEO_HEIGHT); + video.attachCamera(camera); + + addChild(video); + + ExternalInterface.addCallback("snap", snap); + ExternalInterface.addCallback("reset", reset); + ExternalInterface.addCallback("imageDataUrl", imageDataUrl); + + // Notify the container that the SWF is ready to be called. + ExternalInterface.call("setSWFIsReady"); + } + + public function snap():String { + // If we already have a b64 encoded image, just return that. The user + // is calling snap() multiple times in a row without reset() + if (b64EncodedImage) { + return imageDataUrl(); + } + + var bitmapData:BitmapData = new BitmapData(video.width, video.height); + bitmapData.draw(video); // Draw a snapshot of the video onto our bitmapData + video.attachCamera(null); // Stop capturing video + + // Convert to PNG + var pngBytes:ByteArray = new ByteArray(); + bitmapData.encode( + new Rectangle(0, 0, video.width, video.height), + new PNGEncoderOptions(), + pngBytes + ); + + // Convert to Base64 encoding of PNG + var b64Encoder:Base64Encoder = new Base64Encoder(); + b64Encoder.encodeBytes(pngBytes); + b64EncodedImage = b64Encoder.toString(); + + return imageDataUrl(); + } + + public function reset():String { + video.attachCamera(camera); + b64EncodedImage = null; + + return imageDataUrl(); + } + + public function imageDataUrl():String { + if (b64EncodedImage) { + return "data:image/png;base64," + b64EncodedImage; + } + return ""; + } + } +} + diff --git a/lms/static/js/verify_student/CameraCapture.swf b/lms/static/js/verify_student/CameraCapture.swf new file mode 100644 index 0000000000000000000000000000000000000000..d35e25fc26b15447ab997489a1ddcacf38d884d3 GIT binary patch literal 2272 zcmV<62p{)aS5pxn4*&qq2mk!9>}wkMAO0^GfqnXUf=wf zk?ETI6WE=$d)>Mx67Sr{Io!A*tr5(Pkm$6Nt*X-(-rNa=jO46SN!Wt<8W3~mK;B0J zd#RD^fz#s{F>_-9HsIqQ-klNW{?`+ItGbh(&*mKo^lh6=S3hKW?O)P`vp=x{vb)(k z`!Vgb^eL*{fHxozD89qz9nS0>EF9B7Uu`dfjM*inJuU9K3MKMlD$AB?Q zh}>WfKAb0sW3`Rpr!JcyGK>274D&$Ss^M1?NB=i(E@F6%G{(ip28(*wkty(%A(xlv zs&qtz!MBOZJntr!A*gNRL7P znUK6LeW5!uZoP9Za|z&**8A|Sr?mnj6){&2BQQFf4l}j(d&k}b2KxA3G#d}Y7(j^H(OhIRsZ|!ghSZdxAdS;t3?xy1TTAGhfQWHFBea5%ug^gZ-KK6YPn)rj05lPGeN*6^e#tZAf}y?Yp`fs(1)k4R2() zHIIX&9mew@==twmRuYzI(tc$8@AppKK!j)c;th6^?BM2v`3@N-kJ%8!knacHf8=VR zFhpr+Y}^SUnYpL>4Bg>Dy1diG3VCO$mH3XXK&{WG49l1J71(U|H5<5(6WoUlx*Q<5 z7CSN@Em53M>6oZlU>7IQIHgS((Wv)CQ*jP?`Yp(~M`!bV{~7fR?A3TVO1m$|qm7~F z>g%}qnQOl|mh(S`EmS>w1Skl;ctx`do1rP0a$h!2fDEj)tF{-6Utek;KvKneRb+S)P z$Ug7hN?AWjg3&YqBb9&chB>9c0h7-$!zwZmh3+rKAqO=uyC#PUHv~stfKsH?$2KN? zy=iPWPFG72gh9JyrSxlcoUel~;8`R37f77JKR#xjd$%g3Ql7u|cHBi=hF4cnRsJzY zjcP_npJ7f6R~BRL?s5-}Z`s*M-dXhXdXhyZm7JSL5r|A402Y3C{ns9lWncFOa#YL2 zK*oC9StgNym2JZ)c`s&U9O68@y{SOLyapuP5-*+Xl|5;`U?NT4H6O6b z4Nzvf4=ThOeWKIHe?1tEdTQx~8OdNuAI~M}+3{R%lmic=hkt$#D#Oi#*9~>ePorW8 z&j&n}LRV_V18O@wfb=czu?^_CE=#>5xVqT7p1}F?(m|gG=3#k9Kg3^XWsEcQv-hb( z-HN_M0S4iK4n}A{E5IuQKqo;hqkDO~bAvzt;pfgCO5ooayndO8*nZTz@ObIr-2R%>{t^%IZM&=fQft^&TDh7U`xAsZw%~ zl5u|@=|QS;gSFz!OJ4j2rh9O*dw11jFc$k%1ckE(TcSdhU~5rgAhi?!Ij>SpC^kve zOXaEz!W*I}m!leIG*P6 zl%Ih?im|ZX%A~_ze)d(6%c%Vv9{B|4K zn8OSi7$tHrULGkI!pDLCN1j@ygK7F7E}wWL(Z7vDJ}#GG?{21qGTw=dguKc;+zHEg uwW`WGzZU5eknq`myLDC@a').attr({ + type: 'hidden', + name: prop, + value: data[prop] + }).appendTo('#pay_form'); + } + } + ) + .done(function(data) { + $("#pay_form").submit(); + }) + .fail(function(jqXhr,text_status, error_thrown) { + alert(jqXhr.responseText); + }); +} + +function doResetButton(resetButton, captureButton, approveButton) { + approveButton.removeClass('approved'); + nextButton.addClass('disabled'); + + captureButton.show(); + resetButton.hide(); + approveButton.hide(); +} + +function doApproveButton(approveButton, nextButton) { + approveButton.addClass('approved'); + nextButton.removeClass('disabled'); +} + +function doSnapshotButton(captureButton, resetButton, approveButton) { + captureButton.hide(); + resetButton.show(); + approveButton.show(); +} + +function initSnapshotHandler(names, hasHtml5CameraSupport) { + var name = names.pop(); + if (name == undefined) { + return; + } + + var video = $('#' + name + '_video'); + var canvas = $('#' + name + '_canvas'); + var image = $('#' + name + "_image"); + var captureButton = $("#" + name + "_capture_button"); + var resetButton = $("#" + name + "_reset_button"); + var approveButton = $("#" + name + "_approve_button"); + var nextButton = $("#" + name + "_next_button"); + var flashCapture = $("#" + name + "_flash"); + + var ctx = null; + if (hasHtml5CameraSupport) { + ctx = canvas[0].getContext('2d'); + } + var localMediaStream = null; + + function snapshot(event) { + if (hasHtml5CameraSupport) { + if (localMediaStream) { + ctx.drawImage(video[0], 0, 0); + image[0].src = canvas[0].toDataURL('image/png'); + } + else { + return false; + } + video[0].pause(); + } + else { + image[0].src = flashCapture[0].snap(); + } + + doSnapshotButton(captureButton, resetButton, approveButton); + return false; + } + + function reset() { + image[0].src = ""; + + if (hasHtml5CameraSupport) { + video[0].play(); + } + else { + flashCapture[0].reset(); + } + + doResetButton(resetButton, captureButton, approveButton); + return false; + } + + function approve() { + doApproveButton(approveButton, nextButton) + return false; + } + + // Initialize state for this picture taker + captureButton.show(); + resetButton.hide(); + approveButton.hide(); + nextButton.addClass('disabled'); + + // Connect event handlers... + video.click(snapshot); + captureButton.click(snapshot); + resetButton.click(reset); + approveButton.click(approve); + + // If it's flash-based, we can just immediate initialize the next one. + // If it's HTML5 based, we have to do it in the callback from getUserMedia + // so that Firefox doesn't eat the second request. + if (hasHtml5CameraSupport) { + navigator.getUserMedia({video: true}, function(stream) { + video[0].src = window.URL.createObjectURL(stream); + localMediaStream = stream; + + // We do this in a recursive call on success because Firefox seems to + // simply eat the request if you stack up two on top of each other before + // the user has a chance to approve the first one. + initSnapshotHandler(names, hasHtml5CameraSupport); + }, onVideoFail); + } + else { + initSnapshotHandler(names, hasHtml5CameraSupport); + } + +} + +function objectTagForFlashCamera(name) { + return ''; +} + +$(document).ready(function() { + $(".carousel-nav").addClass('sr'); + $("#pay_button").click(submitToPaymentProcessing); + // $("#confirm_pics_good").click(function() { + // if (this.checked) { + // $("#pay_button_frame").removeClass('disabled'); + // } + // else { + // $("#pay_button_frame").addClass('disabled'); + // } + // }); + // + // $("#pay_button_frame").addClass('disabled'); + + var hasHtml5CameraSupport = initVideoCapture(); + + // If HTML5 WebRTC capture is not supported, we initialize jpegcam + if (!hasHtml5CameraSupport) { + $("#face_capture_div").html(objectTagForFlashCamera("face_flash")); + $("#photo_id_capture_div").html(objectTagForFlashCamera("photo_id_flash")); + } + + initSnapshotHandler(["photo_id", "face"], hasHtml5CameraSupport); + +}); diff --git a/lms/templates/verify_student/photo_verification.html b/lms/templates/verify_student/photo_verification.html index 5ffde8fced..c410331c4a 100644 --- a/lms/templates/verify_student/photo_verification.html +++ b/lms/templates/verify_student/photo_verification.html @@ -9,164 +9,7 @@ <%block name="js_extra"> - - + <%block name="content"> @@ -324,7 +167,7 @@
-
+