Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines.html @ a5bc3755

History | View | Annotate | Download (40.4 kB)

1
<!--
2
Copyright 2011 GRNET S.A. All rights reserved.
3

4
Redistribution and use in source and binary forms, with or
5
without modification, are permitted provided that the following
6
conditions are met:
7

8
  1. Redistributions of source code must retain the above
9
     copyright notice, this list of conditions and the following
10
     disclaimer.
11

12
  2. Redistributions in binary form must reproduce the above
13
     copyright notice, this list of conditions and the following
14
     disclaimer in the documentation and/or other materials
15
     provided with the distribution.
16

17
THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
18
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
21
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
POSSIBILITY OF SUCH DAMAGE.
29

30
The views and conclusions contained in the software and
31
documentation are those of the authors and should not be
32
interpreted as representing official policies, either expressed
33
or implied, of GRNET S.A.
34
-->
35

    
36
{% load i18n %}
37

    
38
<div id="machines" class="separator"></div>
39

    
40
<!-- the create button -->
41
<div id="createcontainer">
42
    <div id="beforecreate" style="display:inline;"></div>
43
    <a id="create" rel="#wizard" href="#">{% trans "Create New +" %}</a>
44
</div>
45

    
46
<!-- changing between standard/list view -->
47
<div id="view-select">
48
    <a id="standard" href="{% url machines-standard %}"></a>
49
    <a id="list" href="{% url machines-list %}"></a>
50
    <a id="single" href="{% url machines-single %}"></a>
51
</div>
52

    
53
<div id="emptymachineslist">
54
    <h1 id="welcomeheader">{% trans "Welcome to ~okeanos !" %}</h1>
55
    <br />
56
    <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: " %}<br /><a href="#">{% trans "take the tour" %}</a>.</span>
57
    <br />
58
    <br />
59
    <span class="welcomebody">{% trans "The panel is currently empty, because you don't have any VMs yet. Start by clicking the orange button on the top left. The wizard will guide you through the whole process." %}</span>
60
    <br />
61
    <br />
62
    <span class="welcomefooter">{% trans "For more information or help, click " %}<a href="#">{% trans "here" %}</a>.</span>
63
</div>
64

    
65
<!-- the form -->
66
<form action="#">
67
    <!-- scrollable root element -->
68
    <div class="modal" id="wizard">
69
        <!-- status bar -->
70
        <ul id="status">
71
            <li class="active li-0">
72
                <span class="headernumber" class="first">1</span>
73
                <div class="headerbody first">{% trans "Image" %}</div>
74
                <img src="static/check.png" class="img-check" style="visibility:hidden;" />
75
            </li>
76
            <li class="li-1">
77
                <span class="headernumber">2</span>
78
                <div class="headerbody">{% trans "Flavor" %}</div>
79
                <img src="static/check.png" class="img-check" style="visibility:hidden;" />
80
            </li>
81
            <li class="li-2">
82
                <span class="headernumber">3</span>
83
                <div class="headerbody">{% trans "Name" %}</div>
84
            </li>
85
        </ul>
86
        <!-- scrollable items -->
87
        <div class="items">
88
            <!-- pages -->
89
            <div class="page page1">
90
                <h2>{% trans "Select an OS" %}</h2>
91
                <hr class="topruler" />
92
                <div id="tabscontainer">
93
                    <ul class="tabs">
94
                        <li><a href="#">{% trans "system images" %}</a></li>
95
                        <li><a href="#">{% trans "custom images" %}</a></li>
96
                    </ul>
97
                </div>
98
                <div class="panes">
99
                    <li id="image-template" style="display:none">
100
                        <label for="image.id">
101
                            <a>
102
                                <div class="image-container">
103
                                    <div class="image">
104
                                        <input class="radio" type="radio" name="image-id" id="image-id" />
105
                                        <img src="" class="image-logo"/>
106
                                        <strong class="image-title">image.title</strong>
107
                                        <br />
108
                                        <div class="description-container">
109
                                            <span class="description">image.description</span>
110
                                            <span id="size" class="size">?? MB</span><span class="size"> MB</span>
111
                                        </div>
112
                                    </div>
113
                                </div>
114
                            </a>
115
                        </label>
116
                    </li>
117
                    <ul class="pane" id="standard-images">
118
                        <!-- standard images -->
119
                    </ul>
120
                    <ul class="pane" id="custom-images">
121
                        <!-- custom images -->
122
                    </ul>
123
                </div>
124
                <hr class="bottomruler" />
125
                <button type="button" class="prev" id="cancel">{% trans "Cancel" %}</button>
126
                <button type="button" class="next right">{% trans "Next" %}<img src="static/next.png" class="img-next" /></button>
127
            </div>
128
            <div class="page page2">
129
                <h2>{% trans "Select CPUs, RAM and Disk Size" %}</h2>
130
                <hr class="topruler" />
131
                <ul>
132
                    <li id="machinetype">
133
                        <div class="machine-type">
134
                            <label for="small" id="small">
135
                                <input type="radio" id="small" name="machine-type" value="small" checked="true" />
136
                                <span class="typebody" id="small-body">{% trans "small" %}</span>
137
                            </label>
