upjs-rails 0.8.0 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
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);