HEX
Server: Microsoft-IIS/8.5
System: Windows NT YDAWBH120 6.3 build 9600 (Windows Server 2012 R2 Standard Edition) AMD64
User: tentjecom_web (0)
PHP: 7.4.14
Disabled: NONE
Upload Files
File: D:/HostingSpaces/SBogers27/dndin.nl/wwwroot/js/kms/core.js
'use strict';
//inject directives and services.


var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

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

app.controller('fileUploadController', ['$scope', 'Upload', '$timeout', function ($scope, Upload, $timeout) {
    console.log('fileuploadcontroller loading');

    //The files list
    //Todo, extend with the files form the database
    $scope.files = [];
    //These are the fileIds, used for saving

    $scope.dynamic = false;

    $scope.uploadSizes = '';

    $scope.maxImages;

    $scope.errorMsg = {};

    $scope.subFolder = false;

    $scope.attributeKey = '';

    $scope.forModel;
    $scope.forModelId;

    $scope.canUploadNewImage;

    /**
     * This function uploads the new files
     * @param files
     * @param errFiles
     * @param maximages
     * @param blockId
     * @param tabId optional
     */
    $scope.uploadFiles = function (files, errFiles, maximages, blockId, tabId) {
        console.log("upload for block with blockId: " + blockId + " and tabKey: " + tabId);
        console.log("uploadedFiles files:");
        console.log(files);

        //Get the model and the id where we are uploading images for. Should flow via a service but due to bad design and an upcoming newer angular version does not. todo: improve me
        var htmlElement = document.querySelector("[ng-controller=KmsAttributeDynamicController]");
        $scope.forModel = htmlElement.dataset.forModel;
        $scope.forModelId = htmlElement.dataset.forModelId;
        console.log("fileUploadController uploading files For model: " + $scope.forModel + " with id: " + $scope.forModelId + " and blockId: " + blockId);

        if (typeof $scope.files == 'undefined') $scope.files = [];
        if ($scope.files.length >= maximages) {
            console.log("File upload not allowed. " + $scope.files.length + "/" + maximages + " uploaded");
            return false;
        }
        //Set the files
        $scope.errFiles = errFiles;

        //Foreach each file
        angular.forEach(files, function (file) {

            //Push to true adds image at the back, false at the front
            var push = true;

            //Add the placeholder
            var loadingImage = { loading: true, thumb_image_url: '/images/kms/loading.gif' };

            if (push == true) {
                $scope.files.push(loadingImage);
                var imageKey = $scope.files.length - 1;
            } else {
                //Add at the front
                $scope.files.unshift(loadingImage);
                var imageKey = 0;
            }

            //Upload to the server
            file.upload = Upload.upload({
                url: '/kms/upload',
                data: {
                    //Sent the data and the options
                    file: file,
                    uploadSizes: $scope.uploadSizes,
                    dynamic: $scope.dynamic,
                    subFolder: $scope.subFolder,
                    attribute_key: $scope.attributeKey,
                    forModelName: $scope.forModel,
                    forModelId: $scope.forModelId,
                    forBlockId: blockId,
                    forTabId: tabId
                }
            });
            //After uploading
            file.upload.then(function (response) {
                $timeout(function () {
                    // delete $scope.files.loading
                    console.log(response);

                    //Set the response data

                    // file.result = response.data;
                    // file.result = response.data.uploaded[0];

                    // console.log("Thumb: "+response.data.uploaded.[0].thumb);
                    console.log("Image Id: " + response.data.uploaded[0].id);

                    //Add the file to the current files
                    $scope.files[imageKey] = response.data.uploaded[0];

                    console.log("$scope.files[" + imageKey + "] =");
                    console.log($scope.files[imageKey]);

                    //Reverse push
                    //Add the file to the current files
                    // $scope.files.unshift(file.result);
                    // $scope.setFileIds()

                    //Update fileids
                    var forBlockId = response.data.uploaded[0].forBlockId;

                    var blocksDataObject = $scope.getBlocksData(); //Defined in the KmsAttributeDynamicController

                    for (var key in blocksDataObject) {
                        console.log("Looping over blocks to find a block with id: " + forBlockId + ". Current block id: " + blocksDataObject[key].blockId);
                        // console.log(blocksDataObject[key]);

                        if (blocksDataObject.hasOwnProperty(key) === false || blocksDataObject[key].hasOwnProperty("blockId") === false) {
                            console.warn("Detected block data without a block id. Because of this, it is not possible to upload a file for that block. This does not mean that the uploaded image can be linked to the block your uploading currently for");
                            continue;
                        }

                        if (blocksDataObject[key].blockId == forBlockId) {
                            console.log("found block with id: " + forBlockId);

                            var data = [];
                            if (response.data.uploaded[0].forTabId) {
                                console.log("Uploaded an image for tab: " + response.data.uploaded[0].forTabId);
                                data = response.data.uploaded[0].id + "#" + response.data.uploaded[0].forTabId; //imageid#multipleimagesslot
                            } else {
                                console.log("Uploaded an image without tab: " + response.data.uploaded[0].id);
                                data = response.data.uploaded[0].id;
                            }

                            var fileIds = [];
                            if (blocksDataObject[key].hasOwnProperty('fileIds')) {
                                var length = blocksDataObject[key]['fileIds'].length;

                                //Determine if it is a single image or multiple images.
                                blocksDataObject[key]['fileIds'][length] = data;
                                console.log("Updating fileIds with image id: " + data);
                            } else {
                                console.log("Setting fileIds to a new array with image id: " + data);
                                blocksDataObject[key].fileIds = [data];
                            }

                            console.log("files.length = " + blocksDataObject[key].fileIds.length + " maxImages = " + $scope.maxImages);
                            $scope.canUploadNewImage = blocksDataObject[key].fileIds.length < $scope.maxImages;
                        }

                        $scope.setBlocksData(blocksDataObject);
                    }
                });
            }, function (response) {
                if (response.status > 0) $scope.errorMsg = response.status + ': ' + response.data;
                console.error("Error: " + $scope.errorMsg);
            }, function (evt) {
                file.progress = Math.min(100, parseInt(100.0 * evt.loaded / evt.total));
            });
        });
    };

    $scope.deleteImage = function (index, blockId, tab_key) {
        var idToDelete = $scope.files[index].id;
        console.log("idToDelete: " + idToDelete + " from blockId: " + blockId);

        //Delete the image
        $scope.files.splice(index, 1);
        console.log("Current image amount: " + $scope.files.length);

        //Delete the image id
        // $scope.setFileIds()

        var blocksDataObject = $scope.getBlocksData(); //Defined in the KmsAttributeDynamicController

        for (var blockIndex in blocksDataObject) {
            if (blocksDataObject.hasOwnProperty(blockIndex) === false || blocksDataObject[blockIndex].hasOwnProperty("blockId") === false) {
                console.warn("Detected block data without a block id. Because of this, it is not possible to upload a file for that block. This does not mean that the uploaded image can be linked to the block your uploading currently for");
                continue;
            }

            if (blocksDataObject[blockIndex].blockId == blockId) {
                console.log("found block with id: " + blockId);

                if (blocksDataObject[blockIndex].hasOwnProperty('fileIdsToDelete') === false) blocksDataObject[blockIndex].fileIdsToDelete = [];

                console.log("Current files to delete: " + blocksDataObject[blockIndex].fileIdsToDelete);
                idToDelete = typeof tab_key !== 'undefined' ? idToDelete + "#" + tab_key : idToDelete;

                for (var index in blocksDataObject[blockIndex].fileIds) {
                    var currentId = blocksDataObject[blockIndex].fileIds[index];
                    if (typeof tab_key !== 'undefined') {
                        console.log("Looping over the file ids to find an image with id: " + idToDelete + " for tab: " + tab_key + " (" + currentId + ")");
                    } else {
                        console.log("Looping over the file ids to find an image with id: " + idToDelete);
                    }

                    if (currentId == idToDelete) {
                        console.log("Image marked to delete on save: " + idToDelete);
                        blocksDataObject[blockIndex].fileIdsToDelete[blocksDataObject[blockIndex].fileIdsToDelete.length] = idToDelete;

                        blocksDataObject[blockIndex].fileIds.splice(index, 1);

                        if (typeof tab_key === 'undefined') {
                            $scope.canUploadNewImage = blocksDataObject[blockIndex].fileIds.length < $scope.maxImages;
                        } else {
                            var count = 0;
                            for (var index in blocksDataObject[blockIndex].fileIds) {
                                if (blocksDataObject[blockIndex].fileIds[index].split("#")[1] == tab_key) {
                                    count++;
                                }
                            }

                            $scope.canUploadNewImage = count < $scope.maxImages;
                        }
                        break;
                    }
                }
            }
        }

        $scope.setBlocksData(blocksDataObject);

        delete $scope.errorMsg.toMany;
    };

    // $scope.moveImage = function (index, direction) {
    //     var currentFile = $scope.files[index]
    //     var currentFileId = $scope.fileIds[index]
    //
    //     if (direction == 'left') {
    //         $scope.files[index] = $scope.files[index - 1];
    //         $scope.files[index - 1] = currentFile;
    //     } else {
    //         $scope.files[index] = $scope.files[index + 1];
    //         $scope.files[index + 1] = currentFile;
    //     }
    //     $scope.setFileIds()
    // };

    $scope.initFiles = function (files, maxImages, tab_key) {
        console.log("fileupload:initFiles: " + files + " maxImages: " + maxImages);

        if (files) {
            // //Strip out the image ids that do not belong to the tab we are processing for
            var filesToUse = [];
            if (typeof tab_key !== 'undefined') {
                for (var index in files) {
                    var split = files[index].split("#");
                    if (split.length !== 2) continue; //The imageId did not contain a #

                    if (split[1] != tab_key) {
                        console.log("fileupload:initFiles: Ignoring image with id: " + split[0] + " because it belongs to tab " + split[1] + " and we are processing images for tab " + tab_key);
                    } else {
                        filesToUse[filesToUse.length] = files[index];
                    }
                }
            } else {
                filesToUse = files;
            }

            if (filesToUse.length > 0) {
                $.ajax({
                    type: "POST",
                    url: "/kms/getimagedata",
                    data: {
                        fileIds: filesToUse
                    },
                    success: function success(response) {
                        console.log("Retrieved files: ");
                        console.log(response);

                        // files must look like this files[index].id files[index].sizes
                        $scope.files = response;

                        // $scope.setFileIds();
                        if (typeof maxImages != 'undefined') {
                            $scope.maxImages = maxImages;
                        }

                        console.log("files.length < $scope.maxImages: " + filesToUse.length < $scope.maxImages);
                        $scope.canUploadNewImage = filesToUse.length < $scope.maxImages;

                        $scope.$apply();
                    },
                    error: function error() {
                        console.log("An error occured while retrieving image(s)");
                    },
                    headers: {
                        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
                    },
                    dataType: 'json'
                });
            } else {
                $scope.maxImages = maxImages;
                $scope.canUploadNewImage = true;
                $scope.files = [];
            }
        } else {
            $scope.maxImages = maxImages;
            $scope.canUploadNewImage = true;
            $scope.files = [];
        }
    };

    $scope.updateFiles = function (files) {
        console.log("Updated files");
        $scope.files = files;
    };

    // $scope.setFileIds = function () {
    //     var local_fileIds = [];
    //
    //     angular.forEach($scope.files, function (file) {
    //         local_fileIds.push(file.id);
    //     });
    //
    //     console.log("set file ids ($scope.fileIds):");
    //     console.log(local_fileIds);
    //     $scope.fileIds = local_fileIds
    // };


    // $scope.getFileCount = function () {
    //     return $scope.fileIds.length;
    // };

    $scope.sortableOptions = {
        update: function update(e, ui) {
            ui.item.sortable.cancel();
            var originalIndex = ui.item.sortable.index;
            var newIndex = ui.item.sortable.dropindex;

            var oldImage = $scope.files[originalIndex];
            $scope.files[originalIndex] = $scope.files[newIndex];
            $scope.files[newIndex] = oldImage;
            $scope.setFileIds();
        }

    };

    console.log('fileuploadcontroller initialized');
}]);
'use strict';

