Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines.html @ ef38afe9

History | View | Annotate | Download (29.7 kB)

1
{% load i18n %}
2

    
3
<div id="machines" class="separator"></div>
4

    
5
<!-- the create button -->
6
<div id="createcontainer">
7
    <span id="createbody">{% trans "Start by creating a new Virtual Machine:" %}</span><br />
8
    <a id="create" rel="#wizard" href="#">{% trans "Create New +" %}</a>
9
</div>
10

    
11
<!-- changing between standard/list view -->
12
<div id="view-select">
13
    <a id="standard" href="/machines/standard"></a>
14
    <a id="list" href="/machines/list"></a>
15
    <a id="single" href="#"></a>
16
</div>
17

    
18
<div id="emptymachineslist">
19
    <h1 id="welcomeheader">{% trans "Welcome to the ocean!" %}</h1>
20
    <br />
21
    <span class="welcomebody">{% trans "From this panel you will be able to manage your Virtual Machines (VMs). If you don't know what a VM is: take the " %}<a href="#">{% trans "tour" %}</a>.</span>
22
    <br />
23
    <br />
24
    <span class="welcomebody">{% trans "The panel is currently empty, because you don't have any VMs yet. You can start by creating your new VM by clicking the blue button on the right. The wizard will guide you through the hole process." %}</span>
25
    <br />
26
    <br />
27
    <span class="welcomefooter">{% trans "For more information or help, click " %}<a href="#">{% trans "here" %}</a>.</span>
28
</div>
29

    
30
<!-- the form -->
31
<form action="#">
32
        <!-- scrollable root element -->
33
        <div class="modal" id="wizard">
34
                <!-- status bar -->
35
                <ul id="status">
36
                        <li class="active">
37
                <span class="headernumber" class="first">1</span>
38
                <div class="headerbody first">{% trans "Image" %}</div>
39
            </li>
40
                        <li>
41
                <span class="headernumber">2</span>
42
                <div class="headerbody">{% trans "Flavor" %}</div>
43
            </li>
44
                        <li class="third">
45
                <span class="headernumber">3</span>
46
                <div class="headerbody">{% trans "Name" %}</div>
47
            </li>
48
                </ul>
49
                <!-- scrollable items -->
50
                <div class="items">
51
                        <!-- pages -->
52
                        <div class="page">
53
                <h2>{% trans "Select an OS" %}</h2>
54
                <hr class="topruler" />
55
                <ul class="tabs">
56
                    <li><a href="#">{% trans "system images" %}</a></li>
57
                    <li><a href="#">{% trans "custom images" %}</a></li>
58
                </ul>
59
                <div class="panes">
60
                            <li id="image-template" style="display:none">
61
                                    <label for="image.id"> 
62
                            <a>
63
                                <div class="image-container">
64
                                    <div class="image">
65
                                        <input class="radio" type="radio" name="image-id" id="image-id" />
66
                                        <img src="" class="image-logo"/>
67
                                        <strong class="image-title">image.title</strong>
68
                                        <br />
69
                                        <span class="description">image.description</span> 
70
                                        <span id="size" class="size">?? MB</span><span class="size"> MB</span>                         
71
                                    </div>
72
                                </div>  
73
                            </a>
74
                                    </label>
75
                            </li>
76
                    <ul class="pane" id="standard-images">
77
                                            <!-- standard images -->
78
                                    </ul>
79
                    <ul class="pane" id="custom-images">
80
                                            <!-- custom images -->
81
                    </ul>
82
                </div>
83
                <hr class="bottomruler" />
84
                                <button type="button" class="prev" id="cancel">{% trans "Cancel" %}</button>
85
                                <button type="button" class="next right">{% trans "Next" %}</button>
86
            </div>
87
                        <div class="page">
88
                                <h2>{% trans "Select CPUs, RAM and Disk Size" %}</h2>
89
                <hr class="topruler" />
90
                <ul>
91
                    <li id="machinetype">
92
                        <div class="machine-type">
