├── IOS
├── Example Apps
│ ├── ExampleApp-OSX
│ │ ├── en.lproj
│ │ │ ├── InfoPlist.strings
│ │ │ └── Credits.rtf
│ │ ├── ExampleApp-OSX-Prefix.pch
│ │ ├── main.m
│ │ ├── AppDelegate.h
│ │ ├── ExampleApp-OSX-Info.plist
│ │ └── AppDelegate.m
│ ├── ExampleApp-iOS
│ │ ├── en.lproj
│ │ │ └── InfoPlist.strings
│ │ ├── Default-568h@2x.png
│ │ ├── main.m
│ │ ├── ExampleApp-iOS-Prefix.pch
│ │ ├── ExampleAppDelegate.h
│ │ ├── ExampleApp-iOS-Info.plist
│ │ └── ExampleAppDelegate.m
│ ├── ExampleApp.html
│ ├── ExampleApp-iOS.xcodeproj
│ │ └── project.pbxproj
│ └── ExampleApp-OSX.xcodeproj
│ │ └── project.pbxproj
├── WebViewJavascriptBridge.podspec
├── LICENSE
├── WebViewJavascriptBridge
│ ├── WebViewJavascriptBridge.h
│ └── WebViewJavascriptBridge.js.txt
├── Changelog
└── README.md
├── Chrome
├── Example
│ └── simple_extension
│ │ ├── clock.png
│ │ ├── manifest.json
│ │ ├── user_server.js
│ │ ├── user_client.js
│ │ ├── bridgeClientChrome.js
│ │ └── bridgeServerChrome.js
└── js
│ ├── bridgeClientChrome.js
│ └── bridgeServerChrome.js
├── problem.txt
├── .gitignore
├── Android
├── Example
│ ├── res
│ │ ├── values
│ │ │ └── strings.xml
│ │ ├── layout
│ │ │ └── main.xml
│ │ └── raw
│ │ │ ├── user_client.html
│ │ │ └── WebViewJavascriptBridge.js
│ ├── project.properties
│ ├── Example.iml
│ ├── AndroidManifest.xml
│ ├── ant.properties
│ ├── WebViewJavascriptBridgeExample.iml
│ ├── proguard-project.txt
│ ├── design
│ │ ├── iosdesign.txt
│ │ └── design.txt
│ ├── src
│ │ └── com
│ │ │ ├── example
│ │ │ └── WebViewJavascriptBridgeExample
│ │ │ │ └── MyActivity.java
│ │ │ └── fangjian
│ │ │ └── WebViewJavascriptBridge.java
│ ├── .gitignore
│ └── build.xml
├── ExampleWithWebViewMap
│ ├── res
│ │ ├── values
│ │ │ └── strings.xml
│ │ ├── raw
│ │ │ ├── user_client.html
│ │ │ └── webviewjavascriptbridge.js
│ │ └── layout
│ │ │ └── main.xml
│ ├── assets
│ │ └── map
│ │ │ ├── mapbox
│ │ │ ├── images
│ │ │ │ ├── icons-000000.png
│ │ │ │ ├── icons-ffffff.png
│ │ │ │ ├── icons-000000@2x.png
│ │ │ │ ├── icons-ffffff@2x.png
│ │ │ │ └── render.sh
│ │ │ └── mapbox.css
│ │ │ ├── leaflet-0.7.2
│ │ │ ├── images
│ │ │ │ ├── layers.png
│ │ │ │ ├── layers-2x.png
│ │ │ │ ├── marker-icon.png
│ │ │ │ ├── marker-icon-2x.png
│ │ │ │ └── marker-shadow.png
│ │ │ └── leaflet.css
│ │ │ ├── poi.json
│ │ │ ├── area.json
│ │ │ ├── map.html
│ │ │ └── map.json
│ ├── project.properties
│ ├── Example.iml
│ ├── ant.properties
│ ├── AndroidManifest.xml
│ ├── WebViewJavascriptBridgeExample.iml
│ ├── proguard-project.txt
│ ├── design
│ │ ├── iosdesign.txt
│ │ └── design.txt
│ ├── src
│ │ └── com
│ │ │ ├── example
│ │ │ └── WebViewJavascriptBridgeExample
│ │ │ │ └── MyActivity.java
│ │ │ └── fangjian
│ │ │ └── WebViewJavascriptBridge.java
│ ├── .gitignore
│ └── build.xml
└── WebViewJavascriptBridge
│ ├── res
│ └── raw
│ │ └── webviewjavascriptbridge.js
│ └── src
│ └── com
│ └── fangjian
│ └── WebViewJavascriptBridge.java
├── Html
├── Example
│ ├── multi_js
│ │ ├── example.html
│ │ ├── user_server.js
│ │ ├── user_client.js
│ │ ├── bridgeServerHtml.js
│ │ └── bridgeClientHtml.js
│ └── single_page.html
└── js
│ ├── bridgeServerHtml.js
│ └── bridgeClientHtml.js
└── README.md
/IOS/Example Apps/ExampleApp-OSX/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/IOS/Example Apps/ExampleApp-iOS/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/Chrome/Example/simple_extension/clock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiXing/WebViewJavascriptBridge/HEAD/Chrome/Example/simple_extension/clock.png
--------------------------------------------------------------------------------
/IOS/Example Apps/ExampleApp-iOS/Default-568h@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiXing/WebViewJavascriptBridge/HEAD/IOS/Example Apps/ExampleApp-iOS/Default-568h@2x.png
--------------------------------------------------------------------------------
/problem.txt:
--------------------------------------------------------------------------------
1 | handler(message.data, responseCallback)
2 | responseCallback always exist , but if the other end do not have a callback, call responseCallback cause exception.
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Mac OS X
2 | *.DS_Store
3 |
4 | # Xcode
5 | *.pbxuser
6 | *.mode1v3
7 | *.mode2v3
8 | *.perspectivev3
9 | *.xcuserstate
10 | *.xcworkspace/
11 | xcuserdata/
12 |
--------------------------------------------------------------------------------
/Android/Example/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | WebViewJavascriptBridgeExample
4 |
5 |
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | WebViewJavascriptBridgeExample
4 |
5 |
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/assets/map/mapbox/images/icons-000000.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiXing/WebViewJavascriptBridge/HEAD/Android/ExampleWithWebViewMap/assets/map/mapbox/images/icons-000000.png
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/assets/map/mapbox/images/icons-ffffff.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiXing/WebViewJavascriptBridge/HEAD/Android/ExampleWithWebViewMap/assets/map/mapbox/images/icons-ffffff.png
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/assets/map/leaflet-0.7.2/images/layers.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiXing/WebViewJavascriptBridge/HEAD/Android/ExampleWithWebViewMap/assets/map/leaflet-0.7.2/images/layers.png
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/assets/map/leaflet-0.7.2/images/layers-2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiXing/WebViewJavascriptBridge/HEAD/Android/ExampleWithWebViewMap/assets/map/leaflet-0.7.2/images/layers-2x.png
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/assets/map/mapbox/images/icons-000000@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiXing/WebViewJavascriptBridge/HEAD/Android/ExampleWithWebViewMap/assets/map/mapbox/images/icons-000000@2x.png
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/assets/map/mapbox/images/icons-ffffff@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiXing/WebViewJavascriptBridge/HEAD/Android/ExampleWithWebViewMap/assets/map/mapbox/images/icons-ffffff@2x.png
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/assets/map/leaflet-0.7.2/images/marker-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiXing/WebViewJavascriptBridge/HEAD/Android/ExampleWithWebViewMap/assets/map/leaflet-0.7.2/images/marker-icon.png
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/assets/map/leaflet-0.7.2/images/marker-icon-2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiXing/WebViewJavascriptBridge/HEAD/Android/ExampleWithWebViewMap/assets/map/leaflet-0.7.2/images/marker-icon-2x.png
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/assets/map/leaflet-0.7.2/images/marker-shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiXing/WebViewJavascriptBridge/HEAD/Android/ExampleWithWebViewMap/assets/map/leaflet-0.7.2/images/marker-shadow.png
--------------------------------------------------------------------------------
/IOS/Example Apps/ExampleApp-OSX/ExampleApp-OSX-Prefix.pch:
--------------------------------------------------------------------------------
1 | //
2 | // Prefix header for all source files of the 'ExampleApp-OSX' target in the 'ExampleApp-OSX' project
3 | //
4 |
5 | #ifdef __OBJC__
6 | #import
7 | #endif
8 |
--------------------------------------------------------------------------------
/IOS/Example Apps/ExampleApp-iOS/main.m:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | #import "ExampleAppDelegate.h"
4 |
5 | int main(int argc, char *argv[])
6 | {
7 | @autoreleasepool {
8 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([ExampleAppDelegate class]));
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/IOS/Example Apps/ExampleApp-OSX/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // ExampleApp-OSX
4 | //
5 | // Created by Marcus Westin on 6/8/13.
6 | // Copyright (c) 2013 Marcus Westin. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | int main(int argc, char *argv[])
12 | {
13 | return NSApplicationMain(argc, (const char **)argv);
14 | }
15 |
--------------------------------------------------------------------------------
/IOS/Example Apps/ExampleApp-OSX/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // ExampleApp-OSX
4 | //
5 | // Created by Marcus Westin on 6/8/13.
6 | // Copyright (c) 2013 Marcus Westin. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : NSObject
12 |
13 | @property (assign) IBOutlet NSWindow *window;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/IOS/Example Apps/ExampleApp-iOS/ExampleApp-iOS-Prefix.pch:
--------------------------------------------------------------------------------
1 | //
2 | // Prefix header for all source files of the 'ExampleApp' target in the 'ExampleApp' project
3 | //
4 |
5 | #import
6 |
7 | #ifndef __IPHONE_3_0
8 | #warning "This project uses features only available in iOS SDK 3.0 and later."
9 | #endif
10 |
11 | #ifdef __OBJC__
12 | #import
13 | #import
14 | #endif
15 |
--------------------------------------------------------------------------------
/Html/Example/multi_js/example.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | WebBridge Example
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/IOS/Example Apps/ExampleApp-iOS/ExampleAppDelegate.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import "WebViewJavascriptBridge.h"
3 |
4 | @interface ExampleAppDelegate : UIResponder
5 |
6 | @property (strong, nonatomic) UIWindow *window;
7 | @property (strong, nonatomic) WebViewJavascriptBridge *javascriptBridge;
8 |
9 | - (void)renderButtons:(UIWebView*)webView;
10 | - (void)loadExamplePage:(UIWebView*)webView;
11 |
12 | @end
13 |
--------------------------------------------------------------------------------
/Android/Example/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Html/Example/multi_js/user_server.js:
--------------------------------------------------------------------------------
1 | console.log("user_server.js called!");
2 | bridge.sinit(function(data,responseCallback){
3 | console.log("Received message from javascript: "+data);
4 | if(responseCallback){
5 | responseCallback("Right back atcha");
6 | }
7 | })
8 |
9 | function serverSend(){
10 | bridge.ssend("Well hello there");
11 | bridge.ssend("Give me a response, will you?", function(responseData) {
12 | console.log("Background got its response! "+responseData);
13 | })
14 | }
15 |
16 | setTimeout(serverSend,1000);
17 |
--------------------------------------------------------------------------------
/Chrome/Example/simple_extension/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "wanjuan",
3 | "version": "0.1",
4 | "description": "Wanjuan Reader",
5 | "permissions": ["tabs","storage"],
6 | "content_scripts": [
7 | {
8 | "matches": ["*://*/*"],
9 | "js": ["user_client.js","bridgeClientChrome.js"]
10 | }
11 | ],
12 | "background": {
13 | "scripts": ["bridgeServerChrome.js","user_server.js"]
14 | },
15 | "browser_action": {
16 | "default_title": "Wanjuan Reader",
17 | "default_icon": "clock.png"
18 | },
19 | "manifest_version": 2
20 | }
21 |
--------------------------------------------------------------------------------
/IOS/Example Apps/ExampleApp-OSX/en.lproj/Credits.rtf:
--------------------------------------------------------------------------------
1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;}
2 | {\colortbl;\red255\green255\blue255;}
3 | \paperw9840\paperh8400
4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural
5 |
6 | \f0\b\fs24 \cf0 Engineering:
7 | \b0 \
8 | Some people\
9 | \
10 |
11 | \b Human Interface Design:
12 | \b0 \
13 | Some other people\
14 | \
15 |
16 | \b Testing:
17 | \b0 \
18 | Hopefully not nobody\
19 | \
20 |
21 | \b Documentation:
22 | \b0 \
23 | Whoever\
24 | \
25 |
26 | \b With special thanks to:
27 | \b0 \
28 | Mom\
29 | }
30 |
--------------------------------------------------------------------------------
/Android/Example/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-18
15 |
--------------------------------------------------------------------------------
/Html/Example/multi_js/user_client.js:
--------------------------------------------------------------------------------
1 | console.log("user_client.js called!");
2 | document.addEventListener('WebViewJavascriptBridgeReady', function onBridgeReady(event) {
3 | var bridge = event.bridge
4 | bridge.init(function(message, responseCallback) {
5 | alert('Received message: ' + message)
6 | if (responseCallback) {
7 | responseCallback("Right back atcha")
8 | }
9 | })
10 | bridge.send('Hello from the javascript')
11 | bridge.send('Please respond to this', function responseCallback(responseData) {
12 | console.log("Javascript got its response", responseData)
13 | })
14 | }, false)
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-18
15 |
--------------------------------------------------------------------------------
/Html/js/bridgeServerHtml.js:
--------------------------------------------------------------------------------
1 | //server
2 | bridge={};
3 | (function(d){var e=d.c_||{};d.publish=function(a,b){for(var c=e[a],f=c?c.length:0;f--;)c[f].apply(d,b||[])};d.subscribe=function(a,b){e[a]||(e[a]=[]);e[a].push(b);return[a,b]};d.unsubscribe=function(a){for(var b=e[a[0]],a=a[1],c=b?b.length:0;c--;)b[c]===a&&b.splice(c,1)}})(bridge);
4 | bridge.sinit=function(register){
5 | //assert register is a function
6 | bridge.subscribe("MESSAGE2S",function(message,responseCallback){
7 | register(message,responseCallback);
8 | })
9 | }
10 | bridge.ssend=function(message,responseCallback){
11 | bridge.publish("MESSAGE2C",[message,responseCallback]);
12 | }
--------------------------------------------------------------------------------
/Android/Example/Example.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Chrome/Example/simple_extension/user_server.js:
--------------------------------------------------------------------------------
1 | console.log("user_server.js called!");
2 | bridge.sinit(function(data,responseCallback){
3 | console.log("Received message from javascript: "+data);
4 | responseCallback("Right back atcha");
5 | })
6 |
7 | function serverSend(){
8 | bridge.ssend("Well hello there");
9 | bridge.ssend("Give me a response, will you?", function(responseData) {
10 | console.log("Background got its response! "+responseData);
11 | })
12 | bridge.callHandler("showAlert","42",function(responseData){
13 | console.log("got alert response:"+responseData);
14 | });
15 | }
16 |
17 | bridge.registerHandler("handler1", function(data,responseCallback)
18 | { console.log("handler1:"+data);responseCallback("back from handerl1") });
19 |
20 |
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/Example.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Android/Example/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Android/Example/ant.properties:
--------------------------------------------------------------------------------
1 | # This file is used to override default values used by the Ant build system.
2 | #
3 | # This file must be checked into Version Control Systems, as it is
4 | # integral to the build system of your project.
5 |
6 | # This file is only used by the Ant script.
7 |
8 | # You can use this to override default values such as
9 | # 'source.dir' for the location of your java source folder and
10 | # 'out.dir' for the location of your output folder.
11 |
12 | # You can also use it define how the release builds are signed by declaring
13 | # the following properties:
14 | # 'key.store' for the location of your keystore and
15 | # 'key.alias' for the name of the key to use.
16 | # The password will be asked during the build when you use the 'release' target.
17 |
18 |
--------------------------------------------------------------------------------
/Html/js/bridgeClientHtml.js:
--------------------------------------------------------------------------------
1 | //client
2 | (function(bridge){
3 | //common
4 | function assert(condition, message) {
5 | if (!condition) {
6 | throw message || "Assertion failed";
7 | }
8 | }
9 |
10 | bridge.init=function(register){
11 | //assert register is a function
12 | assert(register instanceof Function,"init() should has a function as parameter");
13 | bridge.subscribe("MESSAGE2C",function(message,responseCallback){
14 | register(message,responseCallback);
15 | })
16 | }
17 | bridge.send=function(message,responseCallback){
18 | bridge.publish("MESSAGE2S",[message,responseCallback]);
19 | }
20 | //dispatch event
21 | var event=new CustomEvent('WebViewJavascriptBridgeReady')
22 | event.bridge=bridge;
23 | document.dispatchEvent(event);
24 | })(bridge)
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/ant.properties:
--------------------------------------------------------------------------------
1 | # This file is used to override default values used by the Ant build system.
2 | #
3 | # This file must be checked into Version Control Systems, as it is
4 | # integral to the build system of your project.
5 |
6 | # This file is only used by the Ant script.
7 |
8 | # You can use this to override default values such as
9 | # 'source.dir' for the location of your java source folder and
10 | # 'out.dir' for the location of your output folder.
11 |
12 | # You can also use it define how the release builds are signed by declaring
13 | # the following properties:
14 | # 'key.store' for the location of your keystore and
15 | # 'key.alias' for the name of the key to use.
16 | # The password will be asked during the build when you use the 'release' target.
17 |
18 |
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Android/Example/WebViewJavascriptBridgeExample.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/Android/Example/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/WebViewJavascriptBridgeExample.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/Html/Example/multi_js/bridgeServerHtml.js:
--------------------------------------------------------------------------------
1 | //server
2 | bridge={};
3 | (function(d){var e=d.c_||{};d.publish=function(a,b){for(var c=e[a],f=c?c.length:0;f--;)c[f].apply(d,b||[])};d.subscribe=function(a,b){e[a]||(e[a]=[]);e[a].push(b);return[a,b]};d.unsubscribe=function(a){for(var b=e[a[0]],a=a[1],c=b?b.length:0;c--;)b[c]===a&&b.splice(c,1)}})(bridge);
4 | bridge.sinit=function(register){
5 | //assert register is a function
6 | bridge.subscribe("MESSAGE2S",function(message,responseCallback){
7 | register(message,responseCallback);
8 | })
9 | }
10 | bridge.ssend=function(message,responseCallback){
11 | bridge.publish("MESSAGE2C",[message,responseCallback]);
12 | }
13 | bridge.scallHandler=function(handlerName, data, responseCallback) {
14 | bridge.publish("[c]"+handlerName,[data, responseCallback]);
15 | }
16 | bridge.sregisterHandler=function(handlerName, handler) {
17 | bridge.subscribe("[s]"+handlerName,handler);
18 | }
--------------------------------------------------------------------------------
/IOS/WebViewJavascriptBridge.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = 'WebViewJavascriptBridge'
3 | s.version = '4.0.1'
4 | s.summary = 'An iOS/OSX bridge for sending messages between Obj-C and JavaScript in UIWebViews/WebViews.'
5 | s.homepage = 'http://github.com/marcuswestin/WebViewJavascriptBridge'
6 | s.license = { :type => 'MIT', :file => 'LICENSE' }
7 | s.author = { 'marcuswestin' => 'marcus.westin@gmail.com' }
8 | s.requires_arc = true
9 | s.source = { :git => 'https://github.com/marcuswestin/WebViewJavascriptBridge.git' }
10 | s.ios.platform = :ios, '5.0'
11 | s.osx.platform = :osx
12 | s.ios.source_files = 'WebViewJavascriptBridge/*.{h,m}'
13 | s.osx.source_files = 'WebViewJavascriptBridge/*.{h,m}'
14 | s.resource = 'WebViewJavascriptBridgeAbstract/WebViewJavascriptBridge.js.txt'
15 | s.ios.framework = 'UIKit'
16 | s.osx.framework = 'WebKit'
17 | end
18 |
--------------------------------------------------------------------------------
/Chrome/Example/simple_extension/user_client.js:
--------------------------------------------------------------------------------
1 | console.log("user_client.js called!");
2 | document.addEventListener('WebViewJavascriptBridgeReady', function onBridgeReady(event) {
3 | var bridge = event.bridge
4 | bridge.init(function(message, responseCallback) {
5 | alert('Received message: ' + message)
6 | if (responseCallback) {
7 | responseCallback("Right back atcha")
8 | }
9 | })
10 | bridge.send('Hello from the javascript')
11 | bridge.send('Please respond to this', function responseCallback(responseData) {
12 | console.log("Javascript got its response", responseData)
13 | })
14 | bridge.registerHandler("showAlert", function(data,responseCallback)
15 | { console.log("alert:"+data);responseCallback("response from alert") });
16 | bridge.callHandler("handler1","gift for handler1",function(responseData){
17 | console.log("got handler1 response:"+responseData);
18 | });
19 | }, false)
--------------------------------------------------------------------------------
/Html/Example/multi_js/bridgeClientHtml.js:
--------------------------------------------------------------------------------
1 | //client
2 | (function(bridge){
3 | //common
4 | function assert(condition, message) {
5 | if (!condition) {
6 | throw message || "Assertion failed";
7 | }
8 | }
9 |
10 | bridge.init=function(register){
11 | //assert register is a function
12 | assert(register instanceof Function,"init() should has a function as parameter");
13 | bridge.subscribe("MESSAGE2C",function(message,responseCallback){
14 | register(message,responseCallback);
15 | })
16 | }
17 | bridge.send=function(message,responseCallback){
18 | bridge.publish("MESSAGE2S",[message,responseCallback]);
19 | }
20 | bridge.callHandler=function(handlerName, data, responseCallback) {
21 | bridge.publish("[s]"+handlerName,[data, responseCallback]);
22 | }
23 | bridge.registerHandler=function(handlerName, handler) {
24 | bridge.subscribe("[c]"+handlerName,handler);
25 | }
26 | //dispatch event
27 | var event=new CustomEvent('WebViewJavascriptBridgeReady')
28 | event.bridge=bridge;
29 | document.dispatchEvent(event);
30 | })(bridge)
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/assets/map/poi.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "FeatureCollection",
3 | "features": [
4 | {
5 | "type": "Feature",
6 | "geometry": {
7 | "type": "Point",
8 | "coordinates": [
9 | 0.200909516011011,
10 | 0.037327561069884
11 | ]
12 | },
13 | "properties": {
14 | "id": "2",
15 | "title": "磁悬浮列车"
16 | }
17 | },
18 | {
19 | "type": "Feature",
20 | "geometry": {
21 | "type": "Point",
22 | "coordinates": [
23 | -0.026763873271805,
24 | 0.230131436760048
25 | ]
26 | },
27 | "properties": {
28 | "id": "1",
29 | "title": "机器人世界"
30 | }
31 | },
32 | {
33 | "type": "Feature",
34 | "geometry": {
35 | "type": "Point",
36 | "coordinates": [
37 | -0.189827246677065,
38 | -0.080610295914104
39 | ]
40 | },
41 | "properties": {
42 | "id": "3",
43 | "title": "火山"
44 | }
45 | }
46 | ]
47 | }
--------------------------------------------------------------------------------
/Android/Example/res/raw/user_client.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
27 |
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/res/raw/user_client.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
27 |
--------------------------------------------------------------------------------
/IOS/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2011-2013 Marcus Westin, Antoine Lagadec
2 |
3 | Permission is hereby granted, free of charge, to any person
4 | obtaining a copy of this software and associated documentation
5 | files (the "Software"), to deal in the Software without
6 | restriction, including without limitation the rights to use,
7 | copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the
9 | Software is furnished to do so, subject to the following
10 | conditions:
11 |
12 | The above copyright notice and this permission notice shall be
13 | included in all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/Chrome/js/bridgeClientChrome.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | //common
3 | function assert(condition, message) {
4 | if (!condition) {
5 | throw message || "Assertion failed";
6 | }
7 | }
8 | //const
9 | var MSG_REGISTER_WANJUAN_INTERFACE="MSG_REGISTER_WANJUAN_INTERFACE";
10 | //bridge
11 | var bridge = {};
12 | bridge.send=function(msg,responseCallback){
13 | assert(!responseCallback || responseCallback instanceof Function,"responseCallback should be function");
14 | if(responseCallback){
15 | chrome.extension.sendMessage(msg,responseCallback)
16 | }else{
17 | chrome.extension.sendMessage(msg)
18 | }
19 | };
20 | bridge.init=function(onMessageCallback){
21 | var adapter=onMessageCallbackAdapter(onMessageCallback);
22 | chrome.extension.onMessage.addListener(adapter);
23 | //register for accept message
24 | chrome.extension.sendMessage(MSG_REGISTER_WANJUAN_INTERFACE);
25 | }
26 | function onMessageCallbackAdapter(onMessageCallback){
27 | var adapter=function(message, sender, sendResponse){
28 | onMessageCallback(message,sendResponse);
29 | }
30 | return adapter;
31 | }
32 | //dispatch event
33 | var event = new CustomEvent('WebViewJavascriptBridgeReady');
34 | event.bridge=bridge;
35 | document.dispatchEvent(event);
36 | })()
37 |
--------------------------------------------------------------------------------
/IOS/Example Apps/ExampleApp-OSX/ExampleApp-OSX-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | WebViewJavascriptBridge.${PRODUCT_NAME:rfc1034identifier}
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | ${PRODUCT_NAME}
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | LSMinimumSystemVersion
26 | ${MACOSX_DEPLOYMENT_TARGET}
27 | NSHumanReadableCopyright
28 | Copyright © 2013 Marcus Westin. All rights reserved.
29 | NSMainNibFile
30 | MainMenu
31 | NSPrincipalClass
32 | NSApplication
33 |
34 |
35 |
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/assets/map/mapbox/images/render.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e -u
3 |
4 | # Color variations to be generated
5 | COLORS="000000 ffffff"
6 |
7 | # Check for required commands
8 | COMMANDS="inkscape pngquant convert"
9 | for COMMAND in $COMMANDS; do
10 | if [ -z $(which $COMMAND) ]; then
11 | echo "Command '$COMMAND' not found."
12 | exit 1
13 | fi
14 | done
15 |
16 | BASE="$(dirname $0)"
17 | TMP="$(mktemp /tmp/tmp.XXXXXXXX)"
18 |
19 | # Render icons.svg variations.
20 | inkscape \
21 | --export-dpi=90 \
22 | --export-png=$TMP.png \
23 | $BASE/icons.svg > /dev/null
24 |
25 | inkscape \
26 | --export-dpi=180 \
27 | --export-png=$TMP@2x.png \
28 | $BASE/icons.svg > /dev/null
29 |
30 | echo ""
31 |
32 | for COLOR in $COLORS; do
33 | convert $TMP.png -fill "#$COLOR" -colorize 100,100,100,0 - | pngquant 32 > $BASE/icons-$COLOR.png
34 | echo -e "\033[01;33m✔ saved $BASE/icons-$COLOR.png"
35 | convert $TMP@2x.png -fill "#$COLOR" -colorize 100,100,100,0 - | pngquant 32 > $BASE/icons-$COLOR@2x.png
36 | echo -e "\033[01;33m✔ saved $BASE/icons-$COLOR@2x.png"
37 | done
38 |
39 | rm -f $TMP $TMP.png $TMP@2x.png
40 |
41 | echo -e "\n\033[00;33mCOMPLETE! Don't forget to update the \`background-size\` property if the sprite size changed\033[0m"
42 |
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
13 |
14 |
19 |
20 |
25 |
26 |
31 |
32 |
33 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Chrome/js/bridgeServerChrome.js:
--------------------------------------------------------------------------------
1 | //common
2 | function assert(condition, message) {
3 | if (!condition) {
4 | throw message || "Assertion failed";
5 | }
6 | }
7 | //const
8 | var MSG_REGISTER_WANJUAN_INTERFACE="MSG_REGISTER_WANJUAN_INTERFACE";
9 |
10 | //bridge
11 | var bridge = {};
12 | bridge.tabIds={};
13 | bridge.ssend=function(msg,responseCallback){
14 | assert(!responseCallback || responseCallback instanceof Function,"responseCallback should be function");
15 | //broadcast msg
16 | for(var tabId in bridge.tabIds){
17 | chrome.tabs.sendMessage(bridge.tabIds[tabId], msg, responseCallback);
18 | }
19 | }
20 | bridge.sinit=function(onMessageCallback){
21 | var adapter=onMessageCallbackAdapter(onMessageCallback);
22 | chrome.extension.onMessage.addListener(adapter);
23 | }
24 | function onMessageCallbackAdapter(onMessageCallback){
25 | var adapter= function(message, sender, sendResponse){
26 | onMessageCallback(message,sendResponse);
27 | };
28 | return adapter;
29 | }
30 | //register
31 | var register=function (message, sender, sendResponse){
32 | if(MSG_REGISTER_WANJUAN_INTERFACE==message && !bridge.tabIds[sender.tab]){
33 | bridge.tabIds[sender.tab.id]=sender.tab.id;
34 | console.log("regiseter:"+sender.tab.id);
35 | }
36 | }
37 | chrome.extension.onMessage.addListener(register);
38 |
39 |
--------------------------------------------------------------------------------
/IOS/Example Apps/ExampleApp-iOS/ExampleApp-iOS-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ${PRODUCT_NAME}
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleIdentifier
12 | com.example.${PRODUCT_NAME:rfc1034identifier}
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | ${PRODUCT_NAME}
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1.0
25 | LSRequiresIPhoneOS
26 |
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/IOS/WebViewJavascriptBridge/WebViewJavascriptBridge.h:
--------------------------------------------------------------------------------
1 | //
2 | // WebViewJavascriptBridge.h
3 | // ExampleApp-iOS
4 | //
5 | // Created by Marcus Westin on 6/14/13.
6 | // Copyright (c) 2013 Marcus Westin. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #define kMessageSeparator @"__WVJB_MESSAGE_SEPERATOR__"
12 | #define kCustomProtocolScheme @"wvjbscheme"
13 | #define kQueueHasMessage @"__WVJB_QUEUE_MESSAGE__"
14 |
15 | #if defined __MAC_OS_X_VERSION_MAX_ALLOWED
16 | #import
17 | #define WVJB_PLATFORM_OSX
18 | #define WVJB_WEBVIEW_TYPE WebView
19 | #define WVJB_WEBVIEW_DELEGATE_TYPE NSObject
20 | #elif defined __IPHONE_OS_VERSION_MAX_ALLOWED
21 | #define WVJB_PLATFORM_IOS
22 | #define WVJB_WEBVIEW_TYPE UIWebView
23 | #define WVJB_WEBVIEW_DELEGATE_TYPE NSObject
24 | #endif
25 |
26 | typedef void (^WVJBResponseCallback)(id responseData);
27 | typedef void (^WVJBHandler)(id data, WVJBResponseCallback responseCallback);
28 |
29 | @interface WebViewJavascriptBridge : WVJB_WEBVIEW_DELEGATE_TYPE
30 |
31 | + (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView handler:(WVJBHandler)handler;
32 | + (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE*)webViewDelegate handler:(WVJBHandler)handler;
33 | + (void)enableLogging;
34 |
35 | - (void)send:(id)message;
36 | - (void)send:(id)message responseCallback:(WVJBResponseCallback)responseCallback;
37 | - (void)registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler;
38 | - (void)callHandler:(NSString*)handlerName;
39 | - (void)callHandler:(NSString*)handlerName data:(id)data;
40 | - (void)callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback;
41 | - (void)reset;
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/Android/Example/design/iosdesign.txt:
--------------------------------------------------------------------------------
1 | function _dispatchMessageFromObjC(messageJSON) {
2 | setTimeout(function _timeoutDispatchMessageFromObjC() {
3 | var message = JSON.parse(messageJSON)
4 | var messageHandler
5 |
6 | if (message.responseId) {
7 | var responseCallback = responseCallbacks[message.responseId]
8 | if (!responseCallback) { return; }
9 | responseCallback(message.responseData)
10 | delete responseCallbacks[message.responseId]
11 | } else {
12 | var responseCallback
13 | if (message.callbackId) {
14 | var callbackResponseId = message.callbackId
15 | responseCallback = function(responseData) {
16 | _doSend({ responseId:callbackResponseId, responseData:responseData })
17 | }
18 | }
19 |
20 | var handler = WebViewJavascriptBridge._messageHandler
21 | if (message.handlerName) {
22 | handler = messageHandlers[message.handlerName]
23 | }
24 |
25 | try {
26 | handler(message.data, responseCallback)
27 | } catch(exception) {
28 | if (typeof console != 'undefined') {
29 | console.log("WebViewJavascriptBridge: WARNING: javascript handler threw.", message, exception)
30 | }
31 | }
32 | }
33 | })
34 | }
35 |
36 | receiveMessageQueue 在调用init之前保存消息。从而init之前的message也可以处理
37 | objc call js
38 | NSString* javascriptCommand = [NSString stringWithFormat:@"WebViewJavascriptBridge._handleMessageFromObjC('%@');", messageJSON];
39 | js call objc,让objc去取一个消息队列,分割后为多个message,再分别处理每个消息队列
40 | NSString *messageQueueString = [_webView stringByEvaluatingJavaScriptFromString:@"WebViewJavascriptBridge._fetchQueue();"];
41 |
42 | NSArray* messages = [messageQueueString componentsSeparatedByString:kMessageSeparator];
43 | for (NSString *messageJSON in messages) {
44 | =======
45 | js:
46 | 发送或接受都封装为json message , 双方的callback打包为message发送
47 | 发送:
48 | 1)放在队列里
49 | 2)请求IOS来取队列
50 |
51 | 接收:
52 | 1)初始化之前,放在队列里
53 | 2)初始化之中,分发队列里的 message
54 | 3)初始化之后,直接分发
55 |
56 | java:
57 | 发送:
58 | sendMessage
59 | 接受:
60 | 收到刷新请求后取队列,解析分发
61 |
62 |
63 | ,
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/design/iosdesign.txt:
--------------------------------------------------------------------------------
1 | function _dispatchMessageFromObjC(messageJSON) {
2 | setTimeout(function _timeoutDispatchMessageFromObjC() {
3 | var message = JSON.parse(messageJSON)
4 | var messageHandler
5 |
6 | if (message.responseId) {
7 | var responseCallback = responseCallbacks[message.responseId]
8 | if (!responseCallback) { return; }
9 | responseCallback(message.responseData)
10 | delete responseCallbacks[message.responseId]
11 | } else {
12 | var responseCallback
13 | if (message.callbackId) {
14 | var callbackResponseId = message.callbackId
15 | responseCallback = function(responseData) {
16 | _doSend({ responseId:callbackResponseId, responseData:responseData })
17 | }
18 | }
19 |
20 | var handler = WebViewJavascriptBridge._messageHandler
21 | if (message.handlerName) {
22 | handler = messageHandlers[message.handlerName]
23 | }
24 |
25 | try {
26 | handler(message.data, responseCallback)
27 | } catch(exception) {
28 | if (typeof console != 'undefined') {
29 | console.log("WebViewJavascriptBridge: WARNING: javascript handler threw.", message, exception)
30 | }
31 | }
32 | }
33 | })
34 | }
35 |
36 | receiveMessageQueue 在调用init之前保存消息。从而init之前的message也可以处理
37 | objc call js
38 | NSString* javascriptCommand = [NSString stringWithFormat:@"WebViewJavascriptBridge._handleMessageFromObjC('%@');", messageJSON];
39 | js call objc,让objc去取一个消息队列,分割后为多个message,再分别处理每个消息队列
40 | NSString *messageQueueString = [_webView stringByEvaluatingJavaScriptFromString:@"WebViewJavascriptBridge._fetchQueue();"];
41 |
42 | NSArray* messages = [messageQueueString componentsSeparatedByString:kMessageSeparator];
43 | for (NSString *messageJSON in messages) {
44 | =======
45 | js:
46 | 发送或接受都封装为json message , 双方的callback打包为message发送
47 | 发送:
48 | 1)放在队列里
49 | 2)请求IOS来取队列
50 |
51 | 接收:
52 | 1)初始化之前,放在队列里
53 | 2)初始化之中,分发队列里的 message
54 | 3)初始化之后,直接分发
55 |
56 | java:
57 | 发送:
58 | sendMessage
59 | 接受:
60 | 收到刷新请求后取队列,解析分发
61 |
62 |
63 | ,
--------------------------------------------------------------------------------
/Chrome/Example/simple_extension/bridgeClientChrome.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | var messageHandlers = {};
3 | var _messageHandler;
4 | //common
5 | function assert(condition, message) {
6 | if (!condition) {
7 | throw message || "Assertion failed";
8 | }
9 | }
10 | //const
11 | var MSG_REGISTER_WANJUAN_INTERFACE="MSG_REGISTER_WANJUAN_INTERFACE";
12 | //bridge
13 | var bridge = {};
14 |
15 | chrome.runtime.onMessage.addListener(
16 | function(message, sender, sendResponse){
17 | _dispatchMessage(message,sendResponse);
18 | });
19 |
20 | bridge.send=function(data,responseCallback){
21 | _send({"data":data},responseCallback);
22 | }
23 | function _send(msg,responseCallback){
24 | assert(!responseCallback || responseCallback instanceof Function,"responseCallback should be function");
25 | if(responseCallback){
26 | chrome.runtime.sendMessage(msg,responseCallback)
27 | }else{
28 | chrome.runtime.sendMessage(msg)
29 | }
30 | }
31 | bridge.init=function(onMessageCallback){
32 | _messageHandler=onMessageCallback;
33 | //register for accept message
34 | chrome.runtime.sendMessage(MSG_REGISTER_WANJUAN_INTERFACE);
35 | }
36 |
37 | bridge.registerHandler=function(handlerName, handler) {
38 | messageHandlers[handlerName] = handler
39 | }
40 |
41 | bridge.callHandler=function(handlerName, data, responseCallback) {
42 | _send({ handlerName:handlerName, data:data }, responseCallback)
43 | }
44 |
45 | function _dispatchMessage(message, responseCallback) {
46 | var handler = _messageHandler;
47 | if (message.handlerName) {
48 | handler = messageHandlers[message.handlerName]
49 | }
50 | try {
51 | handler(message.data, responseCallback)
52 | } catch(exception) {
53 | if (typeof console != 'undefined' && JSON.stringify(exception)!="{}") {
54 | console.log("WebViewJavascriptBridge: WARNING: javascript handler threw.", message, exception)
55 | }
56 | }
57 | }
58 | //dispatch event
59 | var event = new CustomEvent('WebViewJavascriptBridgeReady');
60 | event.bridge=bridge;
61 | document.dispatchEvent(event);
62 | })()
63 |
--------------------------------------------------------------------------------
/IOS/Changelog:
--------------------------------------------------------------------------------
1 | v4.0.1
2 | + Fix detection of arc_weak support
3 |
4 | v4.0.0
5 | + Consolidate platform-specific code into a single WebViewJavascriptBridge.m/h using macros (57ee322a4c5310eadd28b28f4d8522cd54123301)
6 | + Bugfix: Don't make navigation decisions for webviews we don't control (254ea00267f8c1e03727885f4e1e0fd5f5c78be8)
7 |
8 | v3.1.0
9 | + Dont inject the WVJB bridge until all requests have finished loading (61b853)
10 | + Add podspec file (818d49cfc)
11 | + Memory leaks fixed (b06988f1, 20ce1b0b)
12 | + New major contributor @peyton!
13 |
14 | v3.0.0
15 | + OSX Support
16 | + New major contributor @oakho!
17 |
18 | v2.1.2
19 | + Copy handler and response blocks
20 |
21 | v2.1.1
22 | + Handle edge cases gracefully (e.g. don't crash on unknown command or unexpected response)
23 |
24 | v2.1.0
25 | + Remove WVJBResponse object and the notion of responding with an error. See 4ab41bb4d7.
26 |
27 | v2.0.0
28 | + Messages are objects instead of strings. Supports NSDictionary*/Objects, NSArray*/Arrays, NSNumber*/Number & NSString*/String.
29 | + Messages are encoded with NSJSONSerialization. Optional fallback to JSONKit for iOS 4 support.
30 | + Messages can expect responses. A message received with an expected response is accompanied by a WVJBResponse* object.
31 | + Handlers can be registered by name, and called with data and an optional expected response.
32 | + Responses expect either an error or data (`-(void)respond:(id)data`, -(void)respondWithError:(id)error)
33 |
34 | v0.0.1
35 | + ObjC: A WebViewJavascriptBridge class (a UIWebViewDelegate) that enables message passing to and from the JS
36 | + ObjC: A protocol called WebViewJavascriptBridgeDelegate that lets you handle messages received from the JS
37 | + JS: Event when the bridge is ready - document.addEventListener('WebViewJavascriptBridgeReady', function() {}, false)
38 | + JS: Ability to set your message handler - WebViewJavascriptBridge.setMessageHandler(function() {})
39 | + JS: Function to send messages - WebViewJavascriptBridge.sendMessage('a message');
40 | + All messages are strings. Use JSON in your js and e.g. JSONKit in iOS to send structured messages
41 |
--------------------------------------------------------------------------------
/Chrome/Example/simple_extension/bridgeServerChrome.js:
--------------------------------------------------------------------------------
1 | //common
2 | function assert(condition, message) {
3 | if (!condition) {
4 | throw message || "Assertion failed";
5 | }
6 | }
7 | //const
8 | var MSG_REGISTER_WANJUAN_INTERFACE="MSG_REGISTER_WANJUAN_INTERFACE";
9 |
10 | //bridge
11 | var bridge = {};
12 | bridge.tabIds={};
13 | var messageHandlers = {};
14 | var _messageHandler;
15 |
16 | chrome.runtime.onMessage.addListener(
17 | function(message, sender, sendResponse){
18 | if(register(message,sender,sendResponse))return;
19 | _dispatchMessage(message,sendResponse);
20 | });
21 |
22 | bridge.ssend=function(data,responseCallback){
23 | _send({"data":data},responseCallback);
24 | }
25 | function _send(msg,responseCallback){
26 | assert(!responseCallback || responseCallback instanceof Function,"responseCallback should be function");
27 | //broadcast msg
28 | for(var tabId in bridge.tabIds){
29 | chrome.tabs.sendMessage(bridge.tabIds[tabId], msg, responseCallback);
30 | }
31 | }
32 |
33 | bridge.sinit=function(onMessageCallback){
34 | _messageHandler=onMessageCallback;
35 | }
36 | bridge.registerHandler=function(handlerName, handler) {
37 | messageHandlers[handlerName] = handler
38 | }
39 |
40 | bridge.callHandler=function(handlerName, data, responseCallback) {
41 | _send({ handlerName:handlerName, data:data }, responseCallback)
42 | }
43 |
44 | function _dispatchMessage(message, responseCallback) {
45 | var handler = _messageHandler;
46 | if (message.handlerName) {
47 | handler = messageHandlers[message.handlerName]
48 | }
49 | try {
50 | handler(message.data, responseCallback)
51 | } catch(exception) {
52 | if (typeof console != 'undefined') {
53 | console.log("WebViewJavascriptBridge: WARNING: javascript handler threw.", message, exception)
54 | }
55 | }
56 | }
57 | //register
58 | var register=function (message, sender, sendResponse){
59 | if(MSG_REGISTER_WANJUAN_INTERFACE==message && !bridge.tabIds[sender.tab]){
60 | bridge.tabIds[sender.tab.id]=sender.tab.id;
61 | console.log("regiseter:"+sender.tab.id);
62 | return true;
63 | }
64 | }
65 | //chrome.extension.onMessage.addListener(register);
66 |
67 |
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/assets/map/area.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "FeatureCollection",
3 | "features": [
4 | {
5 | "type": "Feature",
6 | "geometry": {
7 | "type": "MultiPolygon",
8 | "coordinates": [
9 | [
10 | [
11 | [
12 | 0.103481714290887,
13 | -0.06317584718524
14 | ],
15 | [
16 | 0.122967274634912,
17 | -0.040613619418474
18 | ],
19 | [
20 | 0.153733948862319,
21 | -0.051894733301857
22 | ],
23 | [
24 | 0.160912839515381,
25 | -0.073431405261042
26 | ],
27 | [
28 | 0.152708393054739,
29 | -0.100095856258129
30 | ],
31 | [
32 | 0.127069497865233,
33 | -0.10419807948845
34 | ],
35 | [
36 | 0.104507270098467,
37 | -0.086763630759585
38 | ],
39 | [
40 | 0.103481714290887,
41 | -0.06317584718524
42 | ]
43 | ]
44 | ]
45 | ]
46 | },
47 | "properties": {
48 | "id": "2",
49 | "name": "测试2区"
50 | }
51 | },
52 | {
53 | "type": "Feature",
54 | "geometry": {
55 | "type": "MultiPolygon",
56 | "coordinates": [
57 | [
58 | [
59 | [
60 | -0.220593920904472,
61 | -0.068303626223141
62 | ],
63 | [
64 | -0.178546132793682,
65 | -0.052920289109437
66 | ],
67 | [
68 | -0.122140563376768,
69 | -0.126760307255215
70 | ],
71 | [
72 | -0.168290574717879,
73 | -0.164705872135684
74 | ],
75 | [
76 | -0.220593920904472,
77 | -0.068303626223141
78 | ]
79 | ]
80 | ]
81 | ]
82 | },
83 | "properties": {
84 | "id": "1",
85 | "name": "测试区1"
86 | }
87 | }
88 | ]
89 | }
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/assets/map/map.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 江苏科技馆
7 |
8 |
9 |
18 |
19 |
20 |
21 |
26 |
27 |
28 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/Android/Example/src/com/example/WebViewJavascriptBridgeExample/MyActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.WebViewJavascriptBridgeExample;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 | import android.util.Log;
6 | import android.webkit.WebView;
7 | import com.fangjian.WebViewJavascriptBridge;
8 |
9 | import java.io.InputStream;
10 |
11 | public class MyActivity extends Activity {
12 | private WebView webView;
13 | private WebViewJavascriptBridge bridge;
14 |
15 | /**
16 | * Called when the activity is first created.
17 | */
18 | @Override
19 | public void onCreate(Bundle savedInstanceState) {
20 | super.onCreate(savedInstanceState);
21 | setContentView(R.layout.main);
22 | webView=(WebView) this.findViewById(R.id.webView);
23 | bridge=
24 | new WebViewJavascriptBridge(this,webView,new UserServerHandler()) ;
25 | loadUserClient();
26 | registerHandle();
27 | }
28 |
29 | private void loadUserClient(){
30 | InputStream is=getResources().openRawResource(R.raw.user_client);
31 | String user_client_html=WebViewJavascriptBridge.convertStreamToString(is);
32 | webView.loadData(user_client_html,"text/html","UTF-8");
33 | }
34 |
35 | class UserServerHandler implements WebViewJavascriptBridge.WVJBHandler{
36 | @Override
37 | public void handle(String data, WebViewJavascriptBridge.WVJBResponseCallback jsCallback) {
38 | Log.d("test","Received message from javascript: "+ data);
39 | if (null !=jsCallback) {
40 | jsCallback.callback("Java said:Right back atcha");
41 | }
42 | bridge.send("I expect a response!",new WebViewJavascriptBridge.WVJBResponseCallback() {
43 | @Override
44 | public void callback(String responseData) {
45 | Log.d("test","Got response! "+responseData);
46 | }
47 | });
48 | bridge.send("Hi");
49 | }
50 | }
51 |
52 | private void registerHandle(){
53 | bridge.registerHandler("handler1",new WebViewJavascriptBridge.WVJBHandler() {
54 | @Override
55 | public void handle(String data, WebViewJavascriptBridge.WVJBResponseCallback jsCallback) {
56 | Log.d("test","handler1 got:"+data);
57 | if(null!=jsCallback){
58 | jsCallback.callback("handler1 answer");
59 | }
60 | bridge.callHandler("showAlert","42");
61 | }
62 | });
63 | }
64 |
65 |
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/IOS/Example Apps/ExampleApp.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 | WebViewJavascriptBridge Demo
11 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/Android/Example/design/design.txt:
--------------------------------------------------------------------------------
1 | Java init:
2 | WebViewJavascriptBridge bridge = new WebViewJavascriptBridge(Webview webview,WVJBHandler handler);
3 |
4 | Interface WVJBHandler {
5 | public void handle(String data,WVJBResponseCallback jsCallback);
6 | }
7 |
8 | Interface WVJBResponseCallback{
9 | public void callback(String data);
10 | }
11 |
12 | class WVJBResponseCallbackImpl{
13 | WVJBResponseCallbackImpl(long callbackId){};
14 | public void callback(String data){
15 | _jscall(callbackId,data); //call js function with callback id
16 | }
17 | }
18 |
19 | Js =>Java
20 | send(data,jsCallback)->_csend(data,jsCallbackId){
21 | _doSend({ data:data }, responseCallback)
22 | } ->responseCallback=new WVJBResponseCallbackImpl(jsCallbackId)
23 | -> handler.handle(data,WVJBResponseCallback responseCallback) {
24 | System.out.println(data);
25 | responseCallback.callback("something");
26 | }
27 |
28 | [JAVA]registerHandler(String handleName, WVJBHandler handler)
29 | [JS]function callHandler(handlerName, data, responseCallback) {
30 | _doSend({ handlerName:handlerName, data:data }, responseCallback) //call java handle with js callbackid
31 | }->handler=getHandler(handlerName);
32 |
33 | -----------------------------------
34 | JS INIT;
35 | bridge.init(messageHandler)
36 | messageHandler=function(message, responseCallback) {}
37 | Java=>js
38 | send(data,javaCallback)->_ssend(data,javaCallbackId) {
39 | responseCallback=getJavaResponseCallback(javaCallbackId);
40 | handle(data,responseCallback)
41 | }
42 |
43 | function getJavaResponseCallback( javaCallbackId){
44 | var javaCallback=function( data){
45 | _javacall( javaCallbackId,data);
46 | }
47 | return javaCallback;
48 | }
49 |
50 | ========
51 | js:
52 | 发送都封装为json message _doSend({ handlerName:handlerName, data:data }, responseCallback)
53 |
54 | 发送:
55 | 1)直接发送
56 |
57 |
58 |
59 | java:
60 | 1) 打包为json发送 WebViewJavascriptBridge._handleMessageFromJava(messageJSON);[js]
61 | 2) 解析分发:
62 | var responseCallback = responseCallbacks[message.responseId]
63 | responseCallback(message.responseData)
64 | f (message.callbackId) {
65 | var callbackResponseId = message.callbackId
66 | responseCallback = function(responseData) {
67 | _doSend({ responseId:callbackResponseId, responseData:responseData })
68 | }
69 | }
70 | var handler = WebViewJavascriptBridge._messageHandler
71 | if (message.handlerName) {
72 | handler = messageHandlers[message.handlerName]
73 | }
74 |
75 | try {
76 | handler(message.data, responseCallback)
77 |
78 |
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/design/design.txt:
--------------------------------------------------------------------------------
1 | Java init:
2 | WebViewJavascriptBridge bridge = new WebViewJavascriptBridge(Webview webview,WVJBHandler handler);
3 |
4 | Interface WVJBHandler {
5 | public void handle(String data,WVJBResponseCallback jsCallback);
6 | }
7 |
8 | Interface WVJBResponseCallback{
9 | public void callback(String data);
10 | }
11 |
12 | class WVJBResponseCallbackImpl{
13 | WVJBResponseCallbackImpl(long callbackId){};
14 | public void callback(String data){
15 | _jscall(callbackId,data); //call js function with callback id
16 | }
17 | }
18 |
19 | Js =>Java
20 | send(data,jsCallback)->_csend(data,jsCallbackId){
21 | _doSend({ data:data }, responseCallback)
22 | } ->responseCallback=new WVJBResponseCallbackImpl(jsCallbackId)
23 | -> handler.handle(data,WVJBResponseCallback responseCallback) {
24 | System.out.println(data);
25 | responseCallback.callback("something");
26 | }
27 |
28 | [JAVA]registerHandler(String handleName, WVJBHandler handler)
29 | [JS]function callHandler(handlerName, data, responseCallback) {
30 | _doSend({ handlerName:handlerName, data:data }, responseCallback) //call java handle with js callbackid
31 | }->handler=getHandler(handlerName);
32 |
33 | -----------------------------------
34 | JS INIT;
35 | bridge.init(messageHandler)
36 | messageHandler=function(message, responseCallback) {}
37 | Java=>js
38 | send(data,javaCallback)->_ssend(data,javaCallbackId) {
39 | responseCallback=getJavaResponseCallback(javaCallbackId);
40 | handle(data,responseCallback)
41 | }
42 |
43 | function getJavaResponseCallback( javaCallbackId){
44 | var javaCallback=function( data){
45 | _javacall( javaCallbackId,data);
46 | }
47 | return javaCallback;
48 | }
49 |
50 | ========
51 | js:
52 | 发送都封装为json message _doSend({ handlerName:handlerName, data:data }, responseCallback)
53 |
54 | 发送:
55 | 1)直接发送
56 |
57 |
58 |
59 | java:
60 | 1) 打包为json发送 WebViewJavascriptBridge._handleMessageFromJava(messageJSON);[js]
61 | 2) 解析分发:
62 | var responseCallback = responseCallbacks[message.responseId]
63 | responseCallback(message.responseData)
64 | f (message.callbackId) {
65 | var callbackResponseId = message.callbackId
66 | responseCallback = function(responseData) {
67 | _doSend({ responseId:callbackResponseId, responseData:responseData })
68 | }
69 | }
70 | var handler = WebViewJavascriptBridge._messageHandler
71 | if (message.handlerName) {
72 | handler = messageHandlers[message.handlerName]
73 | }
74 |
75 | try {
76 | handler(message.data, responseCallback)
77 |
78 |
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/src/com/example/WebViewJavascriptBridgeExample/MyActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.WebViewJavascriptBridgeExample;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 | import android.util.Log;
6 | import android.view.View;
7 | import android.view.View.OnClickListener;
8 | import android.webkit.WebView;
9 | import android.widget.Button;
10 | import android.widget.Toast;
11 |
12 | import com.fangjian.WebViewJavascriptBridge;
13 |
14 | import java.io.InputStream;
15 |
16 | public class MyActivity extends Activity {
17 | private WebView webView;
18 | private Button button1;
19 | private Button button2;
20 | private Button button3;
21 | private WebViewJavascriptBridge bridge;
22 |
23 | /**
24 | * Called when the activity is first created.
25 | */
26 | @Override
27 | public void onCreate(Bundle savedInstanceState) {
28 | super.onCreate(savedInstanceState);
29 | setContentView(R.layout.main);
30 | webView=(WebView) this.findViewById(R.id.webView);
31 | bridge=new WebViewJavascriptBridge(this,webView,new UserServerHandler()) ;
32 | button1=(Button)this.findViewById(R.id.button1);
33 | button2=(Button)this.findViewById(R.id.button2);
34 | button3=(Button)this.findViewById(R.id.button3);
35 | registerButtons();
36 | loadUserClient();
37 | }
38 |
39 | private void registerButtons() {
40 | button1.setOnClickListener(new OnClickListener(){
41 | @Override
42 | public void onClick(View v) {
43 | if(null!=bridge){
44 | bridge.callHandler("gotoMarker","1");
45 | }
46 | }
47 | });
48 | button2.setOnClickListener(new OnClickListener(){
49 | @Override
50 | public void onClick(View v) {
51 | if(null!=bridge){
52 | bridge.callHandler("gotoMarker","2");
53 | }
54 | }
55 | });
56 | button3.setOnClickListener(new OnClickListener(){
57 | @Override
58 | public void onClick(View v) {
59 | if(null!=bridge){
60 | bridge.callHandler("gotoMarker","3");
61 | }
62 | }
63 | });
64 | }
65 |
66 |
67 | private void loadUserClient(){
68 | InputStream is=getResources().openRawResource(R.raw.user_client);
69 | String user_client_html=WebViewJavascriptBridge.convertStreamToString(is);
70 | // webView.loadData(user_client_html,"text/html","UTF-8");
71 | webView.loadUrl("file:///android_asset/map/map.html");
72 | }
73 |
74 | class UserServerHandler implements WebViewJavascriptBridge.WVJBHandler{
75 | @Override
76 | public void handle(String id, WebViewJavascriptBridge.WVJBResponseCallback jsCallback) {
77 | String msg="user click marker: "+ id;
78 | Log.d("test",msg);
79 | Toast.makeText(MyActivity.this, msg, Toast.LENGTH_SHORT).show();
80 | }
81 | }
82 |
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/Android/Example/res/raw/WebViewJavascriptBridge.js:
--------------------------------------------------------------------------------
1 | ;(function() {
2 | if (window.WebViewJavascriptBridge) { return }
3 |
4 | var messageHandlers = {}
5 | var responseCallbacks = {}
6 | var uniqueId = 1
7 |
8 | function init(messageHandler) {
9 | if (WebViewJavascriptBridge._messageHandler) { throw new Error('WebViewJavascriptBridge.init called twice') }
10 | WebViewJavascriptBridge._messageHandler = messageHandler
11 | }
12 |
13 | function send(data, responseCallback) {
14 | _doSend({ data:data }, responseCallback)
15 | }
16 |
17 | function registerHandler(handlerName, handler) {
18 | messageHandlers[handlerName] = handler
19 | }
20 |
21 | function callHandler(handlerName, data, responseCallback) {
22 | _doSend({ handlerName:handlerName, data:data }, responseCallback)
23 | }
24 |
25 | function _doSend(message, responseCallback) {
26 | console.log("responseCallback:"+responseCallback);
27 | if (responseCallback) {
28 | var callbackId = 'cb_'+(uniqueId++)+'_'+new Date().getTime()
29 | responseCallbacks[callbackId] = responseCallback
30 | message['callbackId'] = callbackId
31 | }
32 | console.log("sending:"+JSON.stringify(message));
33 | _WebViewJavascriptBridge._handleMessageFromJs(message.data||null,message.responseId||null,
34 | message.responseData||null,message.callbackId||null,message.handlerName||null);
35 |
36 | }
37 |
38 | function _dispatchMessageFromJava(messageJSON) {
39 | var message = JSON.parse(messageJSON)
40 | var messageHandler
41 |
42 | if (message.responseId) {
43 | var responseCallback = responseCallbacks[message.responseId]
44 | if (!responseCallback) { return; }
45 | responseCallback(message.responseData)
46 | delete responseCallbacks[message.responseId]
47 | } else {
48 | var responseCallback
49 | if (message.callbackId) {
50 | var callbackResponseId = message.callbackId
51 | responseCallback = function(responseData) {
52 | _doSend({ responseId:callbackResponseId, responseData:responseData })
53 | }
54 | }
55 |
56 | var handler = WebViewJavascriptBridge._messageHandler
57 | if (message.handlerName) {
58 | handler = messageHandlers[message.handlerName]
59 | }
60 | try {
61 | handler(message.data, responseCallback)
62 | } catch(exception) {
63 | if (typeof console != 'undefined') {
64 | console.log("WebViewJavascriptBridge: WARNING: javascript handler threw.", message, exception)
65 | }
66 | }
67 | }
68 | }
69 |
70 |
71 | function _handleMessageFromJava(messageJSON) {
72 | _dispatchMessageFromJava(messageJSON)
73 | }
74 |
75 | //export
76 | window.WebViewJavascriptBridge = {
77 | init: init,
78 | send: send,
79 | registerHandler: registerHandler,
80 | callHandler: callHandler,
81 | _handleMessageFromJava: _handleMessageFromJava
82 | }
83 |
84 | //dispatch event
85 | var doc = document;
86 | var readyEvent = doc.createEvent('Events');
87 | readyEvent.initEvent('WebViewJavascriptBridgeReady');
88 | readyEvent.bridge = WebViewJavascriptBridge;
89 | doc.dispatchEvent(readyEvent);
90 | })();
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/res/raw/webviewjavascriptbridge.js:
--------------------------------------------------------------------------------
1 | ;(function() {
2 | if (window.WebViewJavascriptBridge) { return }
3 |
4 | var messageHandlers = {}
5 | var responseCallbacks = {}
6 | var uniqueId = 1
7 |
8 | function init(messageHandler) {
9 | if (WebViewJavascriptBridge._messageHandler) { throw new Error('WebViewJavascriptBridge.init called twice') }
10 | WebViewJavascriptBridge._messageHandler = messageHandler
11 | }
12 |
13 | function send(data, responseCallback) {
14 | _doSend({ data:data }, responseCallback)
15 | }
16 |
17 | function registerHandler(handlerName, handler) {
18 | messageHandlers[handlerName] = handler
19 | }
20 |
21 | function callHandler(handlerName, data, responseCallback) {
22 | _doSend({ handlerName:handlerName, data:data }, responseCallback)
23 | }
24 |
25 | function _doSend(message, responseCallback) {
26 | console.log("responseCallback:"+responseCallback);
27 | if (responseCallback) {
28 | var callbackId = 'cb_'+(uniqueId++)+'_'+new Date().getTime()
29 | responseCallbacks[callbackId] = responseCallback
30 | message['callbackId'] = callbackId
31 | }
32 | console.log("sending:"+JSON.stringify(message));
33 | _WebViewJavascriptBridge._handleMessageFromJs(message.data||null,message.responseId||null,
34 | message.responseData||null,message.callbackId||null,message.handlerName||null);
35 |
36 | }
37 |
38 | function _dispatchMessageFromJava(messageJSON) {
39 | var message = JSON.parse(messageJSON)
40 | var messageHandler
41 |
42 | if (message.responseId) {
43 | var responseCallback = responseCallbacks[message.responseId]
44 | if (!responseCallback) { return; }
45 | responseCallback(message.responseData)
46 | delete responseCallbacks[message.responseId]
47 | } else {
48 | var responseCallback
49 | if (message.callbackId) {
50 | var callbackResponseId = message.callbackId
51 | responseCallback = function(responseData) {
52 | _doSend({ responseId:callbackResponseId, responseData:responseData })
53 | }
54 | }
55 |
56 | var handler = WebViewJavascriptBridge._messageHandler
57 | if (message.handlerName) {
58 | handler = messageHandlers[message.handlerName]
59 | }
60 | try {
61 | handler(message.data, responseCallback)
62 | } catch(exception) {
63 | if (typeof console != 'undefined') {
64 | console.log("WebViewJavascriptBridge: WARNING: javascript handler threw.", message, exception)
65 | }
66 | }
67 | }
68 | }
69 |
70 |
71 | function _handleMessageFromJava(messageJSON) {
72 | _dispatchMessageFromJava(messageJSON)
73 | }
74 |
75 | //export
76 | window.WebViewJavascriptBridge = {
77 | init: init,
78 | send: send,
79 | registerHandler: registerHandler,
80 | callHandler: callHandler,
81 | _handleMessageFromJava: _handleMessageFromJava
82 | }
83 |
84 | //dispatch event
85 | var doc = document;
86 | var readyEvent = doc.createEvent('Events');
87 | readyEvent.initEvent('WebViewJavascriptBridgeReady');
88 | readyEvent.bridge = WebViewJavascriptBridge;
89 | doc.dispatchEvent(readyEvent);
90 | })();
--------------------------------------------------------------------------------
/Android/WebViewJavascriptBridge/res/raw/webviewjavascriptbridge.js:
--------------------------------------------------------------------------------
1 | ;(function() {
2 | if (window.WebViewJavascriptBridge) { return }
3 |
4 | var messageHandlers = {}
5 | var responseCallbacks = {}
6 | var uniqueId = 1
7 |
8 | function init(messageHandler) {
9 | if (WebViewJavascriptBridge._messageHandler) { throw new Error('WebViewJavascriptBridge.init called twice') }
10 | WebViewJavascriptBridge._messageHandler = messageHandler
11 | }
12 |
13 | function send(data, responseCallback) {
14 | _doSend({ data:data }, responseCallback)
15 | }
16 |
17 | function registerHandler(handlerName, handler) {
18 | messageHandlers[handlerName] = handler
19 | }
20 |
21 | function callHandler(handlerName, data, responseCallback) {
22 | _doSend({ handlerName:handlerName, data:data }, responseCallback)
23 | }
24 |
25 | function _doSend(message, responseCallback) {
26 | console.log("responseCallback:"+responseCallback);
27 | if (responseCallback) {
28 | var callbackId = 'cb_'+(uniqueId++)+'_'+new Date().getTime()
29 | responseCallbacks[callbackId] = responseCallback
30 | message['callbackId'] = callbackId
31 | }
32 | console.log("sending:"+JSON.stringify(message));
33 | _WebViewJavascriptBridge._handleMessageFromJs(message.data||null,message.responseId||null,
34 | message.responseData||null,message.callbackId||null,message.handlerName||null);
35 |
36 | }
37 |
38 | function _dispatchMessageFromJava(messageJSON) {
39 | var message = JSON.parse(messageJSON)
40 | var messageHandler
41 |
42 | if (message.responseId) {
43 | var responseCallback = responseCallbacks[message.responseId]
44 | if (!responseCallback) { return; }
45 | responseCallback(message.responseData)
46 | delete responseCallbacks[message.responseId]
47 | } else {
48 | var responseCallback
49 | if (message.callbackId) {
50 | var callbackResponseId = message.callbackId
51 | responseCallback = function(responseData) {
52 | _doSend({ responseId:callbackResponseId, responseData:responseData })
53 | }
54 | }
55 |
56 | var handler = WebViewJavascriptBridge._messageHandler
57 | if (message.handlerName) {
58 | handler = messageHandlers[message.handlerName]
59 | }
60 | try {
61 | handler(message.data, responseCallback)
62 | } catch(exception) {
63 | if (typeof console != 'undefined') {
64 | console.log("WebViewJavascriptBridge: WARNING: javascript handler threw.", message, exception)
65 | }
66 | }
67 | }
68 | }
69 |
70 |
71 | function _handleMessageFromJava(messageJSON) {
72 | _dispatchMessageFromJava(messageJSON)
73 | }
74 |
75 | //export
76 | window.WebViewJavascriptBridge = {
77 | init: init,
78 | send: send,
79 | registerHandler: registerHandler,
80 | callHandler: callHandler,
81 | _handleMessageFromJava: _handleMessageFromJava
82 | }
83 |
84 | //dispatch event
85 | var doc = document;
86 | var readyEvent = doc.createEvent('Events');
87 | readyEvent.initEvent('WebViewJavascriptBridgeReady');
88 | readyEvent.bridge = WebViewJavascriptBridge;
89 | doc.dispatchEvent(readyEvent);
90 | })();
--------------------------------------------------------------------------------
/IOS/Example Apps/ExampleApp-OSX/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // ExampleApp-OSX
4 | //
5 | // Created by Marcus Westin on 6/8/13.
6 | // Copyright (c) 2013 Marcus Westin. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 | #import
11 | #import "WebViewJavascriptBridge.h"
12 |
13 | @implementation AppDelegate {
14 | WebView* _webView;
15 | WebViewJavascriptBridge* _bridge;
16 | }
17 |
18 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
19 | {
20 | [self _createViews];
21 | [self _createBridge];
22 | [self _createObjcButtons];
23 | [self _loadPage];
24 | }
25 |
26 | - (void)_createBridge {
27 | _bridge = [WebViewJavascriptBridge bridgeForWebView:_webView handler:^(id data, WVJBResponseCallback responseCallback) {
28 | NSLog(@"ObjC received message from JS: %@", data);
29 | responseCallback(@"Response for message from ObjC");
30 | }];
31 |
32 | [_bridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) {
33 | NSLog(@"testObjcCallback called: %@", data);
34 | responseCallback(@"Response from testObjcCallback");
35 | }];
36 |
37 | [_bridge send:@"A string sent from ObjC before Webview has loaded." responseCallback:^(id responseData) {
38 | NSLog(@"objc got response! %@", responseData);
39 | }];
40 |
41 | [_bridge callHandler:@"testJavascriptHandler" data:[NSDictionary dictionaryWithObject:@"before ready" forKey:@"foo"]];
42 | }
43 |
44 | - (void)_createObjcButtons {
45 | NSButton *messageButton = [[NSButton alloc] initWithFrame:NSMakeRect(5, 0, 120, 40)];
46 | [messageButton setTitle:@"Send message"];
47 | [messageButton setBezelStyle:NSRoundedBezelStyle];
48 | [messageButton setTarget:self];
49 | [messageButton setAction:@selector(_sendMessage)];
50 | [_webView addSubview:messageButton];
51 |
52 | NSButton *callbackButton = [[NSButton alloc] initWithFrame:NSMakeRect(120, 0, 120, 40)];
53 | [callbackButton setTitle:@"Call handler"];
54 | [callbackButton setBezelStyle:NSRoundedBezelStyle];
55 | [callbackButton setTarget:self];
56 | [callbackButton setAction:@selector(_callHandler)];
57 | [_webView addSubview:callbackButton];
58 | }
59 |
60 | - (void)_sendMessage {
61 | [_bridge send:@"A string sent from ObjC to JS" responseCallback:^(id response) {
62 | NSLog(@"sendMessage got response: %@", response);
63 | }];
64 | }
65 |
66 | - (void)_callHandler {
67 | NSDictionary* data = [NSDictionary dictionaryWithObject:@"Hi there, JS!" forKey:@"greetingFromObjC"];
68 | [_bridge callHandler:@"testJavascriptHandler" data:data responseCallback:^(id response) {
69 | NSLog(@"testJavascriptHandler responded: %@", response);
70 | }];
71 | }
72 |
73 | - (void)_createViews {
74 | NSView* contentView = _window.contentView;
75 | _webView = [[WebView alloc] initWithFrame:contentView.frame];
76 | [_webView setAutoresizingMask:(NSViewHeightSizable | NSViewWidthSizable)];
77 | [contentView addSubview:_webView];
78 | }
79 |
80 | - (void)_loadPage {
81 | NSString* htmlPath = [[NSBundle mainBundle] pathForResource:@"ExampleApp" ofType:@"html"];
82 | NSString* html = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil];
83 | [[_webView mainFrame] loadHTMLString:html baseURL:nil];
84 | }
85 |
86 |
87 | @end
88 |
--------------------------------------------------------------------------------
/IOS/Example Apps/ExampleApp-iOS/ExampleAppDelegate.m:
--------------------------------------------------------------------------------
1 | #import "ExampleAppDelegate.h"
2 |
3 | @implementation ExampleAppDelegate
4 |
5 | @synthesize window = _window;
6 | @synthesize javascriptBridge = _bridge;
7 |
8 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
9 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
10 | UIWebView* webView = [[UIWebView alloc] initWithFrame:self.window.bounds];
11 | [self.window addSubview:webView];
12 |
13 | [WebViewJavascriptBridge enableLogging];
14 |
15 | _bridge = [WebViewJavascriptBridge bridgeForWebView:webView handler:^(id data, WVJBResponseCallback responseCallback) {
16 | NSLog(@"ObjC received message from JS: %@", data);
17 | responseCallback(@"Response for message from ObjC");
18 | }];
19 |
20 | [_bridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) {
21 | NSLog(@"testObjcCallback called: %@", data);
22 | responseCallback(@"Response from testObjcCallback");
23 | }];
24 |
25 | [_bridge send:@"A string sent from ObjC before Webview has loaded." responseCallback:^(id responseData) {
26 | NSLog(@"objc got response! %@", responseData);
27 | }];
28 |
29 | [_bridge callHandler:@"testJavascriptHandler" data:[NSDictionary dictionaryWithObject:@"before ready" forKey:@"foo"]];
30 |
31 | [self renderButtons:webView];
32 | [self loadExamplePage:webView];
33 |
34 | [_bridge send:@"A string sent from ObjC after Webview has loaded."];
35 |
36 | [self.window makeKeyAndVisible];
37 | return YES;
38 | }
39 |
40 | - (void)renderButtons:(UIWebView*)webView {
41 | UIButton *messageButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
42 | [messageButton setTitle:@"Send message" forState:UIControlStateNormal];
43 | [messageButton addTarget:self action:@selector(sendMessage:) forControlEvents:UIControlEventTouchUpInside];
44 | [self.window insertSubview:messageButton aboveSubview:webView];
45 | messageButton.frame = CGRectMake(20, 414, 130, 45);
46 |
47 | UIButton *callbackButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
48 | [callbackButton setTitle:@"Call handler" forState:UIControlStateNormal];
49 | [callbackButton addTarget:self action:@selector(callHandler:) forControlEvents:UIControlEventTouchUpInside];
50 | [self.window insertSubview:callbackButton aboveSubview:webView];
51 | callbackButton.frame = CGRectMake(170, 414, 130, 45);
52 | }
53 |
54 | - (void)sendMessage:(id)sender {
55 | [_bridge send:@"A string sent from ObjC to JS" responseCallback:^(id response) {
56 | NSLog(@"sendMessage got response: %@", response);
57 | }];
58 | }
59 |
60 | - (void)callHandler:(id)sender {
61 | NSDictionary* data = [NSDictionary dictionaryWithObject:@"Hi there, JS!" forKey:@"greetingFromObjC"];
62 | [_bridge callHandler:@"testJavascriptHandler" data:data responseCallback:^(id response) {
63 | NSLog(@"testJavascriptHandler responded: %@", response);
64 | }];
65 | }
66 |
67 | - (void)loadExamplePage:(UIWebView*)webView {
68 | NSString* htmlPath = [[NSBundle mainBundle] pathForResource:@"ExampleApp" ofType:@"html"];
69 | NSString* appHtml = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil];
70 | [webView loadHTMLString:appHtml baseURL:nil];
71 | }
72 |
73 | @end
74 |
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/assets/map/map.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "FeatureCollection",
3 | "crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
4 |
5 | "features": [
6 | { "type": "Feature", "properties": { "id": "9" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 0.045789260282743, 0.037614260743797 ], [ 0.180647430215849, 0.072577473278299 ], [ 0.192634823098792, -0.058284869565449 ], [ 0.142687352753197, -0.133205965137988 ], [ 0.020815525109945, -0.027317446968654 ], [ 0.045789260282743, 0.037614260743797 ] ] ] } },
7 | { "type": "Feature", "properties": { "id": "8" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -0.217933383142, 0.199443664587573 ], [ -0.280867195777449, 0.087561699707584 ], [ -0.347796806040547, 0.106541711123344 ], [ -0.374768440027168, 0.125521710847691 ], [ -0.391750579944671, 0.178465841237821 ], [ -0.37576738943408, 0.230410877947367 ], [ -0.308837779170983, 0.260379084947635 ], [ -0.273874549929066, 0.246393930046665 ], [ -0.217933383142, 0.199443664587573 ] ] ] } },
8 | { "type": "Feature", "properties": { "id": "7" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -0.260888207639211, 0.016636325666744 ], [ -0.204947040852145, 0.013639477550946 ], [ -0.200951243224497, -0.039304837803795 ], [ -0.256892410011564, -0.048295379829764 ], [ -0.260888207639211, 0.016636325666744 ] ] ] } },
9 | { "type": "Feature", "properties": { "id": "6" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -0.061098326256831, -0.29203777632197 ], [ -0.004158210062852, -0.302027136140558 ], [ 0.067766147234805, -0.291038839846852 ], [ 0.076756691897012, -0.365958808636511 ], [ 0.063770349607157, -0.40991157398009 ], [ 0.013822879261562, -0.442875991098272 ], [ -0.02913194523565, -0.43788139159814 ], [ -0.072086769732862, -0.390931998841664 ], [ -0.075083617953598, -0.359965232463082 ], [ -0.061098326256831, -0.29203777632197 ] ] ] } },
10 | { "type": "Feature", "properties": { "id": "5" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 0.282540269720864, -0.052291175917215 ], [ 0.365453070494551, -0.066276460092937 ], [ 0.318502448369692, -0.194141627456279 ], [ 0.251572838106595, -0.273057968461074 ], [ 0.235589647596004, -0.28404628206098 ], [ 0.184643227843497, -0.222112026035719 ], [ 0.235589647596004, -0.176160632089973 ], [ 0.262561281582626, -0.126213337212819 ], [ 0.282540269720864, -0.052291175917215 ] ] ] } },
11 | { "type": "Feature", "properties": { "id": "4" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 0.201625367760999, 0.177466896649782 ], [ 0.274548674465568, 0.245394989839293 ], [ 0.346473031763225, 0.249390750218211 ], [ 0.393423653888085, 0.177466896649782 ], [ 0.354464627018521, 0.109538554015806 ], [ 0.256567585141154, 0.077572216023554 ], [ 0.201625367760999, 0.177466896649782 ] ] ] } },
12 | { "type": "Feature", "properties": { "id": "3" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 0.080752489524659, 0.245394989839293 ], [ 0.114716769359664, 0.349284314962592 ], [ 0.186641126657321, 0.32031527704937 ], [ 0.131698909277166, 0.225416170430827 ], [ 0.080752489524659, 0.245394989839293 ] ] ] } },
13 | { "type": "Feature", "properties": { "id": "2" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 0.001835486378619, 0.261378023999677 ], [ -0.000162412435205, 0.365267194683676 ], [ 0.068765096641716, 0.360272547765722 ], [ 0.046788209689655, 0.256383327951034 ], [ 0.001835486378619, 0.261378023999677 ] ] ] } },
14 | { "type": "Feature", "properties": { "id": "1" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -0.131024784740664, 0.343290727993024 ], [ -0.063096225070655, 0.361271477369545 ], [ -0.043117236932417, 0.254385448983913 ], [ -0.088069960243452, 0.242398168770805 ], [ -0.131024784740664, 0.343290727993024 ] ] ] } }
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/Android/Example/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Eclipse
3 | #################
4 |
5 | *.pydevproject
6 | .project
7 | .metadata
8 | bin/
9 | tmp/
10 | *.tmp
11 | *.bak
12 | *.swp
13 | *~.nib
14 | local.properties
15 | .classpath
16 | .settings/
17 | .loadpath
18 |
19 | # External tool builders
20 | .externalToolBuilders/
21 |
22 | # Locally stored "Eclipse launch configurations"
23 | *.launch
24 |
25 | # CDT-specific
26 | .cproject
27 |
28 | # PDT-specific
29 | .buildpath
30 |
31 |
32 | #################
33 | ## Visual Studio
34 | #################
35 |
36 | ## Ignore Visual Studio temporary files, build results, and
37 | ## files generated by popular Visual Studio add-ons.
38 |
39 | # User-specific files
40 | *.suo
41 | *.user
42 | *.sln.docstates
43 |
44 | # Build results
45 |
46 | [Dd]ebug/
47 | [Rr]elease/
48 | x64/
49 | build/
50 | [Bb]in/
51 | [Oo]bj/
52 |
53 | # MSTest test Results
54 | [Tt]est[Rr]esult*/
55 | [Bb]uild[Ll]og.*
56 |
57 | *_i.c
58 | *_p.c
59 | *.ilk
60 | *.meta
61 | *.obj
62 | *.pch
63 | *.pdb
64 | *.pgc
65 | *.pgd
66 | *.rsp
67 | *.sbr
68 | *.tlb
69 | *.tli
70 | *.tlh
71 | *.tmp
72 | *.tmp_proj
73 | *.log
74 | *.vspscc
75 | *.vssscc
76 | .builds
77 | *.pidb
78 | *.log
79 | *.scc
80 |
81 | # Visual C++ cache files
82 | ipch/
83 | *.aps
84 | *.ncb
85 | *.opensdf
86 | *.sdf
87 | *.cachefile
88 |
89 | # Visual Studio profiler
90 | *.psess
91 | *.vsp
92 | *.vspx
93 |
94 | # Guidance Automation Toolkit
95 | *.gpState
96 |
97 | # ReSharper is a .NET coding add-in
98 | _ReSharper*/
99 | *.[Rr]e[Ss]harper
100 |
101 | # TeamCity is a build add-in
102 | _TeamCity*
103 |
104 | # DotCover is a Code Coverage Tool
105 | *.dotCover
106 |
107 | # NCrunch
108 | *.ncrunch*
109 | .*crunch*.local.xml
110 |
111 | # Installshield output folder
112 | [Ee]xpress/
113 |
114 | # DocProject is a documentation generator add-in
115 | DocProject/buildhelp/
116 | DocProject/Help/*.HxT
117 | DocProject/Help/*.HxC
118 | DocProject/Help/*.hhc
119 | DocProject/Help/*.hhk
120 | DocProject/Help/*.hhp
121 | DocProject/Help/Html2
122 | DocProject/Help/html
123 |
124 | # Click-Once directory
125 | publish/
126 |
127 | # Publish Web Output
128 | *.Publish.xml
129 | *.pubxml
130 |
131 | # NuGet Packages Directory
132 | ## If you have NuGet Package Restore enabled, uncomment the next line
133 | #packages/
134 |
135 | # Windows Azure Build Output
136 | csx
137 | *.build.csdef
138 |
139 | # Windows Store app package directory
140 | AppPackages/
141 |
142 | # Others
143 | sql/
144 | *.Cache
145 | ClientBin/
146 | [Ss]tyle[Cc]op.*
147 | ~$*
148 | *~
149 | *.dbmdl
150 | *.[Pp]ublish.xml
151 | *.pfx
152 | *.publishsettings
153 |
154 | # RIA/Silverlight projects
155 | Generated_Code/
156 |
157 | # Backup & report files from converting an old project file to a newer
158 | # Visual Studio version. Backup files are not needed, because we have git ;-)
159 | _UpgradeReport_Files/
160 | Backup*/
161 | UpgradeLog*.XML
162 | UpgradeLog*.htm
163 |
164 | # SQL Server files
165 | App_Data/*.mdf
166 | App_Data/*.ldf
167 |
168 | #############
169 | ## Windows detritus
170 | #############
171 |
172 | # Windows image file caches
173 | Thumbs.db
174 | ehthumbs.db
175 |
176 | # Folder config file
177 | Desktop.ini
178 |
179 | # Recycle Bin used on file shares
180 | $RECYCLE.BIN/
181 |
182 | # Mac crap
183 | .DS_Store
184 |
185 |
186 | #############
187 | ## Python
188 | #############
189 |
190 | *.py[co]
191 |
192 | # Packages
193 | *.egg
194 | *.egg-info
195 | dist/
196 | build/
197 | eggs/
198 | parts/
199 | var/
200 | sdist/
201 | develop-eggs/
202 | .installed.cfg
203 |
204 | # Installer logs
205 | pip-log.txt
206 |
207 | # Unit test / coverage reports
208 | .coverage
209 | .tox
210 |
211 | #Translations
212 | *.mo
213 |
214 | #Mr Developer
215 | .mr.developer.cfg
216 |
217 | # Intellij
218 | .idea/
219 | gen/
220 | out/
221 |
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Eclipse
3 | #################
4 |
5 | *.pydevproject
6 | .project
7 | .metadata
8 | bin/
9 | tmp/
10 | *.tmp
11 | *.bak
12 | *.swp
13 | *~.nib
14 | local.properties
15 | .classpath
16 | .settings/
17 | .loadpath
18 |
19 | # External tool builders
20 | .externalToolBuilders/
21 |
22 | # Locally stored "Eclipse launch configurations"
23 | *.launch
24 |
25 | # CDT-specific
26 | .cproject
27 |
28 | # PDT-specific
29 | .buildpath
30 |
31 |
32 | #################
33 | ## Visual Studio
34 | #################
35 |
36 | ## Ignore Visual Studio temporary files, build results, and
37 | ## files generated by popular Visual Studio add-ons.
38 |
39 | # User-specific files
40 | *.suo
41 | *.user
42 | *.sln.docstates
43 |
44 | # Build results
45 |
46 | [Dd]ebug/
47 | [Rr]elease/
48 | x64/
49 | build/
50 | [Bb]in/
51 | [Oo]bj/
52 |
53 | # MSTest test Results
54 | [Tt]est[Rr]esult*/
55 | [Bb]uild[Ll]og.*
56 |
57 | *_i.c
58 | *_p.c
59 | *.ilk
60 | *.meta
61 | *.obj
62 | *.pch
63 | *.pdb
64 | *.pgc
65 | *.pgd
66 | *.rsp
67 | *.sbr
68 | *.tlb
69 | *.tli
70 | *.tlh
71 | *.tmp
72 | *.tmp_proj
73 | *.log
74 | *.vspscc
75 | *.vssscc
76 | .builds
77 | *.pidb
78 | *.log
79 | *.scc
80 |
81 | # Visual C++ cache files
82 | ipch/
83 | *.aps
84 | *.ncb
85 | *.opensdf
86 | *.sdf
87 | *.cachefile
88 |
89 | # Visual Studio profiler
90 | *.psess
91 | *.vsp
92 | *.vspx
93 |
94 | # Guidance Automation Toolkit
95 | *.gpState
96 |
97 | # ReSharper is a .NET coding add-in
98 | _ReSharper*/
99 | *.[Rr]e[Ss]harper
100 |
101 | # TeamCity is a build add-in
102 | _TeamCity*
103 |
104 | # DotCover is a Code Coverage Tool
105 | *.dotCover
106 |
107 | # NCrunch
108 | *.ncrunch*
109 | .*crunch*.local.xml
110 |
111 | # Installshield output folder
112 | [Ee]xpress/
113 |
114 | # DocProject is a documentation generator add-in
115 | DocProject/buildhelp/
116 | DocProject/Help/*.HxT
117 | DocProject/Help/*.HxC
118 | DocProject/Help/*.hhc
119 | DocProject/Help/*.hhk
120 | DocProject/Help/*.hhp
121 | DocProject/Help/Html2
122 | DocProject/Help/html
123 |
124 | # Click-Once directory
125 | publish/
126 |
127 | # Publish Web Output
128 | *.Publish.xml
129 | *.pubxml
130 |
131 | # NuGet Packages Directory
132 | ## If you have NuGet Package Restore enabled, uncomment the next line
133 | #packages/
134 |
135 | # Windows Azure Build Output
136 | csx
137 | *.build.csdef
138 |
139 | # Windows Store app package directory
140 | AppPackages/
141 |
142 | # Others
143 | sql/
144 | *.Cache
145 | ClientBin/
146 | [Ss]tyle[Cc]op.*
147 | ~$*
148 | *~
149 | *.dbmdl
150 | *.[Pp]ublish.xml
151 | *.pfx
152 | *.publishsettings
153 |
154 | # RIA/Silverlight projects
155 | Generated_Code/
156 |
157 | # Backup & report files from converting an old project file to a newer
158 | # Visual Studio version. Backup files are not needed, because we have git ;-)
159 | _UpgradeReport_Files/
160 | Backup*/
161 | UpgradeLog*.XML
162 | UpgradeLog*.htm
163 |
164 | # SQL Server files
165 | App_Data/*.mdf
166 | App_Data/*.ldf
167 |
168 | #############
169 | ## Windows detritus
170 | #############
171 |
172 | # Windows image file caches
173 | Thumbs.db
174 | ehthumbs.db
175 |
176 | # Folder config file
177 | Desktop.ini
178 |
179 | # Recycle Bin used on file shares
180 | $RECYCLE.BIN/
181 |
182 | # Mac crap
183 | .DS_Store
184 |
185 |
186 | #############
187 | ## Python
188 | #############
189 |
190 | *.py[co]
191 |
192 | # Packages
193 | *.egg
194 | *.egg-info
195 | dist/
196 | build/
197 | eggs/
198 | parts/
199 | var/
200 | sdist/
201 | develop-eggs/
202 | .installed.cfg
203 |
204 | # Installer logs
205 | pip-log.txt
206 |
207 | # Unit test / coverage reports
208 | .coverage
209 | .tox
210 |
211 | #Translations
212 | *.mo
213 |
214 | #Mr Developer
215 | .mr.developer.cfg
216 |
217 | # Intellij
218 | .idea/
219 | gen/
220 | out/
221 |
--------------------------------------------------------------------------------
/Html/Example/single_page.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
26 |
27 |
44 |
45 |
79 |
87 |
88 |
104 |
105 |
106 |
107 |
108 |
--------------------------------------------------------------------------------
/IOS/WebViewJavascriptBridge/WebViewJavascriptBridge.js.txt:
--------------------------------------------------------------------------------
1 | ;(function() {
2 | if (window.WebViewJavascriptBridge) { return }
3 | var messagingIframe
4 | var sendMessageQueue = []
5 | var receiveMessageQueue = []
6 | var messageHandlers = {}
7 |
8 | var MESSAGE_SEPARATOR = '__WVJB_MESSAGE_SEPERATOR__'
9 | var CUSTOM_PROTOCOL_SCHEME = 'wvjbscheme'
10 | var QUEUE_HAS_MESSAGE = '__WVJB_QUEUE_MESSAGE__'
11 |
12 | var responseCallbacks = {}
13 | var uniqueId = 1
14 |
15 | function _createQueueReadyIframe(doc) {
16 | messagingIframe = doc.createElement('iframe')
17 | messagingIframe.style.display = 'none'
18 | doc.documentElement.appendChild(messagingIframe)
19 | }
20 |
21 | function init(messageHandler) {
22 | if (WebViewJavascriptBridge._messageHandler) { throw new Error('WebViewJavascriptBridge.init called twice') }
23 | WebViewJavascriptBridge._messageHandler = messageHandler
24 | var receivedMessages = receiveMessageQueue
25 | receiveMessageQueue = null
26 | for (var i=0; i
2 |
3 |
4 |
7 |
8 |
9 |
29 |
30 |
31 |
35 |
36 |
37 |
38 |
39 |
40 |
49 |
50 |
51 |
52 |
56 |
57 |
69 |
70 |
71 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/build.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
29 |
30 |
31 |
35 |
36 |
37 |
38 |
39 |
40 |
49 |
50 |
51 |
52 |
56 |
57 |
69 |
70 |
71 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | WebViewJavascriptBridge
2 | =======================
3 | Cross-platform WebViewJavascriptBridge for HTML/Android/Chrome Extension, the javascript interface compatible with [WebViewJavascriptBridge](https://github.com/marcuswestin/WebViewJavascriptBridge)
4 |
5 | TODO:
6 |
7 | - Use the queue ,cache the message before the client and server both inited.
8 | - Use the Long-lived connections instead of the Simple one-time requests, [Message Passing](https://developer.chrome.com/extensions/messaging.html#connect)
9 |
10 | Android
11 | ----------
12 | To use a WebViewJavascriptBridge in your Android project:
13 |
14 | 1) Add "res/raw/webviewjavascriptbridge.js" and "com/fangjian/WebViewJavascriptBridge.java" to your project
15 |
16 | 2) Set up the Android side
17 |
18 | bridge=new WebViewJavascriptBridge(this.getApplicationContext(),webView,new UserServerHandler()) ;
19 |
20 | class UserServerHandler implements WebViewJavascriptBridge.WVJBHandler{
21 | @Override
22 | public void handle(String data, WebViewJavascriptBridge.WVJBResponseCallback jsCallback) {
23 | Log.d("test","Received message from javascript: "+ data);
24 | if (null !=jsCallback) {
25 | jsCallback.callback("Java said:Right back atcha");
26 | }
27 | bridge.send("I expect a response!",new WebViewJavascriptBridge.WVJBResponseCallback() {
28 | @Override
29 | public void callback(String responseData) {
30 | Log.d("test","Got response! "+responseData);
31 | }
32 | });
33 | bridge.send("Hi");
34 | }
35 | }
36 |
37 | bridge.registerHandler("handler1",new WebViewJavascriptBridge.WVJBHandler() {
38 | @Override
39 | public void handle(String data, WebViewJavascriptBridge.WVJBResponseCallback jsCallback) {
40 | Log.d("test","handler1 got:"+data);
41 | if(null!=jsCallback){
42 | jsCallback.callback("handler1 answer");
43 | }
44 | bridge.callHandler("showAlert","42");
45 | }
46 | });
47 |
48 | 3) Set up the Javascript side
49 |
50 | console.log("user_client.js called!");
51 | document.addEventListener('WebViewJavascriptBridgeReady'
52 | , function(event) {
53 | var bridge=event.bridge;
54 | bridge.init(function(message, responseCallback) {
55 | if (responseCallback) {
56 | responseCallback("Right back atcha") ;
57 | }
58 | }) ;
59 | bridge.send('Hello from the javascript');
60 | bridge.send('Please respond to this', function(responseData) {
61 | console.log("Javascript got its response "+ responseData);
62 | });
63 | bridge.registerHandler("showAlert", function(data) { console.log("alert:"+data); });
64 | bridge.callHandler("handler1","gift for handler1",function(responseData){
65 | console.log("got handler1 response:"+responseData);
66 | });
67 | }, false)
68 |
69 |
70 | Chrome
71 | ----------
72 | To use a WebViewJavascriptBridge in your chrome extension:
73 |
74 | 1) Add "bridgeClientChrome.js" and "bridgeServerChrome.js" to your manifest.json
75 |
76 | "content_scripts": [
77 | {
78 | "matches": ["*://*/*"],
79 | "js": ["user_client.js","bridgeClientChrome.js"]
80 | }
81 | ],
82 | "background": {
83 | "scripts": ["bridgeServerChrome.js","user_server.js"]
84 | },
85 | 2) Set up the background side:
86 |
87 | console.log("user_server.js called!");
88 | bridge.sinit(function(data,responseCallback){
89 | console.log("Received message from javascript: "+data);
90 | responseCallback("Right back atcha");
91 | })
92 |
93 | bridge.ssend("Well hello there");
94 | bridge.ssend("Give me a response, will you?", function(responseData) {
95 | console.log("Background got its response! "+responseData);
96 | })
97 |
98 | 3) Set up the foreground side:
99 |
100 | console.log("user_client.js called!");
101 | document.addEventListener('WebViewJavascriptBridgeReady', function onBridgeReady(event) {
102 | var bridge = event.bridge
103 | bridge.init(function(message, responseCallback) {
104 | alert('Received message: ' + message)
105 | if (responseCallback) {
106 | responseCallback("Right back atcha")
107 | }
108 | })
109 | bridge.send('Hello from the javascript')
110 | bridge.send('Please respond to this', function responseCallback(responseData) {
111 | console.log("Javascript got its response", responseData)
112 | })
113 | }, false)
114 |
115 | HTML
116 | ----------
117 | To use a WebViewJavascriptBridge in your HTML page:
118 | 1) Add "bridgeServerHtml.js" and "bridgeClientHtml.js" to your page. bridgeServerHtml.js Must be first and bridgeClientHtml.js Must be last.
119 |
120 |
121 |
122 |
123 |
124 |
125 | 2) Set up the background side:
126 |
127 | console.log("user_server.js called!");
128 | bridge.sinit(function(data,responseCallback){
129 | console.log("Received message from javascript: "+data);
130 | if(responseCallback){
131 | responseCallback("Right back atcha");
132 | }
133 | })
134 | function serverSend(){
135 | bridge.ssend("Well hello there");
136 | bridge.ssend("Give me a response, will you?", function(responseData) {
137 | console.log("Background got its response! "+responseData);
138 | })
139 | }
140 | setTimeout(serverSend,1000);
141 |
142 | 3) Set up the foreground side:
143 |
144 | console.log("user_client.js called!");
145 | document.addEventListener('WebViewJavascriptBridgeReady', function onBridgeReady(event) {
146 | var bridge = event.bridge
147 | bridge.init(function(message, responseCallback) {
148 | alert('Received message: ' + message)
149 | if (responseCallback) {
150 | responseCallback("Right back atcha")
151 | }
152 | })
153 | bridge.send('Hello from the javascript')
154 | bridge.send('Please respond to this', function responseCallback(responseData) {
155 | console.log("Javascript got its response", responseData)
156 | })
157 | }, false)
158 |
159 | IOS
160 | ----------
161 | An iOS/OSX bridge for sending messages between Obj-C and JavaScript in UIWebViews/WebViews.
162 |
163 | forked from [marcuswestin/WebViewJavascriptBridge](https://github.com/marcuswestin/WebViewJavascriptBridge).
164 |
165 |
--------------------------------------------------------------------------------
/IOS/README.md:
--------------------------------------------------------------------------------
1 | WebViewJavascriptBridge
2 | =======================
3 |
4 | An iOS/OSX bridge for sending messages between Obj-C and JavaScript in UIWebViews/WebViews.
5 |
6 | If you like WebViewJavascriptBridge you may also want to check out [WebViewProxy](https://github.com/marcuswestin/WebViewProxy).
7 |
8 | In the Wild
9 | -----------
10 | WebViewJavascriptBridge is used by a range of companies and projects. This list is incomplete, but feel free to add your's and send a PR.
11 |
12 | - [Yardsale](https://www.getyardsale.com/)
13 | - [EverTrue](http://www.evertrue.com/)
14 | - [Game Insight](http://www.game-insight.com/)
15 | - [Altralogica](http://www.altralogica.it)
16 | - [Sush.io](http://www.sush.io)
17 | - Flutterby Labs
18 | - JD Media's [鼎盛中华](https://itunes.apple.com/us/app/ding-sheng-zhong-hua/id537273940?mt=8)
19 |
20 | Setup & Examples (iOS & OSX)
21 | ----------------------------
22 |
23 | Start with the Example Apps/ folder. Open either the iOS or OSX project and hit run to see it in action.
24 |
25 | To use a WebViewJavascriptBridge in your own project:
26 |
27 | 1) Drag the `WebViewJavascriptBridge` folder into your project.
28 |
29 | - In the dialog that appears, uncheck "Copy items into destination group's folder" and select "Create groups for any folders"
30 |
31 | 2) Import the header file:
32 |
33 | #import "WebViewJavascriptBridge.h"
34 |
35 | 3) Instantiate WebViewJavascriptBridge with a UIWebView (iOS) or WebView (OSX):
36 |
37 | WebViewJavascriptBridge* bridge = [WebViewJavascriptBridge bridgeForWebView:webView handler:^(id data, WVJBResponseCallback responseCallback) {
38 | NSLog(@"Received message from javascript: %@", data);
39 | responseCallback(@"Right back atcha");
40 | }];
41 |
42 | 4) Go ahead and send some messages from ObjC to javascript:
43 |
44 | [bridge send:@"Well hello there"];
45 | [bridge send:[NSDictionary dictionaryWithObject:@"Foo" forKey:@"Bar"]];
46 | [bridge send:@"Give me a response, will you?" responseCallback:^(id responseData) {
47 | NSLog(@"ObjC got its response! %@ %@", responseData);
48 | }];
49 |
50 | 4) Finally, set up the javascript side:
51 |
52 | document.addEventListener('WebViewJavascriptBridgeReady', function onBridgeReady(event) {
53 | var bridge = event.bridge
54 | bridge.init(function(message, responseCallback) {
55 | alert('Received message: ' + message)
56 | if (responseCallback) {
57 | responseCallback("Right back atcha")
58 | }
59 | })
60 | bridge.send('Hello from the javascript')
61 | bridge.send('Please respond to this', function responseCallback(responseData) {
62 | console.log("Javascript got its response", responseData)
63 | })
64 | }, false)
65 |
66 | API Reference
67 | -------------
68 |
69 | ### ObjC API
70 |
71 | ##### `[WebViewJavascriptBridge bridgeForWebView:(UIWebView/WebView*)webview handler:(WVJBHandler)handler]`
72 | ##### `[WebViewJavascriptBridge bridgeForWebView:(UIWebView/WebView*)webview webViewDelegate:(UIWebViewDelegate*)webViewDelegate handler:(WVJBHandler)handler]`
73 |
74 | Create a javascript bridge for the given web view.
75 |
76 | The `WVJBResponseCallback` will not be `nil` if the javascript expects a response.
77 |
78 | Optionally, pass in `webViewDelegate:(UIWebViewDelegate*)webViewDelegate` if you need to respond to the [web view's lifecycle events](http://developer.apple.com/library/ios/documentation/uikit/reference/UIWebViewDelegate_Protocol/Reference/Reference.html).
79 |
80 | Example:
81 |
82 | [WebViewJavascriptBridge bridgeForWebView:webView handler:^(id data, WVJBResponseCallback responseCallback) {
83 | NSLog(@"Received message from javascript: %@", data);
84 | if (responseCallback) {
85 | responseCallback(@"Right back atcha");
86 | }
87 | }]
88 |
89 | [WebViewJavascriptBridge bridgeForWebView:webView webViewDelegate:self handler:^(id data, WVJBResponseCallback responseCallback) { /* ... */ }];
90 |
91 | ##### `[bridge send:(id)data]`
92 | ##### `[bridge send:(id)data responseCallback:(WVJBResponseCallback)responseCallback]`
93 |
94 | Send a message to javascript. Optionally expect a response by giving a `responseCallback` block.
95 |
96 | Example:
97 |
98 | [bridge send:@"Hi"];
99 | [bridge send:[NSDictionary dictionaryWithObject:@"Foo" forKey:@"Bar"]];
100 | [bridge send:@"I expect a response!" responseCallback:^(id responseData) {
101 | NSLog(@"Got response! %@", responseData);
102 | }];
103 |
104 | ##### `[bridge registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler]`
105 |
106 | Register a handler called `handlerName`. The javascript can then call this handler with `WebViewJavascriptBridge.callHandler("handlerName")`.
107 |
108 | Example:
109 |
110 | [bridge registerHandler:@"getScreenHeight" handler:^(id data, WVJBResponseCallback responseCallback) {
111 | responseCallback([NSNumber numberWithInt:[UIScreen mainScreen].bounds.size.height]);
112 | }];
113 |
114 | ##### `[bridge callHandler:(NSString*)handlerName data:(id)data]`
115 | ##### `[bridge callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)callback]`
116 |
117 | Call the javascript handler called `handlerName`. Optionally expect a response by giving a `responseCallback` block.
118 |
119 | Example:
120 |
121 | [bridge callHandler:@"showAlert" data:@"Hi from ObjC to JS!"];
122 | [bridge callHandler:@"getCurrentPageUrl" data:nil responseCallback:^(id responseData) {
123 | NSLog(@"Current UIWebView page URL is: %@", responseData);
124 | }];
125 |
126 |
127 | ### Javascript API
128 |
129 | ##### `document.addEventListener('WebViewJavascriptBridgeReady', function onBridgeReady(event) { ... }, false)`
130 |
131 | Always wait for the `WebViewJavascriptBridgeReady` DOM event.
132 |
133 | Example:
134 |
135 | document.addEventListener('WebViewJavascriptBridgeReady', function(event) {
136 | var bridge = event.bridge
137 | // Start using the bridge
138 | }, false)
139 |
140 | ##### `bridge.init(function messageHandler(data, response) { ... })`
141 |
142 | Initialize the bridge. This should be called inside of the `'WebViewJavascriptBridgeReady'` event handler.
143 |
144 | The `messageHandler` function will receive all messages sent from ObjC via `[bridge send:(id)data]` and `[bridge send:(id)data responseCallback:(WVJBResponseCallback)responseCallback]`.
145 |
146 | The `response` object will be defined if if ObjC sent the message with a `WVJBResponseCallback` block.
147 |
148 | Example:
149 |
150 | bridge.init(function(data, responseCallback) {
151 | alert("Got data " + JSON.stringify(data))
152 | if (responseCallback) {
153 | responseCallback("Right back atcha!")
154 | }
155 | })
156 |
157 | ##### `bridge.send("Hi there!")`
158 | ##### `bridge.send({ Foo:"Bar" })`
159 | ##### `bridge.send(data, function responseCallback(responseData) { ... })`
160 |
161 | Send a message to ObjC. Optionally expect a response by giving a `responseCallback` function.
162 |
163 | Example:
164 |
165 | bridge.send("Hi there!")
166 | bridge.send("Hi there!", function(responseData) {
167 | alert("I got a response! "+JSON.stringify(responseData))
168 | })
169 |
170 | ##### `bridge.registerHandler("handlerName", function(responseData) { ... })`
171 |
172 | Register a handler called `handlerName`. The ObjC can then call this handler with `[bridge callHandler:"handlerName" data:@"Foo"]` and `[bridge callHandler:"handlerName" data:@"Foo" responseCallback:^(id responseData) { ... }]`
173 |
174 | Example:
175 |
176 | bridge.registerHandler("showAlert", function(data) { alert(data) })
177 | bridge.registerHandler("getCurrentPageUrl", function(data, responseCallback) {
178 | responseCallback(document.location.toString())
179 | })
180 |
181 |
182 | iOS4 support (with JSONKit)
183 | ---------------------------
184 |
185 | *Note*: iOS4 support has not yet been tested in v2+.
186 |
187 | WebViewJavascriptBridge uses `NSJSONSerialization` by default. If you need iOS 4 support then you can use [JSONKit](https://github.com/johnezang/JSONKit/), and add `USE_JSONKIT` to the preprocessor macros for your project.
188 |
189 | Contributors
190 | ------------
191 | - [@marcuswestin](https://github.com/marcuswestin) Marcus Westin (Author)
192 | - [@oakho](https://github.com/oakho) Antoine Lagadec (OS X version)
193 | - [@psineur](https://github.com/psineur) Stepan Generalov
194 | - [@sergiocampama](https://github.com/sergiocampama) Sergio Campamá
195 | - [@stringbean](https://github.com/stringbean) Michael Stringer
196 | - [@tanis2000](https://github.com/tanis2000) Valerio Santinelli
197 | - [@drewburch](https://github.com/drewburch) Andrew Burch
198 | - [@pj4533](https://github.com/pj4533) PJ Gray
199 | - [@xzeror](https://github.com/xzeror)
200 | - [@kelp404](https://github.com/kelp404)
201 | - [@peyton](https://github.com/peyton) Peyton Randolph
202 | - [@wangjinhua](https://github.com/wangjinhua)
203 |
--------------------------------------------------------------------------------
/Android/Example/src/com/fangjian/WebViewJavascriptBridge.java:
--------------------------------------------------------------------------------
1 | package com.fangjian;
2 | import android.app.Activity;
3 | import android.content.Context;
4 | import android.util.Log;
5 | import android.webkit.*;
6 | import android.widget.Toast;
7 | import org.json.JSONObject;
8 |
9 | import com.example.WebViewJavascriptBridgeExample.R;
10 |
11 | import java.io.IOException;
12 | import java.io.InputStream;
13 | import java.util.HashMap;
14 | import java.util.Map;
15 | import java.util.Scanner;
16 |
17 | /**
18 | * Created with IntelliJ IDEA.
19 | * implements Serializable in case of javascript interface will be removed in obfuscated code.
20 | *
21 | * User: jack_fang
22 | * Date: 13-8-15
23 | * Time: 下午6:08
24 | */
25 | public class WebViewJavascriptBridge implements Serializable {
26 |
27 | WebView mWebView;
28 | Activity mContext;
29 | WVJBHandler _messageHandler;
30 | Map _messageHandlers;
31 | Map _responseCallbacks;
32 | long _uniqueId;
33 |
34 | public WebViewJavascriptBridge(Activity context,WebView webview,WVJBHandler handler) {
35 | this.mContext=context;
36 | this.mWebView=webview;
37 | this._messageHandler=handler;
38 | _messageHandlers=new HashMap();
39 | _responseCallbacks=new HashMap();
40 | _uniqueId=0;
41 | WebSettings webSettings = mWebView.getSettings();
42 | webSettings.setJavaScriptEnabled(true);
43 | mWebView.addJavascriptInterface(this, "_WebViewJavascriptBridge");
44 | mWebView.setWebViewClient(new MyWebViewClient());
45 | mWebView.setWebChromeClient(new MyWebChromeClient()); //optional, for show console and alert
46 | }
47 |
48 |
49 | private void loadWebViewJavascriptBridgeJs(WebView webView) {
50 | InputStream is=mContext.getResources().openRawResource(R.raw.webviewjavascriptbridge);
51 | String script=convertStreamToString(is);
52 | webView.loadUrl("javascript:"+script);
53 |
54 | }
55 |
56 | public static String convertStreamToString(java.io.InputStream is) {
57 | String s="";
58 | try{
59 | Scanner scanner = new Scanner(is, "UTF-8").useDelimiter("\\A");
60 | if (scanner.hasNext()) s= scanner.next();
61 | is.close();
62 | } catch (IOException e) {
63 | e.printStackTrace();
64 | }
65 | return s;
66 | }
67 |
68 | private class MyWebViewClient extends WebViewClient {
69 | @Override
70 | public void onPageFinished(WebView webView, String url) {
71 | Log.d("test", "onPageFinished");
72 | loadWebViewJavascriptBridgeJs(webView);
73 | }
74 | }
75 |
76 | private class MyWebChromeClient extends WebChromeClient {
77 | @Override
78 | public boolean onConsoleMessage(ConsoleMessage cm) {
79 | Log.d("test", cm.message()
80 | +" line:"+ cm.lineNumber()
81 | );
82 | return true;
83 | }
84 |
85 | @Override
86 | public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
87 | // if don't cancel the alert, webview after onJsAlert not responding taps
88 | // you can check this :
89 | // http://stackoverflow.com/questions/15892644/android-webview-after-onjsalert-not-responding-taps
90 | result.cancel();
91 | Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show();
92 | return true;
93 | }
94 | }
95 |
96 | public interface WVJBHandler{
97 | public void handle(String data,WVJBResponseCallback jsCallback);
98 | }
99 |
100 | public interface WVJBResponseCallback{
101 | public void callback(String data);
102 | }
103 |
104 | public void registerHandler(String handlerName,WVJBHandler handler) {
105 | _messageHandlers.put(handlerName,handler);
106 | }
107 |
108 | private class CallbackJs implements WVJBResponseCallback{
109 | private final String callbackIdJs;
110 |
111 | public CallbackJs(String callbackIdJs){
112 | this.callbackIdJs=callbackIdJs;
113 | }
114 | @Override
115 | public void callback(String data) {
116 | _callbackJs(callbackIdJs,data);
117 | }
118 | }
119 |
120 |
121 | private void _callbackJs(String callbackIdJs,String data) {
122 | //TODO: CALL js to call back;
123 | Map message=new HashMap();
124 | message.put("responseId",callbackIdJs);
125 | message.put("responseData",data);
126 | _dispatchMessage(message);
127 | }
128 |
129 | @JavascriptInterface
130 | public void _handleMessageFromJs(String data,String responseId,
131 | String responseData,String callbackId,String handlerName){
132 | if (null!=responseId) {
133 | WVJBResponseCallback responseCallback = _responseCallbacks.get(responseId);
134 | responseCallback.callback(responseData);
135 | _responseCallbacks.remove(responseId);
136 | } else {
137 | WVJBResponseCallback responseCallback = null;
138 | if (null!=callbackId) {
139 | responseCallback=new CallbackJs(callbackId);
140 | }
141 | WVJBHandler handler;
142 | if (null!=handlerName) {
143 | handler = _messageHandlers.get(handlerName);
144 | if (null==handler) {
145 | Log.e("test","WVJB Warning: No handler for "+handlerName);
146 | return ;
147 | }
148 | } else {
149 | handler = _messageHandler;
150 | }
151 | try {
152 | mContext.runOnUiThread(new Runnable(){
153 | @Override
154 | public void run() {
155 | handler.handle(data, responseCallback);
156 | }
157 | });
158 | }catch (Exception exception) {
159 | Log.e("test","WebViewJavascriptBridge: WARNING: java handler threw. "+exception.getMessage());
160 | }
161 | }
162 | }
163 |
164 | public void send(String data) {
165 | send(data,null);
166 | }
167 |
168 | public void send(String data ,WVJBResponseCallback responseCallback) {
169 | _sendData(data,responseCallback,null);
170 | }
171 |
172 | private void _sendData(String data,WVJBResponseCallback responseCallback,String handlerName){
173 | Map message=new HashMap();
174 | message.put("data",data);
175 | if (null!=responseCallback) {
176 | String callbackId = "java_cb_"+ (++_uniqueId);
177 | _responseCallbacks.put(callbackId,responseCallback);
178 | message.put("callbackId",callbackId);
179 | }
180 | if (null!=handlerName) {
181 | message.put("handlerName", handlerName);
182 | }
183 | _dispatchMessage(message);
184 | }
185 |
186 | private void _dispatchMessage(Map message){
187 | String messageJSON = new JSONObject(message).toString();
188 | Log.d("test","sending:"+messageJSON);
189 | final String javascriptCommand =
190 | String.format("javascript:WebViewJavascriptBridge._handleMessageFromJava('%s');",doubleEscapeString(messageJSON));
191 | mContext.runOnUiThread(new Runnable(){
192 | @Override
193 | public void run() {
194 | mWebView.loadUrl(javascriptCommand);
195 | }
196 | });
197 | }
198 |
199 |
200 | public void callHandler(String handlerName) {
201 | callHandler(handlerName, null, null);
202 | }
203 |
204 | public void callHandler(String handlerName,String data) {
205 | callHandler(handlerName, data,null);
206 | }
207 |
208 | public void callHandler(String handlerName,String data,WVJBResponseCallback responseCallback){
209 | _sendData(data, responseCallback,handlerName);
210 | }
211 |
212 | /*
213 | * you must escape the char \ and char ", or you will not recevie a correct json object in
214 | * your javascript which will cause a exception in chrome.
215 | *
216 | * please check this and you will know why.
217 | * http://stackoverflow.com/questions/5569794/escape-nsstring-for-javascript-input
218 | * http://www.json.org/
219 | */
220 | private String doubleEscapeString(String javascript) {
221 | String result;
222 | result = javascript.replace("\\", "\\\\");
223 | result = result.replace("\"", "\\\"");
224 | result = result.replace("\'", "\\\'");
225 | result = result.replace("\n", "\\n");
226 | result = result.replace("\r", "\\r");
227 | result = result.replace("\f", "\\f");
228 | return result;
229 | }
230 |
231 | }
232 |
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/src/com/fangjian/WebViewJavascriptBridge.java:
--------------------------------------------------------------------------------
1 | package com.fangjian;
2 | import android.app.Activity;
3 | import android.content.Context;
4 | import android.util.Log;
5 | import android.webkit.*;
6 | import android.widget.Toast;
7 | import org.json.JSONObject;
8 |
9 | import com.example.WebViewJavascriptBridgeExample.R;
10 |
11 | import java.io.IOException;
12 | import java.io.InputStream;
13 | import java.util.HashMap;
14 | import java.util.Map;
15 | import java.util.Scanner;
16 |
17 | /**
18 | * Created with IntelliJ IDEA.
19 | * implements Serializable in case of javascript interface will be removed in obfuscated code.
20 | *
21 | * User: jack_fang
22 | * Date: 13-8-15
23 | * Time: 下午6:08
24 | */
25 | public class WebViewJavascriptBridge implements Serializable {
26 | WebView mWebView;
27 | Activity mContext;
28 | WVJBHandler _messageHandler;
29 | Map _messageHandlers;
30 | Map _responseCallbacks;
31 | long _uniqueId;
32 |
33 | public WebViewJavascriptBridge(Activity context,WebView webview,WVJBHandler handler) {
34 | this.mContext=context;
35 | this.mWebView=webview;
36 | this._messageHandler=handler;
37 | _messageHandlers=new HashMap();
38 | _responseCallbacks=new HashMap();
39 | _uniqueId=0;
40 | WebSettings webSettings = mWebView.getSettings();
41 | webSettings.setJavaScriptEnabled(true);
42 | mWebView.addJavascriptInterface(this, "_WebViewJavascriptBridge");
43 | mWebView.setWebViewClient(new MyWebViewClient());
44 | mWebView.setWebChromeClient(new MyWebChromeClient()); //optional, for show console and alert
45 | }
46 |
47 |
48 | private void loadWebViewJavascriptBridgeJs(WebView webView) {
49 | InputStream is=mContext.getResources().openRawResource(R.raw.webviewjavascriptbridge);
50 | String script=convertStreamToString(is);
51 | webView.loadUrl("javascript:"+script);
52 |
53 | }
54 |
55 | public static String convertStreamToString(java.io.InputStream is) {
56 | String s="";
57 | try{
58 | Scanner scanner = new Scanner(is, "UTF-8").useDelimiter("\\A");
59 | if (scanner.hasNext()) s= scanner.next();
60 | is.close();
61 | } catch (IOException e) {
62 | e.printStackTrace();
63 | }
64 | return s;
65 | }
66 |
67 | private class MyWebViewClient extends WebViewClient {
68 | @Override
69 | public void onPageFinished(WebView webView, String url) {
70 | Log.d("test", "onPageFinished");
71 | loadWebViewJavascriptBridgeJs(webView);
72 | }
73 | }
74 |
75 | private class MyWebChromeClient extends WebChromeClient {
76 | @Override
77 | public boolean onConsoleMessage(ConsoleMessage cm) {
78 | Log.d("test", cm.message()
79 | +" line:"+ cm.lineNumber()
80 | );
81 | return true;
82 | }
83 |
84 | @Override
85 | public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
86 | // if don't cancel the alert, webview after onJsAlert not responding taps
87 | // you can check this :
88 | // http://stackoverflow.com/questions/15892644/android-webview-after-onjsalert-not-responding-taps
89 | result.cancel();
90 | Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show();
91 | return true;
92 | }
93 | }
94 |
95 | public interface WVJBHandler{
96 | public void handle(String data,WVJBResponseCallback jsCallback);
97 | }
98 |
99 | public interface WVJBResponseCallback{
100 | public void callback(String data);
101 | }
102 |
103 | public void registerHandler(String handlerName,WVJBHandler handler) {
104 | _messageHandlers.put(handlerName,handler);
105 | }
106 |
107 | private class CallbackJs implements WVJBResponseCallback{
108 | private final String callbackIdJs;
109 |
110 | public CallbackJs(String callbackIdJs){
111 | this.callbackIdJs=callbackIdJs;
112 | }
113 | @Override
114 | public void callback(String data) {
115 | _callbackJs(callbackIdJs,data);
116 | }
117 | }
118 |
119 |
120 | private void _callbackJs(String callbackIdJs,String data) {
121 | //TODO: CALL js to call back;
122 | Map message=new HashMap();
123 | message.put("responseId",callbackIdJs);
124 | message.put("responseData",data);
125 | _dispatchMessage(message);
126 | }
127 |
128 | @JavascriptInterface
129 | public void _handleMessageFromJs(String data,String responseId,
130 | String responseData,String callbackId,String handlerName){
131 | if (null!=responseId) {
132 | WVJBResponseCallback responseCallback = _responseCallbacks.get(responseId);
133 | responseCallback.callback(responseData);
134 | _responseCallbacks.remove(responseId);
135 | } else {
136 | WVJBResponseCallback responseCallback = null;
137 | if (null!=callbackId) {
138 | responseCallback=new CallbackJs(callbackId);
139 | }
140 | WVJBHandler handler;
141 | if (null!=handlerName) {
142 | handler = _messageHandlers.get(handlerName);
143 | if (null==handler) {
144 | Log.e("test","WVJB Warning: No handler for "+handlerName);
145 | return ;
146 | }
147 | } else {
148 | handler = _messageHandler;
149 | }
150 | try {
151 | mContext.runOnUiThread(new Runnable(){
152 | @Override
153 | public void run() {
154 | handler.handle(data, responseCallback);
155 | }
156 | });
157 | }catch (Exception exception) {
158 | Log.e("test","WebViewJavascriptBridge: WARNING: java handler threw. "+exception.getMessage());
159 | }
160 | }
161 | }
162 |
163 | public void send(String data) {
164 | send(data,null);
165 | }
166 |
167 | public void send(String data ,WVJBResponseCallback responseCallback) {
168 | _sendData(data,responseCallback,null);
169 | }
170 |
171 | private void _sendData(String data,WVJBResponseCallback responseCallback,String handlerName){
172 | Map message=new HashMap();
173 | message.put("data",data);
174 | if (null!=responseCallback) {
175 | String callbackId = "java_cb_"+ (++_uniqueId);
176 | _responseCallbacks.put(callbackId,responseCallback);
177 | message.put("callbackId",callbackId);
178 | }
179 | if (null!=handlerName) {
180 | message.put("handlerName", handlerName);
181 | }
182 | _dispatchMessage(message);
183 | }
184 |
185 | private void _dispatchMessage(Map message){
186 | String messageJSON = new JSONObject(message).toString();
187 | Log.d("test","sending:"+messageJSON);
188 | final String javascriptCommand =
189 | String.format("javascript:WebViewJavascriptBridge._handleMessageFromJava('%s');",doubleEscapeString(messageJSON));
190 | mContext.runOnUiThread(new Runnable(){
191 | @Override
192 | public void run() {
193 | mWebView.loadUrl(javascriptCommand);
194 | }
195 | });
196 | }
197 |
198 |
199 | public void callHandler(String handlerName) {
200 | callHandler(handlerName, null, null);
201 | }
202 |
203 | public void callHandler(String handlerName,String data) {
204 | callHandler(handlerName, data,null);
205 | }
206 |
207 | public void callHandler(String handlerName,String data,WVJBResponseCallback responseCallback){
208 | _sendData(data, responseCallback,handlerName);
209 | }
210 |
211 | /*
212 | * you must escape the char \ and char ", or you will not recevie a correct json object in
213 | * your javascript which will cause a exception in chrome.
214 | *
215 | * please check this and you will know why.
216 | * http://stackoverflow.com/questions/5569794/escape-nsstring-for-javascript-input
217 | * http://www.json.org/
218 | */
219 | private String doubleEscapeString(String javascript) {
220 | String result;
221 | result = javascript.replace("\\", "\\\\");
222 | result = result.replace("\"", "\\\"");
223 | result = result.replace("\'", "\\\'");
224 | result = result.replace("\n", "\\n");
225 | result = result.replace("\r", "\\r");
226 | result = result.replace("\f", "\\f");
227 | return result;
228 | }
229 |
230 | }
231 |
--------------------------------------------------------------------------------
/Android/WebViewJavascriptBridge/src/com/fangjian/WebViewJavascriptBridge.java:
--------------------------------------------------------------------------------
1 | package com.fangjian;
2 | import android.app.Activity;
3 | import android.content.Context;
4 | import android.util.Log;
5 | import android.webkit.*;
6 | import android.widget.Toast;
7 | import org.json.JSONObject;
8 |
9 | import com.example.WebViewJavascriptBridgeExample.R;
10 |
11 | import java.io.IOException;
12 | import java.io.InputStream;
13 | import java.util.HashMap;
14 | import java.util.Map;
15 | import java.util.Scanner;
16 |
17 | /**
18 | * Created with IntelliJ IDEA.
19 | * implements Serializable in case of javascript interface will be removed in obfuscated code.
20 | *
21 | * User: jack_fang
22 | * Date: 13-8-15
23 | * Time: 下午6:08
24 | */
25 | public class WebViewJavascriptBridge implements Serializable {
26 |
27 | WebView mWebView;
28 | Activity mContext;
29 | WVJBHandler _messageHandler;
30 | Map _messageHandlers;
31 | Map _responseCallbacks;
32 | long _uniqueId;
33 |
34 | public WebViewJavascriptBridge(Activity context,WebView webview,WVJBHandler handler) {
35 | this.mContext=context;
36 | this.mWebView=webview;
37 | this._messageHandler=handler;
38 | _messageHandlers=new HashMap();
39 | _responseCallbacks=new HashMap();
40 | _uniqueId=0;
41 | WebSettings webSettings = mWebView.getSettings();
42 | webSettings.setJavaScriptEnabled(true);
43 | mWebView.addJavascriptInterface(this, "_WebViewJavascriptBridge");
44 | mWebView.setWebViewClient(new MyWebViewClient());
45 | mWebView.setWebChromeClient(new MyWebChromeClient()); //optional, for show console and alert
46 | }
47 |
48 |
49 | private void loadWebViewJavascriptBridgeJs(WebView webView) {
50 | InputStream is=mContext.getResources().openRawResource(R.raw.webviewjavascriptbridge);
51 | String script=convertStreamToString(is);
52 |
53 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
54 | webView.evaluateJavascript("javascript:" + script, new ValueCallback() {
55 | @Override
56 | public void onReceiveValue(String value) {
57 | //TODO
58 | }
59 | });
60 | } else {
61 | webView.loadUrl("javascript:" + script);
62 | }
63 | }
64 |
65 | public static String convertStreamToString(java.io.InputStream is) {
66 | String s="";
67 | try{
68 | Scanner scanner = new Scanner(is, "UTF-8").useDelimiter("\\A");
69 | if (scanner.hasNext()) s= scanner.next();
70 | is.close();
71 | } catch (IOException e) {
72 | e.printStackTrace();
73 | }
74 | return s;
75 | }
76 |
77 | private class MyWebViewClient extends WebViewClient {
78 | @Override
79 | public void onPageFinished(WebView webView, String url) {
80 | Log.d("test", "onPageFinished");
81 | loadWebViewJavascriptBridgeJs(webView);
82 | }
83 | }
84 |
85 | private class MyWebChromeClient extends WebChromeClient {
86 | @Override
87 | public boolean onConsoleMessage(ConsoleMessage cm) {
88 | Log.d("test", cm.message()
89 | +" line:"+ cm.lineNumber()
90 | );
91 | return true;
92 | }
93 |
94 | @Override
95 | public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
96 | // if don't cancel the alert, webview after onJsAlert not responding taps
97 | // you can check this :
98 | // http://stackoverflow.com/questions/15892644/android-webview-after-onjsalert-not-responding-taps
99 | result.cancel();
100 | Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show();
101 | return true;
102 | }
103 | }
104 |
105 | public interface WVJBHandler{
106 | public void handle(String data,WVJBResponseCallback jsCallback);
107 | }
108 |
109 | public interface WVJBResponseCallback{
110 | public void callback(String data);
111 | }
112 |
113 | public void registerHandler(String handlerName,WVJBHandler handler) {
114 | _messageHandlers.put(handlerName,handler);
115 | }
116 |
117 | private class CallbackJs implements WVJBResponseCallback{
118 | private final String callbackIdJs;
119 |
120 | public CallbackJs(String callbackIdJs){
121 | this.callbackIdJs=callbackIdJs;
122 | }
123 | @Override
124 | public void callback(String data) {
125 | _callbackJs(callbackIdJs,data);
126 | }
127 | }
128 |
129 |
130 | private void _callbackJs(String callbackIdJs,String data) {
131 | //TODO: CALL js to call back;
132 | Map message=new HashMap();
133 | message.put("responseId",callbackIdJs);
134 | message.put("responseData",data);
135 | _dispatchMessage(message);
136 | }
137 |
138 | @JavascriptInterface
139 | public void _handleMessageFromJs(String data,String responseId,
140 | String responseData,String callbackId,String handlerName){
141 | if (null!=responseId) {
142 | WVJBResponseCallback responseCallback = _responseCallbacks.get(responseId);
143 | responseCallback.callback(responseData);
144 | _responseCallbacks.remove(responseId);
145 | } else {
146 | WVJBResponseCallback responseCallback = null;
147 | if (null!=callbackId) {
148 | responseCallback=new CallbackJs(callbackId);
149 | }
150 | WVJBHandler handler;
151 | if (null!=handlerName) {
152 | handler = _messageHandlers.get(handlerName);
153 | if (null==handler) {
154 | Log.e("test","WVJB Warning: No handler for "+handlerName);
155 | return ;
156 | }
157 | } else {
158 | handler = _messageHandler;
159 | }
160 | try {
161 | mContext.runOnUiThread(new Runnable(){
162 | @Override
163 | public void run() {
164 | handler.handle(data, responseCallback);
165 | }
166 | });
167 | }catch (Exception exception) {
168 | Log.e("test","WebViewJavascriptBridge: WARNING: java handler threw. "+exception.getMessage());
169 | }
170 | }
171 | }
172 |
173 | public void send(String data) {
174 | send(data,null);
175 | }
176 |
177 | public void send(String data ,WVJBResponseCallback responseCallback) {
178 | _sendData(data,responseCallback,null);
179 | }
180 |
181 | private void _sendData(String data,WVJBResponseCallback responseCallback,String handlerName){
182 | Map message=new HashMap();
183 | message.put("data",data);
184 | if (null!=responseCallback) {
185 | String callbackId = "java_cb_"+ (++_uniqueId);
186 | _responseCallbacks.put(callbackId,responseCallback);
187 | message.put("callbackId",callbackId);
188 | }
189 | if (null!=handlerName) {
190 | message.put("handlerName", handlerName);
191 | }
192 | _dispatchMessage(message);
193 | }
194 |
195 | private void _dispatchMessage(Map message){
196 | String messageJSON = new JSONObject(message).toString();
197 | Log.d("test","sending:"+messageJSON);
198 | final String javascriptCommand =
199 | String.format("javascript:WebViewJavascriptBridge._handleMessageFromJava('%s');",doubleEscapeString(messageJSON));
200 | mContext.runOnUiThread(new Runnable(){
201 | @Override
202 | public void run() {
203 | mWebView.loadUrl(javascriptCommand);
204 | }
205 | });
206 | }
207 |
208 |
209 | public void callHandler(String handlerName) {
210 | callHandler(handlerName, null, null);
211 | }
212 |
213 | public void callHandler(String handlerName,String data) {
214 | callHandler(handlerName, data,null);
215 | }
216 |
217 | public void callHandler(String handlerName,String data,WVJBResponseCallback responseCallback){
218 | _sendData(data, responseCallback,handlerName);
219 | }
220 |
221 | /*
222 | * you must escape the char \ and char ", or you will not recevie a correct json object in
223 | * your javascript which will cause a exception in chrome.
224 | *
225 | * please check this and you will know why.
226 | * http://stackoverflow.com/questions/5569794/escape-nsstring-for-javascript-input
227 | * http://www.json.org/
228 | */
229 | private String doubleEscapeString(String javascript) {
230 | String result;
231 | result = javascript.replace("\\", "\\\\");
232 | result = result.replace("\"", "\\\"");
233 | result = result.replace("\'", "\\\'");
234 | result = result.replace("\n", "\\n");
235 | result = result.replace("\r", "\\r");
236 | result = result.replace("\f", "\\f");
237 | return result;
238 | }
239 |
240 | }
241 |
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/assets/map/leaflet-0.7.2/leaflet.css:
--------------------------------------------------------------------------------
1 | /* required styles */
2 |
3 | .leaflet-map-pane,
4 | .leaflet-tile,
5 | .leaflet-marker-icon,
6 | .leaflet-marker-shadow,
7 | .leaflet-tile-pane,
8 | .leaflet-tile-container,
9 | .leaflet-overlay-pane,
10 | .leaflet-shadow-pane,
11 | .leaflet-marker-pane,
12 | .leaflet-popup-pane,
13 | .leaflet-overlay-pane svg,
14 | .leaflet-zoom-box,
15 | .leaflet-image-layer,
16 | .leaflet-layer {
17 | position: absolute;
18 | left: 0;
19 | top: 0;
20 | }
21 | .leaflet-container {
22 | overflow: hidden;
23 | -ms-touch-action: none;
24 | }
25 | .leaflet-tile,
26 | .leaflet-marker-icon,
27 | .leaflet-marker-shadow {
28 | -webkit-user-select: none;
29 | -moz-user-select: none;
30 | user-select: none;
31 | -webkit-user-drag: none;
32 | }
33 | .leaflet-marker-icon,
34 | .leaflet-marker-shadow {
35 | display: block;
36 | }
37 | /* map is broken in FF if you have max-width: 100% on tiles */
38 | .leaflet-container img {
39 | max-width: none !important;
40 | }
41 | /* stupid Android 2 doesn't understand "max-width: none" properly */
42 | .leaflet-container img.leaflet-image-layer {
43 | max-width: 15000px !important;
44 | }
45 | .leaflet-tile {
46 | filter: inherit;
47 | visibility: hidden;
48 | }
49 | .leaflet-tile-loaded {
50 | visibility: inherit;
51 | }
52 | .leaflet-zoom-box {
53 | width: 0;
54 | height: 0;
55 | }
56 | /* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
57 | .leaflet-overlay-pane svg {
58 | -moz-user-select: none;
59 | }
60 |
61 | .leaflet-tile-pane { z-index: 2; }
62 | .leaflet-objects-pane { z-index: 3; }
63 | .leaflet-overlay-pane { z-index: 4; }
64 | .leaflet-shadow-pane { z-index: 5; }
65 | .leaflet-marker-pane { z-index: 6; }
66 | .leaflet-popup-pane { z-index: 7; }
67 |
68 | .leaflet-vml-shape {
69 | width: 1px;
70 | height: 1px;
71 | }
72 | .lvml {
73 | behavior: url(#default#VML);
74 | display: inline-block;
75 | position: absolute;
76 | }
77 |
78 |
79 | /* control positioning */
80 |
81 | .leaflet-control {
82 | position: relative;
83 | z-index: 7;
84 | pointer-events: auto;
85 | }
86 | .leaflet-top,
87 | .leaflet-bottom {
88 | position: absolute;
89 | z-index: 1000;
90 | pointer-events: none;
91 | }
92 | .leaflet-top {
93 | top: 0;
94 | }
95 | .leaflet-right {
96 | right: 0;
97 | }
98 | .leaflet-bottom {
99 | bottom: 0;
100 | }
101 | .leaflet-left {
102 | left: 0;
103 | }
104 | .leaflet-control {
105 | float: left;
106 | clear: both;
107 | }
108 | .leaflet-right .leaflet-control {
109 | float: right;
110 | }
111 | .leaflet-top .leaflet-control {
112 | margin-top: 10px;
113 | }
114 | .leaflet-bottom .leaflet-control {
115 | margin-bottom: 10px;
116 | }
117 | .leaflet-left .leaflet-control {
118 | margin-left: 10px;
119 | }
120 | .leaflet-right .leaflet-control {
121 | margin-right: 10px;
122 | }
123 |
124 |
125 | /* zoom and fade animations */
126 |
127 | .leaflet-fade-anim .leaflet-tile,
128 | .leaflet-fade-anim .leaflet-popup {
129 | opacity: 0;
130 | -webkit-transition: opacity 0.2s linear;
131 | -moz-transition: opacity 0.2s linear;
132 | -o-transition: opacity 0.2s linear;
133 | transition: opacity 0.2s linear;
134 | }
135 | .leaflet-fade-anim .leaflet-tile-loaded,
136 | .leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
137 | opacity: 1;
138 | }
139 |
140 | .leaflet-zoom-anim .leaflet-zoom-animated {
141 | -webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
142 | -moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
143 | -o-transition: -o-transform 0.25s cubic-bezier(0,0,0.25,1);
144 | transition: transform 0.25s cubic-bezier(0,0,0.25,1);
145 | }
146 | .leaflet-zoom-anim .leaflet-tile,
147 | .leaflet-pan-anim .leaflet-tile,
148 | .leaflet-touching .leaflet-zoom-animated {
149 | -webkit-transition: none;
150 | -moz-transition: none;
151 | -o-transition: none;
152 | transition: none;
153 | }
154 |
155 | .leaflet-zoom-anim .leaflet-zoom-hide {
156 | visibility: hidden;
157 | }
158 |
159 |
160 | /* cursors */
161 |
162 | .leaflet-clickable {
163 | cursor: pointer;
164 | }
165 | .leaflet-container {
166 | cursor: -webkit-grab;
167 | cursor: -moz-grab;
168 | }
169 | .leaflet-popup-pane,
170 | .leaflet-control {
171 | cursor: auto;
172 | }
173 | .leaflet-dragging .leaflet-container,
174 | .leaflet-dragging .leaflet-clickable {
175 | cursor: move;
176 | cursor: -webkit-grabbing;
177 | cursor: -moz-grabbing;
178 | }
179 |
180 |
181 | /* visual tweaks */
182 |
183 | .leaflet-container {
184 | background: #ddd;
185 | outline: 0;
186 | }
187 | .leaflet-container a {
188 | color: #0078A8;
189 | }
190 | .leaflet-container a.leaflet-active {
191 | outline: 2px solid orange;
192 | }
193 | .leaflet-zoom-box {
194 | border: 2px dotted #38f;
195 | background: rgba(255,255,255,0.5);
196 | }
197 |
198 |
199 | /* general typography */
200 | .leaflet-container {
201 | font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif;
202 | }
203 |
204 |
205 | /* general toolbar styles */
206 |
207 | .leaflet-bar {
208 | box-shadow: 0 1px 5px rgba(0,0,0,0.65);
209 | border-radius: 4px;
210 | }
211 | .leaflet-bar a,
212 | .leaflet-bar a:hover {
213 | background-color: #fff;
214 | border-bottom: 1px solid #ccc;
215 | width: 26px;
216 | height: 26px;
217 | line-height: 26px;
218 | display: block;
219 | text-align: center;
220 | text-decoration: none;
221 | color: black;
222 | }
223 | .leaflet-bar a,
224 | .leaflet-control-layers-toggle {
225 | background-position: 50% 50%;
226 | background-repeat: no-repeat;
227 | display: block;
228 | }
229 | .leaflet-bar a:hover {
230 | background-color: #f4f4f4;
231 | }
232 | .leaflet-bar a:first-child {
233 | border-top-left-radius: 4px;
234 | border-top-right-radius: 4px;
235 | }
236 | .leaflet-bar a:last-child {
237 | border-bottom-left-radius: 4px;
238 | border-bottom-right-radius: 4px;
239 | border-bottom: none;
240 | }
241 | .leaflet-bar a.leaflet-disabled {
242 | cursor: default;
243 | background-color: #f4f4f4;
244 | color: #bbb;
245 | }
246 |
247 | .leaflet-touch .leaflet-bar a {
248 | width: 30px;
249 | height: 30px;
250 | line-height: 30px;
251 | }
252 |
253 |
254 | /* zoom control */
255 |
256 | .leaflet-control-zoom-in,
257 | .leaflet-control-zoom-out {
258 | font: bold 18px 'Lucida Console', Monaco, monospace;
259 | text-indent: 1px;
260 | }
261 | .leaflet-control-zoom-out {
262 | font-size: 20px;
263 | }
264 |
265 | .leaflet-touch .leaflet-control-zoom-in {
266 | font-size: 22px;
267 | }
268 | .leaflet-touch .leaflet-control-zoom-out {
269 | font-size: 24px;
270 | }
271 |
272 |
273 | /* layers control */
274 |
275 | .leaflet-control-layers {
276 | box-shadow: 0 1px 5px rgba(0,0,0,0.4);
277 | background: #fff;
278 | border-radius: 5px;
279 | }
280 | .leaflet-control-layers-toggle {
281 | background-image: url(images/layers.png);
282 | width: 36px;
283 | height: 36px;
284 | }
285 | .leaflet-retina .leaflet-control-layers-toggle {
286 | background-image: url(images/layers-2x.png);
287 | background-size: 26px 26px;
288 | }
289 | .leaflet-touch .leaflet-control-layers-toggle {
290 | width: 44px;
291 | height: 44px;
292 | }
293 | .leaflet-control-layers .leaflet-control-layers-list,
294 | .leaflet-control-layers-expanded .leaflet-control-layers-toggle {
295 | display: none;
296 | }
297 | .leaflet-control-layers-expanded .leaflet-control-layers-list {
298 | display: block;
299 | position: relative;
300 | }
301 | .leaflet-control-layers-expanded {
302 | padding: 6px 10px 6px 6px;
303 | color: #333;
304 | background: #fff;
305 | }
306 | .leaflet-control-layers-selector {
307 | margin-top: 2px;
308 | position: relative;
309 | top: 1px;
310 | }
311 | .leaflet-control-layers label {
312 | display: block;
313 | }
314 | .leaflet-control-layers-separator {
315 | height: 0;
316 | border-top: 1px solid #ddd;
317 | margin: 5px -10px 5px -6px;
318 | }
319 |
320 |
321 | /* attribution and scale controls */
322 |
323 | .leaflet-container .leaflet-control-attribution {
324 | background: #fff;
325 | background: rgba(255, 255, 255, 0.7);
326 | margin: 0;
327 | }
328 | .leaflet-control-attribution,
329 | .leaflet-control-scale-line {
330 | padding: 0 5px;
331 | color: #333;
332 | }
333 | .leaflet-control-attribution a {
334 | text-decoration: none;
335 | }
336 | .leaflet-control-attribution a:hover {
337 | text-decoration: underline;
338 | }
339 | .leaflet-container .leaflet-control-attribution,
340 | .leaflet-container .leaflet-control-scale {
341 | font-size: 11px;
342 | }
343 | .leaflet-left .leaflet-control-scale {
344 | margin-left: 5px;
345 | }
346 | .leaflet-bottom .leaflet-control-scale {
347 | margin-bottom: 5px;
348 | }
349 | .leaflet-control-scale-line {
350 | border: 2px solid #777;
351 | border-top: none;
352 | line-height: 1.1;
353 | padding: 2px 5px 1px;
354 | font-size: 11px;
355 | white-space: nowrap;
356 | overflow: hidden;
357 | -moz-box-sizing: content-box;
358 | box-sizing: content-box;
359 |
360 | background: #fff;
361 | background: rgba(255, 255, 255, 0.5);
362 | }
363 | .leaflet-control-scale-line:not(:first-child) {
364 | border-top: 2px solid #777;
365 | border-bottom: none;
366 | margin-top: -2px;
367 | }
368 | .leaflet-control-scale-line:not(:first-child):not(:last-child) {
369 | border-bottom: 2px solid #777;
370 | }
371 |
372 | .leaflet-touch .leaflet-control-attribution,
373 | .leaflet-touch .leaflet-control-layers,
374 | .leaflet-touch .leaflet-bar {
375 | box-shadow: none;
376 | }
377 | .leaflet-touch .leaflet-control-layers,
378 | .leaflet-touch .leaflet-bar {
379 | border: 2px solid rgba(0,0,0,0.2);
380 | background-clip: padding-box;
381 | }
382 |
383 |
384 | /* popup */
385 |
386 | .leaflet-popup {
387 | position: absolute;
388 | text-align: center;
389 | }
390 | .leaflet-popup-content-wrapper {
391 | padding: 1px;
392 | text-align: left;
393 | border-radius: 12px;
394 | }
395 | .leaflet-popup-content {
396 | margin: 13px 19px;
397 | line-height: 1.4;
398 | }
399 | .leaflet-popup-content p {
400 | margin: 18px 0;
401 | }
402 | .leaflet-popup-tip-container {
403 | margin: 0 auto;
404 | width: 40px;
405 | height: 20px;
406 | position: relative;
407 | overflow: hidden;
408 | }
409 | .leaflet-popup-tip {
410 | width: 17px;
411 | height: 17px;
412 | padding: 1px;
413 |
414 | margin: -10px auto 0;
415 |
416 | -webkit-transform: rotate(45deg);
417 | -moz-transform: rotate(45deg);
418 | -ms-transform: rotate(45deg);
419 | -o-transform: rotate(45deg);
420 | transform: rotate(45deg);
421 | }
422 | .leaflet-popup-content-wrapper,
423 | .leaflet-popup-tip {
424 | background: white;
425 |
426 | box-shadow: 0 3px 14px rgba(0,0,0,0.4);
427 | }
428 | .leaflet-container a.leaflet-popup-close-button {
429 | position: absolute;
430 | top: 0;
431 | right: 0;
432 | padding: 4px 4px 0 0;
433 | text-align: center;
434 | width: 18px;
435 | height: 14px;
436 | font: 16px/14px Tahoma, Verdana, sans-serif;
437 | color: #c3c3c3;
438 | text-decoration: none;
439 | font-weight: bold;
440 | background: transparent;
441 | }
442 | .leaflet-container a.leaflet-popup-close-button:hover {
443 | color: #999;
444 | }
445 | .leaflet-popup-scrolled {
446 | overflow: auto;
447 | border-bottom: 1px solid #ddd;
448 | border-top: 1px solid #ddd;
449 | }
450 |
451 | .leaflet-oldie .leaflet-popup-content-wrapper {
452 | zoom: 1;
453 | }
454 | .leaflet-oldie .leaflet-popup-tip {
455 | width: 24px;
456 | margin: 0 auto;
457 |
458 | -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
459 | filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
460 | }
461 | .leaflet-oldie .leaflet-popup-tip-container {
462 | margin-top: -1px;
463 | }
464 |
465 | .leaflet-oldie .leaflet-control-zoom,
466 | .leaflet-oldie .leaflet-control-layers,
467 | .leaflet-oldie .leaflet-popup-content-wrapper,
468 | .leaflet-oldie .leaflet-popup-tip {
469 | border: 1px solid #999;
470 | }
471 |
472 |
473 | /* div icon */
474 |
475 | .leaflet-div-icon {
476 | background: #fff;
477 | border: 1px solid #666;
478 | }
479 |
--------------------------------------------------------------------------------
/IOS/Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 2C1562B5176B9F8400B4AE50 /* WebViewJavascriptBridge.js.txt in Resources */ = {isa = PBXBuildFile; fileRef = 2C1562B4176B9F8400B4AE50 /* WebViewJavascriptBridge.js.txt */; };
11 | 2C1562C0176BA63500B4AE50 /* WebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C1562A9176B9F6200B4AE50 /* WebViewJavascriptBridge.m */; };
12 | 2CA045BF17117439006DEE8B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2CA045B717117439006DEE8B /* InfoPlist.strings */; };
13 | 2CA045C217117439006DEE8B /* ExampleAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA045BD17117439006DEE8B /* ExampleAppDelegate.m */; };
14 | 2CA045C317117439006DEE8B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA045BE17117439006DEE8B /* main.m */; };
15 | 2CA0465C1711AC8E006DEE8B /* ExampleApp.html in Resources */ = {isa = PBXBuildFile; fileRef = 2CA0465B1711AC8D006DEE8B /* ExampleApp.html */; };
16 | 2CAB869B1727684300BD9ED1 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 2CAB869A1727684300BD9ED1 /* Default-568h@2x.png */; };
17 | 2CEB3EC01602563600548120 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CEB3EBF1602563600548120 /* UIKit.framework */; };
18 | 2CEB3EC21602563600548120 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CEB3EC11602563600548120 /* Foundation.framework */; };
19 | 2CEB3EC41602563600548120 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CEB3EC31602563600548120 /* CoreGraphics.framework */; };
20 | /* End PBXBuildFile section */
21 |
22 | /* Begin PBXFileReference section */
23 | 2C1562A8176B9F6200B4AE50 /* WebViewJavascriptBridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge.h; sourceTree = ""; };
24 | 2C1562A9176B9F6200B4AE50 /* WebViewJavascriptBridge.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge.m; sourceTree = ""; };
25 | 2C1562B4176B9F8400B4AE50 /* WebViewJavascriptBridge.js.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebViewJavascriptBridge.js.txt; sourceTree = ""; };
26 | 2CA045B817117439006DEE8B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
27 | 2CA045B917117439006DEE8B /* ExampleApp-iOS-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "ExampleApp-iOS-Info.plist"; sourceTree = ""; };
28 | 2CA045BA17117439006DEE8B /* ExampleApp-iOS-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ExampleApp-iOS-Prefix.pch"; sourceTree = ""; };
29 | 2CA045BC17117439006DEE8B /* ExampleAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExampleAppDelegate.h; sourceTree = ""; };
30 | 2CA045BD17117439006DEE8B /* ExampleAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExampleAppDelegate.m; sourceTree = ""; };
31 | 2CA045BE17117439006DEE8B /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
32 | 2CA0465B1711AC8D006DEE8B /* ExampleApp.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = ExampleApp.html; sourceTree = SOURCE_ROOT; };
33 | 2CAB869A1727684300BD9ED1 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default-568h@2x.png"; path = "ExampleApp-iOS/Default-568h@2x.png"; sourceTree = ""; };
34 | 2CEB3EBB1602563600548120 /* ExampleApp-iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ExampleApp-iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
35 | 2CEB3EBF1602563600548120 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
36 | 2CEB3EC11602563600548120 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
37 | 2CEB3EC31602563600548120 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
38 | /* End PBXFileReference section */
39 |
40 | /* Begin PBXFrameworksBuildPhase section */
41 | 2CEB3EB81602563600548120 /* Frameworks */ = {
42 | isa = PBXFrameworksBuildPhase;
43 | buildActionMask = 2147483647;
44 | files = (
45 | 2CEB3EC01602563600548120 /* UIKit.framework in Frameworks */,
46 | 2CEB3EC21602563600548120 /* Foundation.framework in Frameworks */,
47 | 2CEB3EC41602563600548120 /* CoreGraphics.framework in Frameworks */,
48 | );
49 | runOnlyForDeploymentPostprocessing = 0;
50 | };
51 | /* End PBXFrameworksBuildPhase section */
52 |
53 | /* Begin PBXGroup section */
54 | 2C1562A7176B9F5400B4AE50 /* WebViewJavascriptBridge */ = {
55 | isa = PBXGroup;
56 | children = (
57 | 2C1562B4176B9F8400B4AE50 /* WebViewJavascriptBridge.js.txt */,
58 | 2C1562A8176B9F6200B4AE50 /* WebViewJavascriptBridge.h */,
59 | 2C1562A9176B9F6200B4AE50 /* WebViewJavascriptBridge.m */,
60 | );
61 | name = WebViewJavascriptBridge;
62 | path = ../../WebViewJavascriptBridge;
63 | sourceTree = "";
64 | };
65 | 2CA045B617117439006DEE8B /* ExampleApp-iOS */ = {
66 | isa = PBXGroup;
67 | children = (
68 | 2CA0465B1711AC8D006DEE8B /* ExampleApp.html */,
69 | 2CA045BC17117439006DEE8B /* ExampleAppDelegate.h */,
70 | 2CA045BD17117439006DEE8B /* ExampleAppDelegate.m */,
71 | 2C1562A7176B9F5400B4AE50 /* WebViewJavascriptBridge */,
72 | 2CA046211711A94E006DEE8B /* Supporting Files */,
73 | );
74 | path = "ExampleApp-iOS";
75 | sourceTree = "";
76 | };
77 | 2CA046211711A94E006DEE8B /* Supporting Files */ = {
78 | isa = PBXGroup;
79 | children = (
80 | 2CA045B717117439006DEE8B /* InfoPlist.strings */,
81 | 2CA045B917117439006DEE8B /* ExampleApp-iOS-Info.plist */,
82 | 2CA045BA17117439006DEE8B /* ExampleApp-iOS-Prefix.pch */,
83 | 2CA045BE17117439006DEE8B /* main.m */,
84 | );
85 | name = "Supporting Files";
86 | sourceTree = "";
87 | };
88 | 2CEB3EB01602563600548120 = {
89 | isa = PBXGroup;
90 | children = (
91 | 2CAB869A1727684300BD9ED1 /* Default-568h@2x.png */,
92 | 2CA045B617117439006DEE8B /* ExampleApp-iOS */,
93 | 2CEB3EBE1602563600548120 /* Frameworks */,
94 | 2CEB3EBC1602563600548120 /* Products */,
95 | );
96 | sourceTree = "";
97 | };
98 | 2CEB3EBC1602563600548120 /* Products */ = {
99 | isa = PBXGroup;
100 | children = (
101 | 2CEB3EBB1602563600548120 /* ExampleApp-iOS.app */,
102 | );
103 | name = Products;
104 | sourceTree = "";
105 | };
106 | 2CEB3EBE1602563600548120 /* Frameworks */ = {
107 | isa = PBXGroup;
108 | children = (
109 | 2CEB3EBF1602563600548120 /* UIKit.framework */,
110 | 2CEB3EC11602563600548120 /* Foundation.framework */,
111 | 2CEB3EC31602563600548120 /* CoreGraphics.framework */,
112 | );
113 | name = Frameworks;
114 | sourceTree = "";
115 | };
116 | /* End PBXGroup section */
117 |
118 | /* Begin PBXNativeTarget section */
119 | 2CEB3EBA1602563600548120 /* ExampleApp-iOS */ = {
120 | isa = PBXNativeTarget;
121 | buildConfigurationList = 2CEB3ED31602563600548120 /* Build configuration list for PBXNativeTarget "ExampleApp-iOS" */;
122 | buildPhases = (
123 | 2CEB3EB71602563600548120 /* Sources */,
124 | 2CEB3EB81602563600548120 /* Frameworks */,
125 | 2CEB3EB91602563600548120 /* Resources */,
126 | );
127 | buildRules = (
128 | );
129 | dependencies = (
130 | );
131 | name = "ExampleApp-iOS";
132 | productName = ExampleApp;
133 | productReference = 2CEB3EBB1602563600548120 /* ExampleApp-iOS.app */;
134 | productType = "com.apple.product-type.application";
135 | };
136 | /* End PBXNativeTarget section */
137 |
138 | /* Begin PBXProject section */
139 | 2CEB3EB21602563600548120 /* Project object */ = {
140 | isa = PBXProject;
141 | attributes = {
142 | LastUpgradeCheck = 0450;
143 | ORGANIZATIONNAME = "Marcus Westin";
144 | };
145 | buildConfigurationList = 2CEB3EB51602563600548120 /* Build configuration list for PBXProject "ExampleApp-iOS" */;
146 | compatibilityVersion = "Xcode 3.2";
147 | developmentRegion = English;
148 | hasScannedForEncodings = 0;
149 | knownRegions = (
150 | en,
151 | );
152 | mainGroup = 2CEB3EB01602563600548120;
153 | productRefGroup = 2CEB3EBC1602563600548120 /* Products */;
154 | projectDirPath = "";
155 | projectRoot = "";
156 | targets = (
157 | 2CEB3EBA1602563600548120 /* ExampleApp-iOS */,
158 | );
159 | };
160 | /* End PBXProject section */
161 |
162 | /* Begin PBXResourcesBuildPhase section */
163 | 2CEB3EB91602563600548120 /* Resources */ = {
164 | isa = PBXResourcesBuildPhase;
165 | buildActionMask = 2147483647;
166 | files = (
167 | 2C1562B5176B9F8400B4AE50 /* WebViewJavascriptBridge.js.txt in Resources */,
168 | 2CA045BF17117439006DEE8B /* InfoPlist.strings in Resources */,
169 | 2CA0465C1711AC8E006DEE8B /* ExampleApp.html in Resources */,
170 | 2CAB869B1727684300BD9ED1 /* Default-568h@2x.png in Resources */,
171 | );
172 | runOnlyForDeploymentPostprocessing = 0;
173 | };
174 | /* End PBXResourcesBuildPhase section */
175 |
176 | /* Begin PBXSourcesBuildPhase section */
177 | 2CEB3EB71602563600548120 /* Sources */ = {
178 | isa = PBXSourcesBuildPhase;
179 | buildActionMask = 2147483647;
180 | files = (
181 | 2C1562C0176BA63500B4AE50 /* WebViewJavascriptBridge.m in Sources */,
182 | 2CA045C217117439006DEE8B /* ExampleAppDelegate.m in Sources */,
183 | 2CA045C317117439006DEE8B /* main.m in Sources */,
184 | );
185 | runOnlyForDeploymentPostprocessing = 0;
186 | };
187 | /* End PBXSourcesBuildPhase section */
188 |
189 | /* Begin PBXVariantGroup section */
190 | 2CA045B717117439006DEE8B /* InfoPlist.strings */ = {
191 | isa = PBXVariantGroup;
192 | children = (
193 | 2CA045B817117439006DEE8B /* en */,
194 | );
195 | name = InfoPlist.strings;
196 | sourceTree = "";
197 | };
198 | /* End PBXVariantGroup section */
199 |
200 | /* Begin XCBuildConfiguration section */
201 | 2CEB3ED11602563600548120 /* Debug */ = {
202 | isa = XCBuildConfiguration;
203 | buildSettings = {
204 | ALWAYS_SEARCH_USER_PATHS = NO;
205 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
206 | CLANG_CXX_LIBRARY = "libc++";
207 | CLANG_ENABLE_OBJC_ARC = YES;
208 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
209 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
210 | COPY_PHASE_STRIP = NO;
211 | GCC_C_LANGUAGE_STANDARD = gnu99;
212 | GCC_DYNAMIC_NO_PIC = NO;
213 | GCC_OPTIMIZATION_LEVEL = 0;
214 | GCC_PREPROCESSOR_DEFINITIONS = (
215 | "DEBUG=1",
216 | "$(inherited)",
217 | );
218 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
219 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
220 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
221 | GCC_WARN_UNUSED_VARIABLE = YES;
222 | IPHONEOS_DEPLOYMENT_TARGET = 6.0;
223 | SDKROOT = iphoneos;
224 | };
225 | name = Debug;
226 | };
227 | 2CEB3ED21602563600548120 /* Release */ = {
228 | isa = XCBuildConfiguration;
229 | buildSettings = {
230 | ALWAYS_SEARCH_USER_PATHS = NO;
231 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
232 | CLANG_CXX_LIBRARY = "libc++";
233 | CLANG_ENABLE_OBJC_ARC = YES;
234 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
235 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
236 | COPY_PHASE_STRIP = YES;
237 | GCC_C_LANGUAGE_STANDARD = gnu99;
238 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
239 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
240 | GCC_WARN_UNUSED_VARIABLE = YES;
241 | IPHONEOS_DEPLOYMENT_TARGET = 6.0;
242 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
243 | SDKROOT = iphoneos;
244 | VALIDATE_PRODUCT = YES;
245 | };
246 | name = Release;
247 | };
248 | 2CEB3ED41602563600548120 /* Debug */ = {
249 | isa = XCBuildConfiguration;
250 | buildSettings = {
251 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
252 | GCC_PREFIX_HEADER = "ExampleApp-iOS/ExampleApp-iOS-Prefix.pch";
253 | INFOPLIST_FILE = "ExampleApp-iOS/ExampleApp-iOS-Info.plist";
254 | PRODUCT_NAME = "ExampleApp-iOS";
255 | WRAPPER_EXTENSION = app;
256 | };
257 | name = Debug;
258 | };
259 | 2CEB3ED51602563600548120 /* Release */ = {
260 | isa = XCBuildConfiguration;
261 | buildSettings = {
262 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
263 | GCC_PREFIX_HEADER = "ExampleApp-iOS/ExampleApp-iOS-Prefix.pch";
264 | INFOPLIST_FILE = "ExampleApp-iOS/ExampleApp-iOS-Info.plist";
265 | PRODUCT_NAME = "ExampleApp-iOS";
266 | WRAPPER_EXTENSION = app;
267 | };
268 | name = Release;
269 | };
270 | /* End XCBuildConfiguration section */
271 |
272 | /* Begin XCConfigurationList section */
273 | 2CEB3EB51602563600548120 /* Build configuration list for PBXProject "ExampleApp-iOS" */ = {
274 | isa = XCConfigurationList;
275 | buildConfigurations = (
276 | 2CEB3ED11602563600548120 /* Debug */,
277 | 2CEB3ED21602563600548120 /* Release */,
278 | );
279 | defaultConfigurationIsVisible = 0;
280 | defaultConfigurationName = Release;
281 | };
282 | 2CEB3ED31602563600548120 /* Build configuration list for PBXNativeTarget "ExampleApp-iOS" */ = {
283 | isa = XCConfigurationList;
284 | buildConfigurations = (
285 | 2CEB3ED41602563600548120 /* Debug */,
286 | 2CEB3ED51602563600548120 /* Release */,
287 | );
288 | defaultConfigurationIsVisible = 0;
289 | defaultConfigurationName = Release;
290 | };
291 | /* End XCConfigurationList section */
292 | };
293 | rootObject = 2CEB3EB21602563600548120 /* Project object */;
294 | }
295 |
--------------------------------------------------------------------------------
/Android/ExampleWithWebViewMap/assets/map/mapbox/mapbox.css:
--------------------------------------------------------------------------------
1 | .leaflet-container{background:#fff;font:12px/20px 'Helvetica Neue',Arial,Helvetica,sans-serif;color:#404040;color:rgba(0,0,0,.75);outline:0;overflow:hidden;-ms-touch-action:none}.leaflet-container *,.leaflet-container :after,.leaflet-container :before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.leaflet-container h1,.leaflet-container h2,.leaflet-container h3,.leaflet-container h4,.leaflet-container h5,.leaflet-container h6,.leaflet-container p{font-size:15px;line-height:20px;margin:0 0 10px}.leaflet-container .marker-description img{margin-bottom:10px}.leaflet-container input,.leaflet-container label,.leaflet-container small,.leaflet-container textarea,.leaflet-control-attribution,.leaflet-control-scale,.mapbox-small{font-size:12px;line-height:20px}.leaflet-container a{color:#3887BE;font-weight:400;text-decoration:none}.leaflet-container a:hover,.leaflet-container.dark a{color:#63b6e5}.leaflet-container.dark a:hover{color:#8fcaec}.leaflet-container .mapbox-button,.leaflet-container.dark .mapbox-button{background-color:#3887be;display:inline-block;height:40px;line-height:40px;text-decoration:none;color:#fff;font-size:12px;white-space:nowrap;text-overflow:ellipsis}.leaflet-container .mapbox-button:hover,.leaflet-container.dark .mapbox-button:hover{color:#fff;background-color:#3bb2d0}.leaflet-image-layer,.leaflet-layer,.leaflet-map-pane,.leaflet-marker-icon,.leaflet-marker-pane,.leaflet-marker-shadow,.leaflet-overlay-pane,.leaflet-overlay-pane svg,.leaflet-popup-pane,.leaflet-shadow-pane,.leaflet-tile,.leaflet-tile-container,.leaflet-tile-pane,.leaflet-zoom-box{position:absolute;left:0;top:0}.leaflet-marker-icon,.leaflet-marker-shadow,.leaflet-tile{-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.leaflet-marker-icon,.leaflet-marker-shadow{display:block}.leaflet-tile{filter:inherit;visibility:hidden}.leaflet-tile-loaded{visibility:inherit}.leaflet-zoom-box{width:0;height:0}.leaflet-tile-pane{z-index:2}.leaflet-objects-pane{z-index:3}.leaflet-overlay-pane{z-index:4}.leaflet-shadow-pane{z-index:5}.leaflet-marker-pane{z-index:6}.leaflet-popup-pane{z-index:7}.leaflet-control{position:relative;z-index:7;pointer-events:auto;float:left;clear:both}.leaflet-right .leaflet-control{float:right}.leaflet-top .leaflet-control{margin-top:10px}.leaflet-bottom .leaflet-control{margin-bottom:10px}.leaflet-left .leaflet-control{margin-left:10px}.leaflet-right .leaflet-control{margin-right:10px}.leaflet-bottom,.leaflet-top{position:absolute;z-index:1000;pointer-events:none}.leaflet-top{top:0}.leaflet-right{right:0}.leaflet-bottom{bottom:0}.leaflet-left{left:0}.leaflet-fade-anim .leaflet-popup,.leaflet-fade-anim .leaflet-tile{opacity:0;-webkit-transition:opacity .2s linear;-moz-transition:opacity .2s linear;-o-transition:opacity .2s linear;transition:opacity .2s linear}.leaflet-fade-anim .leaflet-map-pane .leaflet-popup,.leaflet-fade-anim .leaflet-tile-loaded{opacity:1}.leaflet-zoom-anim .leaflet-zoom-animated{-webkit-transition:-webkit-transform .25s cubic-bezier(0,0,.25,1);-moz-transition:-moz-transform .25s cubic-bezier(0,0,.25,1);-o-transition:-o-transform .25s cubic-bezier(0,0,.25,1);transition:transform .25s cubic-bezier(0,0,.25,1)}.leaflet-pan-anim .leaflet-tile,.leaflet-touching .leaflet-zoom-animated,.leaflet-zoom-anim .leaflet-tile{-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none}.leaflet-zoom-anim .leaflet-zoom-hide{visibility:hidden}.leaflet-container{cursor:-webkit-grab;cursor:-moz-grab}.leaflet-container.leaflet-clickable,.leaflet-container.map-clickable{cursor:pointer}.leaflet-control,.leaflet-popup-pane{cursor:auto}.leaflet-dragging,.leaflet-dragging .leaflet-clickable,.leaflet-dragging .leaflet-container,.leaflet-dragging .map-clickable{cursor:move;cursor:-webkit-grabbing;cursor:-moz-grabbing}.leaflet-zoom-box{background:#fff;border:2px dotted #202020;opacity:.5}.leaflet-bar,.leaflet-control-layers{background-color:#fff;border:1px solid #999;border-color:rgba(0,0,0,.4);border-radius:3px;box-shadow:none}.leaflet-bar a,.leaflet-bar a:hover{color:#404040;color:rgba(0,0,0,.75);border-bottom:1px solid #ddd;border-bottom-color:rgba(0,0,0,.1)}.leaflet-bar a:active,.leaflet-bar a:hover{background-color:#f8f8f8;cursor:pointer}.leaflet-bar a:first-child{border-radius:3px 3px 0 0}.leaflet-bar a:last-child{border-bottom:0;border-radius:0 0 3px 3px}.leaflet-bar a:only-of-type{border-radius:3px}.leaflet-bar .leaflet-disabled{cursor:default;opacity:.75}.leaflet-control-zoom-in,.leaflet-control-zoom-out{display:block;content:'';text-indent:-999em}.leaflet-control-layers .leaflet-control-layers-list,.leaflet-control-layers-expanded .leaflet-control-layers-toggle{display:none}.leaflet-control-layers-expanded .leaflet-control-layers-list{display:block;position:relative}.leaflet-control-layers-expanded{background:#fff;padding:6px 10px 6px 6px;color:#404040;color:rgba(0,0,0,.75)}.leaflet-control-layers-selector{margin-top:2px;position:relative;top:1px}.leaflet-control-layers label{display:block}.leaflet-control-layers-separator{height:0;border-top:1px solid #ddd;border-top-color:rgba(0,0,0,.1);margin:5px -10px 5px -6px}.leaflet-container .leaflet-control-attribution{background-color:rgba(255,255,255,.25);margin:0;box-shadow:none}.leaflet-control-attribution a:hover,.map-info-container a:hover{color:inherit;text-decoration:underline}.leaflet-control-attribution,.leaflet-control-scale-line{padding:0 5px}.leaflet-left .leaflet-control-scale{margin-left:5px}.leaflet-bottom .leaflet-control-scale{margin-bottom:5px}.leaflet-control-scale-line{background-color:rgba(255,255,255,.5);border:1px solid #999;border-color:rgba(0,0,0,.4);border-top:0;padding:2px 5px 1px;white-space:nowrap;overflow:hidden}.leaflet-control-scale-line:not(:first-child){border-top:2px solid #ddd;border-top-color:rgba(0,0,0,.1);border-bottom:0;margin-top:-2px}.leaflet-control-scale-line:not(:first-child):not(:last-child){border-bottom:2px solid #777}.leaflet-popup{position:absolute;text-align:center;pointer-events:none}.leaflet-popup-content-wrapper{padding:1px;text-align:left;pointer-events:all}.leaflet-popup-content{padding:10px 10px 15px;margin:0;line-height:inherit}.leaflet-popup-tip-container{width:20px;height:20px;margin:0 auto;position:relative}.leaflet-popup-tip{width:0;height:0;margin:0;border-left:10px solid transparent;border-right:10px solid transparent;border-top:10px solid #fff;box-shadow:none}.leaflet-popup-close-button{text-indent:-999em;position:absolute;top:0;right:0;pointer-events:all}.leaflet-popup-close-button:hover{background-color:#f8f8f8}.leaflet-popup-scrolled{overflow:auto;border-bottom:1px solid #ddd;border-top:1px solid #ddd}.leaflet-div-icon{background:#fff;border:1px solid #999;border-color:rgba(0,0,0,.4)}.leaflet-editing-icon{border-radius:3px}.leaflet-bar a,.leaflet-control-layers-toggle,.leaflet-popup-close-button,.map-tooltip.closable .close,.mapbox-button-icon:before,.mapbox-icon{content:'';display:inline-block;width:26px;height:26px;vertical-align:middle;background-repeat:no-repeat}.leaflet-bar a{display:block}.leaflet-container.dark .map-tooltip .close,.leaflet-control-layers-toggle,.leaflet-control-zoom-in,.leaflet-control-zoom-out,.leaflet-popup-close-button,.map-tooltip .close,.mapbox-icon{opacity:.75;background-image:url(images/icons-000000.png);background-repeat:no-repeat;background-size:26px 260px}.leaflet-container.dark .leaflet-control-layers-toggle,.leaflet-container.dark .leaflet-control-zoom-in,.leaflet-container.dark .leaflet-control-zoom-out,.leaflet-container.dark .mapbox-icon,.mapbox-button-icon:before{opacity:1;background-image:url(images/icons-ffffff.png);background-size:26px 260px}.leaflet-bar .leaflet-control-zoom-in{background-position:0 0}.leaflet-bar .leaflet-control-zoom-out{background-position:0 -26px}.leaflet-popup-close-button,.map-tooltip .close{background-position:0 -52px}.mapbox-icon-info{background-position:0 -78px}.leaflet-control-layers-toggle{background-position:0 -104px}.mapbox-icon-share,.mapbox-icon-share:before{background-position:0 -130px}.mapbox-icon-geocoder,.mapbox-icon-geocoder:before{background-position:0 -156px}.mapbox-icon-facebook,.mapbox-icon-facebook:before{background-position:0 -182px}.mapbox-icon-twitter,.mapbox-icon-twitter:before{background-position:0 -208px}.mapbox-icon-pinterest,.mapbox-icon-pinterest:before{background-position:0 -234px}@media (-webkit-min-device-pixel-ratio:2),(min-resolution:192dpi),(min-resolution:2dppx){.leaflet-control-layers-toggle,.leaflet-control-zoom-in,.leaflet-control-zoom-out,.leaflet-popup-close-button,.mapbox-icon{background-image:url(images/icons-000000@2x.png)}.leaflet-container.dark .leaflet-control-layers-toggle,.leaflet-container.dark .leaflet-control-zoom-in,.leaflet-container.dark .leaflet-control-zoom-out,.leaflet-container.dark .mapbox-icon,.mapbox-button-icon:before{background-image:url(images/icons-ffffff@2x.png)}}.leaflet-popup-content-wrapper,.map-legends,.map-tooltip{background:#fff;border-radius:3px;box-shadow:0 1px 2px rgba(0,0,0,.1)}.map-legends,.map-tooltip{max-width:300px}.map-legends .map-legend{padding:10px}.map-tooltip{z-index:999999;padding:10px;min-width:180px;max-height:400px;overflow:auto;opacity:1;-webkit-transition:opacity 150ms;-moz-transition:opacity 150ms;-o-transition:opacity 150ms;transition:opacity 150ms}.map-tooltip .close{text-indent:-999em;overflow:hidden;display:none}.map-tooltip.closable .close{position:absolute;top:0;right:0;border-radius:3px}.map-tooltip.closable .close:active{background-color:#f8f8f8}.leaflet-control-interaction{position:absolute;top:10px;right:10px;width:300px}.leaflet-popup-content .marker-title{font-weight:700}.leaflet-control .mapbox-button{background-color:#fff;border:1px solid #ddd;border-color:rgba(0,0,0,.1);padding:5px 10px;border-radius:3px}.mapbox-modal>div{position:absolute;top:0;left:0;width:100%;height:100%;z-index:-1;overflow-y:auto}.mapbox-modal.active>div{z-index:99999;transition:all .2s,z-index 0 0}.mapbox-modal .mapbox-modal-mask{background:rgba(0,0,0,.5);opacity:0}.mapbox-modal.active .mapbox-modal-mask{opacity:1}.mapbox-modal .mapbox-modal-content{-webkit-transform:translateY(-100%);-moz-transform:translateY(-100%);-ms-transform:translateY(-100%);transform:translateY(-100%)}.mapbox-modal.active .mapbox-modal-content{-webkit-transform:translateY(0);-moz-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}.mapbox-modal-body{position:relative;background:#fff;padding:20px;z-index:1000;width:50%;margin:20px 0 20px 25%}.mapbox-share-buttons{margin:0 0 20px}.mapbox-share-buttons a{width:33.3333%;border-left:1px solid #fff;text-align:center;border-radius:0}.mapbox-share-buttons a:last-child{border-radius:0 3px 3px 0}.mapbox-share-buttons a:first-child{border:0;border-radius:3px 0 0 3px}.mapbox-modal input{width:100%;height:40px;padding:10px;border:1px solid #ddd;border-color:rgba(0,0,0,.1);color:rgba(0,0,0,.5)}.leaflet-control.mapbox-control-info{margin:5px 30px 10px 10px;min-height:26px}.leaflet-control.mapbox-control-info-right{margin:5px 10px 10px 30px}.mapbox-info-toggle{background-color:#fff;background-color:rgba(255,255,255,.5);border-radius:50%;position:absolute;bottom:0;left:0;z-index:1}.mapbox-control-info-right .mapbox-info-toggle{left:auto;right:0}.mapbox-info-toggle:hover{background-color:#fff}.map-info-container{background:#fff;padding:3px 5px 3px 27px;display:none;position:relative;bottom:0;left:0;border-radius:13px 3px 3px 13px}.mapbox-control-info.active .map-info-container{display:inline-block}.mapbox-control-info-right .map-info-container{left:auto;right:0;padding:3px 27px 3px 5px;border-radius:3px 13px 13px 3px}.leaflet-container .mapbox-improve-map{font-weight:700}.leaflet-control-mapbox-geocoder{position:relative}.leaflet-control-mapbox-geocoder.searching{opacity:.75}.leaflet-control-mapbox-geocoder .leaflet-control-mapbox-geocoder-wrap{background:#fff;position:absolute;border:1px solid #999;border-color:rgba(0,0,0,.4);border-bottom-width:0;overflow:hidden;left:26px;height:27px;width:0;top:-1px;border-radius:0 3px 3px 0;opacity:0;-webkit-transition:opacity 100ms;-moz-transition:opacity 100ms;-o-transition:opacity 100ms;transition:opacity 100ms}.leaflet-control-mapbox-geocoder.active .leaflet-control-mapbox-geocoder-wrap{width:180px;opacity:1}.leaflet-bar .leaflet-control-mapbox-geocoder-toggle,.leaflet-bar .leaflet-control-mapbox-geocoder-toggle:hover{border-bottom:0}.leaflet-control-mapbox-geocoder-toggle{border-radius:3px}.leaflet-control-mapbox-geocoder.active,.leaflet-control-mapbox-geocoder.active .leaflet-control-mapbox-geocoder-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.leaflet-control-mapbox-geocoder .leaflet-control-mapbox-geocoder-form input{background:0 0;border:0;width:180px;padding:0 0 0 10px;height:26px;outline:0}.leaflet-control-mapbox-geocoder-results{width:180px;position:absolute;left:26px;top:25px;border-radius:0 0 3px 3px}.leaflet-control-mapbox-geocoder.active .leaflet-control-mapbox-geocoder-results{background:#fff;border:1px solid #999;border-color:rgba(0,0,0,.4)}.leaflet-control-mapbox-geocoder-results a,.leaflet-control-mapbox-geocoder-results span{padding:0 10px;text-overflow:ellipsis;white-space:nowrap;display:block;width:100%;font-size:12px;line-height:26px;text-align:left;overflow:hidden}.leaflet-control-mapbox-geocoder-results a:first-child{border-top:1px solid #999;border-top-color:rgba(0,0,0,.4);border-radius:0}.leaflet-container.dark .leaflet-control .leaflet-control-mapbox-geocoder-results a:hover,.leaflet-control-mapbox-geocoder-results a:hover{background:#f8f8f8;opacity:1}.leaflet-container.dark .leaflet-bar{background-color:#404040;border-color:#202020;border-color:rgba(0,0,0,.75)}.leaflet-container.dark .leaflet-bar a{color:#404040;border-color:rgba(0,0,0,.5)}.leaflet-container.dark .leaflet-bar a:active,.leaflet-container.dark .leaflet-bar a:hover{background-color:#505050}.leaflet-container.dark .leaflet-control-attribution,.leaflet-container.dark .map-info-container,.leaflet-container.dark .mapbox-info-toggle{background-color:rgba(0,0,0,.25);color:#f8f8f8}.leaflet-container.dark .leaflet-bar a.leaflet-disabled,.leaflet-container.dark .leaflet-control .mapbox-button.disabled{background-color:#252525;color:#404040}.leaflet-container.dark .leaflet-control-mapbox-geocoder>div{border-color:#202020;border-color:rgba(0,0,0,.75)}.leaflet-container.dark .leaflet-control .leaflet-control-mapbox-geocoder-results a{border-color:#ddd #202020;border-color:rgba(0,0,0,.1) rgba(0,0,0,.75)}.leaflet-container.dark .leaflet-control .leaflet-control-mapbox-geocoder-results span{border-color:#202020;border-color:rgba(0,0,0,.75)}@media only screen and (max-width:800px){.mapbox-modal-body{width:83.3333%;margin-left:8.3333%}}@media only screen and (max-width:640px){.mapbox-modal-body{width:100%;height:100%;margin:0}}.leaflet-container img.leaflet-tile{max-width:none!important}.leaflet-container img.leaflet-marker-icon{max-width:none}.leaflet-container img.leaflet-image-layer{max-width:15000px!important}.leaflet-overlay-pane svg{-moz-user-select:none}.leaflet-oldie .mapbox-modal .mapbox-modal-content{display:none}.leaflet-oldie .mapbox-modal.active .mapbox-modal-content{display:block}.map-tooltip{width:280px\8}
--------------------------------------------------------------------------------
/IOS/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 2C136A2517641106004C7401 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C136A2417641106004C7401 /* Cocoa.framework */; };
11 | 2C136A2F17641106004C7401 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2C136A2D17641106004C7401 /* InfoPlist.strings */; };
12 | 2C136A3117641106004C7401 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C136A3017641106004C7401 /* main.m */; };
13 | 2C136A3517641106004C7401 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 2C136A3317641106004C7401 /* Credits.rtf */; };
14 | 2C136A3817641106004C7401 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C136A3717641106004C7401 /* AppDelegate.m */; };
15 | 2C136A4217641236004C7401 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C136A4117641236004C7401 /* WebKit.framework */; };
16 | 2C136A5A17642704004C7401 /* ExampleApp.html in Resources */ = {isa = PBXBuildFile; fileRef = 2C136A5917642704004C7401 /* ExampleApp.html */; };
17 | 2C1562C5176BA9FF00B4AE50 /* WebViewJavascriptBridge.js.txt in Resources */ = {isa = PBXBuildFile; fileRef = 2C1562C3176BA9FF00B4AE50 /* WebViewJavascriptBridge.js.txt */; };
18 | 2C1562C6176BA9FF00B4AE50 /* WebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C1562C4176BA9FF00B4AE50 /* WebViewJavascriptBridge.m */; };
19 | /* End PBXBuildFile section */
20 |
21 | /* Begin PBXFileReference section */
22 | 2C136A2117641106004C7401 /* ExampleApp-OSX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ExampleApp-OSX.app"; sourceTree = BUILT_PRODUCTS_DIR; };
23 | 2C136A2417641106004C7401 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
24 | 2C136A2717641106004C7401 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
25 | 2C136A2817641106004C7401 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
26 | 2C136A2917641106004C7401 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
27 | 2C136A2C17641106004C7401 /* ExampleApp-OSX-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ExampleApp-OSX-Info.plist"; sourceTree = ""; };
28 | 2C136A2E17641106004C7401 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
29 | 2C136A3017641106004C7401 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
30 | 2C136A3217641106004C7401 /* ExampleApp-OSX-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ExampleApp-OSX-Prefix.pch"; sourceTree = ""; };
31 | 2C136A3417641106004C7401 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; };
32 | 2C136A3617641106004C7401 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
33 | 2C136A3717641106004C7401 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
34 | 2C136A4117641236004C7401 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; };
35 | 2C136A5917642704004C7401 /* ExampleApp.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = ExampleApp.html; sourceTree = SOURCE_ROOT; };
36 | 2C1562C2176BA9FF00B4AE50 /* WebViewJavascriptBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge.h; sourceTree = ""; };
37 | 2C1562C3176BA9FF00B4AE50 /* WebViewJavascriptBridge.js.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebViewJavascriptBridge.js.txt; sourceTree = ""; };
38 | 2C1562C4176BA9FF00B4AE50 /* WebViewJavascriptBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge.m; sourceTree = ""; };
39 | /* End PBXFileReference section */
40 |
41 | /* Begin PBXFrameworksBuildPhase section */
42 | 2C136A1E17641106004C7401 /* Frameworks */ = {
43 | isa = PBXFrameworksBuildPhase;
44 | buildActionMask = 2147483647;
45 | files = (
46 | 2C136A4217641236004C7401 /* WebKit.framework in Frameworks */,
47 | 2C136A2517641106004C7401 /* Cocoa.framework in Frameworks */,
48 | );
49 | runOnlyForDeploymentPostprocessing = 0;
50 | };
51 | /* End PBXFrameworksBuildPhase section */
52 |
53 | /* Begin PBXGroup section */
54 | 2C136A1817641106004C7401 = {
55 | isa = PBXGroup;
56 | children = (
57 | 2C136A4117641236004C7401 /* WebKit.framework */,
58 | 2C136A2A17641106004C7401 /* ExampleApp-OSX */,
59 | 2C136A2317641106004C7401 /* Frameworks */,
60 | 2C136A2217641106004C7401 /* Products */,
61 | );
62 | sourceTree = "";
63 | };
64 | 2C136A2217641106004C7401 /* Products */ = {
65 | isa = PBXGroup;
66 | children = (
67 | 2C136A2117641106004C7401 /* ExampleApp-OSX.app */,
68 | );
69 | name = Products;
70 | sourceTree = "";
71 | };
72 | 2C136A2317641106004C7401 /* Frameworks */ = {
73 | isa = PBXGroup;
74 | children = (
75 | 2C136A2417641106004C7401 /* Cocoa.framework */,
76 | 2C136A2617641106004C7401 /* Other Frameworks */,
77 | );
78 | name = Frameworks;
79 | sourceTree = "";
80 | };
81 | 2C136A2617641106004C7401 /* Other Frameworks */ = {
82 | isa = PBXGroup;
83 | children = (
84 | 2C136A2717641106004C7401 /* AppKit.framework */,
85 | 2C136A2817641106004C7401 /* CoreData.framework */,
86 | 2C136A2917641106004C7401 /* Foundation.framework */,
87 | );
88 | name = "Other Frameworks";
89 | sourceTree = "";
90 | };
91 | 2C136A2A17641106004C7401 /* ExampleApp-OSX */ = {
92 | isa = PBXGroup;
93 | children = (
94 | 2C136A3617641106004C7401 /* AppDelegate.h */,
95 | 2C136A3717641106004C7401 /* AppDelegate.m */,
96 | 2C136A5917642704004C7401 /* ExampleApp.html */,
97 | 2C1562C1176BA9FF00B4AE50 /* WebViewJavascriptBridge */,
98 | 2C136A2B17641106004C7401 /* Supporting Files */,
99 | );
100 | path = "ExampleApp-OSX";
101 | sourceTree = "";
102 | };
103 | 2C136A2B17641106004C7401 /* Supporting Files */ = {
104 | isa = PBXGroup;
105 | children = (
106 | 2C136A2C17641106004C7401 /* ExampleApp-OSX-Info.plist */,
107 | 2C136A2D17641106004C7401 /* InfoPlist.strings */,
108 | 2C136A3017641106004C7401 /* main.m */,
109 | 2C136A3217641106004C7401 /* ExampleApp-OSX-Prefix.pch */,
110 | 2C136A3317641106004C7401 /* Credits.rtf */,
111 | );
112 | name = "Supporting Files";
113 | sourceTree = "";
114 | };
115 | 2C1562C1176BA9FF00B4AE50 /* WebViewJavascriptBridge */ = {
116 | isa = PBXGroup;
117 | children = (
118 | 2C1562C2176BA9FF00B4AE50 /* WebViewJavascriptBridge.h */,
119 | 2C1562C3176BA9FF00B4AE50 /* WebViewJavascriptBridge.js.txt */,
120 | 2C1562C4176BA9FF00B4AE50 /* WebViewJavascriptBridge.m */,
121 | );
122 | name = WebViewJavascriptBridge;
123 | path = ../../WebViewJavascriptBridge;
124 | sourceTree = "";
125 | };
126 | /* End PBXGroup section */
127 |
128 | /* Begin PBXNativeTarget section */
129 | 2C136A2017641106004C7401 /* ExampleApp-OSX */ = {
130 | isa = PBXNativeTarget;
131 | buildConfigurationList = 2C136A3E17641106004C7401 /* Build configuration list for PBXNativeTarget "ExampleApp-OSX" */;
132 | buildPhases = (
133 | 2C136A1D17641106004C7401 /* Sources */,
134 | 2C136A1E17641106004C7401 /* Frameworks */,
135 | 2C136A1F17641106004C7401 /* Resources */,
136 | );
137 | buildRules = (
138 | );
139 | dependencies = (
140 | );
141 | name = "ExampleApp-OSX";
142 | productName = "ExampleApp-OSX";
143 | productReference = 2C136A2117641106004C7401 /* ExampleApp-OSX.app */;
144 | productType = "com.apple.product-type.application";
145 | };
146 | /* End PBXNativeTarget section */
147 |
148 | /* Begin PBXProject section */
149 | 2C136A1917641106004C7401 /* Project object */ = {
150 | isa = PBXProject;
151 | attributes = {
152 | LastUpgradeCheck = 0460;
153 | ORGANIZATIONNAME = "Marcus Westin";
154 | };
155 | buildConfigurationList = 2C136A1C17641106004C7401 /* Build configuration list for PBXProject "ExampleApp-OSX" */;
156 | compatibilityVersion = "Xcode 3.2";
157 | developmentRegion = English;
158 | hasScannedForEncodings = 0;
159 | knownRegions = (
160 | en,
161 | );
162 | mainGroup = 2C136A1817641106004C7401;
163 | productRefGroup = 2C136A2217641106004C7401 /* Products */;
164 | projectDirPath = "";
165 | projectRoot = "";
166 | targets = (
167 | 2C136A2017641106004C7401 /* ExampleApp-OSX */,
168 | );
169 | };
170 | /* End PBXProject section */
171 |
172 | /* Begin PBXResourcesBuildPhase section */
173 | 2C136A1F17641106004C7401 /* Resources */ = {
174 | isa = PBXResourcesBuildPhase;
175 | buildActionMask = 2147483647;
176 | files = (
177 | 2C1562C5176BA9FF00B4AE50 /* WebViewJavascriptBridge.js.txt in Resources */,
178 | 2C136A2F17641106004C7401 /* InfoPlist.strings in Resources */,
179 | 2C136A3517641106004C7401 /* Credits.rtf in Resources */,
180 | 2C136A5A17642704004C7401 /* ExampleApp.html in Resources */,
181 | );
182 | runOnlyForDeploymentPostprocessing = 0;
183 | };
184 | /* End PBXResourcesBuildPhase section */
185 |
186 | /* Begin PBXSourcesBuildPhase section */
187 | 2C136A1D17641106004C7401 /* Sources */ = {
188 | isa = PBXSourcesBuildPhase;
189 | buildActionMask = 2147483647;
190 | files = (
191 | 2C136A3117641106004C7401 /* main.m in Sources */,
192 | 2C1562C6176BA9FF00B4AE50 /* WebViewJavascriptBridge.m in Sources */,
193 | 2C136A3817641106004C7401 /* AppDelegate.m in Sources */,
194 | );
195 | runOnlyForDeploymentPostprocessing = 0;
196 | };
197 | /* End PBXSourcesBuildPhase section */
198 |
199 | /* Begin PBXVariantGroup section */
200 | 2C136A2D17641106004C7401 /* InfoPlist.strings */ = {
201 | isa = PBXVariantGroup;
202 | children = (
203 | 2C136A2E17641106004C7401 /* en */,
204 | );
205 | name = InfoPlist.strings;
206 | sourceTree = "";
207 | };
208 | 2C136A3317641106004C7401 /* Credits.rtf */ = {
209 | isa = PBXVariantGroup;
210 | children = (
211 | 2C136A3417641106004C7401 /* en */,
212 | );
213 | name = Credits.rtf;
214 | sourceTree = "";
215 | };
216 | /* End PBXVariantGroup section */
217 |
218 | /* Begin XCBuildConfiguration section */
219 | 2C136A3C17641106004C7401 /* Debug */ = {
220 | isa = XCBuildConfiguration;
221 | buildSettings = {
222 | ALWAYS_SEARCH_USER_PATHS = NO;
223 | ARCHS = "$(ARCHS_STANDARD_64_BIT)";
224 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
225 | CLANG_CXX_LIBRARY = "libc++";
226 | CLANG_ENABLE_OBJC_ARC = YES;
227 | CLANG_WARN_CONSTANT_CONVERSION = YES;
228 | CLANG_WARN_EMPTY_BODY = YES;
229 | CLANG_WARN_ENUM_CONVERSION = YES;
230 | CLANG_WARN_INT_CONVERSION = YES;
231 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
232 | COPY_PHASE_STRIP = NO;
233 | GCC_C_LANGUAGE_STANDARD = gnu99;
234 | GCC_DYNAMIC_NO_PIC = NO;
235 | GCC_ENABLE_OBJC_EXCEPTIONS = YES;
236 | GCC_OPTIMIZATION_LEVEL = 0;
237 | GCC_PREPROCESSOR_DEFINITIONS = (
238 | "DEBUG=1",
239 | "$(inherited)",
240 | );
241 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
242 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
243 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
244 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
245 | GCC_WARN_UNUSED_VARIABLE = YES;
246 | MACOSX_DEPLOYMENT_TARGET = 10.8;
247 | ONLY_ACTIVE_ARCH = YES;
248 | SDKROOT = macosx;
249 | };
250 | name = Debug;
251 | };
252 | 2C136A3D17641106004C7401 /* Release */ = {
253 | isa = XCBuildConfiguration;
254 | buildSettings = {
255 | ALWAYS_SEARCH_USER_PATHS = NO;
256 | ARCHS = "$(ARCHS_STANDARD_64_BIT)";
257 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
258 | CLANG_CXX_LIBRARY = "libc++";
259 | CLANG_ENABLE_OBJC_ARC = YES;
260 | CLANG_WARN_CONSTANT_CONVERSION = YES;
261 | CLANG_WARN_EMPTY_BODY = YES;
262 | CLANG_WARN_ENUM_CONVERSION = YES;
263 | CLANG_WARN_INT_CONVERSION = YES;
264 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
265 | COPY_PHASE_STRIP = YES;
266 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
267 | GCC_C_LANGUAGE_STANDARD = gnu99;
268 | GCC_ENABLE_OBJC_EXCEPTIONS = YES;
269 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
270 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
271 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
272 | GCC_WARN_UNUSED_VARIABLE = YES;
273 | MACOSX_DEPLOYMENT_TARGET = 10.8;
274 | SDKROOT = macosx;
275 | };
276 | name = Release;
277 | };
278 | 2C136A3F17641106004C7401 /* Debug */ = {
279 | isa = XCBuildConfiguration;
280 | buildSettings = {
281 | COMBINE_HIDPI_IMAGES = YES;
282 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
283 | GCC_PREFIX_HEADER = "ExampleApp-OSX/ExampleApp-OSX-Prefix.pch";
284 | INFOPLIST_FILE = "ExampleApp-OSX/ExampleApp-OSX-Info.plist";
285 | PRODUCT_NAME = "$(TARGET_NAME)";
286 | WRAPPER_EXTENSION = app;
287 | };
288 | name = Debug;
289 | };
290 | 2C136A4017641106004C7401 /* Release */ = {
291 | isa = XCBuildConfiguration;
292 | buildSettings = {
293 | COMBINE_HIDPI_IMAGES = YES;
294 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
295 | GCC_PREFIX_HEADER = "ExampleApp-OSX/ExampleApp-OSX-Prefix.pch";
296 | INFOPLIST_FILE = "ExampleApp-OSX/ExampleApp-OSX-Info.plist";
297 | PRODUCT_NAME = "$(TARGET_NAME)";
298 | WRAPPER_EXTENSION = app;
299 | };
300 | name = Release;
301 | };
302 | /* End XCBuildConfiguration section */
303 |
304 | /* Begin XCConfigurationList section */
305 | 2C136A1C17641106004C7401 /* Build configuration list for PBXProject "ExampleApp-OSX" */ = {
306 | isa = XCConfigurationList;
307 | buildConfigurations = (
308 | 2C136A3C17641106004C7401 /* Debug */,
309 | 2C136A3D17641106004C7401 /* Release */,
310 | );
311 | defaultConfigurationIsVisible = 0;
312 | defaultConfigurationName = Release;
313 | };
314 | 2C136A3E17641106004C7401 /* Build configuration list for PBXNativeTarget "ExampleApp-OSX" */ = {
315 | isa = XCConfigurationList;
316 | buildConfigurations = (
317 | 2C136A3F17641106004C7401 /* Debug */,
318 | 2C136A4017641106004C7401 /* Release */,
319 | );
320 | defaultConfigurationIsVisible = 0;
321 | defaultConfigurationName = Release;
322 | };
323 | /* End XCConfigurationList section */
324 | };
325 | rootObject = 2C136A1917641106004C7401 /* Project object */;
326 | }
327 |
--------------------------------------------------------------------------------