terminus 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +27 -89
- data/bin/terminus +7 -23
- data/lib/capybara/driver/terminus.rb +30 -11
- data/lib/terminus.rb +33 -22
- data/lib/terminus/application.rb +13 -7
- data/lib/terminus/browser.rb +110 -28
- data/lib/terminus/controller.rb +51 -20
- data/lib/terminus/host.rb +22 -0
- data/lib/terminus/node.rb +23 -4
- data/lib/terminus/proxy.rb +62 -0
- data/lib/terminus/proxy/driver_body.rb +63 -0
- data/lib/terminus/proxy/external.rb +25 -0
- data/lib/terminus/proxy/rewrite.rb +20 -0
- data/lib/terminus/public/icon.png +0 -0
- data/lib/terminus/public/loader.js +1 -0
- data/lib/terminus/public/style.css +43 -0
- data/lib/terminus/public/syn/browsers.js +150 -0
- data/lib/terminus/public/syn/drag/drag.js +322 -0
- data/lib/terminus/public/syn/key.js +905 -0
- data/lib/terminus/public/syn/mouse.js +284 -0
- data/lib/terminus/public/syn/synthetic.js +830 -0
- data/lib/{public → terminus/public}/terminus.js +109 -40
- data/lib/terminus/server.rb +5 -12
- data/lib/terminus/timeouts.rb +2 -2
- data/lib/{views/bookmarklet.erb → terminus/views/bootstrap.erb} +17 -12
- data/lib/terminus/views/index.erb +21 -0
- data/lib/terminus/views/infinite.html +16 -0
- data/spec/reports/chrome.txt +748 -0
- data/spec/reports/firefox.txt +748 -0
- data/spec/reports/opera.txt +748 -0
- data/spec/reports/safari.txt +748 -0
- data/spec/spec_helper.rb +18 -14
- data/spec/terminus_driver_spec.rb +7 -5
- data/spec/terminus_session_spec.rb +5 -18
- metadata +71 -57
- data/lib/public/loader.js +0 -1
- data/lib/public/style.css +0 -49
- data/lib/public/syn.js +0 -2355
- data/lib/views/index.erb +0 -32
data/lib/terminus/controller.rb
CHANGED
@@ -2,13 +2,11 @@ module Terminus
|
|
2
2
|
class Controller
|
3
3
|
|
4
4
|
include Timeouts
|
5
|
-
attr_accessor :dock_host
|
6
5
|
|
7
6
|
def initialize
|
8
|
-
@connected
|
9
|
-
@browsers
|
10
|
-
@
|
11
|
-
trap('INT') { exit }
|
7
|
+
@connected = false
|
8
|
+
@browsers = {}
|
9
|
+
@host_aliases = {}
|
12
10
|
end
|
13
11
|
|
14
12
|
def browser(id = nil)
|
@@ -16,14 +14,15 @@ module Terminus
|
|
16
14
|
@browsers[id] ||= Browser.new(self)
|
17
15
|
end
|
18
16
|
|
17
|
+
def browsers
|
18
|
+
@browsers.values
|
19
|
+
end
|
20
|
+
|
19
21
|
def browser=(params)
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
wait_with_timeout(:named_window) do
|
25
|
-
@browsers.values.find { |b| b.name == params[:name] }
|
26
|
-
end
|
22
|
+
ensure_connection
|
23
|
+
return @browser = params if Browser === params
|
24
|
+
@browser = wait_with_timeout(:selected_browser) do
|
25
|
+
@browsers.values.find { |b| b === params }
|
27
26
|
end
|
28
27
|
end
|
29
28
|
|
@@ -32,14 +31,9 @@ module Terminus
|
|
32
31
|
@browser = nil if @browser == browser
|
33
32
|
end
|
34
33
|
|
35
|
-
def
|
36
|
-
ensure_connection
|
37
|
-
wait_with_timeout(:browser) { @browser }
|
38
|
-
end
|
39
|
-
|
40
|
-
def ensure_docked_browser
|
34
|
+
def ensure_browsers(n = 1)
|
41
35
|
ensure_connection
|
42
|
-
wait_with_timeout(:
|
36
|
+
wait_with_timeout(:browsers) { @browsers.size >= n }
|
43
37
|
end
|
44
38
|
|
45
39
|
def messenger
|
@@ -57,6 +51,32 @@ module Terminus
|
|
57
51
|
@browsers.each { |id, b| b.return_to_dock }
|
58
52
|
end
|
59
53
|
|
54
|
+
def rewrite_local(url, dock_host)
|
55
|
+
uri = URI.parse(url)
|
56
|
+
uri.host = '127.0.0.1' if uri.host == dock_host
|
57
|
+
uri.path = '' if uri.path == '/'
|
58
|
+
|
59
|
+
# 1.8.7 does not have Hash#key, and 1.9.2 gives warnings for #index
|
60
|
+
remote_host = @host_aliases.respond_to?(:key) ?
|
61
|
+
@host_aliases.key(Host.new(uri)) :
|
62
|
+
@host_aliases.index(Host.new(uri))
|
63
|
+
|
64
|
+
if remote_host
|
65
|
+
uri.host = remote_host.host
|
66
|
+
uri.port = remote_host.port
|
67
|
+
end
|
68
|
+
uri.host = dock_host if dock_host and uri.host =~ LOCALHOST
|
69
|
+
uri
|
70
|
+
end
|
71
|
+
|
72
|
+
def rewrite_remote(url, dock_host = nil)
|
73
|
+
uri = URI.parse(url)
|
74
|
+
return uri unless URI::HTTP === uri and uri.host !~ LOCALHOST and uri.host != dock_host
|
75
|
+
server = boot(uri)
|
76
|
+
uri.host, uri.port = server.host, server.port
|
77
|
+
uri
|
78
|
+
end
|
79
|
+
|
60
80
|
private
|
61
81
|
|
62
82
|
def accept_ping(message)
|
@@ -64,7 +84,18 @@ module Terminus
|
|
64
84
|
end
|
65
85
|
|
66
86
|
def accept_result(message)
|
67
|
-
browser
|
87
|
+
browser = @browsers[message['id']]
|
88
|
+
browser.result!(message) if browser
|
89
|
+
end
|
90
|
+
|
91
|
+
def boot(remote_uri)
|
92
|
+
host = Host.new(remote_uri)
|
93
|
+
@host_aliases[host] ||= begin
|
94
|
+
server = Capybara::Server.new(Proxy[host])
|
95
|
+
Thread.new { server.boot }
|
96
|
+
sleep 0.1 until server.port
|
97
|
+
Host.new(server)
|
98
|
+
end
|
68
99
|
end
|
69
100
|
|
70
101
|
def ensure_connection
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Terminus
|
2
|
+
class Host
|
3
|
+
|
4
|
+
attr_reader :host, :port
|
5
|
+
|
6
|
+
def initialize(uri)
|
7
|
+
@host = uri.host
|
8
|
+
@port = uri.port
|
9
|
+
end
|
10
|
+
|
11
|
+
def eql?(other)
|
12
|
+
host == other.host and
|
13
|
+
port == other.port
|
14
|
+
end
|
15
|
+
alias :== :eql?
|
16
|
+
|
17
|
+
def hash
|
18
|
+
[host, port].hash
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
data/lib/terminus/node.rb
CHANGED
@@ -3,17 +3,30 @@ module Terminus
|
|
3
3
|
|
4
4
|
attr_reader :id
|
5
5
|
|
6
|
-
def initialize(browser, id)
|
7
|
-
@browser, @id = browser, id
|
6
|
+
def initialize(browser, id, driver = nil)
|
7
|
+
@browser, @id, @driver = browser, id, driver
|
8
|
+
end
|
9
|
+
|
10
|
+
def checked?
|
11
|
+
!!self['checked']
|
12
|
+
end
|
13
|
+
|
14
|
+
def selected?
|
15
|
+
!!self['selected']
|
8
16
|
end
|
9
17
|
|
10
18
|
def click
|
11
19
|
page = @browser.page_id
|
12
|
-
|
20
|
+
options = @driver ? @driver.options : {}
|
21
|
+
command = @browser.tell([:click, @id, options])
|
13
22
|
|
14
|
-
@browser.wait_with_timeout(:click_response) do
|
23
|
+
result = @browser.wait_with_timeout(:click_response) do
|
15
24
|
@browser.result(command) || (@browser.page_id != page)
|
16
25
|
end
|
26
|
+
|
27
|
+
if Hash === result and String === result[:value]
|
28
|
+
raise Capybara::TimeoutError, result[:value]
|
29
|
+
end
|
17
30
|
end
|
18
31
|
|
19
32
|
def drag_to(node)
|
@@ -42,10 +55,16 @@ module Terminus
|
|
42
55
|
raise Capybara::UnselectNotAllowed.new unless allowed
|
43
56
|
end
|
44
57
|
|
58
|
+
def to_s
|
59
|
+
"<#{self.class.name} #{@id}>"
|
60
|
+
end
|
61
|
+
alias :inspect :to_s
|
62
|
+
|
45
63
|
alias :select_option :select
|
46
64
|
alias :unselect_option :unselect
|
47
65
|
|
48
66
|
SYNC_DSL_METHODS = [ [:[], :attribute],
|
67
|
+
[:[]=, :set_attribute],
|
49
68
|
:tag_name,
|
50
69
|
:text,
|
51
70
|
:value,
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Terminus
|
2
|
+
class Proxy
|
3
|
+
|
4
|
+
CONTENT_TYPES = %w[text/plain text/html]
|
5
|
+
BASIC_RESOURCES = %w[/favicon.ico /robots.txt]
|
6
|
+
MAX_REDIRECTS = 5
|
7
|
+
|
8
|
+
INFINITE_REDIRECT_RESPONSE = [
|
9
|
+
200,
|
10
|
+
{'Content-Type' => 'text/html'},
|
11
|
+
[File.read(ROOT + '/terminus/views/infinite.html')]
|
12
|
+
]
|
13
|
+
|
14
|
+
autoload :DriverBody, ROOT + '/terminus/proxy/driver_body'
|
15
|
+
autoload :External, ROOT + '/terminus/proxy/external'
|
16
|
+
autoload :Rewrite, ROOT + '/terminus/proxy/rewrite'
|
17
|
+
|
18
|
+
def self.[](app)
|
19
|
+
@proxies ||= {}
|
20
|
+
@proxies[app] ||= new(app)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.content_type(response)
|
24
|
+
type = response[1].find { |key, _| key =~ /^content-type$/i }
|
25
|
+
type && type.last.split(';').first
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(app)
|
29
|
+
app = External.new(app) if Host === app
|
30
|
+
@app = app
|
31
|
+
@redirects = 0
|
32
|
+
end
|
33
|
+
|
34
|
+
def call(env)
|
35
|
+
response = @app.call(env)
|
36
|
+
|
37
|
+
if response.first == 302
|
38
|
+
@redirects += 1
|
39
|
+
if @redirects > MAX_REDIRECTS
|
40
|
+
@redirects = 0
|
41
|
+
response = INFINITE_REDIRECT_RESPONSE
|
42
|
+
end
|
43
|
+
else
|
44
|
+
@redirects = 0
|
45
|
+
end
|
46
|
+
|
47
|
+
return response if response.first == -1 or # async response
|
48
|
+
BASIC_RESOURCES.include?(env['PATH_INFO']) or # not pages - favicon etc
|
49
|
+
env.has_key?('HTTP_X_REQUESTED_WITH') # Ajax calls
|
50
|
+
|
51
|
+
content_type = Proxy.content_type(response)
|
52
|
+
return response unless CONTENT_TYPES.include?(content_type)
|
53
|
+
|
54
|
+
response[1] = response[1].dup
|
55
|
+
response[1].delete_if { |key, _| key =~ /^content-length$/i }
|
56
|
+
response[2] = DriverBody.new(env, response)
|
57
|
+
|
58
|
+
response
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Terminus
|
2
|
+
class Proxy
|
3
|
+
|
4
|
+
class DriverBody
|
5
|
+
TEMPLATE = ERB.new(<<-DRIVER)
|
6
|
+
<script id="terminus-data" type="text/javascript">
|
7
|
+
TERMINUS_STATUS = <%= @response.first %>;
|
8
|
+
TERMINUS_HEADERS = {};
|
9
|
+
<% @response[1].each do |key, value| %>
|
10
|
+
TERMINUS_HEADERS[<%= key.inspect %>] = <%= value.inspect %>;
|
11
|
+
<% end %>
|
12
|
+
TERMINUS_SOURCE = <%= page_source %>;
|
13
|
+
</script>
|
14
|
+
<script type="text/javascript">
|
15
|
+
(function() {
|
16
|
+
var terminusScript = document.getElementById('terminus-data');
|
17
|
+
terminusScript.parentNode.removeChild(terminusScript);
|
18
|
+
})();
|
19
|
+
</script>
|
20
|
+
<%= driver_script %>
|
21
|
+
DRIVER
|
22
|
+
|
23
|
+
def initialize(env, response)
|
24
|
+
@env = env
|
25
|
+
@response = response
|
26
|
+
@body = response[2]
|
27
|
+
end
|
28
|
+
|
29
|
+
def each(&block)
|
30
|
+
script_injected = false
|
31
|
+
@source = ''
|
32
|
+
|
33
|
+
@body.each do |fragment|
|
34
|
+
@source << fragment
|
35
|
+
output = inject_script(fragment)
|
36
|
+
script_injected ||= (output != fragment)
|
37
|
+
block.call(output)
|
38
|
+
end
|
39
|
+
|
40
|
+
unless script_injected
|
41
|
+
block.call(TEMPLATE.result(binding))
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def inject_script(fragment)
|
48
|
+
fragment.gsub(/((?:^\s*)?<\/body>)/i) do
|
49
|
+
TEMPLATE.result(binding) + $1
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def driver_script
|
54
|
+
Terminus.driver_script(@env['SERVER_NAME'])
|
55
|
+
end
|
56
|
+
|
57
|
+
def page_source
|
58
|
+
@source.inspect.gsub('</script>', '</scr"+"ipt>')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Terminus
|
2
|
+
class Proxy
|
3
|
+
|
4
|
+
class External < Rack::Proxy
|
5
|
+
def initialize(uri)
|
6
|
+
@uri = uri
|
7
|
+
end
|
8
|
+
|
9
|
+
def rewrite_env(env)
|
10
|
+
env = env.dup
|
11
|
+
env['SERVER_NAME'] = @uri.host
|
12
|
+
env['SERVER_PORT'] = @uri.port
|
13
|
+
env['HTTP_HOST'] = "#{@uri.host}:#{@uri.port}"
|
14
|
+
env
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(env)
|
18
|
+
response = super
|
19
|
+
response[2].extend(Rewrite)
|
20
|
+
response
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Terminus
|
2
|
+
class Proxy
|
3
|
+
|
4
|
+
module Rewrite
|
5
|
+
def each(&block)
|
6
|
+
handler = lambda do |fragment|
|
7
|
+
block.call(rewrite(fragment))
|
8
|
+
end
|
9
|
+
super(&handler)
|
10
|
+
end
|
11
|
+
|
12
|
+
def rewrite(fragment)
|
13
|
+
fragment.gsub(/\b(action|href)="([^"]*)"/i) do
|
14
|
+
%Q{#{$1}="#{ Terminus.rewrite_remote($2) }"}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
(function(){var a=(typeof this.global==='object')?this.global:this;a.JS=a.JS||{};JS.ENV=a})();JS.Package=function(a){var b=JS.Package.OrderedSet;JS.Package._5(this);this._0=a;this._2=new b();this._6=new b();this._c=new b();this._d=new b();this._3={};this._7={}};(function(d){d.displayName='Package';d.toString=function(){return d.displayName};d.log=function(a){if(typeof window==='undefined')return;if(typeof window.runtime==='object')window.runtime.trace(a);if(window.console&&console.info)console.info(a)};var p=d.OrderedSet=function(a){this._e=this.list=[];this._5={};if(!a)return;for(var b=0,c=a.length;b<c;b++)this.push(a[b])};p.prototype.push=function(a){var b=(a.id!==undefined)?a.id:a,c=this._5;if(c.hasOwnProperty(b))return;c[b]=this._e.length;this._e.push(a)};var m=d.Deferred=function(){this._f='deferred';this._g=null;this._h=[]};m.prototype.callback=function(a,b){if(this._f==='succeeded')a.call(b,this._g);else this._h.push([a,b])};m.prototype.succeed=function(a){this._f='succeeded';this._g=a;var b;while(b=this._h.shift())b[0].call(b[1],a)};d.ENV=JS.ENV;if((this.document||{}).getElementsByTagName){var q=document.getElementsByTagName('script')[0];d._w=(q.readyState!==undefined)}d.onerror=function(a){throw a};d._i=function(a){d.onerror(new Error(a));};var j=d.prototype,n=[['requires','_6'],['uses','_c'],['styling','_d']],o=n.length;while(o--)(function(pair){var r=pair[0],s=pair[1];j[r]=function(){var a=arguments.length,b;for(b=0;b<a;b++)this[s].push(arguments[b]);return this}})(n[o]);j.provides=function(){var a=arguments.length,b;for(b=0;b<a;b++){this._2.push(arguments[b]);d._8(arguments[b]).pkg=this}return this};j.setup=function(a){this._j=a;return this};j._r=function(a,b,c){if(this._7[a])return b.call(c);var e=this._3[a]=this._3[a]||[];e.push([b,c]);this._s()};j._1=function(a){if(this._7[a])return false;this._7[a]=true;var b=this._3[a];if(!b)return true;delete this._3[a];for(var c=0,e=b.length;c<e;c++)b[c][0].call(b[c][1]);return true};j._k=function(a){if(!a&&this.__isLoaded!==undefined)return this.__isLoaded;var b=this._2.list,c=b.length,e,f;while(c--){e=b[c];f=d._4(e,this._l);if(f!==undefined)continue;if(a)return d._i('Expected package at '+this._0+' to define '+e);else return this.__isLoaded=false}return this.__isLoaded=true};j._s=function(){if(!this._1('request'))return;this._t();var h=this._6.list.concat(this._c.list),i=h.length;d.when({load:h});d.when({complete:this._6.list},function(){d.when({complete:h,load:[this]},function(){this._1('complete')},this);var b=this,c=function(a){b._l=a;if(b._j)b._j();b._k(true);b._1('load')};if(this._k()){this._1('download');return this._1('load')}if(this._0===undefined)return d._i('No load path found for '+this._2.list[0]);typeof this._0==='function'?this._0(c):d.Loader.loadFile(this._0,c,this._m);if(!d.Loader.loadStyle)return;var e=this._d.list,f=e.length;while(f--)d.Loader.loadStyle(e[f]);this._1('download')},this)};j._t=function(){if(typeof this._0!=='string'||!d.Loader.fetch)return;this._m=this._m||d.Loader.fetch(this._0)};j.toString=function(){return'Package:'+this._2.list.join(',')};d.when=function(a,b,c){var e=[],f={},h,i,g;for(h in a){if(!a.hasOwnProperty(h))continue;f[h]=[];i=new d.OrderedSet(a[h]);g=i.list.length;while(g--)e.push([h,i.list[g],g])}var k=g=e.length;if(k===0)return b&&b.call(c,f);while(g--)(function(h){var l=d._9(h[1]);l._r(h[0],function(){f[h[0]][h[2]]=d._4(h[1],l._l);k-=1;if(k===0&&b)b.call(c,f)})})(e[g])};d._n=1;d._a={};d._b={};d._o=[];d._5=function(a){a.id=this._n;this._n+=1};d._p=function(a){var b=a.toString();return this._a[b]=this._a[b]||new this(a)};d._9=function(a){if(typeof a!=='string')return a;var b=this._8(a);if(b.pkg)return b.pkg;var c=this._u(a);if(c)return c;var e=new this();e.provides(a);return e};d.remove=function(a){var b=this._9(a);delete this._b[a];delete this._a[b._0]};d._v=function(a,b){this._o.push([a,b])};d._u=function(e){var f=this._o,h=f.length,i,g,k;for(i=0;i<h;i++){g=f[i];if(!g[0].test(e))continue;k=g[1].from+'/'+e.replace(/([a-z])([A-Z])/g,function(a,b,c){return b+'_'+c}).replace(/\./g,'/').toLowerCase()+'.js';var l=new this(k);l.provides(e);if(k=g[1].require)l.requires(e.replace(g[0],k));return l}return null};d._8=function(a){return this._b[a]=this._b[a]||{}};d._4=function(a,b){if(typeof a!=='string')return undefined;var c=b?{}:this._8(a);if(c.obj!==undefined)return c.obj;var e=b||this.ENV,f=a.split('.'),h;while(h=f.shift())e=e&&e[h];if(b&&e===undefined)return this._4(a);return c.obj=e}})(JS.Package);JS.Package.DomLoader={HOST_REGEX:/^https?\:\/\/[^\/]+/i,usable:function(){return!!JS.Package._4('window.document.getElementsByTagName')},__FILE__:function(){var a=document.getElementsByTagName('script');return a[a.length-1].src},fetch:function(a){this.HOST=this.HOST||this.HOST_REGEX.exec(window.location.href);var b=this.HOST_REGEX.exec(a);if(!this.HOST||(b&&b[0]!==this.HOST[0]))return null;JS.Package.log('Loading '+a);var c=new JS.Package.Deferred(),e=this,f=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();f.open('GET',a,true);f.onreadystatechange=function(){if(f.readyState!==4)return;f.onreadystatechange=e._q;c.succeed(f.responseText);f=null};f.send(null);return c},loadFile:function(c,e,f){var h=this,i=document.getElementsByTagName('head')[0],g=document.createElement('script');g.type='text/javascript';if(f)return f.callback(function(code){JS.Package.log('Executing '+c);i.appendChild(g);g.text=code;e()});JS.Package.log('Loading and executing '+c);g.src=c;g.onload=g.onreadystatechange=function(){var a=g.readyState,b=g.status;if(!a||a==='loaded'||a==='complete'||(a===4&&b===200)){e();g.onload=g.onreadystatechange=h._q;i=null;g=null}};i.appendChild(g)},loadStyle:function(a){var b=document.createElement('link');b.rel='stylesheet';b.type='text/css';b.href=a;document.getElementsByTagName('head')[0].appendChild(b)},_q:function(){}};JS.Package.Loader=JS.Package.DomLoader;JS.Package.DSL={__FILE__:function(){return JS.Package.Loader.__FILE__()},pkg:function(a,b){var c=b?JS.Package._p(b):JS.Package._9(a);c.provides(a);return c},file:function(a){return JS.Package._p(a)},load:function(a,b){JS.Package.Loader.loadFile(a,b)},autoload:function(a,b){JS.Package._v(a,b)}};JS.Package.DSL.loader=JS.Package.DSL.file;JS.Packages=function(a){a.call(JS.Package.DSL)};JS.require=function(){var b=[],c=0;while(typeof arguments[c]==='string'){b.push(arguments[c]);c+=1}var e=arguments[c],f=arguments[c+1];JS.Package.when({complete:b},function(a){if(!e)return;e.apply(f||null,a&&a.complete)})};
|
@@ -0,0 +1,43 @@
|
|
1
|
+
body {
|
2
|
+
background: #fff;
|
3
|
+
margin: 0;
|
4
|
+
padding: 0;
|
5
|
+
}
|
6
|
+
|
7
|
+
.bg {
|
8
|
+
position: absolute;
|
9
|
+
width: 100%;
|
10
|
+
height: 200px;
|
11
|
+
background: #f0f0f0;
|
12
|
+
border-bottom: 1px solid #ccc;
|
13
|
+
z-index: -1;
|
14
|
+
}
|
15
|
+
|
16
|
+
h1 {
|
17
|
+
margin: 0 auto;
|
18
|
+
padding: 40px 0 0;
|
19
|
+
width: 250px;
|
20
|
+
}
|
21
|
+
|
22
|
+
h1 a {
|
23
|
+
display: block;
|
24
|
+
background: url(/icon.png) center center no-repeat;
|
25
|
+
height: 0;
|
26
|
+
padding-top: 250px;
|
27
|
+
overflow: hidden;
|
28
|
+
}
|
29
|
+
|
30
|
+
p {
|
31
|
+
color: #666;
|
32
|
+
width: 250px;
|
33
|
+
margin: 40px auto;
|
34
|
+
font: 12px/1.5 FreeSans, Helvetica, Arial, sans-serif;
|
35
|
+
text-align: center;
|
36
|
+
}
|
37
|
+
|
38
|
+
p a {
|
39
|
+
color: #28aad4;
|
40
|
+
font-weight: bold;
|
41
|
+
text-decoration: none;
|
42
|
+
}
|
43
|
+
|
@@ -0,0 +1,150 @@
|
|
1
|
+
steal.then(function(){
|
2
|
+
Syn.key.browsers = {
|
3
|
+
webkit : {
|
4
|
+
'prevent':
|
5
|
+
{"keyup":[],"keydown":["char","keypress"],"keypress":["char"]},
|
6
|
+
'character':
|
7
|
+
{"keydown":[0,"key"],"keypress":["char","char"],"keyup":[0,"key"]},
|
8
|
+
'specialChars':
|
9
|
+
{"keydown":[0,"char"],"keyup":[0,"char"]},
|
10
|
+
'navigation':
|
11
|
+
{"keydown":[0,"key"],"keyup":[0,"key"]},
|
12
|
+
'special':
|
13
|
+
{"keydown":[0,"key"],"keyup":[0,"key"]},
|
14
|
+
'tab':
|
15
|
+
{"keydown":[0,"char"],"keyup":[0,"char"]},
|
16
|
+
'pause-break':
|
17
|
+
{"keydown":[0,"key"],"keyup":[0,"key"]},
|
18
|
+
'caps':
|
19
|
+
{"keydown":[0,"key"],"keyup":[0,"key"]},
|
20
|
+
'escape':
|
21
|
+
{"keydown":[0,"key"],"keyup":[0,"key"]},
|
22
|
+
'num-lock':
|
23
|
+
{"keydown":[0,"key"],"keyup":[0,"key"]},
|
24
|
+
'scroll-lock':
|
25
|
+
{"keydown":[0,"key"],"keyup":[0,"key"]},
|
26
|
+
'print':
|
27
|
+
{"keyup":[0,"key"]},
|
28
|
+
'function':
|
29
|
+
{"keydown":[0,"key"],"keyup":[0,"key"]},
|
30
|
+
'\r':
|
31
|
+
{"keydown":[0,"key"],"keypress":["char","key"],"keyup":[0,"key"]}
|
32
|
+
},
|
33
|
+
gecko : {
|
34
|
+
'prevent':
|
35
|
+
{"keyup":[],"keydown":["char"],"keypress":["char"]},
|
36
|
+
'character':
|
37
|
+
{"keydown":[0,"key"],"keypress":["char",0],"keyup":[0,"key"]},
|
38
|
+
'specialChars':
|
39
|
+
{"keydown":[0,"key"],"keypress":[0,"key"],"keyup":[0,"key"]},
|
40
|
+
'navigation':
|
41
|
+
{"keydown":[0,"key"],"keypress":[0,"key"],"keyup":[0,"key"]},
|
42
|
+
'special':
|
43
|
+
{"keydown":[0,"key"],"keyup":[0,"key"]},
|
44
|
+
'\t':
|
45
|
+
{"keydown":[0,"key"],"keypress":[0,"key"],"keyup":[0,"key"]},
|
46
|
+
'pause-break':
|
47
|
+
{"keydown":[0,"key"],"keypress":[0,"key"],"keyup":[0,"key"]},
|
48
|
+
'caps':
|
49
|
+
{"keydown":[0,"key"],"keyup":[0,"key"]},
|
50
|
+
'escape':
|
51
|
+
{"keydown":[0,"key"],"keypress":[0,"key"],"keyup":[0,"key"]},
|
52
|
+
'num-lock':
|
53
|
+
{"keydown":[0,"key"],"keyup":[0,"key"]},
|
54
|
+
'scroll-lock':
|
55
|
+
{"keydown":[0,"key"],"keyup":[0,"key"]},
|
56
|
+
'print':
|
57
|
+
{"keyup":[0,"key"]},
|
58
|
+
'function':
|
59
|
+
{"keydown":[0,"key"],"keyup":[0,"key"]},
|
60
|
+
'\r':
|
61
|
+
{"keydown":[0,"key"],"keypress":[0,"key"],"keyup":[0,"key"]}
|
62
|
+
},
|
63
|
+
msie : {
|
64
|
+
'prevent':{"keyup":[],"keydown":["char","keypress"],"keypress":["char"]},
|
65
|
+
'character':{"keydown":[null,"key"],"keypress":[null,"char"],"keyup":[null,"key"]},
|
66
|
+
'specialChars':{"keydown":[null,"char"],"keyup":[null,"char"]},
|
67
|
+
'navigation':{"keydown":[null,"key"],"keyup":[null,"key"]},
|
68
|
+
'special':{"keydown":[null,"key"],"keyup":[null,"key"]},
|
69
|
+
'tab':{"keydown":[null,"char"],"keyup":[null,"char"]},
|
70
|
+
'pause-break':{"keydown":[null,"key"],"keyup":[null,"key"]},
|
71
|
+
'caps':{"keydown":[null,"key"],"keyup":[null,"key"]},
|
72
|
+
'escape':{"keydown":[null,"key"],"keypress":[null,"key"],"keyup":[null,"key"]},
|
73
|
+
'num-lock':{"keydown":[null,"key"],"keyup":[null,"key"]},
|
74
|
+
'scroll-lock':{"keydown":[null,"key"],"keyup":[null,"key"]},
|
75
|
+
'print':{"keyup":[null,"key"]},
|
76
|
+
'function':{"keydown":[null,"key"],"keyup":[null,"key"]},
|
77
|
+
'\r':{"keydown":[null,"key"],"keypress":[null,"key"],"keyup":[null,"key"]}
|
78
|
+
},
|
79
|
+
opera : {
|
80
|
+
'prevent':
|
81
|
+
{"keyup":[],"keydown":[],"keypress":["char"]},
|
82
|
+
'character':
|
83
|
+
{"keydown":[null,"key"],"keypress":[null,"char"],"keyup":[null,"key"]},
|
84
|
+
'specialChars':
|
85
|
+
{"keydown":[null,"char"],"keypress":[null,"char"],"keyup":[null,"char"]},
|
86
|
+
'navigation':
|
87
|
+
{"keydown":[null,"key"],"keypress":[null,"key"]},
|
88
|
+
'special':
|
89
|
+
{"keydown":[null,"key"],"keypress":[null,"key"],"keyup":[null,"key"]},
|
90
|
+
'tab':
|
91
|
+
{"keydown":[null,"char"],"keypress":[null,"char"],"keyup":[null,"char"]},
|
92
|
+
'pause-break':
|
93
|
+
{"keydown":[null,"key"],"keypress":[null,"key"],"keyup":[null,"key"]},
|
94
|
+
'caps':
|
95
|
+
{"keydown":[null,"key"],"keyup":[null,"key"]},
|
96
|
+
'escape':
|
97
|
+
{"keydown":[null,"key"],"keypress":[null,"key"]},
|
98
|
+
'num-lock':
|
99
|
+
{"keyup":[null,"key"],"keydown":[null,"key"],"keypress":[null,"key"]},
|
100
|
+
'scroll-lock':
|
101
|
+
{"keydown":[null,"key"],"keypress":[null,"key"],"keyup":[null,"key"]},
|
102
|
+
'print':
|
103
|
+
{},
|
104
|
+
'function':
|
105
|
+
{"keydown":[null,"key"],"keypress":[null,"key"],"keyup":[null,"key"]},
|
106
|
+
'\r':
|
107
|
+
{"keydown":[null,"key"],"keypress":[null,"key"],"keyup":[null,"key"]}
|
108
|
+
}
|
109
|
+
};
|
110
|
+
|
111
|
+
Syn.mouse.browsers = {
|
112
|
+
webkit : {"right":{"mousedown":{"button":2,"which":3},"mouseup":{"button":2,"which":3},"contextmenu":{"button":2,"which":3}},
|
113
|
+
"left":{"mousedown":{"button":0,"which":1},"mouseup":{"button":0,"which":1},"click":{"button":0,"which":1}}},
|
114
|
+
opera: {"right":{"mousedown":{"button":2,"which":3},"mouseup":{"button":2,"which":3}},
|
115
|
+
"left":{"mousedown":{"button":0,"which":1},"mouseup":{"button":0,"which":1},"click":{"button":0,"which":1}}},
|
116
|
+
msie: { "right":{"mousedown":{"button":2},"mouseup":{"button":2},"contextmenu":{"button":0}},
|
117
|
+
"left":{"mousedown":{"button":1},"mouseup":{"button":1},"click":{"button":0}}},
|
118
|
+
chrome : {"right":{"mousedown":{"button":2,"which":3},"mouseup":{"button":2,"which":3},"contextmenu":{"button":2,"which":3}},
|
119
|
+
"left":{"mousedown":{"button":0,"which":1},"mouseup":{"button":0,"which":1},"click":{"button":0,"which":1}}},
|
120
|
+
gecko: {"left":{"mousedown":{"button":0,"which":1},"mouseup":{"button":0,"which":1},"click":{"button":0,"which":1}},
|
121
|
+
"right":{"mousedown":{"button":2,"which":3},"mouseup":{"button":2,"which":3},"contextmenu":{"button":2,"which":3}}}
|
122
|
+
}
|
123
|
+
|
124
|
+
//set browser
|
125
|
+
Syn.key.browser =
|
126
|
+
(function(){
|
127
|
+
if(Syn.key.browsers[window.navigator.userAgent]){
|
128
|
+
return Syn.key.browsers[window.navigator.userAgent];
|
129
|
+
}
|
130
|
+
for(var browser in Syn.browser){
|
131
|
+
if(Syn.browser[browser] && Syn.key.browsers[browser]){
|
132
|
+
return Syn.key.browsers[browser]
|
133
|
+
}
|
134
|
+
}
|
135
|
+
return Syn.key.browsers.gecko;
|
136
|
+
})();
|
137
|
+
|
138
|
+
Syn.mouse.browser =
|
139
|
+
(function(){
|
140
|
+
if(Syn.mouse.browsers[window.navigator.userAgent]){
|
141
|
+
return Syn.mouse.browsers[window.navigator.userAgent];
|
142
|
+
}
|
143
|
+
for(var browser in Syn.browser){
|
144
|
+
if(Syn.browser[browser] && Syn.mouse.browsers[browser]){
|
145
|
+
return Syn.mouse.browsers[browser]
|
146
|
+
}
|
147
|
+
}
|
148
|
+
return Syn.mouse.browsers.gecko;
|
149
|
+
})();
|
150
|
+
})
|