93
                            <label for="small" id="small">
94
                                <input type="radio" id="small" name="machine-type" value="small" checked="true" />
95
                                <span class="typebody" id="small-body">{% trans "small" %}</span>
96
                            </label>
97
                        </div>
98
                        <div class="machine-type">      
99
                            <label for="medium" id="medium">
100
                                <input type="radio" id="medium" name="machine-type" value="medium" />                  
101
                                <span class="typebody" id="medium-body">{% trans "medium" %}</span>
102
                            </label>
103
                        </div>
104
                        <div class="machine-type">
105
                            <label for="large" id="large">
106
                                <input type="radio" id="large" name="machine-type" value="large" />
107
                                <span class="typebody" id="large-body">{% trans "large" %}</span>
108
                            </label>
109
                        </div>
110
                        <div class="machine-type">
111
                            <label for="custom" id="custom">
112
                                <input type="radio" name="machine-type" id="custom" value="large" />
113
                                <span class="typebody" id="custom-body">{% trans "custom" %}</span>
114
                            </label>
115
                        </div>
116
                    </li>
117
                    <div id="page2-container">
118
                        <li class="slider-container">
119
                                        <label><strong class="sliders">CPUs</strong></label>
120
                            <input type="range" id="cpu" style="display:none" />
121
                            <input type="text" class="range" id="cpu-indicator" />
122
                                        <span class="units">cores</span>
123
                        </li>
124
                        <li class="slider-container">
125
                                        <label><strong class="sliders">RAM</strong></label>
126
                            <input type="range" id="ram" style="display:none" />
127
                            <input type="text" class="range" id="ram-indicator" />
128
                                        <span class="units">MB</span>
129
                        </li>
130
                        <li class="slider-container">
131
                                    <label><strong class="sliders">Size</strong></label>
132
                            <input type="range" id="storage" style="display:none" />
133
                            <input type="text" class="range" id="storage-indicator" />
134
                                        <span class="units">GB</span>
135
                        </li>
136
                        <li>
137
                            <div class="cost">
138
                                <span> {% trans "Your wallet:" %} 10,000 Credits </span> | <span>{% trans "This setup will cost you:" %}<input type="text" id="credits-indicator" value="20" class="range" disabled="disabled" /> {% trans "C/hour" %}</span>
139
                            </div>
140
                        </li>
141
                    </div>
142
                </ul>
143
                <hr class="bottomruler" />
144
                                <button type="button" class="prev">{% trans "Back" %}</button>
145
                                <button type="button" class="next right">{% trans "Next" %}</button>
146
            </div>
147
                        <div class="page">
148
                                <h2>{% trans "Confirm your settings" %}</h2>
149
                <hr class="topruler" />
150
                <ul id="page3-container">
151
                    <li class="required" id="label-name">
152
                        <label>
153
                            <strong>Name:</strong>
154
                            <input type="text" class="text" name="machine_name" id="name" value="My Ubuntu 10.04 x86_64 server"/>
155
                        </label>
156
                    </li>
157
                    <li>
158
                        <span>{% trans "Image:" %}</span> <span id="machine_image-label">Ubuntu 10.04 x86_64 server</span>
159
                    </li>
160
                    <li>
161
                        <span>{% trans "CPUs:" %}</span> <span id="machine_cpu-label">2</span> <span>{% trans "cores" %}</span>
162
                    </li>
163
                    <li>
164
                        <span>{% trans "RAM:" %}</span> <span id="machine_ram-label">1024</span><span>MB</span>
165
                    </li>
166
                    <li>
167
                        <span>{% trans "System Disk:" %}</span> <span id="machine_storage-label">10</span><span>GB</span>
168
                    </li>
169
                    <li>
170
                        <span>{% trans "Cost per Hour:" %}</span> <span>40 {% trans "credits" %}</span>
171
                    </li>
172
                    <li>
173
                        <span>{% trans "Credits in Wallet:" %}</span> <span>10.000</span>
174
                    </li>
175
                </ul>
