Uploaded image for project: 'ZK'
  1. ZK
  2. ZK-4338

Quagga readers are not removed when barcodereader is unbind_()

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: Major Major
    • 9.0.0
    • 8.6.2
    • None
    • Security Level: Jimmy
    • None

      Steps to Reproduce

      http://zkfiddle.org/sample/1hv4ehq/1-quagga-listener-not-clean-on-unbind
      run locally
      click remove button

      Current Result

      barcodescanner is removed, quagga reader is not
      see console repeating callback error very rapidely:

      zkmax.barscanner.wpd:36 Uncaught TypeError: Cannot read property 'getContext' of undefined
          at Object.callback (zkmax.barscanner.wpd:36)
          at n (zkmax.barscanner.wpd:4)
          at zkmax.barscanner.wpd:4
          at Array.forEach (<anonymous>)
          at Object.publish (zkmax.barscanner.wpd:4)
          at v (zkmax.barscanner.wpd:4)
          at Worker.n.worker.onmessage (zkmax.barscanner.wpd:4)
      (anonymous) @ zkmax.barscanner.wpd:36
      n @ zkmax.barscanner.wpd:4
      (anonymous) @ zkmax.barscanner.wpd:4
      publish @ zkmax.barscanner.wpd:4
      v @ zkmax.barscanner.wpd:4
      n.worker.onmessage @ zkmax.barscanner.wpd:4
      

      Expected Result

      removing a barcodescanner should also unsubscribe its listeners from the quagga library

      Debug Info

      quagga has an onDetected / offDetected and onProcessed / offProcessed methods to add or remove callbacks from the quagga reader library

      Root Cause

      missing unbind behavior / missing self cleaning listener

      Workaround

      <script><![CDATA[ 
      zk.afterLoad('zkmax.barscanner', function() {
      	var xBarcodescannerStatic = {};
      	zk.override(zkmax.barscanner.Barcodescanner, xBarcodescannerStatic ,{
      		_quaggaInit: function (wgt, video, canvas, target) {
      			//zkmax.barscanner.Barcodescanner.quaggaApp.init(wgt);
      			var readerType = [],
      				reader = wgt._QUAGGAReader;
      			wgt.debug = false;
      			reader._ready = false;
      			readerType = zkmax.barscanner.Barcodescanner._quaggaTypeFilter(wgt);
      	
      			//Before quagga.init, the video status should be 4, so it has videoWidth and videoHeight attribute to set the
      			//size of canvas
      			new Promise(function (resolve, reject) {
      				var waitVideo = setInterval(function () {
      					if (video.readyState == 4) {
      						clearInterval(waitVideo);
      						resolve();
      					}
      				}, 50, wgt);
      			}).then(function () {
      				reader.init({
      					locate: true,
      					inputStream: {
      						name: 'Live',
      						type: 'LiveStream',
      						target: target, // Or '#yourElement' (optional)
      						area: { // defines rectangle of the detection/localization area
      							top: '0%',    // top offset
      							right: '0%',  // right offset
      							left: '0%',   // left offset
      							bottom: '0%'  // bottom offset
      						},
      						size: zkmax.barscanner.Barcodescanner._quaggaCanvasDim(wgt).width
      					},
      					frequency: 1000,
      					decoder: {
      						readers: readerType, // List of active readers
      						debug: {
      							drawBoundingBox: false,
      							showFrequency: false,
      							drawScanline: false,
      							showPattern: false
      						},
      						multiple: false
      					},
      					locator: {
      						halfSample: false,
      						patchSize: 'medium', // x-small, small, medium, large, x-large
      						debug: {
      							showCanvas: wgt.debug,
      							showPatches: wgt.debug,
      							showFoundPatches: wgt.debug,
      							showSkeleton: wgt.debug,
      							showLabels: wgt.debug,
      							showPatchLabels: wgt.debug,
      							showRemainingPatchLabels: wgt.debug,
      							boxFromPatches: {
      								showTransformed: wgt.debug,
      								showTransformedBox: wgt.debug,
      								showBB: wgt.debug
      							}
      						}
      					},
      					debug: wgt.debug
      				}, function (err) {
      					if (err) {
      						zk.error(err);
      						return;
      					}
      					reader.canvas = jq.extend(true, {}, zkmax.barscanner.quagga.canvas);
      					reader._ready = true;
      					reader._reset = true;
      					reader._consistencyBuffer = [];
      				});
      			});
      			var onProcessedCallback = function (result) {
      				if(wgt.$n() == null){
      					reader.offProcessed(onProcessedCallback);
      					return;
      				}
      				var q = zkmax.barscanner.quagga,
      						drawingCanvas = wgt.$n('canvas'),
      						drawingCtx = drawingCanvas.getContext('2d');
      					if (result) {
      						if (result.boxes) {
      							drawingCtx.clearRect(0, 0, parseInt(drawingCanvas.getAttribute('width')), parseInt(drawingCanvas.getAttribute('height')));
      							result.boxes
      								.filter(function (box) { return box !== result.box; })
      								.forEach(function (box) {
      									q.ImageDebug.drawPath(box, {x: 0, y: 1}, drawingCtx, {color: 'green', lineWidth: 2});
      								});
      						}
      						if (result.box)
      							q.ImageDebug.drawPath(result.box, {x: 0, y: 1}, drawingCtx, {color: 'blue', lineWidth: 2});
      						if (result.codeResult && result.codeResult.code)
      							q.ImageDebug.drawPath(result.line, {x: 'x', y: 'y'}, drawingCtx, {color: 'red', lineWidth: 3});
      					}
      				}
      			reader.onProcessed(onProcessedCallback);
      			reader.onDetected(function (result) {
      				if (result[0] != undefined) {
      					result = result[0];
      				}
      				var errors = result.codeResult.decodedCodes
      						.filter(function (i) { return i.error !== undefined; })
      						.map(function (i) { return i.error; }),
      					errorSum = errors.reduce(function (prev, next) { return prev + next; }),
      					errorFactor = errorSum / errors.length;
      				if (errorFactor <= wgt._errorAcceptance) {
      					var format = result.codeResult.format.replace('_', ''),
      						value = result.codeResult.code,
      						buf = reader._consistencyBuffer;
      					buf.push(value);
      					if (buf.length > wgt._consistencyBufferSize) buf.shift();
      					if (buf.filter(function (v) { return v === value; }).length >= wgt._consistencyThreshold) {
      						reader._consistencyBuffer = [];
      						wgt._doDetect(format, value);
      						reader.processing = false;
      						reader.pause();
      					}
      				}
      			});
      		}
      	});
      	zkmax.barscanner.Barcodescanner._initLibrary();
      });
      ]]></script>
      

            rudyhuang rudyhuang
            MDuchemin MDuchemin
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: