Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines.html @ f533f224

History | View | Annotate | Download (36.5 kB)

1
{% load i18n %}
2

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

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

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

    
19
<div id="emptymachineslist">
20
    <h1 id="welcomeheader">{% trans "Welcome to the ocean!" %}</h1>
21
    <br />
22
    <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>
23
    <br />
24
    <br />
25
    <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 whole process." %}</span>
26
    <br />
27
    <br />
28
    <span class="welcomefooter">{% trans "For more information or help, click " %}<a href="#">{% trans "here" %}</a>.</span>
29
</div>
30

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

    
190
<!-- metadata overlay -->
191
<div>
192
    <div id="metadata-wizard" class="modal">
193
        <h3 class="popup-header">{% trans "Manage Tags" %}</h3>
194
        <p style='display:none;'>hidden server id</p>
195
        <div id="on-off" style='display:none;'>hidden server id</div>
196
        <div class="popup-body">
197
            <div class="popup-body-inner">
198
                <div class="popup-title">{% trans "Create, edit and delete Tags for machine:" %}</div>
199
                <div class="name-container">
200
                    <img src="" class="machine-icon" />
201
                    <div class="machine-name"></div>
202
                </div>
203
                <div class="popup-separator"></div>
204
                <div class="large-spinner" style="display:none;"></div>
205
                <div class="metadata-container">
206
                    <!-- append metadata entries here -->
207
                </div>
208
                <div class="metadata-add-template" style="display:none;">
209
                    <input type="text" id="add-meta-key" maxlength="15"></input>
210
                    <ul>
211
                        {% for o in default_keywords %}
212
                            <li><span class="dropdownitem">{{o}}</span></li>
213
                        {% endfor %}
214
                    </ul>
215
                    <input type="text" id="add-meta-value" maxlength="150" value="{% trans 'max 150 characters' %}"></input>
216
                    <div class="addbuttons">
217
                        <span class="save" />
218
                        <span class="cancel" />
219
                    </div>
220
                </div>
221
                <div class="metadata-pair-template" style="display:none;">
222
                    <div class="metadata-key">{% trans "OS" %}</div>
223
                    <div class="vertical-separator"></div>
224
                    <div class="metadata-value">{% trans "Debian" %}</div>
225
                    <div class="metadata-full-value" style="display:none;"></div>
226
                    <div class="metadata-edit">
227
                        <span class="edit" />
228
                        <span class="remove" />
229
                    </div>
230
                    <div class="editbuttons" style="display:none;">
231
                        <span class="save" />
232
                        <span class="remove" />
233
                    </div>
234
                </div>
235
            </div>
236
        </div>
237
        <div class="buttons">
238
            <button type="button" class="save" id="metadata-cancel">{% trans "Close" %}</button>
239
            <button type="button" class="create" id="metadata-create">{% trans "Create New" %}</button>
240
        </div>
241
    </div>
242
</div>
243

    
244
<a id="metadata-scrollable" href="#" rel="#metadata-wizard"></a>
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
<script>
255

256
//add hover to labels
257
$('#machines-pane span.typebody').mouseover(function() {
258
    $(this).addClass('typehover');
259
});
260
$('#machines-pane span.typebody').mouseout(function() {
261
    $(this).removeClass('typehover');
262
});
263

264
// return value from metadata key "OS", if it exists
265
function os_icon(metadata) {
266
    if (!metadata) {
267
        return 'unknown';
268
    }
269
    if (metadata.values.OS == undefined || metadata.values.OS == '') {
270
        return 'unknown';
271
    } else {
272
        if (os_icons.indexOf(metadata.values.OS) == -1) {
273
            return 'unknown';
274
        } else {
275
            return metadata.values.OS;
276
        }
277
    }
278
}
279

280
function os_icon_from_value(metadata) {
281
    if (!metadata) {
282
        return 'unknown';
283
    }
284
if (metadata == undefined || metadata == '') {
285
        return 'unknown';
286
    } else {
287
        if (os_icons.indexOf(metadata) == -1) {
288
            return 'unknown';
289
        } else {
290
            return metadata;
291
        }
292
    }
293
}
294

295
// switch to list view
296
$("#machines-pane a#list").click(function(){
297
    list_view();
298
    return false;
299
});
300

301
// switch to standard view
302
$("#machines-pane a#standard").click(function(){
303
    standard_view();
304
    return false;
305
});
306