176
                <hr class="bottomruler" />
177
                                <button type="button" class="prev">{% trans "Back" %}</button>
178
                                <button type="button" class="next right" id="start">{% trans "Create VM" %}</button>        
179
            </div>
180
                </div>
181
        </div>
182
</form>
183

    
184
<!-- base notification for error/success reporting -->
185
<a id="notification" rel="#error-success" href="#"></a>
186

    
187
<div class="modal" id="error-success">
188
    <h3>{% trans "Error!/Success!" %}</h3>
189
    <div><p>{% trans "More details about the result"%}</p></div>
190
</div>
191

    
192

    
193
<a id="metadata-edit-dialog" rel="#edit-dialog" href="#"></a>
194

    
195
<div class="meta-modal" id="edit-dialog">
196
    <div class='container'>
197
        <h3>
198
            <label>{% trans "Tags for machine:" %}</label>
199
            <span>Server name</span>
200
            <p style='display:none;'>hidden server id</p>
201
        </h3>
202
        <hr class="topruler" />
203
        <hr class="fatruler" />
204
        <div class="content">
205
            <ul class="meta-template" style="display:none">
206
                <li>
207
                    <label>{% trans "Key" %}</label>
208
                    <button type="button" class="remove">{% trans "remove x" %}</button>
209
                    <hr class="meta-separator">
210
                    <p>{% trans "Value" %}</p>
211
                    <button type="button" class="edit">{% trans "edit" %}</button>
212
                </li>
213
            </ul>
214
            <ul class="meta-list">
215
            </ul>
216
        </div>
217
    </div>
218
    <button type="button" class="create">{% trans "Create New+" %}</button>
219
    <div class="bottomruler"></div>
220
</div>
221

    
222
<a id="metadata-add-dialog" rel="#add-dialog" href="#"></a>
223

    
224
<div class="meta-modal" id="add-dialog">
225
    <div class='container'>
226
        <h3>
227
            <label>{% trans "Tags for machine:" %}</label>
228
            <span>Server name</span>
229
            <p style='display:none;'>hidden server id</p>
230
        </h3>
231
        <hr class="topruler" />
232
        <hr class="fatruler" />
233
        <div class="content">
234
            <label class="meta-key">{% trans "Key:" %}</label>
235
            <input type="text" maxlength="15" class="key" value="{% trans 'max 15 characters' %}"/>
236
            <hr class="meta-separator">
237
            <label class="meta-value">{% trans "Value:" %}</label>
238
            <textarea class="value">{% trans "max 150 characters" %}</textarea>
239
        </div>
240
    </div>
241
    <button type="button" class="cancel">{% trans "Cancel" %}</button>
242
    <button type="button" class="save">{% trans "Save" %}</button>
243
    <div class="bottomruler"></div>
244
</div>
245

    
246
<div id="machinesview"></div>
247

    
248
<div class="confirm_multiple">
249
    <p>{% trans "Your actions will affect" %} <span class="actionLen">XX</span> {% trans "machines" %}</p>
250
    <button class="yes">{% trans "Confirm All" %}</button>
251
        <button class="no">{% trans "Cancel All" %}</button>
252
</div>
253

    
254
<div id="machines" class="separator"></div>
255

    
256
<script>
257

258
//add hover to labels
259
$('span.typebody').mouseover(function() {
260
    $(this).addClass('typehover');
261
});
262
$('span.typebody').mouseout(function() {
263
    $(this).removeClass('typehover');
264
});
265

266
// return value from metadata key "OS", if it exists
267
function os_icon(metadata) {
268
    if (!metadata) {
269
        return 'unknown';
270
    }
271

272
    if (metadata.values.OS == undefined || metadata.values.OS == '') {
273
        return 'unknown';
274
    } else {
275
        if (UrlExists("static/machines/" + metadata.values.OS + '-on.png')) {
276
            return metadata.values.OS;
277
        } else {
278
            return 'unknown';
279
        }
280
    }
281
} 
282