138
                        </div>
139
                        <div class="machine-type">
140
                            <label for="medium" id="medium">
141
                                <input type="radio" id="medium" name="machine-type" value="medium" />
142
                                <span class="typebody" id="medium-body">{% trans "medium" %}</span>
143
                            </label>
144
                        </div>
145
                        <div class="machine-type">
146
                            <label for="large" id="large">
147
                                <input type="radio" id="large" name="machine-type" value="large" />
148
                                <span class="typebody" id="large-body">{% trans "large" %}</span>
149
                            </label>
150
                        </div>
151
                        <div class="machine-type">
152
                            <label for="custom" id="custom">
153
                                <input type="radio" name="machine-type" id="custom" value="large" />
154
                                <span class="typebody" id="custom-body">{% trans "custom" %}</span>
155
                            </label>
156
                        </div>
157
                    </li>
158
                    <div id="page2-container">
159
                        <li class="slider-container">
160
                            <label><strong class="sliders">{% trans "CPUs" %}</strong></label>
161
                            <input type="range" id="cpu" style="display:none" />
162
                            <input type="text" class="range" id="cpu-indicator" />
163
                            <span class="units">{% trans "cores" %}</span>
164
                        </li>
165
                        <li class="slider-container">
166
                            <label><strong class="sliders">{% trans "RAM" %}</strong></label>
167
                            <input type="range" id="ram" style="display:none" />
168
                            <input type="text" class="range" id="ram-indicator" />
169
                            <span class="units">MB</span>
170
                        </li>
171
                        <li class="slider-container">
172
                            <label><strong class="sliders">{% trans "Size" %}</strong></label>
173
                            <input type="range" id="storage" style="display:none" />
174
                            <input type="text" class="range" id="storage-indicator" />
175
                            <span class="units">GB</span>
176
                        </li>
177
                        <li>
178
                            <div class="cost">
179
                                <span> {% trans "Your wallet:" %} 10,000 {% trans "Credits" %} </span> | <span>{% trans "This setup will cost you:" %}<input type="text" id="credits-indicator" value="0" class="range" disabled="disabled" /> {% trans "C/hour" %}</span>
180
                            </div>
181
                        </li>
182
                    </div>
183
                </ul>
184
                <hr class="bottomruler" />
185
                <button type="button" class="prev"><img src="static/prev.png" class="img-prev" />{% trans "Back" %}</button>
186
                <button type="button" class="next right">{% trans "Next" %}<img src="static/next.png" class="img-next" /></button>
187
            </div>
188
            <div class="page page3">
189
                <h2>{% trans "Confirm your settings" %}</h2>
190
                <hr class="topruler" />
191
                <ul id="page3-container">
192
                    <li class="required" id="label-name">
193
                        <label>
194
                            <strong>{% trans "Name" %}:</strong>
195
                            <input type="text" class="text" name="machine_name" id="name" value="My Ubuntu 10.04 x86_64 server"/>
196
                        </label>
197
                    </li>
198
                    <li>
199
                        <span>{% trans "Image:" %}</span> <span id="machine_image-label">Ubuntu 10.04 x86_64 server</span>
200
                    </li>
201
                    <li>
202
                        <span>{% trans "CPUs:" %}</span> <span id="machine_cpu-label">2</span> <span>{% trans "cores" %}</span>
203
                    </li>
204
                    <li>
205
                        <span>{% trans "RAM:" %}</span> <span id="machine_ram-label">1024</span><span>MB</span>
206
                    </li>
207
                    <li>
208
                        <span>{% trans "System Disk:" %}</span> <span id="machine_storage-label">10</span><span>GB</span>
209
                    </li>
210
                    <li>
211
                        <span>{% trans "Cost per Hour:" %}</span> <span>40 {% trans "credits" %}</span>
212
                    </li>
213
                    <li>
214
                        <span>{% trans "Credits in Wallet:" %}</span> <span>10.000</span>
215
                    </li>
216
                </ul>
217
                <hr class="bottomruler" />
218
                <button type="button" class="prev"><img src="static/prev.png" class="img-prev" />{% trans "Back" %}</button>
219
                <button type="button" class="next right" id="start">{% trans "Create VM" %}</button>
220
            </div>
221
        </div>
222
        <div class="separator-end"></div>
223
    </div>
224
</form>
225

    
226
<!-- metadata overlay -->
227
<div>
228
    <div id="metadata-wizard" class="modal">
229
        <h3 class="popup-header">{% trans "Manage Tags" %}</h3>
230
        <p style='display:none;'>hidden server id</p>
231
        <div id="on-off" style='display:none;'>hidden server id</div>
232
        <div class="popup-body">
233
            <div class="popup-body-inner">
234
                <div class="popup-title">{% trans "Create, edit and delete Tags for machine:" %}</div>
235
                <div class="name-container">
236
                    <img src="" class="machine-icon" />
237
                    <div class="machine-name"></div>
238
                </div>
239
                <div class="popup-separator"></div>
240
                <div class="large-spinner" style="display:none;"></div>
241
                <div class="metadata-container">
242
                    <!-- append metadata entries here -->
243
                </div>
244
                <div class="metadata-add-template" style="display:none;">
