src/PuphpetBundle/Resources/public/custom.js
var PUPHPET = {};
/**
* Catches anchor tag (#foo) in URL bar and displays proper tab
*/
PUPHPET.displayTabFromUrl = function () {
if (window.location.hash.length < 1) {
return true;
}
$('[data-group=menu-link]').each(function() {
if (window.location.hash == this.getAttribute('href')) {
$(this).click();
$('html, body').scrollTop(0);
return true;
}
});
};
/**
* Handles displaying section help information
*/
PUPHPET.helpTextDisplay = function() {
$(document).on('click', '[data-toggle="help-text"]', function (e) {
$(this).closest('.help-block').find('.hidden')
.removeClass('hidden').addClass('inline');
$(this).remove();
});
};
/**
* Adds HTML response based on clicked element's data-source-url value.
*
* Adds the response above clicked element, and then re-runs selectize.js
* on new elements.
*/
PUPHPET.addBlock = function() {
$(document).on('click', '[data-toggle="add-block"]', function(e){
e.stopPropagation();
e.preventDefault && e.preventDefault();
var sourceUrl = this.getAttribute('href');
var clickedElement = $(this);
var $liContainer = $(this).closest('li');
var $nestedTabsContainer = $(this).closest('.nested-tabs');
var $panelBodyContainer = $(this).closest('.panel-body');
$.ajax({
url: sourceUrl,
cache: false
}).done(function(response) {
response = Array.isArray(response) ? response : [response];
var tabLinkClicked = false;
for (var i = 0; i < response.length; i++) {
$tabLink = parseResponse($liContainer, $nestedTabsContainer, $panelBodyContainer, $(response[i]));
if (!tabLinkClicked) {
tabLinkClicked = true;
$tabLink[0].click();
}
}
});
});
function parseResponse($liContainer, $nestedTabsContainer, $panelBodyContainer, $row) {
var $template = $('#nested-tabs-template').clone(true);
var $tabLink = $template.find('[data-toggle="tab"]');
var rowId = $row[0].getAttribute('id');
var uniqid = $row[0].getAttribute('data-uniqid');
var name = $row[0].getAttribute('data-name');
$template.removeAttr('id');
var targetString = '#' + $tabLink[0].getAttribute('data-target') + rowId;
$tabLink.text(uniqid);
$tabLink[0].setAttribute(
'data-target',
targetString
);
$template.find('[data-toggle="delete-block"]')[0].setAttribute(
'data-target',
targetString
);
$template.find('[data-type="name"]')[0].setAttribute(
'name',
name
);
$panelBodyContainer.find('.tab-content')[0].append($row[0]);
$nestedTabsContainer.append($template);
PUPHPET.runSelectize($row);
PUPHPET.helpTextDisplay();
PUPHPET.checkboxCollapse();
PUPHPET.radioCollapse();
PUPHPET.disableOnUncheck();
PUPHPET.enforceGroupSingleChoice();
PUPHPET.sortableTabs($nestedTabsContainer);
return $tabLink;
}
};
/**
* Deletes element based on data id
*/
PUPHPET.deleteBlock = function() {
$(document).on('click', '[data-toggle="delete-block"]', function(e){
e.stopPropagation();
e.preventDefault && e.preventDefault();
var blockId = this.getAttribute('data-target');
var $liContainer = $(this).closest('li');
var $nestedTabsContainer = $(this).closest('.nested-tabs');
var $blockContainer = $(blockId);
$liContainer.remove();
$blockContainer.slideUp(500, function() {
$(this).remove();
});
// Another tab already marked as active
if ($nestedTabsContainer.find('li.active').length) {
return true;
}
var $children = $nestedTabsContainer.find('li a[data-toggle="tab"]');
if ($children.length < 1) {
return true;
}
$children.first().click();
});
};
/**
* Run selectize.js on initial page load, and then re-run it whenever
* new selectize-enabled elements are dynamically added to the DOM.
*
* @param $element
*/
PUPHPET.runSelectize = function($element) {
// input or select elements; allows user to create their own tags
var $selectTagsEditable = $('.tags, .select-tags-editable', $element).selectize({
plugins: ['remove_button'],
delimiter: ',',
persist: false,
create: function(input) {
return {
value: input,
text: input
}
},
maxItems: null,
valueField: 'value',
labelField: 'text',
searchField: 'value'
});
// input or select elements; allows user to create their own tag - SINGLE selection
var $selectTagEditable = $('.select-tag-editable', $element).selectize({
persist: false,
create: true
});
// select elements; asks user for value of selected tags; cannot create own tags
var $selectTagsUserInput = PUPHPET.selectizeTagsUserInput($element);
// select single element; does not allow creating new tag
var $selectTag = $('.select-tag', $element).selectize({
persist: false,
create: false
});
// select elements; does not allow creating new tags
var $selectTags = $('.select-tags', $element).selectize({
plugins: ['remove_button'],
delimiter: ',',
persist: false,
create: false
});
PUPHPET._trackSelectize($selectTagsEditable);
PUPHPET._trackSelectize($selectTagsUserInput);
PUPHPET._trackSelectize($selectTagEditable);
PUPHPET._trackSelectize($selectTag);
PUPHPET._trackSelectize($selectTags);
};
/**
* Active for select type elements.
*
* On user adding option, prompts user for data, and creates a new, matching
* hidden element containing user input for easier handling of POSTed data.
*
* On user remove option, adds the removed element back to the available options
* list and deletes the hidden element related to removed option.
*
* @param $element
*/
PUPHPET.selectizeTagsUserInput = function($element) {
var $selectTagsUserInput = $('.select-tags-user-input', $element).selectize({
plugins: ['remove_button'],
delimiter: ',',
persist: false,
create: true,
onItemAdd: function(value, $item) {
var targetContainer = '#' + $(this['$input'])[0].getAttribute('data-target-container');
var targetNameStructure = $(this['$input'])[0].getAttribute('data-target-name');
var elementName = targetNameStructure + '[' + this.options[value].text + ']';
var suffix = prompt('Enter Value:') || '0';
var label = this.options[value].text + ' = ' + suffix;
var data = $.extend({}, this.options[value], {
text: label
});
// Append this user input as a new hidden element
$('<input>').attr({
type: 'hidden',
name: elementName,
value: suffix
}).appendTo(targetContainer);
this.updateOption(value, data);
},
onItemRemove: function(value, $item) {
var targetContainer = '#' + $(this['$input'])[0].getAttribute('data-target-container');
var targetNameStructure = $(this['$input'])[0].getAttribute('data-target-name');
var elementName = targetNameStructure + '[' + this.options[value].value + ']';
$(targetContainer + ' input[name="' + elementName + '"]').remove();
var data = $.extend({}, this.options[value], {
text: value
});
this.updateOption(value, data);
}
});
// Adds pre-selected option values to selectize field
for (var i = 0; i < $selectTagsUserInput.length; i++) {
var $selectElement = $selectTagsUserInput[i].selectize;
var targetContainer = '#' + $selectTagsUserInput[i].getAttribute('data-target-container');
var $selectedItems = $(targetContainer);
if (!$selectedItems.length) {
continue;
}
$selectedItems.children().each(function() {
var optionName = this.getAttribute('data-option-name');
var optionValue = $(this).val();
var label = $selectElement.options[optionName].text + ' = ' + optionValue;
var data = $.extend({}, $selectElement.options[optionName], {
text: label
});
$selectElement.updateOption(optionName, data);
});
}
return $selectTagsUserInput;
};
var selectizedObjects = [];
/**
* Keep track of all initialized selectize.js elements
*
* @param $selectizeElements
* @private
*/
PUPHPET._trackSelectize = function($selectizeElements) {
for (var i = 0; i < $selectizeElements.length; i++) {
selectizedObjects[$selectizeElements[i].id] = $selectizeElements[i];
}
};
/**
* Allows adding an item to a selectize.js element on user click
*/
PUPHPET.selectizeAddClickedToElement = function() {
$(document).on('click', '.addClickedToSelectizeElement', function(e){
var target = this.getAttribute('data-target');
var itemValue = this.getAttribute('data-value');
var itemTitle = this.getAttribute('data-title') != null
? this.getAttribute('data-title')
: $(this).text();
if (!(target in selectizedObjects)) {
return false;
}
var control = selectizedObjects[target].selectize;
control.addOption({
value: itemValue,
text: itemTitle
});
control.addItem(itemValue);
return false;
});
};
/**
* Allows user to drag and drop a pre-generated yaml file containing
* their VMs configuration.
*/
PUPHPET.uploadConfig = function() {
var dropzone = document.documentElement;
var tid;
dropzone.addEventListener('dragover', handleDragOver, false);
dropzone.addEventListener('dragleave', handleDragLeave, false);
dropzone.addEventListener('drop', handleFileSelect, false);
$(document).on('paste', function(e) {
if ($(e.target).is('input, textarea')) {
return true;
}
submitForm(e.originalEvent.clipboardData.getData('text/plain'));
});
function handleDragOver(e) {
clearTimeout(tid);
e.stopPropagation();
e.preventDefault && e.preventDefault();
e.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
$('#drag-drop').fadeIn('slow');
}
function handleDragLeave(e) {
tid = setTimeout(function () {
e.stopPropagation();
$('#drag-drop').fadeOut('slow');
}, 300);
}
function handleFileSelect(e) {
e.stopPropagation();
e.preventDefault && e.preventDefault();
$('#drag-drop').fadeOut('slow');
var files = e.dataTransfer.files; // FileList object.
// Only proceed when a single file is dropped
if (files.length > 1 || !files.length) {
return false;
}
var file = files[0];
// Only allow yaml uploads
if (file.name.split('.').pop().toLowerCase() !== 'yaml') {
return false;
}
var reader = new FileReader();
// Closure to capture the file information.
reader.onload = (function (theFile) {
return function (e) {
submitForm(e.target.result);
};
})(file);
reader.readAsText(file);
return false;
}
function submitForm(config) {
if (!config.length) {
return;
}
var form = $(
'<form action="' + uploadConfigUrl + '" method="post">' +
'<textarea style="display:none;" name="config">' + config + '</textarea>' +
'</form>'
);
$('body').append(form);
$(form).submit();
}
};
PUPHPET.disableEnterSubmit = function() {
$('input,select').keypress(function(event) {
if(event.keyCode == 13) {
event.preventDefault();
}
});
};
/**
* Updates local virtualizers' base IP address.
*
* Virtualbox is 192.168.56.*
* Vmware is 192.168.57.*
* Parallels is 192.168.58.*
*/
PUPHPET.updateLocalIpAddress = function() {
$(document).on('change', '[data-toggle="update-local-ip-address"]', function(e) {
var baseIp = this.getAttribute('data-base-ip');
var matches = [
'192.168.56',
'192.168.57',
'192.168.58'
];
// Only replace IP addresses that are using the default ranges, not a custom address
$('[data-target="update-local-ip-address"]').each(function() {
var currentIp = $(this).val();
var currentIpBase = currentIp.replace(
/([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/g,
'$1.$2.$3'
);
if (matches.indexOf(currentIpBase) == -1) {
return true;
}
var newIp = currentIp.replace(
/([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/g,
baseIp + '.$4'
);
$(this).val(newIp);
});
});
};
PUPHPET.yamlConfigDownload = function() {
$(document).on('click', '#yaml-config', function (e) {
e.preventDefault();
e.stopPropagation();
var url = $(this).attr('href');
$.post(url, $('#main-form').serialize(), function (response) {
var w = window.open('about:blank', 'windowname');
w.document.write(response);
w.document.close();
});
});
};
PUPHPET.checkboxCollapse = function() {
$('input[type=checkbox][data-toggle=checkbox-collapse]').each(function (index, item) {
var $item = $(item);
var $target = $($item.data('target'));
var identifier = item.name
? 'input[type=checkbox][name="' + item.name + '"]'
: 'input[type=checkbox][id="' + item.id + '"]';
$(identifier).on('change', function () {
if ($item.is(':checked')) {
$target.collapse('show');
if (this.hasAttribute('data-enable-on-check')) {
PUPHPET.enableFormElements($(this.getAttribute('data-target')));
}
return true;
}
$target.collapse('hide');
if (this.hasAttribute('data-disable-on-uncheck')) {
PUPHPET.disableFormElements($(this.getAttribute('data-target')));
}
});
});
};
PUPHPET.radioCollapse = function() {
$('input[type=radio][data-toggle=radio-collapse]').each(function (index, item) {
var $item = $(item);
var $target = $($item.data('target'));
$('input[type=radio][name="' + item.name + '"]').on('change', function () {
if ($item.is(':checked')) {
$target.collapse('show');
return true;
}
$target.collapse('hide');
});
});
};
/**
* Hides $container and disables all form fields within it
*/
PUPHPET.disableFormElements = function($container) {
$container.addClass('form-elements-disabled');
$container.each(function() {
$(this)
.find('input, textarea, button, select')
.prop('disabled', true);
});
};
/**
* Shows $container and enables all form fields within it
*/
PUPHPET.enableFormElements = function($container) {
$container.removeClass('form-elements-disabled');
$container.each(function() {
$(this)
.find('input, textarea, button, select')
.prop('disabled', false);
});
};
/**
* Unchecks other elements within group
*/
PUPHPET.enforceGroupSingleChoice = function() {
$('input[data-enforce-group-single]').on('change', function () {
var $this = $(this);
var group = this.getAttribute('data-enforce-group-single');
if (!$this.is(':checked')) {
if (this.hasAttribute('data-disable-on-uncheck')) {
PUPHPET.disableFormElements($(this.getAttribute('data-target')));
}
return true;
}
if (this.hasAttribute('data-enable-on-check')) {
PUPHPET.enableFormElements($(this.getAttribute('data-target')));
}
$('input[data-enforce-group-single="' + group + '"]').not(this).each(function (index, item) {
if ($(this).is(':checkbox') && $(this).prop('checked')) {
$(this).click();
}
if (this.hasAttribute('data-disable-on-uncheck')) {
PUPHPET.disableFormElements($(this.getAttribute('data-target')));
}
});
});
};
PUPHPET.menuActive = function() {
$('[data-group=menu-link]').on('click', function () {
var $parent = $(this).parent('li');
if ($parent.length > 0 && $parent.hasClass('active')) {
return true;
}
$parent.addClass('active');
window.location.hash = this.hash;
$('[data-group=menu-link]').each(function() {
var $liContainer = $(this).parent('li');
if ($liContainer.length < 1) {
return true;
}
$liContainer.removeClass('active');
});
});
};
PUPHPET.disableOnUncheck = function() {
$('[data-disable-on-uncheck]').each(function() {
if ($(this).is(':checked')) {
return true;
}
PUPHPET.disableFormElements($(this.getAttribute('data-target')));
});
};
PUPHPET.bootstrapNotify = function() {
$('.growl-alert').each(function() {
new PNotify({
title: this.getAttribute('data-title'),
text: $(this).html(),
type: this.getAttribute('data-type')
});
});
};
PUPHPET.sortableTabs = function(container) {
if (container == undefined) {
container = '.sortable';
}
sortable(container, {
items: ':not(.add)',
forcePlaceholderSize: true,
draggingWidth: '50px'
});
}
$(document).ready(function() {
PUPHPET.runSelectize(null);
PUPHPET.selectizeAddClickedToElement();
PUPHPET.addBlock();
PUPHPET.deleteBlock();
PUPHPET.helpTextDisplay();
PUPHPET.checkboxCollapse();
PUPHPET.radioCollapse();
PUPHPET.updateLocalIpAddress();
PUPHPET.enforceGroupSingleChoice();
PUPHPET.menuActive();
PUPHPET.displayTabFromUrl();
PUPHPET.uploadConfig();
PUPHPET.disableEnterSubmit();
PUPHPET.yamlConfigDownload();
PUPHPET.disableOnUncheck();
PUPHPET.bootstrapNotify();
PUPHPET.sortableTabs();
});