omf_web 1.2.5 → 1.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. data/lib/omf-web/content/content_proxy.rb +28 -15
  2. data/lib/omf-web/content/file_repository.rb +16 -57
  3. data/lib/omf-web/content/git_repository.rb +2 -121
  4. data/lib/omf-web/content/irods_repository.rb +2 -0
  5. data/lib/omf-web/content/repository.rb +121 -10
  6. data/lib/omf-web/content/static_repository.rb +3 -3
  7. data/lib/omf-web/rack/content_handler.rb +8 -6
  8. data/lib/omf-web/theme.rb +16 -2
  9. data/lib/omf-web/thin/logging.rb +13 -4
  10. data/lib/omf-web/version.rb +1 -1
  11. data/lib/omf-web/widget/text/maruku/output/to_html.rb +29 -23
  12. data/lib/omf-web/widget/text/maruku.rb +20 -5
  13. data/omf_web.gemspec +1 -1
  14. data/share/htdocs/graph/js/code_mirror.js +2 -1
  15. data/share/htdocs/vendor/VERSION_MAP.yaml +1 -0
  16. data/share/htdocs/vendor/smartmenus-0.9.6/LICENSE-MIT +22 -0
  17. data/share/htdocs/vendor/smartmenus-0.9.6/README.md +26 -0
  18. data/share/htdocs/vendor/smartmenus-0.9.6/addons/bootstrap/jquery.smartmenus.bootstrap.css +103 -0
  19. data/share/htdocs/vendor/smartmenus-0.9.6/addons/bootstrap/jquery.smartmenus.bootstrap.js +72 -0
  20. data/share/htdocs/vendor/smartmenus-0.9.6/addons/bootstrap/jquery.smartmenus.bootstrap.min.js +3 -0
  21. data/share/htdocs/vendor/smartmenus-0.9.6/addons/keyboard/jquery.smartmenus.keyboard.js +192 -0
  22. data/share/htdocs/vendor/smartmenus-0.9.6/addons/keyboard/jquery.smartmenus.keyboard.min.js +3 -0
  23. data/share/htdocs/vendor/smartmenus-0.9.6/css/sm-blue/css-gradients-fallback/current-item-bg.png +0 -0
  24. data/share/htdocs/vendor/smartmenus-0.9.6/css/sm-blue/css-gradients-fallback/main-item-hover-bg.png +0 -0
  25. data/share/htdocs/vendor/smartmenus-0.9.6/css/sm-blue/css-gradients-fallback/main-menu-bg.png +0 -0
  26. data/share/htdocs/vendor/smartmenus-0.9.6/css/sm-blue/css-gradients-fallback/sub-item-hover-bg.png +0 -0
  27. data/share/htdocs/vendor/smartmenus-0.9.6/css/sm-blue/css-gradients-fallback/vertical-main-item-bg.png +0 -0
  28. data/share/htdocs/vendor/smartmenus-0.9.6/css/sm-blue/sm-blue.css +409 -0
  29. data/share/htdocs/vendor/smartmenus-0.9.6/css/sm-clean/sm-clean.css +315 -0
  30. data/share/htdocs/vendor/smartmenus-0.9.6/css/sm-core-css.css +23 -0
  31. data/share/htdocs/vendor/smartmenus-0.9.6/css/sm-mint/sm-mint.css +320 -0
  32. data/share/htdocs/vendor/smartmenus-0.9.6/css/sm-simple/sm-simple.css +218 -0
  33. data/share/htdocs/vendor/smartmenus-0.9.6/jquery.smartmenus.js +1041 -0
  34. data/share/htdocs/vendor/smartmenus-0.9.6/jquery.smartmenus.min.js +3 -0
  35. metadata +218 -229
@@ -1,7 +1,7 @@
1
1
 
2
2
  module OMF
3
3
  module Web
4
- VERSION = '1.2.5'
4
+ VERSION = '1.2.6'
5
5
  # Used for finding the example directory
6
6
  TOP_DIR = File.dirname(File.dirname(File.dirname(__FILE__)))
7
7
  end
@@ -467,7 +467,10 @@ It is copied as a standard HTML attribute.
467
467
  dt.text = ' ';
468
468
  p = wrap_as_element('p')
469
469
  p.attributes['class'] = 'content'