angular.element(document).ready(function () {
    // angular.element(document.querySelector('[ng-controller]')).scope().debug();
    // //console.log('page loading completed');
});

angular.module('kms.dynamic-attribute', []).controller('KmsAttributeDynamicController', function ($scope, $element, $compile, $timeout) {
    //console.log('KmsAttributeDynamicController initializing');

    // var htmlElement = document.querySelector("[ng-controller=KmsAttributeDynamicController]");
    //console.log("Controller element");
    //console.log($($element)[0]);
    var htmlElement = $($element)[0];

    //For which model and id of the model the dynamic attribute works
    $scope.forModel = htmlElement.dataset.forModel;
    $scope.forModelId = htmlElement.dataset.forModelId;
    //console.log("KmsAttributeDynamicController further initializing For model: "+$scope.forModel+" with id: "+$scope.forModelId);

    $scope.key = htmlElement.dataset.key;
    //console.log("Controller key: "+$scope.key);

    var removeBlocks = function removeBlocks() {
        // Remove the block list for re-render
        angular.element('#' + $scope.key + '_blocks .inner').remove();
    };

    // Check if any blocks exists to prevent JSON.parse error
    // Default is an empty array
    $scope.blocks = [];

    var html = $('#' + $scope.key + '_data', $element).html();
    //console.log("JSON to parse (in element: #"+$scope.key+"_data): "+html);
    if (html != '' && html != '""' && html != undefined) {
        $scope.blocks = JSON.parse(html);
    } else {}
    //console.log("Element called: " + "#" + $scope.key + "_data does not have json data set");


    //console.log('scope blocks');
    //console.log($scope.blocks);

    $scope.blockSettings = {};
    var blockSettingsElement = document.getElementById('blockSettings');
    if (blockSettingsElement) {
        var block_settings = blockSettingsElement.value;
        if (block_settings != '' && block_settings != '""') {
            $scope.blockSettings = JSON.parse(block_settings);
        }
    } else {}
    //console.log("No blocksettings element");


    //console.log("blocksettings");
    //console.log($scope.blockSettings);

    $scope.blockTypes = getBlockTypes($scope.blockSettings);

    $scope.addBlock = function (blockType) {
        if (!angular.isUndefined(blockType)) {
            $scope.blocks.push(angular.copy(blockType));
        }
    };

    $scope.removeBlock = function (block) {
        startToMove();
        var index = $scope.blocks.indexOf(block);
        $scope.blocks.splice(index, 1);
        stopToMove();
    };

    $scope.upBlock = function (block) {
        //load index from the block
        var index = $scope.blocks.indexOf(block);
        //if the index is 0 return
        if (index < 1) return;

        //Remove the editor
        startToMove();

        //Set the block index-1 to current index
        $scope.blocks[index] = $scope.blocks[index - 1];
        //set the triggerd block to index-1
        $scope.blocks[index - 1] = block;

        //enable the editor
        stopToMove();
    };

    $scope.downBlock = function (block) {
        //load the index from the block
        var index = $scope.blocks.indexOf(block);
        //If the block is the last return false
        if (index >= $scope.blocks.length - 1) return;

        //Remove the editor
        startToMove();

        //set the block +1 to the current index
        $scope.blocks[index] = $scope.blocks[index + 1];
        //set the triggerd block to index +1
        $scope.blocks[index + 1] = block;

        //enable the editor
        stopToMove();
    };

    $scope.deleteImage = function (direction, block_key, image_key, tab_key) {
        if (tab_key == null) {
            $scope.blocks[block_key].images.splice(image_key, 1);
        } else {
            $scope.blocks[block_key].tab[tab_key].images.splice(image_key, 1);
        }
    };

    $scope.deleteFile = function (block_key) {
        delete $scope.blocks[block_key].file;
    };

    $scope.changeOrder = function (direction, block_key, image_key, tab_key) {
        //load the index from the block
        var index = image_key;
        if (tab_key == null) {

            var temp_image = $scope.blocks[block_key].images[image_key];

            switch (direction) {
                case 'left':
                    if (index == 0) return;
                    $scope.blocks[block_key].images[image_key] = $scope.blocks[block_key].images[image_key - 1];
                    $scope.blocks[block_key].images[image_key - 1] = temp_image;
                    break;
                case 'right':
                    if (index + 1 == $scope.blocks[block_key].images.length) return;
                    $scope.blocks[block_key].images[image_key] = $scope.blocks[block_key].images[image_key + 1];
                    $scope.blocks[block_key].images[image_key + 1] = temp_image;
                    break;
            }
        } else {

            var temp_image = $scope.blocks[block_key].tab[tab_key].images[image_key];

            switch (direction) {
                case 'left':
                    if (index == 0) return;
                    $scope.blocks[block_key].tab[tab_key].images[image_key] = $scope.blocks[block_key].tab[tab_key].images[image_key - 1];
                    $scope.blocks[block_key].tab[tab_key].images[image_key - 1] = temp_image;
                    break;
                case 'right':
                    if (index + 1 == $scope.blocks[block_key].tab[tab_key].images.length) return;
                    $scope.blocks[block_key].tab[tab_key].images[image_key] = $scope.blocks[block_key].tab[tab_key].images[image_key + 1];
                    $scope.blocks[block_key].tab[tab_key].images[image_key + 1] = temp_image;
                    break;
            }
        }
    };

    /**
     * Add new image tab
     * @param block_index
     */
    $scope.addImageTab = function (block_index) {
        $scope.blocks[block_index].tab.push({ title: '' });

        var new_index = $scope.blocks[block_index].tab.length;

        //set the new tab as active (-1) arrays start at 0
        $scope.setActiveTab(block_index, new_index - 1);
    };

    /**
     * Remove image tab
     * @param block_index
     */
    $scope.removeImageTab = function (block_index, tab_index) {
        $scope.blocks[block_index].tab.splice(tab_index, 1);

        //set the active tab to 0
        $scope.setActiveTab(block_index, 0);
    };

    $scope.setActiveTab = function (index, tab) {
        $scope.blocks[index].active_tab = tab;
    };
    $scope.moveTab = function (direction, index, tab_index) {

        var temptab = $scope.blocks[index].tab[tab_index];
        switch (direction) {
            case 'left':
                if (tab_index == 0) return;
                $scope.blocks[index].tab[tab_index] = $scope.blocks[index].tab[tab_index - 1];
                $scope.blocks[index].tab[tab_index - 1] = temptab;
                break;
            case 'right':
                if (tab_index + 1 == $scope.blocks[index].tab.length) return;
                $scope.blocks[index].tab[tab_index] = $scope.blocks[index].tab[tab_index + 1];
                $scope.blocks[index].tab[tab_index + 1] = temptab;
                break;
        }
    };

    $scope.setUniqueId = function (block_index) {
        if (typeof $scope.blocks[block_index].blockId == 'undefined') {
            var stamp = new Date().valueOf();
            $scope.blocks[block_index].blockId = Math.round(stamp + Math.random() * 1000);
        }
    };

    $scope.debug = function () {
        //console.log('key: ' + $scope.key);
    };

    //console.log('KmsAttributeDynamicController initialized');
}).directive('block', function ($compile) {
    return {
        restrict: 'E',
        template: '<div class="header">' + '<div class="start">' + '<div class="block-title">{{block.typeName}}</div>' + '<div class="buttons">' + '<div class="position-button up" ng-click="upBlock(block)"></div>' + '<div class="position-button down" ng-click="downBlock(block)"></div>' + '</div></div>' + '<div class="end">' + '<div class="btn btn-danger btn-trash" ng-click="removeBlock(block)">&nbsp</div>' + '</div></div>',

        link: function link(scope, element, attr) {
            switch (scope.block.typeSlug) {
                case 'content-block':
                    // //console.log('rendering a content block with this data: '+scope.block);
                    scope.imageBoxId = scope.key + '-image-box-' + scope.$index;
                    scope.textBoxId = scope.key + '-text-box-' + scope.$index;
                    //console.log("Rendering content-block (afbeelding en tekst)");
                    //console.log(scope.block);
                    element.append($compile("<content-block></content-block>")(scope));
                    break;
                case 'view-block':
                    element.append($compile("<view-block></view-block>")(scope));
                    break;
                case 'page-link-block':
                    element.append($compile("<page-link-block></page-link-block>")(scope));
                    break;
                case 'image-slider-block':
                    element.append($compile("<image-slider-block></image-slider-block>")(scope));
                    break;
                case 'video-block':
                    element.append($compile("<video-block></video-block>")(scope));
                    break;
                case 'file-block':
                    element.append($compile("<file-block></file-block>")(scope));
                    break;
                case 'two-column-block':
                    scope.textBoxIds = [];
                    scope.textBoxIds.left = scope.key + '-text-box-' + scope.$index + '-left';
                    scope.textBoxIds.right = scope.key + '-text-box-' + scope.$index + '-right';
                    element.append($compile("<two-column-block></two-column-block>")(scope));
                    break;
                case 'full-text-block':
                    scope.textBoxId = scope.key + '-text-box-' + scope.$index;
                    element.append($compile("<full-text-block></full-text-block>")(scope));
                    break;
                case 'full-image-block':
                    element.append($compile("<full-image-block></full-image-block>")(scope));
                    break;
                case 'multiple-images-block':
                    element.append($compile("<multiple-images-block></multiple-images-block>")(scope));
                    break;
            }

            // //console.log("block data element: "+attr.dataElement);
            scope.dataElement = document.querySelector(attr.dataElement);
            scope.getBlocksData = function () {
                return JSON.parse(scope.dataElement.getAttribute("value"));
            };

            scope.setBlocksData = function (data) {
                scope.dataElement.setAttribute("value", JSON.stringify(data));
                scope.$parent.blocks = data;
            };
        }
    };
}).directive('contentBlock', function ($timeout) {
    var count = 0;
    return {
        restrict: 'E',
        templateUrl: '/kms/api/template/dynamic-page-content-block',
        link: function link(scope, element, attrs) {
            scope.image = 'imageHolder';
            scope.loopCount = count;
            count++;
            scope.loopCount = scope.key;
            // //console.log("getting content block data");
            // //console.log(scope.getBlocksData();

            //initiate the tinyMce editor
            initiateTinyMceWithDelay(scope, $timeout, 100);

            scope.openBox = function (imageBoxId) {
                $.colorbox({
                    href: '/kms/elfinder/standalonepopup/' + imageBoxId,
                    fastIframe: true,
                    iframe: true,
                    width: '70%',
                    height: '520px'
                });
            };
        }
    };
}).directive('viewBlock', function ($timeout) {
    var count = 0;
    return {
        restrict: 'E',
        templateUrl: '/kms/api/template/dynamic-view',
        link: function link(scope) {}
    };
}).directive('twoColumnBlock', function ($timeout) {
    var count = 0;
    return {
        restrict: 'E',
        templateUrl: '/kms/api/template/two-column-block',
        link: function link(scope, element, attrs) {
            scope.image = 'imageHolder', scope.loopCount = count;
            count++;
            scope.loopCount = scope.key;

            //initiate the tinyMce editor
            initiateTinyMceWithDelay(scope, $timeout, 100);

            scope.openBox = function (imageBoxId) {
                $.colorbox({
                    href: '/kms/elfinder/standalonepopup/' + imageBoxId,
                    fastIframe: true,
                    iframe: true,
                    width: '70%',
                    height: '520px'
                });
            };
        }
    };
}).directive('imageSliderBlock', function () {

    return {
        restrict: 'E',
        templateUrl: '/kms/api/template/dynamic-image-slider-block',
        link: function link(node) {
            ////console.log(node);
        }
    };
}).directive('fullImageBlock', function () {

    return {
        restrict: 'E',
        templateUrl: '/kms/api/template/dynamic-full-image-block',
        link: function link(node) {
            ////console.log(node);
        }
    };
}).directive('fullTextBlock', function ($timeout) {

    return {
        restrict: 'E',
        templateUrl: '/kms/api/template/dynamic-full-text-block',
        link: function link(scope) {

            //initiate the tinyMce editor
            initiateTinyMceWithDelay(scope, $timeout, 100);
        }
    };
}).directive('multipleImagesBlock', function () {
    return {
        restrict: 'E',
        templateUrl: '/kms/api/template/dynamic-multiple-images-block',
        link: function link(node) {
            ////console.log(node);
        }
    };
}).directive('pageLinkBlock', function ($http) {
    return {
        restrict: 'E',
        templateUrl: '/kms/api/template/dynamic-page-link-block',
        link: function link(scope, element, attr) {
            scope.pages = [];
            $http.get('/kms/api/pages').then(function (response) {
                // Adopt data
                var pages = [];
                var getChildren = function getChildren(node) {
                    for (var child in node) {
                        if (node[child].title) {
                            pages.push({
                                value: node[child].id,
                                label: node[child].title
                            });
                        }
                        getChildren(node[child].children);
                    }
                };
                getChildren(response.data);
                // Set the data
                scope.pages = pages;
            });
        }
    };
}).directive('videoBlock', function () {
    return {
        restrict: 'E',
        templateUrl: '/kms/api/template/dynamic-video-block',
        link: function link(node) {
            ////console.log(node);
        }
    };
}).directive('fileBlock', function () {
    return {
        restrict: 'E',
        templateUrl: '/kms/api/template/dynamic-file-block',
        link: function link(node) {
            ////console.log(node);
        }
    };
});