245
                    <input type="text" id="add-meta-key" maxlength="15"></input>
246
                    <ul>
247
                        {% for o in default_keywords %}
248
                            <li><span class="dropdownitem">{{o}}</span></li>
249
                        {% endfor %}
250
                    </ul>
251
                    <input type="text" id="add-meta-value" maxlength="150" value="{% trans 'max 150 characters' %}"></input>
252
                    <div class="addbuttons">
253
                        <div class="save"></div>
254
                        <div class="cancel"></div>
255
                    </div>
256
                </div>
257
                <div class="metadata-pair-template" style="display:none;">
258
                    <div class="metadata-key">{% trans "OS" %}</div>
259
                    <div class="vertical-separator"></div>
260
                    <div class="metadata-value">{% trans "Debian" %}</div>
261
                    <div class="metadata-full-value" style="display:none;"></div>
262
                    <div class="metadata-edit">
263
                        <div class="edit"></div>
264
                        <div class="remove"></div>
265
                    </div>
266
                    <div class="editbuttons" style="display:none;">
267
                        <div class="save"></div>
268
                        <div class="remove"></div>
269
                    </div>
270
                </div>
271
            </div>
272
        </div>
273
        <div class="buttons">
274
            <button type="button" class="save" id="metadata-cancel">{% trans "Close" %}</button>
275
            <button type="button" class="create" id="metadata-create">{% trans "Create New" %}</button>
276
        </div>
277
    </div>
278
</div>
279

    
280
<a id="metadata-scrollable" href="#" rel="#metadata-wizard"></a>
281

    
282
<div id="machinesview"></div>
283

    
284
<div class="confirm_multiple">
285
    <p>{% trans "Your actions will affect" %} <span class="actionLen">XX</span> {% trans "machines" %}</p>
286
    <button class="yes">{% trans "Confirm All" %}</button>
287
    <button class="no">{% trans "Cancel All" %}</button>
288
</div>
289

    
290
<script>
291

292
//change hover icon on prev,next buttons
293
$("#wizard button.next").hover(function() {
294
        $(this).find(".img-next").attr("src","static/next-hover.png");
295
    },
296
    function() {
297
        $(this).find(".img-next").attr("src","static/next.png");
298
    }
299
);
300
$("#wizard button.prev").hover(function() {
301
        $(this).find(".img-prev").attr("src","static/prev-hover.png");
302
    },
303
    function() {
304
        $(this).find(".img-prev").attr("src","static/prev.png");
305
    }
306
);
307

308
//add hover to labels
309
$('#machines-pane span.typebody').mouseover(function() {
310
    $(this).addClass('typehover');
311
});
312
$('#machines-pane span.typebody').mouseout(function() {
313
    $(this).removeClass('typehover');
314
});
315

316
// return value from metadata key "OS", if it exists
317
function os_icon(metadata) {
318
    if (!metadata) {
319
        return 'unknown';
320
    }
321
    if (metadata.values.OS == undefined || metadata.values.OS == '') {
322
        return 'unknown';
323
    } else {
324
        if (os_icons.indexOf(metadata.values.OS) == -1) {
325
            return 'unknown';
326
        } else {
327
            return metadata.values.OS;
328
        }
329
    }
330
}
331

332
function os_icon_from_value(metadata) {
333
    if (!metadata) {
334
        return 'unknown';
335
    }
336
if (metadata == undefined || metadata == '') {
337
        return 'unknown';
338
    } else {
339
        if (os_icons.indexOf(metadata) == -1) {
340
            return 'unknown';
341
        } else {
342
            return metadata;
343
        }
344
    }
345
}
346

347
// switch to list view
348
$("#machines-pane a#list").click(function(){
349
    list_view();
350
    return false;
351
});
352

353
// switch to standard view
354
$("#machines-pane a#standard").click(function(){
355
    standard_view();
356
    return false;
357
});
358

359
// switch to single view
360
$("#machines-pane a#single").click(function(){
361
    single_view();
362
    return false;
363
});
364

365
// launch VM creation wizard
366
$("#machines-pane a#create").click(function(){
367
    // launch wizard only if images and flavors are found
368
    if (images.length > 0  && flavors.length > 0) {
369
        $('#machines-pane a#create').data('overlay').close();
370
        $("#wizard").scrollable().begin();
371
        $("#wizard").show();
372
        $('#machines-pane a#create').data('overlay').load();
373
    } else if (images.length == 0 ) {
374
        ajax_error('NO_IMAGES');
375
        return false;
376
    } else if (flavors.length == 0) {
377
        ajax_error('NO_FLAVORS');
378
        return false;
379
    }
380
});
381

382
// create wizard overlay
383
$(function() {
384
    $("#machines-pane a#create").overlay({
385
        mask: '#000',
386
        effect: 'default',
387
        top: '5%',
388
        oneInstance: false,
389
        closeOnClick: false
390
    });
391
});
392