283
//helper function to check file existance
284
function UrlExists(url)
285
{
286
    var http = new XMLHttpRequest();
287
    http.open('HEAD', url, false);
288
    http.send();
289
    return http.status!=404;
290
}
291

292
// switch to list view
293
$("a#list").click(function(){
294
    list_view(); 
295
    return false;
296
});
297

298
// switch to standard view
299
$("a#standard").click(function(){
300
    standard_view();
301
    return false;
302
});
303

304
// launch VM creation wizard
305
$("a#create").click(function(){
306
    // launch wizard only if images and flavors are found
307
    if (images.length > 0  && flavors.length > 0) {
308
        $("#wizard").scrollable().begin();
309
        $("#wizard").show();
310
        $('a#create').data('overlay').load()   
311
    } else if (images.length == 0 ) {
312
        ajax_error('NO_IMAGES');
313
        return false;   
314
    } else if (flavors.length == 0) {
315
        ajax_error('NO_FLAVORS');
316
        return false;
317
    }
318
});
319

320
// create wizard overlay
321
$(function() { 
322
    $("a#create").overlay({
323
        mask: '#000', 
324
        effect: 'default', 
325
        top: '5%', 
326
        oneInstance: false,
327
        closeOnClick: false
328
    });
329
});
330

331
// wizard
332
$(function() {
333
    var root = $("#wizard").scrollable();
334
    var api = root.scrollable();
335
    // rangeinput with default configuration
336
    // validation logic is done inside the onBeforeSeek callback
337
    api.onBeforeSeek(function(event, i) {
338
            // we are going 1 step backwards so no need for validation
339
            if (api.getIndex() < i) {
340
             // 1. get current page
341
                     var page = root.find(".page").eq(api.getIndex()),
342
                         // 2. .. and all required fields inside the page
343
                         inputs = page.find(".required :input").removeClass("error"),
344
                         // 3. .. which are empty
345
                         empty = inputs.filter(function() {
346
                                return $(this).val().replace(/\s*/g, '') == '';
347
                         });
348
                     // if there are empty fields, then
349
                    if (empty.length) {
350
                            // add a CSS class name "error" for empty & required fields
351
                            empty.addClass("error");
352
                            // cancel seeking of the scrollable by returning false
353
                            return false;
354
                    // everything is good
355
                    } 
356
            } 
357
        // update confirm step
358
        if (api.getIndex()==0) {
359
            var image = $("input[type=radio][name=image-id]:checked");
360
            var imageRef = image.length ? image[0].id : false
361
            if (imageRef) {
362
                var imageName = $("label[for=" + imageRef + "] .image-title").text();
363
                $("#machine_image-label")[0].textContent = imageName;
364
                $("input[type=text][name=machine_name]")[0].value = "My " + imageName + " server";
365
            }
366
        } else if (api.getIndex()==1) {
367
            $("#machine_cpu-label")[0].textContent = $("#cpu-indicator")[0].value;
368
            $("#machine_ram-label")[0].textContent = $("#ram-indicator")[0].value;
369
            $("#machine_storage-label")[0].textContent = $("#storage-indicator")[0].value;
370
        }   
371
    });
372
    api.onSeek(function(event, i) {
373
            // update status bar
374
            $("#status li").removeClass("active").eq(i).addClass("active");
375
    });
376
    // if tab is pressed on the next button seek to next page
377
    $(root).live('keydown', function (e) {
378
       if ( e.keyCode == 9 ){
379
           if(e.preventDefault) {
380
               e.preventDefault();
381
           }
382
           api.next();
383
        }
384
    });
385
    //submit wizard by pressing enter on the name textbox
386
    $("#name").keypress(function (e) {
387
                if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
388
                        $('#start').click();
389
                        return false;
390
                } else {
391
                        return true;
392
                }
393
    });
394
});
395

396
// disable sliders in flavor selection
397
function disableSliders() {
398
    $("#cpu").attr('disabled',true);
399
    $("#ram").attr('disabled',true);
400
    $("#storage").attr('disabled',true);
401
}
402

