Album edit interface

http://knockoutjs.com/examples/contactsEditor.html

by matmuchrapna

HTML

<script src="http://cloud.github.com/downloads/SteveSanderson/knockout/knockout-2.1.0.js"></script>
<script src="https://raw.github.com/SteveSanderson/knockout.mapping/master/build/output/knockout.mapping-latest.debug.js"></script>
<div class="figure">

    <div  class="g_top_normal_wrap js_album_edit_ui" >

        <form data-bind="foreach: albums, submit: save" class="form_album_edit_wrap" action="#" >
            <div class="form_album_edit_row form_album_edit_row_title">
                <label>
                    <div class="form_album_edit_label_wrap">
                        <span class="form_album_edit_label">Title</span>
                    </div>
                    <div class="form_album_edit_input_wrap">
                        <input data-bind='value: title' class="form_album_edit_input js_validate_required" name="title" type="text" />
                    </div>
                </label>
            </div>
            <div class="form_album_edit_row form_album_edit_row_genre">
                <div class="form_album_edit_label_wrap">
                    <span class="form_album_edit_label">Genres</span>
                </div>
                <div class="form_album_edit_input_wrap form_album_edit_input_wrap_tags clearfix">
                    <div data-bind="foreach: genres">
                        <span class="btn_wrap btn_wrap_deletable">
                            <a data-bind="text: title" class="btn_text js_auto_helper" data-type="artists" href="#">
                                
                            </a>
                            <a data-bind='click: $root.removeGenre' href="#" class="btn_del">+</a>
                        </span>
                    </div>
                    <span data-bind='click: $root.addGenre' class="btn_wrap" >
                        <a data-id="2" class="btn_text btn_text_add js_auto_helper" data-type="artists" href="#">
                            +
                        </a>
                    </span>
   ...

CSS

.g_top_normal_wrap {
    background: #F7F7F5;
    display: block;
    width: 908px;
    border-radius: 0 8px 8px 8px;
    padding: 30px;
}

.form_album_edit_wrap {
    width: 50%;
    /*padding: 25px 0;*/
}

.form_album_edit_row {
    padding-left: 115px;
    min-height: 26px;
}

.form_album_edit_row + .form_album_edit_row {
    margin-top: 10px;
}

.form_album_edit_label_wrap {
    width: 115px;
    margin-left: -115px;
    float: left;
    text-align: right;
}

.form_album_edit_label,
.form_album_edit_input {
    font-size: 12px;
    line-height: 2;
    color: #333;
    font-family: Helvetica, sans-serif;
}

.form_album_edit_row.invalid .form_album_edit_label {
    color: red
}

.form_album_edit_row.invalid .form_album_edit_input {
    border-color: red;
}


.form_album_edit_label {
    display: inline-block;
    height: 26px;
    cursor: pointer;
    padding-right: 10px;
}

.form_album_edit_input {
    height: 24px;
    line-height: 24px;
    background: #f7f7f7;
    position: relative;
    bottom: -1px;
    width: 100%;
    padding: 0 10px;


    -webkit-box-shadow: 0 2px 5px #e5e5e5 inset;
            box-shadow: 0 2px 5px #e5e5e5 inset;
    -webkit-box-sizing: border-box;
       -moz-box-sizing: border-box;
            box-sizing: border-box;
}

.form_album_edit_input_small {
    width: 150px;

}

.form_album_edit_textarea {
    min-height: 114px;
    resize: vertical;
}

.form_album_edit_input,
.form_album_edit_input:active,
.form_album_edit_input:focus {
    border: 1px solid #e3e3e3;
}


.form_album_edit_art_input {
    display: none;
}

.form_album_edit_art_wrap {
    padding: 9px;
    width: 135px;
    background: #ecf3f5;
    cursor: pointer;
    text-align: right;

    -webkit-border-radius: 8px;
            border-radius: 8px;
    -webkit-box-shadow: 0 8px 13px #e2e9eb inset;
            box-shadow: 0 8px 13px #e2e9eb inset;
}

.form_album_edit_art_wrap,
.form_album_edit_art_img_wrap {
    width: 135px;
}

.form_album_edit_art_img {
    width:...

JavaScript

// http://knockoutjs.com/documentation/click-binding.html
// RID OF METHOD DUPLICATES

//js 
    //js 
    var initialData = [
        {
        id: 101,
        image: 'http://placekitten.com/140/140',
        date: '10.10.2525',
        title: 'Danny',
        artists: [
            {
            id: 11,
            title: 'Timati'},
        {
            id: 12,
            title: 'Busta Rhymes'}],
        genres: [
            {
            id: 21,
            title: 'Noise'},
        {
            id: 22,
            title: 'EBM'}],
        composers: [
            {
            id: 31,
            title: 'Bach'},
        {
            id: 32,
            title: 'Mozart'}],
        lyricists: [
            {
            id: 41,
            title: 'Andre Montagar'},
        {
            id: 42,
            title: 'Zbignev Zapert'}],
        explicit: 'true',
        tracks: [
            {
            id: 101,
            title: 'Unforgiven',
            artists: [
                {
                id: 11,
                title: 'Timati'},
            {
                id: 12,
                title: 'Busta Rhymes'}],
            genres: [
                {
                id: 21,
                title: 'Noise'},
            {
                id: 22,
                title: 'EBM'}],
            composers: [
                {
                id: 31,
                title: 'Bach'},
            {
                id: 32,
                title: 'Mozart'}],
            lyricists: [
                {
                id: 41,
                title: 'Andre Montagar'},
            {
                id: 42,
                title: 'Zbignev Zapert'}],
            lyrics: 'text text'},
        {
            id: 102,
            title: 'Pony',
            artists: [
                {
                id: 11,
                title: 'Timati'},
            {
                id: 12,
                title: 'Busta Rhymes'}],
            genres: [
                {
               ...