393
// wizard
394
$(function() {
395
    var root = $("#wizard").scrollable();
396
    var api = root.scrollable();
397
    // rangeinput with default configuration
398
    // validation logic is done inside the onBeforeSeek callback
399
    api.onBeforeSeek(function(event, i) {
400
        // update status bar
401
        $("#status li").removeClass("active").eq(i).addClass("active");
402
        // we are going 1 step backwards so no need for validation
403
        if (api.getIndex() > i) {
404
            $("#wizard .li-" + i).removeClass("checked");
405
            $("#wizard .li-" + i).find(".img-check").css("visibility","hidden");
406
        }
407
        if (api.getIndex() < i) {
408
            $("#wizard .li-" + api.getIndex()).addClass("checked");
409
            $("#wizard .li-" + api.getIndex()).find(".img-check").css("visibility","visible");
410
             // 1. get current page
411
             var page = root.find(".page").eq(api.getIndex()),
412
             // 2. .. and all required fields inside the page
413
             inputs = page.find(".required :input").removeClass("error"),
414
             // 3. .. which are empty
415
             empty = inputs.filter(function() {
416
                return $(this).val().replace(/\s*/g, '') == '';
417
             });
418
             // if there are empty fields, then
419
            if (empty.length) {
420
                // add a CSS class name "error" for empty & required fields
421
                empty.addClass("error");
422
                // cancel seeking of the scrollable by returning false
423
                return false;
424
            // everything is good
425
            }
426
        }
427
        // update confirm step
428
        if (api.getIndex()==0) {
429
            var image = $("input[type=radio][name=image-id]:checked");
430
            var imageRef = image.length ? image[0].id : false
431
            if (imageRef) {
432
                var imageName = $("label[for=" + imageRef + "] .image-title").text();
433
                $("#machine_image-label")[0].textContent = imageName;
434
                $("input[type=text][name=machine_name]")[0].value = "My " + imageName + " server";
435
            }
436
        } else if (api.getIndex()==1) {
437
            $("#machine_cpu-label")[0].textContent = $("#cpu-indicator")[0].value;
438
            $("#machine_ram-label")[0].textContent = $("#ram-indicator")[0].value;
439
            $("#machine_storage-label")[0].textContent = $("#storage-indicator")[0].value;
440
        }
441
    });
442
    // if tab is pressed on the next button seek to next page
443
    $(root).live('keydown', function (e) {
444
       if ( e.keyCode == 9 ){
445
           if(e.preventDefault) {
446
               e.preventDefault();
447
           }
448
           api.next();
449
        }
450
    });
451
    //submit wizard by pressing enter on the name textbox
452
    $("#name").keypress(function (e) {
453
        if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
454
            $('#start').click();
455
            return false;
456
        } else {
457
            return true;
458
        }
459
    });
460
});
461

462
// disable sliders in flavor selection
463
function disableSliders() {
464
    $("#cpu").attr('disabled',true);
465
    $("#ram").attr('disabled',true);
466
    $("#storage").attr('disabled',true);
467
}
468

469
//update radio button when clicking on text
470
$("#small-body").live('click' ,function() {
471
    $(this).parent().find("#small").click();
472
});
473

474
$("#medium-body").live('click' ,function() {
475
    $(this).parent().find("#medium").click();
476
});
477

478
$("#large-body").live('click' ,function() {
479
    $(this).parent().find("#large").click();
480
});
481

482
$("#custom-body").live('click' ,function() {
483
    $(this).parent().find("#custom").click();
484
});
485

486
//select image div on radio button select
487
$('#machines-pane .radio').live('click' ,function() {
488
    $(this).parents("div").find(".image").removeClass('selecteddiv');
489
    if($(this).is(':checked'))  {
490
        $(this).parent().addClass('selecteddiv');
491
    }
492
});
493

494
// validate cpu input box
495
$("#cpu-indicator").live('change',function(){
496
    var v = Number(this.value);
497
    var i = cpus.indexOf(v);
498
    if (isNaN(v)) {
499
        $(this).value = cpus[0];
500
        $("#cpu").data('rangeinput').setValue(0);
501
    } else if (i == -1) {
502
        for (var j=0; j < cpus.length; j++)
503
            if (v<cpus[j])
504
                break;
505
        $("#cpu").data('rangeinput').setValue(j);
506
    } else {
507
        $("#cpu").data('rangeinput').setValue(i);
508
    }
509
    return false;
510
});
511

512
// validate ram input box
513
$("#ram-indicator").live('change',function(){
514
    var v = Number(this.value);
515
    var i = ram.indexOf(v);
516
    if (isNaN(v)) {
517
        $(this).value = cpus[0];
518
        $("#ram").data('rangeinput').setValue(0);
519
    } else if (i == -1) {
520
        for (var j=0; j < ram.length; j++)
521
            if (v<ram[j])
522
                break;
523
        $("#ram").data('rangeinput').setValue(j);
524
    } else {
525
        $("#ram").data('rangeinput').setValue(i);
526
    }
527
    return false;
528
});
529

530
// validate storage input box
531
$("#storage-indicator").live('change',function(){
532
    var v = Number(this.value);
533
    var i = disks.indexOf(v);
534
    if (isNaN(v)) {
535
        $(this).value = disks[0];
536
        $("#storage").data('rangeinput').setValue(0);
537
    } else if (i == -1) {
538
        for (var j=0; j < disks.length; j++)
539
            if (v<disks[j])
540
                break;
541
        $("#storage").data('rangeinput').setValue(j);
542
    } else {
543
        $("#storage").data('rangeinput').setValue(i);
544
    }
545
    return false;
546
});
547

