/* Template function which outputs an option in a chzn-select
* The replace() call is required to prevent xss attacks (see CVE-2019-12745)
* Using htmlspecialchars() in php isn't sufficient because, chzn_template_func
* will receive an unescaped string
* (see https://forums.select2.org/t/propperly-escape-option-value-to-prevent-xss/788)
*/
chzn_template_func = function (state) {
var subtitle = '';
if($(state.element).data('subtitle'))
subtitle = $(state.element).data('subtitle')+''; /* make sure it is a string */
var warning = '';
if($(state.element).data('warning'))
warning = $(state.element).data('warning')+''; /* make sure it is a string */
var html = '';
if($(state.element).data('before-title'))
html += $(state.element).data('before-title')+'';
if($(state.element).data('icon-before'))
html += ' ';
html += state.text.replace(/'+subtitle.replace(/';
if(warning)
html += '
'+warning+'';
html += '';
var $newstate = $(html);
return $newstate;
};
function escapeHtml(text) {
var map = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
return text.replace(/[&<>"']/g, function(m) { return map[m]; });
}
function treeFolderSelected(formid, nodeid, nodename) {
$('#'+formid).val(nodeid);
$('#choosefoldersearch'+formid).val(nodename);
$('#folderChooser'+formid).modal('hide');
}
function treeDocumentSelected(formid, nodeid, nodename) {
$('#'+formid).val(nodeid);
$('#choosedocsearch'+formid).val(nodename);
$('#docChooser'+formid).modal('hide');
}
function initMost() {
$('.datepicker, #expirationdate, #createstartdate, #createenddate, #expirationstartdate, #expirationenddate')
.datepicker({todayHighlight: true, toggleActive: true})
.on('changeDate', function(ev){
if(ev.date && $(ev.target).data('selectmenu')) {
$("#"+$(ev.target).data('selectmenu')).val('date');
}
$(ev.currentTarget).datepicker('hide');
});
$(".chzn-select").select2({
width: '100%',
templateResult: chzn_template_func//,
//templateSelection: chzn_template_func
});
/* change the color and length of the bar graph showing the password
* strength on each change to the passwod field.
*/
$(".pwd").passStrength({ /* {{{ */
url: seeddms_webroot+"op/op.Ajax.php",
onChange: function(data, target) {
pwsp = 100*data.score;
$('#'+target+' div.bar').width(pwsp+'%');
if(data.ok) {
$('#'+target+' div.bar').removeClass('bar-danger');
$('#'+target+' div.bar').addClass('bar-success');
} else {
$('#'+target+' div.bar').removeClass('bar-success');
$('#'+target+' div.bar').addClass('bar-danger');
}
}
}); /* }}} */
/* The typeahead functionality useѕ the modified version of
* bootstrap-typeahead, which is able to set the render function.
* This was needed because the search function return json objects
* for each hit and render could only process strings.
* */
$("#searchfield").typeahead({ /* {{{ */
minLength: 3,
items: 100, /* the query will limit the number of hits */
source: function(query, process) {
var d = new Date();
var pastYear = d.getFullYear() - 1;
d.setFullYear(pastYear);
// console.log(d.toISOString().split('T')[0]);
var data = {
query: query,
limit: 15,
action: 'typeahead'
};
/* Return a list of json objects, each containing
* type: type of object (D=doc, F=folder, S=searchterm)
* name: name of object
*/
$.get(seeddms_webroot+'out/out.Search.php', data, function(data) {
process(data);
});
},
/* updater is called when the item in the list is clicked. It is
* actually provided to update the input field, but here we use
* it to set the document location. The passed value is the string
* set in data-value of the list items.
* This method relies on some changes in bootstrap-typeahead.js
* Originally, update was passed only the data-value of the li item
* which is set in the render fuction below,
* but the modified version passes all data fields. which also
* contain the 'id' and 'type' (also set in render function).
**/
updater: function (item) {
if(item.id) {
if(item.type == 'D')
document.location = seeddms_webroot+"out/out.ViewDocument.php?documentid=" + item.id;
else
document.location = seeddms_webroot+"out/out.ViewFolder.php?folderid=" + item.id;
} else
document.location = seeddms_webroot+"out/out.Search.php?query=" + encodeURIComponent(item.value);
return item.value;
},
sorter: function(items) {
return items;
},
/* matcher will always return true, because the initial search returns
* matches only
*/
matcher : function (item) {
return true;
},
/* highlighter is for modifying the 'a' tag text. It places an icon
* in front of the name and replaces a '<' within the name with an
* entity.
**/
highlighter : function (item) {
if(item.type.charAt(0) == 'D')
return ' ' + item.name.replace(/' + item.path + '';
else if(item.type.charAt(0) == 'F')
return ' ' + item.name.replace(/' + item.path + '';
else
return ' ' + item.name.replace(/ 0 ? ' (' + item.occurences + ')' : '') + (typeof(item.column) != 'undefined' ? '
' + item.column + '' : '');
},
/* This only works with a modified version of bootstrap typeahead located
* in boostrap-typeahead.js Search for 'render'
* The line
* this.render = this.options.render || this.render
* was added to bootstrap-typeahead.js
* The following function is a copy of the original render function but
* access item.name instead of item
*/
render : function (items) {
var that = this
items = $(items).map(function (i, item) {
i = $(that.options.item).attr('data-value', item.name).attr('data-id', item.id).attr('data-type', item.type);
i.find('a').html(that.highlighter(item))
return i[0]
})
items.first().addClass('active')
this.$menu.html(items)
return this
}
}); /* }}} */
/* Document chooser */
$("[id^=choosedocsearch]").typeahead({ /* {{{ */
minLength: 3,
source: function(query, process) {
// console.log(this.options);
$.get(seeddms_webroot+'op/op.Ajax.php', { command: 'searchdocument', query: query, limit: 8 }, function(data) {
process(data);
});
},
/* updater is called when the item in the list is clicked. It is
* provided to update the input field where you type. */
updater: function (item) {
target = this.$element.data('target');
$('#'+target).attr('value', item.id);
return item.value;
},
sorter: function(items) {
return items;
},
/* Set a matcher that allows any returned value */
matcher : function (item) {
return true;
},
highlighter : function (item) {
return ' ' + item.name.replace(/' + item.path + '' : '');
},
/* This only works with a modified version of bootstrap typeahead located
* in boostrap-typeahead.js Search for 'render'
* The line
* this.render = this.options.render || this.render
* was added to bootstrap-typeahead.js
* The following function is a copy of the original render function but
* access item.name instead of item
*/
render : function (items) {
var that = this
items = $(items).map(function (i, item) {
i = $(that.options.item).attr('data-value', item.name).attr('data-id', item.id).attr('data-type', item.type);
i.find('a').html(that.highlighter(item))
return i[0]
})
items.first().addClass('active')
this.$menu.html(items)
return this
}
}); /* }}} */
/* Folder chooser */
$("[id^=choosefoldersearch]").typeahead({ /* {{{ */
minLength: 3,
source: function(query, process) {
// console.log(this.options);
$.get(seeddms_webroot+'op/op.Ajax.php', { command: 'searchfolder', query: query, limit: 8 }, function(data) {
process(data);
});
},
/* updater is called when the item in the list is clicked. It is
* actually provided to update the input field, but here we use
* it to set the document location. */
updater: function (item) {
target = this.$element.data('target');
$('#'+target).attr('value', item.id);
return item.value;
},
sorter: function(items) {
return items;
},
/* Set a matcher that allows any returned value */
matcher : function (item) {
return true;
},
highlighter : function (item) {
return ' ' + item.name.replace(/' + item.path + '' : '');
},
/* This only works with a modified version of bootstrap typeahead located
* in boostrap-typeahead.js Search for 'render'
* The line
* this.render = this.options.render || this.render
* was added to bootstrap-typeahead.js
* The following function is a copy of the original render function but
* access item.name instead of item
*/
render : function (items) {
var that = this
items = $(items).map(function (i, item) {
i = $(that.options.item).attr('data-value', item.name).attr('data-id', item.id).attr('data-type', item.type);
i.find('a').html(that.highlighter(item))
return i[0]
})
items.first().addClass('active')
this.$menu.html(items)
return this
}
}); /* }}} */
}
$(document).ready( function() {
/* close popovers when clicking somewhere except in the popover or the
* remove icon
*/
$('html').on('click', function(e) {
if (typeof $(e.target).data('original-title') == 'undefined' && !$(e.target).parents().is('.popover.in') && !$(e.target).is('.fa fa-remove')) {
$('[data-original-title]').popover('hide');
}
});
$('body').on('hidden', '.modal', function () {
$(this).removeData('modal');
});
$('body').on('click', '[data-toggle="modal"]', function(ev){
/* Also set the title */
if($(this).data("modal-title"))
$($(this).data("target")+' .modal-header h3').html($(this).data("modal-title"));
});
$('body').on('touchstart.dropdown', '.dropdown-menu', function (e) { e.stopPropagation(); });
initMost();
$('body').on('click', '[id^=clearfolder]', function(ev) { /* {{{ */
ev.preventDefault();
ev.stopPropagation();
target = $(this).data('target');
$('#choosefoldersearch'+target).val('');
$('#'+target).val('');
}); /* }}} */
$('body').on('click', '[id^=cleardocument]', function(ev) { /* {{{ */
ev.preventDefault();
ev.stopPropagation();
target = $(this).data('target');
$('#choosedocsearch'+target).val('');
$('#'+target).val('');
}); /* }}} */
$('body').on('click', '#clipboard-float', function(ev) { /* {{{ */
ev.preventDefault();
ev.stopPropagation();
$('#clipboard-container').toggleClass('clipboard-container');
}); /* }}} */
$('body').on('click', 'a.addtoclipboard', function(ev) { /* {{{ */
ev.preventDefault();
ev.stopPropagation();
attr_rel = $(ev.currentTarget).attr('rel');
attr_msg = $(ev.currentTarget).attr('msg');
type = attr_rel.substring(0, 1) == 'F' ? 'folder' : 'document';
id = attr_rel.substring(1);
$.get(seeddms_webroot+'op/op.Ajax.php',
{ command: 'addtoclipboard', type: type, id: id },
function(data) {
if(data.success) {
$("#main-clipboard").html('Loading').load(seeddms_webroot+'out/out.Clipboard.php?action=mainclipboard')
$("#menu-clipboard div").html('Loading').load(seeddms_webroot+'out/out.Clipboard.php?action=menuclipboard')
noty({
text: attr_msg,
type: 'success',
dismissQueue: true,
layout: 'topRight',
theme: 'defaultTheme',
timeout: 1500
});
} else {
noty({
text: data.message,
type: 'error',
dismissQueue: true,
layout: 'topRight',
theme: 'defaultTheme',
timeout: 3500
});
}
},
'json'
);
}); /* }}} */
$('body').on('click', 'a.removefromclipboard', function(ev){ /* {{{ */
ev.preventDefault();
attr_rel = $(ev.currentTarget).attr('rel');
attr_msg = $(ev.currentTarget).attr('msg');
type = attr_rel.substring(0, 1) == 'F' ? 'folder' : 'document';
id = attr_rel.substring(1);
$.get(seeddms_webroot+'op/op.Ajax.php',
{ command: 'removefromclipboard', type: type, id: id },
function(data) {
if(data.success) {
$("#main-clipboard").html('Loading').load(seeddms_webroot+'out/out.Clipboard.php?action=mainclipboard')
$("#menu-clipboard div").html('Loading').load(seeddms_webroot+'out/out.Clipboard.php?action=menuclipboard')
noty({
text: attr_msg,
type: 'success',
dismissQueue: true,
layout: 'topRight',
theme: 'defaultTheme',
timeout: 1500
});
} else {
noty({
text: data.message,
type: 'error',
dismissQueue: true,
layout: 'topRight',
theme: 'defaultTheme',
timeout: 3500
});
}
},
'json'
);
}); /* }}} */
$('body').on('click', 'a.lock-document-btn', function(ev){ /* {{{ */
ev.preventDefault();
attr_rel = $(ev.currentTarget).attr('rel');
attr_msg = $(ev.currentTarget).attr('msg');
id = attr_rel;
$.get(seeddms_webroot+'op/op.Ajax.php',
{ command: 'tooglelockdocument', formtoken: $(ev.currentTarget).data('formtoken'), id: id },
function(data) {
if(data.success) {
//$("#table-row-document-"+id).html('Loading').load('../op/op.Ajax.php?command=view&view=documentlistrow&id='+id)
$("#table-row-document-"+id).html('Loading').load(seeddms_webroot+'out/out.ViewDocument.php?action=documentlistitem&documentid='+id)
noty({
text: attr_msg,
type: 'success',
dismissQueue: true,
layout: 'topRight',
theme: 'defaultTheme',
timeout: 1500
});
} else {
noty({
text: data.message,
type: 'error',
dismissQueue: true,
layout: 'topRight',
theme: 'defaultTheme',
timeout: 3500
});
}
},
'json'
);
}); /* }}} */
$('a.movefolder').click(function(ev){ /* {{{ */
ev.preventDefault();
attr_source = $(ev.currentTarget).attr('source');
attr_dest = $(ev.currentTarget).attr('dest');
attr_msg = $(ev.currentTarget).attr('msg');
attr_formtoken = $(ev.currentTarget).attr('formtoken');
$.get(seeddms_webroot+'op/op.Ajax.php',
{ command: 'movefolder', folderid: attr_source, targetfolderid: attr_dest, formtoken: attr_formtoken },
function(data) {
if(data.success) {
$('#table-row-folder-'+attr_source).hide('slow');
noty({
text: data.msg,
type: data.success ? 'success' : 'error',
dismissQueue: true,
layout: 'topRight',
theme: 'defaultTheme',
timeout: 1500
});
}
},
'json'
);
}); /* }}} */
$('a.movedocument').click(function(ev){ /* {{{ */
ev.preventDefault();
attr_source = $(ev.currentTarget).attr('source');
attr_dest = $(ev.currentTarget).attr('dest');
attr_msg = $(ev.currentTarget).attr('msg');
attr_formtoken = $(ev.currentTarget).attr('formtoken');
$.get(seeddms_webroot+'op/op.Ajax.php',
{ command: 'movedocument', docid: attr_source, targetfolderid: attr_dest, formtoken: attr_formtoken },
function(data) {
if(data.success) {
$('#table-row-document-'+attr_source).hide('slow');
noty({
text: data.msg,
type: data.success ? 'success' : 'error',
dismissQueue: true,
layout: 'topRight',
theme: 'defaultTheme',
timeout: 1500
});
}
},
'json'
);
}); /* }}} */
$('.send-missing-translation a').click(function(ev){ /* {{{ */
// console.log($(ev.target).parent().children('[name=missing-lang-key]').val());
// console.log($(ev.target).parent().children('[name=missing-lang-lang]').val());
// console.log($(ev.target).parent().children('[name=missing-lang-translation]').val());
$.ajax(seeddms_webroot+'op/op.Ajax.php', {
type:"POST",
async:true,
dataType:"json",
data: {
command: 'submittranslation',
key: $(ev.target).parent().children('[name=missing-lang-key]').val(),
lang: $(ev.target).parent().children('[name=missing-lang-lang]').val(),
phrase: $(ev.target).parent().children('[name=missing-lang-translation]').val()
},
success: function(data, textStatus) {
noty({
text: data.message,
type: data.success ? 'success' : 'error',
dismissQueue: true,
layout: 'topRight',
theme: 'defaultTheme',
timeout: 1500
});
}
});
}); /* }}} */
$('div.ajax').each(function(index) { /* {{{ */
var element = $(this);
var url = '';
var href = element.data('href');
var base = element.data('base');
if(typeof base == 'undefined')
base = '';
var view = element.data('view');
var action = element.data('action');
var query = element.data('query');
var afterload = $(this).data('afterload');
var waitmsg = element.data('wait-msg');
if(typeof waitmsg == 'undefined')
waitmsg = '';
if(view && action) {
url = seeddms_webroot+base+"out/out."+view+".php?action="+action;
if(query) {
url += "&"+query;
}
} else
url = href;
if(!element.data('no-spinner'))
element.prepend('