diff --git a/lib/index.js b/lib/index.js index f396ab8..1b0bf74 100644 --- a/lib/index.js +++ b/lib/index.js @@ -396,7 +396,7 @@ const Popover = createClass({ !this.containerEl.contains(event.target) && !this.targetEl.contains(event.target) ) - if (isOuterAction) this.props.onOuterAction() + if (isOuterAction) this.props.onOuterAction(event) }, untrackPopover () { clearInterval(this.checkLayoutInterval) diff --git a/lib/layout.js b/lib/layout.js index b4c8e86..9b89471 100644 --- a/lib/layout.js +++ b/lib/layout.js @@ -135,7 +135,7 @@ const getPreferenceType = (preference) => ( /* Dimension Fit Checks */ const fitWithinChecker = (dimension) => (domainSize, itemSize) => ( - domainSize[dimension] > itemSize[dimension] + domainSize[dimension] >= itemSize[dimension] ) const doesWidthFitWithin = fitWithinChecker(`w`) @@ -160,10 +160,8 @@ const createPreferenceError = (givenValue) => ( -/* Algorithm for picking the best fitting zone for popover. The current technique will loop through all zones picking the last one that fits. If -none fit the last one is selected. - -TODO In the case that none fit we should pick the least-not-fitting zone. */ +/* Algorithm for picking the best fitting zone for popover. The current technique will loop through all zones picking the last one that fits. +In the case that none fit we should pick the least-not-fitting zone. */ const pickZone = (opts, frameBounds, targetBounds, size) => { const t = targetBounds @@ -174,11 +172,21 @@ const pickZone = (opts, frameBounds, targetBounds, size) => { { side: `end`, standing: `below`, flow: `column`, order: 1, w: f.x2, h: (f.y2 - t.y2) }, { side: `start`, standing: `left`, flow: `row`, order: -1, w: t.x, h: f.y2 }, ] - + + /* Order the zones by the amount of popup that would be cut out if that zone is used. + The first one in the array is the one that cuts the least amount. + + const area = size.w * size.h // Popup area is constant and it does not change the order + */ + zones.forEach((z) => { + z.cutOff = /* area */ - Math.max(0, Math.min(z.w,size.w)) * Math.max(0, Math.min(z.h,size.h)) + }) + zones.sort((a,b) => a.cutOff - b.cutOff) + const availZones = zones.filter((zone) => ( doesFitWithin(zone, size) )) - + /* If a place is required pick it from the available zones if possible. */ if (opts.place) { @@ -190,17 +198,27 @@ const pickZone = (opts, frameBounds, targetBounds, size) => { /* If the preferred side is part of the available zones, use that otherwise pick the largest available zone. If there are no available zones, pick the - largest zone. TODO: logic that executes picking based on largest option. */ + largest zone. */ if (opts.preferPlace) { const preferenceType = getPreferenceType(opts.preferPlace) if (!preferenceType) throw createPreferenceError(opts.preferPlace) + + // Try to fit first in zone where the pop up fit completely const preferredAvailZones = availZones.filter((zone) => ( zone[preferenceType] === opts.preferPlace )) if (preferredAvailZones.length) return preferredAvailZones[0] + + // If there are not areas where the pop up fit completely, it uses the prefered ones + // in order from the one the fit better + const preferredZones = zones.filter((zone) => ( + zone[preferenceType] === opts.preferPlace + )) + if (preferredZones.length) return preferredZones[0] } + // Return a zone that fit completely or the one that fit the best return availZones.length ? availZones[0] : zones[0] } diff --git a/package.json b/package.json index f1a73ff..b722044 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "babel-core": "^6.3.15", "babel-loader": "^6.2.0", "babel-preset-es2015": "^6.3.13", + "babel-preset-react": "^6.3.13", "bluebird": "^3.0.5", "bootstrap-webpack-plugin": "^0.3.0", "chai": "^3.2.0",