/**
* RubyOnRails Support Module v2.2.2
* http://rightjs.org/plugins/rails
*
* Copyright (C) 2009-2011 Nikolay Nemshilov
*/
(function(window, document, RightJS) {
/**
* The Rails plugin initialization script
*
* Copyright (C) 2010-2011 Nikolay Nemshilov
*/
var R = RightJS,
$ = RightJS.$,
$$ = RightJS.$$,
$E = RightJS.$E,
Xhr = RightJS.Xhr,
Object = RightJS.Object;
RightJS.Rails = {
version: '2.2.2'
};
/**
* Underscored aliases for Ruby On Rails
*
* Copyright (C) 2009-2011 Nikolay Nemshilov
*/
// the language and window level aliases
R([
RightJS.String.prototype,
RightJS.Array.prototype,
RightJS.Function.prototype,
RightJS.Object,
RightJS.Options,
RightJS.Observer,
RightJS.Observer.prototype,
RightJS.Window.prototype,
RightJS.Document.prototype
]).each(function(object) {
for (var key in object) {
try { // some keys are not accessable
if (/[A-Z]/.test(key) && typeof(object[key]) === 'function') {
var u_key = R(key).underscored();
if (object[u_key] === null || object[u_key] === undefined) {
object[u_key] = object[key];
}
}
} catch (e) {}
}
});
// DOM package aliases
R([
RightJS.Element,
RightJS.Event,
RightJS.Form,
RightJS.Input
]).each(function(object) {
if (!object) { return; }
var aliases = {}, methods = object.prototype;
for (var key in methods) {
if (/[A-Z]/.test(key) && typeof(methods[key]) === 'function') {
object.prototype[R(key).underscored()] = methods[key];
}
}
});
// various ruby-like method aliases
RightJS.$alias(RightJS.String.prototype, {
index_of: 'indexOf',
last_index_of: 'lastIndexOf',
to_f: 'toFloat',
to_i: 'toInt',
gsub: 'replace',
downcase: 'toLowerCase',
upcase: 'toUpperCase',
index: 'indexOf',
rindex: 'lastIndexOf',
strip: 'trim'
});
RightJS.$alias(RightJS.Array.prototype, {
collect: 'map',
detect: 'filter',
index_of: 'indexOf',
last_index_of: 'lastIndexOf',
index: 'indexOf',
rindex: 'lastIndexOf'
});
/**
* Rails 3 UJS support module
*
* Copyright (C) 2010-2011 Nikolay Nemshilov
*/
// tries to cancel the event via confirmation
function user_cancels(event, element) {
var message = element.get('data-confirm');
if (message && !confirm(message)) {
event.stop();
return true;
}
}
// adds XHR events to the element
function add_xhr_events(element, options) {
return Object.merge({
onCreate: function() { element.fire('ajax:loading', {xhr: this}); },
onComplete: function() { element.fire('ajax:complete', {xhr: this}); },
onSuccess: function() { element.fire('ajax:success', {xhr: this}); },
onFailure: function() { element.fire('ajax:failure', {xhr: this}); }
}, options);
}
// processes link clicks
function try_link_submit(event, link) {
var url = link.get('href'),
method = link.get('data-method'),
remote = link.get('data-remote');
if (user_cancels(event, link)) { return; }
if (method || remote) { event.stop(); }
if (remote) {
Xhr.load(url, add_xhr_events(link, {
method: method || 'get',
spinner: link.get('data-spinner')
}));
} else if (method) {
var param = $$('meta[name=csrf-param]')[0],
token = $$('meta[name=csrf-token]')[0],
form = $E('form', {action: url, method: 'post'});
param = param && param.get('content');
token = token && token.get('content');
if (param && token) {
form.insert('');
}
form.insert('')
.insertTo(document.body).submit();
}
}
// global events listeners
$(document).on({
click: function(event) {
var link = event.find('a');
if (link) {
try_link_submit(event, link);
}
},
submit: function(event) {
var form = event.target;
if (form.has('data-remote') && !user_cancels(event, form)) {
event.stop();
form.send(add_xhr_events(form, {
spinner: form.get('data-spinner') || form.first('.spinner')
}));
}
}
});
/**
* RR is the common ajax operations wrapper for ruby on rails
*
* Copyright (C) 2009-2010 Nikolay Nemshilov
*/
var RR = {
/**
* Basic options
*
* NOTE: DO NOT CHANGE this hash right here
* Use your application.js file to alter the options
*/
Options: {
format: 'js', // the working format for remote requests over the application
flashId: 'flashes', // the flashes element id
flashHideFx: 'slide', // use null if you don't want any fx in here
flashHideDelay: 3200, // use -1 to disable the flash element hidding
highlightUpdates: true,
removeFx: 'fade', // blocks removing fx
insertFx: 'fade', // blocks insertion fx
insertPosition: 'bottom', // default insert position
linkToAjaxEdit: '.ajax_edit',
linkToAjaxDelete: '.ajax_delete',
rescanWithScopes: true // if it should rescan only updated elements
},
/**
* Updates the flashes block with the source
*
* @param String new content
* @return RR this
*/
update_flash: function(content) {
var element = $(this.Options.flashId);
if (element) {
this.replace(element, content).hide_flash();
}
return this;
},
/**
* Initializes the delayed flashes hide call
*
* @return RR this
*/
hide_flash: function() {
if (this.Options.flashHideDelay > -1) {
var element = $(this.Options.flashId);
if (element && element.visible()) {
element.hide.bind(element, this.Options.flashHideFx).delay(this.Options.flashHideDelay);
}
}
return this;
},
/**
* Highlights the element according to the options
*
* @param String element id
* @return RR this
*/
highlight: function(id) {
if ($(id) && this.Options.highlightUpdates) {
$(id).highlight();
}
return this;
},
/**
* Inserts the content into the given element
*
* @param destination String destination id
* @param content String content
* @param position String position
* @return RR this
*/
insert: function(where, what, in_position) {
var position = in_position || this.Options.insertPosition, new_element,
container = $(where).insert(what, position);
// trying to find the new block
switch (position) {
case 'bottom': new_element = container.children().last(); break;
case 'top': new_element = container.first(); break;
case 'before': new_element = container.prev(); break;
case 'after': new_element = container.next(); break;
}
// necely displaying the new block
if (new_element && this.Options.insertFx) {
new_element.hide().show(this.Options.insertFx, {
onFinish: this.highlight.bind(this, new_element)
});
} else {
this.highlight(new_element);
}
return this.rescan(where);
},
/**
* Replaces the given element with a new content
*
* @param destination String destination id
* @param content String content
* @return RR this
*/
replace: function(id, source) {
$(id).replace(source);
return this.highlight(id).rescan(id);
},
/**
* removes the element by id
*
* @param String element id
* @return RR this
*/
remove: function(id) {
if ($(id)) {
$(id).remove(this.Options.removeFx);
}
},
/**
* Makes a remote form out of the form
*
* @param String form id
* @return RR this
*/
remotize_form: function(id) {
var form = $(id);
if (form) {
form.remotize().enable()._.action += '.'+this.Options.format;
}
return this;
},
/**
* Replaces the form with new content and makes it remote
*
* @param form id String form id
* @param content String content
* @return RR this
*/
replace_form: function(id, source) {
var form = $(id);
if (form) {
form.replace(source);
this.remotize_form(id);
}
return this.rescan(id);
},
/**
* Inserts the form source into the given element
*
* @param target id String target id
* @param source String form source
* @return RR this
*/
show_form_for: function(id, source) {
$(id).find('form').each('remove'); // removing old forms
$(id).insert(source);
return this.remotize_form($(id).first('form')).rescan(id);
},
/**
* watches link clicks and processes the ajax edit/delete operations
*
* @param Event event
*/
process_click: function(event) {
var link;
if ((link = event.find('a'+ this.Options.linkToAjaxEdit))) {
event.stop();
Xhr.load(link.get('href') + '.' + this.Options.format);
} else if ((link = event.find('a'+ this.Options.linkToAjaxDelete)) && link.has('onclick')) {
event.stop();
new Function('return '+ link.onclick.toString().replace('.submit', '.send'))().call(link);
}
},
/**
* Scans for updated elements
*
* @return RR this
*/
rescan: function(scope) {
$w('Draggable Droppable Tabs Tags Slider Selectable').each(function(name) {
if (name in window) {
window[name].rescan(this.Options.rescanWithScopes ? scope : null);
}
}, this);
return this;
}
};
/**
* the document onload hooks
*
* Copyright (C) 2010-2011 Nikolay Nemshilov
*/
$(document).on({
ready: function() {
RR.hide_flash();
},
click: function(event) {
RR.process_click(event);
}
});
window.RR = RR;
})(window, document, RightJS);