/**
 * Callback function for ElFinder (hard to implement in angular?)
 *
 * @param filePath
 * @param requestingElementId
 */
function processSelectedFile(filePath, requestingElementId) {
    // Get the scope of the the element that is passed into ElFinder
    var elementScope = $('#' + requestingElementId).parent().parent().scope();
    elementScope.block.image = filePath;
    elementScope.$apply();
}

/**
 * This function will initiate the tinyMce editor on an block
 * It the initiation will be delayed because of the angular
 *
 * @param $scope
 * @param $timeout
 */

function initiateTinyMceWithDelay($scope, $timeout, delay) {
    //if (tinymce) tinymce.remove();
    $timeout(function () {
        initiateTinyMce($scope, $scope.textBoxId);
        if (typeof $scope.textBoxIds !== 'undefined') {
            if ($scope.textBoxIds.left != null) initiateTinyMce($scope, $scope.textBoxIds.left, 'description', 'left');
            if ($scope.textBoxIds.right != null) initiateTinyMce($scope, $scope.textBoxIds.right, 'description', 'right');
        }
    }, delay);
}

function initiateTinyMce($scope, field, blockElement, blockSubElement) {
    if (typeof field === 'undefined') {
        field = $scope.textboxId;
    }
    if (typeof blockElement === 'undefined') {
        blockElement = 'description';
    }

    //textboxIds[] =
    tinymce.init({
        elements: field,
        mode: 'exact',
        skin: 'kms',
        menubar: false,
        statusbar: false,
        plugins: ['code', 'paste', 'link', 'table'],
        toolbar: 'styleselect | bold italic underline | bullist numlist  | indent | link | code',
        height: '200',
        default_link_target: "_blank",
        paste_as_text: true,
        style_formats: [{ title: 'Titel 1', block: 'h1' }, { title: 'Titel 2', block: 'h2' }, { title: 'Titel 3', block: 'h3' }, { title: 'Titel 4', block: 'h4' }],
        convert_urls: false,
        // link_list: "/kms/file-list?key=komma_kms",
        setup: function setup(editor) {
            editor.on('change', function (e) {
                editor.save();
                if (typeof blockSubElement === 'undefined') {
                    $scope.block[blockElement] = editor.getContent();
                } else {
                    $scope.block[blockElement][blockSubElement] = editor.getContent();
                }

                if (!$scope.$$phase) {
                    $scope.$apply();
                }
            });
            // Update model on keypress
            editor.on('KeyUp', function (e) {
                editor.save();
                if (typeof blockSubElement === 'undefined') {
                    $scope.block[blockElement] = editor.getContent();
                } else {
                    $scope.block[blockElement][blockSubElement] = editor.getContent();
                }

                if (!$scope.$$phase) {
                    $scope.$apply();
                }
            });
        }
    });
}

function startToMove() {
    $(document).find('textarea').each(function () {
        tinyMCE.execCommand('mceFocus', false, $(this).attr('id'));
        tinyMCE.execCommand('mceRemoveEditor', false, $(this).attr('id'));
    });
}

function stopToMove() {
    //todo: Reanbling ONLY works after a timeout.
    setTimeout(function () {
        $(document).find('textarea').each(function () {
            tinymce.execCommand('mceAddEditor', true, $(this).attr('id'));
        });
    }, 100);
}

function getBlockTypes(blockSettings) {

    var blocks = {
        two_column_block: {
            typeSlug: 'two-column-block',
            code_name: '',
            view: '',
            typeName: 'Twee tekstkolommen',
            status: true,
            description: { left: '', right: '' },
            textWidth: '50'
        },
        content_block: {
            typeSlug: 'content-block',
            code_name: '',
            view: '',
            typeName: 'Afbeelding en tekst',
            status: true,
            location: 'left',
            textWidth: '66',
            description: '',
            subFolder: 'dynamic',
            image: null,
            max_images: 4,
            link: '',
            link_text: 'Lees meer'
        },
        view_block: {
            typeSlug: 'view-block',
            code_name: '',
            view: '',
            typeName: 'View',
            status: true
        },
        full_image_block: {
            typeSlug: 'full-image-block',
            code_name: '',
            view: '',
            typeName: '100% Afbeelding',
            subFolder: 'dynamic',
            max_images: 2,
            status: true,
            image: null
        },
        full_text_block: {
            typeSlug: 'full-text-block',
            code_name: '',
            view: '',
            typeName: 'Een tekstkolom',
            description: '',
            status: true,
            link: '',
            link_text: 'Lees meer'
        },
        multiple_images_block: {
            typeSlug: 'multiple-images-block',
            code_name: '',
            view: '',
            typeName: 'Meerdere afbeeldingen',
            tab: [{
                title: 'Afbeelding 1', max_images: 1 }, {
                title: 'Afbeelding 2a',
                max_images: 2
            }, {
                title: 'Afbeelding 2b (optioneel)',
                max_images: 1 }],
            status: true,
            location: 'left',
            subFolder: 'dynamic',
            textWidth: '66'
        },
        page_link_block: {
            typeSlug: 'page-link-block',
            code_name: '',
            view: '',
            typeName: 'Page-link block',
            link_text: 'Lees meer',
            special: 0,
            status: true,
            pageId: null
        },
        image_slider_block: {
            typeSlug: 'image-slider-block',
            code_name: '',
            view: '',
            typeName: 'Image gallery',
            tab: [{ title: '' }],
            subFolder: 'dynamic',
            status: true,
            pageId: null
        },
        video_block: {
            typeSlug: 'video-block',
            code_name: '',
            view: '',
            typeName: 'Video',
            youtube: '',
            status: true,
            pageId: null
        },
        file_block: {
            typeSlug: 'file-block',
            code_name: '',
            view: '',
            typeName: 'Bestand block',
            title: '',
            special: 0,
            download_text: 'Download',
            file: '',
            status: true,
            pageId: null
        }
    };

    var blockTypes = {};

    angular.forEach(blockSettings, function (block, blockName) {
        blockTypes[blockName] = angular.merge(blocks[blockName], block);
    });

    return blockTypes;
}

