Title | |
| |
Introduction | |
| |
Hop Primer | |
| |
Web Programming | |
| |
Multitier programming | |
| |
Hop | |
| |
Diffuse Programming | |
|
HopSlide v2.5.7 13 February 2013 | HopSlide Help (v2.5.7)
|
#include <stdio.h> /* a forward definition */ static void hello_world(); /* the entry point of the application */ int( int argc, char *argv[], char *env[] ) { hello_world(); return 0; } void hello_world() { puts( "hello, world!" ); }
#include <stdio.h> #include <stdlib.h> int fib( int n ) { if( n < 2 ) { return 1; } else { return fib( n - 1 ) + fib( n - 2 ); } } int main( int argc, char *argv[], char *env[] ) { printf( "fib: %d\n", fib( atoi( argv[ 1 ] ) ) ); }
foo
, null?
, <
, +
, string->number
, <div>
#include <stdio.h> #include <stdlib.h> int fib( int n ) { return n < 2 ? 1 : fib( n - 1 ) + fib( n - 2 ); } int( int argc, char *argv[], char *env[] ) { printf( "fib: %s\n", fib( atoi( argv[ 1 ] ) ) ); }
(module fib-typed (main start)) (define (fib::int n::int) (if (< n 2) 1 (+ (fib (- n 1)) (fib (- n 2))))) (define (start args::pair) (print "fib: " (fib (string->number (cadr args)))))
(cons 1 (cons 2 '()))
⇒ (1 2)(list 'foo 'bar 'gee)
⇒ (foo bar gee)(car (list 'foo 'bar 'gee))
⇒ foo(cdr (list "foo" "bar" "gee"))
⇒ ("bar" "gee")(cadr (list :foo :bar :gee))
⇒ :bar(pair? (list 1 2 3))
⇒ #t(null? (list 1 2 3))
⇒ #f(reverse (list 1 2 3))
⇒ (3 2 1)(append (list 'foo 'bar) '(gee hux))
⇒ (foo bar gee hux)`(1 ,(+ 2 3) ,@(list 6 7))
⇒ (1 5 6 7)// return a new string composed of the scheme of a URL // url_scheme( "http://hop.inria.fr" ) -> "http" char *url_scheme( char *url ) { char *s = url, *res; int i; while( *s++ != ':' ); i = s - url; res = malloc( i ); res[ i - 1 ] = 0; memcpy( res, url, i - 1 ); return res; }
// return a new string composed of the scheme of a URL // url_scheme( "http://hop.inria.fr" ) -> "http" function url_scheme( url ) { for( var i = 0; url.charAt( i ) != ":"; i++ ); return url.substring( 0, i ); }
// return a new string composed of the scheme of a URL // url_scheme( "http://hop.inria.fr" ) -> "http" function url_scheme( url ) { var m = url.match( new Regexp( "(^[^:]+)://" ) ); return m[ 1 ]; }
;; return a new string composed of the scheme of a URL ;; url_scheme( "http://hop.inria.fr" ) -> "http" (define (url-scheme url) (let loop ((i 0)) (if (char=? (string-ref url i) #\:) (substring url 0 i) (loop (+ i 1)))))
;; return a new string composed of the scheme of a URL ;; url_scheme( "http://hop.inria.fr" ) -> "http" (define (url-scheme url) (cadr (pregexp-match url "(^[^:]+)://")))
(define (plus x . y) ...)
(plus 1 2 3 4 5)
(define (plus #!optional (x 0) (y 0)) ...)
(plus 30)
(define (plus #!key (x 0) (y 0)) ...) (plus :y 14 :x 30)
var sqr = function( x ) { return x * x; } alert( sqr( 5 ) );
(let ((sqr (lambda (x) (* x x)))) (print (sqr 5)))
function o( f, g ) { return function( x ) { f( g( x ) ); } }
(define (o f g) (lambda (x) (f (g x))))
(define (open path) (if (file-exists? path) (open-input-file path) (raise 'file-not-found-error))) (define (expression-count path) (with-handler (lambda (e) (if (eq? e 'file-not-found-error) 0 (raise e))) (let ((p (open path))) (unwind-protect (let loop ((count 0)) (let ((o (read p))) (if (eof-object? o) count (loop (+ count 1))))) (close-output-port p)))))
(define (numbers-or-string path) (let ((p (open path))) (bind-exit (escape) (unwind-protect (let loop ((o (read p))) (cond ((eof-object? o) '()) ((number? o) (cons o (loop (read p)))) ((string? o) (escape o)) (else (loop (read p))))) (close-output-port p)))))
(call/cc (lambda (k) (+ 1 (+ 2 3))))
⇒ 6(call/cc (lambda (k) (+ 1 (k (+ 2 3)))))
⇒ 5(+ 1 (call/cc (lambda (k) (+ 2 (k (+ 3 4))))))
⇒ 8(module myapp (library multimedia hopdroid) (import utils telephony) (export (compose-sms ::bstring ::bstring) (read-sms ::bstring))) (define (compose-sms number::bstring text::bstring) ...) (define (read-sms text::bstring) ...)
GET|HEAD|POST <path> HTTP/1.0\r\n
..., 2xx success, ..., 4xx error, ...
GET /html/rfc1945 HTTP/1.0 Host: tools.ietf.org User-Agent: Mozilla/5.0 Accept-Encoding: gzip, deflate Accept-Charset: utf-8...
HTTP/1.0 200 OK Server: Apache/2.2.12 (Debian) Content-Length: 174663 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> <HTML> <HEAD> <TITLE>RFC 1945 (rfc1945) - Hypertext Transfer Protocol...
(define (make-http-server port) (wait-http-connection (make-server-socket port))) (define (wait-http-connection srv) (let ((sock (socket-accept srv))) (send-http-response (parse-http-request sock) sock) (wait-http-connection srv))) (define (parse-http-request sock) (let* ((l (read-line (socket-input sock))) (m (pregexp-match "^GET ([^ ]+) HTTP/1.0$" l))) (and (pair? m) (cadr m)))) (define (send-http-response path sock) (let ((out (socket-output sock))) (if (and (string? path) (file-exists? path)) (let ((len (file-length path))) (display "HTTP/1.0 200 ok\r\n" out) (display* "Content-Length: " len "\r\n" out) (display "\r\n" out) (send-file path out)) (display "HTTP/1.0 404 Not Found\r\n" out)) (close-output-port out)))
(define (make-http-server port) (wait-http-connection (make-server-socket port))) (define (wait-http-connection srv) (let ((sock (socket-accept srv))) (thread-start! (instantiate::pthread (body (lambda () (send-http-response (parse-http-request sock) sock))))) (wait-http-connection srv))) (define (parse-http-request sock) ...) (define (send-http-response path sock) ...)
cleanerHTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN" "http://www.w3.org/2002/04/xhtml-math/xhtml-math.dtd" [<!ENTITY nbsp " ">]>
<HTML> <HEAD> ... </HEAD> <BODY> ... </BODY> </HTML>
<HEAD> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>RFC 1945 - Hypertext Transfer Protocol -- HTTP/1.0</title> <link rel="shortcut icon" href="/images/rfc.png" type="image/png"/> <link rel="stylesheet" href="default.css" type="text/css"> ... </HEAD>
<TABLE border="1" summary="This table gives some statistics about fruit flies: average height and weight, and percentage with red eyes (for both males and females)."> <CAPTION><EM>A test table with merged cells</EM></CAPTION> <TR><TH rowspan="2"><TH colspan="2">Average <TH rowspan="2">Red<BR>eyes <TR><TH>height<TH>weight <TR<TH>Males<TD>1.9<TD>0.003<TD>40% <TR><TH>Females<TD>1.7<TD>0.002<TD>43% </TABLE>
|
print "<p>Hello "; print $firstname, " ", $name; print ",</p> <div> How do you do? <br> ... ";
int main ( int argc, char *argv[] ) { char *firstname = cgi_args( argc, argv, "firstname" ); char *name = cgi_args( argc, argv, "name" ); printf( "<p>Hello %s %s,</p>\n" "<div> How to you do? <br>\n" "... ", firstname, name ); }
<p> Hello <?php echo $firstname ?>, <?php echo $name ?>, </p> <div> How do you do? <br> ...
<html><head><title> shervlet </title></head><body> It is <?sh date + '%l'?> o'clock now<br> says <?sh uname -a ?></body></html> <html><head><title> shervlet </title></head><body> <?sh if [ "$REMOTE_HOST" = '1.2.3.4' ] ; then ?> Hello pal, <?sh ;else ?> Hi, <?sh fi ?> </body></html>
#!/bin/sh echo -n "<html><head><title> shervlet </title></head><body> It is " date + '%l' echo -n " o'clock<br> says " uname -a echo -n "</body></html>"
<------------- 200 OK Set-Cookie: NGUserID=3e17099b-28471-1016452371-1; expires=Wednesday, 30-Dec-2037 16:00:00 GMT; path=/; domain=www.hi-media.com -------------> GET www.hi-media.com/url Cookie: NGUserID=3e17099b-28471-1016452371-1
capturecontinuations
(let ((n1 (read1stNumber))) (let ((n2 (read2ndNumber n1))) (displaySum n1 n2) ) ) (define (read1stNumber) (define (create-page kUrl) (html (head (title "First number?")) (body (form action: kUrl "A number please? " (input type: 'text name: "n1") (input type: 'submit value: "go!") )))) (let ((request (show create-page))) (string->number (request-parameter-get request "n1") ) ) ) (define (show page-creator) (call/cc (lambda (k) (answer-then-wait (page-creator (register! k))))))
<HTML> <HEAD> <SCRIPT src='client.js' type='text/javascript'></SCRIPT> <SCRIPT type='text/javascript'>var ldate = new Date();</SCRIPT> </HEAD> <BODY> <SCRIPT type='text/javascript'>var idate = new Date();</SCRIPT> <SPAN onclick='alert( "load: " + ldate + " init: " + idate )'> Client Date </SPAN> <A href='javascript:this.href="http://hop.inria.fr"'> <TT>http://www.inria.fr</TT> </A> </BODY> </HTML>
<HTML> <SCRIPT> function clicklistener( obj, event ) { var el = document.getElementById( "myelement" ); el.style.color = "red"; el.replaceNode( el.firstChild, el.lastChild ); obj.innerHTML = "<span class='myclass'>a text</span>"; } </SCRIPT> ... <DIV onclick='clicklistener( this, event )'> ... </DIV> ... <SPAN id='myelement'> ... </SPAN> </HTML>
var httpRequest = new XMLHttpRequest(); handler = function() { if( httpRequest.readyState == 4 ) { // reponse OK if( httpRequest.status == 200 ) { httpRequest.responseText // -> String httpRequest.responseXML // -> DOM } } } httpRequest.onreadystatechange = handler; httpRequest.open( "GET", "http://www.example.org/something" ); httpRequest.send();
[ { a: 1, foo: [-1e-23, 2.0, true] }, 'and even \nUnicode \uABCD!' ]
JSON.parse
)<html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link type="text/css" rel="stylesheet" href="Dict.css"> <title>Dictionary Suggest</title> <script type="text/javascript" src="dict/dict.nocache.js"></script> </head> <body> <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe> <h1>Dictionary suggest</h1> <table align="center"> <tr> <td colspan="2" style="font-weight:bold;">name:</td> </tr> <tr> <td id="nameFieldContainer"></td> <td id="sendButtonContainer"></td> </tr> </table> </body> </html>
package org.nohwere.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.core.client.GWT; ... public class Dict implements EntryPoint { private static final String SERVER_ERROR = "An error occurred while " + "attempting to contact the server. Please check your network " + "connection and try again."; private final GreetingServiceAsync greetingService = GWT.create(GreetingService.class); public void onModuleLoad() { final Button sendButton = new Button("Send"); final TextBox nameField = new TextBox(); sendButton.addStyleName("sendButton"); RootPanel.get("nameFieldContainer").add(nameField); RootPanel.get("sendButtonContainer").add(sendButton); ... } }
<module rename-to='dict'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name='com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. You can change --> <!-- the theme of your GWT application by uncommenting --> <!-- any one of the following lines. --> <inherits name='com.google.gwt.user.theme.standard.Standard'/> <!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> --> <!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> --> <!-- Other module inherits --> <!-- Specify the app entry point class. --> <entry-point class='org.nohwere.client.Dict'/> </module>
package org.nohwere.server; import org.nohwere.client.GreetingService; import com.google.gwt.user.server.rpc.RemoteServiceServlet; @SuppressWarnings("serial") public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService { public String greetServer(String input) { String serverInfo = getServletContext().getServerInfo(); String userAgent = getThreadLocalRequest().getHeader("User-Agent"); return "Hello, " + input + "!<br><br>I am running " + serverInfo + ".<br><br>It looks like you are using:<br>" + userAgent; } }
package mypackage; public MyUtilityClass { public static int computeLoanInterest(int amt, float interestRate, int term) { ... } public static native void defineBridgeMethod() /*-{ $wnd.computeLoanInterest = function(amt, intRate, term) { return @mypackage.MyUtilityClass::computeLoanInterest(IFI)(amt, intRate, term); } }-*/; } public static native String myMethod(String arg) /*-{ eval("var myVar = 'arg is " + arg + "';"); return myVar; }-*/; class C { void doCallback(String callbackData) { ..... } native void invokeExternal(String data) /*-{ $wnd.externalJsFunction(data, @p.C::doCallback(Ljava/lang/String;)); }-*/; }
http://groups.inf.ed.ac.uk/links/examples/wine.links?_cont=AtEUA7gOAAADATS5DgAAAwMyMDi6DgAAAwItMfoUAA==
<!-- dictionary.html --> <html> <head> <title>Dictionary suggest</title> </head> <body> <h1>Dictionary suggest</h1> <form l:onkeyup="{handler!Suggest(pre)}"> <input type="text" l:name="pre" autocomplete="off"/> </form> <div id="suggestions"/> </body> </html>
## dictionary.links var handler = spawn { fun receiver() { receive { case Suggest(pre) -> suggest(pre); receiver() } } receiver() }; fun lowercase(s) { for (c <- s) [toLower(c)] } fun suggest(pre) client { replaceChildren( format(completions(lowercase(pre))), getNodeById("suggestions") ) } fun format(words) { for (w <- words) <div> <b> {stringToXml(w.word)} </b> <i> {stringToXml(w.type)} </i>: {stringToXml(w.meaning)} </div> }
## dictionary.links (follow) fun completions(pre) server { var wordlist = table "wordlist" with ( word : String, type : String, meaning : String ) from (database "dictionary"); if (pre == "") [] else { query [10] { for (w <-- wordlist) where (w.word =~ /^{pre}.*/) orderby (w.word) [w] } } }
(module dict (library sqlite)) (define-service (dict/completions pre) (sqlite-map (instantiate::sqlite (path "dictionary")) cons (format "SELECT word, type FROM dictionary WHERE word like ~a" pre))) (define-service (dict) (let ((suggest (<DIV>))) (<HTML> (<HEAD> :title "Dictionary suggest" ~(define (suggest pre) (with-hop ($dict/completions (string-downcase pre)) (lambda (v) (innerHTML-set! $suggest (format v))))) ~(define (format words) (map (lambda (w) (<DIV> (<B> (car w)) (<I> (cdr w)))) words))) (<BODY> (<H1> "Dictionary suggest") (<INPUT> :type 'text :onkeyup ~(suggest this.value)) suggest))))
<HTML> <BODY> <TABLE> <TR><TD onclick="alert( '1' )">1</TD></TR> <TR><TD onclick="alert( '2' )">2</TD></TR> <TR><TD onclick="alert( '3' )">3</TD></TR> </TABLE> </BODY> </HTML>
(<HTML> (<BODY> (<TABLE> (<TR> (<TD> :onclick ~(alert "1") 1)) (<TR> (<TD> :onclick ~(alert "2") 2)) (<TR> (<TD> :onclick ~(alert "3") 3)))))
<HTML> <BODY> <TABLE> <?php for( $i=1; $i<4; $i++ ) echo "<TR><TD onclick='alert( $i )'>$i</TD></TR>" ?> </TABLE> </BODY> </HTML>
(<HTML> (<BODY> (<TABLE> (map (lambda (i) (<TR> (<TD> :onclick ~(alert $i) i))) (iota 3 1)))))
(let ((el (<UL> (<LI> "foo") (<LI> "bar") (<LI> "gee")))) (<DIV> el (<BUTTON> :onclick ~(let* ((cs (dom-child-nodes $el)) (c0 (car cs)) (c1 (cadr cs))) (dom-replace-child! $el c1 c0) (dom-append-child! $el c0)) "rotate")))
((lambda (a) (+ 1 a)) 4) → 5
((service (a) (+ 1 a)) 4) → http://localhost:8080/hop/svc-23ab4c7?a=4
(with-hop ($(service (a) (+ 1 a)) 4) (lambda (v) v)) → 5
(define cmd (service (dir) (map (lambda (path) (list (basename path) (file-size path))) (directory->path-list dir)))) (let ((console (<DIV>))) (<DIV> (<BUTTON> "du -sk" :onclick ~(with-hop ($cmd "/tmp") (lambda (v) (dom-set-child-node! $console (<TABLE> (map (lambda (r) (<TR> (<TH> (car r)) (<TD> (cadr r)))) v)))))) console))
(let ((canvas (<CANVAS> :width 650 :height 200))) (<HTML> canvas ~(let ((ctx ($canvas.getContext "2d"))) (set! ctx.lineWidth 10) (add-event-listener! $canvas "mousedown" (lambda (evt) (ctx.lineTo (event-mouse-x evt) (event-mouse-y evt)) (ctx.stroke))))))
(let ((canvas (<CANVAS> :width 650 :height 200))) (<HTML> canvas ~(let ((ctx ($canvas.getContext "2d"))) (set! ctx.lineWidth 10) (add-event-listener! $canvas "mousedown" (lambda (evt) (ctx.lineTo (event-mouse-x evt) (event-mouse-y evt)) (ctx.stroke)))) ~(add-event-listener! $canvas "mousedown" (lambda (evt) (with-hop ($(service (e) (hop-event-broadcast! "draw" e)) (cons (event-mouse-x evt) (event-mouse-y evt)))))) ~(window-open :src $reactive-canvas :title "canvas1") ~(window-open :src $reactive-canvas :title "canvas2")))
(define-service (reactive-canvas) (let ((canvas (<CANVAS> :width 650 :height 200))) (<HTML> canvas ~(let ((ctx ($canvas.getContext "2d"))) (set! ctx.lineWidth 10) (set! ctx.strokeStyle "rgba(0,200,0)") (add-event-listener! server "draw" (lambda (evt) (ctx.lineTo (car evt) (cdr evt)) (ctx.stroke)))))))
(module string-lib (export (number->string/padding nunmber size padding))) (define (number->string/padding number size padding) (let* ((s (number->string number)) (l (string-length s))) (if (>= l size) s (blit! (make-string size padding) s)))) (define (blit! dest src) (let loop ((i (- (string-length dest) 1)) (j (- (string-length src) 1))) (if (> j 0) (begin (string-set! dest i (string-ref src j)) (loop (- i 1) (- j 1))) dest)))
(module web-server (import string-lib) ~(import string-lib) (export web-app/service)) (define-service (web-app n) (<HTML> (<BODY> (number->string/padding n #\0 10)))) (define-service (web-app/service n) (<SPAN> n :onclick ~(alert (number->string/padding n #\0 10)))))
(module web-client $(import web-server) (import string-lib) (export (web-client str))) (define (web-client str) (<BUTTON> :onclick (with-hop ($web-app/service (string->integer str)) (lambda (n) (dom-append-child! document.body n))) str))
t | (define cmd (service (dir) (map file-size (directory->path-list dir)))) (let ((console (<DIV>))) (<DIV> (<BUTTON> "du -sk" :onclick ~(with-hop ($cmd "/tmp") (lambda (v) (dom-set-child-node! $console (<TABLE> (map (lambda (r) (<TR> (<TH> r))) v)))))) console)) | t |
(define-service (shello4) (let ((hello (<SPAN> "Hello"))) (<HTML> (<BODY> :onclick ~(innerHTML-set! $hello "Goodbye") hello " world!"))))
|
(define hello (<SPAN> "Hello")) (define-service (shello5/set x) (innerHTML-set! hello x)) (define-service (shello5 #!key x) (<HTML> (<BODY> :onclick ~(with-hop ($shello5/set $x) (lambda (span) (dom-replace-child! document.body span $hello))) hello " world!")))
markup → ... | tree tree → (<TREE> tree-head tree-body) tree-head → (<TRHEAD> markup) tree-body → (<TRBODY> leaf-or-tree*) leaf-or-tree → leaf | tree leaf → (<TRLEAF> markup)
(define (dir->tree dir) (<TREE> (<TRHEAD> (basename dir)) (<TRBODY> (map (lambda (p) (if (directory? p) (dir->tree p) (<TRLEAF> :value p (basename p)))) (directory->path-list dir))))) (dir->tree (dirname (dirname (the-loading-file)))) |
(abstract-class %http-message (seconds::elong read-only (default (current-seconds))) (header::pair-nil (default '())) (content-length::elong read-only (default #e-1)) (charset (default #f))) (class http-request::%http-message (user::user read-only (default (class-nil user))) (localclientp::bool (default #f)) (http::symbol (default 'HTTP/1.1)) (host::bstring (default "localhost")) (scheme::symbol (default 'http)) (port::bint (default 80)) (method::symbol read-only (default 'GET)) (abspath::bstring (default "")) (connection::symbol (default 'keep-alive))) (final-class http-server-request::http-request (authorization (default #f)) (service::obj (default #unspecified))) (class http-proxy-request::http-request (proxy-authorization (default #f)))
(abstract-class %http-response::%http-message (content-type::obj read-only (default #f)) (request::http-request (default (class-nil http-request))) (bodyp::bool read-only (default #t))) (abstract-class %http-response-local::%http-response (server::bstring (default (hop-server-name))) (start-line::bstring read-only (default "HTTP/1.1 200 Ok"))) (class http-response-hop::%http-response-local (backend read-only) (value::obj read-only)) (class http-response-procedure::%http-response-local (proc::procedure read-only)) (class http-response-file::%http-response-local (file::bstring read-only)) (class http-response-string::%http-response-local (body::bstring read-only (default ""))) (class http-response-authentication::http-response-string)
(define-service (service) (if (authorized-service? (current-request) 'service) ;; access authorized ... the actual implementation ... ;; return a "401 Unauthorized" (user-access-denied (current-request)))) (define-service (service2) (let ((req (current-request))) (with-access::http-request req (user localclientp abspath) (if (or localclientp (and (user-authorized-request? user req) (user-authorized-path? user abspath))) ... the actual implementation ... (user-access-denied req))))) (define (user-access-denied req) (instantiate::http-response-authentication (header (authenticate-header req)) (start-line "HTTP/1.0 401 Unauthorized") (request req) (body "Protected Area! Authentication required.")))
$ wget ftp://ftp-sop.inria.fr/indes/fp/Hop/hop-2.4.0.tar.gz $ tar xvfz hop-2.4.0.tar.gz $ cd hop-2.4.0 $ ./configure && make && sudo make install
$ hop -v
$ firefox http://localhost:8080/hop/wizard
$ firefox http://localhost:8080/hop
example |-- config.hop |-- etc | |-- favicon.png | |-- example.wiki | |-- homepage | | |-- 01-homepage.png | | `-- 01-homepage.wiki | |-- logo.png | `-- weblet.info |-- example.hop `-- example.hss
//---------------------------------------------------------------------
// QRCode for JavaScript
//
// Copyright (c) 2009 Kazuhiko Arase
//
// URL: http://www.d-project.com/
//
// Licensed under the MIT license:
// http://www.opensource.org/licenses/mit-license.php
//
// The word "QR Code" is registered trademark of
// DENSO WAVE INCORPORATED
// http://www.denso-wave.com/qrcode/faqpatent-e.html
//
//---------------------------------------------------------------------
//---------------------------------------------------------------------
// QR8bitByte
//---------------------------------------------------------------------
function QR8bitByte(data) {
this.mode = QRMode.MODE_8BIT_BYTE;
this.data = data;
}
QR8bitByte.prototype = {
getLength : function(buffer) {
return this.data.length;
},
write : function(buffer) {
for (var i = 0; i < this.data.length; i++) {
// not JIS ...
buffer.put(this.data.charCodeAt(i), 8);
}
}
};
//---------------------------------------------------------------------
// QRCode
//---------------------------------------------------------------------
function QRCode(typeNumber, errorCorrectLevel) {
this.typeNumber = typeNumber;
this.errorCorrectLevel = errorCorrectLevel;
this.modules = null;
this.moduleCount = 0;
this.dataCache = null;
this.dataList = new Array();
}
QRCode.prototype = {
addData : function(data) {
var newData = new QR8bitByte(data);
this.dataList.push(newData);
this.dataCache = null;
},
isDark : function(row, col) {
if (row < 0 || this.moduleCount <= row || col < 0 || this.moduleCount <= col) {
throw new Error(row + "," + col);
}
return this.modules[row][col];
},
getModuleCount : function() {
return this.moduleCount;
},
make : function() {
this.makeImpl(false, this.getBestMaskPattern() );
},
makeImpl : function(test, maskPattern) {
this.moduleCount = this.typeNumber * 4 + 17;
this.modules = new Array(this.moduleCount);
for (var row = 0; row < this.moduleCount; row++) {
this.modules[row] = new Array(this.moduleCount);
for (var col = 0; col < this.moduleCount; col++) {
this.modules[row][col] = null;//(col + row) % 3;
}
}
this.setupPositionProbePattern(0, 0);
this.setupPositionProbePattern(this.moduleCount - 7, 0);
this.setupPositionProbePattern(0, this.moduleCount - 7);
this.setupPositionAdjustPattern();
this.setupTimingPattern();
this.setupTypeInfo(test, maskPattern);
if (this.typeNumber >= 7) {
this.setupTypeNumber(test);
}
if (this.dataCache == null) {
this.dataCache = QRCode.createData(this.typeNumber, this.errorCorrectLevel, this.dataList);
}
this.mapData(this.dataCache, maskPattern);
},
setupPositionProbePattern : function(row, col) {
for (var r = -1; r <= 7; r++) {
if (row + r <= -1 || this.moduleCount <= row + r) continue;
for (var c = -1; c <= 7; c++) {
if (col + c <= -1 || this.moduleCount <= col + c) continue;
if ( (0 <= r && r <= 6 && (c == 0 || c == 6) )
|| (0 <= c && c <= 6 && (r == 0 || r == 6) )
|| (2 <= r && r <= 4 && 2 <= c && c <= 4) ) {
this.modules[row + r][col + c] = true;
} else {
this.modules[row + r][col + c] = false;
}
}
}
},
getBestMaskPattern : function() {
var minLostPoint = 0;
var pattern = 0;
for (var i = 0; i < 8; i++) {
this.makeImpl(true, i);
var lostPoint = QRUtil.getLostPoint(this);
if (i == 0 || minLostPoint > lostPoint) {
minLostPoint = lostPoint;
pattern = i;
}
}
return pattern;
},
createMovieClip : function(target_mc, instance_name, depth) {
var qr_mc = target_mc.createEmptyMovieClip(instance_name, depth);
var cs = 1;
this.make();
for (var row = 0; row < this.modules.length; row++) {
var y = row * cs;
for (var col = 0; col < this.modules[row].length; col++) {
var x = col * cs;
var dark = this.modules[row][col];
if (dark) {
qr_mc.beginFill(0, 100);
qr_mc.moveTo(x, y);
qr_mc.lineTo(x + cs, y);
qr_mc.lineTo(x + cs, y + cs);
qr_mc.lineTo(x, y + cs);
qr_mc.endFill();
}
}
}
return qr_mc;
},
setupTimingPattern : function() {
for (var r = 8; r < this.moduleCount - 8; r++) {
if (this.modules[r][6] != null) {
continue;
}
this.modules[r][6] = (r % 2 == 0);
}
for (var c = 8; c < this.moduleCount - 8; c++) {
if (this.modules[6][c] != null) {
continue;
}
this.modules[6][c] = (c % 2 == 0);
}
},
setupPositionAdjustPattern : function() {
var pos = QRUtil.getPatternPosition(this.typeNumber);
for (var i = 0; i < pos.length; i++) {
for (var j = 0; j < pos.length; j++) {
var row = pos[i];
var col = pos[j];
if (this.modules[row][col] != null) {
continue;
}
for (var r = -2; r <= 2; r++) {
for (var c = -2; c <= 2; c++) {
if (r == -2 || r == 2 || c == -2 || c == 2
|| (r == 0 && c == 0) ) {
this.modules[row + r][col + c] = true;
} else {
this.modules[row + r][col + c] = false;
}
}
}
}
}
},
setupTypeNumber : function(test) {
var bits = QRUtil.getBCHTypeNumber(this.typeNumber);
for (var i = 0; i < 18; i++) {
var mod = (!test && ( (bits >> i) & 1) == 1);
this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod;
}
for (var i = 0; i < 18; i++) {
var mod = (!test && ( (bits >> i) & 1) == 1);
this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
}
},
setupTypeInfo : function(test, maskPattern) {
var data = (this.errorCorrectLevel << 3) | maskPattern;
var bits = QRUtil.getBCHTypeInfo(data);
// vertical
for (var i = 0; i < 15; i++) {
var mod = (!test && ( (bits >> i) & 1) == 1);
if (i < 6) {
this.modules[i][8] = mod;
} else if (i < 8) {
this.modules[i + 1][8] = mod;
} else {
this.modules[this.moduleCount - 15 + i][8] = mod;
}
}
// horizontal
for (var i = 0; i < 15; i++) {
var mod = (!test && ( (bits >> i) & 1) == 1);
if (i < 8) {
this.modules[8][this.moduleCount - i - 1] = mod;
} else if (i < 9) {
this.modules[8][15 - i - 1 + 1] = mod;
} else {
this.modules[8][15 - i - 1] = mod;
}
}
// fixed module
this.modules[this.moduleCount - 8][8] = (!test);
},
mapData : function(data, maskPattern) {
var inc = -1;
var row = this.moduleCount - 1;
var bitIndex = 7;
var byteIndex = 0;
for (var col = this.moduleCount - 1; col > 0; col -= 2) {
if (col == 6) col--;
while (true) {
for (var c = 0; c < 2; c++) {
if (this.modules[row][col - c] == null) {
var dark = false;
if (byteIndex < data.length) {
dark = ( ( (data[byteIndex] >>> bitIndex) & 1) == 1);
}
var mask = QRUtil.getMask(maskPattern, row, col - c);
if (mask) {
dark = !dark;
}
this.modules[row][col - c] = dark;
bitIndex--;
if (bitIndex == -1) {
byteIndex++;
bitIndex = 7;
}
}
}
row += inc;
if (row < 0 || this.moduleCount <= row) {
row -= inc;
inc = -inc;
break;
}
}
}
}
};
QRCode.PAD0 = 0xEC;
QRCode.PAD1 = 0x11;
QRCode.createData = function(typeNumber, errorCorrectLevel, dataList) {
var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel);
var buffer = new QRBitBuffer();
for (var i = 0; i < dataList.length; i++) {
var data = dataList[i];
buffer.put(data.mode, 4);
buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber) );
data.write(buffer);
}
// calc num max data.
var totalDataCount = 0;
for (var i = 0; i < rsBlocks.length; i++) {
totalDataCount += rsBlocks[i].dataCount;
}
if (buffer.getLengthInBits() > totalDataCount * 8) {
throw new Error("code length overflow. ("
+ buffer.getLengthInBits()
+ ">"
+ totalDataCount * 8
+ ")");
}
// end code
if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) {
buffer.put(0, 4);
}
// padding
while (buffer.getLengthInBits() % 8 != 0) {
buffer.putBit(false);
}
// padding
while (true) {
if (buffer.getLengthInBits() >= totalDataCount * 8) {
break;
}
buffer.put(QRCode.PAD0, 8);
if (buffer.getLengthInBits() >= totalDataCount * 8) {
break;
}
buffer.put(QRCode.PAD1, 8);
}
return QRCode.createBytes(buffer, rsBlocks);
}
QRCode.createBytes = function(buffer, rsBlocks) {
var offset = 0;
var maxDcCount = 0;
var maxEcCount = 0;
var dcdata = new Array(rsBlocks.length);
var ecdata = new Array(rsBlocks.length);
for (var r = 0; r < rsBlocks.length; r++) {
var dcCount = rsBlocks[r].dataCount;
var ecCount = rsBlocks[r].totalCount - dcCount;
maxDcCount = Math.max(maxDcCount, dcCount);
maxEcCount = Math.max(maxEcCount, ecCount);
dcdata[r] = new Array(dcCount);
for (var i = 0; i < dcdata[r].length; i++) {
dcdata[r][i] = 0xff & buffer.buffer[i + offset];
}
offset += dcCount;
var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);
var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1);
var modPoly = rawPoly.mod(rsPoly);
ecdata[r] = new Array(rsPoly.getLength() - 1);
for (var i = 0; i < ecdata[r].length; i++) {
var modIndex = i + modPoly.getLength() - ecdata[r].length;
ecdata[r][i] = (modIndex >= 0)? modPoly.get(modIndex) : 0;
}
}
var totalCodeCount = 0;
for (var i = 0; i < rsBlocks.length; i++) {
totalCodeCount += rsBlocks[i].totalCount;
}
var data = new Array(totalCodeCount);
var index = 0;
for (var i = 0; i < maxDcCount; i++) {
for (var r = 0; r < rsBlocks.length; r++) {
if (i < dcdata[r].length) {
data[index++] = dcdata[r][i];
}
}
}
for (var i = 0; i < maxEcCount; i++) {
for (var r = 0; r < rsBlocks.length; r++) {
if (i < ecdata[r].length) {
data[index++] = ecdata[r][i];
}
}
}
return data;
}
//---------------------------------------------------------------------
// QRMode
//---------------------------------------------------------------------
var QRMode = {
MODE_NUMBER : 1 << 0,
MODE_ALPHA_NUM : 1 << 1,
MODE_8BIT_BYTE : 1 << 2,
MODE_KANJI : 1 << 3
};
//---------------------------------------------------------------------
// QRErrorCorrectLevel
//---------------------------------------------------------------------
var QRErrorCorrectLevel = {
L : 1,
M : 0,
Q : 3,
H : 2
};
//---------------------------------------------------------------------
// QRMaskPattern
//---------------------------------------------------------------------
var QRMaskPattern = {
PATTERN000 : 0,
PATTERN001 : 1,
PATTERN010 : 2,
PATTERN011 : 3,
PATTERN100 : 4,
PATTERN101 : 5,
PATTERN110 : 6,
PATTERN111 : 7
};
//---------------------------------------------------------------------
// QRUtil
//---------------------------------------------------------------------
var QRUtil = {
PATTERN_POSITION_TABLE : [
[],
[6, 18],
[6, 22],
[6, 26],
[6, 30],
[6, 34],
[6, 22, 38],
[6, 24, 42],
[6, 26, 46],
[6, 28, 50],
[6, 30, 54],
[6, 32, 58],
[6, 34, 62],
[6, 26, 46, 66],
[6, 26, 48, 70],
[6, 26, 50, 74],
[6, 30, 54, 78],
[6, 30, 56, 82],
[6, 30, 58, 86],
[6, 34, 62, 90],
[6, 28, 50, 72, 94],
[6, 26, 50, 74, 98],
[6, 30, 54, 78, 102],
[6, 28, 54, 80, 106],
[6, 32, 58, 84, 110],
[6, 30, 58, 86, 114],
[6, 34, 62, 90, 118],
[6, 26, 50, 74, 98, 122],
[6, 30, 54, 78, 102, 126],
[6, 26, 52, 78, 104, 130],
[6, 30, 56, 82, 108, 134],
[6, 34, 60, 86, 112, 138],
[6, 30, 58, 86, 114, 142],
[6, 34, 62, 90, 118, 146],
[6, 30, 54, 78, 102, 126, 150],
[6, 24, 50, 76, 102, 128, 154],
[6, 28, 54, 80, 106, 132, 158],
[6, 32, 58, 84, 110, 136, 162],
[6, 26, 54, 82, 110, 138, 166],
[6, 30, 58, 86, 114, 142, 170]
],
G15 : (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0),
G18 : (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0),
G15_MASK : (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1),
getBCHTypeInfo : function(data) {
var d = data << 10;
while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) {
d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) ) );
}
return ( (data << 10) | d) ^ QRUtil.G15_MASK;
},
getBCHTypeNumber : function(data) {
var d = data << 12;
while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) {
d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) ) );
}
return (data << 12) | d;
},
getBCHDigit : function(data) {
var digit = 0;
while (data != 0) {
digit++;
data >>>= 1;
}
return digit;
},
getPatternPosition : function(typeNumber) {
return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1];
},
getMask : function(maskPattern, i, j) {
switch (maskPattern) {
case QRMaskPattern.PATTERN000 : return (i + j) % 2 == 0;
case QRMaskPattern.PATTERN001 : return i % 2 == 0;
case QRMaskPattern.PATTERN010 : return j % 3 == 0;
case QRMaskPattern.PATTERN011 : return (i + j) % 3 == 0;
case QRMaskPattern.PATTERN100 : return (Math.floor(i / 2) + Math.floor(j / 3) ) % 2 == 0;
case QRMaskPattern.PATTERN101 : return (i * j) % 2 + (i * j) % 3 == 0;
case QRMaskPattern.PATTERN110 : return ( (i * j) % 2 + (i * j) % 3) % 2 == 0;
case QRMaskPattern.PATTERN111 : return ( (i * j) % 3 + (i + j) % 2) % 2 == 0;
default :
throw new Error("bad maskPattern:" + maskPattern);
}
},
getErrorCorrectPolynomial : function(errorCorrectLength) {
var a = new QRPolynomial([1], 0);
for (var i = 0; i < errorCorrectLength; i++) {
a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0) );
}
return a;
},
getLengthInBits : function(mode, type) {
if (1 <= type && type < 10) {
// 1 - 9
switch(mode) {
case QRMode.MODE_NUMBER : return 10;
case QRMode.MODE_ALPHA_NUM : return 9;
case QRMode.MODE_8BIT_BYTE : return 8;
case QRMode.MODE_KANJI : return 8;
default :
throw new Error("mode:" + mode);
}
} else if (type < 27) {
// 10 - 26
switch(mode) {
case QRMode.MODE_NUMBER : return 12;
case QRMode.MODE_ALPHA_NUM : return 11;
case QRMode.MODE_8BIT_BYTE : return 16;
case QRMode.MODE_KANJI : return 10;
default :
throw new Error("mode:" + mode);
}
} else if (type < 41) {
// 27 - 40
switch(mode) {
case QRMode.MODE_NUMBER : return 14;
case QRMode.MODE_ALPHA_NUM : return 13;
case QRMode.MODE_8BIT_BYTE : return 16;
case QRMode.MODE_KANJI : return 12;
default :
throw new Error("mode:" + mode);
}
} else {
throw new Error("type:" + type);
}
},
getLostPoint : function(qrCode) {
var moduleCount = qrCode.getModuleCount();
var lostPoint = 0;
// LEVEL1
for (var row = 0; row < moduleCount; row++) {
for (var col = 0; col < moduleCount; col++) {
var sameCount = 0;
var dark = qrCode.isDark(row, col);
for (var r = -1; r <= 1; r++) {
if (row + r < 0 || moduleCount <= row + r) {
continue;
}
for (var c = -1; c <= 1; c++) {
if (col + c < 0 || moduleCount <= col + c) {
continue;
}
if (r == 0 && c == 0) {
continue;
}
if (dark == qrCode.isDark(row + r, col + c) ) {
sameCount++;
}
}
}
if (sameCount > 5) {
lostPoint += (3 + sameCount - 5);
}
}
}
// LEVEL2
for (var row = 0; row < moduleCount - 1; row++) {
for (var col = 0; col < moduleCount - 1; col++) {
var count = 0;
if (qrCode.isDark(row, col ) ) count++;
if (qrCode.isDark(row + 1, col ) ) count++;
if (qrCode.isDark(row, col + 1) ) count++;
if (qrCode.isDark(row + 1, col + 1) ) count++;
if (count == 0 || count == 4) {
lostPoint += 3;
}
}
}
// LEVEL3
for (var row = 0; row < moduleCount; row++) {
for (var col = 0; col < moduleCount - 6; col++) {
if (qrCode.isDark(row, col)
&& !qrCode.isDark(row, col + 1)
&& qrCode.isDark(row, col + 2)
&& qrCode.isDark(row, col + 3)
&& qrCode.isDark(row, col + 4)
&& !qrCode.isDark(row, col + 5)
&& qrCode.isDark(row, col + 6) ) {
lostPoint += 40;
}
}
}
for (var col = 0; col < moduleCount; col++) {
for (var row = 0; row < moduleCount - 6; row++) {
if (qrCode.isDark(row, col)
&& !qrCode.isDark(row + 1, col)
&& qrCode.isDark(row + 2, col)
&& qrCode.isDark(row + 3, col)
&& qrCode.isDark(row + 4, col)
&& !qrCode.isDark(row + 5, col)
&& qrCode.isDark(row + 6, col) ) {
lostPoint += 40;
}
}
}
// LEVEL4
var darkCount = 0;
for (var col = 0; col < moduleCount; col++) {
for (var row = 0; row < moduleCount; row++) {
if (qrCode.isDark(row, col) ) {
darkCount++;
}
}
}
var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
lostPoint += ratio * 10;
return lostPoint;
}
};
//---------------------------------------------------------------------
// QRMath
//---------------------------------------------------------------------
var QRMath = {
glog : function(n) {
if (n < 1) {
throw new Error("glog(" + n + ")");
}
return QRMath.LOG_TABLE[n];
},
gexp : function(n) {
while (n < 0) {
n += 255;
}
while (n >= 256) {
n -= 255;
}
return QRMath.EXP_TABLE[n];
},
EXP_TABLE : new Array(256),
LOG_TABLE : new Array(256)
};
for (var i = 0; i < 8; i++) {
QRMath.EXP_TABLE[i] = 1 << i;
}
for (var i = 8; i < 256; i++) {
QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4]
^ QRMath.EXP_TABLE[i - 5]
^ QRMath.EXP_TABLE[i - 6]
^ QRMath.EXP_TABLE[i - 8];
}
for (var i = 0; i < 255; i++) {
QRMath.LOG_TABLE[QRMath.EXP_TABLE[i] ] = i;
}
//---------------------------------------------------------------------
// QRPolynomial
//---------------------------------------------------------------------
function QRPolynomial(num, shift) {
if (num.length == undefined) {
throw new Error(num.length + "/" + shift);
}
var offset = 0;
while (offset < num.length && num[offset] == 0) {
offset++;
}
this.num = new Array(num.length - offset + shift);
for (var i = 0; i < num.length - offset; i++) {
this.num[i] = num[i + offset];
}
}
QRPolynomial.prototype = {
get : function(index) {
return this.num[index];
},
getLength : function() {
return this.num.length;
},
multiply : function(e) {
var num = new Array(this.getLength() + e.getLength() - 1);
for (var i = 0; i < this.getLength(); i++) {
for (var j = 0; j < e.getLength(); j++) {
num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i) ) + QRMath.glog(e.get(j) ) );
}
}
return new QRPolynomial(num, 0);
},
mod : function(e) {
if (this.getLength() - e.getLength() < 0) {
return this;
}
var ratio = QRMath.glog(this.get(0) ) - QRMath.glog(e.get(0) );
var num = new Array(this.getLength() );
for (var i = 0; i < this.getLength(); i++) {
num[i] = this.get(i);
}
for (var i = 0; i < e.getLength(); i++) {
num[i] ^= QRMath.gexp(QRMath.glog(e.get(i) ) + ratio);
}
// recursive call
return new QRPolynomial(num, 0).mod(e);
}
};
//---------------------------------------------------------------------
// QRRSBlock
//---------------------------------------------------------------------
function QRRSBlock(totalCount, dataCount) {
this.totalCount = totalCount;
this.dataCount = dataCount;
}
QRRSBlock.RS_BLOCK_TABLE = [
// L
// M
// Q
// H
// 1
[1, 26, 19],
[1, 26, 16],
[1, 26, 13],
[1, 26, 9],
// 2
[1, 44, 34],
[1, 44, 28],
[1, 44, 22],
[1, 44, 16],
// 3
[1, 70, 55],
[1, 70, 44],
[2, 35, 17],
[2, 35, 13],
// 4
[1, 100, 80],
[2, 50, 32],
[2, 50, 24],
[4, 25, 9],
// 5
[1, 134, 108],
[2, 67, 43],
[2, 33, 15, 2, 34, 16],
[2, 33, 11, 2, 34, 12],
// 6
[2, 86, 68],
[4, 43, 27],
[4, 43, 19],
[4, 43, 15],
// 7
[2, 98, 78],
[4, 49, 31],
[2, 32, 14, 4, 33, 15],
[4, 39, 13, 1, 40, 14],
// 8
[2, 121, 97],
[2, 60, 38, 2, 61, 39],
[4, 40, 18, 2, 41, 19],
[4, 40, 14, 2, 41, 15],
// 9
[2, 146, 116],
[3, 58, 36, 2, 59, 37],
[4, 36, 16, 4, 37, 17],
[4, 36, 12, 4, 37, 13],
// 10
[2, 86, 68, 2, 87, 69],
[4, 69, 43, 1, 70, 44],
[6, 43, 19, 2, 44, 20],
[6, 43, 15, 2, 44, 16]
];
QRRSBlock.getRSBlocks = function(typeNumber, errorCorrectLevel) {
var rsBlock = QRRSBlock.getRsBlockTable(typeNumber, errorCorrectLevel);
if (rsBlock == undefined) {
throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + errorCorrectLevel);
}
var length = rsBlock.length / 3;
var list = new Array();
for (var i = 0; i < length; i++) {
var count = rsBlock[i * 3 + 0];
var totalCount = rsBlock[i * 3 + 1];
var dataCount = rsBlock[i * 3 + 2];
for (var j = 0; j < count; j++) {
list.push(new QRRSBlock(totalCount, dataCount) );
}
}
return list;
}
QRRSBlock.getRsBlockTable = function(typeNumber, errorCorrectLevel) {
switch(errorCorrectLevel) {
case QRErrorCorrectLevel.L :
return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
case QRErrorCorrectLevel.M :
return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
case QRErrorCorrectLevel.Q :
return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
case QRErrorCorrectLevel.H :
return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
default :
return undefined;
}
}
//---------------------------------------------------------------------
// QRBitBuffer
//---------------------------------------------------------------------
function QRBitBuffer() {
this.buffer = new Array();
this.length = 0;
}
QRBitBuffer.prototype = {
get : function(index) {
var bufIndex = Math.floor(index / 8);
return ( (this.buffer[bufIndex] >>> (7 - index % 8) ) & 1) == 1;
},
put : function(num, length) {
for (var i = 0; i < length; i++) {
this.putBit( ( (num >>> (length - i - 1) ) & 1) == 1);
}
},
getLengthInBits : function() {
return this.length;
},
putBit : function(bit) {
var bufIndex = Math.floor(this.length / 8);
if (this.buffer.length <= bufIndex) {
this.buffer.push(0);
}
if (bit) {
this.buffer[bufIndex] |= (0x80 >>> (this.length % 8) );
}
this.length++;
}
};
(module qrcode ~(javascript QRCode) (export (<QRCODE> url))) ~(define (<QRCODE> url) (let ((qr (new QRCode 4 "L"))) (qr.addData $url) (qr.make) (let ((l (iota (qr.getModuleCount)))) (dom-append-child! document (<TABLE> :class "qrcode" (map (lambda (r) (<TR> (map (lambda (c) (<TD> :class (if (qr.isDark r c) "B" "W"))) l))) l))))))
(define-service (hopvidemo) (<HTML> (<HEAD> :include "hop-canvas" :include "hopvidemo") (<BODY> ~(add-event-listener! window "load" hopvidemo-init) (<H1> "A plain video") (<DIV> :style "text-align: center" (<VIDEO> :src (service-resource hopvidemo "hopx10.ogv") :width 320 :height 200 :controls #t)) (<H1> "A video with a reflection effect") (<DIV> :style "text-align: center" (<VIDEO> :id "video" :src (service-resource hopvidemo "hopx10.ogv") :width 320 :height 200 :controls #t) (<DIV> (<CANVAS> :id "c1" :style "display: none") (<CANVAS> :id "c2" :style "height: 67px"))))))
(define video #unspecified) (define c1 #unspecified) (define c2 #unspecified) (define ctx1 #unspecified) (define ctx2 #unspecified) (define (hopvidemo-init) (set! video (dom-get-element-by-id "video")) (set! c1 (dom-get-element-by-id "c1")) (set! ctx1 (canvas-get-context c1 "2d")) (set! c2 (dom-get-element-by-id "c2")) (set! ctx2 (canvas-get-context c2 "2d")) (add-event-listener! video "play" (lambda () (let ((height (min 256 (/ video.height 3)))) (set! c1.width video.width) (set! c1.height height) (set! c2.width video.width) (set! c2.height height) (let loop () (unless (or video.paused video.ended) (compute-frame) (after 0 loop)))))))
(define (compute-frame) (canvas-save ctx1) (canvas-set-transform ctx1 1 0 0 -1 0 video.height) (canvas-draw-image ctx1 video 0 0 video.width video.height) (canvas-restore ctx1) (let* ((frame (canvas-get-image-data ctx1 0 0 c1.width c1.height)) (data frame.data) (l (/ data.length 4)) (step (round (/ 256 c2.height)))) ;; shaded rows (let loop ((j 0)) (when (< j c2.height) (let ((alpha (max 0 (- 256 (* step j))))) (alpha-row data video.width j alpha) (loop (+ j 1))))) ;; draw the image (canvas-put-image-data ctx2 frame 0 0))) (define (alpha-row data width j a) (let loop ((i 0)) (when (< i (+ j width)) (vector-set! data (+ 3 (* 4 (+ i (* width j)))) a) (loop (+ i 1)))))
(module translate) (define-service (translate) (let ((input (<INPUT> :type 'text)) (output (<DIV> :id "result"))) (<HTML> input output (<BUTTON> :onclick ~(with-hop ($translate/text $input.value) (lambda (v) (innerHTML-set! $output v))) "translate"))))
(define-service (translate/text text) (with-url (format "http://mymemory.translated.net/api/get?&q=~a&langpair=~a" (url-path-encode text) (url-path-encode "fr|en")) (lambda (o) (let* ((k (cadr (assq :responseStatus o))) (d (cadr (assq :responseData o)))) (if (and (integer? k) (= k 200)) (let ((t (cadr (assq :translatedText d)))) (charset-convert (html-string-decode t) 'UTF-8 (hop-charset))) "")))))
(module pdfbook ~(import (pdfjs-api_client "pdfjs-api-1.*.*.hz")) (import (pdfjs-api "pdfjs-api-1.*.*.hz")) (import (turnjs-api "turnjs-api-1.*.*.hz"))) (define-service (pdfbook #!key src) (<HTML> (<HEAD> :title "PDFBOOK" :include "turnjs-api-1.*.*.hz" "pdfjs-api-1.*.*.hz") (<DIV> ~(add-event-listener! window "load" (lambda () (let ((mag ((@ jQuery js) "#paper"))) (mag.turn (alist->jsobject '((acceleration: #t) (duration: 5000))))))) (<DIV> :id "paper" (map (lambda (i) (<PDF> :controls #f :src src :page i)) (iota 10 1))))))
(module androidemo (library mail phone hopdroid) (import androidemo_config)) (define android (instantiate::androidphone)) (define atts (instantiate::androidtts (phone android)))
(<DIV> (<TEXTAREA> :id "speech" "") (<DIV> "language: " (let ((locale (phone-current-locale android))) (<SELECT> :onchange ~(with-hop ($(service (s) (let ((l (call-with-input-string s read))) (tts-locale-set! atts l))) this.value)) (filter-map (lambda (l) (when (eq? (tts-locale-check atts l) 'lang-country) (<OPTION> :label (list-ref l 3) :value (with-output-to-string (lambda () (write l))) :selected (equal? l locale) (list-ref l 3)))) (phone-locales android))))) (<BUTTON> :onclick ~(let ((el (dom-get-element-by-id "speech"))) (with-hop ($(service (text) (tts-speak atts text)) el.value))) "Speak"))
(add-event-listener! android "sms-received" (lambda (e) (let ((val (event-value e))) (hop-event-broadcast! "sms-received" val) (tts-speak atts (cadr val))))) (<DIV> ~(add-event-listener! server "sms-received" (lambda (e) (innerHTML-set! "sms-received-no" (car (event-value e))) (innerHTML-set! "sms-received-text" (cadr (event-value e))))) (<DIV> "From: " (<SPAN> :id "sms-received-no")) (<PRE> :id "sms-received-text" ""))
~(add-event-listener! window "deviceorientation" (lambda (e) (with-hop ($(service (x) (hop-event-signal! "orientation" x)) e.gamma))))
~(add-event-listener! server "orientation" (lambda (e) (node-style-set! (hopslide-current-slide) :MozTransform (format "rotate: (~adeg)" e.value))))