· 6 years ago · Dec 20, 2019, 01:26 PM
1//
2// mraid.js
3// MRAID 2.0
4//
5// Copyright (c) 2013 Nexage, Inc. All rights reserved.
6//
7(function() {
8
9/***************************************************************************
10 * console logging helper
11 **************************************************************************/
12
13LogLevelEnum = {
14 "DEBUG" : 0,
15 "INFO" : 1,
16 "WARNING" : 2,
17 "ERROR" : 3
18}
19
20var logLevel = LogLevelEnum.DEBUG;
21var log = {};
22
23log.d = function(msg) {
24 if (logLevel <= LogLevelEnum.DEBUG) {
25 console.log("(D) " + msg);
26 }
27}
28
29log.i = function(msg) {
30 if (logLevel <= LogLevelEnum.INFO) {
31 console.log("(I) " + msg);
32 }
33}
34
35log.w = function(msg) {
36 if (logLevel <= LogLevelEnum.WARN) {
37 console.log("(W) " + msg);
38 }
39}
40
41log.e = function(msg) {
42 console.log("(E) " + msg);
43}
44
45/***************************************************************************
46 * MRAID declaration
47 **************************************************************************/
48
49log.i("Setting up mraid object");
50
51var mraid = window.mraid = {};
52
53/***************************************************************************
54 * constants
55 **************************************************************************/
56
57var VERSION = "2.0";
58
59var STATES = mraid.STATES = {
60 "LOADING" : "loading",
61 "DEFAULT" : "default",
62 "EXPANDED" : "expanded",
63 "RESIZED" : "resized",
64 "HIDDEN" : "hidden"
65};
66
67var PLACEMENT_TYPES = mraid.PLACEMENT_TYPES = {
68 "INLINE" : "inline",
69 "INTERSTITIAL" : "interstitial"
70};
71
72var RESIZE_PROPERTIES_CUSTOM_CLOSE_POSITION = mraid.RESIZE_PROPERTIES_CUSTOM_CLOSE_POSITION = {
73 "TOP_LEFT" : "top-left",
74 "TOP_CENTER" : "top-center",
75 "TOP_RIGHT" : "top-right",
76 "CENTER" : "center",
77 "BOTTOM_LEFT" : "bottom-left",
78 "BOTTOM_CENTER" : "bottom-center",
79 "BOTTOM_RIGHT" : "bottom-right"
80};
81
82var ORIENTATION_PROPERTIES_FORCE_ORIENTATION = mraid.ORIENTATION_PROPERTIES_FORCE_ORIENTATION = {
83 "PORTRAIT" : "portrait",
84 "LANDSCAPE" : "landscape",
85 "NONE" : "none"
86};
87
88var EVENTS = mraid.EVENTS = {
89 "ERROR" : "error",
90 "READY" : "ready",
91 "SIZECHANGE" : "sizeChange",
92 "STATECHANGE" : "stateChange",
93 "VIEWABLECHANGE" : "viewableChange"
94};
95
96var SUPPORTED_FEATURES = mraid.SUPPORTED_FEATURES = {
97 "SMS" : "sms",
98 "TEL" : "tel",
99 "CALENDAR" : "calendar",
100 "STOREPICTURE" : "storePicture",
101 "INLINEVIDEO" : "inlineVideo"
102};
103
104/***************************************************************************
105 * state
106 **************************************************************************/
107
108var state = STATES.LOADING;
109var placementType = PLACEMENT_TYPES.INLINE;
110var supportedFeatures = {};
111var isViewable = false;
112var isResizeReady = false;
113
114var expandProperties = {
115 "width" : 0,
116 "height" : 0,
117 "useCustomClose" : false,
118 "isModal" : true
119};
120
121var orientationProperties = {
122 "allowOrientationChange" : true,
123 "forceOrientation" : ORIENTATION_PROPERTIES_FORCE_ORIENTATION.NONE
124};
125
126var resizeProperties = {
127 "width" : 0,
128 "height" : 0,
129 "customClosePosition" : RESIZE_PROPERTIES_CUSTOM_CLOSE_POSITION.TOP_RIGHT,
130 "offsetX" : 0,
131 "offsetY" : 0,
132 "allowOffscreen" : true
133};
134
135var currentPosition = {
136 "x" : 0,
137 "y" : 0,
138 "width" : 0,
139 "height" : 0
140};
141
142var defaultPosition = {
143 "x" : 0,
144 "y" : 0,
145 "width" : 0,
146 "height" : 0
147};
148
149var maxSize = {
150 "width" : 0,
151 "height" : 0
152};
153
154var screenSize = {
155 "width" : 0,
156 "height" : 0
157};
158
159var currentOrientation = 0;
160
161var listeners = {};
162
163/***************************************************************************
164 * "official" API: methods called by creative
165 **************************************************************************/
166
167mraid.addEventListener = function(event, listener) {
168 log.i("mraid.addEventListener " + event + ": " + String(listener));
169 if (!event || !listener) {
170 mraid.fireErrorEvent("Both event and listener are required.", "addEventListener");
171 return;
172 }
173 if (!contains(event, EVENTS)) {
174 mraid.fireErrorEvent("Unknown MRAID event: " + event, "addEventListener");
175 return;
176 }
177 var listenersForEvent = listeners[event] = listeners[event] || [];
178 // check to make sure that the listener isn't already registered
179 for (var i = 0; i < listenersForEvent.length; i++) {
180 var str1 = String(listener);
181 var str2 = String(listenersForEvent[i]);
182 if (listener === listenersForEvent[i] || str1 === str2) {
183 log.i("listener " + str1 + " is already registered for event " + event);
184 return;
185 }
186 }
187 listenersForEvent.push(listener);
188};
189
190mraid.createCalendarEvent = function(parameters) {
191 log.i("mraid.createCalendarEvent with " + parameters);
192 callNative("createCalendarEvent?eventJSON="+JSON.stringify(parameters));
193};
194
195mraid.close = function() {
196 log.i("mraid.close");
197 if (state === STATES.LOADING ||
198 (state === STATES.DEFAULT && placementType === PLACEMENT_TYPES.INLINE) ||
199 state === STATES.HIDDEN) {
200 // do nothing
201 return;
202 }
203 callNative("close");
204};
205
206mraid.expand = function(url) {
207 if (url === undefined) {
208 log.i("mraid.expand (1-part)");
209 } else {
210 log.i("mraid.expand " + url);
211 }
212 // The only time it is valid to call expand is when the ad is
213 // a banner currently in either default or resized state.
214 if (placementType !== PLACEMENT_TYPES.INLINE ||
215 (state !== STATES.DEFAULT && state !== STAES.RESIZED)) {
216 return;
217 }
218 if (url === undefined) {
219 callNative("expand");
220 } else {
221 callNative("expand?url=" + encodeURIComponent(url));
222 }
223};
224
225mraid.getCurrentPosition = function() {
226 log.i("mraid.getCurrentPosition");
227 return currentPosition;
228};
229
230mraid.getDefaultPosition = function() {
231 log.i("mraid.getDefaultPosition");
232 return defaultPosition;
233};
234
235mraid.getExpandProperties = function() {
236 log.i("mraid.getExpandProperties");
237 return expandProperties;
238};
239
240mraid.getMaxSize = function() {
241 log.i("mraid.getMaxSize " + maxSize.width + " x " + maxSize.height);
242 return maxSize;
243};
244
245mraid.getOrientationProperties = function() {
246 log.i("mraid.getOrientationProperties");
247 return orientationProperties;
248};
249
250mraid.getPlacementType = function() {
251 log.i("mraid.getPlacementType");
252 return placementType;
253};
254
255mraid.getResizeProperties = function() {
256 log.i("mraid.getResizeProperties");
257 return resizeProperties;
258};
259
260mraid.getScreenSize = function() {
261 log.i("mraid.getScreenSize");
262 return screenSize;
263};
264
265mraid.getState = function() {
266 log.i("mraid.getState");
267 return state;
268};
269
270mraid.getVersion = function() {
271 log.i("mraid.getVersion");
272 return VERSION;
273};
274
275mraid.isViewable = function() {
276 log.i("mraid.isViewable");
277 return isViewable;
278};
279
280mraid.open = function(url) {
281 log.i("mraid.open " + url);
282 callNative("open?url=" + encodeURIComponent(url));
283};
284
285mraid.playVideo = function(url) {
286 log.i("mraid.playVideo " + url);
287 callNative("playVideo?url=" + encodeURIComponent(url));
288};
289
290mraid.removeEventListener = function(event, listener) {
291 log.i("mraid.removeEventListener " + event + " : " + String(listener));
292 if (!event) {
293 mraid.fireErrorEvent("Event is required.", "removeEventListener");
294 return;
295 }
296 if (!contains(event, EVENTS)) {
297 mraid.fireErrorEvent("Unknown MRAID event: " + event, "removeEventListener");
298 return;
299 }
300 if (listeners.hasOwnProperty(event)) {
301 if (listener) {
302 var listenersForEvent = listeners[event];
303 // try to find the given listener
304 var len = listenersForEvent.length;
305 for (var i = 0; i < len; i++) {
306 var registeredListener = listenersForEvent[i];
307 var str1 = String(listener);
308 var str2 = String(registeredListener);
309 if (listener === registeredListener || str1 === str2) {
310 listenersForEvent.splice(i, 1);
311 break;
312 }
313 }
314 if (i === len) {
315 log.i("listener " + str1 + " not found for event " + event);
316 }
317 if (listenersForEvent.length === 0) {
318 delete listeners[event];
319 }
320 } else {
321 // no listener to remove was provided, so remove all listeners for given event
322 delete listeners[event];
323 }
324 } else {
325 log.i("no listeners registered for event " + event);
326 }
327};
328
329mraid.resize = function() {
330 log.i("mraid.resize");
331 // The only time it is valid to call resize is when the ad is
332 // a banner currently in either default or resized state.
333 // Trigger an error if the current state is expanded.
334 if (placementType === PLACEMENT_TYPES.INTERSTITIAL || state === STATES.LOADING || state === STATES.HIDDEN) {
335 // do nothing
336 return;
337 }
338 if (state === STATES.EXPANDED) {
339 mraid.fireErrorEvent("mraid.resize called when ad is in expanded state", "mraid.resize");
340 return;
341 }
342 if (!isResizeReady) {
343 mraid.fireErrorEvent("mraid.resize is not ready to be called", "mraid.resize");
344 return;
345 }
346 callNative("resize");
347};
348
349mraid.setExpandProperties = function(properties) {
350 log.i("mraid.setExpandProperties");
351
352 if (!validate(properties, "setExpandProperties")) {
353 log.e("failed validation");
354 return;
355 }
356
357 var oldUseCustomClose = expandProperties.useCustomClose;
358
359 // expandProperties contains 3 read-write properties: width, height, and useCustomClose;
360 // the isModal property is read-only
361 var rwProps = [ "width", "height", "useCustomClose" ];
362 for (var i = 0; i < rwProps.length; i++) {
363 var propname = rwProps[i];
364 if (properties.hasOwnProperty(propname)) {
365 expandProperties[propname] = properties[propname];
366 }
367 }
368
369 // In MRAID v2.0, all expanded ads by definition cover the entire screen,
370 // so the only property that the native side has to know about is useCustomClose.
371 // (That is, the width and height properties are not needed by the native code.)
372 if (expandProperties.useCustomClose !== oldUseCustomClose) {
373 callNative("useCustomClose?useCustomClose=" + expandProperties.useCustomClose);
374 }
375};
376
377mraid.setOrientationProperties = function(properties) {
378 log.i("mraid.setOrientationProperties");
379
380 if (!validate(properties, "setOrientationProperties")) {
381 log.e("failed validation");
382 return;
383 }
384
385 var newOrientationProperties = {};
386 newOrientationProperties.allowOrientationChange = orientationProperties.allowOrientationChange,
387 newOrientationProperties.forceOrientation = orientationProperties.forceOrientation;
388
389 // orientationProperties contains 2 read-write properties: allowOrientationChange and forceOrientation
390 var rwProps = [ "allowOrientationChange", "forceOrientation" ];
391 for (var i = 0; i < rwProps.length; i++) {
392 var propname = rwProps[i];
393 if (properties.hasOwnProperty(propname)) {
394 newOrientationProperties[propname] = properties[propname];
395 }
396 }
397
398 // Setting allowOrientationChange to true while setting forceOrientation to either portrait or landscape
399 // is considered an error condition.
400 if (newOrientationProperties.allowOrientationChange &&
401 newOrientationProperties.forceOrientation !== mraid.ORIENTATION_PROPERTIES_FORCE_ORIENTATION.NONE) {
402 mraid.fireErrorEvent("allowOrientationChange is true but forceOrientation is " + newOrientationProperties.forceOrientation,
403 "setOrientationProperties");
404 return;
405 }
406
407 orientationProperties.allowOrientationChange = newOrientationProperties.allowOrientationChange;
408 orientationProperties.forceOrientation = newOrientationProperties.forceOrientation;
409
410 var params =
411 "allowOrientationChange=" + orientationProperties.allowOrientationChange +
412 "&forceOrientation=" + orientationProperties.forceOrientation;
413
414 callNative("setOrientationProperties?" + params);
415};
416
417mraid.setResizeProperties = function(properties) {
418 log.i("mraid.setResizeProperties");
419
420 isResizeReady = false;
421
422 // resizeProperties contains 6 read-write properties:
423 // width, height, offsetX, offsetY, customClosePosition, allowOffscreen
424
425 // The properties object passed into this function must contain width, height, offsetX, offsetY.
426 // The remaining two properties are optional.
427 var requiredProps = [ "width", "height", "offsetX", "offsetY" ];
428 for (var i = 0; i < requiredProps.length; i++) {
429 var propname = requiredProps[i];
430 if (!properties.hasOwnProperty(propname)) {
431 mraid.fireErrorEvent(
432 "required property " + propname + " is missing",
433 "mraid.setResizeProperties");
434 return;
435 }
436 }
437
438 if (!validate(properties, "setResizeProperties")) {
439 mraid.fireErrorEvent("failed validation", "mraid.setResizeProperties");
440 return;
441 }
442
443 var adjustments = { "x": 0, "y": 0 };
444
445 var allowOffscreen = properties.hasOwnProperty("allowOffscreen") ? properties.allowOffscreen : resizeProperties.allowOffscreen;
446 if (!allowOffscreen) {
447 if (properties.width > maxSize.width || properties.height > maxSize.height) {
448 mraid.fireErrorEvent("resize width or height is greater than the maxSize width or height", "mraid.setResizeProperties");
449 return;
450 }
451 adjustments = fitResizeViewOnScreen(properties);
452 } else if (!isCloseRegionOnScreen(properties)) {
453 mraid.fireErrorEvent("close event region will not appear entirely onscreen", "mraid.setResizeProperties");
454 return;
455 }
456
457 var rwProps = [ "width", "height", "offsetX", "offsetY", "customClosePosition", "allowOffscreen" ];
458 for (var i = 0; i < rwProps.length; i++) {
459 var propname = rwProps[i];
460 if (properties.hasOwnProperty(propname)) {
461 resizeProperties[propname] = properties[propname];
462 }
463 }
464
465 var params =
466 "width=" + resizeProperties.width +
467 "&height=" + resizeProperties.height +
468 "&offsetX=" + (resizeProperties.offsetX + adjustments.x) +
469 "&offsetY=" + (resizeProperties.offsetY + adjustments.y) +
470 "&customClosePosition=" + resizeProperties.customClosePosition +
471 "&allowOffscreen=" + resizeProperties.allowOffscreen;
472
473 callNative("setResizeProperties?" + params);
474
475 isResizeReady = true;
476 };
477
478mraid.storePicture = function(url) {
479 log.i("mraid.storePicture " + url);
480 callNative("storePicture?url=" + encodeURIComponent(url));
481};
482
483mraid.supports = function(feature) {
484 log.i("mraid.supports " + feature + " " + supportedFeatures[feature]);
485 var retval = supportedFeatures[feature];
486 if (typeof retval === "undefined") {
487 retval = false;
488 }
489 return retval;
490};
491
492mraid.useCustomClose = function(isCustomClose) {
493 log.i("mraid.useCustomClose " + isCustomClose);
494 if (expandProperties.useCustomClose !== isCustomClose) {
495 expandProperties.useCustomClose = isCustomClose;
496 callNative("useCustomClose?useCustomClose=" + expandProperties.useCustomClose);
497 }
498};
499
500/***************************************************************************
501 * helper methods called by SDK
502 **************************************************************************/
503
504// setters to change state
505
506mraid.setCurrentPosition = function(x, y, width, height) {
507 log.i("mraid.setCurrentPosition " + x + "," + y + "," + width + "," + height);
508
509 var previousSize = {};
510 previousSize.width = currentPosition.width;
511 previousSize.height = currentPosition.height;
512 log.i("previousSize " + previousSize.width + "," + previousSize.height);
513
514 currentPosition.x = x;
515 currentPosition.y = y;
516 currentPosition.width = width;
517 currentPosition.height = height;
518
519 if (width !== previousSize.width || height !== previousSize.height) {
520 mraid.fireSizeChangeEvent(width, height);
521 }
522};
523
524mraid.setDefaultPosition = function(x, y, width, height) {
525 log.i("mraid.setDefaultPosition " + x + "," + y + "," + width + "," + height);
526 defaultPosition.x = x;
527 defaultPosition.y = y;
528 defaultPosition.width = width;
529 defaultPosition.height = height;
530};
531
532mraid.setExpandSize = function(width, height) {
533 log.i("mraid.setExpandSize " + width + "x" + height);
534 expandProperties.width = width;
535 expandProperties.height = height;
536};
537
538mraid.setMaxSize = function(width, height) {
539 log.i("mraid.setMaxSize " + width + "x" + height);
540 maxSize.width = width;
541 maxSize.height = height;
542};
543
544mraid.setPlacementType = function(pt) {
545 log.i("mraid.setPlacementType " + pt);
546 placementType = pt;
547};
548
549mraid.setScreenSize = function(width, height) {
550 log.i("mraid.setScreenSize " + width + "x" + height);
551 screenSize.width = width;
552 screenSize.height = height;
553};
554
555mraid.setSupports = function(feature, supported) {
556 log.i("mraid.setSupports " + feature + " " + supported);
557 supportedFeatures[feature] = supported;
558};
559
560// methods to fire events
561
562mraid.fireErrorEvent = function(message, action) {
563 log.i("mraid.fireErrorEvent " + message + " " + action);
564 fireEvent(mraid.EVENTS.ERROR, message, action);
565};
566
567mraid.fireReadyEvent = function() {
568 log.i("mraid.fireReadyEvent");
569 fireEvent(mraid.EVENTS.READY);
570};
571
572mraid.fireSizeChangeEvent = function(width, height) {
573 log.i("mraid.fireSizeChangeEvent " + width + "x" + height);
574 fireEvent(mraid.EVENTS.SIZECHANGE, width, height);
575};
576
577mraid.fireStateChangeEvent = function(newState) {
578 log.i("mraid.fireStateChangeEvent " + newState);
579 if (state !== newState) {
580 state = newState;
581 fireEvent(mraid.EVENTS.STATECHANGE, state);
582 }
583};
584
585mraid.fireViewableChangeEvent = function(newIsViewable) {
586 log.i("mraid.fireViewableChangeEvent " + newIsViewable);
587 if (isViewable !== newIsViewable) {
588 isViewable = newIsViewable;
589 fireEvent(mraid.EVENTS.VIEWABLECHANGE, isViewable);
590 }
591};
592
593/***************************************************************************
594 * internal helper methods
595 **************************************************************************/
596
597var callNative = function(command) {
598 window.webkit.messageHandlers.observe.postMessage(command);
599};
600
601var fireEvent = function(event) {
602 var args = Array.prototype.slice.call(arguments);
603 args.shift();
604 log.i("fireEvent " + event + " [" + args.toString() + "]");
605
606 var tempEventListeners = listeners[event];
607 if (tempEventListeners) {
608 var eventListeners = tempEventListeners.slice();
609 var len = eventListeners.length;
610 log.i(len + " listener(s) found");
611 for (var i = 0; i < len; i++) {
612 eventListeners[i].apply(null, args);
613 }
614 } else {
615 log.i("no listeners found for " + event);
616 }
617 };
618
619var contains = function(value, array) {
620 for (var i in array) {
621 if (array[i] === value) {
622 return true;
623 }
624 }
625 return false;
626};
627
628// The action parameter is a string which is the name of the setter function which called this function
629// (in other words, setExpandPropeties, setOrientationProperties, or setResizeProperties).
630// It serves both as the key to get the the appropriate set of validating functions from the allValidators object
631// as well as the action parameter of any error event that may be thrown.
632var validate = function(properties, action) {
633 var retval = true;
634 var validators = allValidators[action];
635 for (var prop in properties) {
636 var validator = validators[prop];
637 var value = properties[prop];
638 if (validator && !validator(value)) {
639 mraid.fireErrorEvent("Value of property " + prop + " (" + value + ") is invalid", "mraid." + action);
640 retval = false;
641 }
642 }
643 return retval;
644};
645
646var allValidators = {
647 "setExpandProperties": {
648 // In MRAID 2.0, the only property in expandProperties we actually care about is useCustomClose.
649 // Still, we'll do a basic sanity check on the width and height properties, too.
650 "width" : function(width) {
651 return !isNaN(width);
652 },
653 "height" : function(height) {
654 return !isNaN(height);
655 },
656 "useCustomClose" : function(useCustomClose) {
657 return (typeof useCustomClose === "boolean");
658 }
659 },
660 "setOrientationProperties": {
661 "allowOrientationChange" : function(allowOrientationChange) {
662 return (typeof allowOrientationChange === "boolean");
663 },
664 "forceOrientation" : function(forceOrientation) {
665 var validValues = [ "portrait","landscape","none" ];
666 return validValues.indexOf(forceOrientation) !== -1;
667 }
668 },
669 "setResizeProperties": {
670 "width" : function(width) {
671 return !isNaN(width) && width >= 50;
672 },
673 "height" : function(height) {
674 return !isNaN(height) && height >= 50;
675 },
676 "offsetX" : function(offsetX) {
677 return !isNaN(offsetX);
678 },
679 "offsetY" : function(offsetY) {
680 return !isNaN(offsetY);
681 },
682 "customClosePosition" : function(customClosePosition) {
683 var validPositions = [ "top-left","top-center","top-right","center","bottom-left","bottom-center","bottom-right" ];
684 return validPositions.indexOf(customClosePosition) !== -1;
685 },
686 "allowOffscreen" : function(allowOffscreen) {
687 return (typeof allowOffscreen === "boolean");
688 }
689 }
690};
691
692function isCloseRegionOnScreen(properties) {
693 log.d("isCloseRegionOnScreen");
694 log.d("defaultPosition " + defaultPosition.x + " " + defaultPosition.y);
695 log.d("offset " + properties.offsetX + " " + properties.offsetY);
696
697 var resizeRect = {};
698 resizeRect.x = defaultPosition.x + properties.offsetX;
699 resizeRect.y = defaultPosition.y + properties.offsetY;
700 resizeRect.width = properties.width;
701 resizeRect.height = properties.height;
702 printRect("resizeRect", resizeRect);
703
704 var customClosePosition = properties.hasOwnProperty("customClosePosition") ?
705 properties.customClosePosition : resizeProperties.customClosePosition;
706 log.d("customClosePosition " + customClosePosition);
707
708 var closeRect = { "width": 50, "height": 50 };
709
710 if (customClosePosition.search("left") !== -1) {
711 closeRect.x = resizeRect.x;
712 } else if (customClosePosition.search("center") !== -1) {
713 closeRect.x = resizeRect.x + (resizeRect.width / 2) - 25;
714 } else if (customClosePosition.search("right") !== -1) {
715 closeRect.x = resizeRect.x + resizeRect.width - 50;
716 }
717
718 if (customClosePosition.search("top") !== -1) {
719 closeRect.y = resizeRect.y;
720 } else if (customClosePosition === "center") {
721 closeRect.y = resizeRect.y + (resizeRect.height / 2) - 25;
722 } else if (customClosePosition.search("bottom") !== -1) {
723 closeRect.y = resizeRect.y + resizeRect.height - 50;
724 }
725
726 var maxRect = { "x": 0, "y": 0 };
727 maxRect.width = maxSize.width;
728 maxRect.height = maxSize.height;
729
730 return isRectContained(maxRect, closeRect);
731}
732
733function fitResizeViewOnScreen(properties) {
734 log.d("fitResizeViewOnScreen");
735 log.d("defaultPosition " + defaultPosition.x + " " + defaultPosition.y);
736 log.d("offset " + properties.offsetX + " " + properties.offsetY);
737
738 var resizeRect = {};
739 resizeRect.x = defaultPosition.x + properties.offsetX;
740 resizeRect.y = defaultPosition.y + properties.offsetY;
741 resizeRect.width = properties.width;
742 resizeRect.height = properties.height;
743 printRect("resizeRect", resizeRect);
744
745 var maxRect = { "x": 0, "y": 0 };
746 maxRect.width = maxSize.width;
747 maxRect.height = maxSize.height;
748
749 var adjustments = { "x": 0, "y": 0 };
750
751 if (isRectContained(maxRect, resizeRect)) {
752 log.d("no adjustment necessary");
753 return adjustments;
754 }
755
756 if (resizeRect.x < maxRect.x) {
757 adjustments.x = maxRect.x - resizeRect.x;
758 } else if ((resizeRect.x + resizeRect.width) > (maxRect.x + maxRect.width)) {
759 adjustments.x = (maxRect.x + maxRect.width) - (resizeRect.x + resizeRect.width);
760 }
761 log.d("adjustments.x " + adjustments.x);
762
763 if (resizeRect.y < maxRect.y) {
764 adjustments.y = maxRect.y - resizeRect.y;
765 } else if ((resizeRect.y + resizeRect.height) > (maxRect.y + maxRect.height)) {
766 adjustments.y = (maxRect.y + maxRect.height) - (resizeRect.y + resizeRect.height);
767 }
768 log.d("adjustments.y " + adjustments.y);
769
770 resizeRect.x = defaultPosition.x + properties.offsetX + adjustments.x;
771 resizeRect.y = defaultPosition.y + properties.offsetY + adjustments.y;
772 printRect("adjusted resizeRect", resizeRect);
773
774 return adjustments;
775}
776
777function isRectContained(containingRect, containedRect) {
778 log.d("isRectContained");
779 printRect("containingRect", containingRect);
780 printRect("containedRect", containedRect);
781 return (containedRect.x >= containingRect.x &&
782 (containedRect.x + containedRect.width) <= (containingRect.x + containingRect.width) &&
783 containedRect.y >= containingRect.y &&
784 (containedRect.y + containedRect.height) <= (containingRect.y + containingRect.height));
785}
786
787
788function printRect(label, rect) {
789 log.d(label +
790 " [" + rect.x + "," + rect.y + "]" +
791 ",[" + (rect.x + rect.width) + "," + (rect.y + rect.height) + "]" +
792 " (" + rect.width + "x" + rect.height + ")");
793}
794
795mraid.dumpListeners = function() {
796 var nEvents = Object.keys(listeners).length
797 log.i("dumping listeners (" + nEvents + " events)");
798 for (var event in listeners) {
799 var eventListeners = listeners[event];
800 log.i(" " + event + " contains " + eventListeners.length + " listeners");
801 for (var i = 0; i < eventListeners.length; i++) {
802 log.i(" " + eventListeners[i]);
803 }
804 }
805};
806
807 }());