470
- [Text.new("\n"), p, dt, Text.new("\n")]
470
+ p.attributes['line_no'] = Thread.current['maruku.line_no']
471
+ p.attributes['delegate'] = 'plan' # should most likely go into the js column handler
472
+ #[Text.new("\n"), p, dt, Text.new("\n")]
473
+ [Text.new("\n"), p, Text.new("\n")]
471
474
  end
472
475
  def to_html_ol; add_ws wrap_as_element('ol') end
473
476
  def to_html_li; add_ws wrap_as_element('li') end
@@ -1013,25 +1016,28 @@ If true, raw HTML is discarded from the output.
1013
1016
  " for object #{c.inspect[0,300]}"
1014
1017
  end
1015
1018
 
1016
- if method == 'to_html_header'
1017
- if res.length > 1
1018
- res.pop
1019
- s = res[-1][-1]
1020
- e.each do |el| s << el end
1021
- e = res[-1]
1022
- end
1023
- e << (s = Element.new('section'))
1024
- #puts c.inspect
1025
- s.attributes['line_no'] = c.line_no
1026
- s.attributes['level'] = c.level
1019
+ unless (Thread.current['maruku_context'] || {})[:suppress_section]
1020
+ if method == 'to_html_header'
1021
+ if res.length > 1
1022
+ res.pop
1023
+ s = res[-1][-1]
1024
+ e.each do |el| s << el end
1025
+ e = res[-1]
1026
+ end
1027
+
1028
+ # Wrap into 'section' to more easily find back into MD from html
1029
+ e << (s = Element.new('section'))
1030
+ s.attributes['line_no'] = c.line_no
1031
+ s.attributes['level'] = c.level
1027
1032
 
1028
- toc = Thread.current['maruku.toc'] ||= []
1029
- li = c.level - 1
1030
- toc[li] = toc[li] ? (toc[li] + 1) : 1
1031
- s.attributes['toc'] = toc.map {|l| l ? l : 1 }.join('.')
1033
+ toc = Thread.current['maruku.toc'] ||= []
1034
+ li = c.level - 1
1035
+ toc[li] = toc[li] ? (toc[li] + 1) : 1
1036
+ s.attributes['toc'] = toc.map {|l| l ? l : 1 }.join('.')
1032
1037
 
1033
- res << (e = [])
1038
+ res << (e = [])
1034
1039
 
1040
+ end
1035
1041
  end
1036
1042
 
1037
1043
  if h.kind_of?Array
@@ -1042,12 +1048,12 @@ If true, raw HTML is discarded from the output.
1042
1048
  # puts "LOOP ENDN res: #{res.inspect} -- e: #{e.inspect}"
1043
1049
  end
1044
1050
  # puts "after: #{res.inspect} e: #{e.inspect}"
1045
- if res.length > 1
1046
- res.pop
1047
- s = res[-1][-1]
1048
- e.each do |el| s << el end
1049
- e = res[-1]
1050
- end
1051
+ if res.length > 1
1052
+ res.pop
1053
+ s = res[-1][-1]
1054
+ e.each do |el| s << el end
1055
+ e = res[-1]
1056
+ end
1051
1057
  #puts e.inspect
1052
1058
  e
1053
1059
  end
@@ -5,6 +5,7 @@ require 'maruku'
5
5
  require 'maruku/ext/math'
6
6
  # Monkey patches to add line numbers to html output
7
7
 
8
+ require 'omf_base/lobject'
8
9
  require 'omf_web'
9
10
  require 'omf-web/widget/text/maruku/input/parse_block'
10
11
  require 'omf-web/widget/text/maruku/output/to_html'
@@ -132,11 +133,25 @@ module OMF::Web::Widget::Text
132
133
  end # OMF::Web::Widget::Text
133
134
 
134
135
  if __FILE__ == $0
135
- unless fname = ARGV[0]
136
- puts "ERROR: Missing file name"
137
- exit -1
136
+ OMF::Base::Loggable.init_log 'maruku'
137
+
138
+ if fname = ARGV[0]
139
+ content = File.open(fname).read
140
+ else
141
+ content = %{
142
+ # Lorem ipsum dolor sit
143
+
144
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin
145
+ sollicitudin nibh eu ligula lobortis ornare. Sed nibh nibh,
146
+ ullamcorper at vehicula ac, molestie ac nunc.
147
+
148
+ ## Cras ut volutpat magna
149
+
150
+ Duis sodales, nisi vel pellentesque imperdiet, nisi massa accumsan
151
+ lorem, gravida scelerisque velit est vitae eros. Suspendisse eu
152
+ lacinia elit.
153
+ }
138
154
  end
