omf_web 1.2.5 → 1.2.6

Sign up to get free protection for your applications and to get access to all the features.
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);