403
//update radio button when clicking on text
404
$("#small-body").live('click' ,function() { 
405
    $(this).parent().find("#small").click();
406
});
407
$("#medium-body").live('click' ,function() { 
408
    $(this).parent().find("#medium").click();
409
});
410
$("#large-body").live('click' ,function() { 
411
    $(this).parent().find("#large").click();
412
});
413
$("#custom-body").live('click' ,function() { 
414
    $(this).parent().find("#custom").click();
415
});
416

417
//select image div on radio button select
418
$('.radio').live('click' ,function() {           
419
    $(this).parents("div").find(".image").removeClass('selecteddiv');
420
    if($(this).is(':checked'))  {
421
        $(this).parent().addClass('selecteddiv');
422
    }
423
    
424
});
425

426
// validate cpu input box
427
$("#cpu-indicator").live('change',function(){
428
    var v = Number(this.value);
429
    var i = cpus.indexOf(v);
430
    if (isNaN(v)) {
431
        $(this).value = cpus[0];
432
        $("#cpu").data('rangeinput').setValue(0);
433
    } else if (i == -1) {
434
        for (var j=0; j < cpus.length; j++)
435
            if (v<cpus[j])
436
                break;
437
        $("#cpu").data('rangeinput').setValue(j);
438
    } else {
439
        $("#cpu").data('rangeinput').setValue(i);
440
    }   
441
    return false;
442
});
443

444
// validate ram input box
445
$("#ram-indicator").live('change',function(){
446
    var v = Number(this.value);
447
    var i = ram.indexOf(v);
448
    if (isNaN(v)) {
449
        $(this).value = cpus[0];
450
        $("#ram").data('rangeinput').setValue(0);
451
    } else if (i == -1) {
452
        for (var j=0; j < ram.length; j++)
453
            if (v<ram[j])
454
                break;
455
        $("#ram").data('rangeinput').setValue(j);
456
    } else {
457
        $("#ram").data('rangeinput').setValue(i);
458
    }   
459
    return false;
460
});
461

462
// validate storage input box
463
$("#storage-indicator").live('change',function(){
464
    var v = Number(this.value);
465
    var i = disks.indexOf(v);
466
    if (isNaN(v)) {
467
        $(this).value = disks[0];
468
        $("#storage").data('rangeinput').setValue(0);
469
    } else if (i == -1) {
470
        for (var j=0; j < disks.length; j++)
471
            if (v<disks[j])
472
                break;
473
        $("#storage").data('rangeinput').setValue(j);
474
    } else {
475
        $("#storage").data('rangeinput').setValue(i);
476
    }   
477
    return false;
478
});
479

480
// selecting the small size
481
$("#small").click(function(){
482
    $("#cpu").data('rangeinput').setValue(0);
483
    $("#ram").data('rangeinput').setValue(0);
484
    $("#storage").data('rangeinput').setValue(0);
485
    $("#cpu-indicator")[0].value = cpus[0];
486
    $("#ram-indicator")[0].value = ram[0];
487
    $("#storage-indicator")[0].value = disks[0];
488
    $("#small").addClass("active");
489
    $("#medium").removeClass("active");    
490
    $("#large").removeClass("active");    
491
    $("#custom").removeClass("active");    
492
});
493

494
// selecting the medium size
495
$("#medium").click(function(){
496
    $("#cpu").data('rangeinput').setValue(1);
497
    $("#ram").data('rangeinput').setValue(1);
498
    $("#storage").data('rangeinput').setValue(1);
499
    $("#cpu-indicator")[0].value = cpus[1];
500
    $("#ram-indicator")[0].value = ram[1];
501
    $("#storage-indicator")[0].value = disks[1];  
502
    $("#medium").addClass("active");  
503
    $("#small").removeClass("active");    
504
    $("#large").removeClass("active");    
505
    $("#custom").removeClass("active");  
506
});
507

