// DBX3.0 :: Docking Boxes (dbx) >>> Rules Engine
// *****************************************************
// DOM scripting by brothercake -- http://www.brothercake.com/
// GNU Lesser General Public License -- http://www.gnu.org/licenses/lgpl.html
//******************************************************
dbxGroup.prototype.setRule = function(rule, cname){if(this.orientation != 'freeform') { throw('Error from setRule() method:\nThe rules engine cannot be used with "' + this.orientation + '" orientation'); return false; }if(!dbx.supported || !this.container) { return false; }rule = rule.replace(/\s/g, '');if(!/^[NESWneswT0-9,\$\/\{\}\*\:\|\s]+$/.test(rule)) { throw('Error from setRule() method:\nThe rule "' + rule + '" contains invalid characters'); return false; }else if((/\{/.test(rule) || /\}/.test(rule)) && !/\{[0-9]+\}/i.test(rule)) { throw('Error from setRule() method:\nThe rule "' + rule + '" contains an invalid range token'); return false; }else if(/(\T)/.test(rule) && !/(\T\:)\{?[0-9]+\}?((\/)\{?[0-9]+\}?)?/.test(rule)) { throw('Error from setRule() method:\nThe rule "' + rule + '" contains an invalid triangle description'); return false; }else if(!/(\T)/.test(rule) && !/^((((N|E|S|W|Ne|Se|Sw|Nw)+)|([\*\$]))(\{[0-9]+\})?[,\|]?)+$/.test(rule)) { throw('Error from setRule() method:\nThe rule "' + rule + '" contains invalid compass values'); return false; }rule = rule.replace(/En/g, 'Ne');rule = rule.replace(/Es/g, 'Se');rule = rule.replace(/Wn/g, 'Nw');rule = rule.replace(/Ws/g, 'Sw');rule = rule.replace(/N[ns]/g, 'N');rule = rule.replace(/E[ew]/g, 'E');rule = rule.replace(/S[sn]/g, 'S');rule = rule.replace(/W[we]/g, 'W');rule = rule.split(',');if(rule[0] == '$') { throw('Error from setRule() method:\nCannot use "$" as the first step in a sequence'); return false; }if(rule[rule.length - 1] == '') { throw('Error from setRule() method:\nTrailing comma is not allowed in a rule'); return false; }if(typeof cname == 'undefined'){this.rules.global = { 'pointer' : 0, 'rule' : rule, 'actual' : [] };return true;}else{if(!/^[-_a-zA-Z0-9]+$/i.test(cname) || cname == 'global') { throw('Error from setRule() method:\n"' + cname + '" is an invalid ruleset name'); return false; }this.rules[cname] = { 'pointer' : 0, 'rule' : rule, 'actual' : [] };return true;}return false;};dbxGroup.prototype.removeRule = function(cname){if(!dbx.supported) { return false; }if(typeof cname == 'undefined'){this.rules.global = { 'pointer' : 0, 'rule' : [], 'actual' : [] };return true;}else if(cname == '*'){this.rules = { 'global' : { 'pointer' : 0, 'rule' : [], 'actual' : [] } };return true;}else{if(!/^[-_a-zA-Z0-9]+$/i.test(cname)) { throw('Error from removeRule() method:\n"' + cname + '" is an invalid ruleset name'); return false; }if(typeof this.rules[cname] == 'undefined') { throw('Error from removeRule() method:\nThe ruleset "' + cname + '" does not exist'); return false; }delete this.rules[cname];return true;}return false;};dbxGroup.prototype._updateRulePointer = function(){if(this.rulekey != '' && this.rules[this.rulekey].rule.length > 1){this.rules[this.rulekey].actual.push(this.ruledir);this.rules[this.rulekey].pointer++;this.rulekey = '';}};dbxGroup.prototype._testRules = function(direction, blocks, parent, rulekey){if(rulekey){var key = rulekey;}else{var cname = parent.className.split(' ');for(var i=0; i<cname.length; i++){if(typeof this.rules[cname[i]] != 'undefined'){var found = cname[i];break;}}if(typeof found != 'undefined'){key = found;}else{key = 'global';}}dbx.box = parent;if(this.rules[key].rule.length == 0){dbx.pointer = null;dbx.rule = null;dbx.pattern = null;key = null;var okay = true;}else{this.rulekey = key;this.ruledir = direction;if((typeof this.lastparent != 'undefined' && this.lastparent != parent)|| this.rules[key].pointer == this.rules[key].rule.length){this.rules[key].pointer = 0;this.rules[key].actual = [];}this.lastparent = parent;ruleobj = this.rules[key];var pattern = ruleobj.rule[ruleobj.pointer];if(pattern.indexOf('$') != -1){pattern = pattern.replace('$', ruleobj.actual[ruleobj.actual.length - 1]);}dbx.pattern = pattern;okay = false;pattern = pattern.split('|');for(i=0; i<pattern.length; i++){if(pattern[i].indexOf('T:') != -1){pattern[i] = pattern[i].replace('T:', '').split('/');var same = false;if(pattern[i].length == 1){same = true;pattern[i].push(pattern[i][0]);}var exact = [true, true];for(var j=0; j<2; j++){if(/^\{[0-9]+\}$/.test(pattern[i][j])){exact[j] = false;pattern[i][j] = pattern[i][j].replace(/[\{\}]/g, '');}}pattern[i].sort(function(a, b) { return a - b; });if(((exact[0] && pattern[i][0] == blocks[0]) || (!exact[0] && blocks[0] <= pattern[i][0]))&&((exact[1] && pattern[i][1] == blocks[1]) || (!exact[1] && blocks[1] <= pattern[i][1]))){if((same && blocks[0] == blocks[1]) || !same){okay = true;}}}else{if(pattern[i].indexOf('{') != -1){var tmp = pattern[i].split('{');pattern[i] = tmp[0];var blockrule = parseInt(tmp[1], 10);}tmp = [];for(j=0; j<pattern[i].length; j++){var letter = pattern[i].charAt(j);if(letter.toUpperCase() == letter){tmp.push(letter);}else{var len = tmp[tmp.length - 1].length;if(len < 2) { tmp[tmp.length - 1] += letter; }else { continue; }}}pattern[i] = tmp;for(j=0; j<pattern[i].length; j++){if(direction == pattern[i][j] || pattern[i][j] == '*'){okay = true;break;}}if(okay && typeof blockrule != 'undefined'){if(blocks[0] > blockrule || blocks[1] > blockrule) { okay = false; }}}if(okay) { break; }}dbx.pointer = this.rules[key].pointer;dbx.rule = ruleobj.rule.join(', ');}if(typeof dbx.onruletest == 'undefined'){return okay;}else{dbx.dbxobject = this;dbx.group = this.container;dbx.sourcebox = this.box;dbx.ruleset = key;dbx.direction = direction;dbx.blocks = blocks;dbx.allowed = okay;return dbx.onruletest();}};