307
// switch to single view
308
$("#machines-pane a#single").click(function(){
309
    single_view();
310
    return false;
311
});
312

313
// launch VM creation wizard
314
$("#machines-pane a#create").click(function(){
315
    // launch wizard only if images and flavors are found
316
    if (images.length > 0  && flavors.length > 0) {
317
        $("#wizard").scrollable().begin();
318
        $("#wizard").show();
319
        $('#machines-pane a#create').data('overlay').load()
320
    } else if (images.length == 0 ) {
321
        ajax_error('NO_IMAGES');
322
        return false;
323
    } else if (flavors.length == 0) {
324
        ajax_error('NO_FLAVORS');
325
        return false;
326
    }
327
});
328

329
// create wizard overlay
330
$(function() {
331
    $("#machines-pane a#create").overlay({
332
        mask: '#000',
333
        effect: 'default',
334
        top: '5%',
335
        oneInstance: false,
336
        closeOnClick: false
337
    });
338
});
339

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

405
// disable sliders in flavor selection
406
function disableSliders() {
407
    $("#cpu").attr('disabled',true);
408
    $("#ram").attr('disabled',true);
409
    $("#storage").attr('disabled',true);
410
}
411

412
//update radio button when clicking on text
413
$("#small-body").live('click' ,function() {
414
    $(this).parent().find("#small").click();
415
});
416

417
$("#medium-body").live('click' ,function() {
418
    $(this).parent().find("#medium").click();
419
});
420

421
$("#large-body").live('click' ,function() {
422
    $(this).parent().find("#large").click();
423
});
424

425
$("#custom-body").live('click' ,function() {
426
    $(this).parent().find("#custom").click();
427
});
428

429
//select image div on radio button select
430
$('#machines-pane .radio').live('click' ,function() {
431
    $(this).parents("div").find(".image").removeClass('selecteddiv');
432
    if($(this).is(':checked'))  {
433
        $(this).parent().addClass('selecteddiv');
434
    }
435
});
436

437
// validate cpu input box
438
$("#cpu-indicator").live('change',function(){
439
    var v = Number(this.value);
440
    var i = cpus.indexOf(v);
441
    if (isNaN(v)) {
442
        $(this).value = cpus[0];
443
        $("#cpu").data('rangeinput').setValue(0);
444
    } else if (i == -1) {
445
        for (var j=0; j < cpus.length; j++)
446
            if (v<cpus[j])
447
                break;
448
        $("#cpu").data('rangeinput').setValue(j);
449
    } else {
450
        $("#cpu").data('rangeinput').setValue(i);
451
    }
452
    return false;
453
});
454

455
// validate ram input box
456
$("#ram-indicator").live('change',function(){
457
    var v = Number(this.value);
458
    var i = ram.indexOf(v);
459
    if (isNaN(v)) {
460
        $(this).value = cpus[0];
461
        $("#ram").data('rangeinput').setValue(0);
462
    } else if (i == -1) {
463
        for (var j=0; j < ram.length; j++)
464
            if (v<ram[j])
465
                break;
466
        $("#ram").data('rangeinput').setValue(j);
467
    } else {
468
        $("#ram").data('rangeinput').setValue(i);
469
    }
470
    return false;
471
});
472

473
// validate storage input box
474
$("#storage-indicator").live('change',function(){
475
    var v = Number(this.value);
476
    var i = disks.indexOf(v);
477
    if (isNaN(v)) {
478
        $(this).value = disks[0];
479
        $("#storage").data('rangeinput').setValue(0);
480
    } else if (i == -1) {
481
        for (var j=0; j < disks.length; j++)
482
            if (v<disks[j])
483
                break;
484
        $("#storage").data('rangeinput').setValue(j);
485
    } else {
486
        $("#storage").data('rangeinput').setValue(i);
487
    }
488
    return false;
489
});
490

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

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

519
// selecting the large size
520
$("#large").click(function(){
521
    $("#cpu").data('rangeinput').setValue(2);
522
    $("#ram").data('rangeinput').setValue(2);
523
    $("#storage").data('rangeinput').setValue(2);
524
    $("#cpu-indicator")[0].value = cpus[2];
525
    $("#ram-indicator")[0].value = ram[2];
526
    $("#storage-indicator")[0].value = disks[2];
527
    $("#large").addClass("active");
528
    $("#medium").removeClass("active");
529
    $("#small").removeClass("active");
530
    $("#custom").removeClass("active");
531
});
532