548
// selecting the small size
549
$("#small").click(function(){
550
    $("#cpu").data('rangeinput').setValue(0);
551
    $("#ram").data('rangeinput').setValue(0);
552
    $("#storage").data('rangeinput').setValue(0);
553
    $("#cpu-indicator")[0].value = cpus[0];
554
    $("#ram-indicator")[0].value = ram[0];
555
    $("#storage-indicator")[0].value = disks[0];
556
    $("#small").addClass("active");
557
    $("#medium").removeClass("active");
558
    $("#large").removeClass("active");
559
    $("#custom").removeClass("active");
560
});
561

562
// selecting the medium size
563
$("#medium").click(function(){
564
    $("#cpu").data('rangeinput').setValue(1);
565
    $("#ram").data('rangeinput').setValue(1);
566
    $("#storage").data('rangeinput').setValue(1);
567
    $("#cpu-indicator")[0].value = cpus[1];
568
    $("#ram-indicator")[0].value = ram[1];
569
    $("#storage-indicator")[0].value = disks[1];
570
    $("#medium").addClass("active");
571
    $("#small").removeClass("active");
572
    $("#large").removeClass("active");
573
    $("#custom").removeClass("active");
574
});
575

576
// selecting the large size
577
$("#large").click(function(){
578
    $("#cpu").data('rangeinput').setValue(2);
579
    $("#ram").data('rangeinput').setValue(2);
580
    $("#storage").data('rangeinput').setValue(2);
581
    $("#cpu-indicator")[0].value = cpus[2];
582
    $("#ram-indicator")[0].value = ram[2];
583
    $("#storage-indicator")[0].value = disks[2];
584
    $("#large").addClass("active");
585
    $("#medium").removeClass("active");
586
    $("#small").removeClass("active");
587
    $("#custom").removeClass("active");
588
});
589

590
// selecting the custom flavor enables the sliders
591
$("#custom").click(function(){
592
    $("#cpu").attr('disabled',false);
593
    $("#ram").attr('disabled',false);
594
    $("#storage").attr('disabled',false);
595
    $("strong.sliders").style = 'color: #778899;';
596
    $("#custom input").attr('checked', 'checked');
597
    $("#custom").addClass("active");
598
    $("#medium").removeClass("active");
599
    $("#large").removeClass("active");
600
    $("#small").removeClass("active");
601
});
602

603
//when textbox gains focus, add selection in css
604
$('#cpu-indicator').focus(function() {
605
    $(this).addClass('selectedrange');
606
});
607

608
$('#ram-indicator').focus(function() {
609
    $(this).addClass('selectedrange');
610
});
611

612
$('#storage-indicator').focus(function() {
613
    $(this).addClass('selectedrange');
614
});
615

616
//when textbox loses focus, clear selection in css
617
$('#cpu-indicator').blur(function() {
618
    $(this).removeClass('selectedrange');
619
});
620

621
$('#ram-indicator').blur(function() {
622
    $(this).removeClass('selectedrange');
623
});
624

625
$('#storage-indicator').blur(function() {
626
    $(this).removeClass('selectedrange');
627
});
628

629
// exit the wizard
630
$("#cancel").click(function(){
631
    $("#machines-pane a#create").overlay().close();
632
});
633

634
// starting a new VM through the wizard
635
$("#start").click(function(){
636
    var imageRef = $('input[type=radio][name=image-id]:checked')[0].id.replace('img-radio-','');
637
    var flavorRef = identify_flavor($("#cpu-indicator")[0].value, $("#storage-indicator")[0].value, $("#ram-indicator")[0].value);
638
    var machineName = $('input[name=machine_name]')[0].value;
639
    if (jQuery.trim(machineName) == ''){
640
        return false;
641
    }
642

643
    //replace text 'create new' with progress indicator
644
    $('#wizard #start').text('');
645
    $('#wizard #start').html('<img src="static/icons/indicators/medium/horizontal-progress.gif" / >');
646

647
    create_vm(machineName, imageRef, flavorRef);
648

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

651
});
652

653
// metadata wizard
654
$(function() {
655
    // create wizard overlay
656
    $("a#metadata-scrollable").overlay({
657
        mask: '#000',
658
        effect: 'default',
659
        top: '10%',
660
        closeOnClick: false,
661
        oneInstance: false,
662
        closeOnEsc: false,
663
        load: false,
664
        onClose: function(){
665
            // reset input areas
666
            serverID = $("#metadata-wizard p:first").text();
667
            $("#metadata-wizard div.metadata-container").empty();
668
            get_metadata(serverID, true);
669
        }
670
    });
671
});
672

673
// bring up metadata overlay
674
function show_metadata_wizard() {
675
    // get metadata for current server and fill the dialog
676
    serverID = $("#metadata-wizard p:first").text();
677
    get_metadata(serverID);
678
    $("#metadata-wizard").show();
679
    $("a#metadata-scrollable").data('overlay').load();
680
    $('#metadata-wizard .large-spinner').show();
681
    return false;
682
}
683