508
// selecting the large size
509
$("#large").click(function(){
510
    $("#cpu").data('rangeinput').setValue(2);
511
    $("#ram").data('rangeinput').setValue(2);
512
    $("#storage").data('rangeinput').setValue(2);
513
    $("#cpu-indicator")[0].value = cpus[2];
514
    $("#ram-indicator")[0].value = ram[2];
515
    $("#storage-indicator")[0].value = disks[2];   
516
    $("#large").addClass("active"); 
517
    $("#medium").removeClass("active");    
518
    $("#small").removeClass("active");    
519
    $("#custom").removeClass("active");  
520
});
521

522
// selecting the custom flavor enables the sliders
523
$("#custom").click(function(){
524
    $("#cpu").attr('disabled',false);
525
    $("#ram").attr('disabled',false);
526
    $("#storage").attr('disabled',false);
527
    $("strong.sliders").style = 'color: #778899;';
528
    $("#custom input").attr('checked', 'checked');                
529
    $("#custom").addClass("active"); 
530
    $("#medium").removeClass("active");    
531
    $("#large").removeClass("active");    
532
    $("#small").removeClass("active");  
533
});
534

535
//when textbox gains focus, add selection in css
536
$('#cpu-indicator').focus(function() {
537
    $(this).addClass('selectedrange');
538
});
539
$('#ram-indicator').focus(function() {
540
    $(this).addClass('selectedrange');
541
});
542
$('#storage-indicator').focus(function() {
543
    $(this).addClass('selectedrange');
544
});
545

546
//when textbox loses focus, clear selection in css
547
$('#cpu-indicator').blur(function() {
548
    $(this).removeClass('selectedrange');
549
});
550
$('#ram-indicator').blur(function() {
551
    $(this).removeClass('selectedrange');
552
});
553
$('#storage-indicator').blur(function() {
554
    $(this).removeClass('selectedrange');
555
});
556

557
// exit the wizard
558
$("#cancel").click(function(){
559
    $("a#create").overlay().close();
560
});
561

562
// starting a new VM through the wizard
563
$("#start").click(function(){
564
    var imageRef = $('input[type=radio][name=image-id]:checked')[0].id.replace('img-radio-','');   
565
    var flavorRef = identify_flavor($("#cpu-indicator")[0].value, $("#storage-indicator")[0].value, $("#ram-indicator")[0].value);
566
    var machineName = $('input[name=machine_name]')[0].value;
567
    if (jQuery.trim(machineName) == ''){
568
        return false;
569
    }
570
    create_vm(machineName, imageRef, flavorRef);
571

572
    $('a#create').data('overlay').close();
573

574
    try{console.warn('creating ' + $("input[name=machine_name]")[0].value)} catch(err){}
575

576
    $("#wizard").hide();
577
});
578

579
// confirm all actions
580
$("div.confirm_multiple .yes").live('click', function(){
581
    while(pending_actions.length > 0){ // if there is a pending action for this server execute it
582
        action = pending_actions.pop(); // extract action
583
        var serverID = action[1];
584
        if ($.cookie("list") != '1') { // standard view
585
            $('#' + serverID + ' .selected').removeClass('selected');
586
            $('#' + serverID + ' .display').removeClass('display');
587
            if (action[0] == shutdown) {
588
                $('#' + serverID + ' .status').text('Shutting down');
589
            } else if (action[0] == start) {
590
                $('#' + serverID + ' .status').text('Starting');
591
            } else if (action[0] == reboot) {
592
                $('#' + serverID + ' .status').text('Rebooting');
593
            } else if (action[0] == destroy) {
594
                $('#' + serverID + ' .status').text('Destroying');
595
            }
596
            $('#' + serverID + ' .spinner').show();
597
        } else { // list view
598
            osIcon = $('#'+serverID).parent().parent().find('.list-logo');
599
            osIcon.attr('os',osIcon.attr('src'));
600
            osIcon.attr('src','static/progress.gif');
601
            if (action[0] == shutdown) {
602
                $('#' + serverID).parent().parent().find('span.status').text('Shutting down');
603
            } else if (action[0] == start) {
604
                $('#' + serverID).parent().parent().find('span.status').text('Starting');
605
            } else if (action[0] == reboot) {
606
                $('#' + serverID).parent().parent().find('span.status').text('Rebooting');
607
            } else if (action[0] == destroy) {
608
                $('#' + serverID).parent().parent().find('span.status').text('Destroying');
609
            }
610
        }
611
        action[0]([serverID]); // execute action
612
    }
613
    update_confirmations();    
614
});
615