533
// selecting the custom flavor enables the sliders
534
$("#custom").click(function(){
535
    $("#cpu").attr('disabled',false);
536
    $("#ram").attr('disabled',false);
537
    $("#storage").attr('disabled',false);
538
    $("strong.sliders").style = 'color: #778899;';
539
    $("#custom input").attr('checked', 'checked');
540
    $("#custom").addClass("active");
541
    $("#medium").removeClass("active");
542
    $("#large").removeClass("active");
543
    $("#small").removeClass("active");
544
});
545

546
//when textbox gains focus, add selection in css
547
$('#cpu-indicator').focus(function() {
548
    $(this).addClass('selectedrange');
549
});
550

551
$('#ram-indicator').focus(function() {
552
    $(this).addClass('selectedrange');
553
});
554

555
$('#storage-indicator').focus(function() {
556
    $(this).addClass('selectedrange');
557
});
558

559
//when textbox loses focus, clear selection in css
560
$('#cpu-indicator').blur(function() {
561
    $(this).removeClass('selectedrange');
562
});
563

564
$('#ram-indicator').blur(function() {
565
    $(this).removeClass('selectedrange');
566
});
567

568
$('#storage-indicator').blur(function() {
569
    $(this).removeClass('selectedrange');
570
});
571

572
// exit the wizard
573
$("#cancel").click(function(){
574
    $("#machines-pane a#create").overlay().close();
575
});
576

577
// starting a new VM through the wizard
578
$("#start").click(function(){
579
    var imageRef = $('input[type=radio][name=image-id]:checked')[0].id.replace('img-radio-','');
580
    var flavorRef = identify_flavor($("#cpu-indicator")[0].value, $("#storage-indicator")[0].value, $("#ram-indicator")[0].value);
581
    var machineName = $('input[name=machine_name]')[0].value;
582
    if (jQuery.trim(machineName) == ''){
583
        return false;
584
    }
585

586
    //replace text 'create new' with progress indicator
587
    $('#wizard #start').text('');
588
    $('#wizard #start').html('<img src="/static/icons/indicators/medium/horizontal-progress.gif" / >');
589

590
    create_vm(machineName, imageRef, flavorRef);
591

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

594
});
595

596
// metadata wizard
597
$(function() {
598
    // create wizard overlay
599
    $("a#metadata-scrollable").overlay({
600
        mask: '#000',
601
        effect: 'default',
602
        top: '10%',
603
        closeOnClick: false,
604
        oneInstance: false,
605
        closeOnEsc: true,
606
        load: false,
607
        onClose: function(){
608
            // reset input areas
609
            serverID = $("#metadata-wizard p:first").text();
610
            $("#metadata-wizard div.metadata-container").empty();
611
            get_metadata(serverID, true);
612
        }
613
    });
614
});
615

616
// bring up metadata overlay
617
function show_metadata_wizard() {
618
    // get metadata for current server and fill the dialog
619
    serverID = $("#metadata-wizard p:first").text();
620
    get_metadata(serverID);
621
    $("#metadata-wizard").show();
622
    $("a#metadata-scrollable").data('overlay').load();
623
    $('#metadata-wizard .large-spinner').show();
624
    return false;
625
}
626

627
// update metadata list
628
function list_metadata(data) {
629
    // empty the list if it already exists
630
    $("#metadata-wizard div.metadata-container").empty();
631
    // get the values to show
632
    meta = data.metadata.values;
633
    // set serve icon
634
    var icon_name = os_icon(data.metadata);
635
    $("#metadata-wizard .machine-icon").attr("src","static/icons/machines/small/" + icon_name + '-' + $("#metadata-wizard div#on-off").text() + '.png');
636
    // show values
637
    for (key in meta) {
638
        pair = $("#metadata-wizard div.metadata-pair-template:last").clone();
639
        //truncate metadata
640
        pair.find("div.metadata-key").text(key.substring(0,15));
641
        if (meta[key].length > 25) {
642
            pair.find("div.metadata-value").text(meta[key].substring(0,25) + "...");
643
        } else {
644
            pair.find("div.metadata-value").text(meta[key]);
645
        }
646
        //get the serverID
647
        serverID = $("#metadata-wizard p:first").text();
648
        //store the full metadata value on a hidden div
649
        pair.find("div.metadata-full-value").text(meta[key]);
650
        // show/hide edit-remove buttons on hover
651
        pair.hover(function () {$(this).find('.metadata-edit').show();}, function () {$(this).find('.metadata-edit').hide();});
652
        // add it to the list
653
        pair.appendTo("#metadata-wizard div.metadata-container").fadeIn();
654
    }
655
}
656