684
// update metadata list
685
function list_metadata(data) {
686
    // empty the list if it already exists
687
    $("#metadata-wizard div.metadata-container").empty();
688
    // get the values to show
689
    meta = data.metadata.values;
690
    // set serve icon
691
    var icon_name = os_icon(data.metadata);
692
    $("#metadata-wizard .machine-icon").attr("src","static/icons/machines/small/" + icon_name + '-' + $("#metadata-wizard div#on-off").text() + '.png');
693
    // show values
694
    for (key in meta) {
695
        pair = $("#metadata-wizard div.metadata-pair-template:last").clone();
696
        //truncate metadata
697
        pair.find("div.metadata-key").text(key.substring(0,15));
698
        if (meta[key].length > 25) {
699
            pair.find("div.metadata-value").text(meta[key].substring(0,25) + "...");
700
        } else {
701
            pair.find("div.metadata-value").text(meta[key]);
702
        }
703
        //get the serverID
704
        serverID = $("#metadata-wizard p:first").text();
705
        //store the full metadata value on a hidden div
706
        pair.find("div.metadata-full-value").text(meta[key]);
707
        // show/hide edit-remove buttons on hover
708
        pair.hover(function () {$(this).find('.metadata-edit').show();}, function () {$(this).find('.metadata-edit').hide();});
709
        // add it to the list
710
        pair.appendTo("#metadata-wizard div.metadata-container").fadeIn();
711
    }
712
}
713

714
// exit the metadata wizard
715
$("#metadata-cancel").click(function(){
716
    $("a#metadata-scrollable").overlay().close();
717
});
718

719
//intercept create new metadata click
720
$("#metadata-wizard #metadata-create").click(function(){
721
    pair = $("#metadata-wizard div.metadata-add-template:first").clone();
722
    pair.prependTo("#metadata-wizard div.metadata-container").fadeIn();
723
      with (pair.find('input#add-meta-key')) {
724
        with (next('ul:first')) {
725
          find('li').click(function() {
726
            $(this).parent().prev('.textdropdown-outer').find('input:first').attr('value', $(this).find('.dropdownitem').html());
727
            $(this).parent().hide();
728
          });
729
          hide();
730
        }
731

732
        keypress(function() {
733
          $(this).parent().next('ul:first').hide();
734
        });
735

736
        change(function() {
737
          $(this).parent().next('ul:first').hide();
738
        });
739

740
        wrap('<div class="textdropdown-outer" style="width: ' + width() + 'px; height: ' + (height() + 5) + 'px"></div>');
741
        var btn = parent().prepend('<div class="textdropdown-btn">&nbsp;</div>').find('.textdropdown-btn');
742
        width(width() - btn.width() - 5);
743
        css("border", "0");
744

745
        btn.click(function() {
746
          var p = parent();
747
          with (p.next('ul:first')) {
748
            css('position', 'absolute');
749
            css('width',    p.width());
750
            css('left',     p.position().left + 4);
751
            css('top',      p.position().top + p.height() + 1);
752
            toggle();
753
          }
754
        });
755
      }
756
    pair.find('input#add-meta-key').focus();
757
    //submit keyword by pressing enter on the textbox
758
    $(this).parent().parent().find('input#add-meta-value').keypress(function (e) {
759
        if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
760
            $(this).parent().parent().find('.addbuttons .save').click();
761
            return false;
762
        } else {
763
            return true;
764
        }
765
    });
766
});
767

768
//save new metadata
769
$('#metadata-wizard .addbuttons .save').die('click');
770
$('#metadata-wizard .addbuttons .save').live('click', function(){
771
    keyValue = $(this).parent().parent().find('input#add-meta-key').val();
772
    valValue = $(this).parent().parent().find('input#add-meta-value').val();
773
    if ((keyValue == '{% trans 'max 15 characters' %}') || (valValue == '{% trans 'max 150 characters' %}')) {
774
        return false;
775
    } else {
776
        serverID = $("#metadata-wizard p:first").text();
777
        pair = $("#metadata-wizard div.metadata-pair-template:last").clone();
778
        pair.find("div.metadata-key").text(keyValue.substring(0,15));
779
        if (valValue.length > 25) {
780
            pair.find("div.metadata-value").text(valValue.substring(0,25) + "...");
781
        } else {
782
            pair.find("div.metadata-value").text(valValue);
783
        }
784
        pair.find("div.metadata-full-value").text(valValue);
785
        update_metadata(serverID, keyValue, valValue);
786
        $(this).parent().parent().remove();
787
        pair.hover(function () {$(this).find('.metadata-edit').show();}, function () {$(this).find('.metadata-edit').hide();});
788
        // add it to the list
789
        if ($("#metadata-wizard div.metadata-container").find("div.metadata-pair-template").length > 0) {
790
            pair.insertBefore("#metadata-wizard div.metadata-container div.metadata-pair-template:first").fadeIn();
791
        } else {
792
            pair.prependTo("#metadata-wizard div.metadata-container").fadeIn();
793
        }
794
    }
795
});
796