'use strict';
var attributes = {};

var app = angular.module('kms', ['ui.bootstrap', 'ngSanitize', 'kms.dynamic-attribute', 'fileUpload'

// 'ui.select',
// 'ui.date',
// 'ui.tree',
// 'ui.sortable',

// 'ui.utils.masks',

]);

app.controller('KmsEntities', ['$scope', '$element', function ($scope, $element) {

    $scope.entities = [];
    $scope.paginatedEntities = [];

    $scope.isSorting = false;

    $scope.isSearching = function () {
        return $scope.searchEntitiesText.text.length > 1;
    };

    $scope.currentPage = 1;
    $scope.numPerPage = 5;
    $scope.maxSize = 5;

    var entityList = $('.entities-list-items .entities-list-item', $element);
    for (var i = 0; i < entityList.length; i++) {
        var dataElement = entityList[i];
        var dataObject = {
            thumbHtml: $('.entities-item-pre', dataElement).html(),
            text: $('.entities-item-text', dataElement).html(),
            status: $('.entities-item-status', dataElement).html(),
            link: $('a', dataElement).first().attr('href'),
            active: $(dataElement).hasClass('active')
        };
        $scope.entities.push(dataObject);
    }

    $scope.activateSorting = function () {
        $scope.isSorting = true;
    };

    $scope.deactivateSorting = function () {
        $scope.isSorting = false;
    };

    $scope.$watch("currentPage + numPerPage", function () {
        var begin = ($scope.currentPage - 1) * $scope.numPerPage,
            end = begin + $scope.numPerPage;

        $scope.paginatedEntities = $scope.entities.slice(begin, end);
    });
}]);

app.controller('KmsEntity', ['$scope', '$element', function ($scope, $element) {
    // console.log("attaching save to scope");
    $scope.save = function () {
        var button = document.querySelector('input[value="submit-cloaked"]');
        // console.log(button);
        button.click();
    };
}]);

app.controller('SortableTree', ['$scope', '$http', '$attrs', function ($scope, $http, $attrs) {

    $http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";

    $scope.data = [];

    $scope.treeOptions = {
        dropped: function dropped(event) {
            $http({
                method: 'POST',
                url: '/kms/api/' + $attrs.siteslug + '/' + $attrs.slug,
                data: { "tree": angular.toJson($scope.data) }
            }).then(function (response) {});
        }
    };

    $scope.openLink = function (id) {
        window.location = $scope.url + '/' + id;
    };

    $scope.toggle = function (scope) {
        scope.toggle();
    };

    var getRootNodesScope = function getRootNodesScope() {
        return angular.element(document.getElementById('tree-root').scope());
    };

    $scope.collapseAll = function () {
        var scope = getRootNodesScope();
        scope.collapseAll();
    };

    $scope.expandAll = function () {
        var scope = getRootNodesScope();
        scope.expandAll();
    };

    // console.log('/kms/api/' + $attrs.siteslug + '/' + $attrs.slug);
    $http.get('/kms/api/' + $attrs.siteslug + '/' + $attrs.slug).then(function (response) {
        // console.log("Kms.js SortableTree controller got data from '"+'/kms/api/' + $attrs.siteslug + '/' + $attrs.slug+"':");
        // console.log(angular.toJson(response.data));
        $scope.data = response.data[0]['children'];
    });
}]);

app.controller('KmsAttributes', ['$scope', function ($scope) {
    $scope.attributes = attributes;

    // console.log("$scope.attributes (via KmsAttributes)");
    // console.log($scope.attributes);

    // $scope.createModelString = function (modelKey, $itemKey) {
    //
    //
    //     //Check if the modelKey is an array structure (field_name[x])
    //     var match = modelKey.match(/(.*)\[(.*)]/)
    //
    //     //There is no match, so a basic key
    //     if (match == null) {
    //         //SEt the modelKey as modelString
    //         $scope.modelString = modelKey
    //         //ItemKy is null
    //         $scope.itemKey = null;
    //         //return and exit
    //         return $scope.modelString
    //     }
    //
    //     //Set the match[2] as the itemKey
    //     var itemCounter = match[2];
    //
    //     //If the itemKey is not undefined and itemkey is the string itemKey
    //     if (typeof($itemKey) != "undefined" && match[2] == 'itemKey') {
    //         //Set the $itemKey to the scope itemKey
    //         itemCounter = $itemKey
    //     }
    //     //Glue the parts together
    //     var modelString = match[1] + '_' + itemCounter
    //
    //     //Set to the global modelString
    //     $scope.modelString = modelString;
    //     $scope.itemCounter = itemCounter;
    //
    //     //Return the string
    //     return modelString
    // }

    /**
     * Wrapper for Json.parse()
     * So i can parse Json in blade
     * @param value
     */
    $scope.parse = function (value) {
        //If there is no value return;
        if (!value) {
            console.log("Parse without a value");
            return;
        }
        //If it is already an object, return the value
        if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) == 'object') {
            console.log("Parse value: " + value);
            return value;
        }

        //Parse the string to a Json object
        console.log("Parse string to Json: " + JSON.parse(value));
        return JSON.parse(value);
    };

    $scope.convertToSlug = function (str) {
        str = str.replace(/^\s+|\s+$/g, ''); // trim
        str = str.toLowerCase();

        // remove accents, swap ñ for n, etc
        var from = "ãàáäâẽèéëêìíïîõòóöôùúüûñç·/_,:;";
        var to = "aaaaaeeeeeiiiiooooouuuunc------";
        for (var i = 0, l = from.length; i < l; i++) {
            str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i));
        }

        str = str.replace(/[^a-z0-9 -]/g, '') // remove invalid chars
        .replace(/\s+/g, '-') // collapse whitespace and replace by -
        .replace(/-+/g, '-'); // collapse dashes

        return str;
    };
}]);
app.controller('KmsAttributeTextFieldController', ['$scope', '$element', function ($scope, $element) {

    $scope.attributes = attributes;
}]);

app.controller('KmsAttributePasswordController', ['$scope', '$element', function ($scope, $element) {
    $scope.attributes = attributes;

    //Set enabler true (show enable bottom)
    $scope.enabler = true;
    //Change the password field to a hidden field
    $('.passwordField', $element).attr('type', 'hidden');

    //Method called when clikced on the enable button
    $scope.enablePasswordField = function () {
        //Change the type of the password field to password
        $('.passwordField', $element).attr('type', 'password');
        //Disable the enable buttom
        $scope.enabler = false;
    };
}]);

app.controller('KmsAttributeDateController', ['$scope', '$element', function ($scope, $element) {
    $scope.attributes = attributes;

    $('input[ui-date]', $element).datepicker({
        changeYear: true,
        changeMonth: true,
        firstDay: 1,
        dateFormat: 'dd-mm-yy'
    });
}]);

app.controller('KmsAttributeCurrencyFieldController', ['$scope', '$element', '$locale', function ($scope, $element, $locale) {
    $scope.attributes = attributes;

    $scope.initCurrencyField = function (dec_value, currency) {

        if (typeof currency !== 'undefined') {
            //Set currencySymbol
            $locale.NUMBER_FORMATS.CURRENCY_SYM = currency;
        }

        //Set the value an de dec_value
        attributes[$scope.modelString] = { "value": dec_value / 100, "dec_value": dec_value };

        $scope.$watch('attributes.' + $scope.modelString + '.value', function (newValue, oldValue) {
            if (newValue === oldValue) return;

            attributes[$scope.modelString].dec_value = newValue * 100;
        });
    };
}]);

app.controller('KmsAttributePercentageFieldController', ['$scope', '$element', '$timeout', function ($scope, $element, $timeout) {
    $scope.attributes = attributes;
}]);

app.controller('KmsAttributeTextFieldCurrencyController', ['$scope', '$element', '$timeout', function ($scope, $element, $timeout) {

    $scope.attributes = attributes;
    var id = $('input', $element).attr('id'); // get the id of the hidden field

    var taxSelectFieldId = $('[data-kms-tax-field]', $element).attr('data-kms-tax-field');
    var taxFieldId = id + '_tax';
    var noTaxFieldId = id + '_no_tax';
    var parseCurrencyStringToCents = function parseCurrencyStringToCents(currencyString) {

        var val = currencyString.toString();
        val = val.replace(/[.]/g, '');
        val = val.replace(/[,]/g, '.');
        val = val.replace(/[^0-9\.]+/g, '');
        val = val * 100;
        return val;
    };

    var addTax = function addTax(value) {
        if (attributes[taxSelectFieldId].selected) {
            var factor = 1 + attributes[taxSelectFieldId].selected.fullValue.rate / 100;
            return value * factor;
        }
    };
    var subtractTax = function subtractTax(value) {
        if (attributes[taxSelectFieldId].selected) {
            var factor = 1 + attributes[taxSelectFieldId].selected.fullValue.rate / 100;
            return value / factor;
        }
    };
    $scope.$watch('attributes.' + taxFieldId, function (newValue, oldValue) {
        if (newValue !== oldValue) {
            $scope.attributes[id] = parseCurrencyStringToCents(newValue);
        }
    });

    $scope.$watch('attributes.' + noTaxFieldId, function (newValue, oldValue) {
        if (newValue !== oldValue) {
            $scope.attributes[id] = Math.round(addTax(parseCurrencyStringToCents(newValue)));
        }
    });

    var watcherMain = function watcherMain(newValue, oldVal) {
        if ($.isNumeric($scope.attributes[id])) {
            var $taxField = $('#' + taxFieldId);
            var $noTaxField = $('#' + noTaxFieldId);
            if (!$taxField.is(':focus')) {
                $taxField.val($scope.attributes[id] / 100);
            }
            if (!$noTaxField.is(':focus')) {
                $noTaxField.val(Math.round(subtractTax($scope.attributes[id])) / 100);
            }
        }
    };

    // Clear fields on blur if no value
    $('#' + taxFieldId + ', #' + noTaxFieldId).blur(function (e) {
        if ($scope.attributes[id] == 0) {
            $('#' + taxFieldId + ', #' + noTaxFieldId).val(0);
        }
    });

    $scope.$watch('attributes.' + id, watcherMain);
    $scope.$watch('attributes.' + taxSelectFieldId + '.selected', watcherMain);
    $scope.attributes[id] = $('input', $element).attr('value'); // get the value of the hidden field
    $timeout(watcherMain, 500);
}]);