616
// cancel all actions
617
$("div.confirm_multiple .no").live('click', function(){
618
    pending_actions = [];
619
    $('.machine .selected').removeClass('selected');
620
    $('.machine .display').removeClass('display');
621
    update_confirmations();
622
});
623

624
// bring up edit metadata overlay
625
function show_metadata_edit_dialog() {
626
    var triggers = $("a#metadata-edit-dialog").overlay({
627
        // some mask tweaks suitable for modal dialogs
628
        mask: '#000',
629
        effect: 'default',
630
        top: '10%',
631
        closeOnClick: false,
632
        oneInstance: false,
633
        load: false,
634
        onClose: function() {
635
            // remove all entries so they won't be preloaded next time you open the dialog
636
            $("#edit-dialog div.content ul.meta-list").empty();
637
        },
638
        onLoad: function() {
639
            // this is a workaround for the mask not appearing problem
640
            $("#edit-dialog").expose();
641
        }
642
    });
643
    // get metadata for current server and fill the dialog
644
    serverID = $("#edit-dialog h3 p").text();
645
    get_metadata(serverID);
646
    $("a#metadata-edit-dialog").data('overlay').load();
647
    return false; 
648
}
649

650
// bring up add metadata overlay
651
function show_metadata_add_dialog() {
652
    var triggers = $("a#metadata-add-dialog").overlay({
653
        // some mask tweaks suitable for modal dialogs
654
        mask: '#000',
655
        effect: 'default',
656
        top: '10%',
657
        closeOnClick: false,
658
        oneInstance: false,
659
        load: false,
660
        onLoad: function() {
661
            // this is a workaround for the mask not appearing problem
662
            $("#add-dialog").expose();
663
        },
664
        onClose: function(){
665
            // reset input areas
666
            $(".meta-modal input.key").removeClass("input-enabled");
667
            $(".meta-modal input.key")[0].value = 'max 15 characters';
668
            $(".meta-modal textarea.value").removeClass("input-enabled");
669
            $(".meta-modal textarea.value")[0].value = 'max 150 characters';
670
            show_metadata_edit_dialog();        
671
        }
672
    });
673
    $("a#metadata-add-dialog").data('overlay').load();
674
    return false; 
675
}
676

677
// trapping keydown event
678
jQuery.expr[':'].focus = function( elem ) {
679
  return elem === document.activeElement && ( elem.type || elem.href );
680
};
681

682
$('*').keydown(function (){
683
    if ($('#add-dialog').is(":visible") && !($('input.key').is(':focus') || $('textarea.value').is(':focus'))){
684
        $('input.key').focus();
685
        $('input.key').focusin();         
686
    }
687
    return true;
688
});
689

690
// intercept click on create button in metadata edit dialog
691
$('#edit-dialog.meta-modal button.create').click( function(){
692
    // close edit metadata and open add metadata dialog
693
    $('a#metadata-edit-dialog').data('overlay').close();
694
    show_metadata_add_dialog();
695
});
696

697
// intercept click on remove button in metadata edit dialog
698
$('#edit-dialog.meta-modal button.remove').live('click', function() { 
699
    // get the server id and meta key needed for the ajax call   
700
    var serverID = $(this).closest('div.container').find('h3 p').text();
701
    var meta_key = $(this).parent().find('label').text();
702
    // make the ajax call and list the new GET results
703
    delete_metadata(serverID, meta_key);
704
    return false;
705
});
706

