All Downloads are FREE. Search and download functionalities are using the official Maven repository.

structr.js.entities.js Maven / Gradle / Ivy

Go to download

Structr is an open source framework based on the popular Neo4j graph database.

The newest version!
/*
 * Copyright (C) 2010-2016 Structr GmbH
 *
 * This file is part of Structr .
 *
 * Structr is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Structr is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Structr.  If not, see .
 */
var buttonClicked;
var activeElements = {};
var activeQueryTabPrefix = 'structrActiveQueryTab_' + port;
var activeEditTabPrefix = 'structrActiveEditTab_' + port;

var _Entities = {
	numberAttrs: ['position', 'size'],
	hiddenAttrs: ['base'], //'deleted', 'ownerId', 'owner', 'group', 'categories', 'tag', 'createdBy', 'visibilityStartDate', 'visibilityEndDate', 'parentFolder', 'url', 'path', 'elements', 'components', 'paths', 'parents'],
	readOnlyAttrs: ['lastModifiedDate', 'createdDate', 'createdBy', 'id', 'checksum', 'size', 'version', 'relativeFilePath'],
	changeBooleanAttribute: function(attrElement, value, activeLabel, inactiveLabel) {

		_Logger.log(_LogType.ENTITIES, 'Change boolean attribute ', attrElement, ' to ', value);

		if (value === true) {
			attrElement.removeClass('inactive').addClass('active').prop('checked', true).html('' + (activeLabel ? ' ' + activeLabel : ''));
		} else {
			attrElement.removeClass('active').addClass('inactive').prop('checked', false).text((inactiveLabel ? inactiveLabel : '-'));
		}

	},
	reloadChildren: function(id) {
		var el = Structr.node(id);

		_Logger.log(_LogType.ENTITIES, 'reloadChildren', el);

		$(el).children('.node').remove();
		_Entities.resetMouseOverState(el);

		Command.children(id);

	},
	deleteNode: function(button, entity, rec, callback) {
		buttonClicked = button;
		if (isDisabled(button))
			return;

		Structr.confirmation('

Delete ' + entity.type + ' \'' + entity.name + '\' [' + entity.id + ']' + (rec ? ' recursively' : '') + '?

', function() { Command.deleteNode(entity.id, rec); $.unblockUI({ fadeOut: 25 }); if (callback) { callback(entity); } }); }, showSyncDialog: function(source, target) { Structr.dialog('Sync between ' + source.id + ' and ' + target.id, function() { return true; }, function() { return true; }); dialog.append('
'); dialog.append('
'); dialog.append('
'); $('input[name=syncMode]:radio', dialog).on('change', function() { Command.setSyncMode(source.id, target.id, $(this).val()); }); }, dataBindingDialog: function(entity, el) { el.append('
'); var t = $('.props', el); // General _Entities.appendRowWithInputField(entity, t, 'data-structr-id', 'Element ID (set to ${this.id})'); _Entities.appendRowWithInputField(entity, t, 'data-structr-attr', 'Attribute Key (if set, render input field in edit mode)'); _Entities.appendRowWithInputField(entity, t, 'data-structr-type', 'Data type (e.g. Date, Boolean; default: String)'); _Entities.appendRowWithInputField(entity, t, 'data-structr-placeholder', 'Placeholder text in edit mode'); _Entities.appendRowWithInputField(entity, t, 'data-structr-custom-options-query', 'Custom REST query for value options'); _Entities.appendRowWithInputField(entity, t, 'data-structr-options-key', 'Attribute key used to display option labels (default: name)'); _Entities.appendRowWithInputField(entity, t, 'data-structr-raw-value', 'Raw value (unformatted value for Date or Number fields)'); _Entities.appendRowWithInputField(entity, t, 'data-structr-hide', 'Hide [edit|non-edit|edit,non-edit]'); _Entities.appendRowWithInputField(entity, t, 'data-structr-edit-class', 'Custom CSS class in edit mode'); if (entity.type === 'Button' || entity.type === 'A') { // Buttons _Entities.appendRowWithInputField(entity, t, 'data-structr-action', 'Action [create:<Type>|delete:<Type>|edit|login|logout]'); _Entities.appendRowWithInputField(entity, t, 'data-structr-attributes', 'Attributes (for create, edit, login or registration actions)'); t.append('Reload'); _Entities.appendBooleanSwitch($('#reload', t), entity, 'data-structr-reload', '', 'If active, the page will refresh after a successfull action.'); // Confirm action? t.append('Confirm action?'); _Entities.appendBooleanSwitch($('#confirmOnDel', t), entity, 'data-structr-confirm', '', 'If active, a user has to confirm the action.'); _Entities.appendRowWithInputField(entity, t, 'data-structr-return', 'Return URI after successful action'); t.append('Append ID on create'); _Entities.appendBooleanSwitch($('#append-id', t), entity, 'data-structr-append-id', '', 'On create, append ID of first created object to the return URI.'); } else if (entity.type === 'Input' || entity.type === 'Select' || entity.type === 'Textarea') { // Input fields _Entities.appendRowWithInputField(entity, t, 'data-structr-name', 'Field name (for create action)'); } // _Entities.appendBooleanSwitch(el, entity, 'hideOnEdit', 'Hide in edit mode', 'If active, this node will not be visible in edit mode.'); // _Entities.appendBooleanSwitch(el, entity, 'hideOnNonEdit', 'Hide in non-edit mode', 'If active, this node will not be visible in default (non-edit) mode.'); //_Entities.appendInput(dialog, entity, 'partialUpdateKey', 'Types to trigger partial update', ''); }, appendRowWithInputField: function(entity, el, key, label) { el.append('' + label + ''); var inp = $('[name="' + key + '"]', el); _Entities.activateInput(inp, entity.id); var nullIcon = $('#null_' + key, el); nullIcon.on('click', function() { Command.setProperty(entity.id, key, null, false, function() { inp.val(null); blinkGreen(inp); dialogMsg.html('
Property "' + key + '" was set to null.
'); $('.infoBox', dialogMsg).delay(2000).fadeOut(1000); }); }); }, queryDialog: function(entity, el) { el.append('
'); var t = $('.props', el); t.append('Query auto-limit'); t.append('Hide in index mode'); t.append('Hide in details mode'); _Entities.appendBooleanSwitch($('#queryAutoLimit', t), entity, 'renderDetails', ['Query is limited', 'Query is not limited'], 'Limit result to the object with the ID the URL ends with.'); _Entities.appendBooleanSwitch($('#hideIndexMode', t), entity, 'hideOnIndex', ['Hidden in index mode', 'Visible in index mode'], 'if URL does not end with an ID'); _Entities.appendBooleanSwitch($('#hideDetailsMode', t), entity, 'hideOnDetail', ['Hidden in details mode', 'Visible in details mode'], 'if URL ends with an ID.'); el.append('
  • REST Query
  • Cypher Query
  • XPath Query
  • Function Query
' + '
'); _Entities.appendTextarea($('#content-tab-rest'), entity, 'restQuery', 'REST Query', ''); _Entities.appendTextarea($('#content-tab-cypher'), entity, 'cypherQuery', 'Cypher Query', ''); _Entities.appendTextarea($('#content-tab-xpath'), entity, 'xpathQuery', 'XPath Query', ''); _Entities.appendTextarea($('#content-tab-function'), entity, 'functionQuery', 'Function Query', ''); _Entities.appendInput(el, entity, 'dataKey', 'Data Key', 'The data key is either a word to reference result objects, or it can be the name of a collection property of the result object.
' + 'You can access result objects or the objects of the collection using ${<dataKey>.<propertyKey>}'); _Entities.activateTabs(entity.id, '#data-tabs', '#content-tab-rest'); //_Entities.appendInput(dialog, entity, 'partialUpdateKey', 'Types to trigger partial update', ''); }, activateTabs: function(nodeId, elId, activeId) { var el = $(elId); var tabs = $('li', el); $.each(tabs, function(i, tab) { $(tab).on('click', function() { var tab = $(this); tabs.removeClass('active'); tab.addClass('active'); el.children('div').hide(); var id = tab.prop('id').substring(4); LSWrapper.setItem(activeQueryTabPrefix + '_' + nodeId, id); var content = $('#content-tab-' + id); content.show(); }); }); var id = LSWrapper.getItem(activeQueryTabPrefix + '_' + nodeId) || activeId.substring(13); var tab = $('#tab-' + id); if (!tab.hasClass('active')) { tab.click(); } }, editSource: function(entity) { Structr.dialog('Edit source of "' + (entity.name ? entity.name : entity.id) + '"', function () { _Logger.log(_LogType.ENTITIES, 'Element source saved'); }, function () { _Logger.log(_LogType.ENTITIES, 'cancelled'); }); // Get content in widget mode var url = viewRootUrl + entity.id + '?edit=3', contentType = 'text/html'; $.ajax({ url: url, //async: false, contentType: contentType, success: function(data) { text = data; text = text.replace(/]*>/, ''); var startTag = text.replace(/(<[^>]*>)([^]*)(<\/[^>]*>)/, '$1').replace(/^\s+|\s+$/g, ''); var innerText = text.replace(/(<[^>]*>)([^]*)(<\/[^>]*>)/, '$2').replace(/^\s+|\s+$/g, ''); var endTag = text.replace(/(<[^>]*>)([^]*)(<\/[^>]*>)/, '$3').replace(/^\s+|\s+$/g, ''); text = innerText; dialog.append('
'); var contentBox = $('.editor', dialog); var lineWrapping = LSWrapper.getItem(lineWrappingKey); // Intitialize editor editor = CodeMirror(contentBox.get(0), { value: unescapeTags(innerText), mode: contentType, lineNumbers: true, lineWrapping: lineWrapping, indentUnit: 4, tabSize:4, indentWithTabs: true }); $('.CodeMirror-scroll').prepend('
'); $('.CodeMirror-scroll').append('
'); $('.starttag', dialog).append(escapeTags(startTag.replace(/\sdata-structr-hash=".{32}"/, ""))); $('.endtag', dialog).append(escapeTags(endTag)); editor.id = entity.id; dialogBtn.append(''); dialogBtn.append(''); dialogSaveButton = $('#saveFile', dialogBtn); saveAndClose = $('#saveAndClose', dialogBtn); editor.on('scroll', function() { _Entities.hideDataHashAttribute(editor); }); editor.on('change', function(cm, change) { //text1 = $(contentNode).children('.content_').text(); text2 = editor.getValue(); //console.log(text, text2, text === text2); if (text === text2) { dialogSaveButton.prop("disabled", true).addClass('disabled'); saveAndClose.prop("disabled", true).addClass('disabled'); } else { dialogSaveButton.prop("disabled", false).removeClass('disabled'); saveAndClose.prop("disabled", false).removeClass('disabled'); } _Entities.hideDataHashAttribute(editor); }); dialogSaveButton.on('click', function(e) { e.stopPropagation(); text2 = editor.getValue(); //console.log(text, text2, text === text2); if (text === text2) { dialogSaveButton.prop("disabled", true).addClass('disabled'); saveAndClose.prop("disabled", true).addClass('disabled'); } else { dialogSaveButton.prop("disabled", false).removeClass('disabled'); saveAndClose.prop("disabled", false).removeClass('disabled'); } Command.saveNode(startTag + editor.getValue() + endTag, entity.id, function() { $.ajax({ url: url, contentType: contentType, success: function(data) { text = unescapeTags(data).replace(/]*>/, ''); text = text.replace(/(<[^>]*>)([^]*)(<\/[^>]*>)/, '$2').replace(/^\s+|\s+$/g, ''); editor.setValue(text); dialogSaveButton.prop("disabled", true).addClass('disabled'); saveAndClose.prop("disabled", true).addClass('disabled'); dialogMsg.html('
Node source saved and DOM tree rebuilt.
'); $('.infoBox', dialogMsg).delay(2000).fadeOut(200); if (_Entities.isExpanded(Structr.node(entity.id))) { $('.expand_icon', Structr.node(entity.id)).click().click(); } } }); }); }); saveAndClose.on('click', function(e) { e.stopPropagation(); dialogSaveButton.click(); setTimeout(function() { dialogSaveButton.remove(); saveAndClose.remove(); dialogCancelButton.click(); }, 500); }); dialogMeta.append(' '); $('#lineWrapping').on('change', function() { var inp = $(this); if (inp.is(':checked')) { LSWrapper.setItem(lineWrappingKey, "1"); editor.setOption('lineWrapping', true); } else { LSWrapper.removeItem(lineWrappingKey); editor.setOption('lineWrapping', false); } editor.refresh(); }); Structr.resize(); _Entities.hideDataHashAttribute(editor); }, error: function(xhr, statusText, error) { console.log(xhr, statusText, error); } }); }, hideDataHashAttribute: function(editor) { var sc = editor.getSearchCursor(/\sdata-structr-hash=".{32}"/); while (sc.findNext()) { editor.markText(sc.from(), sc.to(), {className: 'data-structr-hash', collapsed: true, inclusiveLeft: true}); } }, showProperties: function(obj, activeViewOverride) { Command.get(obj.id, function (entity) { var views, activeView = 'ui'; var isRelationship = false; var tabTexts = []; if (activeViewOverride) { activeView = activeViewOverride; } if (entity.hasOwnProperty('relType')) { isRelationship = true; views = ['ui'];//, 'sourceNode', 'targetNode']; tabTexts.ui = 'Relationship Properties'; tabTexts.sourceNode = 'Source Node Properties'; tabTexts.targetNode = 'Target Node Properties'; Structr.dialog('Edit Properties of ' + (entity.type ? entity.type : '') + (isRelationship ? ' relationship ' : ' node ') + (entity.name ? entity.name : entity.id), function() { return true; }, function() { return true; }); var tabsdiv = dialogHead.append('
'); var mainTabs = tabsdiv.append('
    '); var contentEl = dialog.append('
    '); _Entities.appendViews(entity, views, tabTexts, mainTabs, contentEl, activeView); } else { views = ['ui', 'in', 'out']; var hasHtmlAttributes = entity.isDOMNode; if (hasHtmlAttributes && !entity.isContent) { views.unshift('_html_'); //console.log(lastMenuEntry) if (lastMenuEntry === 'pages') { activeView = '_html_'; } } tabTexts._html_ = 'HTML Attributes'; tabTexts.ui = 'Node Properties'; tabTexts.in = 'Incoming Relationships'; tabTexts.out = 'Outgoing Relationships'; Structr.dialog('Edit Properties of ' + (entity.type ? entity.type : '') + (isRelationship ? ' relationship ' : ' node ') + (entity.name ? entity.name : entity.id), function() { return true; }, function() { return true; }); var tabsdiv = dialogHead.append('
    '); var mainTabs = tabsdiv.append('
      '); var contentEl = dialog.append('
      '); if (hasHtmlAttributes) { _Entities.appendPropTab(entity, mainTabs, contentEl, 'query', 'Query and Data Binding', true, function(c) { _Entities.queryDialog(entity, c); }); _Entities.appendPropTab(entity, mainTabs, contentEl, 'editBinding', 'Edit Mode Binding', false, function(c) { _Entities.dataBindingDialog(entity, c); }); } _Entities.appendViews(entity, views, tabTexts, mainTabs, contentEl, activeView, activeViewOverride); } Structr.resize(); }); }, appendPropTab: function(entity, tabsEl, contentEl, name, label, active, callback) { var ul = tabsEl.children('ul'); ul.append('
    • ' + label + '
    • '); var tab = $('#tab-' + name + ''); if (active) { tab.addClass('active'); } tab.on('click', function(e) { e.stopPropagation(); var self = $(this); $('.propTabContent').hide(); $('li', ul).removeClass('active'); contentEl.append('
      '); $('#tabView-' + name).show(); self.addClass('active'); LSWrapper.setItem(activeEditTabPrefix + '_' + entity.id, name); }); contentEl.append('
      '); var content = $('#tabView-' + name); if (active) { content.show(); } if (callback) { callback(content); } return content; }, appendViews: function(entity, views, texts, tabsEl, contentEl, activeView, activeViewOverride) { var ul = tabsEl.children('ul'); $(views).each(function(i, view) { var tabText = texts[view]; ul.append('
    • ' + tabText + '
    • '); contentEl.append('
      '); var tab = $('#tab-' + view); tab.on('click', function(e) { e.stopPropagation(); var self = $(this); contentEl.children('div').hide(); $('li', ul).removeClass('active'); self.addClass('active'); var tabView = $('#tabView-' + view); fastRemoveAllChildren(tabView[0]); tabView.show(); LSWrapper.setItem(activeEditTabPrefix + '_' + entity.id, view); $.ajax({ url: rootUrl + '_schema/' + entity.type + '/ui', dataType: 'json', contentType: 'application/json; charset=utf-8', success: function(data) { var typeInfo = {}; $(data.result).each(function(i, prop) { typeInfo[prop.jsonName] = prop; }); _Entities.listProperties(entity, view, tabView, typeInfo); } }); }); }); activeView = activeViewOverride || LSWrapper.getItem(activeEditTabPrefix + '_' + entity.id) || activeView; $('#tab-' + activeView).click(); }, listProperties: function (entity, view, tabView, typeInfo) { var null_prefix = 'null_attr_'; $.ajax({ url: rootUrl + entity.id + (view ? '/' + view : '') + '?pageSize=10', // TODO: Implement paging or scroll-into-view here dataType: 'json', contentType: 'application/json; charset=utf-8', success: function(data) { // Default: Edit node id var id = entity.id; // ID of graph object to edit $(data.result).each(function(i, res) { // reset id for each object group id = entity.id; var keys = Object.keys(res); tabView.append('
      '); var props = $('.props.' + view + '.' + res['id'] + '_', tabView); var focusAttr = 'class'; if (view === '_html_') { keys.sort(); } $(keys).each(function(i, key) { if (view === '_html_') { var display = false; _Elements.mostUsedAttrs.forEach(function(mostUsed) { if (isIn(entity.tag, mostUsed.elements) && isIn(key.substring(6), mostUsed.attrs)) { display = true; focusAttr = mostUsed.focus ? mostUsed.focus : focusAttr; } }); // Always show non-empty, non 'data-structr-' attributes if (res[key] !== null && key.indexOf('data-structr-') !== 0) { display = true; } if (display || key === '_html_class' || key === '_html_id') { props.append('' + key.replace(view, '') + '' + '' + formatValueInputField(key, res[key]) + ''); } else if (key !== 'id') { props.append('' + key.replace(view, '') + '' + '' + formatValueInputField(key, res[key]) + ''); } } else if (view === 'in' || view === 'out') { if (key === 'id') { // set ID to rel ID id = res[key]; } props.append('' + key + '' + formatValueInputField(key, res[key]) + ''); } else { props.append('' + formatKey(key) + ''); var cell = $('.value.' + key + '_', props); if (!typeInfo[key]) { cell.append(formatValueInputField(key, res[key], isPassword, isReadOnly)); } else { var type = typeInfo[key].type; var isHidden = isIn(key, _Entities.hiddenAttrs); var isReadOnly = isIn(key, _Entities.readOnlyAttrs) || (typeInfo[key].readOnly); var isSystem = typeInfo[key].system; if (type) { var isBoolean = (type === 'Boolean'); //typeInfo[key].className === 'org.structr.core.property.BooleanProperty'; //isIn(key, _Entities.booleanAttrs); var isDate = (type === 'Date'); //typeInfo[key].className === 'org.structr.core.property.ISO8601DateProperty'; //isIn(key, _Entities.dateAttrs); var isPassword = (typeInfo[key].className === 'org.structr.core.property.PasswordProperty'); var isRelated = typeInfo[key].relatedType; } if (!key.startsWith('_html_') && !isHidden) { if (isBoolean) { cell.removeClass('value').append(''); var checkbox = $(props.find('input[type="checkbox"].' + key + '_')); Command.getProperty(id, key, function(val) { if (val) { checkbox.prop('checked', true); } if ((!isReadOnly || isAdmin) && !isSystem) { checkbox.on('change', function() { var checked = checkbox.prop('checked'); _Entities.setProperty(id, key, checked, false, function(newVal) { if (val !== newVal) { blinkGreen(cell); } checkbox.prop('checked', newVal); val = newVal; }); }); } else { checkbox.prop('disabled', 'disabled'); checkbox.addClass('readOnly'); checkbox.addClass('disabled'); } }); } else if (isDate && !isReadOnly) { if (!res[key] || res[key] === 'null') { res[key] = ''; } cell.append(''); var dateField = $(props.find('.dateField')); var dateTimePickerFormat = getDateTimePickerFormat(typeInfo[key].format); dateField.datetimepicker({ dateFormat: dateTimePickerFormat.dateFormat, timeFormat: dateTimePickerFormat.timeFormat, separator: dateTimePickerFormat.separator }); } else if (isRelated && res[key] && (res[key].constructor === Object || res[key].constructor === Array)) { if (res[key] && res[key].constructor === Object) { _Entities.appendRelatedNode(cell, props, id, key, res[key], function(nodeEl) { $('.remove', nodeEl).on('click', function(e) { e.preventDefault(); _Entities.setProperty(id, key, null, false, function(newVal) { if (!newVal) { blinkGreen(cell); dialogMsg.html('
      Related node "' + displayName + '" was removed from property "' + key + '".
      '); $('.infoBox', dialogMsg).delay(2000).fadeOut(1000); cell.empty(); } else { blinkRed(cell); } }); return false; }); }); } else if (res[key] && res[key].constructor === Array) { res[key].forEach(function(node) { _Entities.appendRelatedNode(cell, props, id, key, node, function(nodeEl) { $('.remove', nodeEl).on('click', function(e) { e.preventDefault(); Command.removeFromCollection(id, key, node.id, function() { nodeEl.remove(); blinkGreen(cell); }); return false; }); }); }); } } else { cell.append(formatValueInputField(key, res[key], isPassword, isReadOnly)); } } } } var nullIcon = $('#' + null_prefix + key); nullIcon.on('click', function() { var key = $(this).prop('id').substring(null_prefix.length); var input = $('.' + key + '_').find('input'); _Entities.setProperty(id, key, null, false, function(newVal) { if (!newVal) { blinkGreen(cell); dialogMsg.html('
      Property "' + key + '" was set to null.
      '); $('.infoBox', dialogMsg).delay(2000).fadeOut(1000); if (key === 'name') { var entity = StructrModel.objects[id]; if (entity.type !== 'Template' && entity.type !== 'Content') { entity.name = entity.tag ? entity.tag : '[' + entity.type + ']'; } StructrModel.refresh(id); } if (isRelated) { cell.empty(); } } else { blinkRed(input); } if (!isRelated) { input.val(newVal); } }); }); }); props.append(''); $('.props tr td.value input', dialog).each(function(i, v) { _Entities.activateInput(v, id); }); if (view === '_html_') { $('input[name="_html_' + focusAttr + '"]', props).focus(); tabView.append(''); $('.show-all', tabView).on('click', function() { $('tr.hidden').toggle(); $(this).remove(); }); } }); } }); }, appendRelatedNode: function(cell, props, id, key, node, onDelete) { var displayName = _Crud.displayName(node); cell.append('
      ' + fitStringToWidth(displayName, 80) + '
      '); var nodeEl = $('#_' + node.id, props); nodeEl.on('click', function(e) { e.preventDefault(); _Entities.showProperties(node); return false; }); if (onDelete) { return onDelete(nodeEl); } }, activateInput: function(el, id) { var input = $(el); var oldVal = input.val(); var relId = input.parent().attr('rel_id'); if (!input.hasClass('readonly') && !input.hasClass('newKey')) { input.on('focus', function() { input.addClass('active'); }); input.on('change', function() { input.data('changed', true); _Pages.reloadPreviews(); }); input.on('focusout', function() { _Logger.log(_LogType.ENTITIES, 'relId', relId); var objId = relId ? relId : id; _Logger.log(_LogType.ENTITIES, 'set properties of obj', objId); var keyInput = input.parent().parent().children('td').first().children('input'); _Logger.log(_LogType.ENTITIES, keyInput); if (keyInput && keyInput.length) { var newKey = keyInput.val(); var val = input.val(); // new key _Logger.log(_LogType.ENTITIES, 'new key: Command.setProperty(', objId, newKey, val); Command.setProperty(objId, newKey, val, false, function() { blinkGreen(input); dialogMsg.html('
      New property "' + newKey + '" was added and saved with value "' + val + '".
      '); $('.infoBox', dialogMsg).delay(2000).fadeOut(1000); }); } else { var key = input.prop('name'); var val = input.val(); var isPassword = input.prop('type') === 'password'; if (input.data('changed')) { input.data('changed', false); _Logger.log(_LogType.ENTITIES, 'existing key: Command.setProperty(', objId, key, val); _Entities.setProperty(objId, key, val, false, function(newVal) { if (isPassword || (newVal && newVal !== oldVal)) { blinkGreen(input); input.val(newVal); dialogMsg.html('
      Updated property "' + key + '"' + (!isPassword ? ' with value "' + newVal + '".
      ' : '')); $('.infoBox', dialogMsg).delay(2000).fadeOut(200); } else { input.val(oldVal); } oldVal = newVal; }); } } input.removeClass('active'); input.parent().children('.icon').each(function(i, img) { $(img).remove(); }); }); } }, setProperty: function(id, key, val, recursive, callback) { Command.setProperty(id, key, val, recursive, function() { Command.getProperty(id, key, callback); }); }, appendAccessControlIcon: function(parent, entity) { var protected = !entity.visibleToPublicUsers || !entity.visibleToAuthenticatedUsers; var keyIcon = $('.key_icon', parent); var newKeyIcon = 'Access Control and Visibility'; if (!(keyIcon && keyIcon.length)) { parent.append(newKeyIcon); keyIcon = $('.key_icon', parent); if (protected) { keyIcon.show(); keyIcon.addClass('donthide'); } _Entities.bindAccessControl(keyIcon, entity.id); } }, bindAccessControl: function(btn, id) { btn.on('click', function(e) { e.stopPropagation(); _Entities.showAccessControlDialog(id); }); }, showAccessControlDialog: function(id) { Structr.dialog('Access Control and Visibility', function() { }, function() { Command.get(id, function(entity) { _Crud.refreshRow(id, entity, entity.type); }); }); Command.get(id, function(entity) { _Entities.appendSimpleSelection(dialogText, entity, 'users', 'Owner', 'owner.id'); dialogText.append('

      Visibility

      '); //('
      '); if (entity.type === 'Template' || entity.isFolder || (lastMenuEntry === 'pages' && !(entity.isContent))) { dialogText.append('
      Apply visibility switches recursively?

      '); } _Entities.appendBooleanSwitch(dialogText, entity, 'visibleToPublicUsers', ['Visible to public users', 'Not visible to public users'], 'Click to toggle visibility for users not logged-in', '#recursive'); _Entities.appendBooleanSwitch(dialogText, entity, 'visibleToAuthenticatedUsers', ['Visible to auth. users', 'Not visible to auth. users'], 'Click to toggle visibility to logged-in users', '#recursive'); dialogText.append('

      Access Rights

      '); dialogText.append(''); $.ajax({ url: rootUrl + '/' + entity.id + '/in', dataType: 'json', contentType: 'application/json; charset=utf-8', success: function(data) { $(data.result).each(function(i, result) { var permissions = { 'read': isIn('read', result.allowed), 'write': isIn('write', result.allowed), 'delete': isIn('delete', result.allowed), 'accessControl': isIn('accessControl', result.allowed) }; var principalId = result.principalId; if (principalId) { Command.get(principalId, function(p) { addPrincipal(entity, p, permissions); }); } }); } }); var select = $('#newPrincipal'); select.chosen({width: '90%'}); var i = 0, n = 10000; Command.getByType('Group', n, 1, 'name', 'asc', 'id,name', false, function(groups) { groups.forEach(function(group) { select.append(''); }); select.trigger("chosen:updated"); }); i = 0; var al2 = Structr.loaderIcon(select.parent(), {float: 'right'}); Command.getByType('User', n, 1, 'name', 'asc', 'id,name', false, function(users) { users.forEach(function(user) { select.append(''); }); select.trigger("chosen:updated"); if (al2.length) al2.remove(); }); select.on('change', function() { var sel = $(this); var pId = sel[0].value; var rec = $('#recursive', dialogText).is(':checked'); Command.setPermission(entity.id, pId, 'grant', 'read', rec); $('#new', tb).selectedIndex = 0; Command.get(pId, function(p) { addPrincipal(entity, p, {'read': true}); }); }); }); }, appendTextarea: function(el, entity, key, label, desc) { if (!el || !entity) { return false; } el.append('

      ' + label + '

      ' + desc + '

      '); el.append('
      '); var btn = $('.apply_' + key, el); btn.on('click', function() { Command.setProperty(entity.id, key, $('.' + key + '_', el).val(), false, function(obj) { _Logger.log(_LogType.ENTITIES, key + ' successfully updated!', obj[key]); blinkGreen(btn); _Pages.reloadPreviews(); }); }); }, appendInput: function(el, entity, key, label, desc) { if (!el || !entity) { return false; } el.append('

      ' + label + '

      ' + desc + '

      '); var btn = $('.save_' + key, el); btn.on('click', function() { Command.setProperty(entity.id, key, $('.' + key + '_', el).val(), false, function(obj) { _Logger.log(_LogType.ENTITIES, key + ' successfully updated!', obj[key]); blinkGreen(btn); _Pages.reloadPreviews(); }); }); }, appendBooleanSwitch: function(el, entity, key, label, desc, recElementId) { if (!el || !entity) { return false; } el.append('
      ' + desc + '
      '); var sw = $('.' + key + '_', el); _Entities.changeBooleanAttribute(sw, entity[key], label[0], label[1]); sw.on('click', function(e) { e.stopPropagation(); Command.setProperty(entity.id, key, sw.hasClass('inactive'), $(recElementId, el).is(':checked'), function(obj) { if (obj.id !== entity.id) { return false; } _Entities.changeBooleanAttribute(sw, obj[key], label[0], label[1]); blinkGreen(sw); return true; }); }); }, appendSimpleSelection: function(el, entity, type, title, key) { var subKey; if (key.contains('.')) { subKey = key.substring(key.indexOf('.') + 1, key.length); key = key.substring(0, key.indexOf('.')); } el.append('

      ' + title + '

      '); var element = $('.' + key + 'Box', el); element.append(''); var selectElement = $('.' + key + 'Select'); selectElement.append(''); selectElement.css({'width': '400px'}).chosen(); var id = (subKey && entity[key] ? entity[key][subKey] : entity[key]); var al = Structr.loaderIcon(el, {position: 'absolute', left: '416px', top: '32px'}); var n = 10000; Command.getByType(type, n, 1, 'name', 'asc', 'id,name', false, function (results) { results.forEach(function(result) { var selected = (id === result.id ? 'selected' : ''); selectElement.append(''); }); selectElement.trigger("chosen:updated"); if (al.length) al.remove(); }); selectElement.on('change', function() { var value = selectElement.val(); if (subKey) { entity[key][subKey] = value; } Command.setProperty(entity.id, key, value, false, function() { blinkGreen($('.' + key + 'Select_chosen .chosen-single')); }); }); }, appendEditSourceIcon: function(parent, entity) { if (entity.tag === 'html' || entity.tag === 'body' || entity.tag === 'head' || entity.tag === 'title' || entity.tag === 'script' || entity.tag === 'input' || entity.tag === 'label' || entity.tag === 'button' || entity.tag === 'textarea' || entity.tag === 'link' || entity.tag === 'meta' || entity.tag === 'noscript' || entity.tag === 'tbody' || entity.tag === 'thead' || entity.tag === 'tr' || entity.tag === 'td' || entity.tag === 'caption' || entity.tag === 'colgroup' || entity.tag === 'tfoot' || entity.tag === 'col') { return; } var editIcon = $('.edit_icon', parent); if (!(editIcon && editIcon.length)) { parent.append('Edit source code'); editIcon = $('.edit_icon', parent); } editIcon.on('click', function(e) { e.stopPropagation(); _Logger.log(_LogType.ENTITIES, 'editSource', entity); _Entities.editSource(entity); }); }, appendEditPropertiesIcon: function(parent, entity, visible) { var editIcon = $('.edit_props_icon', parent); if (!(editIcon && editIcon.length)) { parent.append('Edit Properties'); editIcon = $('.edit_props_icon', parent); } editIcon.on('click', function(e) { e.stopPropagation(); _Logger.log(_LogType.ENTITIES, 'showProperties', entity); _Entities.showProperties(entity); }); if (visible) { editIcon.css({ visibility: 'visible', display: 'inline-block' }); } return editIcon; }, appendCollapseChildrenIcon: function(parent, entity, visible) { var collapseChildrenIcon = $('.collapse_children_icon', parent); if (!(collapseChildrenIcon && collapseChildrenIcon.length)) { parent.append('Collapse Children'); collapseChildrenIcon = $('.collapse_children_icon', parent); } collapseChildrenIcon.on('click', function(e) { }); if (visible) { collapseChildrenIcon.css({ visibility: 'visible', display: 'inline-block' }); } return collapseChildrenIcon; }, appendDataIcon: function(parent, entity) { var dataIcon = $('.data_icon', parent); if (!(dataIcon && dataIcon.length)) { parent.append('Edit Data Settings'); dataIcon = $('.data_icon', parent); } dataIcon.on('click', function(e) { e.stopPropagation(); _Logger.log(_LogType.ENTITIES, 'showDataDialog', entity); _Entities.showDataDialog(entity); }); }, appendExpandIcon: function(el, entity, hasChildren, expand) { _Logger.log(_LogType.ENTITIES, '_Entities.appendExpandIcon', el, entity, hasChildren, expand); var button = $(el.children('.expand_icon').first()); if (button && button.length) { _Logger.log(_LogType.ENTITIES, 'Expand icon already existing', el, button); return; } if (hasChildren) { _Logger.log(_LogType.ENTITIES, 'appendExpandIcon hasChildren?', hasChildren, 'expand?', expand); var typeIcon = $(el.children('.typeIcon').first()); var icon = expand ? Structr.expanded_icon : Structr.expand_icon; var displayName = getElementDisplayName(entity); typeIcon.css({ paddingRight: 0 + 'px' }).after('Expand ' + displayName + ''); $(el).on('click', function(e) { e.stopPropagation(); _Entities.toggleElement(this); }); button = $(el.children('.expand_icon').first()); if (button) { button.on('click', function(e) { e.stopPropagation(); _Entities.toggleElement($(this).parent('.node')); }); // Prevent expand icon from being draggable button.on('mousedown', function(e) { e.stopPropagation(); }); if (expand) { _Entities.ensureExpanded(el); } } } else { el.children('.typeIcon').css({ paddingRight: 11 + 'px' }); } }, removeExpandIcon: function(el) { if (!el) return; _Logger.log(_LogType.ENTITIES, 'removeExpandIcon', el); var button = $(el.children('.expand_icon').first()); // unregister click handlers $(el).off('click'); $(button).off('click'); button.remove(); el.children('.typeIcon').css({ paddingRight: 11 + 'px' }); }, makeSelectable: function(el) { var node = $(el).closest('.node'); if (!node || !node.children) { return; } node.on('click', function() { $(this).toggleClass('selected'); }); }, setMouseOver: function(el, allowClick, syncedNodes) { var node = $(el).closest('.node'); if (!node || !node.children) { return; } if (!allowClick) { node.on('click', function(e) { e.stopPropagation(); return false; }); } node.children('b.name_').on('click', function(e) { e.stopPropagation(); _Entities.makeNameEditable(node); }); var nodeId = Structr.getId(el), isComponent; if (nodeId === undefined) { nodeId = Structr.getComponentId(el); if (nodeId) { isComponent = true; } else { nodeId = Structr.getActiveElementId(el); } } node.on({ mouseover: function(e) { e.stopPropagation(); var self = $(this); $('#componentId_' + nodeId).addClass('nodeHover'); if (isComponent) { $('#id_' + nodeId).addClass('nodeHover'); } if (syncedNodes && syncedNodes.length) { syncedNodes.forEach(function(s) { $('#id_' + s).addClass('nodeHover'); $('#componentId_' + s).addClass('nodeHover'); }); } var page = $(el).closest('.page'); if (page.length) { try { $('#preview_' + Structr.getId(page)).contents().find('[data-structr-id=' + nodeId + ']').addClass('nodeHover'); } catch (e) {} } self.addClass('nodeHover').children('img.button').show().css('display', 'inline-block'); self.children('.icons').children('img.button').show(); }, mouseout: function(e) { e.stopPropagation(); $('#componentId_' + nodeId).removeClass('nodeHover'); if (isComponent) { $('#id_' + nodeId).removeClass('nodeHover'); } if (syncedNodes && syncedNodes.length) { syncedNodes.forEach(function(s) { $('#id_' + s).removeClass('nodeHover'); $('#componentId_' + s).removeClass('nodeHover'); }); } _Entities.resetMouseOverState(this); } }); }, resetMouseOverState: function(element) { var el = $(element); var node = el.closest('.node'); if (node) { node.removeClass('nodeHover'); node.find('img.button').not('.donthide').hide().css('display', 'none'); } var page = node.closest('.page'); if (page.length) { //$('#preview_' + Structr.getId(page)).contents().find('[data-structr-id=' + Structr.getId(node) + ']').removeClass('nodeHover'); try { $('#preview_' + Structr.getId(page)).contents().find('[data-structr-id]').removeClass('nodeHover'); } catch (e) {} } }, isExpanded: function(element) { var b = $(element).children('.expand_icon').first(), src = b.prop('src'); if (!b || !src) { return false; } return src.endsWith('icon/tree_arrow_down.png'); }, ensureExpanded: function(element, callback) { if (!element) { return; } var el = $(element); var id = Structr.getId(el); if (!id) { return; } addExpandedNode(id); if (_Entities.isExpanded(element)) { return; } else { _Logger.log(_LogType.ENTITIES, 'ensureExpanded: fetch children', el); Command.children(id, callback); var displayName = getElementDisplayName(Structr.entity(id)); el.children('.expand_icon').first().prop('src', 'icon/tree_arrow_down.png') .prop('alt', 'Collapse ' + displayName) .prop('title', 'Collapse ' + displayName); } }, expandAll: function(ids) { if (!ids || ids.length === 0) { return; } ids.forEach(function(id) { var el = Structr.node(id); if (el) { $('.nodeSelected').removeClass('nodeSelected'); el.addClass('nodeSelected'); } _Entities.ensureExpanded(el, function(childNodes) { if (childNodes && childNodes.length) { var childNode = childNodes[0]; var i = ids.indexOf(childNode.id); if (i > 1) { ids.slice(i - 1, i); } _Entities.expandAll(ids); } }); }); }, toggleElement: function(element, expanded) { var el = $(element); var id = Structr.getId(el) || Structr.getComponentId(el); _Logger.log(_LogType.ENTITIES, 'toggleElement: ', el, id); var b = el.children('.expand_icon').first(); var displayName = getElementDisplayName(Structr.entity(id)); if (_Entities.isExpanded(element)) { $.each(el.children('.node'), function(i, child) { $(child).remove(); }); b.prop('src', 'icon/tree_arrow_right.png') .prop('alt', 'Expand ' + displayName) .prop('title', 'Expand ' + displayName); removeExpandedNode(id); } else { if (!expanded) { _Logger.log(_LogType.ENTITIES, 'toggleElement: fetch children', id); Command.children(id); } b.prop('src', 'icon/tree_arrow_down.png') .prop('alt', 'Collapse ' + displayName) .prop('title', 'Collapse ' + displayName); ; addExpandedNode(id); } }, makeNameEditable: function(element, width) { var w = width || 200; //element.off('dblclick'); //element.off('hover'); var oldName = $.trim(element.children('b.name_').attr('title')); element.children('b.name_').replaceWith(''); //element.find('.button').hide(); var input = $('input', element); input.focus().select(); input.on('blur', function() { var self = $(this); var newName = self.val(); self.replaceWith('' + fitStringToWidth(oldName, w) + ''); element.children('b.name_').on('click', function(e) { e.stopPropagation(); _Entities.makeNameEditable(element, w); }); Command.setProperty(Structr.getId(element), "name", newName); _Pages.reloadPreviews(); }); input.keypress(function(e) { if (e.keyCode === 13) { var self = $(this); var newName = self.val(); self.replaceWith('' + fitStringToWidth(oldName, w) + ''); element.children('b.name_').on('click', function(e) { e.stopPropagation(); _Entities.makeNameEditable(element, w); }); Command.setProperty(Structr.getId(element), "name", newName); _Pages.reloadPreviews(); } }); //element.off('click'); }, handleActiveElement: function(entity) { if (entity) { var idString = 'id_' + entity.id; if (!activeElements.hasOwnProperty(idString)) { activeElements[idString] = entity; var parent = $('#activeElements div.inner'); var id = entity.id; if (entity.parentId) { parent = $('#active_' + entity.parentId); } parent.append('
      '); var div = $('#active_' + id); var query = entity.query; //var dataKey = (entity.dataKey.split(',')[entity.recursionDepth] || ''); var expand = entity.state === 'Query'; var icon = _Elements.icon; var name = '', content = '', action = ''; switch (entity.state) { case 'Query': icon = 'icon/database_table.png'; name = query || entity.dataKey.replace(',', '.'); break; case 'Content': icon = _Contents.icon; content = entity.content ? entity.content : entity.type; break; case 'Button': icon = 'icon/button.png'; action = entity.action; break; case 'Link': icon = 'icon/link.png'; content = entity.action; break; default: content = entity.state; } div.append('' + '' + fitStringToWidth(name, 180, 'slideOut') + '' + '' + (action ? action : ' ') + '' + '' + (content ? fitStringToWidth(content, 180, 'slideOut') : ' ') + '' + '' + entity.id + '' // + (entity._html_id ? '#' + entity._html_id.replace(/\${.*}/g, '${…}') + '' : '') // + (entity._html_class ? '.' + entity._html_class.replace(/\${.*}/g, '${…}').replace(/ /g, '.') + '' : '') ); _Entities.setMouseOver(div); var editIcon = $('.edit_icon', div); if (!(editIcon && editIcon.length)) { div.append('Edit'); editIcon = $('.edit_icon', div); } editIcon.on('click', function(e) { e.stopPropagation(); switch (entity.state) { case 'Query': _Entities.openQueryDialog(entity.id); break; case 'Content': _Contents.openEditContentDialog(this, entity); break; case 'Button': _Entities.openEditModeBindingDialog(entity.id); break; case 'Link': _Entities.showProperties(entity); break; default: _Entities.showProperties(entity); } }); $('b[title]', div).on('click', function() { _Entities.openQueryDialog(entity.id); }); $('.content_', div).on('click', function() { _Contents.openEditContentDialog(this, entity); }); $('.action', div).on('click', function() { _Entities.openEditModeBindingDialog(entity.id); }); var typeIcon = $(div.children('.typeIcon').first()); var padding = 0; var displayName = getElementDisplayName(entity); if (!expand) { padding = 11; } else { typeIcon.css({ paddingRight: padding + 'px' }).after('Expand ' + displayName + ''); } } } }, openQueryDialog: function(id) { Command.get(id, function(obj) { var entity = StructrModel.create(obj); Structr.dialog('Query and Data Binding of ' + (entity.name ? entity.name : entity.id), function() { return true; }, function() { return true; }); dialogText.append('

      '); _Entities.queryDialog(entity, dialogText); if (entity.restQuery) { _Entities.activateTabs(entity.id, '#data-tabs', '#content-tab-rest'); } else if (entity.cypherQuery) { _Entities.activateTabs(entity.id, '#data-tabs', '#content-tab-cypher'); } else if (entity.xpathQuery) { _Entities.activateTabs(entity.id, '#data-tabs', '#content-tab-xpath'); } else { _Entities.activateTabs(entity.id, '#data-tabs', '#content-tab-rest'); } }); }, openEditModeBindingDialog: function(id) { Command.get(id, function(obj) { var entity = StructrModel.create(obj); Structr.dialog('Edit mode binding for ' + (entity.name ? entity.name : entity.id), function() { return true; }, function() { return true; }); dialogText.append('

      '); _Entities.dataBindingDialog(entity, dialogText); }); } }; function addPrincipal(entity, principal, permissions) { $('#newPrincipal option[value="' + principal.id + '"]').remove(); $('#newPrincipal').trigger('chosen:updated'); $('#new').after(''); var row = $('._' + principal.id, dialogText); ['read', 'write', 'delete', 'accessControl'].forEach(function(perm) { row.append(''); var disabled = false; $('.' + perm, row).on('dblclick', function() { return false; }); $('.' + perm, row).on('click', function(e) { e.preventDefault(); if (disabled) return false; var sw = $(this); disabled = true; sw.prop('disabled', 'disabled'); window.setTimeout(function() { disabled = false; sw.prop('disabled', null); }, 200); if (!$('input:checked', row).length) { $('#newPrincipal').append('').trigger('chosen:updated'); row.remove(); } var rec = $('#recursive', dialogText).is(':checked'); Command.setPermission(entity.id, principal.id, permissions[perm] ? 'revoke' : 'grant', perm, rec, function() { permissions[perm] = !permissions[perm]; sw.prop('checked', permissions[perm]); _Logger.log(_LogType.ENTITIES, 'Permission successfully updated!'); blinkGreen(sw.parent()); }); }); }); } function formatValueInputField(key, obj, isPassword, isReadOnly) { if (obj === null) { return ''; } else if (obj.constructor === Object) { var node = obj; var displayName = _Crud.displayName(node); return '
      ' + fitStringToWidth(displayName, 80) + '
      '; //return ''; } else if (obj.constructor === Array) { var out = ''; $(obj).each(function(i, v) { out += formatValueInputField(key, v, isPassword, isReadOnly) + '
      '; }); return out; //return ''; } else { return ''; } }









      NameReadWriteDeleteAccess Control
      ' + principal.name + '