app.controller('KmsAttributeMultiSelectController', ['$scope', '$element', function ($scope, $element) {

    $scope.attributes = attributes;
    $scope.selectData = [];

    /**
     * Initialize the choices for ui-select
     *
     * @param choices | string
     * @returns {*}
     */
    $scope.initChoices = function (choices) {
        //If there are no choices;
        if (!choices) return;

        //If it is not already an object, make one from json
        if ((typeof choices === 'undefined' ? 'undefined' : _typeof(choices)) != 'object') choices = JSON.parse(choices);

        //Set the choices to the selectData
        $scope.selectData = choices;
        return choices;
    };

    $scope.setValue = function (values) {

        if (!values) return;
        // compare "values" array and "$scope.selectData" array
        var result = [];
        for (var i = 0; i < $scope.selectData.length; i++) {
            var valueInElement = false;
            for (var j = 0; j < values.length; j++) {
                if ($scope.selectData[i].value == values[j]) {
                    valueInElement = true;
                    break;
                }
            }
            if (valueInElement) result.push($scope.selectData[i]);
        }

        // $scope.attributes[id] = angular.toJson(values);
        // $scope.attributes[id + '_select'] = result;
        return result;
    };
}]);

app.controller('KmsAttributeSlugController', ['$scope', '$element', function ($scope, $element) {
    $scope.attributes = attributes;

    //Get the slugField key
    var slugField = $('[data-kms-slug-field]', $element).attr('data-kms-slug-field');
    //Change [[itemCounter]] with the $scope.itemCounter (fieldGroup)
    slugField = slugField.replace('[[itemCounter]]', $scope.itemCounter);

    //Watch the slugField
    $scope.$watch('attributes.' + slugField, function (newValue, oldValue) {
        //When nothing changes, do nothing
        if (newValue === oldValue) return;
        //Set the string converted to Slug to the field
        attributes[$scope.modelString] = $scope.convertToSlug(attributes[slugField]);
    });
}]);

app.controller('KmsAttributeFieldGroupController', ['$scope', '$element', function ($scope, $element) {
    $scope.number = 0;
    $scope.itemKey = 1;
    $scope.maxFieldGroups = null;

    $scope.getNumber = function () {
        return new Array($scope.number);
    };

    $scope.addRow = function () {

        if ($scope.itemKey >= $scope.maxFieldGroups) return;
        //Add one to the itemKey
        $scope.itemKey++;
        //Addd one to the numbers
        $scope.number++;
    };
    /**
     * Initialize the given values
     * @param itemKey | Amount (-1) of  items fieldGroups
     * @param maxFieldGroups | max fieldgroups
     */
    $scope.init = function (itemKey, maxFieldGroups) {

        //Items in the fieldGroup
        $scope.itemKey = itemKey;
        //Max items in fieldGroup
        $scope.maxFieldGroups = maxFieldGroups;
        //If it is a new, add a row
        if (itemKey == 0) $scope.addRow();
    };
}]);

app.controller('KmsAttributeRouteController', ['$scope', '$element', function ($scope, $element) {

    $scope.attributes = attributes;

    var id = $('input', $element).attr('id');
    attributes[id] = $('input', $element).attr('value');

    //Get the name of the slugField
    var slugField = $('[data-kms-slug-field]', $element).attr('data-kms-slug-field');
    //Change [[itemCounter]] with the $scope.itemCounter (fieldGroup)
    slugField = slugField.replace('[[itemCounter]]', $scope.itemCounter);
    //Get the name of the parentField
    var parentField = $('[data-kms-parent-field]', $element).attr('data-kms-parent-field');

    //Set the languageId
    var languageId = $('[data-kms-language-id]', $element).attr('data-kms-language-id');
    //Set the structure
    var structure = $('[data-kms-structure]', $element).attr('data-kms-structure');

    /**
     * This function generates the correct Route
     * when a watched field is changed
     *
     * @param newValue
     * @param oldValue
     */
    var parseStructure = function parseStructure(newValue, oldValue) {
        //If the value is the same, stop and return
        if (newValue === oldValue) return;

        //Create an empty parentSlug string
        var parentSlug = '';

        // todo: make this work
        //Check if the parentField exist in then attributes
        if (attributes[parentField]) {
            //Check if the parentField has an selected.routes object
            if (!attributes[parentField].selected.routes) {
                //If not trow an error
                console.error('Routes are not set in the ' + parentField + 'field');
            }
            //Set the routes for the current language to parentSlug
            parentSlug = attributes[parentField].selected.routes[languageId];
        }

        //Create newRoute
        var newRoute = '';

        //Replace {{parentSlugs}} with the parentSlug
        newRoute = structure.replace('{{parentSlugs}}', parentSlug);
        //Replace {{slug}} with the Slug
        newRoute = newRoute.replace('{{slug}}', $scope.convertToSlug(newValue));

        //Set the new route to the attribute of the current $scope.modelString
        attributes[$scope.modelString] = newRoute;
    };

    //Set a watch on the slugField, and execute the parseStructure method on a change
    $scope.$watch('attributes.' + slugField, parseStructure);
    //If there is an parentField
    if (attributes[parentField]) {
        //Set a watch on the parentField, and execute the parseStructure method on a change
        $scope.$watch('attributes.' + parentField + '.selected', parseStructure);
    }
}]);

app.controller('KmsAttributeSorterController', ['$scope', '$element', function ($scope, $element) {
    $scope.attributes = attributes;
}]);

app.filter("multiWordFilter", ['$filter', function ($filter) {
    console.log('hoi');
    return function (inputArray, searchText) {
        var wordArray = searchText ? searchText.toLowerCase().split(/\s+/) : [];
        var wordCount = wordArray.length;
        for (var i = 0; i < wordCount; i++) {
            // Hack for filtering on text parameter: {text:wordArray[i]}
            inputArray = $filter('filter')(inputArray, { text: wordArray[i] });
        }
        return inputArray;
    };
}]);

app.filter('valuesToArrayFilter', function () {
    return function (input) {

        if (!input) return;

        var output = input.map(function (a) {
            return a.value;
        });

        return output;
    };
});

/**
 * AngularJS default filter with the following expression:
 * "person in people | filter: {name: $select.search, age: $select.search}"
 * performs a AND between 'name: $select.search' and 'age: $select.search'.
 * We want to perform a OR.
 */
app.filter('propsFilter', function () {
    return function (items, props) {
        var out = [];

        if (angular.isArray(items)) {
            items.forEach(function (item) {
                var itemMatches = false;

                var keys = Object.keys(props);
                for (var i = 0; i < keys.length; i++) {
                    var prop = keys[i];
                    var text = props[prop].toLowerCase();
                    if (item[prop].toString().toLowerCase().indexOf(text) !== -1) {
                        itemMatches = true;
                        break;
                    }
                }

                if (itemMatches) {
                    out.push(item);
                }
            });
        } else {
            // Let the output be the input untouched
            out = items;
        }
        return out;
    };
});

var IsJsonString = function IsJsonString(str) {
    try {
        JSON.parse(str);
    } catch (e) {
        return false;
    }
    return true;
};

$(function () {

    var activeListItem = $('#sidebar .navigation li.active');
    var activeListItemParents = activeListItem.parents();
    var activeListItemParentsLength = activeListItemParents.length;

    for (var i = 0; i <= activeListItemParentsLength; i++) {
        var node = activeListItemParents[i];
        if (node && node.tagName == 'LI' && node.classList.contains('has-sub-items')) {
            node.classList.add('active');
        }
    }

    var siteListItems = document.querySelectorAll('#sidebar .navigation .has-sub-items');
    var siteListItemsLength = siteListItems.length;
    for (var i = 0; i < siteListItemsLength; i++) {
        var siteListItem = siteListItems[i].querySelector('span');

        siteListItem.addEventListener('click', function () {
            this.parentNode.classList.toggle('active');
        });
    }
});
(function ($) {

    // TinyMCE
    tinymce.init({
        selector: 'textarea.tiny-mce',
        skin: 'kms',
        menubar: false,
        statusbar: false,
        plugins: ['code', 'paste', 'link'],
        toolbar: 'styleselect | bold italic underline | bullist numlist  | indent | link image | code',
        height: '200',
        paste_as_text: true,
        style_formats: [{ title: 'Titel 1', block: 'h1' }, { title: 'Titel 2', block: 'h2' }, { title: 'Titel 3', block: 'h3' }, { title: 'Titel 4', block: 'h4' }],
        convert_urls: false
        // link_list: "/kms/file-list?key=komma_kms",
    });

    // Hierarchical list
    $('.entities-list-item .dropdown-icon').click(function (e) {
        e.preventDefault();
        if ($(this).parent().parent().hasClass('open')) {
            //$('.animate-to-triangle', this)[0].beginElement();
            $(this).parent().parent().removeClass('open');
        } else {
            //$('.animate-to-minus', this)[0].beginElement();
            $(this).parent().parent().addClass('open');
        }
    });

    var toggled = true;

    // Scroll to active item in list
    $(window).load(function () {

        if ($('#entity-form .lock').hasClass('open')) {
            toggled = false;
            $('#entity-form').find('input, textarea').attr('disabled', toggled);
        }

        var $container = $('#entities .entities-list');
        var $activeListItem = $('.entities-list-item.active', $container).first();
        if ($activeListItem.length == 0) return;
        var top = $activeListItem.position().top;
        $container.scrollTop(top);

        $('.site-brand-name input').attr('placeholder', $('#global_name').val());
    });

    $('#global_name').change(function () {
        $('.site-brand-name input').attr('placeholder', $(this).val());
    });

    //error accordian
    $('.error-accordion .collapsible-ul').hide();
    $('.error-accordion h3').click(function () {
        $(this).parent().find('.collapsible-ul').toggle();
    });

    //$('.order-status.selectize').selectize();


    // Product category selector

    //$('#productCategorySelector').selectize();

    //$('#selectYearAndMonthForm select').selectize();

    $('#selectYearAndMonthForm select').change(function () {
        var location = '/kms/orders/voltooid?month=' + $('#selectYearAndMonthForm select#orderMonthSelector').val() + '&year=' + $('#selectYearAndMonthForm select#orderYearSelector').val();
        window.location = location;
    });

    $('#productCategorySelector').change(function () {
        window.location = '/kms/products?category=' + encodeURIComponent(this.value);
    });

    // Flash messages
    var hideFlashMessage = function hideFlashMessage() {
        $('#flash-message').fadeOut();
    };
    $('#flash-message').click(function () {
        hideFlashMessage();
    });
    setTimeout(function () {
        hideFlashMessage();
    }, 5000);

    //var toggled = true;
    $('#entity-form .lock').click(function () {
        $(this).toggleClass('open');
        toggled = !toggled;
        $(this).parents('#entity-form').find('input, textarea').attr('disabled', toggled);
    });

    /* grab important elements */
    var sortInput = jQuery('#sort_order');
    var submit = jQuery('#autoSubmit');
    var messageBox = jQuery('#message-box');
    var list = jQuery('.fieldGroupItems');
    /* create requesting function to avoid duplicate code */

    /* worker function */
    var fnSubmit = function fnSubmit(save) {
        var sortOrder = [];
        list.children('li').each(function () {
            sortOrder.push(jQuery(this).data('id'));
        });
        sortInput.val(sortOrder.join(','));
        console.log(sortInput.val());
        if (save) {
            request();
        }
    };
    /* store values */
    list.children('li').each(function () {
        var li = jQuery(this);
        li.data('id', li.attr('title')).attr('title', '');
    });
    /* sortables */
    list.sortable({
        opacity: 0.7,
        update: function update() {}
    });

    /* ajax form submission */
    jQuery('#dd-form').bind('submit', function (e) {
        if (e) e.preventDefault();
        fnSubmit(true);
    });
})(jQuery);

