upjs-rails 0.8.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +6 -3
  3. data/dist/up-bootstrap.css +5 -0
  4. data/dist/up-bootstrap.js +14 -0
  5. data/dist/up-bootstrap.min.css +1 -0
  6. data/dist/up-bootstrap.min.js +1 -0
  7. data/dist/up.css +22 -36
  8. data/dist/up.js +300 -137
  9. data/dist/up.min.css +1 -1
  10. data/dist/up.min.js +2 -2
  11. data/lib/assets/javascripts/up/browser.js.coffee +9 -35
  12. data/lib/assets/javascripts/up/bus.js.coffee +10 -10
  13. data/lib/assets/javascripts/up/modal.js.coffee +98 -40
  14. data/lib/assets/javascripts/up/motion.js.coffee +13 -13
  15. data/lib/assets/javascripts/up/navigation.js.coffee +28 -3
  16. data/lib/assets/javascripts/up/popup.js.coffee +14 -12
  17. data/lib/assets/javascripts/up/proxy.js.coffee +21 -24
  18. data/lib/assets/javascripts/up/util.js.coffee +72 -9
  19. data/lib/assets/javascripts/up/viewport.js.coffee +10 -8
  20. data/lib/assets/javascripts/up-bootstrap/modal-ext.js.coffee +16 -0
  21. data/lib/assets/javascripts/up-bootstrap.js.coffee +1 -0
  22. data/lib/assets/stylesheets/up/modal.css.sass +37 -24
  23. data/lib/assets/stylesheets/up/popup.css.sass +1 -6
  24. data/lib/assets/stylesheets/up-bootstrap/modal-ext.css.sass +9 -0
  25. data/lib/assets/stylesheets/up-bootstrap.css.sass +1 -0
  26. data/lib/assets/stylesheets/up.css.sass +3 -0
  27. data/lib/upjs/rails/version.rb +1 -1
  28. data/spec_app/Gemfile.lock +1 -1
  29. data/spec_app/spec/javascripts/up/modal_spec.js.coffee +26 -0
  30. data/spec_app/spec/javascripts/up/navigation_spec.js.coffee +6 -0
  31. data/spec_app/spec/javascripts/up/util_spec.js.coffee +24 -0
  32. metadata +11 -3
  33. data/lib/assets/stylesheets/up.css +0 -3
data/dist/up.js CHANGED
@@ -25,7 +25,22 @@ If you use them in your own code, you will get hurt.
25
25
  var slice = [].slice;
26
26
 
