• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

divio / django-cms / #29932

16 Sep 2025 01:24PM UTC coverage: 75.132%. Remained the same
#29932

push

travis-ci

web-flow
Merge ad745d6dd into 7ec333dc8

1079 of 1626 branches covered (66.36%)

2568 of 3418 relevant lines covered (75.13%)

26.22 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

32.14
/cms/static/cms/js/modules/shortcuts/placeholders.js
1
import keyboard from '../keyboard';
2
import $ from 'jquery';
3

4
import '../jquery.trap';
5

6
/**
7
 * Binds shortcuts:
8
 * [esc] go back to global "cms" context
9
 * [enter] when focusing the placeholder - go to it's first plugin
10
 * [+] / [a] add plugin to placeholder
11
 * [x] expand all / collapse all
12
 * [s] open settings menu for current placeholder
13
 *
14
 * @function bindPlaceholderKeys
15
 * @private
16
 */
17
var bindPlaceholderKeys = function () {
1✔
18
    keyboard.setContext('placeholders');
1✔
19
    keyboard.bind('escape', function () {
1✔
20
        $('.cms-structure .cms-dragarea').removeAttr('tabindex');
×
21
        $('.cms-structure-content').untrap();
×
22
        $('html').focus();
×
23
        keyboard.setContext('cms');
×
24
    });
25

26
    keyboard.bind('enter', function () {
1✔
27
        keyboard.setContext('plugins');
×
28
        var area = $('.cms-dragarea:focus');
×
29
        var plugins = area.find('.cms-dragitem');
×
30

31
        if (!plugins.length) {
×
32
            return;
×
33
        }
34

35
        plugins.attr('tabindex', '0');
×
36
        area.find('.cms-dragitem:first').focus();
×
37
        area.trap();
×
38
        keyboard.setContext('plugins');
×
39
    });
40

41
    keyboard.bind(['+', 'a'], function () {
1✔
42
        var area = $('.cms-dragarea:focus');
×
43

44
        area.find('.cms-submenu-add:first').trigger('pointerup');
×
45
    });
46

47
    keyboard.bind('x', function () {
1✔
48
        var area = $('.cms-dragarea:focus');
×
49

50
        area.find('.cms-dragbar-toggler a:visible').trigger('click');
×
51
    });
52

53
    keyboard.bind(['!', 's'], function () {
1✔
54
        var area = $('.cms-dragarea:focus');
×
55

56
        area.find('.cms-submenu-settings:first').trigger('pointerup');
×
57
        keyboard.setContext('placeholder-actions');
×
58
        area.find('.cms-submenu-item a:first').focus();
×
59
        area.find('.cms-dropdown-inner').trap();
×
60
    });
61
};
62

63

64
/**
65
 * Binds shortcuts:
66
 * [esc] go back to "placeholders" context
67
 *
68
 * @function bindPlaceholderActionKeys
69
 * @private
70
 */
71
var bindPlaceholderActionKeys = function () {
1✔
72
    keyboard.setContext('placeholder-actions');
1✔
73
    keyboard.bind('escape', function () {
1✔
74
        var dropdown = $('.cms-dropdown-inner:visible');
×
75
        var area = dropdown.closest('.cms-dragarea');
×
76

77
        area.find('.cms-submenu-settings:first').trigger('pointerup');
×
78
        dropdown.untrap();
×
79
        area.focus();
×
80
        keyboard.setContext('placeholders');
×
81
    });
82
};
83

84
/**
85
 * Binds shortcuts:
86
 * [esc] go back to "placeholders" context
87
 * [e] edit plugin
88
 * [+] / [a] add child plugin
89
 * [x] expand / collapse plugin
90
 * [s] open settings menu
91
 *
92
 * @function bindPluginKeys
93
 * @private
94
 */
95
var bindPluginKeys = function () {
1✔
96
    keyboard.setContext('plugins');
1✔
97
    keyboard.bind('escape', function () {
1✔
98
        var plugin = $('.cms-dragitem:focus');
×
99
        var area = plugin.closest('.cms-dragarea');
×
100

101
        $('.cms-dragitem').removeAttr('tabindex');
×
102
        area.untrap();
×
103
        area.focus();
×
104
        keyboard.setContext('placeholders');
×
105
    });
106

107
    keyboard.bind('e', function () {
1✔
108
        var plugin = $('.cms-dragitem:focus');
×
109

110
        plugin.find('.cms-submenu-edit').trigger('click');
×
111
    });
112
    keyboard.bind(['+', 'a'], function () {
1✔
113
        var plugin = $('.cms-dragitem:focus');
×
114

115
        plugin.find('.cms-submenu-add:first').trigger('pointerup');
×
116
    });
117
    keyboard.bind('x', function () {
1✔
118
        var plugin = $('.cms-dragitem:focus');
×
119

120
        plugin.find('.cms-dragitem-text').trigger('click');
×
121
    });
122
    keyboard.bind(['!', 's'], function () {
1✔
123
        var plugin = $('.cms-dragitem:focus');
×
124

125
        plugin.find('.cms-submenu-settings:first').trigger('pointerup');
×
126
        keyboard.setContext('plugin-actions');
×
127
        plugin.find('.cms-submenu-item a:first').focus();
×
128
        plugin.find('.cms-dropdown-inner').trap();
×
129
    });
130
};
131

132
/**
133
 * Binds shortcuts:
134
 * [esc] go back to "plugins" context
135
 *
136
 * @function bindPluginActionKeys
137
 * @private
138
 */
139
var bindPluginActionKeys = function () {
1✔
140
    keyboard.setContext('plugin-actions');
1✔
141
    keyboard.bind('escape', function () {
1✔
142
        var dropdown = $('.cms-dropdown-inner:visible');
×
143
        var plugin = dropdown.closest('.cms-dragitem');
×
144

145
        plugin.find('.cms-submenu-settings:first').trigger('pointerup');
×
146
        dropdown.untrap();
×
147
        plugin.focus();
×
148
        keyboard.setContext('plugins');
×
149
    });
150
};
151

152
/**
153
 * Binds [f p] / [alt+p] shortcuts to focus first placeholder.
154
 * Only works in structure mode.
155
 *
156
 * @function initPlaceholders
157
 * @public
158
 */
159
export default function initPlaceholders() {
160
    var data = CMS.config.lang.shortcutAreas[1].shortcuts.placeholders;
1✔
161

162
    bindPlaceholderKeys();
1✔
163
    bindPlaceholderActionKeys();
1✔
164
    bindPluginKeys();
1✔
165
    bindPluginActionKeys();
1✔
166

167
    keyboard.setContext('cms');
1✔
168

169
    keyboard.bind(data.shortcut.split(' / '), function () {
1✔
170
        if (CMS.settings.mode !== 'structure') {
×
171
            return;
×
172
        }
173

174
        $('.cms-structure .cms-dragarea').attr('tabindex', '0');
×
175
        $('.cms-structure .cms-dragarea:first').focus();
×
176
        $('.cms-structure-content').trap();
×
177
        keyboard.setContext('placeholders');
×
178
    });
179
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc