views:

77

answers:

1

Hey all,

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: function(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>
A: 

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());
Ravindra Sane
It always returns "string : site_num". This line right here seems to be destroying remembered variables: var tableReady = new Table($(this)) Hence, order_value will ALWAYS be equal to site_num and never -site_num. So I believe that's the issue.
JohnMerlino
Actually, the -site_num is supposed to be written into the href of the link in the erb file using params[:order] but it never happens. Hence, when a new Table is instantiated it grabs the value site_num over and over, and is never equal to -site_num.
JohnMerlino
try doing this : var order_value1 = (order_value.indexOf("-") > -1) ? order_value : "-" + order_value; var page_value1 = page_value; return {order : order_value1, page : page_value1 };
Ravindra Sane
by the way, it seems yuo are specifically looking for "-" to be in the first char... it would make more sense to use order_value[0]=="-" if you are sure that order_value will never be empty
Ravindra Sane
None of those options are working either. It's always returning -order_value after the first click. The time this comparison is made, it's always thinking that there isn't a "-".
JohnMerlino
Changing the erb file to have this: <%= (params[:order].nil?) ? :site_num : params[:order] %> didn't help either.
JohnMerlino
is this a public site? a link would help at this point..
Ravindra Sane
No it's not public. While there was one issue that was fixed with substring: var order_value1 = (order_value.indexOf("-") > -1) ? order_value.substring(1) : "-" + order_value; I think there is an underlying anti-design pattern in the source html.
JohnMerlino