27
27
  up.util = (function() {
28
- var $createElementFromSelector, ANIMATION_PROMISE_KEY, CONSOLE_PLACEHOLDERS, ajax, castsToFalse, castsToTrue, clientSize, compact, contains, copy, copyAttributes, createElement, createElementFromHtml, createSelectorFromElement, cssAnimate, debug, detect, each, error, escapePressed, extend, findWithSelf, finishCssAnimate, forceCompositing, get, ifGiven, isArray, isBlank, isDeferred, isDefined, isElement, isFunction, isGiven, isHash, isJQuery, isMissing, isNull, isObject, isPresent, isPromise, isStandardPort, isString, isUndefined, isUnmodifiedKeyEvent, isUnmodifiedMouseEvent, keys, last, locationFromXhr, measure, merge, methodFromXhr, nextFrame, normalizeMethod, normalizeUrl, nullJquery, only, option, options, prependGhost, presence, presentAttr, remove, resolvableWhen, resolvedDeferred, resolvedPromise, select, setMissingAttrs, stringifyConsoleArgs, temporaryCss, times, toArray, trim, unwrap, warn;
28
+ var $createElementFromSelector, ANIMATION_PROMISE_KEY, CONSOLE_PLACEHOLDERS, ajax, castsToFalse, castsToTrue, clientSize, compact, config, contains, copy, copyAttributes, createElement, createElementFromHtml, createSelectorFromElement, cssAnimate, debug, detect, each, error, escapePressed, extend, findWithSelf, finishCssAnimate, forceCompositing, get, ifGiven, isArray, isBlank, isDeferred, isDefined, isElement, isFunction, isGiven, isHash, isJQuery, isMissing, isNull, isObject, isPresent, isPromise, isStandardPort, isString, isUndefined, isUnmodifiedKeyEvent, isUnmodifiedMouseEvent, keys, last, locationFromXhr, measure, memoize, merge, methodFromXhr, nextFrame, normalizeMethod, normalizeUrl, nullJquery, once, only, option, options, prependGhost, presence, presentAttr, remove, resolvableWhen, resolvedDeferred, resolvedPromise, scrollbarWidth, select, setMissingAttrs, stringifyConsoleArgs, temporaryCss, times, toArray, trim, uniq, unwrap, warn;
29
+ memoize = function(func) {
30
+ var cache, cached;
31
+ cache = void 0;
32
+ cached = false;
33
+ return function() {
34
+ var args;
35
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
36
+ if (cached) {
37
+ return cache;
38
+ } else {
39
+ cached = true;
40
+ return cache = func.apply(null, args);
41
+ }
42
+ };
43
+ };
29
44
  get = function(url, options) {
30
45
  options = options || {};
31
46
  options.url = url;
@@ -418,6 +433,17 @@ If you use them in your own code, you will get hurt.
418
433
  compact = function(array) {
419
434
  return select(array, isGiven);
420
435
  };
436
+ uniq = function(array) {
437
+ var seen;
438
+ seen = {};
439
+ return select(array, function(element) {
440
+ if (seen.hasOwnProperty(element)) {
441
+ return false;
442
+ } else {
443
+ return seen[element] = true;
444
+ }
445
+ });
446
+ };
421
447
  select = function(array, tester) {
422
448
  var matches;
423
449
  matches = [];
@@ -456,6 +482,41 @@ If you use them in your own code, you will get hurt.
456
482
  height: element.clientHeight
457
483
  };
458
484
  };
485
+ scrollbarWidth = memoize(function() {
486
+ var $outer, outer, width;
487
+ $outer = $('<div>').css({
488
+ position: 'absolute',
489
+ top: '0',
490
+ left: '0',
491
+ width: '50px',
492
+ height: '50px',
493
+ overflowY: 'scroll'
494
+ });
495
+ $outer.appendTo(document.body);
496
+ outer = $outer.get(0);
497
+ width = outer.offsetWidth - outer.clientWidth;
498
+ $outer.remove();
499
+ return width;
500
+ });
501
+
502
+ /**
503
+ Modifies the given function so it only runs once.
504
+ Subsequent calls will return the previous return value.
505
+
506
+ @method up.util.once
507
+ @private
508
+ */
509
+ once = function(fun) {
510
+ var result;
511
+ result = void 0;
512
+ return function() {
513
+ if (fun != null) {
514
+ result = fun();
515
+ }
516
+ fun = void 0;
517
+ return result;
518
+ };
519
+ };
459
520
  temporaryCss = function($element, css, block) {
460
521
  var memo, oldCss;
461
522
  oldCss = $element.css(keys(css));
@@ -467,7 +528,7 @@ If you use them in your own code, you will get hurt.
467
528
  block();
468
529
  return memo();
469
530
  } else {
470
- return memo;
531
+ return once(memo);
471
532
  }
472
533
  };
473
534
  forceCompositing = function($element) {
@@ -630,8 +691,8 @@ If you use them in your own code, you will get hurt.
630
691
  escapePressed = function(event) {
631
692
  return event.keyCode === 27;
632
693
  };
633
- contains = function(array, element) {
634
- return array.indexOf(element) >= 0;
694
+ contains = function(stringOrArray, element) {
695
+ return stringOrArray.indexOf(element) >= 0;
635
696
  };
636
697
  castsToTrue = function(object) {
637
698
  return String(object) === "true";
@@ -717,6 +778,31 @@ If you use them in your own code, you will get hurt.
717
778
  return element;
718
779
  }
719
780
  };
781
+ config = function(factoryOptions) {
782
+ var apiKeys, hash;
783
+ if (factoryOptions == null) {
784
+ factoryOptions = {};
785
+ }
786
+ hash = {
787
+ reset: function() {
788
+ var j, key, len, ownKeys;
789
+ ownKeys = Object.getOwnPropertyNames(hash);
790
+ for (j = 0, len = ownKeys.length; j < len; j++) {
791
+ key = ownKeys[j];
792
+ if (!contains(apiKeys, key)) {
793
+ delete hash[key];
794
+ }
795
+ }
796
+ return hash.update(copy(factoryOptions));
797
+ },
798
+ update: function(options) {
799
+ return extend(hash, options);
800
+ }
801
+ };
802
+ apiKeys = Object.getOwnPropertyNames(hash);
803
+ hash.reset();
804
+ return hash;
805
+ };
720
806
  return {
721
807
  presentAttr: presentAttr,
722
808
  createElement: createElement,
@@ -740,6 +826,7 @@ If you use them in your own code, you will get hurt.
740
826
  detect: detect,
741
827
  select: select,
742
828
  compact: compact,
829
+ uniq: uniq,
743
830
  last: last,
744
831
  isNull: isNull,
745
832
  isDefined: isDefined,
@@ -787,7 +874,10 @@ If you use them in your own code, you will get hurt.
787
874
  resolvedDeferred: resolvedDeferred,
788
875
  resolvableWhen: resolvableWhen,
789
876
  setMissingAttrs: setMissingAttrs,
790
- remove: remove
877
+ remove: remove,
878
+ memoize: memoize,
879
+ scrollbarWidth: scrollbarWidth,
880
+ config: config
791
881
  };
792
882
  })();
793
883
 
@@ -797,17 +887,16 @@ If you use them in your own code, you will get hurt.
797
887
  Browser interface
798
888
  =================
799
889
 
800
- Some browser-interfacing methods and switches that we can't currently get rid off.
890
+ Some browser-interfacing methods and switches that
891
+ we can't currently get rid off.
801
892
 
802
893
  @protected
803
894
  @class up.browser
804
895
  */
805
896
 