139
- content = File.open(fname).read
140
155
  x = OMF::Web::Widget::Text::Maruku.format_content(content)
141
- puts x.to_html
156
+ puts x.to_html(suppress_section: false)
142
157
  end
data/omf_web.gemspec CHANGED
@@ -30,7 +30,7 @@ Gem::Specification.new do |s|
30
30
  s.add_runtime_dependency "maruku", "~> 0.6.0"
31
31
  s.add_runtime_dependency "ritex", "~> 1.0.0"
32
32
  s.add_runtime_dependency "json", "~> 1.7.0"
33
- s.add_runtime_dependency "grit", "~> 2.5.0"
33
+ s.add_runtime_dependency "gitlab-grit"
34
34
  s.add_runtime_dependency "websocket-rack", "~> 0.4.0"
35
35
  s.add_runtime_dependency "rack-accept", "~> 0.4.0"
36
36
  s.add_runtime_dependency "i18n"
@@ -47,6 +47,7 @@ define(["graph/abstract_widget"], function (abstract_widget) {
47
47
  lineNumbers: true,
48
48
  matchBrackets: true,
49
49
  tabMode: "indent",
50
+ readOnly: (o.read_only == true),
50
51
  onCursorActivity: function() {
51
52
  // try to highlight active line
52
53
  cm.setLineClass(hlLine, null, null);
@@ -123,4 +124,4 @@ define(["graph/abstract_widget"], function (abstract_widget) {
123
124
 
124
125
  return code_mirror;
125
126
 
126
- });
127
+ });
@@ -13,3 +13,4 @@ underscore: underscore-1.4.4
13
13
  require: require-2.1.8
14
14
  require-css: require-css-0.0.7
15
15
  font-awesome: font-awesome-4.0.3
16
+ smartmenus: smartmenus-0.9.6
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Vasil Dinkov, Vadikom Web Ltd.
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.
@@ -0,0 +1,26 @@
1
+ # SmartMenus
2
+
3
+ jQuery website menu plugin. Responsive and accessible list-based website menus that work on all devices.
4
+ Check out [the demo page](http://vadikom.github.io/smartmenus/src/demo/).
5
+
6
+ ## Homepage
7
+
8
+ http://www.smartmenus.org/
9
+
10
+ ## Download
11
+
12
+ Download the ZIP package which includes a basic demo:
13
+
14
+ http://www.smartmenus.org/download/
15
+
16
+ ## Getting started and API documentation
17
+
18
+ http://www.smartmenus.org/docs/
19
+
20
+ ## Bugs and issues
21
+
22
+ https://github.com/vadikom/smartmenus/issues
23
+
24
+ ## Support forums
25
+
26
+ http://www.smartmenus.org/support/forums/
@@ -0,0 +1,103 @@
1
+ /*
2
+ You probably do not need to edit this at all.
3
+
4
+ Add some SmartMenus required styles not covered in Bootstrap 3's default CSS.
5
+ These are theme independent and should work with any Bootstrap 3 theme mod.
6
+ */
7
+ /* sub menus arrows */
8
+ .navbar-nav .sub-arrow, .navbar-nav .collapsible .sub-arrow {
9
+ position:static;
10
+ margin-top:0;
11
+ margin-right:0;
12
+ margin-left:6px;
13
+ display:inline-block;
14
+ width:0;
15
+ height:0;
16
+ overflow:hidden;
17
+ vertical-align:middle;
18
+ border-top:4px solid;
19
+ border-right:4px dashed transparent;
20
+ border-bottom:4px dashed transparent;
21
+ border-left:4px dashed transparent;
22
+ }
23
+ .navbar-fixed-bottom .sub-arrow {
24
+ margin-top:-5px;
25
+ border-top:4px dashed transparent;
26
+ border-bottom:4px solid;
27
+ }
28
+ .navbar-nav ul .sub-arrow {
29
+ position:absolute;
30
+ right:0;
31
+ margin-top:6px;
32
+ margin-right:15px;
33
+ border-top:4px dashed transparent;
34
+ border-bottom:4px dashed transparent;
35
+ border-left:4px solid;
36
+ }
37
+ .navbar-nav ul a.has-submenu {
38
+ padding-right:30px;
39
+ }
40
+ /* scrolling arrows for tall menus */
41
+ .navbar-nav span.scroll-up, .navbar-nav span.scroll-down {
42
+ position:absolute;
43
+ display:none;
44
+ visibility:hidden;
45
+ height:20px;
46
+ overflow:hidden;
47
+ text-align:center;
48
+ }
49
+ .navbar-nav span.scroll-up-arrow, .navbar-nav span.scroll-down-arrow {
50
+ position:absolute;
51
+ top:-2px;
52
+ left:50%;
53
+ margin-left:-8px;
54
+ width:0;
55
+ height:0;
56
+ overflow:hidden;
57
+ border-top:7px dashed transparent;
58
+ border-right:7px dashed transparent;
59
+ border-bottom:7px solid;
60
+ border-left:7px dashed transparent;
61
+ }
62
+ .navbar-nav span.scroll-down-arrow {
63
+ top:6px;
64
+ border-top:7px solid;
65
+ border-right:7px dashed transparent;
66
+ border-bottom:7px dashed transparent;
67
+ border-left:7px dashed transparent;
68
+ }
69
+ /* add more indentation for 2+ level sub in collapsible mode - Bootstrap normally supports just 1 level sub menus */
70
+ .navbar-nav .collapsible ul .dropdown-menu > li > a,
71
+ .navbar-nav .collapsible ul .dropdown-menu .dropdown-header {
72
+ padding-left:35px;
73
+ }
74
+ .navbar-nav .collapsible ul ul .dropdown-menu > li > a,
75
+ .navbar-nav .collapsible ul ul .dropdown-menu .dropdown-header {
76
+ padding-left:45px;
77
+ }
78
+ .navbar-nav .collapsible ul ul ul .dropdown-menu > li > a,
79
+ .navbar-nav .collapsible ul ul ul .dropdown-menu .dropdown-header {
80
+ padding-left:55px;
81
+ }
82
+ .navbar-nav .collapsible ul ul ul ul .dropdown-menu > li > a,
83
+ .navbar-nav .collapsible ul ul ul ul .dropdown-menu .dropdown-header {
84
+ padding-left:65px;
85
+ }
86
+ /* fix SmartMenus sub menus auto width (subMenusMinWidth and subMenusMaxWidth options) */
87
+ .navbar-nav .dropdown-menu > li > a {
88
+ white-space:normal;
89
+ }
90
+ .navbar-nav ul.sm-nowrap > li > a {
91
+ white-space:nowrap;
92
+ }
93
+ /* fix .navbar-right subs alignment */
94
+ .navbar-right ul.dropdown-menu {
95
+ left:0;
96
+ right:auto;
97
+ }
98
+ /* The following will make the sub menus collapsible for small screen devices (it's not recommended editing these) */
99
+ .navbar-nav .collapsible ul {display:none;position:static !important;top:auto !important;left:auto !important;margin-left:0 !important;margin-top:0 !important;width:auto !important;min-width:0 !important;max-width:none !important;}
100
+ .navbar-nav .collapsible ul.sm-nowrap > li > a {white-space:normal;}
101
+ .navbar-nav .collapsible iframe{display:none;}
102
+ /* disable Bootstrap 3's global box-sizing:border-box; for the menus as it doesn't play nice with SmartMenus */
103
+ ul.sm li *,ul.sm li *:before,ul.sm li *:after{-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;}
@@ -0,0 +1,72 @@
1
+ /*!
2
+ * SmartMenus jQuery Plugin Bootstrap Addon - v0.1.0 - March 27, 2014
3
+ * http://www.smartmenus.org/
4
+ *
5
+ * Copyright 2014 Vasil Dinkov, Vadikom Web Ltd.
6
+ * http://vadikom.com
7
+ *
8
+ * Licensed MIT
9
+ */
10
+
11
+ (function($) {
12
+
13
+ // init ondomready
14
+ $(function() {
15
+
16
+ // init all menus
17
+ $('ul.navbar-nav').each(function() {
18
+ var $this = $(this);
19
+ $this.addClass('sm').smartmenus({
20
+
21
+ // these are some good default options that should work for all
22
+ // you can, of course, tweak these as you like
23
+ subMenusSubOffsetX: 2,
24
+ subMenusSubOffsetY: -6,
25
+ subIndicatorsPos: 'append',
26
+ subIndicatorsText: '...',
27
+ collapsibleShowFunction: null,
28
+ collapsibleHideFunction: null,
29
+ rightToLeftSubMenus: $this.hasClass('navbar-right'),
30
+ bottomToTopSubMenus: $this.closest('.navbar').hasClass('navbar-fixed-bottom')
31
+ })
32
+ // set Bootstrap's "active" class to SmartMenus "current" items (should someone decide to enable markCurrentItem: true)
33
+ .find('a.current').parent().addClass('active');
34
+ })
35
+ .bind({
36
+ // set/unset proper Bootstrap classes for some menu elements
37
+ 'show.smapi': function(e, menu) {
38
+ var $menu = $(menu),
39
+ $scrollArrows = $menu.dataSM('scroll-arrows'),
40
+ obj = $(this).data('smartmenus');
41
+ if ($scrollArrows) {
42
+ // they inherit border-color from body, so we can use its background-color too
43
+ $scrollArrows.css('background-color', $(document.body).css('background-color'));
44
+ }
45
+ $menu.parent().addClass('open' + (obj.isCollapsible() ? ' collapsible' : ''));
46
+ },
47
+ 'hide.smapi': function(e, menu) {
48
+ $(menu).parent().removeClass('open collapsible');
49
+ },
50
+ // click the parent item to toggle the sub menus (and reset deeper levels and other branches on click)
51
+ 'click.smapi': function(e, item) {
52
+ var obj = $(this).data('smartmenus');
53
+ if (obj.isCollapsible()) {
54
+ var $item = $(item),
55
+ $sub = $item.parent().dataSM('sub');
56
+ if ($sub && $sub.dataSM('shown-before') && $sub.is(':visible')) {
57
+ obj.itemActivate($item);
58
+ obj.menuHide($sub);
59
+ return false;
60
+ }
61
+ }
62
+ }
63
+ });
64
+
65
+ });
66
+
67
+ // fix collapsible menu detection for Bootstrap 3
68
+ $.SmartMenus.prototype.isCollapsible = function() {
69
+ return this.$firstLink.parent().css('float') != 'left';
70
+ };
71
+
72
+ })(jQuery);
@@ -0,0 +1,3 @@
1
+ /*! SmartMenus jQuery Plugin Bootstrap Addon - v0.1.0 - March 27, 2014
2
+ * http://www.smartmenus.org/
3
+ * Copyright 2014 Vasil Dinkov, Vadikom Web Ltd. http://vadikom.com; Licensed MIT */(function(t){t(function(){t("ul.navbar-nav").each(function(){var s=t(this);s.addClass("sm").smartmenus({subMenusSubOffsetX:2,subMenusSubOffsetY:-6,subIndicatorsPos:"append",subIndicatorsText:"...",collapsibleShowFunction:null,collapsibleHideFunction:null,rightToLeftSubMenus:s.hasClass("navbar-right"),bottomToTopSubMenus:s.closest(".navbar").hasClass("navbar-fixed-bottom")}).find("a.current").parent().addClass("active")}).bind({"show.smapi":function(s,e){var i=t(e),o=i.dataSM("scroll-arrows"),a=t(this).data("smartmenus");o&&o.css("background-color",t(document.body).css("background-color")),i.parent().addClass("open"+(a.isCollapsible()?" collapsible":""))},"hide.smapi":function(s,e){t(e).parent().removeClass("open collapsible")},"click.smapi":function(s,e){var i=t(this).data("smartmenus");if(i.isCollapsible()){var o=t(e),a=o.parent().dataSM("sub");if(a&&a.dataSM("shown-before")&&a.is(":visible"))return i.itemActivate(o),i.menuHide(a),!1}}})}),t.SmartMenus.prototype.isCollapsible=function(){return"left"!=this.$firstLink.parent().css("float")}})(jQuery);
@@ -0,0 +1,192 @@
1
+ /*!
2
+ * SmartMenus jQuery Plugin Keyboard Addon - v0.1.0 - March 27, 2014
3
+ * http://www.smartmenus.org/
4
+ *
5
+ * Copyright 2014 Vasil Dinkov, Vadikom Web Ltd.
6
+ * http://vadikom.com
7
+ *
8
+ * Licensed MIT
9
+ */
10
+
11
+ (function($) {
12
+
13
+ function getFirstItemLink($ul) {
14
+ return $ul.find('> li > a:not(.disabled)').eq(0);
15
+ }
16
+ function getLastItemLink($ul) {
17
+ return $ul.find('> li > a:not(.disabled)').eq(-1);
18
+ }
19
+ function getNextItemLink($li, noLoop) {
20
+ var $a = $li.nextAll('li').children('a:not(.disabled)').eq(0);
21
+ return noLoop || $a.length ? $a : getFirstItemLink($li.parent());
22
+ }
23
+ function getPreviousItemLink($li, noLoop) {
24
+ var $a = $li.prevAll('li').children('a:not(.disabled)').eq(0);
25
+ return noLoop || $a.length ? $a : getLastItemLink($li.parent());
26
+ }
27
+
28
+ // jQuery's .focus() is unreliable in some versions, so we're going to call the links' native JS focus method
29
+ $.fn.focusSM = function() {
30
+ if (this.length && this[0].focus) {
31
+ this[0].focus();
32
+ }
33
+ return this;
34
+ }
35
+
36
+ $.extend($.SmartMenus.Keyboard = {}, {
37
+ docKeydown: function(e) {
38
+ var keyCode = e.keyCode;
39
+ if (!/(27|37|38|39|40)/.test(keyCode)) {
40
+ return;
41
+ }
42
+ var $root = $(this),
43
+ obj = $root.data('smartmenus'),
44
+ $target = $(e.target);
45
+ if (!obj || !$target.is('a')) {
46
+ return;
47
+ }
48
+ var $li = $target.parent(),
49
+ $ul = $li.parent(),
50
+ level = $ul.dataSM('level');
51
+ // exit it if this is an A inside a mega drop-down
52
+ if (!level) {
53
+ return;
54
+ }
55
+ // swap left & right keys
56
+ if (obj.opts.rightToLeftSubMenus) {
57
+ if (keyCode == 37) {
58
+ keyCode = 39;
59
+ } else if (keyCode == 39) {
60
+ keyCode = 37;
61
+ }
62
+ }
63
+ switch (keyCode) {
64
+ case 27: // Esc
65
+ if (obj.visibleSubMenus[level]) {
66
+ obj.menuHide(obj.visibleSubMenus[level]);
67
+ } else if (level == 1) {
68
+ if (obj.opts.isPopup) {
69
+ obj.menuHideAll();
70
+ }
71
+ if (obj.opts.keyboardEscapeFocus) {
72
+ try { obj.opts.keyboardEscapeFocus.focusSM(); } catch(e) {};
73
+ // focus next focusable page element
74
+ } else {
75
+ var $lastMenuFocusable = $root.find('a, input, select, button, textarea').eq(-1),
76
+ $allFocusables = $('a, input, select, button, textarea'),
77
+ nextFocusableIndex = $allFocusables.index($lastMenuFocusable[0]) + 1;
78
+ $allFocusables.eq(nextFocusableIndex).focusSM();
79
+ }
80
+ } else {
81
+ $ul.dataSM('parent-a').focusSM();
82
+ obj.menuHide(obj.visibleSubMenus[level - 1]);
83
+ }
84
+ break;
85
+ case 37: // Left
86
+ if (obj.isCollapsible()) {
87
+ break;
88
+ }
89
+ if (level > 2 || level == 2 && $root.hasClass('sm-vertical')) {
90
+ obj.activatedItems[level - 2].focusSM();
91
+ // move to previous non-disabled parent item (make sure we cycle so it might be the last item)
92
+ } else if (!$root.hasClass('sm-vertical')) {
93
+ getPreviousItemLink(obj.activatedItems[0].parent()).focusSM();
94
+ }
95
+ break;
96
+ case 38: // Up
97
+ if (obj.isCollapsible()) {
98
+ var $firstItem;
99
+ // if this is the first item of a sub menu, move to the parent item
100
+ if (level > 1 && ($firstItem = getFirstItemLink($ul)).length && $target[0] == $firstItem[0]) {
101
+ obj.activatedItems[level - 2].focusSM();
102
+ } else {
103
+ getPreviousItemLink($li).focusSM();
104
+ }
105
+ } else {
106
+ if (level == 1 && !$root.hasClass('sm-vertical') && obj.visibleSubMenus[level] && obj.opts.bottomToTopSubMenus) {
107
+ getLastItemLink(obj.visibleSubMenus[level]).focusSM();
108
+ } else if (level > 1 || $root.hasClass('sm-vertical')) {
109
+ getPreviousItemLink($li).focusSM();
110
+ }
111
+ }
112
+ break;
113
+ case 39: // Right
114
+ if (obj.isCollapsible()) {
115
+ break;
116
+ }
117
+ // move to next non-disabled parent item (make sure we cycle so it might be the last item)
118
+ if ((level == 1 || !obj.visibleSubMenus[level]) && !$root.hasClass('sm-vertical')) {
119
+ getNextItemLink(obj.activatedItems[0].parent()).focusSM();
120
+ } else if (obj.visibleSubMenus[level] && !obj.visibleSubMenus[level].hasClass('mega-menu')) {
121
+ getFirstItemLink(obj.visibleSubMenus[level]).focusSM();
122
+ }
123
+ break;
124
+ case 40: // Down
125
+ if (obj.isCollapsible()) {
126
+ var $firstSubItem,
127
+ $lastItem;
128
+ // move to sub menu if appropriate
129
+ if (obj.visibleSubMenus[level] && !obj.visibleSubMenus[level].hasClass('mega-menu') && ($firstSubItem = getFirstItemLink(obj.visibleSubMenus[level])).length) {
130
+ $firstSubItem.focusSM();
131
+ // if this is the last item of a sub menu, move to the next parent item
132
+ } else if (level > 1 && ($lastItem = getLastItemLink($ul)).length && $target[0] == $lastItem[0]) {
133
+ var $parentItem = obj.activatedItems[level - 2].parent(),
134
+ $nextParentItem = null;
135
+ while ($parentItem.is('li')) {
136
+ if (($nextParentItem = getNextItemLink($parentItem, true)).length) {
137
+ break;
138
+ }
139
+ $parentItem = $parentItem.parent().parent();
140
+ }
141
+ $nextParentItem.focusSM();
142
+ } else {
143
+ getNextItemLink($li).focusSM();
144
+ }
145
+ } else {
146
+ if (level == 1 && !$root.hasClass('sm-vertical') && obj.visibleSubMenus[level] && !obj.opts.bottomToTopSubMenus) {
147
+ getFirstItemLink(obj.visibleSubMenus[level]).focusSM();
148
+ } else if (level > 1 || $root.hasClass('sm-vertical')) {
149
+ getNextItemLink($li).focusSM();
150
+ }
151
+ }
152
+ break;
153
+ }
154
+ e.stopPropagation();
155
+ e.preventDefault();
156
+ }
157
+ });
158
+
159
+ // hook it
160
+ $(document).delegate('ul.sm', 'keydown.smartmenus', $.SmartMenus.Keyboard.docKeydown);
161
+
162
+ $.extend($.SmartMenus.prototype, {
163
+ keyboardSetEscapeFocus: function($elm) {
164
+ this.opts.keyboardEscapeFocus = $elm;
165
+ },
166
+ keyboardSetHotkey: function(keyCode, modifiers) {
167
+ var self = this;
168
+ $(document).bind('keydown.smartmenus' + this.rootId, function(e) {
169
+ if (keyCode == e.keyCode) {
170
+ var procede = true;
171
+ if (modifiers) {
172
+ if (typeof modifiers == 'string') {
173
+ modifiers = [modifiers];
174
+ }
175
+ $.each(['ctrlKey', 'shiftKey', 'altKey', 'metaKey'], function(index, value) {
176
+ if ($.inArray(value, modifiers) >= 0 && !e[value] || $.inArray(value, modifiers) < 0 && e[value]) {
177
+ procede = false;
178
+ return false;
179
+ }
180
+ });
181
+ }
182
+ if (procede) {
183
+ getFirstItemLink(self.$root).focusSM();
184
+ e.stopPropagation();
185
+ e.preventDefault();
186
+ }
187
+ }
188
+ });
189
+ }
190
+ });
191
+
192
+ })(jQuery);
@@ -0,0 +1,3 @@
1
+ /*! SmartMenus jQuery Plugin Keyboard Addon - v0.1.0 - March 27, 2014
2
+ * http://www.smartmenus.org/
3
+ * Copyright 2014 Vasil Dinkov, Vadikom Web Ltd. http://vadikom.com; Licensed MIT */(function(t){function s(t){return t.find("> li > a:not(.disabled)").eq(0)}function e(t){return t.find("> li > a:not(.disabled)").eq(-1)}function i(t,e){var i=t.nextAll("li").children("a:not(.disabled)").eq(0);return e||i.length?i:s(t.parent())}function o(t,s){var i=t.prevAll("li").children("a:not(.disabled)").eq(0);return s||i.length?i:e(t.parent())}t.fn.focusSM=function(){return this.length&&this[0].focus&&this[0].focus(),this},t.extend(t.SmartMenus.Keyboard={},{docKeydown:function(a){var n=a.keyCode;if(/(27|37|38|39|40)/.test(n)){var r=t(this),h=r.data("smartmenus"),u=t(a.target);if(h&&u.is("a")){var l=u.parent(),d=l.parent(),c=d.dataSM("level");if(c){switch(h.opts.rightToLeftSubMenus&&(37==n?n=39:39==n&&(n=37)),n){case 27:if(h.visibleSubMenus[c])h.menuHide(h.visibleSubMenus[c]);else if(1==c)if(h.opts.isPopup&&h.menuHideAll(),h.opts.keyboardEscapeFocus)try{h.opts.keyboardEscapeFocus.focusSM()}catch(a){}else{var m=r.find("a, input, select, button, textarea").eq(-1),p=t("a, input, select, button, textarea"),f=p.index(m[0])+1;p.eq(f).focusSM()}else d.dataSM("parent-a").focusSM(),h.menuHide(h.visibleSubMenus[c-1]);break;case 37:if(h.isCollapsible())break;c>2||2==c&&r.hasClass("sm-vertical")?h.activatedItems[c-2].focusSM():r.hasClass("sm-vertical")||o(h.activatedItems[0].parent()).focusSM();break;case 38:if(h.isCollapsible()){var v;c>1&&(v=s(d)).length&&u[0]==v[0]?h.activatedItems[c-2].focusSM():o(l).focusSM()}else 1==c&&!r.hasClass("sm-vertical")&&h.visibleSubMenus[c]&&h.opts.bottomToTopSubMenus?e(h.visibleSubMenus[c]).focusSM():(c>1||r.hasClass("sm-vertical"))&&o(l).focusSM();break;case 39:if(h.isCollapsible())break;1!=c&&h.visibleSubMenus[c]||r.hasClass("sm-vertical")?h.visibleSubMenus[c]&&!h.visibleSubMenus[c].hasClass("mega-menu")&&s(h.visibleSubMenus[c]).focusSM():i(h.activatedItems[0].parent()).focusSM();break;case 40:if(h.isCollapsible()){var b,M;if(h.visibleSubMenus[c]&&!h.visibleSubMenus[c].hasClass("mega-menu")&&(b=s(h.visibleSubMenus[c])).length)b.focusSM();else if(c>1&&(M=e(d)).length&&u[0]==M[0]){for(var S=h.activatedItems[c-2].parent(),w=null;S.is("li")&&!(w=i(S,!0)).length;)S=S.parent().parent();w.focusSM()}else i(l).focusSM()}else 1!=c||r.hasClass("sm-vertical")||!h.visibleSubMenus[c]||h.opts.bottomToTopSubMenus?(c>1||r.hasClass("sm-vertical"))&&i(l).focusSM():s(h.visibleSubMenus[c]).focusSM()}a.stopPropagation(),a.preventDefault()}}}}}),t(document).delegate("ul.sm","keydown.smartmenus",t.SmartMenus.Keyboard.docKeydown),t.extend(t.SmartMenus.prototype,{keyboardSetEscapeFocus:function(t){this.opts.keyboardEscapeFocus=t},keyboardSetHotkey:function(e,i){var o=this;t(document).bind("keydown.smartmenus"+this.rootId,function(a){if(e==a.keyCode){var n=!0;i&&("string"==typeof i&&(i=[i]),t.each(["ctrlKey","shiftKey","altKey","metaKey"],function(s,e){return t.inArray(e,i)>=0&&!a[e]||0>t.inArray(e,i)&&a[e]?(n=!1,!1):void 0})),n&&(s(o.$root).focusSM(),a.stopPropagation(),a.preventDefault())}})}})})(jQuery);