Commit b339c747a9943e9961239a234dcd6e16566a53e1

Authored by Dmitriy Zaporozhets
2 parents c7aeb512 245544a9

Merge pull request #1937 from riyad/add-file-line-links

Add file line links
Gemfile
... ... @@ -33,7 +33,7 @@ gem 'grit_ext', git: "https://github.com/gitlabhq/grit_ext.git", ref
33 33 gem "gitolite", '1.1.0'
34 34  
35 35 # Syntax highlighter
36   -gem "pygments.rb", "0.3.1"
  36 +gem "pygments.rb", git: "https://github.com/gitlabhq/pygments.rb.git", ref: '4db80c599067e2d5f23c5c243bf85b8ca0368ad4'
37 37  
38 38 # Language detection
39 39 gem "github-linguist", "~> 2.3.4" , require: "linguist"
... ...
Gemfile.lock
... ... @@ -42,6 +42,15 @@ GIT
42 42 rubyntlm (~> 0.1.1)
43 43  
44 44 GIT
  45 + remote: https://github.com/gitlabhq/pygments.rb.git
  46 + revision: 4db80c599067e2d5f23c5c243bf85b8ca0368ad4
  47 + ref: 4db80c599067e2d5f23c5c243bf85b8ca0368ad4
  48 + specs:
  49 + pygments.rb (0.3.2)
  50 + posix-spawn (~> 0.3.6)
  51 + yajl-ruby (~> 1.1.0)
  52 +
  53 +GIT
45 54 remote: https://github.com/gitlabhq/yaml_db.git
46 55 revision: 98e9a5dca43e3fedd3268c76a73af40d1bdf1dfd
47 56 ref: 98e9a5dca43e3fedd3268c76a73af40d1bdf1dfd
... ... @@ -271,9 +280,6 @@ GEM
271 280 coderay (~> 1.0.5)
272 281 method_source (~> 0.7.1)
273 282 slop (>= 2.4.4, < 3)
274   - pygments.rb (0.3.1)
275   - posix-spawn (~> 0.3.6)
276   - yajl-ruby (~> 1.1.0)
277 283 pyu-ruby-sasl (0.0.3.3)
278 284 quiet_assets (1.0.1)
279 285 railties (~> 3.1)
... ... @@ -470,7 +476,7 @@ DEPENDENCIES
470 476 pg
471 477 poltergeist
472 478 pry
473   - pygments.rb (= 0.3.1)
  479 + pygments.rb!
474 480 quiet_assets (= 1.0.1)
475 481 rack-mini-profiler
476 482 rails (= 3.2.9)
... ...
app/assets/javascripts/application.js
... ... @@ -13,6 +13,7 @@
13 13 //= require jquery.history
14 14 //= require jquery.waitforimages
15 15 //= require jquery.atwho
  16 +//= require jquery.scrollto
16 17 //= require bootstrap
17 18 //= require modernizr
18 19 //= require chosen-jquery
... ...
app/assets/javascripts/tree.js.coffee
... ... @@ -35,3 +35,22 @@ $ -&gt;
35 35 state = History.getState()
36 36 window.ajaxGet(state.url)
37 37 )(window)
  38 +
  39 + # See if there are lines selected
  40 + # "#L12" and "#L34-56" supported
  41 + highlightBlobLines = ->
  42 + if window.location.hash isnt ""
  43 + matches = window.location.hash.match /\#L(\d+)(\-(\d+))?/
  44 + first_line = parseInt matches[1]
  45 + last_line = parseInt matches[3]
  46 +
  47 + unless isNaN first_line
  48 + last_line = first_line if isNaN last_line
  49 + $("#tree-content-holder .highlight .line").removeClass("hll")
  50 + $("#LC#{line}").addClass("hll") for line in [first_line..last_line]
  51 + $("#L#{first_line}").ScrollTo()
  52 +
  53 + # Highlight the correct lines on load
  54 + highlightBlobLines()
  55 + # Highlight the correct lines when the hash part of the URL changes
  56 + $(window).on 'hashchange', highlightBlobLines
... ...
app/assets/stylesheets/gitlab_bootstrap/files.scss
... ... @@ -132,39 +132,73 @@
132 132 * Code file
133 133 */
134 134 &.code {
135   - padding:0;
136   - td.code {
137   - width: 100%;
138   - .highlight {
139   - margin-left: 55px;
140   - overflow:auto;
141   - overflow-y:hidden;
142   - }
143   - }
144   - .highlight pre {
145   - white-space: pre;
146   - word-wrap:normal;
147   - }
  135 + padding: 0;
148 136  
149   - table.highlighttable {
  137 + table.lines {
150 138 border: none;
151   - }
152   - body.project-page table.highlighttable td { border: none }
153   - table.highlighttable tr:hover { background:none;}
  139 + box-shadow: none;
  140 + margin: 0px;
  141 + padding: 0px;
  142 + table-layout: fixed;
154 143  
155   - table.highlighttable pre{
156   - line-height:16px !important;
157   - font-size:12px !important;
158   - }
  144 + pre {
  145 + background: none;
  146 + border: none;
  147 + font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
  148 + font-size: 12px !important;
  149 + line-height: 16px !important;
  150 + margin: 0;
  151 + padding: 10px 0;
  152 + }
  153 + td {
  154 + border: none;
  155 + margin: 0;
  156 + padding: 0;
  157 + vertical-align: top;
  158 +
  159 + &:first-child {
  160 + background: #eee;
  161 + width: 50px;
  162 + }
  163 + &:last-child {
  164 + }
  165 + }
  166 + tr:hover {
  167 + background: none;
  168 + }
159 169  
160   - table.highlighttable .linenodiv {
161   - a {
  170 + pre.line_numbers {
162 171 color: #666;
163   - }
164   - pre {
  172 + padding: 10px 6px 10px 0;
165 173 text-align: right;
166   - padding-right: 4px;
167   - color:#666;
  174 +
  175 + a {
  176 + color: #666;
  177 +
  178 + i {
  179 + display: none;
  180 + font-size: 14px;
  181 + line-height: 14px;
  182 + }
  183 + &:hover i {
  184 + display: inherit;
  185 + }
  186 + }
  187 + }
  188 +
  189 + .highlight {
  190 + border-left: 1px solid #DEE2E3;
  191 + overflow: auto;
  192 + overflow-y: hidden;
  193 +
  194 + pre {
  195 + white-space: pre;
  196 + word-wrap: normal;
  197 +
  198 + .line {
  199 + padding: 0 10px;
  200 + }
  201 + }
168 202 }
169 203 }
170 204 }
... ...
app/assets/stylesheets/highlight/dark.scss
1   -.black .highlighttable {
2   - td.linenos { border:none; }
3   - pre { color: #eee }
4   - .highlight { background: #333; border-left:1px solid #555; }
  1 +.black .lines .highlight {
  2 + background: #333;
  3 + pre { color: #eee; }
5 4  
6   - .hll { background-color: #ffffff }
  5 + .hll { display: block; background-color: darken($hover, 65%) }
7 6 .c { color: #888888; font-style: italic } /* Comment */
8 7 .err { color: #a61717; background-color: #e3d2d2 } /* Error */
9 8 .k { color: #CDA869; font-weight: bold } /* Keyword */
... ... @@ -22,43 +21,43 @@
22 21 .gs { font-weight: bold } /* Generic.Strong */
23 22 .gu { color: #606060 } /* Generic.Subheading */
24 23 .gt { color: #aa0000 } /* Generic.Traceback */
25   - .highlight .kc{font-weight:bold;} /* Keyword.Constant */
26   - .highlight .kd{font-weight:bold;} /* Keyword.Declaration */
27   - .highlight .kn{font-weight:bold;} /* Keyword.Namespace */
28   - .highlight .kp{font-weight:bold;} /* Keyword.Pseudo */
29   - .highlight .kr{font-weight:bold;} /* Keyword.Reserved */
30   - .highlight .kt{color:#458;font-weight:bold;} /* Keyword.Type */
  24 + .kc{font-weight:bold;} /* Keyword.Constant */
  25 + .kd{font-weight:bold;} /* Keyword.Declaration */
  26 + .kn{font-weight:bold;} /* Keyword.Namespace */
  27 + .kp{font-weight:bold;} /* Keyword.Pseudo */
  28 + .kr{font-weight:bold;} /* Keyword.Reserved */
  29 + .kt{color:#458;font-weight:bold;} /* Keyword.Type */
31 30 .m { color: #0000DD; font-weight: bold } /* Literal.Number */
32 31 .p { color: #eee; }
33 32 .s { color: #0AD; background-color: transparent } /* Literal.String */
34   - .highlight .na{color:#008080;} /* Name.Attribute */
35   - .highlight .nb{color:#0086B3;} /* Name.Builtin */
36   - .highlight .nc{color:#ccc;font-weight:bold;} /* Name.Class */
37   - .highlight .no{color:turquoise;} /* Name.Constant */
38   - .highlight .ni{color:#800080;}
39   - .highlight .ne{color:#900;font-weight:bold;} /* Name.Exception */
40   - .highlight .nf{color:#ccc;font-weight:bold;} /* Name.Function */
41   - .highlight .nn{color:#79C3E0;font-weight:bold;} /* Name.Namespace */
42   - .highlight .nt{color:#fc5;} /* Name.Tag */
43   - .highlight .nv{color:#FA4;} /* Name.Variable */
  33 + .na{color:#008080;} /* Name.Attribute */
  34 + .nb{color:#0086B3;} /* Name.Builtin */
  35 + .nc{color:#ccc;font-weight:bold;} /* Name.Class */
  36 + .no{color:turquoise;} /* Name.Constant */
  37 + .ni{color:#800080;}
  38 + .ne{color:#900;font-weight:bold;} /* Name.Exception */
  39 + .nf{color:#ccc;font-weight:bold;} /* Name.Function */
  40 + .nn{color:#79C3E0;font-weight:bold;} /* Name.Namespace */
  41 + .nt{color:#fc5;} /* Name.Tag */
  42 + .nv{color:#FA4;} /* Name.Variable */
44 43 .py { color: #336699; font-weight: bold } /* Name.Property */
45 44 .ow { color: #008800 } /* Operator.Word */
46 45 .w { color: #bbbbbb } /* Text.Whitespace */
47 46 .mf { color: #7AC; font-weight: bold } /* Literal.Number.Float */
48 47 .mh { color: #7AC; font-weight: bold } /* Literal.Number.Hex */
49   - .highlight .mi {color:#099;} /* Literal.Number.Integer */
  48 + .mi {color:#099;} /* Literal.Number.Integer */
50 49 .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
51 50 .sb { color: #dd2200; background-color: transparent; } /* Literal.String.Backtick */
52   - .highlight .sc{color:#d14;} /* Literal.String.Char */
  51 + .sc{color:#d14;} /* Literal.String.Char */
53 52 .sd { color: #dd2200; background-color: transparent; } /* Literal.String.Doc */
54   - .highlight .s2{color:orange;} /* Literal.String.Double */
55   - .highlight .se{color:orange;} /* Literal.String.Escape */
56   - .highlight .sh{color:orange;} /* Literal.String.Heredoc */
57   - .highlight .si{color:orange;} /* Literal.String.Interpol */
58   - .highlight .sx{color:orange;} /* Literal.String.Other */
59   - .highlight .sr{color:orange;} /* Literal.String.Regex */
60   - .highlight .s1{color:orange;} /* Literal.String.Single */
61   - .highlight .ss{color:orange;} /* Literal.String.Symbol */
  53 + .s2{color:orange;} /* Literal.String.Double */
  54 + .se{color:orange;} /* Literal.String.Escape */
  55 + .sh{color:orange;} /* Literal.String.Heredoc */
  56 + .si{color:orange;} /* Literal.String.Interpol */
  57 + .sx{color:orange;} /* Literal.String.Other */
  58 + .sr{color:orange;} /* Literal.String.Regex */
  59 + .s1{color:orange;} /* Literal.String.Single */
  60 + .ss{color:orange;} /* Literal.String.Symbol */
62 61 .bp { color: #D58 } /* Name.Builtin.Pseudo */
63 62 .vc { color: #336699 } /* Name.Variable.Class */
64 63 .vg { color: #dd7700 } /* Name.Variable.Global */
... ...
app/assets/stylesheets/highlight/white.scss
1   -table.highlighttable {
2   - margin:0px;
3   - padding:0px;
4   - font-size:12px;
5   - table-layout:fixed;
6   - background: #EEE;
7   - box-shadow: none;
8   - border: none;
9   - td.linenos {
10   - background:#eee;
11   - border-left:none;
12   - }
13   - td.code {
14   - border-right:none;
15   - }
16   -}
17   -
18   -
19   -td.code,
20   -td.linenos{
21   - padding:0;
22   - margin:0;
23   - border-top:0;
24   - vertical-align:top;
25   -}
26   -
27   -.highlighttable .highlight{
28   - background:none;
29   - padding:10px 0px 0px 10px;
30   - margin-left:0px;
31   - border-left: 1px solid #DEE2E3;
  1 +.white .lines .highlight {
32 2 background: white;
33   -}
34   -
35   -.linenodiv pre,
36   -.highlighttable .highlight pre{
37   - margin:0;
38   - padding:0;
39   - background:none;
40   - border:none;
41   -}
  3 + pre { color: #333; }
42 4  
43   -.linenodiv pre {
44   - white-space:pre-line;
  5 + .hll { display: block; background-color: $hover }
  6 + .c { color: #888888; font-style: italic } /* Comment */
  7 + .err { color: #a61717; background-color: #e3d2d2 } /* Error */
  8 + .k { color: #000000; font-weight: bold } /* Keyword */
  9 + .cm { color: #888888 } /* Comment.Multiline */
  10 + .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
  11 + .c1 { color: #888888 } /* Comment.Single */
  12 + .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
  13 + .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
  14 + .ge { font-style: italic } /* Generic.Emph */
  15 + .gr { color: #aa0000 } /* Generic.Error */
  16 + .gh { color: #303030 } /* Generic.Heading */
  17 + .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
  18 + .go { color: #888888 } /* Generic.Output */
  19 + .gp { color: #555555 } /* Generic.Prompt */
  20 + .gs { font-weight: bold } /* Generic.Strong */
  21 + .gu { color: #606060 } /* Generic.Subheading */
  22 + .gt { color: #aa0000 } /* Generic.Traceback */
  23 + .kc{font-weight:bold;} /* Keyword.Constant */
  24 + .kd{font-weight:bold;} /* Keyword.Declaration */
  25 + .kn{font-weight:bold;} /* Keyword.Namespace */
  26 + .kp{font-weight:bold;} /* Keyword.Pseudo */
  27 + .kr{font-weight:bold;} /* Keyword.Reserved */
  28 + .kt{color:#458;font-weight:bold;} /* Keyword.Type */
  29 + .m { color: #0000DD; font-weight: bold } /* Literal.Number */
  30 + .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
  31 + .na{color:#008080;} /* Name.Attribute */
  32 + .nb{color:#0086B3;} /* Name.Builtin */
  33 + .nc{color:#458;font-weight:bold;} /* Name.Class */
  34 + .no{color:#008080;} /* Name.Constant */
  35 + .ni{color:#800080;}
  36 + .ne{color:#900;font-weight:bold;} /* Name.Exception */
  37 + .nf{color:#900;font-weight:bold;} /* Name.Function */
  38 + .nn{color:#005;font-weight:bold;} /* Name.Namespace */
  39 + .nt{color:#000080;} /* Name.Tag */
  40 + .nv{color:#008080;} /* Name.Variable */
  41 + .py { color: #336699; font-weight: bold } /* Name.Property */
  42 + .ow { color: #008800 } /* Operator.Word */
  43 + .w { color: #bbbbbb } /* Text.Whitespace */
  44 + .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
  45 + .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
  46 + .mi {color:#099;} /* Literal.Number.Integer */
  47 + .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
  48 + .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
  49 + .sc{color:#d14;} /* Literal.String.Char */
  50 + .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
  51 + .s2{color:#d14;} /* Literal.String.Double */
  52 + .se{color:#d14;} /* Literal.String.Escape */
  53 + .sh{color:#d14;} /* Literal.String.Heredoc */
  54 + .si{color:#d14;} /* Literal.String.Interpol */
  55 + .sx{color:#d14;} /* Literal.String.Other */
  56 + .sr{color:#d14;} /* Literal.String.Regex */
  57 + .s1{color:#d14;} /* Literal.String.Single */
  58 + .ss{color:#d14;} /* Literal.String.Symbol */
  59 + .bp { color: #003388 } /* Name.Builtin.Pseudo */
  60 + .vc { color: #336699 } /* Name.Variable.Class */
  61 + .vg { color: #dd7700 } /* Name.Variable.Global */
  62 + .vi { color: #3333bb }
45 63 }
46 64  
47   -td.linenos {
48   - /*background:#F7F7F7;*/
49   - color:#666;
50   - padding:10px 0px 0px 10px;
51   - float:left;
52   - width:45px;
53   - border-right: 1px solid #ccc;
54   -
55   -}
56   -
57   -td.code .highlight {
58   - overflow: auto;
59   -}
60   -table.highlighttable pre{
61   - padding:0;
62   - margin:0;
63   - font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
64   - color: #333;
65   - text-align:left;
66   -}
67   -
68   -.git-empty .highlight {
69   - pre{
70   - padding:15px;
71   - line-height:2.0;
72   - margin:0;
73   - font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
74   - color: #333;
75   - text-align:left;}
76   - }
77   -
78   -.shadow{
  65 +.shadow {
79 66 -webkit-box-shadow:0 5px 15px #000;
80 67 -moz-box-shadow:0 5px 15px #000;
81 68 box-shadow:0 5px 15px #000;
82 69 }
83   -
84   -.hll { background-color: #ffffff }
85   -.c { color: #888888; font-style: italic } /* Comment */
86   -.err { color: #a61717; background-color: #e3d2d2 } /* Error */
87   -.k { color: #000000; font-weight: bold } /* Keyword */
88   -.cm { color: #888888 } /* Comment.Multiline */
89   -.cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
90   -.c1 { color: #888888 } /* Comment.Single */
91   -.cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
92   -.gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
93   -.ge { font-style: italic } /* Generic.Emph */
94   -.gr { color: #aa0000 } /* Generic.Error */
95   -.gh { color: #303030 } /* Generic.Heading */
96   -.gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
97   -.go { color: #888888 } /* Generic.Output */
98   -.gp { color: #555555 } /* Generic.Prompt */
99   -.gs { font-weight: bold } /* Generic.Strong */
100   -.gu { color: #606060 } /* Generic.Subheading */
101   -.gt { color: #aa0000 } /* Generic.Traceback */
102   -.highlight .kc{font-weight:bold;} /* Keyword.Constant */
103   -.highlight .kd{font-weight:bold;} /* Keyword.Declaration */
104   -.highlight .kn{font-weight:bold;} /* Keyword.Namespace */
105   -.highlight .kp{font-weight:bold;} /* Keyword.Pseudo */
106   -.highlight .kr{font-weight:bold;} /* Keyword.Reserved */
107   -.highlight .kt{color:#458;font-weight:bold;} /* Keyword.Type */
108   -.m { color: #0000DD; font-weight: bold } /* Literal.Number */
109   -.s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
110   -.highlight .na{color:#008080;} /* Name.Attribute */
111   -.highlight .nb{color:#0086B3;} /* Name.Builtin */
112   -.highlight .nc{color:#458;font-weight:bold;} /* Name.Class */
113   -.highlight .no{color:#008080;} /* Name.Constant */
114   -.highlight .ni{color:#800080;}
115   -.highlight .ne{color:#900;font-weight:bold;} /* Name.Exception */
116   -.highlight .nf{color:#900;font-weight:bold;} /* Name.Function */
117   -.highlight .nn{color:#005;font-weight:bold;} /* Name.Namespace */
118   -.highlight .nt{color:#000080;} /* Name.Tag */
119   -.highlight .nv{color:#008080;} /* Name.Variable */
120   -.py { color: #336699; font-weight: bold } /* Name.Property */
121   -.ow { color: #008800 } /* Operator.Word */
122   -.w { color: #bbbbbb } /* Text.Whitespace */
123   -.mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
124   -.mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
125   -.highlight .mi {color:#099;} /* Literal.Number.Integer */
126   -.mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
127   -.sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
128   -.highlight .sc{color:#d14;} /* Literal.String.Char */
129   -.sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
130   -.highlight .s2{color:#d14;} /* Literal.String.Double */
131   -.highlight .se{color:#d14;} /* Literal.String.Escape */
132   -.highlight .sh{color:#d14;} /* Literal.String.Heredoc */
133   -.highlight .si{color:#d14;} /* Literal.String.Interpol */
134   -.highlight .sx{color:#d14;} /* Literal.String.Other */
135   -.highlight .sr{color:#d14;} /* Literal.String.Regex */
136   -.highlight .s1{color:#d14;} /* Literal.String.Single */
137   -.highlight .ss{color:#d14;} /* Literal.String.Symbol */
138   -.bp { color: #003388 } /* Name.Builtin.Pseudo */
139   -.vc { color: #336699 } /* Name.Variable.Class */
140   -.vg { color: #dd7700 } /* Name.Variable.Global */
141   -.vi { color: #3333bb }
... ...
app/views/tree/blob/_text.html.haml
... ... @@ -10,6 +10,6 @@
10 10 - unless blob.empty?
11 11 %div{class: current_user.dark_scheme ? "black" : "white"}
12 12 = preserve do
13   - = raw blob.colorize(options: { linenos: true, lineanchors: :line, anchorlinenos: true })
  13 + = raw blob.colorize(formatter: :gitlab)
14 14 - else
15 15 %h4.nothing_here_message Empty file
... ...
vendor/assets/javascripts/jquery.scrollto.js 0 → 100644
... ... @@ -0,0 +1,225 @@
  1 +/**
  2 + * @depends jquery
  3 + * @name jquery.scrollto
  4 + * @package jquery-scrollto {@link http://balupton.com/projects/jquery-scrollto}
  5 + */
  6 +
  7 +/**
  8 + * jQuery Aliaser
  9 + */
  10 +(function(window,undefined){
  11 + // Prepare
  12 + var jQuery, $, ScrollTo;
  13 + jQuery = $ = window.jQuery;
  14 +
  15 + /**
  16 + * jQuery ScrollTo (balupton edition)
  17 + * @version 1.2.0
  18 + * @date July 9, 2012
  19 + * @since 0.1.0, August 27, 2010
  20 + * @package jquery-scrollto {@link http://balupton.com/projects/jquery-scrollto}
  21 + * @author Benjamin "balupton" Lupton {@link http://balupton.com}
  22 + * @copyright (c) 2010 Benjamin Arthur Lupton {@link http://balupton.com}
  23 + * @license MIT License {@link http://creativecommons.org/licenses/MIT/}
  24 + */
  25 + ScrollTo = $.ScrollTo = $.ScrollTo || {
  26 + /**
  27 + * The Default Configuration
  28 + */
  29 + config: {
  30 + duration: 400,
  31 + easing: 'swing',
  32 + callback: undefined,
  33 + durationMode: 'each',
  34 + offsetTop: 0,
  35 + offsetLeft: 0
  36 + },
  37 +
  38 + /**
  39 + * Configure ScrollTo
  40 + */
  41 + configure: function(options){
  42 + // Apply Options to Config
  43 + $.extend(ScrollTo.config, options||{});
  44 +
  45 + // Chain
  46 + return this;
  47 + },
  48 +
  49 + /**
  50 + * Perform the Scroll Animation for the Collections
  51 + * We use $inline here, so we can determine the actual offset start for each overflow:scroll item
  52 + * Each collection is for each overflow:scroll item
  53 + */
  54 + scroll: function(collections, config){
  55 + // Prepare
  56 + var collection, $container, container, $target, $inline, position,
  57 + containerScrollTop, containerScrollLeft,
  58 + containerScrollTopEnd, containerScrollLeftEnd,
  59 + startOffsetTop, targetOffsetTop, targetOffsetTopAdjusted,
  60 + startOffsetLeft, targetOffsetLeft, targetOffsetLeftAdjusted,
  61 + scrollOptions,
  62 + callback;
  63 +
  64 + // Determine the Scroll
  65 + collection = collections.pop();
  66 + $container = collection.$container;
  67 + container = $container.get(0);
  68 + $target = collection.$target;
  69 +
  70 + // Prepare the Inline Element of the Container
  71 + $inline = $('<span/>').css({
  72 + 'position': 'absolute',
  73 + 'top': '0px',
  74 + 'left': '0px'
  75 + });
  76 + position = $container.css('position');
  77 +
  78 + // Insert the Inline Element of the Container
  79 + $container.css('position','relative');
  80 + $inline.appendTo($container);
  81 +
  82 + // Determine the top offset
  83 + startOffsetTop = $inline.offset().top;
  84 + targetOffsetTop = $target.offset().top;
  85 + targetOffsetTopAdjusted = targetOffsetTop - startOffsetTop - parseInt(config.offsetTop,10);
  86 +
  87 + // Determine the left offset
  88 + startOffsetLeft = $inline.offset().left;
  89 + targetOffsetLeft = $target.offset().left;
  90 + targetOffsetLeftAdjusted = targetOffsetLeft - startOffsetLeft - parseInt(config.offsetLeft,10);
  91 +
  92 + // Determine current scroll positions
  93 + containerScrollTop = container.scrollTop;
  94 + containerScrollLeft = container.scrollLeft;
  95 +
  96 + // Reset the Inline Element of the Container
  97 + $inline.remove();
  98 + $container.css('position',position);
  99 +
  100 + // Prepare the scroll options
  101 + scrollOptions = {};
  102 +
  103 + // Prepare the callback
  104 + callback = function(event){
  105 + // Check
  106 + if ( collections.length === 0 ) {
  107 + // Callback
  108 + if ( typeof config.callback === 'function' ) {
  109 + config.callback.apply(this,[event]);
  110 + }
  111 + }
  112 + else {
  113 + // Recurse
  114 + ScrollTo.scroll(collections,config);
  115 + }
  116 + // Return true
  117 + return true;
  118 + };
  119 +
  120 + // Handle if we only want to scroll if we are outside the viewport
  121 + if ( config.onlyIfOutside ) {
  122 + // Determine current scroll positions
  123 + containerScrollTopEnd = containerScrollTop + $container.height();
  124 + containerScrollLeftEnd = containerScrollLeft + $container.width();
  125 +
  126 + // Check if we are in the range of the visible area of the container
  127 + if ( containerScrollTop < targetOffsetTopAdjusted && targetOffsetTopAdjusted < containerScrollTopEnd ) {
  128 + targetOffsetTopAdjusted = containerScrollTop;
  129 + }
  130 + if ( containerScrollLeft < targetOffsetLeftAdjusted && targetOffsetLeftAdjusted < containerScrollLeftEnd ) {
  131 + targetOffsetLeftAdjusted = containerScrollLeft;
  132 + }
  133 + }
  134 +
  135 + // Determine the scroll options
  136 + if ( targetOffsetTopAdjusted !== containerScrollTop ) {
  137 + scrollOptions.scrollTop = targetOffsetTopAdjusted;
  138 + }
  139 + if ( targetOffsetLeftAdjusted !== containerScrollLeft ) {
  140 + scrollOptions.scrollLeft = targetOffsetLeftAdjusted;
  141 + }
  142 +
  143 + // Perform the scroll
  144 + if ( $.browser.safari && container === document.body ) {
  145 + window.scrollTo(scrollOptions.scrollLeft, scrollOptions.scrollTop);
  146 + callback();
  147 + }
  148 + else if ( scrollOptions.scrollTop || scrollOptions.scrollLeft ) {
  149 + $container.animate(scrollOptions, config.duration, config.easing, callback);
  150 + }
  151 + else {
  152 + callback();
  153 + }
  154 +
  155 + // Return true
  156 + return true;
  157 + },
  158 +
  159 + /**
  160 + * ScrollTo the Element using the Options
  161 + */
  162 + fn: function(options){
  163 + // Prepare
  164 + var collections, config, $container, container;
  165 + collections = [];
  166 +
  167 + // Prepare
  168 + var $target = $(this);
  169 + if ( $target.length === 0 ) {
  170 + // Chain
  171 + return this;
  172 + }
  173 +
  174 + // Handle Options
  175 + config = $.extend({},ScrollTo.config,options);
  176 +
  177 + // Fetch
  178 + $container = $target.parent();
  179 + container = $container.get(0);
  180 +
  181 + // Cycle through the containers
  182 + while ( ($container.length === 1) && (container !== document.body) && (container !== document) ) {
  183 + // Check Container for scroll differences
  184 + var scrollTop, scrollLeft;
  185 + scrollTop = $container.css('overflow-y') !== 'visible' && container.scrollHeight !== container.clientHeight;
  186 + scrollLeft = $container.css('overflow-x') !== 'visible' && container.scrollWidth !== container.clientWidth;
  187 + if ( scrollTop || scrollLeft ) {
  188 + // Push the Collection
  189 + collections.push({
  190 + '$container': $container,
  191 + '$target': $target
  192 + });
  193 + // Update the Target
  194 + $target = $container;
  195 + }
  196 + // Update the Container
  197 + $container = $container.parent();
  198 + container = $container.get(0);
  199 + }
  200 +
  201 + // Add the final collection
  202 + collections.push({
  203 + '$container': $(
  204 + ($.browser.msie || $.browser.mozilla) ? 'html' : 'body'
  205 + ),
  206 + '$target': $target
  207 + });
  208 +
  209 + // Adjust the Config
  210 + if ( config.durationMode === 'all' ) {
  211 + config.duration /= collections.length;
  212 + }
  213 +
  214 + // Handle
  215 + ScrollTo.scroll(collections,config);
  216 +
  217 + // Chain
  218 + return this;
  219 + }
  220 + };
  221 +
  222 + // Apply our jQuery Prototype Function
  223 + $.fn.ScrollTo = $.ScrollTo.fn;
  224 +
  225 +})(window);
... ...