806
897
  (function() {
807
- var slice = [].slice;
808
-
809
898
  up.browser = (function() {
810
- var canCssAnimation, canInputEvent, canPushState, ensureConsoleExists, ensureRecentJquery, isSupported, loadPage, memoize, u, url;
899
+ var canCssAnimation, canInputEvent, canPushState, ensureConsoleExists, ensureRecentJquery, isSupported, loadPage, u, url;
811
900
  u = up.util;
812
901
  loadPage = function(url, options) {
813
902
  var $form, csrfParam, csrfToken, metadataInput, method, target;
@@ -851,28 +940,13 @@ Some browser-interfacing methods and switches that we can't currently get rid of
851
940
  (base6 = window.console).groupCollapsed || (base6.groupCollapsed = noop);
852
941
  return (base7 = window.console).groupEnd || (base7.groupEnd = noop);
853
942
  };
854
- memoize = function(func) {
855
- var cache, cached;
856
- cache = void 0;
857
- cached = false;
858
- return function() {
859
- var args;
860
- args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
861
- if (cached) {
862
- return cache;
863
- } else {
864
- cached = true;
865
- return cache = func.apply(null, args);
866
- }
867
- };
868
- };
869
- canPushState = memoize(function() {
943
+ canPushState = u.memoize(function() {
870
944
  return u.isDefined(history.pushState);
871
945
  });
872
- canCssAnimation = memoize(function() {
946
+ canCssAnimation = u.memoize(function() {
873
947
  return 'transition' in document.documentElement.style;
874
948
  });
875
- canInputEvent = memoize(function() {
949
+ canInputEvent = u.memoize(function() {
876
950
  return 'oninput' in document.createElement('input');
877
951
  });
878
952
  ensureRecentJquery = function() {
@@ -884,7 +958,7 @@ Some browser-interfacing methods and switches that we can't currently get rid of
884
958
  compatible = major >= 2 || (major === 1 && minor >= 9);
885
959
  return compatible || u.error("jQuery %o found, but Up.js requires 1.9+", version);
886
960
  };
887
- isSupported = memoize(function() {
961
+ isSupported = u.memoize(function() {
888
962
  return u.isDefined(document.addEventListener);
889
963
  });
890
964
  return {
@@ -954,6 +1028,17 @@ We need to work on this page:
954
1028
  u = up.util;
955
1029
  callbacksByEvent = {};
956
1030
  defaultCallbacksByEvent = {};
1031
+
1032
+ /**
1033
+ Resets the list of registered event listeners to the
1034
+ moment when the framework was booted.
1035
+
1036
+ @private
1037
+ @method up.bus.reset
1038
+ */
1039
+ reset = function() {
1040
+ return callbacksByEvent = u.copy(defaultCallbacksByEvent);
1041
+ };
957
1042
  callbacksFor = function(event) {
958
1043
  return callbacksByEvent[event] || (callbacksByEvent[event] = []);
959
1044
  };
@@ -976,17 +1061,6 @@ We need to work on this page:
976
1061
  return results;
977
1062
  };
978
1063
 
979
- /**
980
- Resets the list of registered event listeners to the
981
- moment when the framework was booted.
982
-
983
- @private
984
- @method up.bus.reset
985
- */
986
- reset = function() {
987
- return callbacksByEvent = u.copy(defaultCallbacksByEvent);
988
- };
989
-
990
1064
  /**
991
1065
  Registers an event handler to be called when the given
992
1066
  event is triggered.
@@ -1087,13 +1161,8 @@ By default Up.js will always scroll to an element before updating it.
1087
1161
 
1088
1162
  (function() {
1089
1163
  up.viewport = (function() {
1090
- var SCROLL_PROMISE_KEY, config, defaults, finishScrolling, reveal, scroll, u;
1164
+ var SCROLL_PROMISE_KEY, config, finishScrolling, reset, reveal, scroll, u;
1091
1165
  u = up.util;
1092
- config = {
1093
- duration: 0,
1094
- view: 'body',
1095
- easing: 'swing'
1096
- };
1097
1166
 
1098
1167
  /**
1099
1168
  @method up.viewport.defaults
@@ -1102,8 +1171,13 @@ By default Up.js will always scroll to an element before updating it.
1102
1171
  @param {Number} [options.padding]
1103
1172
  @param {String|Element|jQuery} [options.view]
1104
1173
  */
1105
- defaults = function(options) {
1106
- return u.extend(config, options);
1174
+ config = u.config({
1175
+ duration: 0,
1176
+ view: 'body',
1177
+ easing: 'swing'
1178
+ });
1179
+ reset = function() {
1180
+ return config.reset();
1107
1181
  };
1108
1182
  SCROLL_PROMISE_KEY = 'up-scroll-promise';
1109
1183
 
@@ -1193,11 +1267,12 @@ By default Up.js will always scroll to an element before updating it.
1193
1267
  return u.resolvedDeferred();
1194
1268
  }
1195
1269
  };
1270
+ up.bus.on('framework:reset', reset);
1196
1271
  return {
1197
1272
  reveal: reveal,
1198
1273
  scroll: scroll,
1199
1274
  finishScrolling: finishScrolling,
1200
- defaults: defaults
1275
+ defaults: config.update
1201
1276
  };
1202
1277
  })();
1203
1278
 
@@ -2130,26 +2205,30 @@ We need to work on this page:
2130
2205
 
2131
2206
  (function() {
2132
2207
  up.motion = (function() {
2133
- var GHOSTING_PROMISE_KEY, animate, animateOptions, animation, animations, assertIsDeferred, config, defaultAnimations, defaultTransitions, defaults, findAnimation, finish, finishGhosting, morph, none, reset, resolvableWhen, snapshot, transition, transitions, u, withGhosts;
2208
+ var GHOSTING_PROMISE_KEY, animate, animateOptions, animation, animations, assertIsDeferred, config, defaultAnimations, defaultTransitions, findAnimation, finish, finishGhosting, morph, none, reset, resolvableWhen, snapshot, transition, transitions, u, withGhosts;
2134
2209
  u = up.util;
2135
2210
  animations = {};
2136
2211
  defaultAnimations = {};
2137
2212
  transitions = {};
2138
2213
  defaultTransitions = {};
2139
- config = {
2140
- duration: 300,
2141
- delay: 0,
2142
- easing: 'ease'
2143
- };
2144
2214
 
2145
2215
  /**
2216
+ Sets default options for animations and transitions.
2217
+
2146
2218
  @method up.motion.defaults
2147
2219
  @param {Number} [options.duration=300]
2148
2220
  @param {Number} [options.delay=0]
2149
2221
  @param {String} [options.easing='ease']
2150
2222
  */
2151
- defaults = function(options) {
2152
- return u.extend(config, options);
2223
+ config = u.config({
2224
+ duration: 300,
2225
+ delay: 0,
2226
+ easing: 'ease'
2227
+ });
2228
+ reset = function() {
2229
+ animations = u.copy(defaultAnimations);
2230
+ transitions = u.copy(defaultTransitions);
2231
+ return config.reset();
2153
2232
  };
2154
2233
 
2155
2234
  /**
@@ -2473,10 +2552,6 @@ We need to work on this page:
2473
2552
  defaultAnimations = u.copy(animations);
2474
2553
  return defaultTransitions = u.copy(transitions);
2475
2554
  };
2476
- reset = function() {
2477
- animations = u.copy(defaultAnimations);
2478
- return transitions = u.copy(defaultTransitions);
2479
- };
2480
2555
 
2481
2556
  /**
2482
2557
  Returns a new promise that resolves once all promises in arguments resolve.
@@ -2640,7 +2715,7 @@ We need to work on this page:
2640
2715
  finish: finish,
2641
2716
  transition: transition,
2642
2717
  animation: animation,
2643
- defaults: defaults,
2718
+ defaults: config.update,
2644
2719
  none: none,
2645
2720
  when: resolvableWhen
2646
2721
  };
@@ -2710,21 +2785,36 @@ You can change (or remove) this delay like this:
2710
2785
 
2711
2786
  (function() {
2712
2787
  up.proxy = (function() {
2713
- var $waitingLink, FACTORY_CONFIG, SAFE_HTTP_METHODS, ajax, alias, busy, busyDelayTimer, busyEventEmitted, cache, cacheKey, cancelBusyDelay, cancelPreloadDelay, checkPreload, clear, config, defaults, get, idle, isFresh, isIdempotent, load, loadEnded, loadStarted, normalizeRequest, pendingCount, preload, preloadDelayTimer, remove, reset, set, startPreloadDelay, timestamp, trim, u;
2788
+ var $waitingLink, SAFE_HTTP_METHODS, ajax, alias, busy, busyDelayTimer, busyEventEmitted, cache, cacheKey, cancelBusyDelay, cancelPreloadDelay, checkPreload, clear, config, get, idle, isFresh, isIdempotent, load, loadEnded, loadStarted, normalizeRequest, pendingCount, preload, preloadDelayTimer, remove, reset, set, startPreloadDelay, timestamp, trim, u;
2714
2789
  u = up.util;
2715
2790
  cache = void 0;
2716
2791
  $waitingLink = void 0;
2717
2792
  preloadDelayTimer = void 0;
2718
2793
  busyDelayTimer = void 0;
2719
2794
  pendingCount = void 0;
2720
- config = void 0;
2721
2795
  busyEventEmitted = void 0;
2722
- FACTORY_CONFIG = {
2796
+
2797
+ /**
2798
+ @method up.proxy.defaults
2799
+ @param {Number} [options.preloadDelay=75]
2800
+ The number of milliseconds to wait before [`[up-preload]`](#up-preload)
2801
+ starts preloading.
2802
+ @param {Number} [options.cacheSize=70]
2803
+ The maximum number of responses to cache.
2804
+ If the size is exceeded, the oldest items will be dropped from the cache.
2805
+ @param {Number} [options.cacheExpiry=300000]
2806
+ The number of milliseconds until a cache entry expires.
2807
+ Defaults to 5 minutes.
2808
+ @param {Number} [options.busyDelay=300]
2809
+ How long the proxy waits until emitting the `proxy:busy` [event](/up.bus).
2810
+ Use this to prevent flickering of spinners.
2811
+ */
2812
+ config = u.config({
2723
2813
  busyDelay: 300,
2724
2814
  preloadDelay: 75,
2725
2815
  cacheSize: 70,
2726
2816
  cacheExpiry: 1000 * 60 * 5
2727
- };
2817
+ });
2728
2818
  cancelPreloadDelay = function() {
2729
2819
  clearTimeout(preloadDelayTimer);
2730
2820
  return preloadDelayTimer = null;
@@ -2739,29 +2829,10 @@ You can change (or remove) this delay like this:
2739
2829
  cancelPreloadDelay();
2740
2830
  cancelBusyDelay();
2741
2831
  pendingCount = 0;
2742
- config = u.copy(FACTORY_CONFIG);
2832
+ config.reset();
2743
2833
  return busyEventEmitted = false;
2744
2834
  };
2745
2835
  reset();
2746
-
2747
- /**
2748
- @method up.proxy.defaults
2749
- @param {Number} [options.preloadDelay=75]
2750
- The number of milliseconds to wait before [`[up-preload]`](#up-preload)
2751
- starts preloading.
2752
- @param {Number} [options.cacheSize=70]
2753
- The maximum number of responses to cache.
2754
- If the size is exceeded, the oldest items will be dropped from the cache.
2755
- @param {Number} [options.cacheExpiry=300000]
2756
- The number of milliseconds until a cache entry expires.
2757
- Defaults to 5 minutes.
2758
- @param {Number} [options.busyDelay=300]
2759
- How long the proxy waits until emitting the `proxy:busy` [event](/up.bus).
2760
- Use this to prevent flickering of spinners.
2761
- */
2762
- defaults = function(options) {
2763
- return u.extend(config, options);
2764
- };
2765
2836
  cacheKey = function(request) {
2766
2837
  normalizeRequest(request);
2767
2838
  return [request.url, request.method, request.data, request.selector].join('|');
@@ -3014,7 +3085,6 @@ You can change (or remove) this delay like this:
3014
3085
  return u.resolvedPromise();
3015
3086
  }
3016
3087
  };
3017
- up.bus.on('framework:reset', reset);
3018
3088
 
3019
3089
  /**
3020
3090
  Links with an `up-preload` attribute will silently fetch their target
@@ -3035,6 +3105,7 @@ You can change (or remove) this delay like this:
3035
3105
  return checkPreload($element);
3036
3106
  }
3037
3107
  });
3108
+ up.bus.on('framework:reset', reset);
3038
3109
  return {
3039
3110
  preload: preload,
3040
3111
  ajax: ajax,
@@ -3045,7 +3116,7 @@ You can change (or remove) this delay like this:
3045
3116
  remove: remove,
3046
3117
  idle: idle,
3047
3118
  busy: busy,
3048
- defaults: defaults
3119
+ defaults: config.update
3049
3120
  };
3050
3121
  })();
3051
3122
 
@@ -3781,22 +3852,23 @@ We need to work on this page:
3781
3852
 
3782
3853
  (function() {
3783
3854
  up.popup = (function() {
3784
- var autoclose, close, config, contains, createHiddenPopup, currentSource, defaults, discardHistory, ensureInViewport, open, rememberHistory, setPosition, source, u, updated;
3855
+ var autoclose, close, config, contains, createHiddenPopup, currentSource, discardHistory, ensureInViewport, open, rememberHistory, reset, setPosition, source, u, updated;
3785
3856
  u = up.util;
3786
3857
  currentSource = void 0;
3787
- config = {
3788
- openAnimation: 'fade-in',
3789
- closeAnimation: 'fade-out',
3790
- position: 'bottom-right'
3791
- };
3792
3858
 
3793
3859
  /**
3794
3860
  @method up.popup.defaults
3795
3861
  @param {String} options.animation
3796
3862
  @param {String} options.position
3797
3863
  */
3798
- defaults = function(options) {
3799
- return u.extend(config, options);
3864
+ config = u.config({
3865
+ openAnimation: 'fade-in',
3866
+ closeAnimation: 'fade-out',
3867
+ position: 'bottom-right'
3868
+ });
3869
+ reset = function() {
3870
+ close();
3871
+ return config.reset();
3800
3872
  };
3801
3873
  setPosition = function($link, $popup, position) {
3802
3874
  var css, linkBox;
@@ -3971,6 +4043,8 @@ We need to work on this page:
3971
4043
  });
3972
4044
  currentSource = void 0;
3973
4045
  return up.destroy($popup, options);
4046
+ } else {
4047
+ return u.resolvedPromise();
3974
4048
  }
3975
4049
  };
3976
4050
  autoclose = function() {
@@ -4051,12 +4125,12 @@ We need to work on this page:
4051
4125
  return close();
4052
4126
  }
4053
4127
  });
4054
- up.bus.on('framework:reset', close);
4128
+ up.bus.on('framework:reset', reset);
4055
4129
  return {
4056
4130
  open: open,
4057
4131
  close: close,
4058
4132
  source: source,
4059
- defaults: defaults,
4133
+ defaults: config.update,
4060
4134
  contains: contains
4061
4135
  };
4062
4136
  })();
@@ -4079,34 +4153,32 @@ For small popup overlays ("dropdowns") see [up.popup](/up.popup) instead.
4079
4153
  var slice = [].slice;
4080
4154
 
4081
4155
  up.modal = (function() {
4082
- var autoclose, close, config, contains, createHiddenModal, currentSource, defaults, discardHistory, open, rememberHistory, source, templateHtml, u, updated;
4156
+ var autoclose, close, config, contains, createHiddenModal, currentSource, discardHistory, open, rememberHistory, reset, shiftBody, source, templateHtml, u, unshiftBody, updated;
4083
4157
  u = up.util;
4084
- currentSource = void 0;
4085
- config = {
4086
- width: 'auto',
4087
- height: 'auto',
4088
- openAnimation: 'fade-in',
4089
- closeAnimation: 'fade-out',
4090
- closeLabel: 'X',
4091
- template: function(config) {
4092
- return "<div class=\"up-modal\">\n <div class=\"up-modal-dialog\">\n <div class=\"up-modal-close\" up-close>" + config.closeLabel + "</div>\n <div class=\"up-modal-content\"></div>\n </div>\n</div>";
4093
- }
4094
- };
4095
4158
 
4096
4159
  /**
4097
4160
  Sets default options for future modals.
4098
4161
 
4099
4162
  @method up.modal.defaults
4100
- @param {Number} [options.width='auto']
4101
- The width of the dialog in pixels.
4102
- Defaults to `'auto'`, meaning that the dialog will grow to fit its contents.
4163
+ @param {Number} [options.width]
4164
+ The width of the dialog as a CSS value like `'400px'` or `50%`.
4165
+
4166
+ Defaults to `undefined`, meaning that the dialog will grow to fit its contents
4167
+ until it reaches `options.maxWidth`. Leaving this as `undefined` will
4168
+ also allow you to control the width using CSS.
4169
+ @param {Number} [options.maxWidth]
4170
+ The width of the dialog as a CSS value like `'400px'` or `50%`.
4171
+ You can set this to `undefined` to make the dialog fit its contents.
4172
+ Be aware however, that e.g. Bootstrap stretches input elements
4173
+ to `width: 100%`, meaning the dialog will also stretch to the full
4174
+ width of the screen.
4103
4175
  @param {Number} [options.height='auto']
4104
4176
  The height of the dialog in pixels.
4105
- Defaults to `'auto'`, meaning that the dialog will grow to fit its contents.
4177
+ Defaults to `undefined`, meaning that the dialog will grow to fit its contents.
4106
4178
  @param {String|Function(config)} [options.template]
4107
4179
  A string containing the HTML structure of the modal.
4108
4180
  You can supply an alternative template string, but make sure that it
4109
- contains tags with the classes `up-modal`, `up-modal-dialog` and `up-modal-content`.
4181
+ contains a containing tag with the class `up-modal`.
4110
4182
 
4111
4183
  You can also supply a function that returns a HTML string.
4112
4184
  The function will be called with the modal options (merged from these defaults
@@ -4120,8 +4192,23 @@ For small popup overlays ("dropdowns") see [up.popup](/up.popup) instead.
4120
4192
  The animation used to close the modal. The animation will be applied
4121
4193
  to both the dialog box and the overlay dimming the page.
4122
4194
  */
4123
- defaults = function(options) {
4124
- return u.extend(config, options);
4195
+ config = u.config({
4196
+ maxWidth: void 0,
4197
+ minWidth: void 0,
4198
+ width: void 0,
4199
+ height: void 0,
4200
+ openAnimation: 'fade-in',
4201
+ closeAnimation: 'fade-out',
4202
+ closeLabel: '×',
4203
+ template: function(config) {
4204
+ return "<div class=\"up-modal\">\n <div class=\"up-modal-dialog\">\n <div class=\"up-modal-close\" up-close>" + config.closeLabel + "</div>\n <div class=\"up-modal-content\"></div>\n </div>\n</div>";
4205
+ }
4206
+ });
4207
+ currentSource = void 0;
4208
+ reset = function() {
4209
+ close();
4210
+ currentSource = void 0;
4211
+ return config.reset();
4125
4212
  };
4126
4213
  templateHtml = function() {
4127
4214
  var template;
@@ -4144,32 +4231,53 @@ For small popup overlays ("dropdowns") see [up.popup](/up.popup) instead.
4144
4231
  $popup.removeAttr('up-previous-url');
4145
4232
  return $popup.removeAttr('up-previous-title');
4146
4233
  };
4147
- createHiddenModal = function(selector, width, height, sticky) {
4234
+ createHiddenModal = function(options) {
4148
4235
  var $content, $dialog, $modal, $placeholder;
4149
4236
  $modal = $(templateHtml());
4150
- if (sticky) {
4237
+ if (options.sticky) {
4151
4238
  $modal.attr('up-sticky', '');
4152
4239
  }
4153
4240
  $modal.attr('up-previous-url', up.browser.url());
4154
4241
  $modal.attr('up-previous-title', document.title);
4155
4242
  $dialog = $modal.find('.up-modal-dialog');
4156
- if (u.isPresent(width)) {
4157
- $dialog.css('width', width);
4243
+ if (u.isPresent(options.width)) {
4244
+ $dialog.css('width', options.width);
4158
4245
  }
4159
- if (u.isPresent(height)) {
4160
- $dialog.css('height', height);
4246
+ if (u.isPresent(options.maxWidth)) {
4247
+ $dialog.css('max-width', options.maxWidth);
4161
4248
  }
4162
- $content = $dialog.find('.up-modal-content');
4163
- $placeholder = u.$createElementFromSelector(selector);
4249
+ if (u.isPresent(options.height)) {
4250
+ $dialog.css('height', options.height);
4251
+ }
4252
+ $content = $modal.find('.up-modal-content');
4253
+ $placeholder = u.$createElementFromSelector(options.selector);
4164
4254
  $placeholder.appendTo($content);
4165
4255
  $modal.appendTo(document.body);
4166
4256
  rememberHistory();
4167
4257
  $modal.hide();
4168
4258
  return $modal;
4169
4259
  };
4260
+ unshiftBody = void 0;
4261
+ shiftBody = function() {
4262
+ var bodyRightPadding, bodyRightShift, scrollbarWidth;
4263
+ scrollbarWidth = u.scrollbarWidth();
4264
+ bodyRightPadding = parseInt($('body').css('padding-right'));
4265
+ bodyRightShift = scrollbarWidth + bodyRightPadding;
4266
+ return unshiftBody = u.temporaryCss($('body'), {
4267
+ 'padding-right': bodyRightShift + "px",
4268
+ 'overflow-y': 'hidden'
4269
+ });
4270
+ };
4170
4271
  updated = function($modal, animation, animateOptions) {
4272
+ var promise;
4273
+ up.bus.emit('modal:open');
4274
+ shiftBody();
4171
4275
  $modal.show();
4172
- return up.animate($modal, animation, animateOptions);
4276
+ promise = up.animate($modal, animation, animateOptions);
4277
+ promise.then(function() {
4278
+ return up.bus.emit('modal:opened');
4279
+ });
4280
+ return promise;
4173
4281
  };
4174
4282
 
4175
4283
  /**
@@ -4187,6 +4295,13 @@ For small popup overlays ("dropdowns") see [up.popup](/up.popup) instead.
4187
4295
  This will request `/foo`, extract the `.list` selector from the response
4188
4296
  and open the selected container in a modal dialog.
4189
4297
 
4298
+ \#\#\#\# Events
4299
+
4300
+ - Emits an [event](/up.bus) `modal:open` when the modal
4301
+ is starting to open.
4302
+ - Emits an [event](/up.bus) `modal:opened` when the opening
4303
+ animation has finished and the modal contents are fully visible.
4304
+
4190
4305
  @method up.modal.open
4191
4306
  @param {Element|jQuery|String} [elementOrSelector]
4192
4307
  The link to follow.
@@ -4219,7 +4334,7 @@ For small popup overlays ("dropdowns") see [up.popup](/up.popup) instead.
4219
4334
  A promise that will be resolved when the modal has finished loading.
4220
4335
  */
4221
4336
  open = function() {
4222
- var $link, $modal, animateOptions, animation, args, height, history, options, selector, sticky, url, width;
4337
+ var $link, $modal, animateOptions, animation, args, height, history, maxWidth, options, selector, sticky, url, width;
4223
4338
  args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
4224
4339
  if (u.isObject(args[0]) && !u.isElement(args[0]) && !u.isJQuery(args[0])) {
4225
4340
  $link = u.nullJquery();
@@ -4232,13 +4347,20 @@ For small popup overlays ("dropdowns") see [up.popup](/up.popup) instead.
4232
4347
  url = u.option(options.url, $link.attr('up-href'), $link.attr('href'));
4233
4348
  selector = u.option(options.target, $link.attr('up-modal'), 'body');
4234
4349
  width = u.option(options.width, $link.attr('up-width'), config.width);
4350
+ maxWidth = u.option(options.maxWidth, $link.attr('up-max-width'), config.maxWidth);
4235
4351
  height = u.option(options.height, $link.attr('up-height'), config.height);
4236
4352
  animation = u.option(options.animation, $link.attr('up-animation'), config.openAnimation);
4237
4353
  sticky = u.option(options.sticky, $link.is('[up-sticky]'));
4238
4354
  history = up.browser.canPushState() ? u.option(options.history, $link.attr('up-history'), true) : false;
4239
4355
  animateOptions = up.motion.animateOptions(options, $link);
4240
4356
  close();
4241
- $modal = createHiddenModal(selector, width, height, sticky);
4357
+ $modal = createHiddenModal({
4358
+ selector: selector,
4359
+ width: width,
4360
+ maxWidth: maxWidth,
4361
+ height: height,
4362
+ sticky: sticky
4363
+ });
4242
4364
  return up.replace(selector, url, {
4243
4365
  history: history,
4244
4366
  insert: function() {
@@ -4263,12 +4385,19 @@ For small popup overlays ("dropdowns") see [up.popup](/up.popup) instead.
4263
4385
  Closes a currently opened modal overlay.
4264
4386
  Does nothing if no modal is currently open.
4265
4387
 
4388
+ \#\#\#\# Events
4389
+
4390
+ - Emits an [event](/up.bus) `modal:close` when the modal
4391
+ is starting to close.
4392
+ - Emits an [event](/up.bus) `modal:closed` when the closing
4393
+ animation has finished and the modal has been removed from the DOM.
4394
+
4266
4395
  @method up.modal.close
4267
4396
  @param {Object} options
4268
4397
  See options for [`up.animate`](/up.motion#up.animate)
4269
4398
  */
4270
4399
  close = function(options) {
4271
- var $modal;
4400
+ var $modal, promise;
4272
4401
  $modal = $('.up-modal');
4273
4402
  if ($modal.length) {
4274
4403
  options = u.options(options, {
@@ -4277,7 +4406,15 @@ For small popup overlays ("dropdowns") see [up.popup](/up.popup) instead.
4277
4406
  title: $modal.attr('up-previous-title')
4278
4407
  });
4279
4408
  currentSource = void 0;
4280
- return up.destroy($modal, options);
4409
+ up.bus.emit('modal:close');
4410
+ promise = up.destroy($modal, options);
4411
+ promise.then(function() {
4412
+ unshiftBody();
4413
+ return up.bus.emit('modal:closed');
4414
+ });
4415
+ return promise;
4416
+ } else {
4417
+ return u.resolvedPromise();
4281
4418
  }
4282
4419
  };
4283
4420
  autoclose = function() {
@@ -4406,12 +4543,12 @@ For small popup overlays ("dropdowns") see [up.popup](/up.popup) instead.
4406
4543
  return close();
4407
4544
  }
4408
4545
  });
4409
- up.bus.on('framework:reset', close);
4546
+ up.bus.on('framework:reset', reset);
4410
4547
  return {
4411
4548
  open: open,
4412
4549
  close: close,
4413
4550
  source: source,
4414
- defaults: defaults,
4551
+ defaults: config.update,
4415
4552
  contains: contains
4416
4553
  };
4417
4554
  })();
@@ -4571,10 +4708,31 @@ by providing instant feedback for user interactions.
4571
4708
 
4572
4709
  (function() {
4573
4710
  up.navigation = (function() {
4574
- var CLASS_ACTIVE, CLASS_CURRENT, SELECTORS_SECTION, SELECTOR_ACTIVE, SELECTOR_SECTION, SELECTOR_SECTION_INSTANT, enlargeClickArea, locationChanged, normalizeUrl, sectionClicked, sectionUrls, selector, u, unmarkActive, urlSet;
4711
+ var CLASS_ACTIVE, SELECTORS_SECTION, SELECTOR_ACTIVE, SELECTOR_SECTION, SELECTOR_SECTION_INSTANT, config, currentClass, enlargeClickArea, locationChanged, normalizeUrl, reset, sectionClicked, sectionUrls, selector, u, unmarkActive, urlSet;
4575
4712
  u = up.util;
4713
+
4714
+ /**
4715
+ Sets default options for this module.
4716
+
4717
+ @param {Number} [options.currentClass]
4718
+ The class to set on [links that point the current location](#up-current).
4719
+ @method up.navigation.defaults
4720
+ */
4721
+ config = u.config({
4722
+ currentClass: 'up-current'
4723
+ });
4724
+ reset = function() {
4725
+ return config.reset();
4726
+ };
4727
+ currentClass = function() {
4728
+ var klass;
4729
+ klass = config.currentClass;
4730
+ if (!u.contains(klass, 'up-current')) {
4731
+ klass += ' up-current';
4732
+ }
4733
+ return klass;
4734
+ };
4576
4735
  CLASS_ACTIVE = 'up-active';
4577
- CLASS_CURRENT = 'up-current';
4578
4736
  SELECTORS_SECTION = ['a', '[up-href]', '[up-alias]'];
4579
4737
  SELECTOR_SECTION = SELECTORS_SECTION.join(', ');
4580
4738
  SELECTOR_SECTION_INSTANT = ((function() {
@@ -4637,16 +4795,17 @@ by providing instant feedback for user interactions.
4637
4795
  };
4638
4796
  };
4639
4797
  locationChanged = function() {
4640
- var currentUrls;
4798
+ var currentUrls, klass;
4641
4799
  currentUrls = urlSet([normalizeUrl(up.browser.url()), normalizeUrl(up.modal.source()), normalizeUrl(up.popup.source())]);
4800
+ klass = currentClass();
4642
4801
  return u.each($(SELECTOR_SECTION), function(section) {
4643
4802
  var $section, urls;
4644
4803
  $section = $(section);
4645
4804
  urls = sectionUrls($section);
4646
4805
  if (currentUrls.matchesAny(urls)) {
4647
- return $section.addClass(CLASS_CURRENT);
4806
+ return $section.addClass(klass);
4648
4807
  } else {
4649
- return $section.removeClass(CLASS_CURRENT);
4808
+ return $section.removeClass(klass);
4650
4809
  }
4651
4810
  });
4652
4811
  };
@@ -4748,11 +4907,15 @@ by providing instant feedback for user interactions.
4748
4907
  unmarkActive();
4749
4908
  return locationChanged();
4750
4909
  });
4751
- return up.bus.on('fragment:destroy', function($fragment) {
4910
+ up.bus.on('fragment:destroy', function($fragment) {
4752
4911
  if ($fragment.is('.up-modal, .up-popup')) {
4753
4912
  return locationChanged();
4754
4913
  }
4755
4914
  });
4915
+ up.bus.on('framework:reset', reset);
4916
+ return {
4917
+ defaults: config.update
4918
+ };
4756
4919
  })();
4757
4920
 
4758
4921
  }).call(this);