File: /home/enamadmin/public_html/aaelearningb/enrol/attributes/js/jquery.booleanEditor.js
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @package enrol_attributes
* @author Julien Furrer <Julien.Furrer@unil.ch>
* @copyright 2012-2015 Université de Lausanne {@link http://www.unil.ch}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
;
(function ($) {
$.booleanEditor = {
defaults: {
rules: [],
change: null
},
paramList: M.enrol_attributes.paramList,
operatorList: [
{label: " = ", value: "="},
{label: " != ", value: "!="},
{label: " < ", value: "<"},
{label: " > ", value: ">"},
{label: " <= ", value: "<="},
{label: " >= ", value: ">="},
{label: " contains ", value: "contains"},
{label: " list item ", value: "listitem"},
]
};
$.fn.extend({
booleanEditor: function (options) {
var isMethodCall = (typeof options == 'string'), // is it a method call or booleanEditor instantiation ?
args = Array.prototype.slice.call(arguments, 1);
if (isMethodCall) switch (options) {
case 'serialize':
var mode = ( args[0] ) ? args[0].mode : '',
ser_obj = serialize(this);
switch (mode) {
case 'json':
return JSON.stringify(ser_obj);
break;
case 'object':
default:
return ser_obj;
}
break;
case 'getExpression':
return getBooleanExpression(this);
break;
default:
return;
}
settings = $.extend({}, $.booleanEditor.defaults, options);
return this.each(function () {
if (settings.change) {
$(this).data('change', settings.change)
}
$(this)
.addClass("enrol-attributes-boolean-editor")
.append(createRuleList($('<ul></ul>'), settings.rules));
changed(this);
});
}
});
function serialize(root_elem) {
var ser_obj = {rules: []};
var group_c_op = $("select:first[name='cond-operator']", root_elem).val();
if (group_c_op)
ser_obj.cond_op = group_c_op;
$("ul:first > li", root_elem).each(function () {
r = $(this);
if (r.hasClass('group')) {
ser_obj['rules'].push(serialize(this));
} else {
var cond_obj = {
param: $("select[name='comparison-param'] option:selected", r).val(),
comp_op: $("select[name='comparison-operator']", r).val(),
value: $("input[name='value']", r).val()
};
var cond_op = $("select[name='cond-operator']", r).val();
if (cond_op)
cond_obj.cond_op = cond_op;
ser_obj['rules'].push(cond_obj);
}
});
return ser_obj;
}
function getBooleanExpression(editor) {
var expression = "";
$("ul:first > li", editor).each(function () {
r = $(this);
var c_op = $("select[name='cond-operator']", r).val();
if (c_op != undefined) c_op = '<span class="cond-op"> ' + c_op + ' </span>';
if (r.hasClass('group')) {
expression += c_op + '<span class="group-op group-group">(</span>' + getBooleanExpression(this) + '<span class="group-op group-group">)</span>';
} else {
expression += [
c_op,
'<span class="group-op group-cond">(</span>',
'<span class="comp-param">' + $("select[name='comparison-param'] option:selected", r).text() + '</span>',
'<span class="comp-op"> ' + $("select[name='comparison-operator']", r).val() + ' </span>',
'<span class="comp-val">' + '\'' + $("input[name='value']", r).val() + '\'' + '</span>',
'<span class="group-op group-cond">)</span>'
].join("");
}
});
return expression;
}
function changed(o) {
$o = $(o);
if (!$o.hasClass('enrol-attributes-boolean-editor')) {
$o = $o.parents('.enrol-attributes-boolean-editor').eq(0);
}
if ($o.data('change')) {
$o.data('change').apply($o.get(0));
}
}
function createRuleList(list_elem, rules) {
if (list_elem.parent("li").eq(0).hasClass("group")) {
console.log("inside a group");
return;
}
if (rules.length == 0) {
// No rules, create a new one
list_elem.append(getRuleConditionElement({first: true}));
} else {
// Read all rules
for (var r_idx = 0; r_idx < rules.length; r_idx++) {
var r = rules[r_idx];
r['first'] = (r_idx == 0);
// If the rule is an array, create a group of rules
if (r.rules && (typeof r.rules[0] == 'object')) {
r.group = true;
var rg = getRuleConditionElement(r);
list_elem.append(rg);
createRuleList($("ul:first", rg), r.rules);
}
else {
list_elem.append(getRuleConditionElement(r));
}
}
}
return list_elem;
};
/**
* Build the HTML code for editing a rule condition.
* A rule is composed of one or more rule conditions linked by boolean operators
*/
function getRuleConditionElement(config) {
config = $.extend({},
{
first: false,
group: false,
cond_op: null,
param: null,
comp_op: null,
value: ''
},
config
);
// If group flag is set, wrap content with <ul></ul>, content is obtained by a recursive call
// to the function, passing a copy of config with flag group set to false
var cond_block_content = $('<div class="sre-condition-box"></div>');
if (config.group) {
cond_block_content.append('<ul></ul>');
} else {
cond_block_content
.append(makeSelectList({ // The list of parameters to be compared
name: 'comparison-param',
params: $.booleanEditor.paramList,
selected_value: config.param
}).addClass("comp-param"))
//append dropdown with different comparison operators
.append(makeSelectList({
name: 'comparison-operator',
params: $.booleanEditor.operatorList,
selected_value: config.comp_op || 'listitem'
}).addClass("comp-op"))
.append($('<input type="text" name="value" value="' + config.value + '"/>')
.change(function () {
changed(this)
})
); // The value of the comparions
}
var ruleConditionElement = $('<li></li>')
.addClass((config.group) ? 'group' : 'rule')
.append(createRuleOperatorSelect(config))
.append(cond_block_content)
.append(createButtonPannel())
return ruleConditionElement;
};
function createRuleOperatorSelect(config) {
return (config.first) ? '' :
makeSelectList({
'name': 'cond-operator',
params: [
{label: 'AND', value: 'and'},
{label: 'OR', value: 'or'}
],
selected_value: config.cond_op
}).addClass('sre-condition-rule-operator');
}
function createButtonPannel() {
var buttonPannel = $('<div class="button-pannel"></div>')
.append($('<button type="button" class="button-add-cond">'+ M.util.get_string('addcondition', 'enrol_attributes') +'</button>')
.click(function () {
addNewConditionAfter($(this).parents('li').get(0));
})
)
.append($('<button type="button" class="button-add-group">'+ M.util.get_string('addgroup', 'enrol_attributes') +'</button>')
.click(function () {
addNewGroupAfter($(this).parents('li').get(0));
})
)
.append($('<button type="button" class="button-del-cond">'+ M.util.get_string('deletecondition', 'enrol_attributes') +'</button>')
.click(function () {
deleteCondition($(this).parents('li').eq(0));
})
);
$('button', buttonPannel).each(function () {
$(this)
.focus(function () {
this.blur()
})
.attr("title", $(this).text())
.wrapInner('<span/>');
});
return buttonPannel;
}
function makeSelectList(config) {
config = $.extend({},
{
name: 'list_name',
params: [{label: 'label', value: 'value'}],
selected_value: null
},
config);
var selectList = $('<select name="' + config.name + '"></select>')
.change(function () {
changed(this);
});
$.each(config.params, function (i, p) {
var p_obj = $('<option></option>')
.attr({label: p.label, value: p.value})
.text(p.label);
if (p.value == config.selected_value) {
p_obj.attr("selected", "selected");
}
p_obj.appendTo(selectList);
});
return selectList;
}
//
// -->> Conditions manipulation <<--
//
function addNewConditionAfter(elem, config) {
getRuleConditionElement(config)
.hide()
.insertAfter(elem)
.fadeIn("normal", function () {
changed(elem)
});
}
function addNewGroupAfter(elem, config) {
getRuleConditionElement({group: true})
.hide()
.insertAfter(elem)
.find("ul:first")
.append(getRuleConditionElement($.extend({}, config, {first: true})))
.end()
.fadeIn("normal", function () {
changed(elem)
});
}
/*
*
* Supprimer une condition : supprimer éventuellement le parent si dernier enfant,
* mettre à jour le parent dans tous les cas.
*
*/
function deleteCondition(elem) {
if (elem.parent().parent().hasClass('enrol-attributes-boolean-editor')) {
// Level 1
if (elem.siblings().length == 0) {
return;
}
} else {
// Higher level
if (elem.siblings().length == 0) {
// The last cond of the group, target the group itself, to be removed
elem = elem.parents('li').eq(0);
}
}
p = elem.parent();
elem.fadeOut("normal", function () {
$(this).remove();
$("li:first .sre-condition-rule-operator", ".enrol-attributes-boolean-editor ul").remove();
changed(p);
});
}
})(jQuery);