657
// exit the metadata wizard
658
$("#metadata-cancel").click(function(){
659
    $("a#metadata-scrollable").overlay().close();
660
});
661

662
//intercept create new metadata click
663
$("#metadata-wizard #metadata-create").click(function(){
664
    pair = $("#metadata-wizard div.metadata-add-template:first").clone();
665
    pair.prependTo("#metadata-wizard div.metadata-container").fadeIn();
666
      with (pair.find('input#add-meta-key')) {
667
        with (next('ul:first')) {
668
          find('li').click(function() {
669
            $(this).parent().prev('.textdropdown-outer').find('input:first').attr('value', $(this).find('.dropdownitem').html());
670
            $(this).parent().hide();
671
          });
672
          hide();
673
        }
674

675
        keypress(function() {
676
          $(this).parent().next('ul:first').hide();
677
        });
678

679
        change(function() {
680
          $(this).parent().next('ul:first').hide();
681
        });
682

683
        wrap('<div class="textdropdown-outer" style="width: ' + width() + 'px; height: ' + (height() + 5) + 'px"></div>');
684
        var btn = parent().prepend('<div class="textdropdown-btn">&nbsp;</div>').find('.textdropdown-btn');
685
        width(width() - btn.width() - 5);
686
        css("border", "0");
687

688
        btn.click(function() {
689
          var p = parent();
690
          with (p.next('ul:first')) {
691
            css('position', 'absolute');
692
            css('width',    p.width());
693
            css('left',     p.position().left + 4);
694
            css('top',      p.position().top + p.height() + 1);
695
            toggle();
696
          }
697
        });
698
      }
699
    pair.find('input#add-meta-key').focus();
700
});
701

702
//save new metadata
703
$('#metadata-wizard .addbuttons .save').die('click');
704
$('#metadata-wizard .addbuttons .save').live('click', function(){
705
    keyValue = $(this).parent().parent().find('input#add-meta-key').val();
706
    valValue = $(this).parent().parent().find('input#add-meta-value').val();
707
    if ((keyValue == '{% trans 'max 15 characters' %}') || (valValue == '{% trans 'max 150 characters' %}')) {
708
        return false;
709
    } else {
710
        serverID = $("#metadata-wizard p:first").text();
711
        pair = $("#metadata-wizard div.metadata-pair-template:last").clone();
712
        pair.find("div.metadata-key").text(keyValue.substring(0,15));
713
        if (valValue.length > 25) {
714
            pair.find("div.metadata-value").text(valValue.substring(0,25) + "...");
715
        } else {
716
            pair.find("div.metadata-value").text(valValue);
717
        }
718
        pair.find("div.metadata-full-value").text(valValue);
719
        update_metadata(serverID, keyValue, valValue);
720
        $(this).parent().parent().remove();
721
        pair.hover(function () {$(this).find('.metadata-edit').show();}, function () {$(this).find('.metadata-edit').hide();});
722
        // add it to the list
723
        if ($("#metadata-wizard div.metadata-container").find("div.metadata-pair-template").length > 0) {
724
            pair.insertBefore("#metadata-wizard div.metadata-container div.metadata-pair-template:first").fadeIn();
725
        } else {
726
            pair.prependTo("#metadata-wizard div.metadata-container").fadeIn();
727
        }
728
    }
729
});
730

731
//intercept cancel new metadata creation
732
$("#metadata-wizard .addbuttons .cancel").die('click');
733
$("#metadata-wizard .addbuttons .cancel").live('click',function(){
734
    $(this).parent().parent().fadeOut('fast');
735
    window.setTimeout(function(){$(this).parent().parent().remove();}, 400);
736
});
737

738
//metadata remove button
739
$("#metadata-wizard .metadata-edit .remove").die('click')
740
$("#metadata-wizard .metadata-edit .remove").live('click', function() {
741
    $(this).parent().parent().fadeOut('slow');
742
    serverID = $("#metadata-wizard p:first").text();
743
    keyValue = $(this).parent().parent().find('div.metadata-key').text();
744
    //update icons if deleting the OS metadata
745
    if (keyValue == "OS") {
746
        $("#metadata-wizard .machine-icon").attr("src","static/icons/machines/small/unknown-" + $("#metadata-wizard div#on-off").text() + '.png');
747
        $("#machinesview-icon").find("div#" + serverID).find("img.logo").attr("src", "static/icons/machines/medium/unknown-" + $("#metadata-wizard div#on-off").text() + '.png');
748
    }
749
    delete_metadata(serverID, keyValue);
750
});
751

