ytkns/public/assets/editor.js
2020-06-10 16:03:13 +00:00

1082 lines
43 KiB
JavaScript

function ytknsRequestJson(url, callback, method, data, headers, handleErr, upload) {
if(!callback)
callback = function(){};
var xhr = new XMLHttpRequest;
if(xhr.upload && upload) {
xhr.upload.onloadstart = function(ev) { upload('loadstart', ev); };
xhr.upload.onprogress = function(ev) { upload('progress', ev) };
xhr.upload.onload = function(ev) { upload('load', ev); };
}
xhr.onreadystatechange = function() {
if(xhr.readyState !== 4)
return;
var json = JSON.parse(xhr.responseText);
if(json.err && !handleErr) {
alert(json.err);
callback([]);
} else
callback(json);
};
xhr.open(method || 'GET', url);
if(headers && headers.length > 0)
for(var i = 0; i < headers.length; i++)
xhr.setRequestHeader(headers[i].name, headers[i].value);
xhr.send(data || null);
}
function ytknsEditorLoadEffects(callback) {
ytknsRequestJson('/zones/_effects', callback);
}
function ytknsLoadZoneInfo(zoneId, callback) {
ytknsRequestJson('/zones/' + parseInt(zoneId).toString() + '.json', callback);
}
function ytknsLoadUploadInfo(uploadId, callback) {
ytknsRequestJson('/uploads/' + uploadId.toString() + '.json', callback);
}
function ytknsCreateUrlString(set) {
var parts = [];
for(var i = 0; i < set.length; i++)
parts.push(encodeURIComponent(set[i].name) + '=' + encodeURIComponent(set[i].value));
return parts.join('&');
}
function ytknsCreateUrlStringPart(name, value) {
return { 'name': name.toString(), 'value': (
(typeof value).toLowerCase() === 'object'
? JSON.stringify(value)
: value.toString()
) };
}
function ytknsZoneInfoToUrlString(zoneInfo) {
return ytknsCreateUrlString(ytknsZoneInfoSerialise(zoneInfo, ytknsCreateUrlStringPart));
}
function ytknsZoneInfoSerialise(zoneInfo, callback) {
var set = [];
if(zoneInfo) {
set.push(callback('zone_token', ytknsEditorToken || ''));
set.push(callback('zone_id', zoneInfo.id));
set.push(callback('zone_name', zoneInfo.name));
set.push(callback('zone_title', zoneInfo.title));
if(zoneInfo.effects && zoneInfo.effects.length > 0) {
for(var i = 0; i < zoneInfo.effects.length; i++) {
var format = 'zone_effect[%1][%2]'.replace('%1', zoneInfo.effects[i].type),
keys = Object.keys(zoneInfo.effects[i].values);
if(keys.length < 1) {
set.push(callback(format.replace('%2', '_'), '_'));
} else
for(var j = 0; j < keys.length; j++) {
var key = format.replace('%2', keys[j]);
set.push(callback(key, zoneInfo.effects[i].values[keys[j]] || ''));
}
}
}
}
return set;
}
function ytknsSaveZoneInfo(zoneInfo, callback) {
if(!zoneInfo || !zoneInfo.id)
return;
ytknsRequestJson(
'/zones/' + parseInt(zoneInfo.id).toString() + '.json',
callback,
'POST',
ytknsZoneInfoToUrlString(zoneInfo),
[{ name: 'Content-Type', value: 'application/x-www-form-urlencoded' }]
);
}
function ytknsEditorPreview(zoneInfo) {
var formElement = document.createElement('form');
formElement.action = '/zones/_preview';
formElement.method = 'post';
formElement.target = '_blank';
formElement.style.display = 'none';
var elements = ytknsZoneInfoSerialise(zoneInfo, function(name, value) {
var inputElement = document.createElement('input');
inputElement.name = name;
inputElement.type = 'hidden';
inputElement.value = (
(typeof value).toLowerCase() === 'object'
? JSON.stringify(value)
: value.toString()
);
formElement.appendChild(inputElement);
});
document.body.appendChild(formElement);
formElement.submit();
formElement.parentNode.removeChild(formElement);
}
function ytknsEditorCreateUpload(file, callback, status) {
var formData = new FormData;
formData.append('upload_token', ytknsEditorUploadToken || '');
formData.append('upload_file', file);
ytknsRequestJson(
'/uploads',
callback,
'POST',
formData,
null,
true,
status
);
}
var ytknsZoneInfo = null,
ytknsEditorToken = '',
ytknsEditorUploadToken = '',
ytknsEditorElemSidebar = null,
ytknsEditorElemSidebarButtons = null,
ytknsEditorElemSidebarEffects = null,
ytknsEditorElemMain = null,
ytknsEditorElemMainTitle = null,
ytknsEditorElemMainContainer = null,
ytknsEditorEffects = [],
ytknsEditorIgnoreHashChange = false,
ytknsEditorCleanExit = true;
function ytknsEditorChangeHash(hash) {
ytknsEditorIgnoreHashChange = true;
location.hash = hash;
}
function ytknsEditorBeforeUnload(ev) {
if(!ytknsEditorCleanExit) {
ev.preventDefault();
ev.returnValue = '';
}
}
function ytknsGetEffectInfoByType(type) {
for(var i = 0; i < ytknsEditorEffects.length; i++)
if(ytknsEditorEffects[i].type === type)
return ytknsEditorEffects[i];
return null;
}
function ytknsGetEffectValueByType(type) {
if(ytknsZoneInfo === null || ytknsZoneInfo.effects === null || ytknsZoneInfo.effects.length < 1)
return null;
for(var i = 0; i < ytknsZoneInfo.effects.length; i++)
if(ytknsZoneInfo.effects[i].type === type)
return ytknsZoneInfo.effects[i];
return null;
}
function ytknsRemoveEffectValueByType(type) {
var info = ytknsGetEffectValueByType(type);
if(!info) {
alert('Tried to remove an effect that doesn\'t exist.');
return;
}
var index = ytknsZoneInfo.effects.indexOf(info);
if(index >= 0)
ytknsZoneInfo.effects.splice(index, 1);
ytknsEditorUpdateSidebarEffects();
}
function ytknsEditorFilePickerDoUpload(files, callback, status) {
if(files.length < 1) {
alert('No file selected.');
return;
}
var file = files[0];
ytknsEditorCreateUpload(file, function(resp) {
if(resp.file) {
ytknsLoadUploadInfo(resp.file, function(uploadInfo) {
callback(uploadInfo);
});
} else if(resp.err) {
alert(resp.err);
if(status)
status(-1, -1);
}
}, function(type, ev) {
if(status)
status(ev.loaded, ev.total);
});
}
function ytknsEditorShowFilePicker(mimes, title, callback) {
var container = document.createElement('div');
container.classList.add('ye-applet-uploads');
var progressBarContainer = document.createElement('div');
progressBarContainer.classList.add('ye-applet-uploads-progress');
progressBarContainer.classList.add('ye-applet-uploads-hidden');
container.appendChild(progressBarContainer);
var progressBar = document.createElement('progress');
progressBar.min = 0;
progressBar.max = 100;
progressBar.value = 0;
progressBar.classList.add('ye-applet-uploads-progress-bar');
progressBarContainer.appendChild(progressBar);
var dropZone = document.createElement('div'),
dropZoneInner = document.createElement('div');
dropZone.classList.add('ye-applet-uploads-dropzone');
dropZoneInner.classList.add('ye-applet-uploads-dropzone-inner');
dropZoneInner.textContent = 'Drop a file or click here!';
dropZone.appendChild(dropZoneInner);
container.appendChild(dropZone);
var cancel = document.createElement('input');
cancel.classList.add('ye-applet-uploads-cancel');
cancel.type = 'button';
cancel.value = 'Cancel';
cancel.onclick = function() { callback(null); };
container.appendChild(cancel);
var doUpload = function(files) {
dropZone.classList.add('ye-applet-uploads-hidden');
cancel.classList.add('ye-applet-uploads-hidden');
progressBarContainer.classList.remove('ye-applet-uploads-hidden');
ytknsEditorFilePickerDoUpload(files, function(resp) {
dropZone.classList.remove('ye-applet-uploads-hidden');
cancel.classList.remove('ye-applet-uploads-hidden');
progressBarContainer.classList.add('ye-applet-uploads-hidden');
callback(resp);
}, function(loaded, total) {
if(loaded < 0 && total < 0) {
dropZone.classList.remove('ye-applet-uploads-hidden');
cancel.classList.remove('ye-applet-uploads-hidden');
progressBarContainer.classList.add('ye-applet-uploads-hidden');
return;
}
progressBar.value = Math.ceil((loaded / total) * 100);
});
};
dropZone.onclick = function() {
var selector = document.createElement('input');
selector.type = 'file';
selector.onchange = function() { doUpload(selector.files); };
if(mimes)
selector.accept = mimes.join(',');
selector.click();
};
dropZone.ondragenter = function(ev) {
ev.preventDefault();
ev.stopPropagation();
dropZone.classList.add('ye-applet-uploads-dropzone--active');
};
dropZone.ondragleave = function(ev) {
ev.preventDefault();
ev.stopPropagation();
dropZone.classList.remove('ye-applet-uploads-dropzone--active');
};
dropZone.ondragover = function(ev) {
ev.preventDefault();
ev.stopPropagation();
dropZone.classList.add('ye-applet-uploads-dropzone--active');
};
dropZone.ondrop = function(ev) {
ev.preventDefault();
ev.stopPropagation();
dropZone.classList.remove('ye-applet-uploads-dropzone--active');
doUpload(ev.dataTransfer.files);
};
ytknsEditorMainSetContainer(container, title || 'Upload File');
}
function ytknsLoadEffectEditor(effectInfo, effectValue) {
ytknsEditorChangeHash(effectInfo.type);
var editor = document.createElement('div');
editor.classList.add('ye-applet-editor');
if(effectInfo.props.length < 1) {
var empty = document.createElement('div');
editor.classList.add('ye-applet-editor--fill');
empty.classList.add('ye-applet-editor-empty');
empty.textContent = 'This effect has no properties.';
editor.appendChild(empty);
} else {
var properties = document.createElement('div');
properties.classList.add('ye-applet-editor-properties');
editor.appendChild(properties);
for(var i = 0; i < effectInfo.props.length; i++) {
ytknsAddEffectEditorProperty(
properties,
effectInfo, effectValue, effectInfo.props[i],
function() { ytknsLoadEffectEditor(effectInfo, effectValue); } // there's gotta be a better way
);
}
}
ytknsEditorMainSetContainer(editor, effectInfo.name);
}
function ytknsAddEffectEditorProperty(listContainer, effectInfo, effectValue, propInfo, redraw) {
var container = document.createElement('div');
container.classList.add('ye-applet-editor-properties-property');
listContainer.appendChild(container);
var propTitle = document.createElement('div');
propTitle.classList.add('ye-applet-editor-properties-property-title');
propTitle.textContent = propInfo.title;
container.appendChild(propTitle);
var propWrap = document.createElement('div');
propWrap.classList.add('ye-applet-editor-properties-property-wrap');
container.appendChild(propWrap);
switch(propInfo.type.name) {
case 'upload':
var propUpload = document.createElement('div');
propUpload.classList.add('ye-applet-editor-properties-property-upload');
propWrap.appendChild(propUpload);
var propUploadId = document.createElement('div');
propUploadId.classList.add('ye-applet-editor-properties-property-upload-id');
propUploadId.textContent = effectValue.values[propInfo.name] || '(none)';
propUpload.appendChild(propUploadId);
var propUploadSelect = document.createElement('div');
propUploadSelect.classList.add('ye-applet-editor-properties-property-upload-select');
propUploadSelect.title = 'Upload file';
propUploadSelect.onclick = function() {
ytknsEditorShowFilePicker(propInfo.type.allowed || [], ('Selecting ' + propInfo.title + ' for ' + effectInfo.name), function(uploadInfo) {
if(uploadInfo)
effectValue.values[propInfo.name] = uploadInfo.id || null;
redraw();
});
};
propUpload.appendChild(propUploadSelect);
break;
case 'bool':
var propBool = document.createElement('label');
propBool.classList.add('ye-applet-editor-properties-property-bool');
propWrap.appendChild(propBool);
var propBoolToggle = document.createElement('input');
propBoolToggle.classList.add('ye-applet-editor-properties-property-bool-toggle');
propBoolToggle.type = 'checkbox';
propBoolToggle.checked = (typeof effectValue.values[propInfo.name]).toLowerCase() === 'undefined'
? (propInfo.default || false)
: effectValue.values[propInfo.name];
propBoolToggle.onchange = function() {
effectValue.values[propInfo.name] = propBoolToggle.checked;
redraw();
};
propBool.appendChild(propBoolToggle);
break;
case 'int':
case 'float':
var propInt = document.createElement('label');
propInt.classList.add('ye-applet-editor-properties-property-int');
propWrap.appendChild(propInt);
var propIntInput = document.createElement('input');
propIntInput.classList.add('ye-applet-editor-properties-property-int-input');
propIntInput.type = 'number';
if(propInfo.min)
propIntInput.min = propInfo.min;
if(propInfo.max)
propIntInput.max = propInfo.max;
if(propInfo.type.name === 'float')
propIntInput.step = 0.01;
propIntInput.value = effectValue.values[propInfo.name] || propInfo.default || 0;
propIntInput.onchange = function() {
effectValue.values[propInfo.name] = propInfo.type.name === 'int' ? parseInt(propIntInput.value) : parseFloat(propIntInput.value);
redraw();
};
propInt.appendChild(propIntInput);
break;
case 'select':
var propSelect = document.createElement('label');
propSelect.classList.add('ye-applet-editor-properties-property-select');
propWrap.appendChild(propSelect);
var propSelectInput = document.createElement('select');
propSelectInput.classList.add('ye-applet-editor-properties-property-select-input');
propSelectInput.onchange = function() {
effectValue.values[propInfo.name] = propSelectInput.value;
redraw();
};
propSelect.appendChild(propSelectInput);
var propSelectOptionsKeys = Object.keys(propInfo.type.options),
propSelectOptionsValues = Object.values(propInfo.type.options);
for(var i = 0; i < propSelectOptionsKeys.length; i++) {
var propSelectOption = document.createElement('option');
propSelectOption.value = propSelectOptionsKeys[i];
propSelectOption.textContent = propSelectOptionsValues[i];
propSelectOption.selected = (effectValue.values[propInfo.name] || propInfo.default) === propSelectOptionsKeys[i];
propSelectInput.appendChild(propSelectOption);
}
break;
case 'colour':
var propColour = document.createElement('label');
propColour.classList.add('ye-applet-editor-properties-property-colour');
propWrap.appendChild(propColour);
var propColourInput = document.createElement('input');
propColourInput.type = 'color';
propColourInput.value = '#' + (effectValue.values[propInfo.name] || 0).toString(16).padStart(6, '0');
propColourInput.classList.add('ye-applet-editor-properties-property-colour-input');
propColourInput.onchange = function() {
effectValue.values[propInfo.name] = parseInt(propColourInput.value.substring(1), 16);
redraw();
};
propColour.appendChild(propColourInput);
break;
case 'string':
var propString = document.createElement('label');
propString.classList.add('ye-applet-editor-properties-property-string');
propWrap.appendChild(propString);
var propStringInput = document.createElement('input');
propStringInput.type = 'text';
if(propInfo.type.min)
propStringInput.minLength = propInfo.type.min;
if(propInfo.type.max)
propStringInput.maxLength = propInfo.type.max;
propStringInput.value = effectValue.values[propInfo.name] || '';
propStringInput.classList.add('ye-applet-editor-properties-property-string-input');
propStringInput.onchange = function() {
effectValue.values[propInfo.name] = propStringInput.value;
redraw();
};
propString.appendChild(propStringInput);
break;
case 'gradient':
if(!effectValue.values[propInfo.name])
effectValue.values[propInfo.name] = {};
var propGrad = document.createElement('div');
propGrad.classList.add('ye-applet-editor-properties-property-gradient');
propWrap.appendChild(propGrad);
var propGradPreview = document.createElement('div');
propGradPreview.classList.add('ye-applet-editor-properties-property-gradient-preview');
propGrad.appendChild(propGradPreview);
var propGradDirection = document.createElement('div');
propGradDirection.classList.add('ye-applet-editor-properties-property-gradient-direction');
propGrad.appendChild(propGradDirection);
var propGradDirectionCircle = document.createElement('div');
propGradDirectionCircle.classList.add('ye-applet-editor-properties-property-gradient-direction-circle');
propGradDirection.appendChild(propGradDirectionCircle);
var propGradDirectionCircleValue = document.createElement('div');
propGradDirectionCircleValue.classList.add('ye-applet-editor-properties-property-gradient-direction-circle-value');
propGradDirectionCircle.appendChild(propGradDirectionCircleValue);
var propGradDirectionCircleIndicator = document.createElement('div');
propGradDirectionCircleIndicator.classList.add('ye-applet-editor-properties-property-gradient-direction-circle-indicator');
propGradDirectionCircleValue.appendChild(propGradDirectionCircleIndicator);
var propGradDirectionValue = document.createElement('input');
propGradDirectionValue.classList.add('ye-applet-editor-properties-property-gradient-direction-input');
propGradDirectionValue.type = 'number';
propGradDirectionValue.min = 0;
propGradDirectionValue.max = 359;
propGradDirectionValue.value = 0;
propGradDirection.appendChild(propGradDirectionValue);
var propGradRedrawPreview = function() {
propGradPreview.style.backgroundImage = ytknsEditorGradientCSS(effectValue.values[propInfo.name]);
};
var propGradDirectionSet = function(val) {
val = parseInt(val);
effectValue.values[propInfo.name].d = val;
if(propGradDirectionValue.value != val)
propGradDirectionValue.value = val;
propGradDirectionCircleValue.style.transform = 'rotate(' + val + 'deg)';
propGradRedrawPreview();
};
propGradDirectionSet(effectValue.values[propInfo.name].d || 0);
propGradDirectionValue.onchange = function() {
propGradDirectionSet(propGradDirectionValue.value);
};
var propGradDirectionCircleMouseEvent = function(ev) {
if((ev.buttons & 1) < 1)
return;
var rect = ev.target.getBoundingClientRect(),
y = ev.layerY - (rect.height / 2),
x = ev.layerX - (rect.width / 2),
deg = Math.atan2(x, y) * 180 / Math.PI,
val = 180 - parseInt(deg);
propGradDirectionSet(val);
};
propGradDirectionCircle.onmousedown = propGradDirectionCircleMouseEvent;
propGradDirectionCircle.onmousemove = propGradDirectionCircleMouseEvent;
var propGradPoints = document.createElement('div');
propGradPoints.classList.add('ye-applet-editor-properties-property-gradient-points');
propGrad.appendChild(propGradPoints);
var propGradPointAdd = function(point) {
if(!point)
point = {};
if((typeof point.c).toLowerCase() === 'undefined')
point.c = parseInt(0xFFFFFF * Math.random());
if((typeof point.o).toLowerCase() === 'undefined')
point.o = parseInt(100 * Math.random());
var propGradPoint = document.createElement('div');
propGradPoint.classList.add('ye-applet-editor-properties-property-gradient-points-point');
propGradPoints.appendChild(propGradPoint);
var propGradPointActions = document.createElement('div');
propGradPointActions.classList.add('ye-applet-editor-properties-property-gradient-points-point-actions');
propGradPoint.appendChild(propGradPointActions);
var propGradPointActionsAdd = function(name, title, action) {
var propGradPointAction = document.createElement('div');
propGradPointAction.classList.add('ye-applet-editor-properties-property-gradient-points-point-actions-action');
propGradPointAction.classList.add('ye-applet-editor-properties-property-gradient-points-point-actions-action--' + name);
propGradPointAction.title = title;
propGradPointAction.onclick = function() { if(action) action(); };
propGradPointActions.appendChild(propGradPointAction);
};
propGradPointActionsAdd('delete', 'Delete', function() {
var index = effectValue.values[propInfo.name].p.indexOf(point);
if(index < 0)
return;
effectValue.values[propInfo.name].p.splice(index, 1);
propGradPoints.removeChild(propGradPoint);
propGradRedrawPreview();
});
var propGradPointColour = document.createElement('label');
propGradPointColour.classList.add('ye-applet-editor-properties-property-gradient-points-point-colour');
propGradPoint.appendChild(propGradPointColour);
var propGradPointColourValue = document.createElement('input');
propGradPointColourValue.type = 'color';
propGradPointColourValue.value = '#' + point.c.toString(16).padStart(6, '0');
propGradPointColourValue.classList.add('ye-applet-editor-properties-property-gradient-points-point-colour-value');
propGradPointColourValue.onchange = function() {
point.c = parseInt(propGradPointColourValue.value.substring(1), 16);
propGradPointColour.style.backgroundColor = propGradPointColourValue.value;
propGradRedrawPreview();
};
propGradPointColour.appendChild(propGradPointColourValue);
propGradPointColour.style.backgroundColor = propGradPointColourValue.value;
var propGradPointOffset = document.createElement('input');
propGradPointOffset.type = 'range';
propGradPointOffset.classList.add('ye-applet-editor-properties-property-gradient-points-point-offset-range');
propGradPointOffset.value = 0;
propGradPointOffset.min = 0;
propGradPointOffset.max = 100;
propGradPoint.appendChild(propGradPointOffset);
var propGradPointOffsetNum = document.createElement('input');
propGradPointOffsetNum.type = 'number';
propGradPointOffsetNum.classList.add('ye-applet-editor-properties-property-gradient-points-point-offset-numeric');
propGradPointOffsetNum.value = 0;
propGradPointOffsetNum.min = 0;
propGradPointOffsetNum.max = 100;
propGradPoint.appendChild(propGradPointOffsetNum);
var propGradPointOffsetIsSetting = false,
propGradPointOffsetSet = function(val) {
if(propGradPointOffsetIsSetting)
return;
propGradPointOffsetIsSetting = true;
val = parseInt(val);
propGradPointOffset.value = propGradPointOffsetNum.value = point.o = val;
propGradRedrawPreview();
propGradPointOffsetIsSetting = false;
};
propGradPointOffsetSet(point.o);
propGradPointOffset.onchange = function() {
propGradPointOffsetSet(propGradPointOffset.value);
};
propGradPointOffsetNum.onchange = function() {
propGradPointOffsetSet(propGradPointOffsetNum.value);
};
};
var propGradPointAddButton = document.createElement('button');
propGradPointAddButton.classList.add('ye-applet-editor-properties-property-gradient-points-add');
propGradPointAddButton.onclick = function() {
var point = {};
if(!effectValue.values[propInfo.name].p)
effectValue.values[propInfo.name].p = [];
effectValue.values[propInfo.name].p.push(point);
propGradPointAdd(point);
propGradRedrawPreview();
};
propGradDirection.appendChild(propGradPointAddButton);
var propGradPointAddButtonIcon = document.createElement('div');
propGradPointAddButtonIcon.classList.add('ye-applet-editor-properties-property-gradient-points-add-icon');
propGradPointAddButton.appendChild(propGradPointAddButtonIcon);
var propGradPointAddButtonText = document.createElement('div');
propGradPointAddButtonText.classList.add('ye-applet-editor-properties-property-gradient-points-add-text');
propGradPointAddButtonText.textContent = 'Add gradient point';
propGradPointAddButton.appendChild(propGradPointAddButtonText);
if(effectValue.values[propInfo.name].p)
for(var i = 0; i < effectValue.values[propInfo.name].p.length; i++)
propGradPointAdd(effectValue.values[propInfo.name].p[i]);
break;
default:
var propNone = document.createElement('div');
propNone.classList.add('ye-applet-editor-properties-property-none');
propNone.textContent = 'There is no handler available for this property type.';
propWrap.appendChild(propNone);
break;
}
var propDefault = document.createElement('div');
propDefault.classList.add('ye-applet-editor-properties-property-reset');
propDefault.title = 'Reset';
propDefault.onclick = function() {
effectValue.values[propInfo.name] = propInfo.default;
redraw();
};
propWrap.appendChild(propDefault);
}
function ytknsEditorGradientCSS(obj) {
var str = 'linear-gradient(' + (obj.d || 0).toString() + 'deg, ',
points = [];
if(obj.p)
for(var i = 0; i < obj.p.length; i++)
points.push('#' + (obj.p[i].c || 0).toString(16).padStart(6, '0') + ' ' + (obj.p[i].o || 0).toString() + '%');
return str + points.join(', ') + ')';
}
function ytknsEditorAddSidebarButton(className, title, callback) {
var button = document.createElement('div');
button.classList.add('ye-sidebar-buttons-button');
button.classList.add('ye-sidebar-buttons-button--' + className);
button.title = title;
button.onclick = callback;
ytknsEditorElemSidebarButtons.appendChild(button);
}
function ytknsEditorAddSidebarButtonSeparator() {
var separator = document.createElement('div');
separator.classList.add('ye-sidebar-buttons-separator');
ytknsEditorElemSidebarButtons.appendChild(separator);
}
function ytknsEditorAddSidebarEffect(effectValue) {
var effectInfo = ytknsGetEffectInfoByType(effectValue.type);
if(!effectInfo) {
alert('Attempted to add unregistered effect.');
return;
}
var effect = document.createElement('div');
effect.classList.add('ye-sidebar-effects-effect');
ytknsEditorElemSidebarEffects.appendChild(effect);
var effectName = document.createElement('div');
effectName.classList.add('ye-sidebar-effects-effect-name');
effectName.textContent = effectInfo.name;
effect.appendChild(effectName);
var effectActions = document.createElement('div');
effectActions.classList.add('ye-sidebar-effects-effect-actions');
effect.appendChild(effectActions);
ytknsEditorAddSidebarEffectAction(effectActions, 'edit', 'Edit Effect', function() {
ytknsLoadEffectEditor(effectInfo, effectValue);
});
ytknsEditorAddSidebarEffectAction(effectActions, 'delete', 'Delete Effect', function() {
var previous = ytknsEditorMainClone();
ytknsEditorMainShowEffectDeleteConfirm(effectInfo, function(accept) {
if(accept) {
ytknsRemoveEffectValueByType(effectValue.type);
ytknsEditorMainShowWelcome();
} else {
ytknsEditorMainRestore(previous);
}
});
});
}
function ytknsEditorMainShowEffectDeleteConfirm(effectInfo, callback) {
var confirmation = document.createElement('div'),
text = confirmation.appendChild(document.createElement('div')),
actions = confirmation.appendChild(document.createElement('div'));
confirmation.classList.add('ye-main-effect-delete-confirm');
text.classList.add('ye-main-effect-delete-confirm-text');
text.textContent = 'Are you sure you want to delete "' + effectInfo.name + '"?';
actions.classList.add('ye-main-effect-delete-confirm-actions');
var accept = document.createElement('div');
accept.classList.add('ye-main-effect-delete-confirm-actions-action');
accept.classList.add('ye-main-effect-delete-confirm-actions-action--accept');
accept.textContent = 'Yes';
accept.onclick = function() { callback(true); };
actions.appendChild(accept);
var deny = document.createElement('div');
deny.classList.add('ye-main-effect-delete-confirm-actions-action');
deny.classList.add('ye-main-effect-delete-confirm-actions-action--deny');
deny.textContent = 'No';
deny.onclick = function() { callback(false); };
actions.appendChild(deny);
ytknsEditorMainSetContainer(confirmation, 'Delete effect');
}
function ytknsEditorAddSidebarEffectAction(container, className, title, callback) {
var action = document.createElement('div');
action.classList.add('ye-sidebar-effects-effect-actions-action');
action.classList.add('ye-sidebar-effects-effect-actions-action--' + className);
action.title = title;
action.onclick = callback;
container.appendChild(action);
}
function ytknsEditorUpdateSidebarEffects() {
ytknsEditorElemSidebarEffects.innerHTML = '';
if(ytknsZoneInfo == null || ytknsZoneInfo.effects == null || ytknsZoneInfo.effects.length < 1) {
var nothing = document.createElement('div');
nothing.classList.add('ye-sidebar-effects-empty');
nothing.textContent = 'You have not added any effects yet.';
ytknsEditorElemSidebarEffects.appendChild(nothing);
} else {
for(var i = 0; i < ytknsZoneInfo.effects.length; i++)
ytknsEditorAddSidebarEffect(ytknsZoneInfo.effects[i]);
}
}
function ytknsShowDetailsEdit() {
ytknsEditorChangeHash('details');
var container = document.createElement('div');
container.classList.add('ye-main-details');
var fieldsElem = document.createElement('div');
fieldsElem.classList.add('ye-main-details-fields');
container.appendChild(fieldsElem);
var fields = [
{ name: 'Zone ID', value: ytknsZoneInfo.id },
{ name: 'Subdomain', value: ytknsZoneInfo.name, suffix: '.' + location.host },
{ name: 'Title', value: ytknsZoneInfo.title, max: 255, edit: function(val) {
ytknsZoneInfo.title = val;
} },
];
for(var i = 0; i < fields.length; i++) {
var field = fields[i],
fieldElem = document.createElement('div');
fieldElem.classList.add('ye-main-details-fields-field');
var fieldName = document.createElement('div');
fieldName.classList.add('ye-main-details-fields-field-name');
fieldName.textContent = field.name + ':';
fieldElem.appendChild(fieldName);
var fieldWrap = document.createElement('div');
fieldWrap.classList.add('ye-main-details-fields-field-wrap');
fieldElem.appendChild(fieldWrap);
var fieldInput = document.createElement('input');
fieldInput.classList.add('ye-main-details-fields-field-input');
fieldInput.type = 'text';
fieldInput.value = field.value;
if(field.max)
fieldInput.maxLength = field.max;
if(field.edit) {
var onedit = field.edit;
fieldInput.onchange = function(ev) {
onedit(ev.target.value);
};
} else {
fieldInput.readOnly = true;
fieldElem.classList.add('ye-main-details-fields-field--readonly');
}
fieldWrap.appendChild(fieldInput);
if(field.suffix)
fieldWrap.appendChild(document.createTextNode(field.suffix));
fieldsElem.appendChild(fieldElem);
}
ytknsEditorMainSetContainer(container, 'Zone information');
}
function ytknsEditorMainGetTitle() {
return ytknsEditorElemMainTitle.textContent;
}
function ytknsEditorMainSetTitle(title) {
ytknsEditorElemMainTitle.textContent = title;
}
function ytknsEditorMainGetContainer() {
return ytknsEditorElemMainContainer.firstChild;
}
function ytknsEditorMainSetContainer(child, title) {
if(title)
ytknsEditorMainSetTitle(title);
ytknsEditorElemMainContainer.innerHTML = '';
ytknsEditorElemMainContainer.appendChild(child);
}
function ytknsEditorMainClone() {
return {
'title': ytknsEditorMainGetTitle(),
'content': ytknsEditorMainGetContainer().cloneNode(true),
};
}
function ytknsEditorMainRestore(clone) {
ytknsEditorMainSetContainer(clone.content, clone.title);
}
function ytknsEditorMainShowWelcome() {
var welcome = document.createElement('div');
welcome.classList.add('ye-main-welcome');
var welcomeH1 = document.createElement('h1');
welcomeH1.classList.add('ye-main-welcome-h1');
welcomeH1.textContent = 'Welcome!';
welcome.appendChild(welcomeH1);
var welcomeP = document.createElement('p');
welcomeP.classList.add('ye-main-welcome-p');
welcomeP.textContent = 'Select a tool in the sidebar to get started.';
welcome.appendChild(welcomeP);
ytknsEditorMainSetContainer(welcome, 'Welcome to the YTKNS Editor');
}
function ytknsEditorMainShowEffectList() {
ytknsEditorChangeHash('add');
var container = document.createElement('div');
container.classList.add('ye-applet-effects');
var effects = document.createElement('div');
effects.classList.add('ye-applet-effects-list');
container.appendChild(effects);
for(var i = 0; i < ytknsEditorEffects.length; i++) {
var effectInfo = ytknsEditorEffects[i],
effectValue = ytknsGetEffectValueByType(effectInfo.type),
effectElement = document.createElement('div'),
effectUsed = effectValue !== null;
effectElement.classList.add('ye-applet-effects-list-item');
if(effectUsed)
effectElement.classList.add('ye-applet-effects-list-item--used');
var effectName = document.createElement('div');
effectName.classList.add('ye-applet-effects-list-item-name');
effectName.textContent = effectInfo.name;
effectElement.appendChild(effectName);
var effectActions = document.createElement('div');
effectActions.classList.add('ye-applet-effects-list-item-actions');
effectElement.appendChild(effectActions);
if(!effectUsed) {
var effectActionAdd = document.createElement('div');
effectActionAdd.classList.add('ye-applet-effects-list-item-actions-action');
effectActionAdd.classList.add('ye-applet-effects-list-item-actions-action--add');
effectActionAdd.title = 'Add Effect';
(function() { // javascript is very cool and good
var effectInfoCopy = effectInfo;
effectActionAdd.onclick = function() {
var effectValueNew = ytknsEditorAddNewEffect(effectInfoCopy);
ytknsEditorUpdateSidebarEffects();
ytknsLoadEffectEditor(effectInfoCopy, effectValueNew);
};
})();
effectActions.appendChild(effectActionAdd);
}
effects.appendChild(effectElement);
}
ytknsEditorMainSetContainer(container, 'Available effects');
}
function ytknsEditorAddNewEffect(effectInfo) {
var effectValue = {
type: effectInfo.type,
values: {},
};
for(var i = 0; i < effectInfo.props.length; i++) {
var propInfo = effectInfo.props[i];
effectValue.values[propInfo.name] = propInfo.default || '';
}
ytknsZoneInfo.effects.push(effectValue);
return effectValue;
}
function ytknsEditorConfirmReloadZoneInfo(zoneId) {
if(confirm('Are you sure you want to undo any changes you\'ve made?'))
ytknsEditorReloadZoneInfo(zoneId);
}
function ytknsEditorReloadZoneInfo(zoneId, onComplete) {
ytknsEditorChangeHash('');
ytknsEditorMainShowWelcome();
ytknsEditorLoadEffects(function(effects) {
ytknsEditorEffects = effects;
ytknsLoadZoneInfo(zoneId, function(zoneInfo) {
ytknsZoneInfo = zoneInfo;
ytknsEditorUpdateSidebarEffects();
if(onComplete)
onComplete();
});
});
}
function ytknsEditorSwitchString(str) {
switch(str) {
case '':
ytknsEditorMainShowWelcome();
break;
case 'add':
ytknsEditorMainShowEffectList();
break;
case 'details':
ytknsShowDetailsEdit();
break;
default:
var openEffectInfo = ytknsGetEffectInfoByType(str);
if(openEffectInfo) {
var openEffectValue = ytknsGetEffectValueByType(str);
ytknsLoadEffectEditor(openEffectInfo, openEffectValue);
}
break;
}
}
function ytknsEditorHashChange(ev) {
if(!ytknsEditorIgnoreHashChange)
ytknsEditorSwitchString(location.hash.substring(1));
ytknsEditorIgnoreHashChange = false;
}
function ytknsEditorMain(container, zoneId, editorToken, uploadToken) {
if(navigator.userAgent.match(/mobile/gi) && !confirm("The editor is not designed to be used on phones whatsoever.\r\nHit OK to continue anyway or cancel to whereever you came from.")) {
history.go(-1);
return;
}
window.onhashchange = ytknsEditorHashChange;
window.onbeforeunload = ytknsEditorBeforeUnload;
ytknsEditorToken = editorToken;
ytknsEditorUploadToken = uploadToken;
container.innerHTML = '';
container.classList.add('ye');
ytknsEditorElemSidebar = container.appendChild(document.createElement('div'));
ytknsEditorElemSidebar.classList.add('ye-sidebar');
ytknsEditorElemSidebarButtons = ytknsEditorElemSidebar.appendChild(document.createElement('div'));
ytknsEditorElemSidebarButtons.classList.add('ye-sidebar-buttons');
ytknsEditorAddSidebarButton('save', 'Save', function() {
ytknsSaveZoneInfo(ytknsZoneInfo, function(res) {
if(res.msg)
alert(res.msg);
});
});
ytknsEditorAddSidebarButton('cancel', 'Cancel', function() { location.assign('/zones?f=my'); });
ytknsEditorAddSidebarButton('reset', 'Undo Changes', function() { ytknsEditorConfirmReloadZoneInfo(zoneId); });
ytknsEditorAddSidebarButton('edit', 'Edit Details', function() { ytknsShowDetailsEdit(); });
ytknsEditorAddSidebarButtonSeparator();
ytknsEditorAddSidebarButton('preview', 'Show Preview', function() { ytknsEditorPreview(ytknsZoneInfo); });
ytknsEditorAddSidebarButton('live', 'View Live', function() { window.open('//%1.%2'.replace('%2', location.host).replace('%1', ytknsZoneInfo.name)); });
ytknsEditorAddSidebarButtonSeparator();
ytknsEditorAddSidebarButton('add', 'Add Effect', function() { ytknsEditorMainShowEffectList(); });
ytknsEditorElemSidebarEffects = ytknsEditorElemSidebar.appendChild(document.createElement('div'));
ytknsEditorElemSidebarEffects.classList.add('ye-sidebar-effects');
ytknsEditorUpdateSidebarEffects();
ytknsEditorElemMain = container.appendChild(document.createElement('div'));
ytknsEditorElemMain.classList.add('ye-main');
ytknsEditorElemMainTitle = ytknsEditorElemMain.appendChild(document.createElement('div'));
ytknsEditorElemMainTitle.classList.add('ye-main-title');
ytknsEditorElemMainContainer = ytknsEditorElemMain.appendChild(document.createElement('div'));
ytknsEditorElemMainContainer.classList.add('ye-main-container');
var goToEditor = location.hash.substring(1);
ytknsEditorReloadZoneInfo(zoneId, function() {
ytknsEditorSwitchString(goToEditor);
});
}