luca 0.7.6 → 0.7.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,649 @@
1
+ // JQuery Console 1.0
2
+ // Sun Feb 21 20:28:47 GMT 2010
3
+ //
4
+ // Copyright 2010 Chris Done, Simon David Pratt. All rights reserved.
5
+ //
6
+ // Redistribution and use in source and binary forms, with or without
7
+ // modification, are permitted provided that the following conditions
8
+ // are met:
9
+ //
10
+ // 1. Redistributions of source code must retain the above
11
+ // copyright notice, this list of conditions and the following
12
+ // disclaimer.
13
+ //
14
+ // 2. Redistributions in binary form must reproduce the above
15
+ // copyright notice, this list of conditions and the following
16
+ // disclaimer in the documentation and/or other materials
17
+ // provided with the distribution.
18
+ //
19
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
+ // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
+ // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22
+ // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23
+ // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24
+ // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25
+ // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26
+ // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
+ // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29
+ // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
+ // POSSIBILITY OF SUCH DAMAGE.
31
+
32
+ // TESTED ON
33
+ // Internet Explorer 6
34
+ // Opera 10.01
35
+ // Chromium 4.0.237.0 (Ubuntu build 31094)
36
+ // Firefox 3.5.8, 3.6.2 (Mac)
37
+ // Safari 4.0.5 (6531.22.7) (Mac)
38
+ // Google Chrome 5.0.375.55 (Mac)
39
+
40
+ (function($){
41
+ $.fn.console = function(config){
42
+ ////////////////////////////////////////////////////////////////////////
43
+ // Constants
44
+ // Some are enums, data types, others just for optimisation
45
+ var keyCodes = {
46
+ // left
47
+ 37: moveBackward,
48
+ // right
49
+ 39: moveForward,
50
+ // up
51
+ 38: previousHistory,
52
+ // down
53
+ 40: nextHistory,
54
+ // backspace
55
+ 8: backDelete,
56
+ // delete
57
+ 46: forwardDelete,
58
+ // end
59
+ 35: moveToEnd,
60
+ // start
61
+ 36: moveToStart,
62
+ // return
63
+ 13: commandTrigger,
64
+ // tab
65
+ 18: doNothing
66
+ };
67
+ var ctrlCodes = {
68
+ // C-a
69
+ 65: moveToStart,
70
+ // C-e
71
+ 69: moveToEnd,
72
+ // C-d
73
+ 68: forwardDelete,
74
+ // C-n
75
+ 78: nextHistory,
76
+ // C-p
77
+ 80: previousHistory,
78
+ // C-b
79
+ 66: moveBackward,
80
+ // C-f
81
+ 70: moveForward,
82
+ // C-k
83
+ 75: deleteUntilEnd
84
+ };
85
+ var altCodes = {
86
+ // M-f
87
+ 70: moveToNextWord,
88
+ // M-b
89
+ 66: moveToPreviousWord,
90
+ // M-d
91
+ 68: deleteNextWord
92
+ };
93
+ var cursor = '<span class="jquery-console-cursor">&nbsp;</span>';
94
+
95
+ ////////////////////////////////////////////////////////////////////////
96
+ // Globals
97
+ var container = $(this);
98
+ var inner = $('<div class="jquery-console-inner"></div>');
99
+ // erjiang: changed this from a text input to a textarea so we
100
+ // can get pasted newlines
101
+ var typer = $('<textarea class="jquery-console-typer"></textarea>');
102
+ // Prompt
103
+ var promptBox;
104
+ var prompt;
105
+ var promptLabel = config && config.promptLabel? config.promptLabel : "> ";
106
+ var continuedPromptLabel = config && config.continuedPromptLabel?
107
+ config.continuedPromptLabel : "> ";
108
+ var column = 0;
109
+ var promptText = '';
110
+ var restoreText = '';
111
+ var continuedText = '';
112
+ // Prompt history stack
113
+ var history = [];
114
+ var ringn = 0;
115
+ // For reasons unknown to The Sword of Michael himself, Opera
116
+ // triggers and sends a key character when you hit various
117
+ // keys like PgUp, End, etc. So there is no way of knowing
118
+ // when a user has typed '#' or End. My solution is in the
119
+ // typer.keydown and typer.keypress functions; I use the
120
+ // variable below to ignore the keypress event if the keydown
121
+ // event succeeds.
122
+ var cancelKeyPress = 0;
123
+ // When this value is false, the prompt will not respond to input
124
+ var acceptInput = true;
125
+ // When this value is true, the command has been canceled
126
+ var cancelCommand = false;
127
+
128
+ // External exports object
129
+ var extern = {};
130
+
131
+ ////////////////////////////////////////////////////////////////////////
132
+ // Main entry point
133
+ (function(){
134
+ container.append(inner);
135
+ inner.append(typer);
136
+ typer.css({position:'absolute',top:0,left:'-9999px'});
137
+ if (config.welcomeMessage)
138
+ message(config.welcomeMessage,'jquery-console-welcome');
139
+ newPromptBox();
140
+ if (config.autofocus) {
141
+ inner.addClass('jquery-console-focus');
142
+ typer.focus();
143
+ setTimeout(function(){
144
+ inner.addClass('jquery-console-focus');
145
+ typer.focus();
146
+ },100);
147
+ }
148
+ extern.inner = inner;
149
+ extern.typer = typer;
150
+ extern.scrollToBottom = scrollToBottom;
151
+ })();
152
+
153
+ ////////////////////////////////////////////////////////////////////////
154
+ // Reset terminal
155
+ extern.reset = function(){
156
+ var welcome = (typeof config.welcomeMessage != 'undefined');
157
+ inner.parent().fadeOut(function(){
158
+ inner.find('div').each(function(){
159
+ if (!welcome) {
160
+ $(this).remove();
161
+ } else {
162
+ welcome = false;
163
+ }
164
+ });
165
+ newPromptBox();
166
+ inner.parent().fadeIn(function(){
167
+ inner.addClass('jquery-console-focus');
168
+ typer.focus();
169
+ });
170
+ });
171
+ };
172
+
173
+ ////////////////////////////////////////////////////////////////////////
174
+ // Reset terminal
175
+ extern.notice = function(msg,style){
176
+ var n = $('<div class="notice"></div>').append($('<div></div>').text(msg))
177
+ .css({visibility:'hidden'});
178
+ container.append(n);
179
+ var focused = true;
180
+ if (style=='fadeout')
181
+ setTimeout(function(){
182
+ n.fadeOut(function(){
183
+ n.remove();
184
+ });
185
+ },4000);
186
+ else if (style=='prompt') {
187
+ var a = $('<br/><div class="action"><a href="javascript:">OK</a><div class="clear"></div></div>');
188
+ n.append(a);
189
+ focused = false;
190
+ a.click(function(){ n.fadeOut(function(){ n.remove();inner.css({opacity:1}) }); });
191
+ }
192
+ var h = n.height();
193
+ n.css({height:'0px',visibility:'visible'})
194
+ .animate({height:h+'px'},function(){
195
+ if (!focused) inner.css({opacity:0.5});
196
+ });
197
+ n.css('cursor','default');
198
+ return n;
199
+ };
200
+
201
+ ////////////////////////////////////////////////////////////////////////
202
+ // Make a new prompt box
203
+ function newPromptBox() {
204
+ column = 0;
205
+ promptText = '';
206
+ ringn = 0; // Reset the position of the history ring
207
+ enableInput();
208
+ promptBox = $('<div class="jquery-console-prompt-box"></div>');
209
+ var label = $('<span class="jquery-console-prompt-label"></span>');
210
+ var labelText = extern.continuedPrompt? continuedPromptLabel : promptLabel;
211
+ promptBox.append(label.text(labelText).show());
212
+ label.html(label.html().replace(' ','&nbsp;'));
213
+ prompt = $('<span class="jquery-console-prompt"></span>');
214
+ promptBox.append(prompt);
215
+ inner.append(promptBox);
216
+ updatePromptDisplay();
217
+ };
218
+
219
+ ////////////////////////////////////////////////////////////////////////
220
+ // Handle setting focus
221
+ container.click(function(){
222
+ inner.addClass('jquery-console-focus');
223
+ inner.removeClass('jquery-console-nofocus');
224
+ typer.focus();
225
+ scrollToBottom();
226
+ return false;
227
+ });
228
+
229
+ ////////////////////////////////////////////////////////////////////////
230
+ // Handle losing focus
231
+ typer.blur(function(){
232
+ inner.removeClass('jquery-console-focus');
233
+ inner.addClass('jquery-console-nofocus');
234
+ });
235
+
236
+ ////////////////////////////////////////////////////////////////////////
237
+ // Bind to the paste event of the input box so we know when we
238
+ // get pasted data
239
+ typer.bind('paste', function(e) {
240
+ // wipe typer input clean just in case
241
+ typer.val("");
242
+ // this timeout is required because the onpaste event is
243
+ // fired *before* the text is actually pasted
244
+ setTimeout(function() {
245
+ typer.consoleInsert(typer.val());
246
+ typer.val("");
247
+ }, 0);
248
+ });
249
+
250
+ ////////////////////////////////////////////////////////////////////////
251
+ // Handle key hit before translation
252
+ // For picking up control characters like up/left/down/right
253
+
254
+ typer.keydown(function(e){
255
+ cancelKeyPress = 0;
256
+ var keyCode = e.keyCode;
257
+ // C-c: cancel the execution
258
+ if(e.ctrlKey && keyCode == 67) {
259
+ cancelKeyPress = keyCode;
260
+ cancelExecution();
261
+ return false;
262
+ }
263
+ if (acceptInput) {
264
+ if (keyCode in keyCodes) {
265
+ cancelKeyPress = keyCode;
266
+ (keyCodes[keyCode])();
267
+ return false;
268
+ } else if (e.ctrlKey && keyCode in ctrlCodes) {
269
+ cancelKeyPress = keyCode;
270
+ (ctrlCodes[keyCode])();
271
+ return false;
272
+ } else if (e.altKey && keyCode in altCodes) {
273
+ cancelKeyPress = keyCode;
274
+ (altCodes[keyCode])();
275
+ return false;
276
+ }
277
+ }
278
+ });
279
+
280
+ ////////////////////////////////////////////////////////////////////////
281
+ // Handle key press
282
+ typer.keypress(function(e){
283
+ var keyCode = e.keyCode || e.which;
284
+ if (isIgnorableKey(e)) {
285
+ return false;
286
+ }
287
+ // // C-v: don't insert on paste event
288
+ if ((e.ctrlKey || e.metaKey) && String.fromCharCode(keyCode).toLowerCase() == 'v') {
289
+ return true;
290
+ }
291
+ if (acceptInput && cancelKeyPress != keyCode && keyCode >= 32){
292
+ if (cancelKeyPress) return false;
293
+ if (typeof config.charInsertTrigger == 'undefined' ||
294
+ (typeof config.charInsertTrigger == 'function' &&
295
+ config.charInsertTrigger(keyCode,promptText)))
296
+ typer.consoleInsert(keyCode);
297
+ }
298
+ if ($.browser.webkit) return false;
299
+ });
300
+
301
+ function isIgnorableKey(e) {
302
+ // for now just filter alt+tab that we receive on some platforms when
303
+ // user switches windows (goes away from the browser)
304
+ return ((e.keyCode == keyCodes.tab || e.keyCode == 192) && e.altKey);
305
+ };
306
+
307
+ ////////////////////////////////////////////////////////////////////////
308
+ // Rotate through the command history
309
+ function rotateHistory(n){
310
+ if (history.length == 0) return;
311
+ ringn += n;
312
+ if (ringn < 0) ringn = history.length;
313
+ else if (ringn > history.length) ringn = 0;
314
+ var prevText = promptText;
315
+ if (ringn == 0) {
316
+ promptText = restoreText;
317
+ } else {
318
+ promptText = history[ringn - 1];
319
+ }
320
+ if (config.historyPreserveColumn) {
321
+ if (promptText.length < column + 1) {
322
+ column = promptText.length;
323
+ } else if (column == 0) {
324
+ column = promptText.length;
325
+ }
326
+ } else {
327
+ column = promptText.length;
328
+ }
329
+ updatePromptDisplay();
330
+ };
331
+
332
+ function previousHistory() {
333
+ rotateHistory(-1);
334
+ };
335
+
336
+ function nextHistory() {
337
+ rotateHistory(1);
338
+ };
339
+
340
+ // Add something to the history ring
341
+ function addToHistory(line){
342
+ history.push(line);
343
+ restoreText = '';
344
+ };
345
+
346
+ // Delete the character at the current position
347
+ function deleteCharAtPos(){
348
+ if (column < promptText.length){
349
+ promptText =
350
+ promptText.substring(0,column) +
351
+ promptText.substring(column+1);
352
+ restoreText = promptText;
353
+ return true;
354
+ } else return false;
355
+ };
356
+
357
+ function backDelete() {
358
+ if (moveColumn(-1)){
359
+ deleteCharAtPos();
360
+ updatePromptDisplay();
361
+ }
362
+ };
363
+
364
+ function forwardDelete() {
365
+ if (deleteCharAtPos())
366
+ updatePromptDisplay();
367
+ };
368
+
369
+ function deleteUntilEnd() {
370
+ while(deleteCharAtPos()) {
371
+ updatePromptDisplay();
372
+ }
373
+ };
374
+
375
+ function deleteNextWord() {
376
+ // A word is defined within this context as a series of alphanumeric
377
+ // characters.
378
+ // Delete up to the next alphanumeric character
379
+ while(column < promptText.length &&
380
+ !isCharAlphanumeric(promptText[column])) {
381
+ deleteCharAtPos();
382
+ updatePromptDisplay();
383
+ }
384
+ // Then, delete until the next non-alphanumeric character
385
+ while(column < promptText.length &&
386
+ isCharAlphanumeric(promptText[column])) {
387
+ deleteCharAtPos();
388
+ updatePromptDisplay();
389
+ }
390
+ };
391
+
392
+ ////////////////////////////////////////////////////////////////////////
393
+ // Validate command and trigger it if valid, or show a validation error
394
+ function commandTrigger() {
395
+ var line = promptText;
396
+ if (typeof config.commandValidate == 'function') {
397
+ var ret = config.commandValidate(line);
398
+ if (ret == true || ret == false) {
399
+ if (ret) {
400
+ handleCommand();
401
+ }
402
+ } else {
403
+ commandResult(ret,"jquery-console-message-error");
404
+ }
405
+ } else {
406
+ handleCommand();
407
+ }
408
+ };
409
+
410
+ // Scroll to the bottom of the view
411
+ function scrollToBottom() {
412
+ if (jQuery.fn.jquery > "1.6") {
413
+ inner.prop({ scrollTop: inner.prop("scrollHeight") });
414
+ }
415
+ else {
416
+ inner.attr({ scrollTop: inner.attr("scrollHeight") });
417
+ }
418
+ };
419
+
420
+ function cancelExecution() {
421
+ if(typeof config.cancelHandle == 'function') {
422
+ config.cancelHandle();
423
+ }
424
+ }
425
+
426
+ ////////////////////////////////////////////////////////////////////////
427
+ // Handle a command
428
+ function handleCommand() {
429
+ if (typeof config.commandHandle == 'function') {
430
+ disableInput();
431
+ addToHistory(promptText);
432
+ var text = promptText;
433
+ if (extern.continuedPrompt) {
434
+ if (continuedText)
435
+ continuedText += '\n' + promptText;
436
+ else continuedText = promptText;
437
+ } else continuedText = undefined;
438
+ if (continuedText) text = continuedText;
439
+ var ret = config.commandHandle(text,function(msgs){
440
+ commandResult(msgs);
441
+ });
442
+ if (extern.continuedPrompt && !continuedText)
443
+ continuedText = promptText;
444
+ if (typeof ret == 'boolean') {
445
+ if (ret) {
446
+ // Command succeeded without a result.
447
+ commandResult();
448
+ } else {
449
+ commandResult('Command failed.',
450
+ "jquery-console-message-error");
451
+ }
452
+ } else if (typeof ret == "string") {
453
+ commandResult(ret,"jquery-console-message-success");
454
+ } else if (typeof ret == 'object' && ret.length) {
455
+ commandResult(ret);
456
+ } else if (extern.continuedPrompt) {
457
+ commandResult();
458
+ }
459
+ }
460
+ };
461
+
462
+ ////////////////////////////////////////////////////////////////////////
463
+ // Disable input
464
+ function disableInput() {
465
+ acceptInput = false;
466
+ };
467
+
468
+ // Enable input
469
+ function enableInput() {
470
+ acceptInput = true;
471
+ }
472
+
473
+ ////////////////////////////////////////////////////////////////////////
474
+ // Reset the prompt in invalid command
475
+ function commandResult(msg,className) {
476
+ column = -1;
477
+ updatePromptDisplay();
478
+ if (typeof msg == 'string') {
479
+ message(msg,className);
480
+ } else if ($.isArray(msg)) {
481
+ for (var x in msg) {
482
+ var ret = msg[x];
483
+ message(ret.msg,ret.className);
484
+ }
485
+ } else { // Assume it's a DOM node or jQuery object.
486
+ inner.append(msg);
487
+ }
488
+ newPromptBox();
489
+ };
490
+
491
+ ////////////////////////////////////////////////////////////////////////
492
+ // Display a message
493
+ function message(msg,className) {
494
+ var mesg = $('<div class="jquery-console-message"></div>');
495
+ if (className) mesg.addClass(className);
496
+ mesg.filledText(msg).hide();
497
+ inner.append(mesg);
498
+ mesg.show();
499
+ };
500
+
501
+ ////////////////////////////////////////////////////////////////////////
502
+ // Handle normal character insertion
503
+ // data can either be a number, which will be interpreted as the
504
+ // numeric value of a single character, or a string
505
+ typer.consoleInsert = function(data){
506
+ // TODO: remove redundant indirection
507
+ var text = isNaN(data) ? data : String.fromCharCode(data);
508
+ var before = promptText.substring(0,column);
509
+ var after = promptText.substring(column);
510
+ promptText = before + text + after;
511
+ moveColumn(text.length);
512
+ restoreText = promptText;
513
+ updatePromptDisplay();
514
+ };
515
+
516
+ ////////////////////////////////////////////////////////////////////////
517
+ // Move to another column relative to this one
518
+ // Negative means go back, positive means go forward.
519
+ function moveColumn(n){
520
+ if (column + n >= 0 && column + n <= promptText.length){
521
+ column += n;
522
+ return true;
523
+ } else return false;
524
+ };
525
+
526
+ function moveForward() {
527
+ if(moveColumn(1)) {
528
+ updatePromptDisplay();
529
+ return true;
530
+ }
531
+ return false;
532
+ };
533
+
534
+ function moveBackward() {
535
+ if(moveColumn(-1)) {
536
+ updatePromptDisplay();
537
+ return true;
538
+ }
539
+ return false;
540
+ };
541
+
542
+ function moveToStart() {
543
+ if (moveColumn(-column))
544
+ updatePromptDisplay();
545
+ };
546
+
547
+ function moveToEnd() {
548
+ if (moveColumn(promptText.length-column))
549
+ updatePromptDisplay();
550
+ };
551
+
552
+ function moveToNextWord() {
553
+ while(column < promptText.length &&
554
+ !isCharAlphanumeric(promptText[column]) &&
555
+ moveForward()) {
556
+ }
557
+ while(column < promptText.length &&
558
+ isCharAlphanumeric(promptText[column]) &&
559
+ moveForward()) {
560
+ }
561
+ };
562
+
563
+ function moveToPreviousWord() {
564
+ // Move backward until we find the first alphanumeric
565
+ while(column -1 >= 0 &&
566
+ !isCharAlphanumeric(promptText[column-1]) &&
567
+ moveBackward()) {
568
+ }
569
+ // Move until we find the first non-alphanumeric
570
+ while(column -1 >= 0 &&
571
+ isCharAlphanumeric(promptText[column-1]) &&
572
+ moveBackward()) {
573
+ }
574
+ };
575
+
576
+ function isCharAlphanumeric(charToTest) {
577
+ if(typeof charToTest == 'string') {
578
+ var code = charToTest.charCodeAt();
579
+ return (code >= 'A'.charCodeAt() && code <= 'Z'.charCodeAt()) ||
580
+ (code >= 'a'.charCodeAt() && code <= 'z'.charCodeAt()) ||
581
+ (code >= '0'.charCodeAt() && code <= '9'.charCodeAt());
582
+ }
583
+ return false;
584
+ };
585
+
586
+ function doNothing() {};
587
+
588
+ extern.promptText = function(text){
589
+ if (text) {
590
+ promptText = text;
591
+ column = promptText.length;
592
+ updatePromptDisplay();
593
+ }
594
+ return promptText;
595
+ };
596
+
597
+ ////////////////////////////////////////////////////////////////////////
598
+ // Update the prompt display
599
+ function updatePromptDisplay(){
600
+ var line = promptText;
601
+ var html = '';
602
+ if (column > 0 && line == ''){
603
+ // When we have an empty line just display a cursor.
604
+ html = cursor;
605
+ } else if (column == promptText.length){
606
+ // We're at the end of the line, so we need to display
607
+ // the text *and* cursor.
608
+ html = htmlEncode(line) + cursor;
609
+ } else {
610
+ // Grab the current character, if there is one, and
611
+ // make it the current cursor.
612
+ var before = line.substring(0, column);
613
+ var current = line.substring(column,column+1);
614
+ if (current){
615
+ current =
616
+ '<span class="jquery-console-cursor">' +
617
+ htmlEncode(current) +
618
+ '</span>';
619
+ }
620
+ var after = line.substring(column+1);
621
+ html = htmlEncode(before) + current + htmlEncode(after);
622
+ }
623
+ prompt.html(html);
624
+ scrollToBottom();
625
+ };
626
+
627
+ // Simple HTML encoding
628
+ // Simply replace '<', '>' and '&'
629
+ // TODO: Use jQuery's .html() trick, or grab a proper, fast
630
+ // HTML encoder.
631
+ function htmlEncode(text){
632
+ return (
633
+ text.replace(/&/g,'&amp;')
634
+ .replace(/</g,'&lt;')
635
+ .replace(/</g,'&lt;')
636
+ .replace(/ /g,'&nbsp;')
637
+ .replace(/\n/g,'<br />')
638
+ );
639
+ };
640
+
641
+ return extern;
642
+ };
643
+ // Simple utility for printing messages
644
+ $.fn.filledText = function(txt){
645
+ $(this).text(txt);
646
+ $(this).html($(this).html().replace(/\n/g,'<br/>'));
647
+ return this;
648
+ };
649
+ })(jQuery);
@@ -0,0 +1,2 @@
1
+ #= require ./dependencies/jquery-console
2
+ #= require ./dependencies/coffee-script
@@ -23,6 +23,10 @@ Sandbox.views.PagesController = Luca.components.Controller.extend
23
23
  ctype: 'grid_demo'
24
24
  name: 'grid_demo'
25
25
  title: 'Collection Grid'
26
+ ,
27
+ ctype: 'development_console'
28
+ name: 'development_console'
29
+ title: "Development Console"
26
30
  ]
27
31
  ]
28
32
 
@@ -1,3 +1,4 @@
1
+ #= require ./development-console
1
2
  #= require ./sandbox/config
2
3
  #= require_tree ./sandbox/templates
3
4
  #= require_tree ./sandbox/views
@@ -1,6 +1,6 @@
1
1
  module Luca
2
2
  module Rails
3
- VERSION = "0.7.6"
3
+ VERSION = "0.7.7"
4
4
  end
5
5
  end
6
6