/**
 * Fills an ul element with data retrieved from an api and makes the items searchable.
 /* The data to and from the api has this structure for example.
 *
 * [
 *  {
 *      id:1
 *      title:false
 *      thumbnail:false
 *      status: "active"
 *      routes: []
 *      children: [
 *          {
 *              id: 12
 *              title: "Thuis"
 *              thumbnail: false
 *              routes: [{
 *                  40: "en/Homenew",
 *                  104: "nl/Thuisnew"
 *              }]
 *          }
 *      ]
 *  }
 * ]
 */

var SearchController = function () {
    function SearchController(sectionId, selector, inputSelector, mainUlId, resultCounterId) {
        _classCallCheck(this, SearchController);

        this.apiUrl = '';
        this.data = '';
        this.dataToLoad = '';
        this.editEntitiesUrl = '';
        this.initialized = false;
        this.sectionId = sectionId;
        this.selector = selector;
        this.mainUlId = mainUlId;
        this.resultCounterId = resultCounterId;
        this.disabled = true;
        this.inputSelector = inputSelector;

        this.listItemClass = 'entities-list-item';

        //The class that is added to li items that must be visible because they match (a part) of the search value).
        //This is also the class applied to the rootUl if any results are found.
        this.visibleClass = 'active';
        this.invisibleClass = 'hide';

        this.section = document.getElementById(this.sectionId);
        var rootUl = document.querySelector(this.selector);

        this.siteSlug = rootUl.dataset.siteSlug;
        this.slug = rootUl.dataset.slug;
        this.activeId = rootUl.dataset.activeId;
    }

    /**
     * Initializes the controller so that it knows where it can get its data from,
     * where it needs to direct users when they click on an item and from which ul it
     * should create a sortable ul
     *
     * @param dataSource A string|Object
     * @param editEntitiesUrl A string
     *
     * In case of the data source being an object it must look like this:
     * {
     *  data: [{
     *      id: null,
     *      routes: []
     *      status: "",
     *      title: "",
     *      children: [
     *          {
     *              id: "2",
     *              routes: []
     *              status: "",
     *              title: "My username"
     *              children: []
     *          }
     *      ]
     *  }]
     * }
     */


    _createClass(SearchController, [{
        key: 'init',
        value: function init(dataSource, editEntitiesUrl) {
            if (typeof dataSource === "string") {
                this.apiUrl = dataSource;
            } else {
                this.dataToLoad = dataSource;
            }
            this.editEntitiesUrl = editEntitiesUrl;

            this.initialized = true;
        }

        /**
         * Returns a promise that resolves with the root ul that then will contain the items retrieved from the api
         */

    }, {
        key: 'load',
        value: function load() {
            if (this.initialized === false) {
                console.error('Please initialize the controller with the init method first.');return;
            }

            var self = this;

            return new Promise(function (resolve, reject) {
                if (self.initialized === false) {
                    reject('Please initialize the controller with the init method first.');
                }

                if (self.apiUrl !== '' && self.dataToLoad === '') {
                    axios.get(self.apiUrl).then(function (response) {
                        if (!response.data) {
                            reject('The sortable did not get any data from the api');
                            return;
                        }
                        // console.log(response);

                        /** @var Array[] menuItemArrays*/
                        response.data[0].children.forEach(function (itemObject) {
                            /** @var array htmlElements **/
                            var htmlElements = self.createHtmlElement(itemObject);

                            htmlElements.forEach(function (element) {
                                document.querySelector(self.selector).append(element);
                            });
                        });

                        // console.log(document.querySelector(self.selector));

                        self.initializeSearch();

                        resolve(document.querySelector(self.selector));
                    }).catch(function (error) {
                        reject(error);
                    });
                } else if (self.apiUrl === '' && self.dataToLoad !== '') {
                    // console.log('data children');
                    // console.log(self.dataToLoad.data[0].children);

                    self.dataToLoad.data[0].children.forEach(function (itemObject) {
                        var htmlElements = self.createHtmlElement(itemObject);

                        htmlElements.forEach(function (element) {
                            document.querySelector(self.selector).append(element);
                        });
                    });

                    self.initializeSearch();

                    resolve(document.querySelector(self.selector));
                }
            });
        }

        /**
         * Initialize search functionality on the ul this searchable does its job for
         */

    }, {
        key: 'initializeSearch',
        value: function initializeSearch() {
            var _this = this;

            var section = this.section;
            var input = document.querySelector(this.inputSelector);
            var searchUl = document.querySelector(this.selector);
            var resultCounter = document.getElementById(this.resultCounterId);

            //handles searching
            input.addEventListener('keyup', function (event) {
                var mainUl = document.getElementById(_this.mainUlId);

                var resultsCount = 0;

                var filterValue = input.value.toLowerCase();

                var noSearchValue = filterValue == '' ? true : false;

                var listItems = searchUl.querySelectorAll('li');

                var listItemsCount = listItems.length;

                // console.log(listItemsCount);
                for (var i = 0; i < listItemsCount; i++) {
                    var itemValue = listItems[i].dataset.title.toLowerCase();

                    if (itemValue.indexOf(filterValue) > -1 && noSearchValue === false) {
                        //item found
                        resultsCount++;
                        listItems[i].classList.add(_this.visibleClass);
                    } else {
                        //item not found
                        listItems[i].classList.remove(_this.visibleClass);
                    }
                }

                if (resultsCount > 0) {
                    // searchUl.parentNode.classList.add(this.visibleClass);
                    // mainUl.classList.add(this.invisibleClass);
                } else {
                        // searchUl.parentNode.classList.remove(this.visibleClass);
                        // mainUl.classList.remove(this.invisibleClass);
                    }

                resultCounter.innerHTML = resultsCount + "";

                if (!noSearchValue) {
                    section.classList.add(_this.visibleClass);
                    mainUl.classList.add(_this.invisibleClass);
                } else {
                    section.classList.remove(_this.visibleClass);
                    mainUl.classList.remove(_this.invisibleClass);
                }
            });

            searchUl.classList.remove(this.visibleClass);
        }

        /**
         * Creates a menu item (HTMLElement) and sub menu items if necessary
         *
         * @param data
         * @param items array Used internally. Humans must not touch this
         * @param currentTreeLevel string Used internally. Humans must not touch this
         * @returns {Array}
         */

    }, {
        key: 'createHtmlElement',
        value: function createHtmlElement(data) {
            var items = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
            var currentTreeLevel = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';

            if (this.initialized === false) {
                console.error('Please initialize the controller with the init method first.');return;
            }

            var self = this;
            var activeId = self.activeId;
            var id = data.id;
            var title = data.title;
            var children = data.children;
            var status = data.status;
            var thumbnail = data.thumbnail;

            var breadcrumb = currentTreeLevel;
            var treeBreadcrumb = currentTreeLevel !== "" ? currentTreeLevel + " | " + title : title;
            // console.log(breadcrumb);

            // console.log(data);

            //Render all child html items first
            var childItems = [];
            var _iteratorNormalCompletion = true;
            var _didIteratorError = false;
            var _iteratorError = undefined;

            try {
                for (var _iterator = children[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
                    var object = _step.value;

                    childItems.push(this.createHtmlElement(object, items, treeBreadcrumb));
                }

                //Displays a red or green line in front of the item depending on if the status (class) is active or not
            } catch (err) {
                _didIteratorError = true;
                _iteratorError = err;
            } finally {
                try {
                    if (!_iteratorNormalCompletion && _iterator.return) {
                        _iterator.return();
                    }
                } finally {
                    if (_didIteratorError) {
                        throw _iteratorError;
                    }
                }
            }

            var colorStatusHtml = '\n            <span class="color-status" data-status-type="' + status + '">\n                &nbsp;\n            </span>\n        ';

            //Displays the items icon thumbnail OR the first character of its title
            var iconHtml = '\n            <div class="icon" ' + (thumbnail ? 'style="background-image: url(\'' + thumbnail + '\');"' : '') + ' >\n                ' + (thumbnail ? '' : '<span>' + (title ? title.substring(0, 1) : '') + '</span>') + '\n            </div>\n        ';

            //The main item html that has all other items
            var listIem = '\n            <li data-title="' + title + '" class="' + this.listItemClass + ' ' + (id == activeId ? 'active' : '') + '"> \n                <a href="' + this.editEntitiesUrl + '/' + id + '">\n                    ' + colorStatusHtml + '\n                    ' + iconHtml + '\n                    <p data-breadcrumb="' + breadcrumb + '">' + title + '</p>\n                </a>\n            </li> \n        ';

            //Render it to a real html element
            var domParser = new DOMParser();
            var document = domParser.parseFromString(listIem, "text/html");

            items.push(document.body.firstChild);
            // console.log('rendered item: ');
            // console.log(items);

            //And then add the children inside
            if (childItems.length > 0) {
                // console.log('adding rendered childitems');
                childItems.forEach(function (element) {
                    items.push(element[0]);
                });
            }
            // console.log('items result:');
            // console.log(items);

            //and return it
            return items;
        }
    }]);

    return SearchController;
}();
/**
 * Fills an ul element with data retrieved from an api and makes the items draggable so that you can sort them.
 * Also updates the api with the new positions of the items. The data to and from the api has this structure for example.
 *
 * [
 *  {
 *      id:1
 *      title:false
 *      thumbnail:false
 *      status: "active"
 *      routes: []
 *      children: [
 *          {
 *              id: 12
 *              title: "Thuis"
 *              thumbnail: false
 *              routes: [{
 *                  40: "en/Homenew",
 *                  104: "nl/Thuisnew"
 *              }]
 *          }
 *      ]
 *  }
 * ]
 */


var SortableController = function () {
    function SortableController(selector) {
        _classCallCheck(this, SortableController);

        this.apiUrl = '';
        this.editEntitiesUrl = '';
        this.initialized = false;
        this.selector = selector;
        this.disabled = true;

        this.listItemClass = 'entities-list-item';

        var rootUl = document.querySelector(this.selector);
        this.siteSlug = rootUl.dataset.siteSlug;
        this.slug = rootUl.dataset.slug;
        this.activeId = rootUl.dataset.activeId;
    }

    /**
     * Initializes the controller so that it knows where it can get its data from,
     * where it needs to direct users when they click on an item and from which ul it
     * should create a sortable ul
     *
     * @param apiUrl A string
     * @param editEntitiesUrl A string
     */


    _createClass(SortableController, [{
        key: 'init',
        value: function init(apiUrl, editEntitiesUrl) {
            this.apiUrl = apiUrl;
            this.editEntitiesUrl = editEntitiesUrl;

            var itemsThatHaveSubUl = document.querySelectorAll(this.selector + " li ul");
            itemsThatHaveSubUl.forEach(function (node, index) {
                // console.log('clicked ul');
                node.style.display = node.style.display !== 'none' ? 'none' : '';
            });

            this.initialized = true;
        }
    }, {
        key: 'updateSortableJavascript',
        value: function updateSortableJavascript() {
            // console.log("Updating all sortable elements with these selectors: '" + this.selector+" .sortable' AND '"+this.selector+"'");

            $('.sortable').sortable({
                connectWith: ".sortable",
                placeholder: "sortable-placeholder",
                disabled: this.disabled
            });

            var itemsThatHaveSubUl = document.querySelectorAll(this.selector + " li ul");
            itemsThatHaveSubUl.forEach(function (node, index) {
                // console.log('clicked ul');
                // node.style.display = node.style.display !== 'none' ? 'none' : '';
            });
        }

        /**
         * Makes the rootUl sortable
         */

    }, {
        key: 'enableSortable',
        value: function enableSortable() {
            if (this.initialized === false) {
                console.error('Please initialize the controller with the init method first.');return;
            }

            this.disabled = false;
            $(this.selector).sortable({
                disabled: this.disabled
            }).addClass('sorting');

            this.updateSortableJavascript();
        }

        /**
         * Diables the rootUl so that it cannot be sorted
         */

    }, {
        key: 'disableSortable',
        value: function disableSortable() {
            // if (this.initialized === false) { console.error('Please initialize the controller with the init method first.'); return; }

            this.disabled = true;
            $(this.selector).sortable({
                disabled: this.disabled
            }).removeClass('sorting');

            this.save();
        }

        /**
         * Saves the item data to the api
         */

    }, {
        key: 'save',
        value: function save() {
            if (this.initialized === false) {
                console.error('Please initialize the controller with the init method first.');return;
            }
            var itemsJson = this.itemsToJson(document.querySelector(this.selector));

            itemsJson = JSON.stringify(itemsJson);
            var apiJson = {
                "tree": itemsJson
            };

            axios.post(this.apiUrl, apiJson).then(function (response) {
                // console.log('Successfully stored the sort order to the api: ');
                // console.log(response);
            }).catch(function (error) {
                // console.error('Could not save sortable sort order to api because an error occured: ');
                console.error(error);
            });
        }

        /**
         * Converts the rootUl back to json for saving it
         *
         * @param htmlElement HTMLElement Root ul
         * @return null|[] if something went wrong null, or an array containing json items if successfull.
         */

    }, {
        key: 'itemsToJson',
        value: function itemsToJson(htmlElement) {
            if (this.initialized === false) {
                console.error('Please initialize the controller with the init method first.');return;
            }

            var jsonArray = [];
            var error = false;

            //find all child li items
            var listItems = htmlElement.querySelectorAll(':scope > li.' + this.listItemClass);
            var _iteratorNormalCompletion2 = true;
            var _didIteratorError2 = false;
            var _iteratorError2 = undefined;

            try {
                for (var _iterator2 = listItems[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
                    var listItem = _step2.value;

                    var elementJson = listItem.dataset.json;
                    if (!elementJson) {
                        console.error('One or more li HTMLElements with class "' + this.listItemClass + '" did not have data-json attribute set while it should.');
                        error = true;
                    }

                    var currentItemJson = JSON.parse(listItem.dataset.json);
                    var childUl = listItem.querySelector('ul');
                    if (childUl) {
                        currentItemJson.children = this.itemsToJson(childUl);
                        if (!currentItemJson.children) error = true;
                    } else {
                        currentItemJson.children = [];
                    }

                    jsonArray.push(currentItemJson);
                }
            } catch (err) {
                _didIteratorError2 = true;
                _iteratorError2 = err;
            } finally {
                try {
                    if (!_iteratorNormalCompletion2 && _iterator2.return) {
                        _iterator2.return();
                    }
                } finally {
                    if (_didIteratorError2) {
                        throw _iteratorError2;
                    }
                }
            }

            if (error) return null;

            return jsonArray;
        }

        /**
         * Returns a promise that resolves with the root ul that then will contain the items retrieved from the api
         */

    }, {
        key: 'load',
        value: function load() {
            if (this.initialized === false) {
                console.error('Please initialize the controller with the init method first.');return;
            }

            self = this;

            return new Promise(function (resolve, reject) {
                if (self.initialized === false) {
                    reject('Please initialize the controller with the init method first.');
                }

                axios.get(self.apiUrl).then(function (response) {
                    if (!response.data) {
                        reject('The sortable did not get any data from the api');
                        return;
                    }

                    /** @var HTMLElement[] menuItems*/
                    var menuItems = [];
                    response.data[0].children.forEach(function (itemObject) {
                        menuItems.push(self.createHtmlElement(itemObject));
                    });

                    menuItems.forEach(function (htmlElementItem) {
                        document.querySelector(self.selector).appendChild(htmlElementItem);
                    });

                    self.updateSortableJavascript();

                    resolve(document.querySelector(self.selector));
                }).catch(function (error) {
                    reject(error);
                });
            });
        }

        /**
         * Removes all children from the ul
         */

    }, {
        key: 'clearRootUl',
        value: function clearRootUl() {
            if (this.initialized === false) {
                console.error('Please initialize the controller with the init method first.');return;
            }

            var rootUl = document.querySelector(this.selector);
            while (rootUl.firstChild) {
                rootUl.removeChild(rootUl.firstChild);
            }
        }

        /**
         * Creates a menu item (HTMLElement) and sub menu items if necessary
         *
         * @param data
         * @returns {HTMLElement}
         */

    }, {
        key: 'createHtmlElement',
        value: function createHtmlElement(data) {
            if (this.initialized === false) {
                console.error('Please initialize the controller with the init method first.');return;
            }

            self = this;

            var activeId = self.activeId;

            var id = data.id;
            var title = data.title;
            var thumbnail = data.thumbnail;
            var children = data.children;
            var status = data.status;
            var routes = data.routes;

            //Generate json data representing that element
            var routesForElement = {};
            for (var routeProperty in routes) {
                if (!routes.hasOwnProperty(routeProperty)) continue;

                routesForElement[routeProperty] = routes[routeProperty];
            }
            if (routesForElement == {}) routesForElement = [];

            var elementJson = {
                id: data.id,
                title: data.title,
                thumbnail: data.thumbnail,
                routes: routesForElement,
                status: data.status
            };
            elementJson = JSON.stringify(elementJson);

            //Render all child html items first
            var childItems = [];
            var _iteratorNormalCompletion3 = true;
            var _didIteratorError3 = false;
            var _iteratorError3 = undefined;

            try {
                for (var _iterator3 = children[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
                    var object = _step3.value;

                    childItems.push(this.createHtmlElement(object));
                }

                //Displays a red or green line in front of the item depending on if the status (class) is active or not
            } catch (err) {
                _didIteratorError3 = true;
                _iteratorError3 = err;
            } finally {
                try {
                    if (!_iteratorNormalCompletion3 && _iterator3.return) {
                        _iterator3.return();
                    }
                } finally {
                    if (_didIteratorError3) {
                        throw _iteratorError3;
                    }
                }
            }

            var colorStatusHtml = '\n            <span class="color-status" data-status-type="' + status + '">\n                &nbsp;\n            </span>\n        ';

            //Displays the items icon thumbnail OR the first character of its title
            var iconHtml = '\n            <div class="icon" ' + (thumbnail ? 'style="background-image: url(\'' + thumbnail + '\');"' : '') + ' >\n                ' + (thumbnail ? '' : '<span>' + (title ? title.substring(0, 1) : '') + '</span>') + '\n            </div>\n        ';

            //The main item html that has all other items
            var listIem = '\n            <li data-json=\'' + elementJson + '\' class="' + this.listItemClass + ' ' + (id == activeId ? 'active' : '') + '"> \n                <a href="' + this.editEntitiesUrl + '/' + id + '">\n                    ' + colorStatusHtml + '\n                    ' + iconHtml + '\n                    <p>' + title + '</p>\n                </a>\n            </li> \n        ';

            //Render it to a real html element
            var domParser = new DOMParser();
            var document = domParser.parseFromString(listIem, "text/html");
            var node = document.body.firstChild;

            //And add the children inside
            if (childItems.length > 0) {
                var subList = document.createElement('ul');
                subList.className = 'sortable';

                // console.log('rendered childItems');
                // console.log(childItems);
                childItems.forEach(function (element) {
                    subList.appendChild(element);
                });

                node.appendChild(subList);
            }

            //and return it
            return node;
        }
    }]);

    return SortableController;
}();

var ConfirmationController = function () {
    /**
     * ConfirmationController constructor
     *
     * @param selector
     * @param headerText
     * @param message
     * @param confirmText
     * @param cancelText
     */
    function ConfirmationController(selector, headerText, message, confirmText, cancelText) {
        _classCallCheck(this, ConfirmationController);

        if (ConfirmationController.selectorValid(selector) === false) {
            console.error('The selector "' + selector + '" isn\'t valid. Did not enable the confirmation functionality for that selector');
            return;
        }

        ConfirmationController.headerText = headerText;
        ConfirmationController.message = message;
        ConfirmationController.confirmText = confirmText;
        ConfirmationController.cancelText = cancelText;

        ConfirmationController.button = document.querySelector(selector);

        ConfirmationController.promptElement = this.createPrompt();
        document.body.appendChild(ConfirmationController.promptElement);

        this.addListenersToButton(ConfirmationController.button);
        this.addListenersToModalButtons();
    }

    /**
     * Adds listeners to the button that the selector from the constructor references to.
     * So that the button works
     *
     * @param button
     */


    _createClass(ConfirmationController, [{
        key: 'addListenersToButton',
        value: function addListenersToButton(button) {
            button.addEventListener('click', function (controller) {
                return function (clickEvent) {
                    clickEvent.preventDefault();
                    controller.showConfirmationPrompt(true);
                };
            }(this));
        }

        /**
         * Add listeners to the modals buttons.
         * Usually the yes no buttons.
         */

    }, {
        key: 'addListenersToModalButtons',
        value: function addListenersToModalButtons() {
            if (!ConfirmationController.promptElement) console.error('First create the modal with the createPrompt method');

            var confirmButton = ConfirmationController.promptElement.querySelector('button.confirm');
            var cancelButton = ConfirmationController.promptElement.querySelector('button.cancel');
            var shader = ConfirmationController.promptElement.querySelector('div.shader');
            // console.log(confirmButton);
            // console.log(cancelButton);
            confirmButton.addEventListener('click', this.confirmClicked.bind(this));
            cancelButton.addEventListener('click', this.cancelClicked.bind(this));
            shader.addEventListener('click', this.cancelClicked.bind(this));
        }
    }, {
        key: 'confirmClicked',
        value: function confirmClicked(mouseEvent) {
            mouseEvent.preventDefault();
            console.log(ConfirmationController.button);

            var form = this.findForm(ConfirmationController.button);
            console.log(form);
            if (form) form.submit();
            this.showConfirmationPrompt(false);
        }
    }, {
        key: 'cancelClicked',
        value: function cancelClicked(mouseEvent) {
            mouseEvent.preventDefault();
            this.showConfirmationPrompt(false);
        }

        /**
         * Retrieves an HTML element and starts traversing up into the dom to find the first form the element is in.
         * Returns the form or false if it cannot be found
         * @param element
         */

    }, {
        key: 'findForm',
        value: function findForm(element) {
            if (!element.parentNode) return false;
            if (element.parentNode.tagName === 'FORM') return element.parentNode;
            return this.findForm(element.parentNode);
        }

        /**
         * Create a div that represents a prompt
         *
         * @returns {HTMLDivElement}
         */

    }, {
        key: 'createPrompt',
        value: function createPrompt() {
            var html = '<div class="modal">' + '<div class="header"><h4>' + ConfirmationController.headerText + '</h4></div>' + '<div class="body">' + '<p class="message">' + ConfirmationController.message + '</p>' + '<div class="buttons">' + '<button class="confirm">' + ConfirmationController.confirmText + '</button>' + '<button class="cancel">' + ConfirmationController.cancelText + '</button>' + '</div>' + '</div>' + '</div>' + '</div>' + '<div class="shader"></div>';

            var promptElement = document.createElement("div");
            promptElement.setAttribute('id', 'confirmBox');
            promptElement.innerHTML = html;

            return promptElement;
        }

        /**
         * Show or hides the confirmation prompt by adding a hidden class to it.
         */

    }, {
        key: 'showConfirmationPrompt',
        value: function showConfirmationPrompt(show) {
            ConfirmationController.promptElement.classList.add('show');
            if (!show) ConfirmationController.promptElement.classList.remove('show');
        }

        /**
         * Returns true when a selector references a button tag or an input tag with type button.
         * false if not
         *
         * @param selector
         * @returns {boolean}
         */

    }], [{
        key: 'selectorValid',
        value: function selectorValid(selector) {
            var button = document.querySelector(selector);
            if (!button) return false;
            if (button.tagName !== 'BUTTON' && button.tagName !== 'INPUT') return false;
            if (button.tagName === "INPUT") if (button.getAttribute('type').toLowerCase() !== 'button' && button.getAttribute('type').toLowerCase() !== 'submit') return false;

            return true;
        }
    }]);

    return ConfirmationController;
}();

var TabsController = function () {

    /**
     * The tab controller can obviously control tabs.
     * You just have to have a couple of divs that hold the content. These divs must all have a class name that
     * corresponds to the value of constructor parameter tabContentIdAndClassAndPrefix. And they all must have an id
     * that also starts with the value of tabContentIdAndClassAndPrefix followed by the tab slug.
     *
     * You can specify if you have an hidden input field that needs to be updated with the curent tab slug. You do that
     * with the tabSlugInputSelector.
     *
     * Content tab divs and buttons will also receive an active state class to make them visible / stand out when present
     * or hidden / to background. You can specify this class name with the activeClass parameter.
     *
     * The tabButtonGroupSelector selects an element that holds the tab buttons to switch tabs. This element must have an
     * ul element that holds li elements containing a elements.
     *
     * The reactToUrlHashChange parameter controls if the controller should react if the hash part of the url did change.
     *
     * @param tabContentIdAndClassAndPrefix stringseelc
     * @param tabButtonGroupSelector string
     * @param activeClass string
     * @param reactToUrlHashChange
     * @param tabSlugInputSelector string
     */
    function TabsController() {
        var tabContentIdAndClassAndPrefix = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'tab';
        var tabButtonGroupSelector = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '.tab-buttons';
        var activeClass = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'active';
        var reactToUrlHashChange = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
        var tabSlugInputSelector = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : undefined;

        _classCallCheck(this, TabsController);

        this.tabContentDivsClassAndIdPrefix = tabContentIdAndClassAndPrefix;
        this.tabSlugInputId = tabSlugInputSelector;
        this.activeClass = activeClass;
        this.reactToUrlHashChange = reactToUrlHashChange;

        if (reactToUrlHashChange) this.addListenerForHashChange(reactToUrlHashChange);
    }

    /**
     * Opens the tab by using the tab slug
     *
     * @param tabSlug
     */


    _createClass(TabsController, [{
        key: 'openTab',
        value: function openTab(tabSlug) {
            //Remove trailing / on the left hand side
            tabSlug = this.removeLeftHandSlashInSlug(tabSlug);
            if (!tabSlug) {
                console.error("TabsController: Could not open tab with an empty slug");return;
            }

            this.updateTabSlugInput(tabSlug);

            this.showTabContentForTabWithSlug(tabSlug);
            this.makeTabButtonActiveForSlug(tabSlug);
        }

        /**
         * Removes a / at the beginning of a tab slug
         *
         * @param tabSlug
         */

    }, {
        key: 'removeLeftHandSlashInSlug',
        value: function removeLeftHandSlashInSlug(tabSlug) {
            return tabSlug.replace(/^\/(.*)/, '$1');
        }

        /**
         * Updates a usually hidden input field holding the tab slug with a new slug
         *
         * @param newSlug string
         */

    }, {
        key: 'updateTabSlugInput',
        value: function updateTabSlugInput(newSlug) {
            if (this.tabSlugInputId === undefined) return;
            var element = document.querySelector(this.tabSlugInputId);
            if (element) element.value = newSlug;
        }
    }, {
        key: 'makeTabButtonActiveForSlug',
        value: function makeTabButtonActiveForSlug(slug) {
            $('.entity-tabs >ul >li').removeClass('active');
            $('.entity-tabs >ul >li a[href="#' + slug + '"]').parent().addClass('active');
        }

        /**
         * Shows the tab content div with the specified slug and hides the other content div tabs.
         * It does this by adding and removing classes (the active class you specified in the constructor)
         *
         * @param slug string
         */

    }, {
        key: 'showTabContentForTabWithSlug',
        value: function showTabContentForTabWithSlug(slug) {
            var _this2 = this;

            //Remove the active class from all tab content classes
            document.querySelectorAll('.' + this.tabContentDivsClassAndIdPrefix).forEach(function (element) {
                element.classList.remove(_this2.activeClass);
            });

            //Add the active class to the tab that has the correct slug appended to the IdPrefix
            var activeTab = document.querySelector("#" + this.tabContentDivsClassAndIdPrefix + "-" + slug);
            if (!activeTab) {
                console.error("TabsController: Could not make content tab active. It should have an ID with: #" + this.tabContentDivsClassAndIdPrefix + "-" + slug);return;
            }

            activeTab.classList.add(this.activeClass);
        }

        /**
         * Adds or disables listening for hashchange events to update tabs
         *
         * @param boolean
         */

    }, {
        key: 'addListenerForHashChange',
        value: function addListenerForHashChange(boolean) {
            if (boolean) {
                window.addEventListener('hashchange', this.hashChanged.bind(this));
                window.addEventListener('load', this.hashChanged.bind(this));
            } else {
                window.removeEventListener('hashchange', this.hashChanged);
                window.removeEventListener('load', this.hashChanged);
            }
        }

        /**
         * Called automatically by an internal listener (controlled by the addListenerForHashChange method)
         */

    }, {
        key: 'hashChanged',
        value: function hashChanged(event) {
            var tabSlug = window.location.hash.substring(1);
            if (tabSlug) {
                this.openTab(tabSlug);
                return;
            }

            var tabSlugElement = document.querySelector(this.tabSlugInputId);
            if (!tabSlugElement) return;

            this.openTab(tabSlugElement.value);
        }
    }]);

    return TabsController;
}();