提交 a06c47a5 编写于 作者: J Joshua Peek

Drop JS scripts from core

上级 bddd1bb6
jQuery(function ($) {
var rails = {
update: function (selector, content, position) {
var element = $('#' + selector);
if (position) {
switch (position) {
case "before":
element.before(content);
break;
case "after":
element.after(content);
break;
case "top":
element.prepend(content);
break;
case "bottom":
element.append(content);
break;
default:
element.append(content);
break;
}
} else {
element.html(content);
}
},
remote: function (e) {
var el = $(this),
data = [],
condition = el.attr('data-condition') ? eval(el.attr('data-condition')) : true,
method = el.attr('method') || el.attr('data-method') || 'GET',
url = el.attr('action') || el.attr('data-url') || '#',
async = el.attr('data-remote-type') === 'synchronous' ? false : true;
if (el.attr('data-submit')) {
data = $('#' + el.attr('data-submit')).serializeArray();
} else if (el.attr('data-with')) {
if (e && e.target.tagName.toUpperCase() == 'SCRIPT' && el.attr('data-observed') !== null) {
var observed = $('#' + el.attr('data-observed'));
if(observed[0].tagName.toUpperCase() === 'FORM'){
data = el.attr('data-with') + '=' + observed.serialize();
} else if(observed[0].tagName.toUpperCase() === 'INPUT' && observed.attr('type').toUpperCase() !== "BUTTON" && observed.attr('type').toUpperCase() !== "SUBMIT") {
data = el.attr('data-with') + '=' + observed.val();
}
} else {
// TODO: remove eval when deprecated
data = eval(el.attr('data-with'));
}
} else if (e && e.target.tagName.toUpperCase() == 'FORM') {
data = el.serializeArray();
} else if (e && e.target.tagName.toUpperCase() == 'INPUT') {
data = el.closest('form').serializeArray();
}
if (condition) {
el.trigger('rails:before');
$.ajax({
async: async,
url: url,
data: data,
type: method.toUpperCase(),
beforeSend: function (xhr) {
xhr.setRequestHeader("Accept", "text/javascript")
el.trigger('rails:after', xhr);
el.trigger('rails:loading', xhr);
},
success: function (data, status, xhr) {
el.trigger('rails:success', [data, status, xhr]);
if (el.attr('data-update-success')) {
rails.update(el.attr('data-update-success'), data, el.attr('data-update-position'));
}
},
complete: function (xhr) {
// enable disabled_with buttons
if (el[0].tagName.toUpperCase() == 'FORM') {
el.children('input[type="button"][data-enable-with],input[type="submit"][data-enable-with]').each(function(i, button){
button = $(button);
button.attr('value', button.attr('data-enable-with'));
button.removeAttr('data-enable-with');
button.removeAttr('disabled');
});
} else {
el.attr('value', el.attr('data-enable-with'));
el.removeAttr('data-enable-with');
el.removeAttr('disabled');
}
el.trigger('rails:complete', xhr);
el.trigger('rails:loaded', xhr);
},
error: function (xhr, status, error) {
el.trigger('rails:failure', [xhr, status, error]);
if (el.attr('data-update-failure')) {
rails.update(el.attr('data-update-failure'), xhr.responseText, el.attr('data-update-position'));
}
}
});
}
e.preventDefault();
}
}
/**
* observe_form, and observe_field
*/
$('script[data-observe="true"]').each(function (index, e) {
var el = $(e),
observed = $('#' + $(e).attr('data-observed'));
frequency = el.attr('data-frequency') ? el.attr('data-frequency') : 10,
value = observed[0].tagName.toUpperCase() === 'FORM' ? observed.serialize() : observed.val();
var observe = function (observed, frequency, value, e) {
return function () {
var event = new jQuery.Event('periodical'),
newValue = observed[0].tagName.toUpperCase() === 'FORM' ? observed.serialize() : observed.val();
event.target = e;
if(value !== newValue) {
value = newValue;
$(e).trigger('rails:observe');
rails.remote.call(el, event);
}
}
}(observed, frequency, value, e);
setInterval(observe, frequency * 1000);
});
/**
* confirm
* make sure this event is first!
*/
$('a[data-confirm],input[type="submit"][data-confirm],input[type="button"][data-confirm]').live('click', function(e){
var el = $(this);
if(!confirm(el.attr('data-confirm'))){
return false;
}
});
/**
* periodically_call_remote
*/
$('script[data-periodical="true"]').each(function (index, e) {
var el = $(e),
frequency = el.attr('data-frequency') ? el.attr('data-frequency') : 10;
setInterval(function () {
return function () {
var event = new jQuery.Event('periodical');
event.target = e;
rails.remote.call(el, event);
}
}(e, el), frequency * 1000);
});
/**
* disable_with
*/
$('input[type="button"][data-disable-with],input[type="submit"][data-disable-with]').live('click', function(e){
var el = $(this);
el.attr('data-enable-with', el.attr('value'));
el.attr('disabled', 'disabled');
el.attr('value', el.attr('data-disable-with'));
});
/**
* remote_form_tag, and remote_form_for
*/
$('form[data-remote="true"]').live('submit', rails.remote);
/**
* link_to_remote, button_to_remote, and submit_to_remote
*/
$('a[data-remote="true"],input[data-remote="true"],input[data-remote-submit="true"]').live('click', rails.remote);
/*
* popup
*/
$('a[data-popup],input[type="button"][data-popup]').live('click', function(e){
var el = $(this),
url = el.attr('data-url') || el.attr('href');
e.preventDefault();
if(el.attr('data-popup') === "true"){
window.open(url);
} else {
window.open(url, el.attr('data-popup'));
}
});
/**
*
* Rails 2.x Helper / Event Handlers
* By default we listen to all callbacks, and status code callbacks and
* check the element for data-<callback> attribute and eval it.
*
*/
rails.compat = {
evalAttribute: function (element, attribute) {
var el = $(element),
attr = el.attr('data-' + attribute);
return (attr) ? eval(attr) : true;
}
};
$('form[data-remote="true"],a[data-remote="true"],input[data-remote="true"],script[data-observe="true"]')
.live('rails:before', function (e) {
rails.compat.evalAttribute(this, 'onbefore');
})
.live('rails:after', function (e, xhr) {
rails.compat.evalAttribute(this, 'onafter');
})
.live('rails:loading', function (e, xhr) {
rails.compat.evalAttribute(this, 'onloading');
})
.live('rails:loaded', function (e, xhr) {
rails.compat.evalAttribute(this, 'onloaded');
})
.live('rails:complete', function (e, xhr) {
rails.compat.evalAttribute(this, 'oncomplete');
rails.compat.evalAttribute(this, 'on' + xhr.status);
})
.live('rails:success', function (e, data, status, xhr) {
rails.compat.evalAttribute(this, 'onsuccess');
})
.live('rails:failure', function (e, xhr, status, error) {
rails.compat.evalAttribute(this, 'onfailure');
})
.live('rails:observe', function (e) {
rails.compat.evalAttribute(this, 'onobserve');
});
});
Event.observe(document, 'dom:loaded', function() {
function handle_remote(el, e){
var data = null,
method = el.readAttribute('method') || el.readAttribute('data-method') || 'GET',
url = el.readAttribute('action') || el.readAttribute('data-url') || '#',
async = el.readAttribute('data-remote-type') === 'synchronous' ? false : true,
update = el.readAttribute('data-update-success'),
position = el.readAttribute('data-update-position');
if (el.readAttribute('data-submit')) {
var submit_el = $(el.readAttribute('data-submit'));
if(submit_el !== undefined && submit_el.tagName.toUpperCase() == 'FORM'){
data = submit_el.serialize();
}
} else if (el.readAttribute('data-with')) {
// It seems there is a big inconsistency between what :with means depending on the element type
// so this is going to look a bit crazy
if(el.tagName.toUpperCase() === 'SCRIPT' && el.readAttribute('data-observed') !== null){
// Handle observe_field and observe_form
var observed_element = $(el.readAttribute('data-observed'));
if(observed_element.tagName.toUpperCase() === 'FORM'){
data = el.readAttribute('data-with') + '=' + observed_element.serialize();
} else if(observed_element.tagName.toUpperCase() === 'INPUT' && observed_element.readAttribute('type').toUpperCase() !== "BUTTON" && observed_element.readAttribute('type').toUpperCase() !== "SUBMIT") {
data = el.readAttribute('data-with') + '=' + observed_element.getValue();
}
} else {
// Handle link_to and button_to
data = evalAttribute(el, 'data-with');
}
} else if(el.tagName.toUpperCase() === 'FORM') {
data = el.serialize();
}
document.fire('rails:before');
var request = new Ajax.Request(url, {
method: method,
asynchronous: async,
parameters: data,
evalJS: true,
evalJSON: true,
onComplete: function(xhr){
document.fire('rails:complete', {xhr: xhr, element: el, submitted_button: getEventProperty(e, 'submitted_button')});
},
onLoading: function(xhr){
document.fire('rails:after', {xhr: xhr, element: el});
document.fire('rails:loading', {xhr: xhr, element: el});
},
onLoaded: function(xhr){
document.fire('rails:loaded', {xhr: xhr, element: el});
},
onSuccess: function(xhr){
document.fire('rails:success', {xhr: xhr, element: el});
},
onFailure: function(xhr){
document.fire('rails:failure', {xhr: xhr, element: el});
}
});
}
function setEventProperty(e, property, value){
if(e.memo === undefined){
e.memo = {};
}
e.memo[property] = value;
}
function getEventProperty(e, property){
if(e !== null && e.memo !== undefined && e.memo[property] !== undefined){
return e.memo[property];
}
}
function confirmed(e, el){
if(getEventProperty(e,'confirm_checked') !== true){
setEventProperty(e, 'confirm_checked', true);
el = Event.findElement(e, 'form') || el;
var confirm_msg = el.readAttribute('data-confirm');
if(confirm_msg !== null){
var result = el.fire('rails:confirm', {confirm_msg: confirm_msg});
if(result.memo.stop_event === true){
Event.stop(e);
return false;
}
}
}
return true;
}
function disable_button(el){
var disable_with = el.readAttribute('data-disable-with');
if(disable_with !== null){
el.writeAttribute('data-enable-with', el.readAttribute('value'));
el.writeAttribute('value', disable_with);
el.writeAttribute('disabled', true);
}
}
function enable_button(el){
var enable_with = el.readAttribute('data-enable-with');
if(enable_with !== null){
el.writeAttribute('value', enable_with);
}
el.writeAttribute('disabled', false);
}
function updateHTML(el, content, result){
var element_id = null;
if(result === 'success'){
element_id = el.readAttribute('data-update-success');
} else if(result === 'failure'){
element_id = el.readAttribute('data-update-failure');
}
var element_to_update = $(element_id);
if(element_to_update !== null){
var position = el.readAttribute('data-update-position');
if(position !== null){
var options = {};
options[position] = content;
element_to_update.insert(options);
} else {
element_to_update.update(content);
}
}
}
$$("script[data-periodical=true]").each(function(el){
var executor = new PeriodicalExecuter(function() { handle_remote(el);}, el.readAttribute('data-frequency'));
});
$$("script[data-observe=true]").each(function(el){
var observed_element = $(el.readAttribute('data-observed'));
var original_value = observed_element.tagName.toUpperCase() === 'FORM' ? observed_element.serialize() : observed_element.getValue();
var callback = el.readAttribute('data-onobserve');
var executor = new PeriodicalExecuter(function() {
var value = observed_element.tagName.toUpperCase() === 'FORM' ? observed_element.serialize() : observed_element.getValue();
if(original_value !== value){
original_value = value;
if(callback !== null){
evalAttribute(el, 'onobserve');
} else if(el.readAttribute('data-url') !== null){
handle_remote(el);
}
}
}, el.readAttribute('data-frequency'));
});
/**
*
* Event Listeners
*
* the original element is contained inside the event,
* for some reason prototype wont let me listen for custom events on document
* if the event wasn't fired on document
*
*/
Event.observe(document, 'submit', function (e) {
var form = Event.findElement(e, 'form');
// Make sure conditions and confirm have not already run
if(form !== undefined && conditions_met(e, form) && confirmed(e, form)){
var button = form.down('input[data-submitted=true]');
button.writeAttribute('data-submitted', null);
setEventProperty(e, 'submitted_button', button);
disable_button(button);
if(form.readAttribute('data-remote') === 'true'){
Event.stop(e);
handle_remote(form, e);
}
}
});
Event.observe(document, 'click', function (e) {
var el = Event.findElement(e, 'a') || Event.findElement(e, 'input');
if(el !== undefined && el.tagName.toUpperCase() === 'INPUT' && el.readAttribute('type').toUpperCase() === 'SUBMIT'){
el.writeAttribute('data-submitted', 'true');
// Submit is handled by submit event, don't continue on this path
el = undefined;
} else if(el !== undefined && el.tagName.toUpperCase() === 'INPUT' && el.readAttribute('type').toUpperCase() !== 'BUTTON'){
// Make sure other inputs do not send this event
el = undefined;
}
if(el !== undefined && conditions_met(e, el) && confirmed(e, el)){
if(el.tagName.toUpperCase() === 'INPUT' && el.readAttribute('type').toUpperCase() === 'BUTTON'){
disable_button(el);
}
if(el.readAttribute('data-remote') === 'true'){
Event.stop(e);
handle_remote(el, e);
} else if(el.readAttribute('data-popup') !== null){
Event.stop(e);
document.fire('rails:popup', {element: el});
}
}
});
/**
*
* Default Event Handlers
*
*/
Event.observe(document, 'rails:confirm', function(e){
setEventProperty(e, 'stop_event', !confirm(getEventProperty(e,'confirm_msg')));
});
Event.observe(document, 'rails:popup', function(e){
var el = getEventProperty(e, 'element');
var url = el.readAttribute('href') || el.readAttribute('data-url');
if(el.readAttribute('data-popup') === true){
window.open(url);
} else {
window.open(url, el.readAttribute('data-popup'));
}
});
Event.observe(document, 'rails:complete', function(e){
var el = getEventProperty(e, 'element');
if(el.tagName.toUpperCase() === 'FORM'){
var button = getEventProperty(e, 'submitted_button') ;
enable_button(button);
}
});
Event.observe(document, 'rails:success', function(e){
var el = getEventProperty(e, 'element'),
xhr = getEventProperty(e, 'xhr');
if(xhr.responseText !== null){
updateHTML(el, xhr.responseText, 'success');
}
});
Event.observe(document, 'rails:failure', function(e){
var el = getEventProperty(e, 'element'),
xhr = getEventProperty(e, 'xhr');
if(xhr.responseText !== null){
updateHTML(el, xhr.responseText, 'failure');
}
});
/**
*
* Rails 2.x Helpers / Event Handlers
*
*/
function evalAttribute(el, attribute){
var js = el.readAttribute('data-' + attribute);
if(js){
eval(js);
}
}
function conditions_met(e, el){
if(getEventProperty(e,'condition_checked') !== true){
setEventProperty(e, 'condition_checked', true);
el = Event.findElement(e, 'form') || el;
var conditions = el.readAttribute('data-condition');
if(conditions !== null){
if(eval(conditions) === false){
Event.stop(e);
return false;
}
}
}
return true;
}
Event.observe(document, 'rails:success', function(e){
evalAttribute(el, 'onsuccess');
});
Event.observe(document, 'rails:failure', function(e){
evalAttribute(el, 'onfailure');
});
Event.observe(document, 'rails:complete', function(e){
var el = getEventProperty(e, 'element');
evalAttribute(el, 'oncomplete');
evalAttribute(el, 'on' + getEventProperty('xhr', xhr.status));
if(el.readAttribute('data-periodical') === 'true'){
evalAttribute(el, 'onobserve');
}
});
Event.observe(document, 'rails:loading', function(e){
evalAttribute(el, 'onloading');
});
Event.observe(document, 'rails:loaded', function(e){
evalAttribute(el, 'onloaded');
});
Event.observe(document, 'rails:before', function(e){
evalAttribute(el, 'onbefore');
});
Event.observe(document, 'rails:after', function(e){
evalAttribute(el, 'onafter');
});
});
......@@ -86,15 +86,13 @@ def test_activerecord_is_removed_from_frameworks_if_skip_activerecord_is_given
assert_file "config/boot.rb", /# require "active_record\/railtie"/
end
def test_prototype_and_test_unit_are_added_by_default
def test_test_unit_is_added_by_default
run_generator
assert_file "public/javascripts/prototype.js"
assert_file "test"
end
def test_prototype_and_test_unit_are_skipped_if_required
run_generator [destination_root, "--skip-prototype", "--skip-testunit"]
assert_no_file "public/javascripts/prototype.js"
def test_test_unit_is_skipped_if_required
run_generator [destination_root, "--skip-testunit"]
assert_no_file "test"
end
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册