707
// intercept click on edit button in metadata edit dialog
708
$('#edit-dialog.meta-modal button.edit').click( function(){
709
    // inline editing of selected key-value pair
710
    // on submission ajax call from updating
711
    // on success update the overlay
712
    // TODO
713
});
714

715
// intercept click on cancel button in metadata add dialog
716
$('#add-dialog.meta-modal button.cancel').click( function(){
717
    // close add metadata and open edit metadata dialog
718
    $('a#metadata-add-dialog').data('overlay').close();
719
});
720

721
// intercept create metadata key focus
722
$(".meta-modal input.key").live('focusin', function() {
723
    if ($(this).hasClass("input-enabled")) {
724
    } else {
725
        $(".meta-modal input.key").addClass("input-enabled"); 
726
        $(this).addClass("input-enabled"); 
727
        this.value = '';
728
    }
729
    return false;
730
});
731

732
// intercept create metadata key focus out
733
$(".meta-modal input.key").live('focusout', function() {
734
    if (this.value == "") {
735
        $(this).removeClass("input-enabled"); 
736
        this.value = 'max 15 characters';
737
    }
738
    return false;
739
});
740

741
// intercept create metadata key focus
742
$(".meta-modal textarea.value").live('focusin', function() {
743
    if ($(this).hasClass("input-enabled")) {
744
    } else {
745
        $(".meta-modal textarea.value").addClass("input-enabled"); 
746
        $(this).addClass("input-enabled"); 
747
        this.value = '';
748
    }
749
    return false;
750
});
751

752
// intercept create metadata key focus out
753
$(".meta-modal textarea.value").live('focusout', function() {
754
    if (this.value == "") {
755
        $(this).removeClass("input-enabled"); 
756
        this.value = 'max 150 characters';
757
    }
758
    return false;
759
});
760

761
// intercept click on save button in metadata add dialog
762
$('#add-dialog.meta-modal button.save').live('click', function() {
763
    // if both fields are filled in     
764
    if ($('input.key').hasClass("input-enabled") && $('textarea.value').hasClass("input-enabled")) {
765
        // get the server id, meta key and meta value needed for the ajax call     
766
        var serverID = $(this).parent().find('h3 p').text();
767
        var meta_key = $(this).parent().find('input.key').attr('value');
768
        var meta_value = $(this).parent().find('textarea.value')[0].value;
769
        // make the ajax call and list the new GET results
770
        add_metadata(serverID, meta_key, meta_value);
771
        // close add metadata and open edit metadata dialog
772
        $('a#metadata-add-dialog').data('overlay').close();
773
        show_metadata_edit_dialog();
774
    } else {
775
        // find which field is not filled in and focus there
776
        if (!$('input.key').hasClass("input-enabled")) {
777
            $('input.key').focus();
778
            $('input.key').focusin();
779
        } else {
780
            $('textarea.value').focus();
781
            $('textarea.value').focusin();
782
        }
783
    }
784
    return false;
785
});
786

787
// update metadata in edit dialog
788
function list_metadata(data) {    
789
    // empty the list if it already exists
790
    $("#edit-dialog div.content ul.meta-list").empty();
791
    // get the values to show
792
    meta = data.metadata.values;
793
    // show values
794
    for (key in meta) {
795
        pair = $("ul.meta-template li").clone();
796
        //truncate metadata
797
        pair.find("label").text(key.substring(0,15));
798
        if (meta[key].length > 25) {
799
            pair.find("p").text(meta[key].substring(0,25) + "...");
800
        } else {
801
            pair.find("p").text(meta[key]);            
802
        }
803
        pair.appendTo("#edit-dialog div.content ul.meta-list").fadeIn();
804
    }
805
}
806

807
// basic functions executed on page load
808
if (images.length > 0) {
809
    // populate image list
810
    update_wizard_images();
811
}
812
if (flavors.length > 0) {
813
    // configure flavors
814
    update_wizard_flavors(); 
815
}
816
// create tabs for main menu
817
$("ul.tabs").tabs("div.panes ul");
818

    
819
</script>