I think I'm having a scope issue with a custom sort method

ray_voelker

I've been working on a javascript class to simplify the sorting and comparing of library of congress call numbers. For the most part, the majority of it is working, except for one of the the main methods to return a sorted list. I can do the sort outside of the class given other methods of the class, so I'm not sure why I'm losing the scope when I enter the sort() function.

I'm not sure if there's a way I can pass the scope into the sort() or what I need to do to have access to that method.

I've created a github gist of the javascript and a quick html test of the class (including the error) that should demonstrate things:

https://gist.github.com/rayvoelker/accaa95c6b5db28f7f84429f8a3d8cdf

Here's the class methods that I'm having trouble with. Maybe I'm just not seeing something that should be simple.

locCallClass.prototype.localeCompare = function (a, b) {
    try {
        var a_norm = this.returnNormLcCall(a),
            b_norm = this.returnNormLcCall(b);

            return ( a_norm < b_norm ? -1 : (a_norm > b_norm ? 1 : 0) );
    }
    catch (err) {
        // console.log("error")
    }
}

locCallClass.prototype.sortCallNumbers = function (callnumbers) {
    var sorted = callnumbers.sort(function (a,b) {
        return this.localeCompare(a,b);
    });

    return sorted;
}

And here is the way that I'm calling it:

var loc = new locCallClass();
var set1 = ["LC 346 .65 .B29","LC 346 .M634","HX 754 .5 .C15","HX 754 .C7723"];

var sorted = loc.sortCallNumbers(set1);

And here's a snippet of the same demonstration code from the gist:

// js-loc-callnumbers
// A javascript class to normalize and perform various sorting options on
// Library of Congress Call Numbers within a library institution.

function locCallClass() {
	// the regular expression that defines the Library of 
	// Congress call number. Thanks to Bill Dueber's post on the subject for the regex 
	// http://robotlibrarian.billdueber.com/2008/11/normalizing-loc-call-numbers-for-sorting/
	this.lc = /^\s*([A-Z]{1,3})\s*(\d+(?:\s*\.\s*\d+)?)?\s*(?:\.?\s*([A-Z]+)\s*(\d+)?)?(?:\.?\s*([A-Z]+)\s*(\d+)?)?\s*(.*?)\s*$/;
	
	//local storage for an array of call numbers
	this.callNumberArray = [];
	//a mostly sorted array of call numbers for testing
	this.testCallNumbers = ["Z10.1 A", "Z5.1 A", "CB3 .C55", "CS418 .J82", "CS425 .B95", "D21 .W93", "D21.1.D58 1981", "D761 .W54", "D761.9.F7 G8", "DA86 .P884", "DA86 .R52", "DA506.A2 A4", "DA506.A2 B75", "DA784.5 .M23 1989", "DA785 .S12", "DC129 .W6", "DC130.A2 H3", "DF623 .C46", "DF631 .B313", "DK 267 .W78", "DK268.A1D56213 1999", "DS 70.7 .O6", "DS 70.7 .S27", "DS557.C28S6", "DS 557 .F3", "DS 917 .W47", "DS 917.35 .P33", "DT 636 .S5 A3", "DT636.2.F65 1996", "E 160 .F72", "E 160 .F73", "E184.A1I444 1992", "E184.A1I445 1996", "E 302 .J442 1984", "E302.J442 2004B", "E 487 .C746", "E 487 .C746 1966", "E 876 .U84 1986", "E 876 .V53", "F548.9.N4R437 2005", "F548.9.N4S77 2007", "F 1656 .C7 1968", "F 1659 .B55 F4", "GN 51 .A58", "GN 51 .A58 1988B", "GV 741 .B56", "GV741 .I58", "Q183.9.I34 2002", "Q183.9.L45 1993", "QA 29 .P775 A3 1987", "QA29.R3A4 1995", "QA 76.758 .H86 1989", "QA76.758.K365 2008", "QA 164 .C63 1969", "QA 164 .C63 1969", "QA274.73.R84 2004", "QA274.73.S2813 1999", "QA 353 .E5 Z4313 1993", "QA 353 .G44 W55 1990", "QA 640.7 .B55 1970", "QA641.A587 1996", "QC 173.98 .M44 V.1", "QC 173.98 .M44 V.1", "QD 21 .C51", "QD 21 .C51", "QD501 .B242 V.37", "QD501.B242 V.38", "QH 81 .B73", "QH 81 .B754", "QH540.I5", "QH540.I5", "QK 314 .F54", "QK 321 .A3613", "QL951 .C8", "QL951 .C8", "QP 601 .C733 V.171", "QP 601 .C733 V.172", "RA 410.7 .C5", "RA 410.7 .E73", "RC455.S8 1961", "RC 455 .S928", "RD 98 .G38", "RD 99 .E42 1955", "S 942 .C6 1974", "S 942 .K63 1972", "TA166.W68 1980", "TA167.A965 1998", "TA1520.S87 2007", "TA1520.W35 1998", "TD 741 .I33", "TD 741 .I33 1956", "TJ163.2 .A55", "TJ163.2 .A55", "TK5105.875.I57G723 2005", "TK5105.875.I57H338 1996", "TL215.J58L35 2005", "TL215.M18D53 2005", "TP155.C69 V.5 1997", "TP 155 .C74 1986", "TS156 .I838 2003", "TS 156 .J324"];
}

