Skip to content

Instantly share code, notes, and snippets.

@Tom32i
Created August 12, 2013 09:55
Show Gist options
  • Save Tom32i/6209600 to your computer and use it in GitHub Desktop.
Save Tom32i/6209600 to your computer and use it in GitHub Desktop.
Queriable plugin.

Queriable.js

Usage:

// new Queriable(form, subset [,queryKey] [,callback] [,labels]);

new Queriable(
    $('#my-form'), 
    $('#my-form > .my-subset'),
    'query',
    function (data) { },
    {and_button: "Add AND statement", or_button: "Add OR statement"}
);
function Queriable (form, subset, queryKey, callback, labels)
{
if (form.length === 1 && subset.length === 1) {
this.labels = typeof(labels) != "undefined" ? labels : {};
this.statement = [];
this.form = form;
this.subset = subset;
this.callback = typeof(callback) != "undefined" ? callback : this.defaultCallback.bind(this);
this.queryKey = typeof(queryKey) != "undefined" ? queryKey : 'query';
this.action = this.form.attr('action');
this.andBtn = $('<button class="queriable-and-btn" type="button">' + this.getLabel('and_button') + '</button>');
this.orBtn = $('<button class="queriable-or-btn" type="button">' + this.getLabel('or_button') + '</button>');
this.container = $('<div class="queriable-statement-container"></div>');
this.statementEl = [];
this.andBtn.on('click', this.onAddAnd.bind(this));
this.orBtn.on('click', this.onAddOr.bind(this));
this.form.on('submit', this.submit.bind(this));
this.subset.replaceWith(this.container);
this.container.after(this.andBtn);
this.addAnd();
} else {
if (form.length === 0) {
console.log("[Queriable Error] The form does not exist.");
}
if (form.length > 1) {
console.log("[Queriable Error] The specified form is not unique.");
}
if (subset.length === 0) {
console.log("[Queriable Error] The subset does not exist.");
}
if (subset.length > 1) {
console.log("[Queriable Error] The specified subset is not unique.");
}
}
}
Queriable.prototype.getLabel = function (id)
{
if (typeof(this.labels[id]) != "undefined") {
return this.labels[id];
}
switch (id) {
case 'and_button': return "Add AND statement";
case 'or_button': return "Add OR statement";
}
};
Queriable.prototype.addAnd = function ()
{
var andStatement = new AndStatement(this);
this.statement.push(andStatement);
andStatement.addOr();
};
Queriable.prototype.onAddAnd = function (e)
{
this.addAnd();
};
Queriable.prototype.onAddOr = function (e)
{
var element = $(e.currentTarget).parent(),
AndStatement = this.getAndStatementByElement(element);
if (element) {
AndStatement.addOr();
}
};
Queriable.prototype.getAndStatementByElement = function (element)
{
for (var i = this.statement.length - 1; i >= 0; i--) {
if (this.statement[i].element[0] === element[0]) {
return this.statement[i];
}
}
return false;
};
Queriable.prototype.submit = function (e)
{
e.preventDefault();
console.log(this.serialize());
$.post(this.action, this.serialize(), this.callback, "json");
};
Queriable.prototype.serialize = function ()
{
var data = {},
query = [];
for (var i = this.statement.length - 1; i >= 0; i--) {
query.push(this.statement[i].serialize());
}
data[this.queryKey] = query;
return data;
};
Queriable.prototype.getNewSubset = function (and, or)
{
var subset = this.subset.html(),
suffix = '-' + and + '-' + or;
subset = subset.replace(/<label([^>]+)for="([^"]+)"/ig, '<label$1for="$2' + suffix + '"');
subset = subset.replace(/<(input|select|textarea)([^>]+)id="([^"]+)"/ig, '<$1$2id="$3' + suffix + '"');
subset = subset.replace(/<(input|select|textarea)([^>]+)name="([^"]+)"/ig, '<$1$2name="$3' + suffix + '"');
return subset;
};
Queriable.prototype.defaultCallback = function (data)
{
console.log(data);
};
function AndStatement (queriable)
{
this.queriable = queriable;
this.element = $('<div class="queriable-and"></div>');
this.or = [];
this.element.prepend(this.queriable.orBtn.clone(true));
this.queriable.container.append(this.element);
}
AndStatement.prototype.addOr = function ()
{
var orStatement = $('<div class="queriable-or"></div>'),
and = this.queriable.statement.indexOf(this),
or = this.or.length;
orStatement.html(this.queriable.getNewSubset(and, or));
this.or.push(orStatement);
this.element.append(orStatement);
};
AndStatement.prototype.serialize = function ()
{
var data = [];
for (var i = this.or.length - 1; i >= 0; i--) {
var fields = this.or[i].find("input,select,textarea").serializeArray(),
subset = {};
for (var j = fields.length - 1; j >= 0; j--) {
var name = fields[j].name.replace(/^(.+)-[0-9]+-[0-9]+$/gi, '$1');
subset[name] = fields[j].value;
}
data.push(subset);
}
return data;
};
<html>
<head>
<title>Queriable.js</title>
</head>
<body>
<form id="my-form" action="http://test.dev" method="POST">
<fieldset id="sample-query">
<label for="name">name</label>
<input type="text" name="name" id="name">
<label for="title">title</label>
<input type="text" name="title" id="title">
<label for="model">model</label>
<select name="model" id="model">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</select>
</fieldset>
<button type="submit">Envoyer</button>
</form>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.9.1.min.js"><\/script>')</script>
<script src="Queriable.js"></script>
<script type="text/javascript">
$(function() {
new Queriable($('#my-form'), $('#sample-query'));
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment