forked from chilipeppr/widget-template
-
Notifications
You must be signed in to change notification settings - Fork 0
/
widget.js
351 lines (317 loc) · 15.8 KB
/
widget.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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
/* global requirejs cprequire cpdefine chilipeppr THREE */
// Defining the globals above helps Cloud9 not show warnings for those variables
// ChiliPeppr Widget/Element Javascript
requirejs.config({
/*
Dependencies can be defined here. ChiliPeppr uses require.js so
please refer to http://requirejs.org/docs/api.html for info.
Most widgets will not need to define Javascript dependencies.
Make sure all URLs are https and http accessible. Try to use URLs
that start with // rather than http:// or https:// so they simply
use whatever method the main page uses.
Also, please make sure you are not loading dependencies from different
URLs that other widgets may already load like jquery, bootstrap,
three.js, etc.
You may slingshot content through ChiliPeppr's proxy URL if you desire
to enable SSL for non-SSL URL's. ChiliPeppr's SSL URL is
https://i2dcui.appspot.com which is the SSL equivalent for
http://chilipeppr.com
*/
paths: {
// Example of how to define the key (you make up the key) and the URL
// Make sure you DO NOT put the .js at the end of the URL
// SmoothieCharts: '//smoothiecharts.org/smoothie',
},
shim: {
// See require.js docs for how to define dependencies that
// should be loaded before your script/widget.
}
});
cprequire_test(["inline:com-chilipeppr-widget-template"], function(myWidget) {
// Test this element. This code is auto-removed by the chilipeppr.load()
// when using this widget in production. So use the cpquire_test to do things
// you only want to have happen during testing, like loading other widgets or
// doing unit tests. Don't remove end_test at the end or auto-remove will fail.
// Please note that if you are working on multiple widgets at the same time
// you may need to use the ?forcerefresh=true technique in the URL of
// your test widget to force the underlying chilipeppr.load() statements
// to referesh the cache. For example, if you are working on an Add-On
// widget to the Eagle BRD widget, but also working on the Eagle BRD widget
// at the same time you will have to make ample use of this technique to
// get changes to load correctly. If you keep wondering why you're not seeing
// your changes, try ?forcerefresh=true as a get parameter in your URL.
console.log("test running of " + myWidget.id);
$('body').prepend('<div id="testDivForFlashMessageWidget"></div>');
chilipeppr.load(
"#testDivForFlashMessageWidget",
"http://raw.githubusercontent.com/chilipeppr/element-flash/master/auto-generated-widget.html",
function() {
console.log("mycallback got called after loading flash msg module");
cprequire(["inline:com-chilipeppr-elem-flashmsg"], function(fm) {
//console.log("inside require of " + fm.id);
fm.init();
});
}
);
// init my widget
myWidget.init();
$('#' + myWidget.id).css('margin', '20px');
$('title').html(myWidget.name);
} /*end_test*/ );
// This is the main definition of your widget. Give it a unique name.
cpdefine("inline:com-chilipeppr-widget-template", ["chilipeppr_ready", /* other dependencies here */ ], function() {
return {
/**
* The ID of the widget. You must define this and make it unique.
*/
id: "com-chilipeppr-widget-template", // Make the id the same as the cpdefine id
name: "Widget / Template", // The descriptive name of your widget.
desc: "This example widget gives you a framework for creating your own widget. Please change this description once you fork this template and create your own widget. Make sure to run runme.js every time you are done editing your code so you can regenerate your README.md file, regenerate your auto-generated-widget.html, and automatically push your changes to Github.", // A description of what your widget does
url: "(auto fill by runme.js)", // The final URL of the working widget as a single HTML file with CSS and Javascript inlined. You can let runme.js auto fill this if you are using Cloud9.
fiddleurl: "(auto fill by runme.js)", // The edit URL. This can be auto-filled by runme.js in Cloud9 if you'd like, or just define it on your own to help people know where they can edit/fork your widget
githuburl: "(auto fill by runme.js)", // The backing github repo
testurl: "(auto fill by runme.js)", // The standalone working widget so can view it working by itself
/**
* Define pubsub signals below. These are basically ChiliPeppr's event system.
* ChiliPeppr uses amplify.js's pubsub system so please refer to docs at
* http://amplifyjs.com/api/pubsub/
*/
/**
* Define the publish signals that this widget/element owns or defines so that
* other widgets know how to subscribe to them and what they do.
*/
publish: {
// Define a key:value pair here as strings to document what signals you publish.
'/onExampleGenerate': 'Example: Publish this signal when we go to generate gcode.'
},
/**
* Define the subscribe signals that this widget/element owns or defines so that
* other widgets know how to subscribe to them and what they do.
*/
subscribe: {
// Define a key:value pair here as strings to document what signals you subscribe to
// so other widgets can publish to this widget to have it do something.
// '/onExampleConsume': 'Example: This widget subscribe to this signal so other widgets can send to us and we'll do something with it.'
},
/**
* Document the foreign publish signals, i.e. signals owned by other widgets
* or elements, that this widget/element publishes to.
*/
foreignPublish: {
// Define a key:value pair here as strings to document what signals you publish to
// that are owned by foreign/other widgets.
// '/jsonSend': 'Example: We send Gcode to the serial port widget to do stuff with the CNC controller.'
},
/**
* Document the foreign subscribe signals, i.e. signals owned by other widgets
* or elements, that this widget/element subscribes to.
*/
foreignSubscribe: {
// Define a key:value pair here as strings to document what signals you subscribe to
// that are owned by foreign/other widgets.
// '/com-chilipeppr-elem-dragdrop/ondropped': 'Example: We subscribe to this signal at a higher priority to intercept the signal. We do not let it propagate by returning false.'
},
/**
* All widgets should have an init method. It should be run by the
* instantiating code like a workspace or a different widget.
*/
init: function() {
console.log("I am being initted. Thanks.");
this.setupUiFromLocalStorage();
this.btnSetup();
this.forkSetup();
console.log("I am done being initted.");
},
/**
* Call this method from init to setup all the buttons when this widget
* is first loaded. This basically attaches click events to your
* buttons. It also turns on all the bootstrap popovers by scanning
* the entire DOM of the widget.
*/
btnSetup: function() {
// Chevron hide/show body
var that = this;
$('#' + this.id + ' .hidebody').click(function(evt) {
console.log("hide/unhide body");
if ($('#' + that.id + ' .panel-body').hasClass('hidden')) {
// it's hidden, unhide
that.showBody(evt);
}
else {
// hide
that.hideBody(evt);
}
});
// Ask bootstrap to scan all the buttons in the widget to turn
// on popover menus
$('#' + this.id + ' .btn').popover({
delay: 1000,
animation: true,
placement: "auto",
trigger: "hover",
container: 'body'
});
// Init Say Hello Button on Main Toolbar
// We are inlining an anonymous method as the callback here
// as opposed to a full callback method in the Hello Word 2
// example further below. Notice we have to use "that" so
// that the this is set correctly inside the anonymous method
$('#' + this.id + ' .btn-sayhello').click(function() {
console.log("saying hello");
// Make sure popover is immediately hidden
$('#' + that.id + ' .btn-sayhello').popover("hide");
// Show a flash msg
chilipeppr.publish(
"/com-chilipeppr-elem-flashmsg/flashmsg",
"Hello Title",
"Hello World from widget " + that.id,
1000
);
});
// Init Hello World 2 button on Tab 1. Notice the use
// of the slick .bind(this) technique to correctly set "this"
// when the callback is called
$('#' + this.id + ' .btn-helloworld2').click(this.onHelloBtnClick.bind(this));
},
/**
* onHelloBtnClick is an example of a button click event callback
*/
onHelloBtnClick: function(evt) {
console.log("saying hello 2 from btn in tab 1");
chilipeppr.publish(
'/com-chilipeppr-elem-flashmsg/flashmsg',
"Hello 2 Title",
"Hello World 2 from Tab 1 from widget " + this.id,
2000 /* show for 2 second */
);
},
/**
* User options are available in this property for reference by your
* methods. If any change is made on these options, please call
* saveOptionsLocalStorage()
*/
options: null,
/**
* Call this method on init to setup the UI by reading the user's
* stored settings from localStorage and then adjust the UI to reflect
* what the user wants.
*/
setupUiFromLocalStorage: function() {
// Read vals from localStorage. Make sure to use a unique
// key specific to this widget so as not to overwrite other
// widgets' options. By using this.id as the prefix of the
// key we're safe that this will be unique.
// Feel free to add your own keys inside the options
// object for your own items
var options = localStorage.getItem(this.id + '-options');
if (options) {
options = $.parseJSON(options);
console.log("just evaled options: ", options);
}
else {
options = {
showBody: true,
tabShowing: 1,
customParam1: null,
customParam2: 1.0
};
}
this.options = options;
console.log("options:", options);
// show/hide body
if (options.showBody) {
this.showBody();
}
else {
this.hideBody();
}
},
/**
* When a user changes a value that is stored as an option setting, you
* should call this method immediately so that on next load the value
* is correctly set.
*/
saveOptionsLocalStorage: function() {
// You can add your own values to this.options to store them
// along with some of the normal stuff like showBody
var options = this.options;
var optionsStr = JSON.stringify(options);
console.log("saving options:", options, "json.stringify:", optionsStr);
// store settings to localStorage
localStorage.setItem(this.id + '-options', optionsStr);
},
/**
* Show the body of the panel.
* @param {jquery_event} evt - If you pass the event parameter in, we
* know it was clicked by the user and thus we store it for the next
* load so we can reset the user's preference. If you don't pass this
* value in we don't store the preference because it was likely code
* that sent in the param.
*/
showBody: function(evt) {
$('#' + this.id + ' .panel-body').removeClass('hidden');
$('#' + this.id + ' .panel-footer').removeClass('hidden');
$('#' + this.id + ' .hidebody span').addClass('glyphicon-chevron-up');
$('#' + this.id + ' .hidebody span').removeClass('glyphicon-chevron-down');
if (!(evt == null)) {
this.options.showBody = true;
this.saveOptionsLocalStorage();
}
// this will send an artificial event letting other widgets know to resize
// themselves since this widget is now taking up more room since it's showing
$(window).trigger("resize");
},
/**
* Hide the body of the panel.
* @param {jquery_event} evt - If you pass the event parameter in, we
* know it was clicked by the user and thus we store it for the next
* load so we can reset the user's preference. If you don't pass this
* value in we don't store the preference because it was likely code
* that sent in the param.
*/
hideBody: function(evt) {
$('#' + this.id + ' .panel-body').addClass('hidden');
$('#' + this.id + ' .panel-footer').addClass('hidden');
$('#' + this.id + ' .hidebody span').removeClass('glyphicon-chevron-up');
$('#' + this.id + ' .hidebody span').addClass('glyphicon-chevron-down');
if (!(evt == null)) {
this.options.showBody = false;
this.saveOptionsLocalStorage();
}
// this will send an artificial event letting other widgets know to resize
// themselves since this widget is now taking up less room since it's hiding
$(window).trigger("resize");
},
/**
* This method loads the pubsubviewer widget which attaches to our
* upper right corner triangle menu and generates 3 menu items like
* Pubsub Viewer, View Standalone, and Fork Widget. It also enables
* the modal dialog that shows the documentation for this widget.
*
* By using chilipeppr.load() we can ensure that the pubsubviewer widget
* is only loaded and inlined once into the final ChiliPeppr workspace.
* We are given back a reference to the instantiated singleton so its
* not instantiated more than once. Then we call it's attachTo method
* which creates the full pulldown menu for us and attaches the click
* events.
*/
forkSetup: function() {
var topCssSelector = '#' + this.id;
$(topCssSelector + ' .panel-title').popover({
title: this.name,
content: this.desc,
html: true,
delay: 1000,
animation: true,
trigger: 'hover',
placement: 'auto'
});
var that = this;
chilipeppr.load("http://raw.githubusercontent.com/chilipeppr/widget-pubsubviewer/master/auto-generated-widget.html", function() {
require(['inline:com-chilipeppr-elem-pubsubviewer'], function(pubsubviewer) {
pubsubviewer.attachTo($(topCssSelector + ' .panel-heading .dropdown-menu'), that);
});
});
},
}
});