LP# 1811898: Fixes improper display and printing of long call numbers
authorAdam Bowling <abowling@emeralddata.net>
Fri, 16 Aug 2019 06:17:21 +0000 (02:17 -0400)
committerAdam Bowling <abowling@emeralddata.net>
Fri, 16 Aug 2019 06:17:21 +0000 (02:17 -0400)
in the spine label print view.

Signed-off-by: Adam Bowling <abowling@emeralddata.net>
Open-ILS/web/js/ui/default/staff/cat/printlabels/app.js

index 2553689..7958f92 100644 (file)
@@ -265,8 +265,9 @@ function ($scope, $q, $window, $routeParams, $location, $timeout, egCore, egNet,
 
                 angular.forEach(data.copies, function (copy) {
                     promises.push(
-                        itemSvc.fetch(null, copy).then(function (res) {
+                        itemSvc.fetch(null, copy.target_copy).then(function (res) {
                             var flat_copy = egCore.idl.toHash(res.copy, true);
+                            flat_copy.copy_bucket_item_id = copy.id;
                             $scope.preview_scope.copies.push(flat_copy);
                             $scope.record_details[flat_copy['call_number.record.id']] = 1;
                         })
@@ -289,6 +290,8 @@ function ($scope, $q, $window, $routeParams, $location, $timeout, egCore, egNet,
                     });
 
                     $q.all(promises2).then(function () {
+                        // sort copies into the order they were entered into the bucket
+                        $scope.preview_scope.copies.sort((a, b) => (a.copy_bucket_item_id > b.copy_bucket_item_id) ? 1 : ((b.copy_bucket_item_id > a.copy_bucket_item_id) ? -1 : 0));
                         // today, staff, current_location, etc.
                         egCore.print.fleshPrintScope($scope.preview_scope);
                         $scope.template_changed(); // load the default
@@ -519,6 +522,7 @@ function ($scope, $q, $window, $routeParams, $location, $timeout, egCore, egNet,
                     $scope.rendered_cn_key_by_copy_id[copy.id] = key;
                 }
             }
+            console.log($scope.rendered_call_number_set);
             $scope.preview_scope.tickle = Date() + ' ' + Math.random();
         });
     }
@@ -725,7 +729,9 @@ function ($scope, $q, $window, $routeParams, $location, $timeout, egCore, egNet,
 
 .filter('cn_wrap', function () {
     return function (input, w, h, wrap_type) {
-        var names;
+        var addedElements = 0;
+        /* Pattern matches for LC ([0]) and non-LC ([1]) CNs */
+        var patterns = [/^([A-Z]{1,3})\s*(\d{1,4})(\.*\d{1,3})?\s*(\d[A-Z0-9]{0,3})?(\.*[A-Z]\d{1,3})?(\d[A-Z0-9]{0,3})?([A-Z]\d{1,3})?(.*)?/i, /^([A-Z]+)?\s*(\d+)(\.\d+)?\s*(.*)?$/i];
         var prefix = input[0];
         var callnum = input[1];
         var suffix = input[2];
@@ -733,78 +739,77 @@ function ($scope, $q, $window, $routeParams, $location, $timeout, egCore, egNet,
         if (!w) { w = 8; }
         if (!h) { h = 9; }
 
-        /* handle spine labels differently if using LC */
-        if (wrap_type == 'lc' || wrap_type == 3) {
-            /* Establish a pattern where every return value should be isolated on its own line 
-               on the spine label: subclass letters, subclass numbers, cutter numbers, trailing stuff (date) */
-            var patt1 = /^([A-Z]{1,3})\s*(\d+(?:\.\d+)?)\s*(\.[A-Z]\d*)\s*([A-Z]\d*)?\s*(\d\d\d\d(?:-\d\d\d\d)?)?\s*(.*)$/i;
-            var result = callnum.match(patt1);
-            if (result) {
-                callnum = result.slice(1).join('\t');
-            } else {
-                callnum = callnum.split(/\s+/).join('\t');
-            }
-
-            /* If result is null, leave callnum alone. Can't parse this malformed call num */
+        var cn_patt; /* <- regex from patterns to use based on wrap_type */
+        var z = 3; /* <-Text match position in patterns for variable text (7th position in LC regex pattern); default to non-LC (3rd position in non-LC regex pattern) */
+        if (wrap_type === 3 || wrap_type === 'lc') {
+            cn_patt = patterns[0];
+            z = 7;
         } else {
-            callnum = callnum.split(/\s+/).join('\t');
-        }
-
-        if (prefix) {
-            callnum = prefix + '\t' + callnum;
-        }
-        if (suffix) {
-            callnum += '\t' + suffix;
-        }
-
-        /* At this point, the call number pieces are separated by tab characters.  This allows
-        *  some space-containing constructs like "v. 1" to appear on one line
-        */
-        callnum = callnum.replace(/\t\t/g, '\t');  /* Squeeze out empties */
-        names = callnum.split('\t');
-        var j = 0; var tb = [];
-        while (j < h) {
-
-            /* spine */
-            if (j < w) {
-
-                var name = names.shift();
-                if (name) {
-                    name = String(name);
-
-                    /* if the name is greater than the label width... */
-                    if (name.length > w) {
-                        /* then try to split it on periods */
-                        var sname = name.split(/\./);
-                        if (sname.length > 1) {
-                            /* if we can, then put the periods back in on each splitted element */
-                            if (name.match(/^\./)) sname[0] = '.' + sname[0];
-                            for (var k = 1; k < sname.length; k++) sname[k] = '.' + sname[k];
-                            /* and put all but the first one back into the names array */
-                            names = sname.slice(1).concat(names);
-                            /* if the name fragment is still greater than the label width... */
-                            if (sname[0].length > w) {
-                                /* then just truncate and throw the rest back into the names array */
-                                tb[j] = sname[0].substr(0, w);
-                                names = [sname[0].substr(w)].concat(names);
-                            } else {
-                                /* otherwise we're set */
-                                tb[j] = sname[0];
-                            }
+            cn_patt = patterns[1];
+        }
+
+        var result = callnum.match(cn_patt);
+        if (result) {
+            result = result.slice(1);
+            /* Fix the variable lines of the call number that are longer than 'w'; proceed through algorithm to break up the elements in a standard spine label format (on spaces, periods, decimals, etc.) */
+            if (result[z + addedElements]) {
+                result[z + addedElements] = result[z + addedElements].replace(/\s+$/, "");
+                if (result[z + addedElements].length > w) {
+                    var n = z + addedElements;
+                    var sub_patt = [/^([^\.]+?)(?!\.) ([^\s]+)$/, /^(.+?) ([^\s]+)$/];
+                    while (n < result.length) {
+                        var y = result[n].match(sub_patt[0]) ? 0 : result[n].match(sub_patt[1]) ? 1 : 0;
+                        if (result[n].match(sub_patt[y]) && result[n].length > w) {
+                            var str = result[n].match(sub_patt[y]);
+                            result[n] = str[1];
+                            result.splice(n + 1, 0, str[2]);
+                            addedElements++;
                         } else {
-                            /* if we can't split on periods, then just truncate and throw the rest back into the names array */
-                            tb[j] = name.substr(0, w);
-                            names = [name.substr(w)].concat(names);
+                            n++;
                         }
+                    }
+                }
+            }
+        } else {
+            result = [];
+            divideOnCharLen(callnum, result, 0, 0);
+        }
+        prefix ? result.splice(0, 0, prefix) : false;
+        suffix ? result.push(suffix) : false;
+
+        /* Give each line a final check and cleanup if it exceeds width of 'w' */
+        addedElements = 0;
+        for (var i = 0; i < result.length; i++) {
+            if (result[i]) {
+                divideOnCharLen(result[i], result, i, addedElements);
+            }
+        }
+        var output = [];
+        for (var j = 0; j < result.length; j++) {
+            result[j] ? result[j] = result[j].replace(/^\s*(.*?)\s*$/, "$1") : false;
+            result[j] ? output.push(result[j]) : false;
+        }
+        output = output.slice(0, h); /*Limit lines to height in org unit settings (or default) */
+
+        return output.join('\n');
+
+        function divideOnCharLen(val, arr, index, incr) {
+            var x = 1;
+            while ((val.length / x) > w) {
+                x++;
+            }
+            var charMatch = val.match(new RegExp(".{1," + Math.ceil((val.length / x)) + "}", "g"));
+            if (charMatch) {
+                for (var t = 0; t < charMatch.length; t++) {
+                    if (t === 0) {
+                        arr[index] = charMatch[t];
                     } else {
-                        /* otherwise we're set */
-                        tb[j] = name;
+                        arr.splice((index + t), 0, charMatch[t]);
+                        incr++;
                     }
                 }
             }
-            j++;
         }
-        return tb.join('\n');
     }
 })