228 lines
9.1 KiB
JavaScript
228 lines
9.1 KiB
JavaScript
angular.module('umbraco.services').factory('archetypeService', function () {
|
|
|
|
// Variables.
|
|
var draggedRteArchetype;
|
|
var archetypeEditors;
|
|
var rteClass = ".archetypeEditor .umb-rte textarea";
|
|
var editorSettings = {};
|
|
var disabledSortables = [];
|
|
|
|
//public
|
|
return {
|
|
//helper that returns a JS ojbect from 'value' string or the original string
|
|
jsonOrString: function (value, developerMode, debugLabel){
|
|
if(value && typeof value == 'string'){
|
|
try{
|
|
if(developerMode == '1'){
|
|
console.log("Trying to parse " + debugLabel + ": " + value);
|
|
}
|
|
value = JSON.parse(value);
|
|
}
|
|
catch(exception)
|
|
{
|
|
if(developerMode == '1'){
|
|
console.log("Failed to parse " + debugLabel + ".");
|
|
}
|
|
}
|
|
}
|
|
|
|
if(value && developerMode == '1'){
|
|
console.log(debugLabel + " post-parsing: ");
|
|
console.log(value);
|
|
}
|
|
|
|
return value;
|
|
},
|
|
getFieldsetByAlias: function (fieldsets, alias)
|
|
{
|
|
return _.find(fieldsets, function(fieldset){
|
|
return fieldset.alias == alias;
|
|
});
|
|
},
|
|
getPropertyIndexByAlias: function(properties, alias){
|
|
for (var i in properties)
|
|
{
|
|
if (properties[i].alias == alias) {
|
|
return i;
|
|
}
|
|
}
|
|
},
|
|
getPropertyByAlias: function (fieldset, alias){
|
|
return _.find(fieldset.properties, function(property){
|
|
return property.alias == alias;
|
|
});
|
|
},
|
|
getUniquePropertyAlias: function (currentScope, propertyAliasParts, excludeUniqueId) {
|
|
if (currentScope.hasOwnProperty('fieldsetIndex') && currentScope.hasOwnProperty('property') && currentScope.hasOwnProperty('propertyConfigIndex'))
|
|
{
|
|
var currentPropertyAlias = "f" + currentScope.fieldsetIndex + "-" + currentScope.property.alias + "-p" + currentScope.propertyConfigIndex;
|
|
propertyAliasParts.push(currentPropertyAlias);
|
|
}
|
|
else if (currentScope.hasOwnProperty('isPreValue')) // Crappy way to identify this is the umbraco property scope
|
|
{
|
|
var umbracoPropertyAlias = currentScope.$parent.$parent.property.alias; // Crappy way to get the umbraco host alias once we identify its scope
|
|
propertyAliasParts.push(umbracoPropertyAlias);
|
|
}
|
|
|
|
if (currentScope.$parent)
|
|
this.getUniquePropertyAlias(currentScope.$parent, propertyAliasParts, true);
|
|
|
|
var reversed = _.unique(propertyAliasParts).reverse();
|
|
|
|
if (!excludeUniqueId) {
|
|
reversed.push(_.uniqueId("u-"));
|
|
}
|
|
|
|
return reversed.join("-");
|
|
},
|
|
getFieldset: function(scope) {
|
|
var renderModel = scope.archetypeRenderModel;
|
|
return renderModel ? renderModel.fieldsets[scope.fieldsetIndex] : null;
|
|
},
|
|
getFieldsetProperty: function (scope) {
|
|
var fieldset = this.getFieldset(scope);
|
|
return fieldset ? fieldset.properties[scope.renderModelPropertyIndex] : null;
|
|
},
|
|
setFieldsetValidity: function (fieldset) {
|
|
// mark the entire fieldset as invalid if there are any invalid properties in the fieldset, otherwise mark it as valid
|
|
fieldset.isValid =
|
|
_.find(fieldset.properties, function (property) {
|
|
return property.isValid == false
|
|
}) == null;
|
|
},
|
|
validateProperty: function (fieldset, property, configFieldsetModel) {
|
|
var propertyConfig = this.getPropertyByAlias(configFieldsetModel, property.alias);
|
|
|
|
if (propertyConfig) {
|
|
// use property.value !== property.value to check for NaN values on numeric inputs
|
|
if (propertyConfig.required && (property.value == null || property.value === "" || property.value !== property.value)) {
|
|
property.isValid = false;
|
|
}
|
|
// issue 116: RegEx validate property value
|
|
// Only validate the property value if anything has been entered - RegEx is considered a supplement to "required".
|
|
if (property.isValid == true && propertyConfig.regEx && property.value) {
|
|
var regEx = new RegExp(propertyConfig.regEx);
|
|
if (regEx.test(property.value) == false) {
|
|
property.isValid = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
this.setFieldsetValidity(fieldset);
|
|
},
|
|
// called when the value of any property in a fieldset changes
|
|
propertyValueChanged: function (fieldset, property) {
|
|
// it's the Umbraco way to hide the invalid state when altering an invalid property, even if the new value isn't valid either
|
|
property.isValid = true;
|
|
this.setFieldsetValidity(fieldset);
|
|
},
|
|
// This stores the rich text editors in all Archetypes (e.g., during a drag operation).
|
|
// Typically, the editors will be restored after the drag completes.
|
|
storeEditors: function (element) {
|
|
|
|
// If there are not tinyMCE editors, this may be undefined.
|
|
if (typeof tinyMCE === "undefined") {
|
|
return;
|
|
}
|
|
|
|
// Variables.
|
|
var self = this;
|
|
draggedRteArchetype = element;
|
|
|
|
// Empty the stored settings.
|
|
editorSettings = {};
|
|
|
|
// For fast lookups, store each editor by the element ID.
|
|
var editorsById = {};
|
|
for (var i = 0; i < tinyMCE.editors.length; i++) {
|
|
var tempEditor = tinyMCE.editors[i];
|
|
editorsById[tempEditor.id] = tempEditor;
|
|
}
|
|
|
|
// Process each rich text editor.
|
|
$(rteClass).each(function() {
|
|
|
|
// Variables.
|
|
var id = $(this).attr("id");
|
|
var editor = editorsById[id];
|
|
|
|
// Get the property's temporary ID.
|
|
var scope = angular.element(this).scope().$parent;
|
|
var property = self.getFieldsetProperty(scope);
|
|
var tempId = property ? property.editorState.temporaryId : null;
|
|
|
|
// Store the editor settings by the temporary ID?
|
|
if (editor && editor.settings && tempId) {
|
|
editorSettings[tempId] = editor.settings;
|
|
}
|
|
|
|
});
|
|
|
|
},
|
|
// This restores the rich text editors in the specified Archetype
|
|
// (e.g., after a drop drop operation).
|
|
restoreEditors: function(element) {
|
|
|
|
// If there are not tinyMCE editors, this may be undefined.
|
|
if (typeof tinyMCE === "undefined") {
|
|
return;
|
|
}
|
|
|
|
// Variables.
|
|
var bothElements = element
|
|
? element.add(draggedRteArchetype)
|
|
: draggedRteArchetype;
|
|
var self = this;
|
|
|
|
// Process each RTE in both Archetypes.
|
|
$(rteClass, bothElements).each(function () {
|
|
|
|
// Variables.
|
|
var id = $(this).attr("id");
|
|
|
|
// Get the stored editor settings.
|
|
var scope = angular.element(this).scope().$parent;
|
|
var property = self.getFieldsetProperty(scope);
|
|
var tempId = property ? property.editorState.temporaryId : null;
|
|
var settings = editorSettings[tempId];
|
|
|
|
// Remove and reinitialize the editor.
|
|
if (settings) {
|
|
tinyMCE.execCommand("mceRemoveEditor", false, id);
|
|
tinyMCE.init(settings);
|
|
}
|
|
|
|
});
|
|
|
|
},
|
|
// Ensures the specified property has a temporary ID in its editor state,
|
|
// optionally forcing one to be regenerated (if specified).
|
|
ensureTemporaryId: function(property, regenerateId) {
|
|
if (!property.editorState) {
|
|
property.editorState = {};
|
|
}
|
|
var editorState = property.editorState;
|
|
if (!editorState.temporaryId || regenerateId) {
|
|
editorState.temporaryId = _.uniqueId("property-temp-id-");
|
|
}
|
|
},
|
|
// Remembers a sortable that has been disabled (so it can be enabled later).
|
|
rememberDisabledSortable: function(sortable) {
|
|
disabledSortables.push(sortable);
|
|
},
|
|
// Enables all of the sortables that were disabled.
|
|
enableSortables: function() {
|
|
_.each(disabledSortables, function(sortable) {
|
|
sortable.enable();
|
|
});
|
|
disabledSortables = [];
|
|
},
|
|
// Get all active archetype editors on the current page
|
|
getEditors: function() {
|
|
if (archetypeEditors == null) {
|
|
archetypeEditors = $('.archetypeEditor');
|
|
}
|
|
return archetypeEditors;
|
|
}
|
|
}
|
|
}); |