797
//intercept cancel new metadata creation
798
$("#metadata-wizard .addbuttons .cancel").die('click');
799
$("#metadata-wizard .addbuttons .cancel").live('click',function(){
800
    $(this).parent().parent().fadeOut('fast', function() { $(this).remove(); });
801
});
802

803
//metadata remove button
804
$("#metadata-wizard .metadata-edit .remove").die('click')
805
$("#metadata-wizard .metadata-edit .remove").live('click', function() {
806
    $(this).parent().parent().fadeOut('slow');
807
    serverID = $("#metadata-wizard p:first").text();
808
    keyValue = $(this).parent().parent().find('div.metadata-key').text();
809
    //update icons if deleting the OS metadata
810
    if (keyValue == "OS") {
811
        $("#metadata-wizard .machine-icon").attr("src","static/icons/machines/small/unknown-" + $("#metadata-wizard div#on-off").text() + '.png');
812
        $("#machinesview-icon").find("div#" + serverID).find("img.logo").attr("src", "static/icons/machines/medium/unknown-" + $("#metadata-wizard div#on-off").text() + '.png');
813
    }
814
    delete_metadata(serverID, keyValue);
815
});
816

817
//metadata edit button
818
$("#metadata-wizard .metadata-edit .edit").die('click');
819
$("#metadata-wizard .metadata-edit .edit").live('click', function() {
820
    $(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() +
821
                                    "\" / ><span class=\"oldValue\">" +
822
                                    $(this).parent().parent().find('.metadata-full-value').text() + "</span>");
823
    //submit keyword by pressing enter on the textbox
824
    $(this).parent().parent().find('input.metatextbox').keypress(function (e) {
825
        if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
826
            $(this).parent().parent().find('.editbuttons .save').click();
827
            return false;
828
        } else {
829
            return true;
830
        }
831
    });
832
    $(this).parent().parent().find('input.metatextbox').select()
833
    $(this).parent().hide();
834
    $(this).parent().parent().unbind('mouseenter').unbind('mouseleave');
835
    $(this).parent().parent().find('.editbuttons').show();
836
});
837

838
//capture Esc key
839
bar = {};
840
bar.onkeyup = function(e) {
841
    if (e.keyCode == 27) {
842
        //if we are inside an add or edit textbox, cancel editing
843
        if ($('input.metatextbox:focus').length > 0) {
844
            $('input.metatextbox:focus').parent().parent().find('.editbuttons .remove').click();
845
        } else if ($('input#add-meta-key:focus').length > 0)  {
846
            $('input#add-meta-key:focus').parent().parent().find('.addbuttons .cancel').click();
847
        } else if ($('input#add-meta-value:focus').length > 0) {
848
            $('input#add-meta-value:focus').parent().parent().find('.addbuttons .cancel').click();
849
        } else {
850
            //else close the metadata wizard
851
            $("a#metadata-scrollable").overlay().close();
852
        }
853
        e.preventDefault();
854
        e.stopPropagation();
855
    }
856
};
857
document.onkeyup = bar.onkeyup; 
858

859

860
//metadata cancel edit button
861
$("#metadata-wizard .editbuttons .remove").die('click');
862
$("#metadata-wizard .editbuttons .remove").live('click', function() {
863
    var oldValue = $(this).parent().parent().find('.oldValue').text();
864
    if (oldValue.length > 25) {
865
        oldValue = oldValue.substring(0,25) + "...";
866
    }
867
    $(this).parent().parent().find('div.metadata-value').html(oldValue);
868
    $(this).parent().parent().hover(function () {$(this).find('.metadata-edit').show();}, function () {$(this).find('.metadata-edit').hide();});
869
    $(this).parent().hide();
870
});
871

872

873
//metadata save edit button
874
$("#metadata-wizard .editbuttons .save").die('click');
875
$("#metadata-wizard .editbuttons .save").live('click', function() {
876
    newValue = $(this).parent().parent().find('input.metatextbox').val();
877
    keyValue = $(this).parent().parent().find('div.metadata-key').text();
878
    oldValue = $(this).parent().parent().find('.oldValue').text();
879
    if (!(newValue == oldValue)) {
880
        update_metadata(serverID, keyValue, newValue);
881
    }
882
    if (newValue.length > 25) {
883
        newValueSort = newValue.substring(0,25) + "...";
884
    } else {
885
        newValueSort = newValue
886
    }
887
    $(this).parent().parent().find('div.metadata-value').html(newValueSort);
888
    $(this).parent().parent().find('div.metadata-full-value').html(newValue);
889
    $(this).parent().parent().hover(function () {$(this).find('.metadata-edit').show();}, function () {$(this).find('.metadata-edit').hide();});
890
    $(this).parent().hide();
891

892
});
893

894
// intercept create metadata key focus
895
$("#metadata-wizard input#add-meta-key").live('focusin', function() {
896
    if ($(this).parent().hasClass("div-enabled")) {
897
    } else {
898
        $(this).parent().addClass("div-enabled");
899
        $(this).addClass("input-enabled");
900
        if (this.value == '{% trans 'max 15 characters' %}') {
901
            this.value = '';
902
        }
903
    }
904
    return false;
905
});
906

