spreadsheet directive

by jacobwsmith

HTML

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"></script>
<link rel="stylesheet" href="https://acadmin.vizu.com/admin/assets/lib/normalize.css/normalize.css">
<link rel="stylesheet" href="https://acadmin.vizu.com/admin/assets/css/_type.css">
<link rel="stylesheet" href="https://acadmin.vizu.com/admin/assets/css/_tables.css">
<link rel="stylesheet" href="https://acadmin.vizu.com/admin/assets/css/_forms.css">
<h1>Setting to Data Example</h1>

<div ng-controller="MyCtrl">
    <div class="scrollable">
        <table class="sheet header">
            <thead>
                <tr>
                    <th></th>
                    <th>Name1</th>
                    <th>Name2</th>
                    <th>Name3</th>
                </tr>
                <thead>
                    <tr ng-repeat="item in data">
                        <td>{{$index+1}}</td>
                        <td>
                            <edit-in-place value="item.id"></edit-in-place>
                        </td>
                        <td>
                            <edit-in-place value="item.friendlyName"></edit-in-place>
                        </td>
                        <td>
                            <edit-in-place value="item.groupName"></edit-in-place>
                        </td>
                    </tr>
                </thead>
            </thead>
        </table>
    </div>
    <table class="sheet footer">
        <tfoot>
            <tr>
                <td></td>
            </tr>
        </tfoot>
    </table>
</div>

CSS

.edit-in-place div {
    cursor: pointer;
}
/* Excel Like Spread Sheet Table*/
 table.sheet {
    border-top:1px solid #ccc;
    border-left:1px solid #ccc;
    width: 100%;
    margin: 0;
}
div.scrollable {
    border-right:1px solid #ccc;
    max-height: 305px;
    overflow-x:hidden;
    overflow-y: scroll;
    width:100%;
}
/*div.scrollable table.sheet {
    border-top: none;
}
table.sheet.header th  {
}

table.sheet.footer {

}
*/
 div.scrollable table {
    border-top: 1px solid transparent;
}
table.sheet th:nth-child(1), table.sheet td:nth-child(1) {
    text-align: center;
    width: 39px;
}
table.sheet th:nth-child(2), table.sheet td:nth-child(2) {
    width: 250px;
}
table.sheet th:nth-child(3), table.sheet td:nth-child(3) {
    width: auto;
}
table.sheet th:nth-child(4), table.sheet td:nth-child(4) {
    width: 250px;
}
table.sheet th:nth-child(5) {
    width: 81px;
}
table.sheet td:nth-child(5) {
    width: 65px;
}
table.sheet th, table.sheet td {
    border-bottom:none;
    border: 1px solid #ccc;
    box-sizing: border-box;
    empty-cells: show;
    line-height: 14px;
    padding: 0 0;
    vertical-align: middle;
}
table.sheet tbody tr td {
    min-height:28px;
    vertical-align: middle;
    position: relative;
    background-clip: padding-box;
}
table.sheet tbody tr:first-child td {
    border-top: none;
}
table.sheet tbody tr:last-child td {
    border-bottom: none;
}
table.sheet th {
    text-align: left;
    padding: 7px 5px;
}
table.sheet th, table.sheet tr td:first-child {
    background-color: #eee;
    color: #222;
    font-weight:bold;
    white-space: nowrap;
}
/* Delete Button */
 table.sheet tr th:last-child, table.sheet tr td:last-child {
    text-align: center;
    padding:4px 0;
}
/* Footer */
 table.sheet tfoot tr td {
    empty-cells: show;
    height:22px;
    vertical-align: top;
}
input[type="file"].file {
    display:none;
}
/* Input */
 table.sheet.body tbody tr td input[type="text"] {
    background: transparent;
    border:...

JavaScript

var app = angular.module('myApp', []);

function MyCtrl($scope) {

    var temp = [];
    for (var i = 0; i < 1000; i++) {
        temp.push({
            id: 'Moe',
            friendlyName: 'Curly',
            groupName: 'Larry'
        })
    }
    $scope.data = temp;
}

/////////////
app.directive('editInPlace', function () {
    return {
        restrict: 'E',
        scope: {
            value: '='
        },
        template: '<div ng-click="edit()" ng-show="!editing" ng-bind="value"></div><textarea ng-show="editing" ng-model="value" ng-blur="editing = false"></textarea>',
        link: function ($scope, element, attrs) {
            
            // Let's get a reference to the input element, as we'll want to reference it.
            var inputElement = angular.element(element.children()[1]);
            console.log(inputElement);

            // This directive should have a set class so we can style it.
            element.addClass('edit-in-place');

            // Initially, we're not editing.
            $scope.editing = false;

            // ng-click handler to activate edit-in-place
            $scope.edit = function () {
                $scope.editing = true;

                // We control display through a class on the directive itself. See the CSS.
                element.addClass('active');

                // And we must focus the element. 
                // `angular.element()` provides a chainable array, like jQuery so to access a native DOM function, 
                // we have to reference the first element in the array.
                inputElement[0].focus();
            };

            // When we leave the input, we're done editing.
            inputElement.prop('onblur', function () {
                $scope.editing = false;
                element.removeClass('active');
            });
        }
    };
});