-
Notifications
You must be signed in to change notification settings - Fork 6.7k
/
Copy pathtoolbar.js
157 lines (148 loc) · 5.61 KB
/
toolbar.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/**
* Toolbar plugin
*
* This plugin provides a generic graphical toolbar. Other plugins that
* want to expose a button or other widget, can add those to this toolbar.
*
* Using a single consolidated toolbar for all GUI widgets makes it easier
* to position and style the toolbar rather than having to do that for lots
* of different divs.
*
*
* *** For presentation authors: *****************************************
*
* To add/activate the toolbar in your presentation, add this div:
*
* <div id="impress-toolbar"></div>
*
* Styling the toolbar is left to presentation author. Here's an example CSS:
*
* .impress-enabled div#impress-toolbar {
* position: fixed;
* right: 1px;
* bottom: 1px;
* opacity: 0.6;
* }
* .impress-enabled div#impress-toolbar > span {
* margin-right: 10px;
* }
*
* The [mouse-timeout](../mouse-timeout/README.md) plugin can be leveraged to hide
* the toolbar from sight, and only make it visible when mouse is moved.
*
* body.impress-mouse-timeout div#impress-toolbar {
* display: none;
* }
*
*
* *** For plugin authors **********************************************
*
* To add a button to the toolbar, trigger the `impress:toolbar:appendChild`
* or `impress:toolbar:insertBefore` events as appropriate. The detail object
* should contain following parameters:
*
* { group : 1, // integer. Widgets with the same group are grouped inside
* // the same <span> element.
* html : "<button>Click</button>", // The html to add.
* callback : "mycallback", // Toolbar plugin will trigger event
* // `impress:toolbar:added:mycallback` when done.
* before: element } // The reference element for an insertBefore() call.
*
* You should also listen to the `impress:toolbar:added:mycallback` event. At
* this point you can find the new widget in the DOM, and for example add an
* event listener to it.
*
* You are free to use any integer for the group. It's ok to leave gaps. It's
* ok to co-locate with widgets for another plugin, if you think they belong
* together.
*
* See navigation-ui for an example.
*
* Copyright 2016 Henrik Ingo (@henrikingo)
* Released under the MIT license.
*/
/* global document */
( function( document ) {
"use strict";
var toolbar = document.getElementById( "impress-toolbar" );
var groups = [];
/**
* Get the span element that is a child of toolbar, identified by index.
*
* If span element doesn't exist yet, it is created.
*
* Note: Because of Run-to-completion, this is not a race condition.
* https://developer.mozilla.org/en/docs/Web/JavaScript/EventLoop#Run-to-completion
*
* :param: index Method will return the element <span id="impress-toolbar-group-{index}">
*/
var getGroupElement = function( index ) {
var id = "impress-toolbar-group-" + index;
if ( !groups[ index ] ) {
groups[ index ] = document.createElement( "span" );
groups[ index ].id = id;
var nextIndex = getNextGroupIndex( index );
if ( nextIndex === undefined ) {
toolbar.appendChild( groups[ index ] );
} else {
toolbar.insertBefore( groups[ index ], groups[ nextIndex ] );
}
}
return groups[ index ];
};
/**
* Get the span element from groups[] that is immediately after given index.
*
* This can be used to find the reference node for an insertBefore() call.
* If no element exists at a larger index, returns undefined. (In this case,
* you'd use appendChild() instead.)
*
* Note that index needn't itself exist in groups[].
*/
var getNextGroupIndex = function( index ) {
var i = index + 1;
while ( !groups[ i ] && i < groups.length ) {
i++;
}
if ( i < groups.length ) {
return i;
}
};
// API
// Other plugins can add and remove buttons by sending them as events.
// In return, toolbar plugin will trigger events when button was added.
if ( toolbar ) {
/**
* Append a widget inside toolbar span element identified by given group index.
*
* :param: e.detail.group integer specifying the span element where widget will be placed
* :param: e.detail.element a dom element to add to the toolbar
*/
toolbar.addEventListener( "impress:toolbar:appendChild", function( e ) {
var group = getGroupElement( e.detail.group );
group.appendChild( e.detail.element );
} );
/**
* Add a widget to toolbar using insertBefore() DOM method.
*
* :param: e.detail.before the reference dom element, before which new element is added
* :param: e.detail.element a dom element to add to the toolbar
*/
toolbar.addEventListener( "impress:toolbar:insertBefore", function( e ) {
toolbar.insertBefore( e.detail.element, e.detail.before );
} );
/**
* Remove the widget in e.detail.remove.
*/
toolbar.addEventListener( "impress:toolbar:removeWidget", function( e ) {
toolbar.removeChild( e.detail.remove );
} );
document.addEventListener( "impress:init", function( event ) {
var api = event.detail.api;
api.lib.gc.pushCallback( function() {
toolbar.innerHTML = "";
groups = [];
} );
} );
} // If toolbar
} )( document );