// locCallClass.returnNormLcCall(call_number)
// returns a "normalized" call number
locCallClass.prototype.returnNormLcCall = function(call_number) {
	var result = this.lc.exec(call_number);
	if (!result) {
		throw new Error(call_number + " Not a Call Number");		
	}
	
	// track the position of what we're looking at in the callnumber 
	var before_first_cutter = true;
	var return_string = "";
	
	// work through the results starting at 1 (the 0 value in the array is the original input)
	for(var i=1; i<=(result.length-1); i++) {
		if (i>1) {
			return_string = return_string + "."
		}
		
		if (i>2) {
			before_first_cutter = false;
		}
		
		return_string = return_string + this.padZed(result[i], before_first_cutter);
	}		
	
	// TODO: consider adding further checks to see if the return string 
	// consists of 8 segments 9 characters and throw an error if not
	return return_string;
}

// locCallClass.localeCompare(b,a)
// replicates functionality of the normal compare function 
// so that it may be used in external sorting operations:
// 
// A negative number if the reference string (a) occurs before the 
// given string (b); 
// positive if the reference string (a) occurs after 
// the compare string (b); 
// 0 if they are equivalent.
locCallClass.prototype.localeCompare = function (a, b) {
	try {
		var a_norm = this.returnNormLcCall(a),
			b_norm = this.returnNormLcCall(b);
						
			return ( a_norm < b_norm ? -1 : (a_norm > b_norm ? 1 : 0) );
	}
	catch (err) {
		// console.log("error")
	}
}

// locCallClass.sortCallNumbers()
// takes a variable list of call numbers as arguments, and returns 
// a sorted array of call numbers in their original format/
// You can also use this method with an array like the following:
// loc.sortCallNumbers.call(loc_instance,input)
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters
//
// TODO: Consider removing this method, instead using something like the
// following:
// var loc = new locCallClass();
// loc.testCallNumbers.sort(function(a,b) {return loc.localeCompare(a,b)});
locCallClass.prototype.sortCallNumbers = function (callnumbers) {
	var sorted = callnumbers.sort(function (a,b) {
		return this.localeCompare(a,b);
	});
	
	return sorted;
}

// locCallClass.isBetween(a,b,c)
// returns true if a <= c <= b
locCallClass.prototype.isBetween = function (a,b,c) {
	//this.localeCompare(a, b) <= 0 if in sort order	
	return ( (this.localeCompare(a,c) <= 0 && this.localeCompare(c,b) <=0) ? true : false );
}