752
//metadata edit button
753
$("#metadata-wizard .metadata-edit .edit").die('click');
754
$("#metadata-wizard .metadata-edit .edit").live('click', function() {
755
    $(this).parent().parent().find('div.metadata-value').html("<input id=\"value-edit\" maxlength=\"150\" type=\"text\" class=\"metatextbox\" value=\"" + $(this).parent().parent().find('.metadata-full-value').text() +
756
                                    "\" / ><span class=\"oldValue\">" +
757
                                    $(this).parent().parent().find('.metadata-full-value').text() + "</span>");
758
    $(this).parent().hide();
759
    $(this).parent().parent().unbind('mouseenter').unbind('mouseleave');
760
    $(this).parent().parent().find('.editbuttons').show();
761
});
762

763
//metadata cancel edit button
764
$("#metadata-wizard .editbuttons .remove").die('click');
765
$("#metadata-wizard .editbuttons .remove").live('click', function() {
766
    var oldValue = $(this).parent().parent().find('.oldValue').text();
767
    if (oldValue.length > 25) {
768
        oldValue = oldValue.substring(0,25) + "...";
769
    }
770
    $(this).parent().parent().find('div.metadata-value').html(oldValue);
771
    $(this).parent().parent().hover(function () {$(this).find('.metadata-edit').show();}, function () {$(this).find('.metadata-edit').hide();});
772
    $(this).parent().hide();
773
});
774

775
//metadata save edit button
776
$("#metadata-wizard .editbuttons .save").die('click');
777
$("#metadata-wizard .editbuttons .save").live('click', function() {
778
    newValue = $(this).parent().parent().find('input.metatextbox').val();
779
    keyValue = $(this).parent().parent().find('div.metadata-key').text();
780
    oldValue = $(this).parent().parent().find('.oldValue').text();
781
    if (!(newValue == oldValue)) {
782
        update_metadata(serverID, keyValue, newValue);
783
    }
784
    if (newValue.length > 25) {
785
        newValueSort = newValue.substring(0,25) + "...";
786
    } else {
787
        newValueSort = newValue
788
    }
789
    $(this).parent().parent().find('div.metadata-value').html(newValueSort);
790
    $(this).parent().parent().find('div.metadata-full-value').html(newValue);
791
    $(this).parent().parent().hover(function () {$(this).find('.metadata-edit').show();}, function () {$(this).find('.metadata-edit').hide();});
792
    $(this).parent().hide();
793

794
});
795

796
// trapping keydown event
797
jQuery.expr[':'].focus = function( elem ) {
798
    var api = $("#metadata-wizard").data("scrollable");
799
    if (api.getIndex() == 1) {
800
      return elem === document.activeElement && ( elem.type || elem.href );
801
    }
802
};
803

804
// intercept create metadata key focus
805
$("#metadata-wizard input#add-meta-key").live('focusin', function() {
806
    if ($(this).parent().hasClass("div-enabled")) {
807
    } else {
808
        $(this).parent().addClass("div-enabled");
809
        $(this).addClass("input-enabled");
810
        if (this.value == '{% trans 'max 15 characters' %}') {
811
            this.value = '';
812
        }
813
    }
814
    return false;
815
});
816

817
// intercept create metadata key focus out
818
$("#metadata-wizard input#add-meta-key").live('focusout', function() {
819
    $(this).parent().removeClass("div-enabled");
820
    if (this.value == "") {
821
        $(this).removeClass("input-enabled");
822
        this.value = '{% trans 'max 15 characters' %}';
823
    }
824
    return false;
825
});
826

827

828
// intercept metadata dropdown item click
829
$(".metadata-add-template li").live('click', function() {
830
    $(this).parent().parent().parent().find("input#add-meta-value").focus();
831
    $(this).parent().parent().parent().find("input#add-meta-key").addClass("input-enabled");
832
});
833

