summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2012-11-16 03:46:43 -0800
committerDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2012-11-16 03:46:43 -0800
commitb339c747a9943e9961239a234dcd6e16566a53e1 (patch)
treef933d5d04aa155fb55941c5bc9175dbb6eacc917
parentc7aeb5127e3e7e852ed76096ad90a68ebd1195fa (diff)
parent245544a9d9807c6875eb7b3d63ab6d76468464d6 (diff)
downloadgitlab-ce-b339c747a9943e9961239a234dcd6e16566a53e1.tar.gz
Merge pull request #1937 from riyad/add-file-line-links
Add file line links
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock14
-rw-r--r--app/assets/javascripts/application.js1
-rw-r--r--app/assets/javascripts/tree.js.coffee19
-rw-r--r--app/assets/stylesheets/gitlab_bootstrap/files.scss88
-rw-r--r--app/assets/stylesheets/highlight/dark.scss61
-rw-r--r--app/assets/stylesheets/highlight/white.scss194
-rw-r--r--app/views/tree/blob/_text.html.haml2
-rw-r--r--vendor/assets/javascripts/jquery.scrollto.js225
9 files changed, 409 insertions, 197 deletions
diff --git a/Gemfile b/Gemfile
index aaf1f000ba8..d4cd45cef66 100644
--- a/Gemfile
+++ b/Gemfile
@@ -33,7 +33,7 @@ gem 'grit_ext', git: "https://github.com/gitlabhq/grit_ext.git", ref
gem "gitolite", '1.1.0'
# Syntax highlighter
-gem "pygments.rb", "0.3.1"
+gem "pygments.rb", git: "https://github.com/gitlabhq/pygments.rb.git", ref: '4db80c599067e2d5f23c5c243bf85b8ca0368ad4'
# Language detection
gem "github-linguist", "~> 2.3.4" , require: "linguist"
diff --git a/Gemfile.lock b/Gemfile.lock
index 76e92cd9d2f..3c1fa68dcb1 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -42,6 +42,15 @@ GIT
rubyntlm (~> 0.1.1)
GIT
+ remote: https://github.com/gitlabhq/pygments.rb.git
+ revision: 4db80c599067e2d5f23c5c243bf85b8ca0368ad4
+ ref: 4db80c599067e2d5f23c5c243bf85b8ca0368ad4
+ specs:
+ pygments.rb (0.3.2)
+ posix-spawn (~> 0.3.6)
+ yajl-ruby (~> 1.1.0)
+
+GIT
remote: https://github.com/gitlabhq/yaml_db.git
revision: 98e9a5dca43e3fedd3268c76a73af40d1bdf1dfd
ref: 98e9a5dca43e3fedd3268c76a73af40d1bdf1dfd
@@ -271,9 +280,6 @@ GEM
coderay (~> 1.0.5)
method_source (~> 0.7.1)
slop (>= 2.4.4, < 3)
- pygments.rb (0.3.1)
- posix-spawn (~> 0.3.6)
- yajl-ruby (~> 1.1.0)
pyu-ruby-sasl (0.0.3.3)
quiet_assets (1.0.1)
railties (~> 3.1)
@@ -470,7 +476,7 @@ DEPENDENCIES
pg
poltergeist
pry
- pygments.rb (= 0.3.1)
+ pygments.rb!
quiet_assets (= 1.0.1)
rack-mini-profiler
rails (= 3.2.9)
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index c4e9a1b027d..49effdf9c15 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -13,6 +13,7 @@
//= require jquery.history
//= require jquery.waitforimages
//= require jquery.atwho
+//= require jquery.scrollto
//= require bootstrap
//= require modernizr
//= require chosen-jquery
diff --git a/app/assets/javascripts/tree.js.coffee b/app/assets/javascripts/tree.js.coffee
index 37adef70f35..8ef41e16853 100644
--- a/app/assets/javascripts/tree.js.coffee
+++ b/app/assets/javascripts/tree.js.coffee
@@ -35,3 +35,22 @@ $ ->
state = History.getState()
window.ajaxGet(state.url)
)(window)
+
+ # See if there are lines selected
+ # "#L12" and "#L34-56" supported
+ highlightBlobLines = ->
+ if window.location.hash isnt ""
+ matches = window.location.hash.match /\#L(\d+)(\-(\d+))?/
+ first_line = parseInt matches[1]
+ last_line = parseInt matches[3]
+
+ unless isNaN first_line
+ last_line = first_line if isNaN last_line
+ $("#tree-content-holder .highlight .line").removeClass("hll")
+ $("#LC#{line}").addClass("hll") for line in [first_line..last_line]
+ $("#L#{first_line}").ScrollTo()
+
+ # Highlight the correct lines on load
+ highlightBlobLines()
+ # Highlight the correct lines when the hash part of the URL changes
+ $(window).on 'hashchange', highlightBlobLines
diff --git a/app/assets/stylesheets/gitlab_bootstrap/files.scss b/app/assets/stylesheets/gitlab_bootstrap/files.scss
index 580b74238ab..4887d1c9402 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/files.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/files.scss
@@ -132,39 +132,73 @@
* Code file
*/
&.code {
- padding:0;
- td.code {
- width: 100%;
- .highlight {
- margin-left: 55px;
- overflow:auto;
- overflow-y:hidden;
- }
- }
- .highlight pre {
- white-space: pre;
- word-wrap:normal;
- }
+ padding: 0;
- table.highlighttable {
+ table.lines {
border: none;
- }
- body.project-page table.highlighttable td { border: none }
- table.highlighttable tr:hover { background:none;}
+ box-shadow: none;
+ margin: 0px;
+ padding: 0px;
+ table-layout: fixed;
- table.highlighttable pre{
- line-height:16px !important;
- font-size:12px !important;
- }
+ pre {
+ background: none;
+ border: none;
+ font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
+ font-size: 12px !important;
+ line-height: 16px !important;
+ margin: 0;
+ padding: 10px 0;
+ }
+ td {
+ border: none;
+ margin: 0;
+ padding: 0;
+ vertical-align: top;
+
+ &:first-child {
+ background: #eee;
+ width: 50px;
+ }
+ &:last-child {
+ }
+ }
+ tr:hover {
+ background: none;
+ }
- table.highlighttable .linenodiv {
- a {
+ pre.line_numbers {
color: #666;
- }
- pre {
+ padding: 10px 6px 10px 0;
text-align: right;
- padding-right: 4px;
- color:#666;
+
+ a {
+ color: #666;
+
+ i {
+ display: none;
+ font-size: 14px;
+ line-height: 14px;
+ }
+ &:hover i {
+ display: inherit;
+ }
+ }
+ }
+
+ .highlight {
+ border-left: 1px solid #DEE2E3;
+ overflow: auto;
+ overflow-y: hidden;
+
+ pre {
+ white-space: pre;
+ word-wrap: normal;
+
+ .line {
+ padding: 0 10px;
+ }
+ }
}
}
}
diff --git a/app/assets/stylesheets/highlight/dark.scss b/app/assets/stylesheets/highlight/dark.scss
index 97c57835b75..0996cc772f4 100644
--- a/app/assets/stylesheets/highlight/dark.scss
+++ b/app/assets/stylesheets/highlight/dark.scss
@@ -1,9 +1,8 @@
-.black .highlighttable {
- td.linenos { border:none; }
- pre { color: #eee }
- .highlight { background: #333; border-left:1px solid #555; }
+.black .lines .highlight {
+ background: #333;
+ pre { color: #eee; }
- .hll { background-color: #ffffff }
+ .hll { display: block; background-color: darken($hover, 65%) }
.c { color: #888888; font-style: italic } /* Comment */
.err { color: #a61717; background-color: #e3d2d2 } /* Error */
.k { color: #CDA869; font-weight: bold } /* Keyword */
@@ -22,43 +21,43 @@
.gs { font-weight: bold } /* Generic.Strong */
.gu { color: #606060 } /* Generic.Subheading */
.gt { color: #aa0000 } /* Generic.Traceback */
- .highlight .kc{font-weight:bold;} /* Keyword.Constant */
- .highlight .kd{font-weight:bold;} /* Keyword.Declaration */
- .highlight .kn{font-weight:bold;} /* Keyword.Namespace */
- .highlight .kp{font-weight:bold;} /* Keyword.Pseudo */
- .highlight .kr{font-weight:bold;} /* Keyword.Reserved */
- .highlight .kt{color:#458;font-weight:bold;} /* Keyword.Type */
+ .kc{font-weight:bold;} /* Keyword.Constant */
+ .kd{font-weight:bold;} /* Keyword.Declaration */
+ .kn{font-weight:bold;} /* Keyword.Namespace */
+ .kp{font-weight:bold;} /* Keyword.Pseudo */
+ .kr{font-weight:bold;} /* Keyword.Reserved */
+ .kt{color:#458;font-weight:bold;} /* Keyword.Type */
.m { color: #0000DD; font-weight: bold } /* Literal.Number */
.p { color: #eee; }
.s { color: #0AD; background-color: transparent } /* Literal.String */
- .highlight .na{color:#008080;} /* Name.Attribute */
- .highlight .nb{color:#0086B3;} /* Name.Builtin */
- .highlight .nc{color:#ccc;font-weight:bold;} /* Name.Class */
- .highlight .no{color:turquoise;} /* Name.Constant */
- .highlight .ni{color:#800080;}
- .highlight .ne{color:#900;font-weight:bold;} /* Name.Exception */
- .highlight .nf{color:#ccc;font-weight:bold;} /* Name.Function */
- .highlight .nn{color:#79C3E0;font-weight:bold;} /* Name.Namespace */
- .highlight .nt{color:#fc5;} /* Name.Tag */
- .highlight .nv{color:#FA4;} /* Name.Variable */
+ .na{color:#008080;} /* Name.Attribute */
+ .nb{color:#0086B3;} /* Name.Builtin */
+ .nc{color:#ccc;font-weight:bold;} /* Name.Class */
+ .no{color:turquoise;} /* Name.Constant */
+ .ni{color:#800080;}
+ .ne{color:#900;font-weight:bold;} /* Name.Exception */
+ .nf{color:#ccc;font-weight:bold;} /* Name.Function */
+ .nn{color:#79C3E0;font-weight:bold;} /* Name.Namespace */
+ .nt{color:#fc5;} /* Name.Tag */
+ .nv{color:#FA4;} /* Name.Variable */
.py { color: #336699; font-weight: bold } /* Name.Property */
.ow { color: #008800 } /* Operator.Word */
.w { color: #bbbbbb } /* Text.Whitespace */
.mf { color: #7AC; font-weight: bold } /* Literal.Number.Float */
.mh { color: #7AC; font-weight: bold } /* Literal.Number.Hex */
- .highlight .mi {color:#099;} /* Literal.Number.Integer */
+ .mi {color:#099;} /* Literal.Number.Integer */
.mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.sb { color: #dd2200; background-color: transparent; } /* Literal.String.Backtick */
- .highlight .sc{color:#d14;} /* Literal.String.Char */
+ .sc{color:#d14;} /* Literal.String.Char */
.sd { color: #dd2200; background-color: transparent; } /* Literal.String.Doc */
- .highlight .s2{color:orange;} /* Literal.String.Double */
- .highlight .se{color:orange;} /* Literal.String.Escape */
- .highlight .sh{color:orange;} /* Literal.String.Heredoc */
- .highlight .si{color:orange;} /* Literal.String.Interpol */
- .highlight .sx{color:orange;} /* Literal.String.Other */
- .highlight .sr{color:orange;} /* Literal.String.Regex */
- .highlight .s1{color:orange;} /* Literal.String.Single */
- .highlight .ss{color:orange;} /* Literal.String.Symbol */
+ .s2{color:orange;} /* Literal.String.Double */
+ .se{color:orange;} /* Literal.String.Escape */
+ .sh{color:orange;} /* Literal.String.Heredoc */
+ .si{color:orange;} /* Literal.String.Interpol */
+ .sx{color:orange;} /* Literal.String.Other */
+ .sr{color:orange;} /* Literal.String.Regex */
+ .s1{color:orange;} /* Literal.String.Single */
+ .ss{color:orange;} /* Literal.String.Symbol */
.bp { color: #D58 } /* Name.Builtin.Pseudo */
.vc { color: #336699 } /* Name.Variable.Class */
.vg { color: #dd7700 } /* Name.Variable.Global */
diff --git a/app/assets/stylesheets/highlight/white.scss b/app/assets/stylesheets/highlight/white.scss
index 9b003b8ace5..d6792b37e9c 100644
--- a/app/assets/stylesheets/highlight/white.scss
+++ b/app/assets/stylesheets/highlight/white.scss
@@ -1,141 +1,69 @@
-table.highlighttable {
- margin:0px;
- padding:0px;
- font-size:12px;
- table-layout:fixed;
- background: #EEE;
- box-shadow: none;
- border: none;
- td.linenos {
- background:#eee;
- border-left:none;
- }
- td.code {
- border-right:none;
- }
-}
-
-
-td.code,
-td.linenos{
- padding:0;
- margin:0;
- border-top:0;
- vertical-align:top;
-}
-
-.highlighttable .highlight{
- background:none;
- padding:10px 0px 0px 10px;
- margin-left:0px;
- border-left: 1px solid #DEE2E3;
+.white .lines .highlight {
background: white;
-}
-
-.linenodiv pre,
-.highlighttable .highlight pre{
- margin:0;
- padding:0;
- background:none;
- border:none;
-}
+ pre { color: #333; }
-.linenodiv pre {
- white-space:pre-line;
+ .hll { display: block; background-color: $hover }
+ .c { color: #888888; font-style: italic } /* Comment */
+ .err { color: #a61717; background-color: #e3d2d2 } /* Error */
+ .k { color: #000000; font-weight: bold } /* Keyword */
+ .cm { color: #888888 } /* Comment.Multiline */
+ .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
+ .c1 { color: #888888 } /* Comment.Single */
+ .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
+ .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
+ .ge { font-style: italic } /* Generic.Emph */
+ .gr { color: #aa0000 } /* Generic.Error */
+ .gh { color: #303030 } /* Generic.Heading */
+ .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
+ .go { color: #888888 } /* Generic.Output */
+ .gp { color: #555555 } /* Generic.Prompt */
+ .gs { font-weight: bold } /* Generic.Strong */
+ .gu { color: #606060 } /* Generic.Subheading */
+ .gt { color: #aa0000 } /* Generic.Traceback */
+ .kc{font-weight:bold;} /* Keyword.Constant */
+ .kd{font-weight:bold;} /* Keyword.Declaration */
+ .kn{font-weight:bold;} /* Keyword.Namespace */
+ .kp{font-weight:bold;} /* Keyword.Pseudo */
+ .kr{font-weight:bold;} /* Keyword.Reserved */
+ .kt{color:#458;font-weight:bold;} /* Keyword.Type */
+ .m { color: #0000DD; font-weight: bold } /* Literal.Number */
+ .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
+ .na{color:#008080;} /* Name.Attribute */
+ .nb{color:#0086B3;} /* Name.Builtin */
+ .nc{color:#458;font-weight:bold;} /* Name.Class */
+ .no{color:#008080;} /* Name.Constant */
+ .ni{color:#800080;}
+ .ne{color:#900;font-weight:bold;} /* Name.Exception */
+ .nf{color:#900;font-weight:bold;} /* Name.Function */
+ .nn{color:#005;font-weight:bold;} /* Name.Namespace */
+ .nt{color:#000080;} /* Name.Tag */
+ .nv{color:#008080;} /* Name.Variable */
+ .py { color: #336699; font-weight: bold } /* Name.Property */
+ .ow { color: #008800 } /* Operator.Word */
+ .w { color: #bbbbbb } /* Text.Whitespace */
+ .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
+ .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
+ .mi {color:#099;} /* Literal.Number.Integer */
+ .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
+ .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
+ .sc{color:#d14;} /* Literal.String.Char */
+ .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
+ .s2{color:#d14;} /* Literal.String.Double */
+ .se{color:#d14;} /* Literal.String.Escape */
+ .sh{color:#d14;} /* Literal.String.Heredoc */
+ .si{color:#d14;} /* Literal.String.Interpol */
+ .sx{color:#d14;} /* Literal.String.Other */
+ .sr{color:#d14;} /* Literal.String.Regex */
+ .s1{color:#d14;} /* Literal.String.Single */
+ .ss{color:#d14;} /* Literal.String.Symbol */
+ .bp { color: #003388 } /* Name.Builtin.Pseudo */
+ .vc { color: #336699 } /* Name.Variable.Class */
+ .vg { color: #dd7700 } /* Name.Variable.Global */
+ .vi { color: #3333bb }
}
-td.linenos {
- /*background:#F7F7F7;*/
- color:#666;
- padding:10px 0px 0px 10px;
- float:left;
- width:45px;
- border-right: 1px solid #ccc;
-
-}
-
-td.code .highlight {
- overflow: auto;
-}
-table.highlighttable pre{
- padding:0;
- margin:0;
- font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
- color: #333;
- text-align:left;
-}
-
-.git-empty .highlight {
- pre{
- padding:15px;
- line-height:2.0;
- margin:0;
- font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
- color: #333;
- text-align:left;}
- }
-
-.shadow{
+.shadow {
-webkit-box-shadow:0 5px 15px #000;
-moz-box-shadow:0 5px 15px #000;
box-shadow:0 5px 15px #000;
}
-
-.hll { background-color: #ffffff }
-.c { color: #888888; font-style: italic } /* Comment */
-.err { color: #a61717; background-color: #e3d2d2 } /* Error */
-.k { color: #000000; font-weight: bold } /* Keyword */
-.cm { color: #888888 } /* Comment.Multiline */
-.cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
-.c1 { color: #888888 } /* Comment.Single */
-.cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
-.gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
-.ge { font-style: italic } /* Generic.Emph */
-.gr { color: #aa0000 } /* Generic.Error */
-.gh { color: #303030 } /* Generic.Heading */
-.gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
-.go { color: #888888 } /* Generic.Output */
-.gp { color: #555555 } /* Generic.Prompt */
-.gs { font-weight: bold } /* Generic.Strong */
-.gu { color: #606060 } /* Generic.Subheading */
-.gt { color: #aa0000 } /* Generic.Traceback */
-.highlight .kc{font-weight:bold;} /* Keyword.Constant */
-.highlight .kd{font-weight:bold;} /* Keyword.Declaration */
-.highlight .kn{font-weight:bold;} /* Keyword.Namespace */
-.highlight .kp{font-weight:bold;} /* Keyword.Pseudo */
-.highlight .kr{font-weight:bold;} /* Keyword.Reserved */
-.highlight .kt{color:#458;font-weight:bold;} /* Keyword.Type */
-.m { color: #0000DD; font-weight: bold } /* Literal.Number */
-.s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
-.highlight .na{color:#008080;} /* Name.Attribute */
-.highlight .nb{color:#0086B3;} /* Name.Builtin */
-.highlight .nc{color:#458;font-weight:bold;} /* Name.Class */
-.highlight .no{color:#008080;} /* Name.Constant */
-.highlight .ni{color:#800080;}
-.highlight .ne{color:#900;font-weight:bold;} /* Name.Exception */
-.highlight .nf{color:#900;font-weight:bold;} /* Name.Function */
-.highlight .nn{color:#005;font-weight:bold;} /* Name.Namespace */
-.highlight .nt{color:#000080;} /* Name.Tag */
-.highlight .nv{color:#008080;} /* Name.Variable */
-.py { color: #336699; font-weight: bold } /* Name.Property */
-.ow { color: #008800 } /* Operator.Word */
-.w { color: #bbbbbb } /* Text.Whitespace */
-.mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
-.mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
-.highlight .mi {color:#099;} /* Literal.Number.Integer */
-.mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
-.sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
-.highlight .sc{color:#d14;} /* Literal.String.Char */
-.sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
-.highlight .s2{color:#d14;} /* Literal.String.Double */
-.highlight .se{color:#d14;} /* Literal.String.Escape */
-.highlight .sh{color:#d14;} /* Literal.String.Heredoc */
-.highlight .si{color:#d14;} /* Literal.String.Interpol */
-.highlight .sx{color:#d14;} /* Literal.String.Other */
-.highlight .sr{color:#d14;} /* Literal.String.Regex */
-.highlight .s1{color:#d14;} /* Literal.String.Single */
-.highlight .ss{color:#d14;} /* Literal.String.Symbol */
-.bp { color: #003388 } /* Name.Builtin.Pseudo */
-.vc { color: #336699 } /* Name.Variable.Class */
-.vg { color: #dd7700 } /* Name.Variable.Global */
-.vi { color: #3333bb }
diff --git a/app/views/tree/blob/_text.html.haml b/app/views/tree/blob/_text.html.haml
index 3b7f293a35c..9e0f4bc4bc1 100644
--- a/app/views/tree/blob/_text.html.haml
+++ b/app/views/tree/blob/_text.html.haml
@@ -10,6 +10,6 @@
- unless blob.empty?
%div{class: current_user.dark_scheme ? "black" : "white"}
= preserve do
- = raw blob.colorize(options: { linenos: true, lineanchors: :line, anchorlinenos: true })
+ = raw blob.colorize(formatter: :gitlab)
- else
%h4.nothing_here_message Empty file
diff --git a/vendor/assets/javascripts/jquery.scrollto.js b/vendor/assets/javascripts/jquery.scrollto.js
new file mode 100644
index 00000000000..7f10b7f1082
--- /dev/null
+++ b/vendor/assets/javascripts/jquery.scrollto.js
@@ -0,0 +1,225 @@
+/**
+ * @depends jquery
+ * @name jquery.scrollto
+ * @package jquery-scrollto {@link http://balupton.com/projects/jquery-scrollto}
+ */
+
+/**
+ * jQuery Aliaser
+ */
+(function(window,undefined){
+ // Prepare
+ var jQuery, $, ScrollTo;
+ jQuery = $ = window.jQuery;
+
+ /**
+ * jQuery ScrollTo (balupton edition)
+ * @version 1.2.0
+ * @date July 9, 2012
+ * @since 0.1.0, August 27, 2010
+ * @package jquery-scrollto {@link http://balupton.com/projects/jquery-scrollto}
+ * @author Benjamin "balupton" Lupton {@link http://balupton.com}
+ * @copyright (c) 2010 Benjamin Arthur Lupton {@link http://balupton.com}
+ * @license MIT License {@link http://creativecommons.org/licenses/MIT/}
+ */
+ ScrollTo = $.ScrollTo = $.ScrollTo || {
+ /**
+ * The Default Configuration
+ */
+ config: {
+ duration: 400,
+ easing: 'swing',
+ callback: undefined,
+ durationMode: 'each',
+ offsetTop: 0,
+ offsetLeft: 0
+ },
+
+ /**
+ * Configure ScrollTo
+ */
+ configure: function(options){
+ // Apply Options to Config
+ $.extend(ScrollTo.config, options||{});
+
+ // Chain
+ return this;
+ },
+
+ /**
+ * Perform the Scroll Animation for the Collections
+ * We use $inline here, so we can determine the actual offset start for each overflow:scroll item
+ * Each collection is for each overflow:scroll item
+ */
+ scroll: function(collections, config){
+ // Prepare
+ var collection, $container, container, $target, $inline, position,
+ containerScrollTop, containerScrollLeft,
+ containerScrollTopEnd, containerScrollLeftEnd,
+ startOffsetTop, targetOffsetTop, targetOffsetTopAdjusted,
+ startOffsetLeft, targetOffsetLeft, targetOffsetLeftAdjusted,
+ scrollOptions,
+ callback;
+
+ // Determine the Scroll
+ collection = collections.pop();
+ $container = collection.$container;
+ container = $container.get(0);
+ $target = collection.$target;
+
+ // Prepare the Inline Element of the Container
+ $inline = $('<span/>').css({
+ 'position': 'absolute',
+ 'top': '0px',
+ 'left': '0px'
+ });
+ position = $container.css('position');
+
+ // Insert the Inline Element of the Container
+ $container.css('position','relative');
+ $inline.appendTo($container);
+
+ // Determine the top offset
+ startOffsetTop = $inline.offset().top;
+ targetOffsetTop = $target.offset().top;
+ targetOffsetTopAdjusted = targetOffsetTop - startOffsetTop - parseInt(config.offsetTop,10);
+
+ // Determine the left offset
+ startOffsetLeft = $inline.offset().left;
+ targetOffsetLeft = $target.offset().left;
+ targetOffsetLeftAdjusted = targetOffsetLeft - startOffsetLeft - parseInt(config.offsetLeft,10);
+
+ // Determine current scroll positions
+ containerScrollTop = container.scrollTop;
+ containerScrollLeft = container.scrollLeft;
+
+ // Reset the Inline Element of the Container
+ $inline.remove();
+ $container.css('position',position);
+
+ // Prepare the scroll options
+ scrollOptions = {};
+
+ // Prepare the callback
+ callback = function(event){
+ // Check
+ if ( collections.length === 0 ) {
+ // Callback
+ if ( typeof config.callback === 'function' ) {
+ config.callback.apply(this,[event]);
+ }
+ }
+ else {
+ // Recurse
+ ScrollTo.scroll(collections,config);
+ }
+ // Return true
+ return true;
+ };
+
+ // Handle if we only want to scroll if we are outside the viewport
+ if ( config.onlyIfOutside ) {
+ // Determine current scroll positions
+ containerScrollTopEnd = containerScrollTop + $container.height();
+ containerScrollLeftEnd = containerScrollLeft + $container.width();
+
+ // Check if we are in the range of the visible area of the container
+ if ( containerScrollTop < targetOffsetTopAdjusted && targetOffsetTopAdjusted < containerScrollTopEnd ) {
+ targetOffsetTopAdjusted = containerScrollTop;
+ }
+ if ( containerScrollLeft < targetOffsetLeftAdjusted && targetOffsetLeftAdjusted < containerScrollLeftEnd ) {
+ targetOffsetLeftAdjusted = containerScrollLeft;
+ }
+ }
+
+ // Determine the scroll options
+ if ( targetOffsetTopAdjusted !== containerScrollTop ) {
+ scrollOptions.scrollTop = targetOffsetTopAdjusted;
+ }
+ if ( targetOffsetLeftAdjusted !== containerScrollLeft ) {
+ scrollOptions.scrollLeft = targetOffsetLeftAdjusted;
+ }
+
+ // Perform the scroll
+ if ( $.browser.safari && container === document.body ) {
+ window.scrollTo(scrollOptions.scrollLeft, scrollOptions.scrollTop);
+ callback();
+ }
+ else if ( scrollOptions.scrollTop || scrollOptions.scrollLeft ) {
+ $container.animate(scrollOptions, config.duration, config.easing, callback);
+ }
+ else {
+ callback();
+ }
+
+ // Return true
+ return true;
+ },
+
+ /**
+ * ScrollTo the Element using the Options
+ */
+ fn: function(options){
+ // Prepare
+ var collections, config, $container, container;
+ collections = [];
+
+ // Prepare
+ var $target = $(this);
+ if ( $target.length === 0 ) {
+ // Chain
+ return this;
+ }
+
+ // Handle Options
+ config = $.extend({},ScrollTo.config,options);
+
+ // Fetch
+ $container = $target.parent();
+ container = $container.get(0);
+
+ // Cycle through the containers
+ while ( ($container.length === 1) && (container !== document.body) && (container !== document) ) {
+ // Check Container for scroll differences
+ var scrollTop, scrollLeft;
+ scrollTop = $container.css('overflow-y') !== 'visible' && container.scrollHeight !== container.clientHeight;
+ scrollLeft = $container.css('overflow-x') !== 'visible' && container.scrollWidth !== container.clientWidth;
+ if ( scrollTop || scrollLeft ) {
+ // Push the Collection
+ collections.push({
+ '$container': $container,
+ '$target': $target
+ });
+ // Update the Target
+ $target = $container;
+ }
+ // Update the Container
+ $container = $container.parent();
+ container = $container.get(0);
+ }
+
+ // Add the final collection
+ collections.push({
+ '$container': $(
+ ($.browser.msie || $.browser.mozilla) ? 'html' : 'body'
+ ),
+ '$target': $target
+ });
+
+ // Adjust the Config
+ if ( config.durationMode === 'all' ) {
+ config.duration /= collections.length;
+ }
+
+ // Handle
+ ScrollTo.scroll(collections,config);
+
+ // Chain
+ return this;
+ }
+ };
+
+ // Apply our jQuery Prototype Function
+ $.fn.ScrollTo = $.ScrollTo.fn;
+
+})(window);