From 83cc4b019710235418cd05f3f4848989ea89b14e Mon Sep 17 00:00:00 2001 From: techfg Date: Fri, 19 Feb 2021 16:39:12 -0800 Subject: [PATCH 1/7] Resolves #377 - call onConfigured after rebind --- examples/index.html | 1 + examples/rebind.html | 117 +++++++++++++++++++++++++++++++++++++++++++ src/core.js | 5 +- src/mapdata.js | 10 +++- 4 files changed, 130 insertions(+), 3 deletions(-) create mode 100644 examples/rebind.html diff --git a/examples/index.html b/examples/index.html index 38206cf..82f0bc6 100644 --- a/examples/index.html +++ b/examples/index.html @@ -25,6 +25,7 @@

ImageMapster Examples

  • Nohref & Href Attribute Values
  • StaticState Values
  • IncludeKeys Values
  • +
  • Rebind
  • diff --git a/examples/rebind.html b/examples/rebind.html new file mode 100644 index 0000000..fb229b0 --- /dev/null +++ b/examples/rebind.html @@ -0,0 +1,117 @@ + + + + + Rebind Test + + + + + + + + + + + + + + + +

    Rebind Test

    +

    + Test 'rebind' using various combinations of values. This should + be converted to a unit test once the testing framework is updated. +

    +

    The behavior should be:

    + +

    Selected Keys:

    +
    + +
    +
    + +
    + + + + + + +
    + + diff --git a/src/core.js b/src/core.js index 48af47d..134bfbe 100644 --- a/src/core.js +++ b/src/core.js @@ -1,6 +1,6 @@ -/* +/* core.js - ImageMapster core + ImageMapster core */ (function ($) { @@ -925,6 +925,7 @@ me.bindImages().then(function () { me.buildDataset(true); me.complete = true; + me.onConfigured(); }); //this.redrawSelections(); }, diff --git a/src/mapdata.js b/src/mapdata.js index 8446af0..1d90a14 100644 --- a/src/mapdata.js +++ b/src/mapdata.js @@ -825,8 +825,16 @@ me.configureAutoResize(); } + me.onConfigured(); + }, + + onConfigured: function() { + var me = this, + $img = $(me.image), + opts = me.options; + if (opts.onConfigured && typeof opts.onConfigured === 'function') { - opts.onConfigured.call(img, true); + opts.onConfigured.call($img, true); } }, From ca83f25b4ac0a0554212c76cabfef91938e789ef Mon Sep 17 00:00:00 2001 From: techfg Date: Fri, 19 Feb 2021 19:43:07 -0800 Subject: [PATCH 2/7] Resolves #83 - Keep boundList in sync --- examples/boundlist.html | 335 ++++++++++++++++++++++++++++++++++++++++ examples/usa.html | 4 +- src/areadata.js | 7 + src/core.js | 27 +--- src/mapdata.js | 95 ++++++++---- 5 files changed, 409 insertions(+), 59 deletions(-) create mode 100644 examples/boundlist.html diff --git a/examples/boundlist.html b/examples/boundlist.html new file mode 100644 index 0000000..c5d117c --- /dev/null +++ b/examples/boundlist.html @@ -0,0 +1,335 @@ + + + + + Bound List Test + + + + + + + + + + + + + + + + + +

    Bound List Test

    +

    + Test 'boundList' option using various combinations of values. This should + be converted to a unit test once the testing framework is updated. +

    +

    The behavior should be:

    + +

    Single Select:

    +

    Selected Keys:

    +
    +
    + +
    +
    +
    +
      +
      +
      +
      +
      +
      + +
      +
      + +
      +
      + +
      +
      +
      +
      + + + + + + + + + + + + + diff --git a/examples/usa.html b/examples/usa.html index 7a5bf66..dfa9a97 100644 --- a/examples/usa.html +++ b/examples/usa.html @@ -357,15 +357,13 @@

      Highlight Types

      } function addCheckBoxes(items) { - var item, selected; + var item; $statelist.children().remove(); for (var i = 0; i < items.length; i++) { - selected = items[i].isSelected(); item = $( '
      ' + diff --git a/src/areadata.js b/src/areadata.js index 8ccc804..a0f4c11 100644 --- a/src/areadata.js +++ b/src/areadata.js @@ -310,6 +310,13 @@ selected: state }); } + if (state_type === 'select' && this.owner.options.boundList) { + this.owner.setBoundListProperties( + this.owner.options, + m.getBoundList(this.owner.options, this.key), + state + ); + } }, // highlight this area diff --git a/src/core.js b/src/core.js index 134bfbe..d984b5d 100644 --- a/src/core.js +++ b/src/core.js @@ -377,24 +377,6 @@ }); return result; }, - // Causes changes to the bound list based on the user action (select or deselect) - // area: the jQuery area object - // returns the matching elements from the bound list for the first area passed (normally only one should be passed, but - // a list can be passed - setBoundListProperties: function (opts, target, selected) { - target.each(function (_, e) { - if (opts.listSelectedClass) { - if (selected) { - $(e).addClass(opts.listSelectedClass); - } else { - $(e).removeClass(opts.listSelectedClass); - } - } - if (opts.listSelectedAttribute) { - $(e).prop(opts.listSelectedAttribute, selected); - } - }); - }, getMapDataIndex: function (obj) { var img, id; switch (obj.tagName && obj.tagName.toLowerCase()) { @@ -838,14 +820,7 @@ // Clean up after a group that applied to the same map function finishSetForMap(map_data) { $.each(area_list, function (_, el) { - var newState = setSelection(el); - if (map_data.options.boundList) { - m.setBoundListProperties( - map_data.options, - m.getBoundList(map_data.options, key_list), - newState - ); - } + setSelection(el); }); if (!selected) { map_data.removeSelectionFinish(); diff --git a/src/mapdata.js b/src/mapdata.js index 1d90a14..0b9bf5b 100644 --- a/src/mapdata.js +++ b/src/mapdata.js @@ -346,10 +346,6 @@ if (canChangeState) { ar.toggle(); } - - if (opts.boundList && opts.boundList.length > 0) { - m.setBoundListProperties(opts, list_target, ar.isSelected()); - } } mousedown.call(this, e); @@ -671,6 +667,63 @@ } }); }, + // Causes changes to the bound list based on the user action (select or deselect) + // area: the jQuery area object + // returns the matching elements from the bound list for the first area passed + // (normally only one should be passed, but a list can be passed) + setBoundListProperties: function (opts, target, selected) { + target.each(function (_, e) { + if (opts.listSelectedClass) { + if (selected) { + $(e).addClass(opts.listSelectedClass); + } else { + $(e).removeClass(opts.listSelectedClass); + } + } + if (opts.listSelectedAttribute) { + $(e).prop(opts.listSelectedAttribute, selected); + } + }); + }, + clearBoundListProperties: function (opts) { + var me = this; + if (!opts.boundList) { + return; + } + me.setBoundListProperties(opts, opts.boundList, false); + }, + refreshBoundList: function (opts) { + var me = this; + me.clearBoundListProperties(opts); + me.setBoundListProperties( + opts, + m.getBoundList(opts, me.getSelected()), + true + ); + }, + setBoundList: function (opts) { + var me = this, + sorted_list = me.data.slice(0), + sort_func; + if (opts.sortList) { + if (opts.sortList === 'desc') { + sort_func = function (a, b) { + return a === b ? 0 : a > b ? -1 : 1; + }; + } else { + sort_func = function (a, b) { + return a === b ? 0 : a < b ? -1 : 1; + }; + } + + sorted_list.sort(function (a, b) { + a = a.value; + b = b.value; + return sort_func(a, b); + }); + } + me.options.boundList = opts.onGetList.call(me.image, sorted_list); + }, ///called when images are done loading initialize: function () { var imgCopy, @@ -682,8 +735,6 @@ i, size, img, - sort_func, - sorted_list, scale, me = this, opts = me.options; @@ -795,29 +846,6 @@ u.setOpacity(me.images[1], 1); - if (opts.isSelectable && opts.onGetList) { - sorted_list = me.data.slice(0); - if (opts.sortList) { - if (opts.sortList === 'desc') { - sort_func = function (a, b) { - return a === b ? 0 : a > b ? -1 : 1; - }; - } else { - sort_func = function (a, b) { - return a === b ? 0 : a < b ? -1 : 1; - }; - } - - sorted_list.sort(function (a, b) { - a = a.value; - b = b.value; - return sort_func(a, b); - }); - } - - me.options.boundList = opts.onGetList.call(me.image, sorted_list); - } - me.complete = true; me.processCommandQueue(); @@ -828,7 +856,7 @@ me.onConfigured(); }, - onConfigured: function() { + onConfigured: function () { var me = this, $img = $(me.image), opts = me.options; @@ -977,6 +1005,13 @@ // populate areas from config options me.setAreaOptions(opts.areas); + if (opts.isSelectable && opts.onGetList) { + me.setBoundList(opts); + } + + if (opts.boundList && opts.boundList.length > 0) { + me.refreshBoundList(opts); + } me.redrawSelections(); }, processCommandQueue: function () { From 46a5e153c722667087b0d4234772d69c3a4fe8cd Mon Sep 17 00:00:00 2001 From: techfg Date: Fri, 19 Feb 2021 20:00:32 -0800 Subject: [PATCH 3/7] Resolves #380 - fix onGetList when isSelectable false --- examples/boundlist.html | 21 ++++++++++++++++++++- src/mapdata.js | 2 +- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/examples/boundlist.html b/examples/boundlist.html index c5d117c..feb652b 100644 --- a/examples/boundlist.html +++ b/examples/boundlist.html @@ -137,6 +137,7 @@ // return $veglist.empty().append(listItems).find('input'); // })(), singleSelect: true, + isSelectable: true, showToolTip: true, toolTip: function (data) { return $(data.target).data('tooltip'); @@ -150,11 +151,13 @@ }; $('#reset_map').on('click', function () { + $veglist.empty(); $image.mapster('unbind').mapster(imageOptions); }); $('#rebind_map').on('click', function () { - var options = $.extend({}, imageOptions); + $veglist.empty(); + var options = $.extend({}, $image.mapster('get_options')); options.areas.push({ key: 'squash', selected: true @@ -182,9 +185,20 @@ $image.mapster('set', null, 'carrots,celery'); }); + $('#toggle_isselectable').on('click', function () { + $veglist.empty(); + var options = $image.mapster('get_options'); + $image + .mapster('unbind') + .mapster( + $.extend({}, options, { isSelectable: !options.isSelectable }) + ); + }); + function updateOptions() { var options = $image.mapster('get_options'); $('#singleSelect').text(options.singleSelect); + $('#isSelectable').text(options.isSelectable); } function updateKeys() { @@ -226,8 +240,10 @@

      Bound List Test

      > comes in to play. +
    • List should display and sync regardless of value of isSelectable
    • Single Select:

      +

      IsSelectable:

      Selected Keys:

      @@ -254,6 +270,9 @@

      Bound List Test

      +
      + +
      diff --git a/src/mapdata.js b/src/mapdata.js index 0b9bf5b..48b0dbc 100644 --- a/src/mapdata.js +++ b/src/mapdata.js @@ -1005,7 +1005,7 @@ // populate areas from config options me.setAreaOptions(opts.areas); - if (opts.isSelectable && opts.onGetList) { + if (opts.onGetList) { me.setBoundList(opts); } From 8b63e6618164e1621bedd24e86f76ec240ca2235 Mon Sep 17 00:00:00 2001 From: techfg Date: Fri, 19 Feb 2021 20:01:25 -0800 Subject: [PATCH 4/7] missed update to index on prev commits --- examples/index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/index.html b/examples/index.html index 82f0bc6..22e2926 100644 --- a/examples/index.html +++ b/examples/index.html @@ -26,6 +26,7 @@

      ImageMapster Examples

    • StaticState Values
    • IncludeKeys Values
    • Rebind
    • +
    • Bound List
    • From 12de758c4c1957293093a37d94d159e70e24fe85 Mon Sep 17 00:00:00 2001 From: techfg Date: Sat, 20 Feb 2021 01:10:39 -0800 Subject: [PATCH 5/7] Resolves #381 - tests should wait for onConfigured --- tests/migrated.tests.js | 650 ++++++++++++++++++++++------------------ tests/resize.tests.js | 105 ++++--- 2 files changed, 410 insertions(+), 345 deletions(-) diff --git a/tests/migrated.tests.js b/tests/migrated.tests.js index 6f0b7bc..9989162 100644 --- a/tests/migrated.tests.js +++ b/tests/migrated.tests.js @@ -34,7 +34,9 @@ this.tests.push( mu = $.mapster.utils, // Save current state to see if we cleaned up properly later domCount = $('#test_elements *').length, - map = $('img').mapster(); + map = $('img').mapster({ + onConfigured: getPromise('configured1').resolve + }); // // testing with no canvas on a browser that doesn't support it anyway doesn't make sense, regular test will cover it // var has_canvas = (document.namespaces && document.namespaces.g_vml_) ? false : @@ -45,306 +47,360 @@ this.tests.push( // a.pass("The browser does not support canvases: this test was skipped.") // return; // } - - map.mapster('unbind'); - - // var oldHasCanvas = $.mapster.hasCanvas; - // if (disableCanvas) { - // $.mapster.hasCanvas=false; - // } - - // test using only bound images - var isObfuscated = map.mapster('test', "typeof m === 'undefined'"); - if (!isObfuscated) { - map = $('img').mapster(map_options); - a.equals( - 1, - map.mapster( - 'test', - "typeof m !== 'undefined' && m.map_cache && m.map_cache.length" - ), - 'Only imagemap bound images were obtained on generic create' - ); - - map = $('img,div').mapster({ mapKey: 'state' }); - - a.equals( - 1, - map.mapster( - 'test', - "typeof m !== 'undefined' && m.map_cache && m.map_cache.length" - ), - 'Only imagemap bound images were obtained on generic create with other elements' - ); - } - map = $('#usa_image').mapster( - $.extend(map_options, { - onConfigured: getPromise('configured').resolve - }) - ); - - getPromise('configured').then(function () { - var initialOpts = mu.updateProps({}, $.mapster.defaults, map_options), - opts = map.mapster('get_options'); - a.equals(opts, initialOpts, 'Options retrieved match initial options'); - - // todo - test new options options - //opts = map.mapster('get_options',null,true); - //initialOpts.render_select = u.mergeObjects({template:$.mapster.render_defaults }); - - var newOpts = { - isSelectable: false, - areas: [{ key: 'MT', isDeselectable: false }] - }; - map.mapster('set_options', newOpts); - opts = map.mapster('get_options'); - - // to compare this we have to ignore areas, since they won't be the same object - - var expectedNewOpts = $.extend({}, initialOpts); - expectedNewOpts.isSelectable = false; - - a.propertyValueEquals( - opts, - expectedNewOpts, - 'Options retrieved match updated value' - ); - a.equals(opts.areas.length, 6, 'Area option was added'); - - // restore original options before continuing - opts = map.mapster('set_options', { - isSelectable: true, - areas: [{ key: 'MT', isDeselectable: true }] - }); - - a.equals(!!map.mapster, true, 'Plugin returns jQuery object'); - a.equals( - map, - $('#usa_image'), - 'Plugin returns jquery same object as invocation' - ); - - // order is not guaranteed - this is the order the areas are created. - var selected = map.mapster('get'); - - // This test should NOT show "WA" because StaticState items are not considered "selected" - - a.collectionEquals( - selected, - 'AK,TX', - "Initially selected items returned with 'get'" - ); - - selected = map.mapster('get', 'TX'); - a.equals( - selected, - true, - "Initially selected single item returned true with 'get'" - ); - selected = map.mapster('get', 'ME'); - a.equals( - selected, - false, - "Initially deselected single item returned false with 'get'" - ); - - // Test setting/getting via area - - // AK was already selected, should be ignored - - attrMatches($('area'), 'state', 'AK,HI,LA').mapster('set', true); - var area_sel = map.mapster('get'); - a.collectionEquals(area_sel, 'HI,AK,LA,TX', 'Set using area works'); - - map.mapster('set', false, 'LA,TX'); - a.collectionEquals( - 'HI,AK', - map.mapster('get'), - 'unset using keys works' - ); - - map.mapster('set', true, 'ME,OH,TX'); - a.collectionEquals( - 'HI,AK,ME,OH,TX', - map.mapster('get'), - 'set using keys works' - ); - - // test toggling: AK should go off, MT should go on - var areas = $('area[state=AK]').first(); - areas = areas.add($('area[state=MT]').first()); - areas.mapster('set'); - a.collectionEquals( - 'HI,ME,OH,TX,MT', - map.mapster('get'), - 'toggling keys works' - ); - - // test clicking - $('area[state="AZ"]').first().click(); - selected = map.mapster('get', 'AZ'); - a.equals(true, selected, "Click-selected area returned 'get'"); - a.collectionEquals( - 'HI,ME,OH,TX,MT,AZ', - map.mapster('get'), - "Complete list returned with 'get'" - ); - - /// try to click select "staticstate areas - - $('area[state="OR"]').first().click(); - selected = map.mapster('get', 'OR'); - a.equals( - selected, - false, - "Cannot select 'staticState=false' area with click" - ); - - selected = map.mapster('get', 'WA'); - a.equals( - selected, - false, - 'staticState=true area is considered not selected' - ); - - opts = map.mapster('get_options', 'WA'); - a.equals( - opts.staticState, - true, - 'get effective options returned correct static state for WA' - ); - - opts = map.mapster('get_options', 'OR'); - a.equals( - opts.staticState, - false, - 'get effective options returned correct static state for OR' - ); - - $('area[state="WA"]').first().click(); - selected = map.mapster('get', 'WA'); - a.equals( - selected, - false, - "Cannot change selection state of 'staticState=true' area with click" - ); - - // do it programatically - - map.mapster('set', true, 'OR'); - selected = map.mapster('get', 'OR'); - a.equals( - selected, - true, - "Can select 'staticState=false' area with 'set'" - ); - - map.mapster('set', false, 'WA'); - a.equals( - map.mapster('get', 'WA'), - false, - "Can deselect staticState=true' area with 'set'" - ); - - // test rebind - newOpts = map.mapster('get_options'); - newOpts.singleSelect = true; - map.mapster('rebind', newOpts); - a.collectionEquals( - map.mapster('get'), - 'TX,AK', - 'Rebind with singleSelect reverted to original state' - ); - - map.mapster('set', true, 'MI'); - a.equals(map.mapster('get'), 'MI', 'Single select worked.'); - - map.mapster('set_options', { isDeselectable: false }); - $('area[state="MI"]').first().click(); - a.equals( - map.mapster('get', 'MI'), - true, - 'Cannot deselect single selected item with isDeselectable=false' - ); - - $('area[state="UT"]').first().click(); - - a.equals(map.mapster('get'), 'UT', 'New single state selected'); - - map.mapster('set_options', { - singleSelect: false, - isDeselectable: true, - areas: [{ key: 'ME', isDeselectable: false }] - }); - - $('area[state="UT"]').first().click(); - a.equals( - map.mapster('get', 'UT'), - false, - 'Was able to deselect item after removing singleSelect' - ); - - map.mapster('set', true, 'CA,HI,ME'); - - $('area[state="ME"]').first().click(); - a.equals( - map.mapster('get', 'ME'), - true, - 'Could not deselect one item marked as !isDeselectable' - ); - $('area[state="CA"]').first().click(); - a.equals( - map.mapster('get', 'CA'), - false, - 'Could deselect other items ' - ); - - // Test manual highlighting - - a.equals(map.mapster('highlight'), null, 'nothing is highlighted'); - - $('area[state="CA"]').first().mapster('highlight'); - - a.equals(map.mapster('highlight'), 'CA', 'highlighted manually'); - - map.mapster('highlight', 'LA'); - - a.equals( - map.mapster('highlight'), - 'LA', - 'highlighted manually using other technique' - ); - - map.mapster('highlight', false); - - a.equals(map.mapster('highlight'), null, 'everything unhighlighted'); - - // restore internal canvas setting or these tests won't work - // if (disableCanvas) { - // map.mapster('test', 'has_canvas=true'); - // } else { - - // // cleanup tests - skip to play with map afterwards - // // return; - - // if (has_canvas) { - // a.equals($('canvas').length, 2, 'There are 2 canvases.'); - // map.mapster(map_options); - // a.equals($('canvas').length, 2, 'There are 2 canvases (recreate was clean)'); - // } - // } + getPromise('configured1').then(function () { map.mapster('unbind'); - a.equals($('canvas').length, 0, 'No canvases remain after an unbind.'); - - a.equals( - $('#test_elements *').length, - domCount, - '# elements in DOM is the same.' - ); + // var oldHasCanvas = $.mapster.hasCanvas; // if (disableCanvas) { - // $.mapster.hasCanvas=oldHasCanvas; + // $.mapster.hasCanvas=false; // } + + // test using only bound images + var isObfuscated = map.mapster('test', "typeof m === 'undefined'"); + if (!isObfuscated) { + map = $('img').mapster( + $.extend({}, map_options, { + onConfigured: getPromise('configured2').resolve + }) + ); + getPromise('configured2').then(function () { + a.equals( + 1, + map.mapster( + 'test', + "typeof m !== 'undefined' && m.map_cache && m.map_cache.length" + ), + 'Only imagemap bound images were obtained on generic create' + ); + + var els = $('img,div'), + els_count = els.find('img[usemap]').length, + els_configured = 0; + + map = $('img,div').mapster( + $.extend( + { mapKey: 'state' }, + { + onConfigured: function () { + els_configured = els_configured + 1; + if (els_configured === els_count) { + getPromise('configured3').resolve(); + } + } + } + ) + ); + + getPromise('configured3').then(function () { + a.equals( + 1, + map.mapster( + 'test', + "typeof m !== 'undefined' && m.map_cache && m.map_cache.length" + ), + 'Only imagemap bound images were obtained on generic create with other elements' + ); + + getPromise('stage2').resolve(); + }); + }); + } else { + getPromise('stage2').resolve(); + } + + getPromise('stage2').then(function () { + var usaOpts = $.extend({}, map_options, { + onConfigured: getPromise('configured4').resolve + }); + + map = $('#usa_image').mapster(usaOpts); + getPromise('configured4').then(function () { + var initialOpts = mu.updateProps({}, $.mapster.defaults, usaOpts), + opts = map.mapster('get_options'); + a.propertyValueEquals( + opts, + initialOpts, + 'Options retrieved match initial options' + ); + + // todo - test new options options + //opts = map.mapster('get_options',null,true); + //initialOpts.render_select = u.mergeObjects({template:$.mapster.render_defaults }); + + var newOpts = { + isSelectable: false, + areas: [{ key: 'MT', isDeselectable: false }] + }; + map.mapster('set_options', newOpts); + opts = map.mapster('get_options'); + + // to compare this we have to ignore areas, since they won't be the same object + + var expectedNewOpts = $.extend({}, initialOpts); + expectedNewOpts.isSelectable = false; + + a.propertyValueEquals( + opts, + expectedNewOpts, + 'Options retrieved match updated value' + ); + a.equals(opts.areas.length, 6, 'Area option was added'); + + // restore original options before continuing + opts = map.mapster('set_options', { + isSelectable: true, + areas: [{ key: 'MT', isDeselectable: true }] + }); + + a.equals(!!map.mapster, true, 'Plugin returns jQuery object'); + a.equals( + map, + $('#usa_image'), + 'Plugin returns jquery same object as invocation' + ); + + // order is not guaranteed - this is the order the areas are created. + var selected = map.mapster('get'); + + // This test should NOT show "WA" because StaticState items are not considered "selected" + + a.collectionEquals( + selected, + 'AK,TX', + "Initially selected items returned with 'get'" + ); + + selected = map.mapster('get', 'TX'); + a.equals( + selected, + true, + "Initially selected single item returned true with 'get'" + ); + selected = map.mapster('get', 'ME'); + a.equals( + selected, + false, + "Initially deselected single item returned false with 'get'" + ); + + // Test setting/getting via area + + // AK was already selected, should be ignored + + attrMatches($('area'), 'state', 'AK,HI,LA').mapster('set', true); + var area_sel = map.mapster('get'); + a.collectionEquals(area_sel, 'HI,AK,LA,TX', 'Set using area works'); + + map.mapster('set', false, 'LA,TX'); + a.collectionEquals( + 'HI,AK', + map.mapster('get'), + 'unset using keys works' + ); + + map.mapster('set', true, 'ME,OH,TX'); + a.collectionEquals( + 'HI,AK,ME,OH,TX', + map.mapster('get'), + 'set using keys works' + ); + + // test toggling: AK should go off, MT should go on + var areas = $('area[state=AK]').first(); + areas = areas.add($('area[state=MT]').first()); + areas.mapster('set'); + a.collectionEquals( + 'HI,ME,OH,TX,MT', + map.mapster('get'), + 'toggling keys works' + ); + + // test clicking + $('area[state="AZ"]').first().click(); + selected = map.mapster('get', 'AZ'); + a.equals(true, selected, "Click-selected area returned 'get'"); + a.collectionEquals( + 'HI,ME,OH,TX,MT,AZ', + map.mapster('get'), + "Complete list returned with 'get'" + ); + + /// try to click select "staticstate areas + + $('area[state="OR"]').first().click(); + selected = map.mapster('get', 'OR'); + a.equals( + selected, + false, + "Cannot select 'staticState=false' area with click" + ); + + selected = map.mapster('get', 'WA'); + a.equals( + selected, + false, + 'staticState=true area is considered not selected' + ); + + opts = map.mapster('get_options', 'WA'); + a.equals( + opts.staticState, + true, + 'get effective options returned correct static state for WA' + ); + + opts = map.mapster('get_options', 'OR'); + a.equals( + opts.staticState, + false, + 'get effective options returned correct static state for OR' + ); + + $('area[state="WA"]').first().click(); + selected = map.mapster('get', 'WA'); + a.equals( + selected, + false, + "Cannot change selection state of 'staticState=true' area with click" + ); + + // do it programatically + + map.mapster('set', true, 'OR'); + selected = map.mapster('get', 'OR'); + a.equals( + selected, + true, + "Can select 'staticState=false' area with 'set'" + ); + + map.mapster('set', false, 'WA'); + a.equals( + map.mapster('get', 'WA'), + false, + "Can deselect staticState=true' area with 'set'" + ); + + // test rebind + newOpts = $.extend({}, map.mapster('get_options'), { + singleSelect: true, + onConfigured: getPromise('configured5').resolve + }); + map.mapster('rebind', newOpts); + getPromise('configured5').then(function () { + a.collectionEquals( + map.mapster('get'), + 'TX,AK', + 'Rebind with singleSelect reverted to original state' + ); + + map.mapster('set', true, 'MI'); + a.equals(map.mapster('get'), 'MI', 'Single select worked.'); + + map.mapster('set_options', { isDeselectable: false }); + $('area[state="MI"]').first().click(); + a.equals( + map.mapster('get', 'MI'), + true, + 'Cannot deselect single selected item with isDeselectable=false' + ); + + $('area[state="UT"]').first().click(); + + a.equals(map.mapster('get'), 'UT', 'New single state selected'); + + map.mapster('set_options', { + singleSelect: false, + isDeselectable: true, + areas: [{ key: 'ME', isDeselectable: false }] + }); + + $('area[state="UT"]').first().click(); + a.equals( + map.mapster('get', 'UT'), + false, + 'Was able to deselect item after removing singleSelect' + ); + + map.mapster('set', true, 'CA,HI,ME'); + + $('area[state="ME"]').first().click(); + a.equals( + map.mapster('get', 'ME'), + true, + 'Could not deselect one item marked as !isDeselectable' + ); + $('area[state="CA"]').first().click(); + a.equals( + map.mapster('get', 'CA'), + false, + 'Could deselect other items ' + ); + + // Test manual highlighting + + a.equals( + map.mapster('highlight'), + null, + 'nothing is highlighted' + ); + + $('area[state="CA"]').first().mapster('highlight'); + + a.equals(map.mapster('highlight'), 'CA', 'highlighted manually'); + + map.mapster('highlight', 'LA'); + + a.equals( + map.mapster('highlight'), + 'LA', + 'highlighted manually using other technique' + ); + + map.mapster('highlight', false); + + a.equals( + map.mapster('highlight'), + null, + 'everything unhighlighted' + ); + + // restore internal canvas setting or these tests won't work + // if (disableCanvas) { + // map.mapster('test', 'has_canvas=true'); + // } else { + + // // cleanup tests - skip to play with map afterwards + // // return; + + // if (has_canvas) { + // a.equals($('canvas').length, 2, 'There are 2 canvases.'); + // map.mapster(map_options); + // a.equals($('canvas').length, 2, 'There are 2 canvases (recreate was clean)'); + // } + // } + map.mapster('unbind'); + a.equals( + $('canvas').length, + 0, + 'No canvases remain after an unbind.' + ); + + a.equals( + $('#test_elements *').length, + domCount, + '# elements in DOM is the same.' + ); + + getPromise('finished').resolve(); + + // if (disableCanvas) { + // $.mapster.hasCanvas=oldHasCanvas; + // } + }); + }); + }); }); + a.resolves(getPromise('finished'), 'The last test resolved'); }) ); diff --git a/tests/resize.tests.js b/tests/resize.tests.js index 7fc1aea..9064332 100644 --- a/tests/resize.tests.js +++ b/tests/resize.tests.js @@ -9,6 +9,7 @@ this.tests.push( 'use strict'; var img = $('img'), + me = this, altImages = { img1: 'images/usa_map_720_alt_1.jpg', img2: 'images/usa_map_720_alt_2.jpg', @@ -16,64 +17,72 @@ this.tests.push( img4: 'images/usa_map_720_alt_4.jpg', img5: 'images/usa_map_720_alt_5.jpg' }, - map = img.mapster({ - altImages: altImages - }), - x = parseInt(img.css('width').replace('px', ''), 10), - y = parseInt(img.css('height').replace('px', ''), 10), - newWidth = x + 200; + map, + x, + y, + newWidth; - this.when(function (cb) { - map.mapster('resize', newWidth, 0, cb); + me.when(function (cb) { + map = img.mapster({ + altImages: altImages, + onConfigured: cb + }); }).then(function () { - var expectedWidth = newWidth + 'px', - expectedHeight = Math.round((newWidth / x) * y) + 'px'; - a.equals( - img.css('width'), - expectedWidth, - 'image width is correct after resize' - ); - a.equals( - img.css('height'), - expectedHeight, - 'image height is correct after resize' - ); - - var wrapper = img.closest('div'); - - a.equals( - wrapper.attr('id').substring(0, 12), - 'mapster_wrap', - 'sanity check - we have the wrapper element' - ); - a.equals( - wrapper.css('width'), - expectedWidth, - 'wrapper width matches image width' - ); - a.equals( - wrapper.css('height'), - expectedHeight, - 'wrapper height matches image height' - ); - Object.values(altImages).map(function (ai) { - var selector = 'img[src="' + ai + '"]', - altImg = $(wrapper).children(selector); + x = parseInt(img.css('width').replace('px', ''), 10); + y = parseInt(img.css('height').replace('px', ''), 10); + newWidth = x + 200; + me.when(function (cb) { + map.mapster('resize', newWidth, 0, cb); + }).then(function () { + var expectedWidth = newWidth + 'px', + expectedHeight = Math.round((newWidth / x) * y) + 'px'; a.equals( - altImg.css('width'), + img.css('width'), expectedWidth, - 'altimage ' + ai + ' width matches image width' + 'image width is correct after resize' ); a.equals( - altImg.css('height'), + img.css('height'), expectedHeight, - 'altimage ' + ai + ' height matches image height' + 'image height is correct after resize' + ); + + var wrapper = img.closest('div'); + + a.equals( + wrapper.attr('id').substring(0, 12), + 'mapster_wrap', + 'sanity check - we have the wrapper element' ); a.equals( - altImg.css('display'), - 'none', - 'altimage ' + ai + ' has display of none' + wrapper.css('width'), + expectedWidth, + 'wrapper width matches image width' + ); + a.equals( + wrapper.css('height'), + expectedHeight, + 'wrapper height matches image height' ); + Object.values(altImages).map(function (ai) { + var selector = 'img[src="' + ai + '"]', + altImg = $(wrapper).children(selector); + a.equals( + altImg.css('width'), + expectedWidth, + 'altimage ' + ai + ' width matches image width' + ); + a.equals( + altImg.css('height'), + expectedHeight, + 'altimage ' + ai + ' height matches image height' + ); + a.equals( + altImg.css('display'), + 'none', + 'altimage ' + ai + ' has display of none' + ); + }); }); }); }) From 19b01e4a5d9e1aaf82776447ada6781569896574 Mon Sep 17 00:00:00 2001 From: techfg Date: Sat, 20 Feb 2021 01:48:10 -0800 Subject: [PATCH 6/7] fix jQuery deprecation warnings (#318) --- tests/migrated.tests.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/migrated.tests.js b/tests/migrated.tests.js index 9989162..eacf968 100644 --- a/tests/migrated.tests.js +++ b/tests/migrated.tests.js @@ -216,7 +216,7 @@ this.tests.push( ); // test clicking - $('area[state="AZ"]').first().click(); + $('area[state="AZ"]').first().trigger('click'); selected = map.mapster('get', 'AZ'); a.equals(true, selected, "Click-selected area returned 'get'"); a.collectionEquals( @@ -227,7 +227,7 @@ this.tests.push( /// try to click select "staticstate areas - $('area[state="OR"]').first().click(); + $('area[state="OR"]').first().trigger('click'); selected = map.mapster('get', 'OR'); a.equals( selected, @@ -256,7 +256,7 @@ this.tests.push( 'get effective options returned correct static state for OR' ); - $('area[state="WA"]').first().click(); + $('area[state="WA"]').first().trigger('click'); selected = map.mapster('get', 'WA'); a.equals( selected, @@ -298,14 +298,14 @@ this.tests.push( a.equals(map.mapster('get'), 'MI', 'Single select worked.'); map.mapster('set_options', { isDeselectable: false }); - $('area[state="MI"]').first().click(); + $('area[state="MI"]').first().trigger('click'); a.equals( map.mapster('get', 'MI'), true, 'Cannot deselect single selected item with isDeselectable=false' ); - $('area[state="UT"]').first().click(); + $('area[state="UT"]').first().trigger('click'); a.equals(map.mapster('get'), 'UT', 'New single state selected'); @@ -315,7 +315,7 @@ this.tests.push( areas: [{ key: 'ME', isDeselectable: false }] }); - $('area[state="UT"]').first().click(); + $('area[state="UT"]').first().trigger('click'); a.equals( map.mapster('get', 'UT'), false, @@ -324,13 +324,13 @@ this.tests.push( map.mapster('set', true, 'CA,HI,ME'); - $('area[state="ME"]').first().click(); + $('area[state="ME"]').first().trigger('click'); a.equals( map.mapster('get', 'ME'), true, 'Could not deselect one item marked as !isDeselectable' ); - $('area[state="CA"]').first().click(); + $('area[state="CA"]').first().trigger('click'); a.equals( map.mapster('get', 'CA'), false, From 67dbb7437f0c8fd791430178b6a46743c017ea69 Mon Sep 17 00:00:00 2001 From: techfg Date: Sat, 20 Feb 2021 22:03:26 -0800 Subject: [PATCH 7/7] Resolves #378 - UI doesn't match selected state after rebind --- examples/rebind.html | 89 +++++++++++++-- src/mapdata.js | 9 +- tests/migrated.tests.js | 234 +++++++++++++++++++++++----------------- 3 files changed, 220 insertions(+), 112 deletions(-) diff --git a/examples/rebind.html b/examples/rebind.html index fb229b0..6ebc759 100644 --- a/examples/rebind.html +++ b/examples/rebind.html @@ -23,6 +23,12 @@ + + @@ -62,17 +119,29 @@

      Rebind Test

      - Test 'rebind' using various combinations of values. This should - be converted to a unit test once the testing framework is updated. + Test 'rebind' using various combinations of values. This should be + converted to a unit test once the testing framework is updated.

      The behavior should be:

      • onConfigured should appear in log on page load
      • onConfigured should be appended to log after rebind
      • +
      • + Rebind should apply configuration specified and not preserve selected + state +

      Selected Keys:

      - + + + + +
      + + +
      +
      Rebind Test diff --git a/src/mapdata.js b/src/mapdata.js index 48b0dbc..59afefb 100644 --- a/src/mapdata.js +++ b/src/mapdata.js @@ -938,6 +938,7 @@ if (rebind) { mapArea = me.mapAreas[$area.data('mapster') - 1]; mapArea.configure(curKey); + mapArea.areaDataXref = []; } else { mapArea = new m.MapArea(me, area, curKey); me.mapAreas.push(mapArea); @@ -1012,7 +1013,13 @@ if (opts.boundList && opts.boundList.length > 0) { me.refreshBoundList(opts); } - me.redrawSelections(); + + if (rebind) { + me.graphics.removeSelections(); + me.graphics.refreshSelections(); + } else { + me.redrawSelections(); + } }, processCommandQueue: function () { var cur, diff --git a/tests/migrated.tests.js b/tests/migrated.tests.js index eacf968..b7dfe17 100644 --- a/tests/migrated.tests.js +++ b/tests/migrated.tests.js @@ -283,120 +283,152 @@ this.tests.push( // test rebind newOpts = $.extend({}, map.mapster('get_options'), { - singleSelect: true, onConfigured: getPromise('configured5').resolve }); map.mapster('rebind', newOpts); getPromise('configured5').then(function () { a.collectionEquals( - map.mapster('get'), 'TX,AK', - 'Rebind with singleSelect reverted to original state' + map.mapster('get'), + 'Rebind reverted to configured state' ); - map.mapster('set', true, 'MI'); - a.equals(map.mapster('get'), 'MI', 'Single select worked.'); - - map.mapster('set_options', { isDeselectable: false }); - $('area[state="MI"]').first().trigger('click'); + map.mapster('set', true, 'OR'); + selected = map.mapster('get', 'OR'); a.equals( - map.mapster('get', 'MI'), + selected, true, - 'Cannot deselect single selected item with isDeselectable=false' + "Can select 'staticState=false' area with 'set'" ); - $('area[state="UT"]').first().trigger('click'); - - a.equals(map.mapster('get'), 'UT', 'New single state selected'); - - map.mapster('set_options', { - singleSelect: false, - isDeselectable: true, - areas: [{ key: 'ME', isDeselectable: false }] + newOpts = $.extend({}, map.mapster('get_options'), { + singleSelect: true, + onConfigured: getPromise('configured6').resolve + }); + map.mapster('rebind', newOpts); + getPromise('configured6').then(function () { + // Note - selected keys revert to original state due to + // options being passed and not having anything to + // due specifically with singleSelect. Rebind + // does not persist previously selected state + // as of commit https://github.com/jamietre/ImageMapster/commit/3de37f3 + // so this test is asserting that areas selected + // by configuration are selected even when + // singleSelect === true + a.collectionEquals( + 'TX,AK', + map.mapster('get'), + 'Rebind with singleSelect reverted to configured state' + ); + + map.mapster('set', true, 'MI'); + a.equals(map.mapster('get'), 'MI', 'Single select worked.'); + + map.mapster('set_options', { isDeselectable: false }); + $('area[state="MI"]').first().trigger('click'); + a.equals( + map.mapster('get', 'MI'), + true, + 'Cannot deselect single selected item with isDeselectable=false' + ); + + $('area[state="UT"]').first().trigger('click'); + + a.equals(map.mapster('get'), 'UT', 'New single state selected'); + + map.mapster('set_options', { + singleSelect: false, + isDeselectable: true, + areas: [{ key: 'ME', isDeselectable: false }] + }); + + $('area[state="UT"]').first().trigger('click'); + a.equals( + map.mapster('get', 'UT'), + false, + 'Was able to deselect item after removing singleSelect' + ); + + map.mapster('set', true, 'CA,HI,ME'); + + $('area[state="ME"]').first().trigger('click'); + a.equals( + map.mapster('get', 'ME'), + true, + 'Could not deselect one item marked as !isDeselectable' + ); + $('area[state="CA"]').first().trigger('click'); + a.equals( + map.mapster('get', 'CA'), + false, + 'Could deselect other items ' + ); + + // Test manual highlighting + + a.equals( + map.mapster('highlight'), + null, + 'nothing is highlighted' + ); + + $('area[state="CA"]').first().mapster('highlight'); + + a.equals( + map.mapster('highlight'), + 'CA', + 'highlighted manually' + ); + + map.mapster('highlight', 'LA'); + + a.equals( + map.mapster('highlight'), + 'LA', + 'highlighted manually using other technique' + ); + + map.mapster('highlight', false); + + a.equals( + map.mapster('highlight'), + null, + 'everything unhighlighted' + ); + + // restore internal canvas setting or these tests won't work + // if (disableCanvas) { + // map.mapster('test', 'has_canvas=true'); + // } else { + + // // cleanup tests - skip to play with map afterwards + // // return; + + // if (has_canvas) { + // a.equals($('canvas').length, 2, 'There are 2 canvases.'); + // map.mapster(map_options); + // a.equals($('canvas').length, 2, 'There are 2 canvases (recreate was clean)'); + // } + // } + map.mapster('unbind'); + a.equals( + $('canvas').length, + 0, + 'No canvases remain after an unbind.' + ); + + a.equals( + $('#test_elements *').length, + domCount, + '# elements in DOM is the same.' + ); + + getPromise('finished').resolve(); + + // if (disableCanvas) { + // $.mapster.hasCanvas=oldHasCanvas; + // } }); - - $('area[state="UT"]').first().trigger('click'); - a.equals( - map.mapster('get', 'UT'), - false, - 'Was able to deselect item after removing singleSelect' - ); - - map.mapster('set', true, 'CA,HI,ME'); - - $('area[state="ME"]').first().trigger('click'); - a.equals( - map.mapster('get', 'ME'), - true, - 'Could not deselect one item marked as !isDeselectable' - ); - $('area[state="CA"]').first().trigger('click'); - a.equals( - map.mapster('get', 'CA'), - false, - 'Could deselect other items ' - ); - - // Test manual highlighting - - a.equals( - map.mapster('highlight'), - null, - 'nothing is highlighted' - ); - - $('area[state="CA"]').first().mapster('highlight'); - - a.equals(map.mapster('highlight'), 'CA', 'highlighted manually'); - - map.mapster('highlight', 'LA'); - - a.equals( - map.mapster('highlight'), - 'LA', - 'highlighted manually using other technique' - ); - - map.mapster('highlight', false); - - a.equals( - map.mapster('highlight'), - null, - 'everything unhighlighted' - ); - - // restore internal canvas setting or these tests won't work - // if (disableCanvas) { - // map.mapster('test', 'has_canvas=true'); - // } else { - - // // cleanup tests - skip to play with map afterwards - // // return; - - // if (has_canvas) { - // a.equals($('canvas').length, 2, 'There are 2 canvases.'); - // map.mapster(map_options); - // a.equals($('canvas').length, 2, 'There are 2 canvases (recreate was clean)'); - // } - // } - map.mapster('unbind'); - a.equals( - $('canvas').length, - 0, - 'No canvases remain after an unbind.' - ); - - a.equals( - $('#test_elements *').length, - domCount, - '# elements in DOM is the same.' - ); - - getPromise('finished').resolve(); - - // if (disableCanvas) { - // $.mapster.hasCanvas=oldHasCanvas; - // } }); }); });