834
// intercept create metadata key focus
835
$("#metadata-wizard input#add-meta-value").live('focusin', function() {
836
    if ($(this).hasClass("input-enabled")) {
837
    } else {
838
        $(this).addClass("input-enabled");
839
        this.value = '';
840
    }
841
    return false;
842
});
843

844
// intercept create metadata key focus out
845
$("#metadata-wizard input#add-meta-value").live('focusout', function() {
846
    if (this.value == "") {
847
        $(this).removeClass("input-enabled");
848
        this.value = '{% trans 'max 150 characters' %}';
849
    }
850
    return false;
851
});
852

853
// intercept click on cancel button in metadata add dialog
854
$('#add-dialog button.cancel').live('click', function() {
855

856
});
857

858
// intercept click on save button in metadata add dialog
859
$('#add-dialog button.save').live('click', function() {
860
    // if both fields are filled in
861
    if ($('input.key').hasClass("input-enabled") && $('textarea.value').hasClass("input-enabled")) {
862
        // get the server id, meta key and meta value needed for the ajax call
863
        var serverID = $(this).parent().find('h3 p').text();
864
        var meta_key = $(this).parent().find('input.key').attr('value');
865
        var meta_value = $(this).parent().find('textarea.value')[0].value;
866
        // make the ajax call and list the new GET results
867
        add_metadata(serverID, meta_key, meta_value);
868
        // go to previous step
869
        $('#add-dialog button.prev').click();
870
    } else {
871
        // find which field is not filled in and focus there
872
        if (!$('input.key').hasClass("input-enabled")) {
873
            $('input.key').focus();
874
            $('input.key').focusin();
875
        } else {
876
            $('textarea.value').focus();
877
            $('textarea.value').focusin();
878
        }
879
    }
880
    return false;
881
});
882

883
// confirm all actions
884
$("#machines-pane div.confirm_multiple .yes").live('click', function(){
885
    while(pending_actions.length > 0){ // if there is a pending action for this server execute it
886
        action = pending_actions.pop(); // extract action
887
        var serverID = action[1];
888
        if ($.cookie("view") != '1') { // standard view
889
            $('#' + serverID + ' .selected').removeClass('selected');
890
            $('#' + serverID + ' .display').removeClass('display');
891
            if (action[0] == shutdown) {
892
                $('#' + serverID + ' .status').text(TRANSITIONS['Shutting down']);
893
            } else if (action[0] == start) {
894
                $('#' + serverID + ' .status').text(TRANSITIONS['Starting']);
895
            } else if (action[0] == reboot) {
896
                $('#' + serverID + ' .status').text(TRANSITIONS['Rebooting']);
897
            } else if (action[0] == destroy) {
898
                $('#' + serverID + ' .status').text(TRANSITIONS['Destroying']);
899
            }
900
            $('#' + serverID + ' .spinner').show();
901
        } else { // list view
902
            osIcon = $('#'+serverID).parent().parent().find('.list-logo');
903
            osIcon.attr('os',osIcon.attr('src'));
904
            osIcon.attr('src','static/icons/indicators/small/progress.gif');
905
            if (action[0] == shutdown) {
906
                $('#' + serverID).parent().parent().find('span.status').text(TRANSITIONS['Shutting down']);
907
            } else if (action[0] == start) {
908
                $('#' + serverID).parent().parent().find('span.status').text(TRANSITIONS['Starting']);
909
            } else if (action[0] == reboot) {
910
                $('#' + serverID).parent().parent().find('span.status').text(TRANSITIONS['Rebooting']);
911
            } else if (action[0] == destroy) {
912
                $('#' + serverID).parent().parent().find('span.status').text(TRANSITIONS['Destroying']);
913
            }
914
        }
915
        action[0]([serverID]); // execute action
916
    }
917
    update_confirmations();
918
});
919

920
// cancel all actions
921
$("#machines-pane div.confirm_multiple .no").live('click', function(){
922
    pending_actions = [];
923
    $('#machines-pane .machine .selected').removeClass('selected');
924
    $('#machinesview-list .actions .selected').removeClass('selected');
925
    $('#machines-pane .machine .display').removeClass('display');
926
    update_confirmations();
927
});
928

929
// basic functions executed on page load
930
if (images.length > 0) {
931
    // populate image list
932
    update_wizard_images();
933
}
934
if (flavors.length > 0) {
935
    // configure flavors
936
    update_wizard_flavors();
937
}
938
// create tabs for main menu
939
$("ul.tabs").tabs("div.panes ul");
940

    
941
</script>