// locCallClass.padZed()
// returns portion of the call number padded out to enable sorting.
locCallClass.prototype.padZed = function (value, before_first_cutter) {
	//pad value with zeros - return value will have a length of 9 
	// The exceptions here are going to be if the number is before the 
	// cutter, then we should treat it as two different parts: whole 
	// number, and decimal portion.

	if(value) {
		if(before_first_cutter && !isNaN(value) ) {
			//this is a number before the first cutter, split it, and then
			// pad each of the parts 
			var int_portion = Math.floor(value).toString();
			var dec_portion = (value % 1).toFixed(3).toString().substr(2,3);
			var pad_zeros = "";
			
			for (var i=0; i<(9 - int_portion.length); i++) {
				pad_zeros = pad_zeros + "0";
			}
			
			return_value = pad_zeros + int_portion;
			
			var pad_zeros = "";
			for (var i=0; i<(9 - dec_portion.length); i++) {
				pad_zeros = pad_zeros + "0";
			}
			
			return_value += "." + dec_portion + pad_zeros;
			return return_value;
		} // end if
	
		else {
			//pad the value to the right
			var pad_zeros = "";
			for (var i=0; i<(9 - value.length); i++) {
				pad_zeros = pad_zeros + "0";
			}

			return value + pad_zeros;
		}
	} 
	
	else {
		return "000000000";
	}
}


/* test script */

var loc = new locCallClass();

var output1 = document.getElementById("output1");

// define, show and then sort the first set
var set1 = ["LC 346 .65 .B29",
            "LC 346 .M634",		
            "HX 754 .5 .C15",
            "HX 754 .C7723"
           ];
output1.innerHTML = "<b>pre-sort</b><br>";
for(var i=0; i<set1.length; i++) {
  output1.innerHTML += set1[i] + "<br>";
}

//sort with the specialized sort method from our class, "loc"
var sorted1 = set1.sort(function(a,b) {
  return loc.localeCompare(a,b);
});

output1.innerHTML += "<hr><b>sorted</b><br>";

for(var i=0; i<sorted1.length; i++) {
  output1.innerHTML += sorted1[i] + "<br>";
}

// now test the built in method to sort call numbers
// which doesn't work for some reason
var alt_sorted = loc.sortCallNumbers(set1);
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>locCallClass test sorting of call numbers</title>
</head>

<body style="font-family:monospace;">

	<h3>test sorting of call numbers</h3>
	
	<div id="output1"></div>
		
</body>

Thanks in advance to anyone who could help me out!

dNitro

Cache this:

locCallClass.prototype.sortCallNumbers = function(callnumbers) {
  var self = this;
  var sorted = callnumbers.sort(function(a, b) {
    return self.localeCompare(a, b);
  });

  return sorted;
}

Or hard bind the sort's callback function to this:

locCallClass.prototype.sortCallNumbers = function(callnumbers) {
  var sorted = callnumbers.sort(function(a, b) {
    return this.localeCompare(a, b);
  }.bind(this));

  return sorted;
}

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

I'm having an issue displaying changes to the surface using pygame

I'm having an issue displaying changes to the surface using pygame

I'm having an issue with knockout's beforeRemove callback and CSS transitions

I'm having a issue using fancybox on bootstrap 4

I'm having trouble with "AXIOS PATCH" method

I'm having an issue trying to recover information from mongodb

I'm having trouble with the sort order in a kbmmemtable

I'm having an issue in Navigation view item click listener in androidx

I'm having an issue regarding AttributeError

Discord.js - I'm having an issue with my snipe command

I'm having a SQL Insert issue in my gridview

Port forwarding issue (I think)

Scope (I think?!) challenge in JavaScript

devise undefined method `id' for nil:NilClass, yet current_user is out of scope (i think?)

Can someone explain this table CSS issue I'm having?

Variable not in scope (I think), but not sure how to fix it

I'm having problems with my linkedlist method

Trouble assigning value to integers inside a function to be referred to later - scope issue - I think

I'm having issue with rtcwake being run from a Cron job

I'm having a really weird issue with memory leaks and strings

I'm having an issue with the drawing action

I'm having an issue with deploying angular app to github pages

Why I'm having this css background-image referencing issue?

I'm having an issue with the calculator that I'm building on Android

Having struggles with what I think is the scope of a boolean variable - tkinter window won't quit

I'm having an issue running Nodemon in my project

I'm having an issue with linked list of structures in C

I'm having issue with counting with multiple criteria

Is what I'm doing an Insertion sort, I think the logic is correct but unconventional?