I don't expect anyone took read this whole script, but you will notice that there is a sort object with an insert() function that returns an object that use a ternary operator to return either "-order_value" or "order_value", where order_value is a local variable holding a value. Problem is in the query string it always passes "-order_value" and never "order_value". I believe problem is when ajax method is called, it always instantiates a new Table object and therefore all variables are erased and rather than remembering the -order_value, it defaults back to order_value. Any solutions?
<script>
(function($){
var listview = $('#listview');
var lists = (function(){
var criteria = {
dropFilter: {
insert: function(value){
if(value)
return {"filter" : value};
},
msg: "Filtering..."
},
searchFilter: {
insert: function(value){
if(value)
return {"search" : value}
},
msg: "Searching..."
},
sort: {
insert: function(order, page){
arr = [];
arr[arr.length] = order;
arr[arr.length] = page;
return function(order_value, page_value){
var order_value = (order_value.indexOf("-") > -1) ? order_value : "-" + order_value;
var page_value = page_value;
return {order : order_value, page : page_value };
}
},
msg: "Sorting..."
}
}
return {
create: function(component){
var component = component.href.substring(component.href.lastIndexOf('#') + 1);
return component;
},
setDefaults: function(component){
var parameter = {};
switch(component){
case "sites":
parameter = {
'url': 'sites',
'order': 'site_num',
'per_page': '20'
}
}
return parameter;
},
getCriteria: function(criterion){
return criteria[criterion];
},
addCriteria: funct开发者_StackOverflow中文版ion(criterion, method){
criteria[criterion] = method;
}
}
})();
var Form = function(form){
var fields = [];
$(form[0].elements).each(function(){
var field = $(this);
if(typeof field.attr('alter-data') !== 'undefined') fields.push(new Field(field));
})
}
Form.prototype = {
initiate: function(){
for(field in this.fields){
this.fields[field].calculate();
}
},
isCalculable: function(){
for(field in this.fields){
if(!this.fields[field].alterData){
return false;
}
}
return true;
}
}
var Field = function(field){
this.field = field;
this.alterData = true;
this.component = {'url' : window.location.hash.substring(window.location.hash.indexOf('#') + 1)};
this.attach("change");
this.attach("keypress");
}
Field.prototype = {
attach: function(event){
var obj = this;
if(event == "change"){
obj.field.bind("change", function(){
return obj.calculate();
})
}
if(event == "keypress"){
obj.field.bind("keypress", function(e){
var code = (e.keyCode ? e.keyCode : e.which);
if(code == 13){
e.preventDefault();
return obj.calculate();
}
})
}
},
calculate: function(){
var obj = this,
field = obj.field,
component = obj.component,
msgClass = "msgClass",
msgList = $(document.createElement("ul")).addClass("msgClass"),
types = field.attr("alter-data").split(" "),
container = field.parent(),
messages = [];
field.next(".msgClass").remove();
for(var type in types){
var criterion = lists.getCriteria(types[type]);
if(field.val()){
var result = criterion.insert(field.val());
container.addClass("waitingMsg");
messages.push(criterion.msg);
obj.alterData = true;
initializeTable(component, result);
}
else {
return false;
obj.alterData = false;
}
}
if(messages.length){
for(msg in messages){
msgList.append("<li>" + messages[msg] + "</li");
}
}
else{
msgList.remove();
}
}
}
var Table = function(table){
headers = [];
$(table[0].getElementsByTagName('th')).each(function(){
var header = $(this);
if(typeof header.attr('data-sorter') !== 'undefined') headers.push(new Header(header));
})
}
Table.prototype = {
isSortable: function(){
}
}
var Header = function(header){
this.header = header;
this.isSortable = true;
this.component = {'url' : window.location.hash.substring(window.location.hash.indexOf('#') + 1)};
this.fieldName = header.children()[0].href.substring(header.children()[0].href.lastIndexOf("/") + 1, header.children()[0].href.length);
this.attach('click');
}
Header.prototype = {
attach: function(event){
var obj = this;
if(event == "click"){
obj.header.children().bind("click", function(e){
e.preventDefault();
return obj.calculate();
})
}
},
calculate: function(){
var obj = this,
header = obj.header,
component = obj.component,
fieldName = obj.fieldName, //I cannot put default value here (e.g. a variable that holds -value or value, because no value will be remembered since we instantiate a new Table object at the end of this function call with initializeTable().)
msgClass = "msgClass",
msgList = $(document.createElement("ul")).addClass("msgClass"),
types = header.attr("data-sorter").split(" "),
container = header.parent(),
messages = [];
header.next(".msgClass").remove();
for(var type in types){
var criterion = lists.getCriteria(types[type]);
}
var result = criterion.insert("order", "page");
result = result(fieldName, 1);
container.addClass("waitingMsg");
messages.push(criterion.msg);
initializeTable(component, result);
}
}
$('#dashboard a').click(function(){
var currentComponent = lists.create(this);
var defaults = lists.setDefaults(currentComponent);
initializeTable(defaults);
});
var initializeTable = function(defaults, custom){
var custom = custom || {};
var query_string = $.extend(defaults, custom);
var params = [];
$.each(query_string, function(key,value){
params += "&" + key + '=' + value;
})
params = params.substring(1);
var url = params.substring(params.indexOf("=") + 1,params.indexOf("&"));
params = params.substring(params.indexOf("&")+1, params.length);
$.ajax({
type: 'GET',
url: '/' + url,
data: params,
dataType: 'html',
error: function(){},
beforeSend: function(){},
complete: function() {},
success: function(response) {
listview.html(response);
var form = $('form');
form.calculation();
var table = $('table');
table.calculation();
}
})
}
$.extend($.fn, {
calculation: function(){
switch($(this)[0].nodeName){
case 'FORM':
var formReady = new Form($(this));
if(!formReady.isCalculable){
return false;
}
break;
case 'TABLE':
var tableReady = new Table($(this))
if(!tableReady.isSortable){
return false;
}
break;
}
}
})
})(jQuery)
</script>
_index.html.erb:
<th data-sorter="sort"><a href="<%= (params[:order].nil?) ? :site_num : params[:order] %>">Site</a></th>
here's the function in question.
insert: function(order, page){
arr = [];
arr[arr.length] = order;
arr[arr.length] = page;
return function(order_value, page_value){
var order_value = (order_value.indexOf("-") > -1) ? order_value : "-" + order_value;
var page_value = page_value;
return {order : order_value, page : page_value };
}
},
you'll notice that the line
var order_value = (order_value.indexOf("-") > -1) ? order_value : "-" + order_value;
is redefining the order_value (which I find odd, not so sure if that is the cause) an might cause compiler confusion.
Since the ternary operator is never finding the sign in order_value it might point to the fact that order_value is an integer.
Try putting this line before the previous line :
alert((typeof order_value) + " : " + order_value.toString());
精彩评论