907
// intercept create metadata key focus out
908
$("#metadata-wizard input#add-meta-key").live('focusout', function() {
909
    $(this).parent().removeClass("div-enabled");
910
    if (this.value == "") {
911
        $(this).removeClass("input-enabled");
912
        this.value = '{% trans 'max 15 characters' %}';
913
    }
914
    return false;
915
});
916

917

918
// intercept metadata dropdown item click
919
$(".metadata-add-template li").live('click', function() {
920
    $(this).parent().parent().parent().find("input#add-meta-value").focus();
921
    $(this).parent().parent().parent().find("input#add-meta-key").addClass("input-enabled");
922
});
923

924
// intercept create metadata key focus
925
$("#metadata-wizard input#add-meta-value").live('focusin', function() {
926
    if ($(this).hasClass("input-enabled")) {
927
    } else {
928
        $(this).addClass("input-enabled");
929
        this.value = '';
930
    }
931
    return false;
932
});
933

934
// intercept create metadata key focus out
935
$("#metadata-wizard input#add-meta-value").live('focusout', function() {
936
    if (this.value == "") {
937
        $(this).removeClass("input-enabled");
938
        this.value = '{% trans 'max 150 characters' %}';
939
    }
940
    return false;
941
});
942

943
// intercept click on cancel button in metadata add dialog
944
$('#add-dialog button.cancel').live('click', function() {
945

946
});
947

948
// intercept click on save button in metadata add dialog
949
$('#add-dialog button.save').live('click', function() {
950
    // if both fields are filled in
951
    if ($('input.key').hasClass("input-enabled") && $('textarea.value').hasClass("input-enabled")) {
952
        // get the server id, meta key and meta value needed for the ajax call
953
        var serverID = $(this).parent().find('h3 p').text();
954
        var meta_key = $(this).parent().find('input.key').attr('value');
955
        var meta_value = $(this).parent().find('textarea.value')[0].value;
956
        // make the ajax call and list the new GET results
957
        add_metadata(serverID, meta_key, meta_value);
958
        // go to previous step
959
        $('#add-dialog button.prev').click();
960
    } else {
961
        // find which field is not filled in and focus there
962
        if (!$('input.key').hasClass("input-enabled")) {
963
            $('input.key').focus();
964
            $('input.key').focusin();
965
        } else {
966
            $('textarea.value').focus();
967
            $('textarea.value').focusin();
968
        }
969
    }
970
    return false;
971
});
972

973
// confirm all actions
974
$("#machines-pane div.confirm_multiple .yes").live('click', function(){
975
    while(pending_actions.length > 0){ // if there is a pending action for this server execute it
976
        action = pending_actions.pop(); // extract action
977
        var serverID = action[1];
978
        if ($.cookie("view") != '1') { // standard view
979
            $('#' + serverID + ' .selected').removeClass('selected');
980
            $('#' + serverID + ' .display').removeClass('display');
981
            if (action[0] == shutdown) {
982
                $('#' + serverID + ' .status').text(TRANSITIONS['Shutting down']);
983
            } else if (action[0] == start) {
984
                $('#' + serverID + ' .status').text(TRANSITIONS['Starting']);
985
            } else if (action[0] == reboot) {
986
                $('#' + serverID + ' .status').text(TRANSITIONS['Rebooting']);
987
            } else if (action[0] == destroy) {
988
                $('#' + serverID + ' .status').text(TRANSITIONS['Destroying']);
989
            }
990
            $('#' + serverID + ' .spinner').show();
991
        } else { // list view
992
            osIcon = $('#'+serverID).parent().parent().find('.list-logo');
993
            osIcon.attr('os',osIcon.attr('src'));
994
            osIcon.attr('src','static/icons/indicators/small/progress.gif');
995
            if (action[0] == shutdown) {
996
                $('#' + serverID).parent().parent().find('span.status').text(TRANSITIONS['Shutting down']);
997
            } else if (action[0] == start) {
998
                $('#' + serverID).parent().parent().find('span.status').text(TRANSITIONS['Starting']);
999
            } else if (action[0] == reboot) {
1000
                $('#' + serverID).parent().parent().find('span.status').text(TRANSITIONS['Rebooting']);
1001
            } else if (action[0] == destroy) {
1002
                $('#' + serverID).parent().parent().find('span.status').text(TRANSITIONS['Destroying']);
1003
            }
1004
        }
1005
        action[0]([serverID]); // execute action
1006
    }
1007
    update_confirmations();
1008
});
1009

1010
// cancel all actions
1011
$("#machines-pane div.confirm_multiple .no").live('click', function(){
1012
    pending_actions = [];
1013
    $('#machines-pane .machine .selected').removeClass('selected');
1014
    $('#machinesview-list .actions .selected').removeClass('selected');
1015
    $('#machines-pane .machine .display').removeClass('display');
1016
    update_confirmations();
1017
});
1018

1019
// basic functions executed on page load
1020
if (images.length > 0) {
1021
    // populate image list
1022
    update_wizard_images();
1023
}
1024
if (flavors.length > 0) {
1025
    // configure flavors
1026
    update_wizard_flavors();
1027
}
1028
// create tabs for main menu
1029
$("ul.tabs").tabs("div.panes ul");
1030

    
1031
</script>