1086 lines
43 KiB
JavaScript
1086 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 = ytknsEditorSBS ? 'preview' : '_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,
|
|
ytknsEditorSBS = false;
|
|
|
|
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);
|
|
|
|
if(ytknsEditorSBS)
|
|
ytknsEditorPreview(ytknsZoneInfo);
|
|
}
|
|
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, sideBySide) {
|
|
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;
|
|
ytknsEditorSBS = sideBySide;
|
|
|
|
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);
|
|
});
|
|
}
|