rails-angular-material 0.8.3.1 → 0.8.3.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7938d10e99d0dcaefd215dac8244e6e8613055fe
4
- data.tar.gz: d64395f9565cae116aeb76a98edc0da0ebb44a37
3
+ metadata.gz: 4cab5b92caf22dec280b638785ddc7cae93df26e
4
+ data.tar.gz: 75a49098df0249a0ab01c57af45737783978b992
5
5
  SHA512:
6
- metadata.gz: 92e2ae36933f0664c142de1792aa08b6fdc1df4f71f0243ecc57d4738815782c44732e1ed9667dcb1a5203c971998e96587e1f6f35c0c687d2bf78ffbbcbfa75
7
- data.tar.gz: 304a2385937077b6962d8e9d7d6ecb75ad51ec77aad07795ecde60e985a7654cad8dad42317e0ec4371455388a2c5d486285222bef8d0d8ece26e25cefa14bb8
6
+ metadata.gz: 72b514763597abf190defb104a88cbb005b390ffe7e041fb876fa7f4f7e047fcbdc5d7f742280446f01e99b5e816b3701f6916c78b1e4abf945b4c8848616367
7
+ data.tar.gz: 09d7f10daae58c09dd18a2eb656740eb9f4bf641b03992131816978b17734d6c808454c8f57e4cf93763e813612feff04d3e53cfbf2a8e02ef72029e19b598ae
data/README.md CHANGED
@@ -23,4 +23,4 @@ If you desire to require minified AngularMaterial files, add the following:
23
23
 
24
24
  ## Versioning
25
25
 
26
- Current version of AngularMaterial - 0.8.3-74601d0
26
+ Current version of AngularMaterial - 0.8.3-b3459ab
@@ -1,3 +1,3 @@
1
1
  module AngularMaterialRails
2
- VERSION = "0.8.3.1"
2
+ VERSION = "0.8.3.2"
3
3
  end
@@ -4,7 +4,7 @@
4
4
  * @license MIT
5
5
  * v0.8.3
6
6
  */
7
- angular.module('ngMaterial', ["ng","ngAnimate","ngAria","material.core","material.core.theming.palette","material.core.theming","material.components.autocomplete","material.components.backdrop","material.components.bottomSheet","material.components.button","material.components.card","material.components.checkbox","material.components.chips","material.components.content","material.components.dialog","material.components.divider","material.components.gridList","material.components.icon","material.components.input","material.components.list","material.components.progressCircular","material.components.progressLinear","material.components.radioButton","material.components.select","material.components.sidenav","material.components.slider","material.components.sticky","material.components.subheader","material.components.swipe","material.components.switch","material.components.tabs","material.components.textField","material.components.toast","material.components.toolbar","material.components.tooltip","material.components.whiteframe"]);
7
+ angular.module('ngMaterial', ["ng","ngAnimate","ngAria","material.core","material.core.gestures","material.core.theming.palette","material.core.theming","material.components.autocomplete","material.components.backdrop","material.components.bottomSheet","material.components.button","material.components.card","material.components.checkbox","material.components.chips","material.components.content","material.components.dialog","material.components.divider","material.components.gridList","material.components.icon","material.components.input","material.components.list","material.components.progressCircular","material.components.progressLinear","material.components.radioButton","material.components.select","material.components.sidenav","material.components.slider","material.components.sticky","material.components.subheader","material.components.swipe","material.components.switch","material.components.tabs","material.components.textField","material.components.toast","material.components.toolbar","material.components.tooltip","material.components.whiteframe"]);
8
8
  /*!
9
9
  * Angular Material Design
10
10
  * https://github.com/angular/material
@@ -19,7 +19,7 @@ angular.module('ngMaterial', ["ng","ngAnimate","ngAria","material.core","materia
19
19
  * requirements.
20
20
  */
21
21
  angular
22
- .module('material.core', [ 'material.core.theming' ])
22
+ .module('material.core', [ 'material.core.gestures', 'material.core.theming' ])
23
23
  .config( MdCoreConfigure );
24
24
 
25
25
 
@@ -835,7 +835,7 @@ function AriaService($$rAF, $log, $window) {
835
835
  * @param {optional} defaultValue What to set the attr to if no value is found
836
836
  */
837
837
  function expect(element, attrName, defaultValue) {
838
- var node = element[0];
838
+ var node = element[0] || element;
839
839
 
840
840
  // if node exists and neither it nor its children have the attribute
841
841
  if (node &&
@@ -1049,418 +1049,446 @@ mdCompilerService.$inject = ["$q", "$http", "$injector", "$compile", "$controlle
1049
1049
  * @license MIT
1050
1050
  * v0.8.3
1051
1051
  */
1052
- (function() {
1053
- 'use strict';
1052
+ (function (jQuery) {
1053
+ 'use strict';
1054
1054
 
1055
- /*
1056
- * TODO: Add support for multiple fingers on the `pointer` object (enables pinch gesture)
1057
- */
1055
+ var HANDLERS = {};
1056
+ var pointer, lastPointer; // The state of the current and previous 'pointer' (user's hand)
1058
1057
 
1059
- var START_EVENTS = 'mousedown touchstart pointerdown';
1060
- var MOVE_EVENTS = 'mousemove touchmove pointermove';
1061
- var END_EVENTS = 'mouseup mouseleave touchend touchcancel pointerup pointercancel';
1062
- var HANDLERS;
1058
+ angular
1059
+ .module('material.core.gestures', [ ])
1060
+ .factory('$mdGesture', MdGesture)
1061
+ .factory('$$MdGestureHandler', MdGestureHandler)
1062
+ .run( attachToDocument );
1063
1063
 
1064
- document.contains || (document.contains = function(node) {
1065
- return document.body.contains(node);
1066
- });
1064
+ /**
1065
+ * MdGesture factory construction function
1066
+ */
1067
+ function MdGesture($$MdGestureHandler, $$rAF, $timeout) {
1068
+ var userAgent = navigator.userAgent || navigator.vendor || window.opera;
1069
+ var isIos = userAgent.match(/iPad/i) || userAgent.match(/iPhone/i) || userAgent.match(/iPod/i);
1070
+ var isAndroid = userAgent.match(/Android/i);
1071
+ var shouldHijackClicks = isIos || isAndroid;
1072
+
1073
+ var self = {
1074
+ handler: addHandler,
1075
+ register: register
1076
+ };
1067
1077
 
1068
- // TODO add windows phone to this
1069
- var userAgent = navigator.userAgent || navigator.vendor || window.opera;
1070
- var isIos = userAgent.match(/iPad/i) || userAgent.match(/iPhone/i) || userAgent.match(/iPod/i);
1071
- var isAndroid = userAgent.match(/Android/i);
1072
- var shouldHijackClicks = isIos || isAndroid;
1073
-
1074
- if (shouldHijackClicks) {
1075
- document.addEventListener('click', function(ev) {
1076
- // Space/enter on a button, and submit events, can send clicks
1077
- var isKeyClick = ev.clientX === 0 && ev.clientY === 0;
1078
- if (isKeyClick || ev.$material) return;
1079
-
1080
- // Prevent clicks unless they're sent by material
1081
- ev.preventDefault();
1082
- ev.stopPropagation();
1083
- }, true);
1084
- }
1078
+ if (self.$$hijackClicks = shouldHijackClicks) {
1079
+ self.handler('click', {
1080
+ options: {
1081
+ maxDistance: 6
1082
+ },
1083
+ onEnd: function (ev, pointer) {
1084
+ if (pointer.distance < this.state.options.maxDistance) {
1085
+ this.dispatchEvent(ev, 'click');
1086
+ }
1087
+ }
1088
+ });
1089
+ }
1085
1090
 
1086
- angular.element(document)
1087
- .on(START_EVENTS, gestureStart)
1088
- .on(MOVE_EVENTS, gestureMove)
1089
- .on(END_EVENTS, gestureEnd)
1090
- // For testing
1091
- .on('$$mdGestureReset', function() {
1092
- lastPointer = pointer = null;
1093
- });
1091
+ return self
1092
+ .handler('press', {
1093
+ onStart: function (ev, pointer) {
1094
+ this.dispatchEvent(ev, '$md.pressdown');
1095
+ },
1096
+ onEnd: function (ev, pointer) {
1097
+ this.dispatchEvent(ev, '$md.pressup');
1098
+ }
1099
+ })
1100
+ .handler('hold', {
1101
+ options: {
1102
+ // If the user keeps his finger within the same <maxDistance> area for
1103
+ // <delay> ms, dispatch a hold event.
1104
+ maxDistance: 6,
1105
+ delay: 500
1106
+ },
1107
+ onCancel: function () {
1108
+ $timeout.cancel(this.state.timeout);
1109
+ },
1110
+ onStart: function (ev, pointer) {
1111
+ // For hold, require a parent to be registered with $mdGesture.register()
1112
+ // Because we prevent scroll events, this is necessary.
1113
+ if (!this.state.registeredParent) return this.cancel();
1114
+
1115
+ this.state.pos = {x: pointer.x, y: pointer.y};
1116
+ this.state.timeout = $timeout(angular.bind(this, function holdDelayFn() {
1117
+ this.dispatchEvent(ev, '$md.hold');
1118
+ this.cancel(); //we're done!
1119
+ }), this.state.options.delay, false);
1120
+ },
1121
+ onMove: function (ev, pointer) {
1122
+ // Don't scroll while waiting for hold
1123
+ ev.preventDefault();
1124
+ var dx = this.state.pos.x - pointer.x;
1125
+ var dy = this.state.pos.y - pointer.y;
1126
+ if (Math.sqrt(dx * dx + dy * dy) > this.options.maxDistance) {
1127
+ this.cancel();
1128
+ }
1129
+ },
1130
+ onEnd: function () {
1131
+ this.onCancel();
1132
+ }
1133
+ })
1134
+ .handler('drag', {
1135
+ options: {
1136
+ minDistance: 6,
1137
+ horizontal: true
1138
+ },
1139
+ onStart: function (ev) {
1140
+ // For drag, require a parent to be registered with $mdGesture.register()
1141
+ if (!this.state.registeredParent) this.cancel();
1142
+ },
1143
+ onMove: function (ev, pointer) {
1144
+ var shouldStartDrag, shouldCancel;
1145
+ // Don't allow touch events to scroll while we're dragging or
1146
+ // deciding if this touchmove is a proper drag
1147
+ ev.preventDefault();
1148
+
1149
+ if (!this.state.dragPointer) {
1150
+ if (this.state.options.horizontal) {
1151
+ shouldStartDrag = Math.abs(pointer.distanceX) > this.state.options.minDistance;
1152
+ shouldCancel = Math.abs(pointer.distanceY) > this.state.options.minDistance * 1.5;
1153
+ } else {
1154
+ shouldStartDrag = Math.abs(pointer.distanceY) > this.state.options.minDistance;
1155
+ shouldCancel = Math.abs(pointer.distanceX) > this.state.options.minDistance * 1.5;
1156
+ }
1157
+
1158
+ if (shouldStartDrag) {
1159
+ // Create a new pointer, starting at this point where the drag started.
1160
+ this.state.dragPointer = makeStartPointer(ev);
1161
+ updatePointerState(ev, this.state.dragPointer);
1162
+ this.dispatchEvent(ev, '$md.dragstart', this.state.dragPointer);
1094
1163
 
1095
- // The state of the current and previous 'pointer' (user's hand)
1096
- var pointer, lastPointer;
1164
+ } else if (shouldCancel) {
1165
+ this.cancel();
1166
+ }
1167
+ } else {
1168
+ this.dispatchDragMove(ev);
1169
+ }
1170
+ },
1171
+ // Only dispatch these every frame; any more is unnecessray
1172
+ dispatchDragMove: $$rAF.throttle(function (ev) {
1173
+ // Make sure the drag didn't stop while waiting for the next frame
1174
+ if (this.state.isRunning) {
1175
+ updatePointerState(ev, this.state.dragPointer);
1176
+ this.dispatchEvent(ev, '$md.drag', this.state.dragPointer);
1177
+ }
1178
+ }),
1179
+ onEnd: function (ev, pointer) {
1180
+ if (this.state.dragPointer) {
1181
+ updatePointerState(ev, this.state.dragPointer);
1182
+ this.dispatchEvent(ev, '$md.dragend', this.state.dragPointer);
1183
+ }
1184
+ }
1185
+ })
1186
+ .handler('swipe', {
1187
+ options: {
1188
+ minVelocity: 0.65,
1189
+ minDistance: 10
1190
+ },
1191
+ onEnd: function (ev, pointer) {
1192
+ if (Math.abs(pointer.velocityX) > this.state.options.minVelocity &&
1193
+ Math.abs(pointer.distanceX) > this.state.options.minDistance) {
1194
+ var eventType = pointer.directionX == 'left' ? '$md.swipeleft' : '$md.swiperight';
1195
+ this.dispatchEvent(ev, eventType);
1196
+ }
1197
+ }
1198
+ })
1097
1199
 
1098
- function runHandlers(handlerEvent, event) {
1099
- var handler;
1100
- for (var handlerName in HANDLERS) {
1101
- handler = HANDLERS[handlerName];
1102
- if (handlerEvent === 'start') {
1103
- // Run cancel to reset any handlers' state
1104
- handler.cancel();
1200
+ function register(element, handlerName, options) {
1201
+ var handler = HANDLERS[handlerName.replace(/^\$md./, '')];
1202
+ if (!handler) {
1203
+ throw new Error('Failed to register element with handler ' + handlerName + '. ' +
1204
+ 'Available handlers: ' + Object.keys(HANDLERS).join(', '));
1205
+ }
1206
+ return handler.registerElement(element, options);
1105
1207
  }
1106
- handler[handlerEvent](event, pointer);
1107
- }
1108
- }
1109
1208
 
1110
- function gestureStart(ev) {
1111
- // If we're already touched down, abort
1112
- if (pointer) return;
1209
+ function addHandler(name, definition) {
1210
+ var handler = new $$MdGestureHandler(name);
1211
+ angular.extend(handler, definition);
1212
+ HANDLERS[name] = handler;
1113
1213
 
1114
- var now = +Date.now();
1214
+ return self;
1215
+ }
1216
+ }
1217
+ MdGesture.$inject = ["$$MdGestureHandler", "$$rAF", "$timeout"];
1115
1218
 
1116
- // iOS & old android bug: after a touch event, a click event is sent 350 ms later.
1117
- // If <400ms have passed, don't allow an event of a different type than the previous event
1118
- if (lastPointer && !typesMatch(ev, lastPointer) && (now - lastPointer.endTime < 1500)) {
1119
- return;
1219
+ /**
1220
+ * MdGestureHandler factory construction function
1221
+ */
1222
+ function GestureHandler (name) {
1223
+ this.name = name;
1224
+ this.state = {};
1120
1225
  }
1121
1226
 
1122
- pointer = makeStartPointer(ev);
1227
+ function MdGestureHandler($$rAF) {
1228
+ var hasJQuery = typeof jQuery !== 'undefined' && angular.element === jQuery;
1123
1229
 
1124
- runHandlers('start', ev);
1125
- }
1126
1230
 
1127
- function gestureMove(ev) {
1128
- if (!pointer || !typesMatch(ev, pointer)) return;
1231
+ GestureHandler.prototype = {
1232
+ options: {},
1233
+ dispatchEvent: hasJQuery ? jQueryDispatchEvent : nativeDispatchEvent,
1129
1234
 
1130
- updatePointerState(ev, pointer);
1131
- runHandlers('move', ev);
1132
- }
1235
+ onStart: angular.noop,
1236
+ onMove: angular.noop,
1237
+ onEnd: angular.noop,
1238
+ onCancel: angular.noop,
1133
1239
 
1134
- function gestureEnd(ev) {
1135
- if (!pointer || !typesMatch(ev, pointer)) return;
1240
+ start: function (ev, pointer) {
1241
+ if (this.state.isRunning) return;
1242
+ var parentTarget = this.getNearestParent(ev.target);
1243
+ var parentTargetOptions = parentTarget && parentTarget.$mdGesture[this.name] || {};
1136
1244
 
1137
- updatePointerState(ev, pointer);
1138
- pointer.endTime = +Date.now();
1245
+ this.state = {
1246
+ isRunning: true,
1247
+ options: angular.extend({}, this.options, parentTargetOptions),
1248
+ registeredParent: parentTarget
1249
+ };
1250
+ this.onStart(ev, pointer);
1251
+ },
1252
+ move: function (ev, pointer) {
1253
+ if (!this.state.isRunning) return;
1254
+ this.onMove(ev, pointer);
1255
+ },
1256
+ end: function (ev, pointer) {
1257
+ if (!this.state.isRunning) return;
1258
+ this.onEnd(ev, pointer);
1259
+ this.state.isRunning = false;
1260
+ },
1261
+ cancel: function (ev, pointer) {
1262
+ this.onCancel(ev, pointer);
1263
+ this.state = {};
1264
+ },
1139
1265
 
1140
- runHandlers('end', ev);
1266
+ // Find and return the nearest parent element that has been registered via
1267
+ // $mdGesture.register(element, 'handlerName').
1268
+ getNearestParent: function (node) {
1269
+ var current = node;
1270
+ while (current) {
1271
+ if ((current.$mdGesture || {})[this.name]) {
1272
+ return current;
1273
+ }
1274
+ current = current.parentNode;
1275
+ }
1276
+ },
1141
1277
 
1142
- lastPointer = pointer;
1143
- pointer = null;
1144
- }
1278
+ registerElement: function (element, options) {
1279
+ var self = this;
1280
+ element[0].$mdGesture = element[0].$mdGesture || {};
1281
+ element[0].$mdGesture[this.name] = options || {};
1282
+ element.on('$destroy', onDestroy);
1145
1283
 
1146
- /******** Helpers *********/
1147
- function typesMatch(ev, pointer) {
1148
- return ev && pointer && ev.type.charAt(0) === pointer.type;
1149
- }
1284
+ return onDestroy;
1150
1285
 
1151
- function getEventPoint(ev) {
1152
- ev = ev.originalEvent || ev; // support jQuery events
1153
- return (ev.touches && ev.touches[0]) ||
1154
- (ev.changedTouches && ev.changedTouches[0]) ||
1155
- ev;
1156
- }
1286
+ function onDestroy() {
1287
+ delete element[0].$mdGesture[self.name];
1288
+ element.off('$destroy', onDestroy);
1289
+ }
1290
+ }
1291
+ };
1157
1292
 
1158
- function updatePointerState(ev, pointer) {
1159
- var point = getEventPoint(ev);
1160
- var x = pointer.x = point.pageX;
1161
- var y = pointer.y = point.pageY;
1293
+ return GestureHandler;
1162
1294
 
1163
- pointer.distanceX = x - pointer.startX;
1164
- pointer.distanceY = y - pointer.startY;
1165
- pointer.distance = Math.sqrt(
1166
- pointer.distanceX * pointer.distanceX + pointer.distanceY * pointer.distanceY
1167
- );
1295
+ /**
1296
+ * Internal methods
1297
+ */
1298
+ function jQueryDispatchEvent(srcEvent, eventType, eventPointer) {
1299
+ eventPointer = eventPointer || pointer;
1300
+ var eventObj = new angular.element.Event(eventType);
1301
+
1302
+ eventObj.$material = true;
1303
+ eventObj.pointer = eventPointer;
1304
+ eventObj.srcEvent = srcEvent;
1305
+
1306
+ angular.extend(eventObj, {
1307
+ clientX: eventPointer.x,
1308
+ clientY: eventPointer.y,
1309
+ screenX: eventPointer.x,
1310
+ screenY: eventPointer.y,
1311
+ pageX: eventPointer.x,
1312
+ pageY: eventPointer.y,
1313
+ ctrlKey: srcEvent.ctrlKey,
1314
+ altKey: srcEvent.altKey,
1315
+ shiftKey: srcEvent.shiftKey,
1316
+ metaKey: srcEvent.metaKey
1317
+ });
1318
+ angular.element(eventPointer.target).trigger(eventObj);
1319
+ }
1168
1320
 
1169
- pointer.directionX = pointer.distanceX > 0 ? 'right' : pointer.distanceX < 0 ? 'left' : '';
1170
- pointer.directionY = pointer.distanceY > 0 ? 'up' : pointer.distanceY < 0 ? 'down' : '';
1321
+ /*
1322
+ * NOTE: nativeDispatchEvent is very performance sensitive.
1323
+ */
1324
+ function nativeDispatchEvent(srcEvent, eventType, eventPointer) {
1325
+ eventPointer = eventPointer || pointer;
1326
+ var eventObj;
1327
+
1328
+ if (eventType === 'click') {
1329
+ eventObj = document.createEvent('MouseEvents');
1330
+ eventObj.initMouseEvent(
1331
+ 'click', true, true, window, srcEvent.detail,
1332
+ eventPointer.x, eventPointer.y, eventPointer.x, eventPointer.y,
1333
+ srcEvent.ctrlKey, srcEvent.altKey, srcEvent.shiftKey, srcEvent.metaKey,
1334
+ srcEvent.button, srcEvent.relatedTarget || null
1335
+ );
1171
1336
 
1172
- pointer.duration = +Date.now() - pointer.startTime;
1173
- pointer.velocityX = pointer.distanceX / pointer.duration;
1174
- pointer.velocityY = pointer.distanceY / pointer.duration;
1175
- }
1337
+ } else {
1338
+ eventObj = document.createEvent('CustomEvent');
1339
+ eventObj.initCustomEvent(eventType, true, true, {});
1340
+ }
1341
+ eventObj.$material = true;
1342
+ eventObj.pointer = eventPointer;
1343
+ eventObj.srcEvent = srcEvent;
1344
+ eventPointer.target.dispatchEvent(eventObj);
1345
+ }
1176
1346
 
1347
+ }
1348
+ MdGestureHandler.$inject = ["$$rAF"];
1177
1349
 
1178
- function makeStartPointer(ev) {
1179
- var point = getEventPoint(ev);
1180
- var startPointer = {
1181
- startTime: +Date.now(),
1182
- target: ev.target,
1183
- // 'p' for pointer, 'm' for mouse, 't' for touch
1184
- type: ev.type.charAt(0)
1185
- };
1186
- startPointer.startX = startPointer.x = point.pageX;
1187
- startPointer.startY = startPointer.y = point.pageY;
1188
- return startPointer;
1189
- }
1350
+ /**
1351
+ * Attach Gestures: hook document and check shouldHijack clicks
1352
+ */
1353
+ function attachToDocument( $mdGesture, $$MdGestureHandler ) {
1190
1354
 
1191
- angular.module('material.core')
1192
- .run(["$mdGesture", function($mdGesture) {}]) // make sure $mdGesture is always instantiated
1193
- .factory('$mdGesture', ["$$MdGestureHandler", "$$rAF", "$timeout", function($$MdGestureHandler, $$rAF, $timeout) {
1194
- HANDLERS = {};
1195
-
1196
- if (shouldHijackClicks) {
1197
- addHandler('click', {
1198
- options: {
1199
- maxDistance: 6
1200
- },
1201
- onEnd: function(ev, pointer) {
1202
- if (pointer.distance < this.state.options.maxDistance) {
1203
- this.dispatchEvent(ev, 'click');
1204
- }
1205
- }
1355
+ document.contains || (document.contains = function (node) {
1356
+ return document.body.contains(node);
1206
1357
  });
1207
- }
1208
1358
 
1209
- addHandler('press', {
1210
- onStart: function(ev, pointer) {
1211
- this.dispatchEvent(ev, '$md.pressdown');
1212
- },
1213
- onEnd: function(ev, pointer) {
1214
- this.dispatchEvent(ev, '$md.pressup');
1215
- }
1216
- });
1359
+ if ( $mdGesture.$$hijackClicks ) {
1217
1360
 
1361
+ // If hijacking use capture-phase to prevent non-key clicks
1362
+ // unless they're sent by material
1218
1363
 
1219
- addHandler('hold', {
1220
- options: {
1221
- // If the user keeps his finger within the same <maxDistance> area for
1222
- // <delay> ms, dispatch a hold event.
1223
- maxDistance: 6,
1224
- delay: 500
1225
- },
1226
- onCancel: function() {
1227
- $timeout.cancel(this.state.timeout);
1228
- },
1229
- onStart: function(ev, pointer) {
1230
- // For hold, require a parent to be registered with $mdGesture.register()
1231
- // Because we prevent scroll events, this is necessary.
1232
- if (!this.state.registeredParent) return this.cancel();
1233
-
1234
- this.state.pos = {x: pointer.x, y: pointer.y};
1235
- this.state.timeout = $timeout(angular.bind(this, function holdDelayFn() {
1236
- this.dispatchEvent(ev, '$md.hold');
1237
- this.cancel(); //we're done!
1238
- }), this.state.options.delay, false);
1239
- },
1240
- onMove: function(ev, pointer) {
1241
- // Don't scroll while waiting for hold
1242
- ev.preventDefault();
1243
- var dx = this.state.pos.x - pointer.x;
1244
- var dy = this.state.pos.y - pointer.y;
1245
- if (Math.sqrt(dx*dx + dy*dy) > this.options.maxDistance) {
1246
- this.cancel();
1247
- }
1248
- },
1249
- onEnd: function() { this.onCancel(); }
1250
- });
1364
+ document.addEventListener('click', function (ev)
1365
+ {
1366
+ // Space/enter on a button, and submit events, can send clicks
1251
1367
 
1252
- addHandler('drag', {
1253
- options: {
1254
- minDistance: 6,
1255
- horizontal: true
1256
- },
1257
- onStart: function(ev) {
1258
- // For drag, require a parent to be registered with $mdGesture.register()
1259
- if (!this.state.registeredParent) this.cancel();
1260
- },
1261
- onMove: function(ev, pointer) {
1262
- var shouldStartDrag, shouldCancel;
1263
- // Don't allow touch events to scroll while we're dragging or
1264
- // deciding if this touchmove is a proper drag
1265
- ev.preventDefault();
1368
+ var isKeyClick = ev.clientX === 0 && ev.clientY === 0;
1369
+ if (isKeyClick || ev.$material) return;
1266
1370
 
1267
- if (!this.state.dragPointer) {
1268
- if (this.state.options.horizontal) {
1269
- shouldStartDrag = Math.abs(pointer.distanceX) > this.state.options.minDistance;
1270
- shouldCancel = Math.abs(pointer.distanceY) > this.state.options.minDistance * 1.5;
1271
- } else {
1272
- shouldStartDrag = Math.abs(pointer.distanceY) > this.state.options.minDistance;
1273
- shouldCancel = Math.abs(pointer.distanceX) > this.state.options.minDistance * 1.5;
1274
- }
1371
+ ev.preventDefault();
1372
+ ev.stopPropagation();
1373
+
1374
+ }, true);
1375
+
1376
+ }
1275
1377
 
1276
- if (shouldStartDrag) {
1277
- // Create a new pointer, starting at this point where the drag started.
1278
- this.state.dragPointer = makeStartPointer(ev);
1279
- updatePointerState(ev, this.state.dragPointer);
1280
- this.dispatchEvent(ev, '$md.dragstart', this.state.dragPointer);
1378
+ var START_EVENTS = 'mousedown touchstart pointerdown';
1379
+ var MOVE_EVENTS = 'mousemove touchmove pointermove';
1380
+ var END_EVENTS = 'mouseup mouseleave touchend touchcancel pointerup pointercancel';
1381
+
1382
+ angular.element(document)
1383
+ .on(START_EVENTS, gestureStart)
1384
+ .on(MOVE_EVENTS, gestureMove)
1385
+ .on(END_EVENTS, gestureEnd)
1386
+ .on('$$mdGestureReset', gestureClearCache); // For testing
1387
+
1388
+ function runHandlers(handlerEvent, event) {
1389
+ var handler;
1390
+ for (var name in HANDLERS) {
1391
+ handler = HANDLERS[name];
1392
+ if( handler instanceof $$MdGestureHandler ) {
1393
+
1394
+ if (handlerEvent === 'start') {
1395
+ // Run cancel to reset any handlers' state
1396
+ angular.isFunction(handler.cancel) && handler.cancel();
1397
+ }
1398
+ handler[handlerEvent](event, pointer);
1281
1399
 
1282
- } else if (shouldCancel) {
1283
- this.cancel();
1284
1400
  }
1285
- } else {
1286
- this.dispatchDragMove(ev);
1287
- }
1288
- },
1289
- // Only dispatch these every frame; any more is unnecessray
1290
- dispatchDragMove: $$rAF.throttle(function(ev) {
1291
- // Make sure the drag didn't stop while waiting for the next frame
1292
- if (this.state.isRunning) {
1293
- updatePointerState(ev, this.state.dragPointer);
1294
- this.dispatchEvent(ev, '$md.drag', this.state.dragPointer);
1295
- }
1296
- }),
1297
- onEnd: function(ev, pointer) {
1298
- if (this.state.dragPointer) {
1299
- updatePointerState(ev, this.state.dragPointer);
1300
- this.dispatchEvent(ev, '$md.dragend', this.state.dragPointer);
1301
1401
  }
1302
1402
  }
1303
- });
1304
1403
 
1305
- addHandler('swipe', {
1306
- options: {
1307
- minVelocity: 0.65,
1308
- minDistance: 10
1309
- },
1310
- onEnd: function(ev, pointer) {
1311
- if (Math.abs(pointer.velocityX) > this.state.options.minVelocity &&
1312
- Math.abs(pointer.distanceX) > this.state.options.minDistance) {
1313
- var eventType = pointer.directionX == 'left' ? '$md.swipeleft' : '$md.swiperight';
1314
- this.dispatchEvent(ev, eventType);
1404
+ function gestureStart(ev) {
1405
+ // If we're already touched down, abort
1406
+ if (pointer) return;
1407
+
1408
+ var now = +Date.now();
1409
+
1410
+ // iOS & old android bug: after a touch event, a click event is sent 350 ms later.
1411
+ // If <400ms have passed, don't allow an event of a different type than the previous event
1412
+ if (lastPointer && !typesMatch(ev, lastPointer) && (now - lastPointer.endTime < 1500)) {
1413
+ return;
1315
1414
  }
1415
+
1416
+ pointer = makeStartPointer(ev);
1417
+
1418
+ runHandlers('start', ev);
1316
1419
  }
1317
- });
1420
+ function gestureMove(ev) {
1421
+ if (!pointer || !typesMatch(ev, pointer)) return;
1318
1422
 
1319
- var self;
1320
- return self = {
1321
- handler: addHandler,
1322
- register: register
1323
- };
1423
+ updatePointerState(ev, pointer);
1424
+ runHandlers('move', ev);
1425
+ }
1426
+ function gestureEnd(ev) {
1427
+ if (!pointer || !typesMatch(ev, pointer)) return;
1324
1428
 
1325
- function addHandler(name, definition) {
1326
- var handler = new $$MdGestureHandler(name);
1327
- angular.extend(handler, definition);
1328
- HANDLERS[name] = handler;
1329
- return self;
1330
- }
1429
+ updatePointerState(ev, pointer);
1430
+ pointer.endTime = +Date.now();
1431
+
1432
+ runHandlers('end', ev);
1331
1433
 
1332
- function register(element, handlerName, options) {
1333
- var handler = HANDLERS[ handlerName.replace(/^\$md./, '') ];
1334
- if (!handler) {
1335
- throw new Error('Failed to register element with handler ' + handlerName + '. ' +
1336
- 'Available handlers: ' + Object.keys(HANDLERS).join(', '));
1434
+ lastPointer = pointer;
1435
+ pointer = null;
1436
+ }
1437
+ function gestureClearCache () {
1438
+ lastPointer = pointer = null;
1337
1439
  }
1338
- return handler.registerElement(element, options);
1339
- }
1340
- }])
1341
- .factory('$$MdGestureHandler', ["$$rAF", function($$rAF) {
1342
1440
 
1343
- function GestureHandler(name) {
1344
- this.name = name;
1345
- this.state = {};
1346
1441
  }
1347
- GestureHandler.prototype = {
1348
- onStart: angular.noop,
1349
- onMove: angular.noop,
1350
- onEnd: angular.noop,
1351
- onCancel: angular.noop,
1352
- options: {},
1353
-
1354
- dispatchEvent: typeof window.jQuery !== 'undefined' && angular.element === window.jQuery ?
1355
- jQueryDispatchEvent :
1356
- nativeDispatchEvent,
1357
-
1358
- start: function(ev, pointer) {
1359
- if (this.state.isRunning) return;
1360
- var parentTarget = this.getNearestParent(ev.target);
1361
- var parentTargetOptions = parentTarget && parentTarget.$mdGesture[this.name] || {};
1362
-
1363
- this.state = {
1364
- isRunning: true,
1365
- options: angular.extend({}, this.options, parentTargetOptions),
1366
- registeredParent: parentTarget
1367
- };
1368
- this.onStart(ev, pointer);
1369
- },
1370
- move: function(ev, pointer) {
1371
- if (!this.state.isRunning) return;
1372
- this.onMove(ev, pointer);
1373
- },
1374
- end: function(ev, pointer) {
1375
- if (!this.state.isRunning) return;
1376
- this.onEnd(ev, pointer);
1377
- this.state.isRunning = false;
1378
- },
1379
- cancel: function(ev, pointer) {
1380
- this.onCancel(ev, pointer);
1381
- this.state = {};
1382
- },
1442
+ attachToDocument.$inject = ["$mdGesture", "$$MdGestureHandler"];
1383
1443
 
1384
- // Find and return the nearest parent element that has been registered via
1385
- // $mdGesture.register(element, 'handlerName').
1386
- getNearestParent: function(node) {
1387
- var current = node;
1388
- while (current) {
1389
- if ( (current.$mdGesture || {})[this.name] ) {
1390
- return current;
1391
- }
1392
- current = current.parentNode;
1393
- }
1394
- },
1444
+ // ********************
1445
+ // Module Functions
1446
+ // ********************
1395
1447
 
1396
- registerElement: function(element, options) {
1397
- var self = this;
1398
- element[0].$mdGesture = element[0].$mdGesture || {};
1399
- element[0].$mdGesture[this.name] = options || {};
1400
- element.on('$destroy', onDestroy);
1448
+ function typesMatch(ev, pointer) {
1449
+ return ev && pointer && ev.type.charAt(0) === pointer.type;
1450
+ }
1401
1451
 
1402
- return onDestroy;
1452
+ function makeStartPointer(ev) {
1453
+ var point = getEventPoint(ev);
1454
+ var startPointer = {
1455
+ startTime: +Date.now(),
1456
+ target: ev.target,
1457
+ // 'p' for pointer, 'm' for mouse, 't' for touch
1458
+ type: ev.type.charAt(0)
1459
+ };
1460
+ startPointer.startX = startPointer.x = point.pageX;
1461
+ startPointer.startY = startPointer.y = point.pageY;
1462
+ return startPointer;
1463
+ }
1403
1464
 
1404
- function onDestroy() {
1405
- delete element[0].$mdGesture[self.name];
1406
- element.off('$destroy', onDestroy);
1407
- }
1408
- }
1409
- };
1465
+ function updatePointerState(ev, pointer) {
1466
+ var point = getEventPoint(ev);
1467
+ var x = pointer.x = point.pageX;
1468
+ var y = pointer.y = point.pageY;
1410
1469
 
1411
- function jQueryDispatchEvent(srcEvent, eventType, eventPointer) {
1412
- eventPointer = eventPointer || pointer;
1413
- var eventObj = new angular.element.Event(eventType);
1414
-
1415
- eventObj.$material = true;
1416
- eventObj.pointer = eventPointer;
1417
- eventObj.srcEvent = srcEvent;
1418
-
1419
- angular.extend(eventObj, {
1420
- clientX: eventPointer.x,
1421
- clientY: eventPointer.y,
1422
- screenX: eventPointer.x,
1423
- screenY: eventPointer.y,
1424
- pageX: eventPointer.x,
1425
- pageY: eventPointer.y,
1426
- ctrlKey: srcEvent.ctrlKey,
1427
- altKey: srcEvent.altKey,
1428
- shiftKey: srcEvent.shiftKey,
1429
- metaKey: srcEvent.metaKey
1430
- });
1431
- angular.element(eventPointer.target).trigger(eventObj);
1432
- }
1470
+ pointer.distanceX = x - pointer.startX;
1471
+ pointer.distanceY = y - pointer.startY;
1472
+ pointer.distance = Math.sqrt(
1473
+ pointer.distanceX * pointer.distanceX + pointer.distanceY * pointer.distanceY
1474
+ );
1433
1475
 
1434
- /*
1435
- * NOTE: nativeDispatchEvent is very performance sensitive.
1436
- */
1437
- function nativeDispatchEvent(srcEvent, eventType, eventPointer) {
1438
- eventPointer = eventPointer || pointer;
1439
- var eventObj;
1440
-
1441
- if (eventType === 'click') {
1442
- eventObj = document.createEvent('MouseEvents');
1443
- eventObj.initMouseEvent(
1444
- 'click', true, true, window, srcEvent.detail,
1445
- eventPointer.x, eventPointer.y, eventPointer.x, eventPointer.y,
1446
- srcEvent.ctrlKey, srcEvent.altKey, srcEvent.shiftKey, srcEvent.metaKey,
1447
- srcEvent.button, srcEvent.relatedTarget || null
1448
- );
1476
+ pointer.directionX = pointer.distanceX > 0 ? 'right' : pointer.distanceX < 0 ? 'left' : '';
1477
+ pointer.directionY = pointer.distanceY > 0 ? 'up' : pointer.distanceY < 0 ? 'down' : '';
1449
1478
 
1450
- } else {
1451
- eventObj = document.createEvent('CustomEvent');
1452
- eventObj.initCustomEvent(eventType, true, true, {});
1453
- }
1454
- eventObj.$material = true;
1455
- eventObj.pointer = eventPointer;
1456
- eventObj.srcEvent = srcEvent;
1457
- eventPointer.target.dispatchEvent(eventObj);
1479
+ pointer.duration = +Date.now() - pointer.startTime;
1480
+ pointer.velocityX = pointer.distanceX / pointer.duration;
1481
+ pointer.velocityY = pointer.distanceY / pointer.duration;
1458
1482
  }
1459
1483
 
1460
- return GestureHandler;
1461
- }]);
1484
+ function getEventPoint(ev) {
1485
+ ev = ev.originalEvent || ev; // support jQuery events
1486
+ return (ev.touches && ev.touches[0]) ||
1487
+ (ev.changedTouches && ev.changedTouches[0]) ||
1488
+ ev;
1489
+ }
1462
1490
 
1463
- })();
1491
+ })(window.jQuery);
1464
1492
 
1465
1493
  /*!
1466
1494
  * Angular Material Design
@@ -3883,17 +3911,22 @@ angular.module('material.components.card', [
3883
3911
  * @description
3884
3912
  * The `<md-card>` directive is a container element used within `<md-content>` containers.
3885
3913
  *
3914
+ * An image included as a direct descendant will fill the card's width, while the `<md-card-content>`
3915
+ * container will wrap text content and provide padding.
3916
+ *
3886
3917
  * Cards have constant width and variable heights; where the maximum height is limited to what can
3887
- * fit within a single view on a platform, but it can temporarily expand as needed
3918
+ * fit within a single view on a platform, but it can temporarily expand as needed.
3888
3919
  *
3889
3920
  * @usage
3890
3921
  * <hljs lang="html">
3891
3922
  * <md-card>
3892
3923
  * <img src="img/washedout.png" class="md-card-image">
3893
- * <h2>Paracosm</h2>
3894
- * <p>
3895
- * The titles of Washed Out's breakthrough song and the first single from Paracosm share the * two most important words in Ernest Greene's musical language: feel it. It's a simple request, as well...
3896
- * </p>
3924
+ * <md-card-content>
3925
+ * <h2>Paracosm</h2>
3926
+ * <p>
3927
+ * The titles of Washed Out's breakthrough song and the first single from Paracosm share the * two most important words in Ernest Greene's musical language: feel it. It's a simple request, as well...
3928
+ * </p>
3929
+ * <md-card-content>
3897
3930
  * </md-card>
3898
3931
  * </hljs>
3899
3932
  *
@@ -4020,7 +4053,7 @@ function MdCheckboxDirective(inputDirective, $mdInkRipple, $mdAria, $mdConstant,
4020
4053
  ngModelCtrl.$render = render;
4021
4054
 
4022
4055
  function keypressHandler(ev) {
4023
- if(ev.which === $mdConstant.KEY_CODE.SPACE) {
4056
+ if(ev.which === $mdConstant.KEY_CODE.SPACE || ev.which === $mdConstant.KEY_CODE.ENTER) {
4024
4057
  ev.preventDefault();
4025
4058
  listener(ev);
4026
4059
  }
@@ -4847,8 +4880,6 @@ angular.module('material.components.divider', [
4847
4880
  ])
4848
4881
  .directive('mdDivider', MdDividerDirective);
4849
4882
 
4850
- function MdDividerController(){}
4851
-
4852
4883
  /**
4853
4884
  * @ngdoc directive
4854
4885
  * @name mdDivider
@@ -4870,8 +4901,7 @@ function MdDividerController(){}
4870
4901
  function MdDividerDirective($mdTheming) {
4871
4902
  return {
4872
4903
  restrict: 'E',
4873
- link: $mdTheming,
4874
- controller: [MdDividerController]
4904
+ link: $mdTheming
4875
4905
  };
4876
4906
  }
4877
4907
  MdDividerDirective.$inject = ["$mdTheming"];
@@ -6604,14 +6634,16 @@ angular.module('material.components.list', [
6604
6634
  * </hljs>
6605
6635
  *
6606
6636
  */
6607
- function mdListDirective() {
6637
+ function mdListDirective($mdTheming) {
6608
6638
  return {
6609
6639
  restrict: 'E',
6610
- compile: function(element) {
6611
- element[0].setAttribute('role', 'list');
6640
+ compile: function(tEl) {
6641
+ tEl[0].setAttribute('role', 'list');
6642
+ return $mdTheming;
6612
6643
  }
6613
6644
  };
6614
6645
  }
6646
+ mdListDirective.$inject = ["$mdTheming"];
6615
6647
 
6616
6648
  /**
6617
6649
  * @ngdoc directive
@@ -6633,14 +6665,154 @@ function mdListDirective() {
6633
6665
  * </hljs>
6634
6666
  *
6635
6667
  */
6636
- function mdItemDirective() {
6668
+ function mdItemDirective($document, $log, $mdUtil, $mdAria) {
6669
+ var proxiedTypes = ['md-checkbox', 'md-switch'];
6637
6670
  return {
6638
6671
  restrict: 'E',
6639
- compile: function(element) {
6640
- element[0].setAttribute('role', 'listitem');
6672
+ compile: function(tEl, tAttrs) {
6673
+ // Check for proxy controls (no ng-click on parent, and a control inside)
6674
+ var secondaryItem = tEl[0].querySelector('.md-secondary');
6675
+ var hasProxiedElement;
6676
+ var proxyElement;
6677
+
6678
+ tEl[0].setAttribute('role', 'listitem');
6679
+
6680
+ if (!tAttrs.ngClick) {
6681
+ for (var i = 0, type; type = proxiedTypes[i]; ++i) {
6682
+ if (proxyElement = tEl[0].querySelector(type)) {
6683
+ hasProxiedElement = true;
6684
+ break;
6685
+ }
6686
+ }
6687
+ if (hasProxiedElement) {
6688
+ wrapIn('div');
6689
+ } else {
6690
+ tEl.addClass('md-no-proxy');
6691
+ }
6692
+ } else {
6693
+ wrapIn('button');
6694
+ }
6695
+ setupToggleAria();
6696
+
6697
+
6698
+ function setupToggleAria() {
6699
+ var toggleTypes = ['md-switch', 'md-checkbox'];
6700
+ var toggle;
6701
+
6702
+ for (var i = 0, toggleType; toggleType = toggleTypes[i]; ++i) {
6703
+ if (toggle = tEl.find(toggleType)[0]) {
6704
+ if (!toggle.hasAttribute('aria-label')) {
6705
+ var p = tEl.find('p')[0];
6706
+ if (!p) return;
6707
+ toggle.setAttribute('aria-label', 'Toggle ' + p.textContent);
6708
+ }
6709
+ }
6710
+ }
6711
+ }
6712
+
6713
+
6714
+ function wrapIn(type) {
6715
+ var container;
6716
+ if (type == 'div') {
6717
+ container = angular.element('<div class="md-no-style md-item-inner">');
6718
+ container.append(tEl.contents());
6719
+ tEl.addClass('md-proxy-focus');
6720
+ } else {
6721
+ container = angular.element('<button tabindex="0" class="md-no-style"><div class="md-item-inner"></div></button>');
6722
+ container[0].setAttribute('ng-click', tEl[0].getAttribute('ng-click'));
6723
+ tEl[0].removeAttribute('ng-click');
6724
+ container.children().eq(0).append(tEl.contents());
6725
+ }
6726
+
6727
+ tEl[0].setAttribute('tabindex', '-1');
6728
+ tEl.append(container);
6729
+
6730
+ if (secondaryItem && secondaryItem.hasAttribute('ng-click')) {
6731
+ $mdAria.expect(secondaryItem, 'aria-label');
6732
+ }
6733
+
6734
+ // Check for a secondary item and move it outside
6735
+ if ( secondaryItem && (
6736
+ secondaryItem.hasAttribute('ng-click') ||
6737
+ ( tAttrs.ngClick &&
6738
+ isProxiedElement(secondaryItem) )
6739
+ )) {
6740
+ tEl.addClass('md-with-secondary');
6741
+ tEl.append(secondaryItem);
6742
+ }
6743
+ }
6744
+
6745
+ function isProxiedElement(el) {
6746
+ return proxiedTypes.indexOf(el.nodeName.toLowerCase()) != -1;
6747
+ }
6748
+
6749
+ return postLink;
6750
+
6751
+ function postLink($scope, $element, $attr) {
6752
+
6753
+ var proxies = [];
6754
+
6755
+ computeProxies();
6756
+ computeClickable();
6757
+
6758
+ if ($element.hasClass('md-proxy-focus') && proxies.length) {
6759
+ angular.forEach(proxies, function(proxy) {
6760
+ proxy = angular.element(proxy);
6761
+ proxy.on('focus', function() {
6762
+ $element.addClass('md-focused');
6763
+ proxy.on('blur', function() {
6764
+ $element.removeClass('md-focused');
6765
+ proxy.off('blur');
6766
+ });
6767
+ });
6768
+ });
6769
+ }
6770
+
6771
+ function computeProxies() {
6772
+ if (!$element.children()[0].hasAttribute('ng-click')) {
6773
+ angular.forEach(proxiedTypes, function(type) {
6774
+ angular.forEach($element[0].firstElementChild.querySelectorAll(type), function(child) {
6775
+ proxies.push(child);
6776
+ });
6777
+ });
6778
+ }
6779
+ }
6780
+ function computeClickable() {
6781
+ if (proxies.length || $element[0].firstElementChild.hasAttribute('ng-click')) {
6782
+ $element.addClass('md-clickable');
6783
+ }
6784
+ }
6785
+
6786
+ if (!$element[0].firstElementChild.hasAttribute('ng-click') && !proxies.length) {
6787
+ $element[0].firstElementChild.addEventListener('keypress', function(e) {
6788
+ if (e.keyCode == 13 || e.keyCode == 32) {
6789
+ $element[0].firstElementChild.click();
6790
+ e.preventDefault();
6791
+ e.stopPropagation();
6792
+ }
6793
+ });
6794
+ }
6795
+
6796
+ $element.off('click');
6797
+ $element.off('keypress');
6798
+
6799
+ if (proxies.length) {
6800
+ $element.children().eq(0).on('click', function(e) {
6801
+ if ($element[0].firstElementChild.contains(e.target)) {
6802
+ angular.forEach(proxies, function(proxy) {
6803
+ if (e.target !== proxy && !proxy.contains(e.target)) {
6804
+ angular.element(proxy).triggerHandler('click');
6805
+ proxy.focus();
6806
+ }
6807
+ });
6808
+ }
6809
+ });
6810
+ }
6811
+ }
6641
6812
  }
6642
6813
  };
6643
6814
  }
6815
+ mdItemDirective.$inject = ["$document", "$log", "$mdUtil", "$mdAria"];
6644
6816
  })();
6645
6817
 
6646
6818
  /*!
@@ -7259,7 +7431,7 @@ function SelectDirective($mdSelect, $mdUtil, $mdTheming, $interpolate, $compile,
7259
7431
 
7260
7432
  return {
7261
7433
  restrict: 'E',
7262
- require: ['mdSelect', 'ngModel'],
7434
+ require: ['mdSelect', 'ngModel', '?^form'],
7263
7435
  compile: compile,
7264
7436
  controller: function() { } // empty placeholder controller to be initialized in link
7265
7437
  };
@@ -7298,6 +7470,20 @@ function SelectDirective($mdSelect, $mdUtil, $mdTheming, $interpolate, $compile,
7298
7470
  );
7299
7471
  }
7300
7472
 
7473
+ if (attr.name) {
7474
+ var autofillClone = angular.element('<select style="position: absolute; z-index: -1">');
7475
+ autofillClone.attr({
7476
+ 'name': '.' + attr.name,
7477
+ 'ng-model': attr.ngModel
7478
+ });
7479
+ var opts = element.find('md-option');
7480
+ angular.forEach(opts, function(el) {
7481
+ var el = angular.element('<option value="' + el.getAttribute('value') + '">' + el.innerHTML + '</option>');
7482
+ autofillClone.append(el);
7483
+ });
7484
+ element.parent().append(autofillClone);
7485
+ }
7486
+
7301
7487
  // Use everything that's left inside element.contents() as the contents of the menu
7302
7488
  var selectTemplate = '<div class="md-select-menu-container">' +
7303
7489
  '<md-select-menu ' +
@@ -7315,11 +7501,18 @@ function SelectDirective($mdSelect, $mdUtil, $mdTheming, $interpolate, $compile,
7315
7501
 
7316
7502
  var mdSelectCtrl = ctrls[0];
7317
7503
  var ngModel = ctrls[1];
7504
+ var formCtrl = ctrls[2];
7505
+
7318
7506
  var labelEl = element.find('md-select-label');
7319
7507
  var customLabel = labelEl.text().length !== 0;
7320
- var selectContainer, selectScope;
7508
+ var selectContainer, selectScope, selectMenuCtrl;
7321
7509
  createSelect();
7322
7510
 
7511
+ if (attr.name && formCtrl) {
7512
+ var selectEl = element.parent()[0].querySelector('select[name=".' + attr.name + '"]')
7513
+ formCtrl.$removeControl(angular.element(selectEl).controller());
7514
+ }
7515
+
7323
7516
  var originalRender = ngModel.$render;
7324
7517
  ngModel.$render = function() {
7325
7518
  originalRender();
@@ -7359,7 +7552,6 @@ function SelectDirective($mdSelect, $mdUtil, $mdTheming, $interpolate, $compile,
7359
7552
  element.removeAttr('multiple');
7360
7553
  }
7361
7554
  if (selectContainer) {
7362
- var selectMenuCtrl = selectContainer.find('md-select-menu').controller('mdSelectMenu');
7363
7555
  selectMenuCtrl.setMultiple(multiple);
7364
7556
  originalRender = ngModel.$render;
7365
7557
  ngModel.$render = function() {
@@ -7384,17 +7576,17 @@ function SelectDirective($mdSelect, $mdUtil, $mdTheming, $interpolate, $compile,
7384
7576
  if (disabled) {
7385
7577
  element.attr('tabindex', -1);
7386
7578
  element.off('click', openSelect);
7387
- element.off('keydown', openOnKeypress);
7579
+ element.off('keydown', handleKeypress);
7388
7580
  } else {
7389
7581
  element.attr('tabindex', 0);
7390
7582
  element.on('click', openSelect);
7391
- element.on('keydown', openOnKeypress);
7583
+ element.on('keydown', handleKeypress);
7392
7584
  }
7393
7585
  });
7394
7586
  if (!attr.disabled && !attr.ngDisabled) {
7395
7587
  element.attr('tabindex', 0);
7396
7588
  element.on('click', openSelect);
7397
- element.on('keydown', openOnKeypress);
7589
+ element.on('keydown', handleKeypress);
7398
7590
  }
7399
7591
 
7400
7592
  element.attr({
@@ -7424,14 +7616,28 @@ function SelectDirective($mdSelect, $mdUtil, $mdTheming, $interpolate, $compile,
7424
7616
  selectEl.data('$mdSelectController', mdSelectCtrl);
7425
7617
  selectScope = scope.$new();
7426
7618
  selectContainer = $compile(selectContainer)(selectScope);
7619
+ selectMenuCtrl = selectContainer.find('md-select-menu').controller('mdSelectMenu');
7427
7620
  }
7428
7621
 
7429
- function openOnKeypress(e) {
7622
+ function handleKeypress(e) {
7430
7623
  var allowedCodes = [32, 13, 38, 40];
7431
7624
  if (allowedCodes.indexOf(e.keyCode) != -1 ) {
7432
7625
  // prevent page scrolling on interaction
7433
7626
  e.preventDefault();
7434
7627
  openSelect(e);
7628
+ } else {
7629
+ if (e.keyCode <= 90 && e.keyCode >= 31) {
7630
+ e.preventDefault();
7631
+ var node = selectMenuCtrl.optNodeForKeyboardSearch(e);
7632
+ if (!node) return;
7633
+ var optionCtrl = angular.element(node).controller('mdOption');
7634
+ if (!selectMenuCtrl.isMultiple) {
7635
+ selectMenuCtrl.deselect( Object.keys(selectMenuCtrl.selected)[0] );
7636
+ }
7637
+ selectMenuCtrl.select(optionCtrl.hashKey, optionCtrl.value);
7638
+ selectMenuCtrl.refreshViewValue();
7639
+ ngModel.$render();
7640
+ }
7435
7641
  }
7436
7642
  }
7437
7643
 
@@ -7556,6 +7762,33 @@ function SelectMenuDirective($parse, $mdUtil, $mdTheming) {
7556
7762
  }
7557
7763
  };
7558
7764
 
7765
+ var searchStr = '';
7766
+ var clearSearchTimeout, optNodes, optText;
7767
+ var CLEAR_SEARCH_AFTER = 300;
7768
+ self.optNodeForKeyboardSearch = function(e) {
7769
+ clearSearchTimeout && clearTimeout(clearSearchTimeout);
7770
+ clearSearchTimeout = setTimeout(function() {
7771
+ clearSearchTimeout = undefined;
7772
+ searchStr = '';
7773
+ optText = undefined;
7774
+ optNodes = undefined;
7775
+ }, CLEAR_SEARCH_AFTER);
7776
+ searchStr += String.fromCharCode(e.keyCode);
7777
+ var search = new RegExp('^' + searchStr, 'i');
7778
+ if (!optNodes) {
7779
+ optNodes = $element.find('md-option');
7780
+ optText = new Array(optNodes.length);
7781
+ angular.forEach(optNodes, function(el, i) {
7782
+ optText[i] = el.textContent;
7783
+ });
7784
+ }
7785
+ for (var i = 0; i < optText.length; ++i) {
7786
+ if (search.test(optText[i])) {
7787
+ return optNodes[i];
7788
+ }
7789
+ }
7790
+ };
7791
+
7559
7792
 
7560
7793
  self.init = function(ngModel) {
7561
7794
  self.ngModel = ngModel;
@@ -7896,9 +8129,15 @@ function SelectProvider($$interimElementProvider) {
7896
8129
  switch (ev.keyCode) {
7897
8130
  case $mdConstant.KEY_CODE.UP_ARROW: return focusPrevOption();
7898
8131
  case $mdConstant.KEY_CODE.DOWN_ARROW: return focusNextOption();
8132
+ default:
8133
+ if (ev.keyCode >= 31 && ev.keyCode <= 90) {
8134
+ var optNode = opts.selectEl.controller('mdSelectMenu').optNodeForKeyboardSearch(ev);
8135
+ optNode && optNode.focus();
8136
+ }
7899
8137
  }
7900
8138
  });
7901
8139
 
8140
+
7902
8141
  function focusOption(direction) {
7903
8142
  var optionsArray = nodesToArray(optionNodes);
7904
8143
  var index = optionsArray.indexOf(opts.focusedNode);
@@ -9214,7 +9453,9 @@ angular.module('material.components.subheader', [
9214
9453
  * @restrict E
9215
9454
  *
9216
9455
  * @description
9217
- * The `<md-subheader>` directive is a subheader for a section
9456
+ * The `<md-subheader>` directive is a subheader for a section. By default it is sticky.
9457
+ * You can make it not sticky by applying the `md-no-sticky` class to the subheader.
9458
+ *
9218
9459
  *
9219
9460
  * @usage
9220
9461
  * <hljs lang="html">
@@ -9247,12 +9488,14 @@ function MdSubheaderDirective($mdSticky, $compile, $mdTheming) {
9247
9488
 
9248
9489
  // Create another clone, that uses the outer and inner contents
9249
9490
  // of the element, that will be 'stickied' as the user scrolls.
9250
- transclude(scope, function(clone) {
9251
- var stickyClone = $compile(angular.element(outerHTML))(scope);
9252
- $mdTheming(stickyClone);
9253
- getContent(stickyClone).append(clone);
9254
- $mdSticky(scope, element, stickyClone);
9255
- });
9491
+ if (!element.hasClass('md-no-sticky')) {
9492
+ transclude(scope, function(clone) {
9493
+ var stickyClone = $compile(angular.element(outerHTML))(scope);
9494
+ $mdTheming(stickyClone);
9495
+ getContent(stickyClone).append(clone);
9496
+ $mdSticky(scope, element, stickyClone);
9497
+ });
9498
+ }
9256
9499
  };
9257
9500
  }
9258
9501
  };
@@ -10145,11 +10388,12 @@ angular
10145
10388
  *
10146
10389
  * @usage
10147
10390
  * <hljs lang="html">
10148
- * <md-icon icon="/img/icons/ic_play_arrow_24px.svg">
10391
+ * <md-button class="md-fab md-accent" aria-label="Play">
10149
10392
  * <md-tooltip>
10150
10393
  * Play Music
10151
10394
  * </md-tooltip>
10152
- * </md-icon>
10395
+ * <md-icon icon="/img/icons/ic_play_arrow_24px.svg"></md-icon>
10396
+ * </md-button>
10153
10397
  * </hljs>
10154
10398
  *
10155
10399
  * @param {expression=} md-visible Boolean bound to whether the tooltip is
@@ -10370,41 +10614,497 @@ angular.module('material.components.whiteframe', []);
10370
10614
  (function () {
10371
10615
  'use strict';
10372
10616
  angular
10373
- .module('material.components.autocomplete')
10374
- .controller('MdAutocompleteCtrl', MdAutocompleteCtrl);
10375
-
10376
- function MdAutocompleteCtrl ($scope, $element, $mdUtil, $mdConstant, $timeout) {
10377
-
10378
- //-- private variables
10379
-
10380
- var self = this,
10381
- itemParts = $scope.itemsExpr.split(/ in /i),
10382
- itemExpr = itemParts[1],
10383
- elements = null,
10384
- promise = null,
10385
- cache = {},
10386
- noBlur = false;
10617
+ .module('material.components.chips')
10618
+ .directive('mdChipRemove', MdChipRemove);
10387
10619
 
10388
- //-- public variables
10620
+ /**
10621
+ * @ngdoc directive
10622
+ * @name mdChipRemove
10623
+ * @module material.components.chips
10624
+ *
10625
+ * @description
10626
+ * `<md-chip-remove>`
10627
+ * Creates a remove button for the given chip.
10628
+ *
10629
+ * @usage
10630
+ * <hljs lang="html">
10631
+ * <md-chip>{{$chip}}<md-chip-remove></md-chip-remove></md-chip>
10632
+ * </hljs>
10633
+ */
10634
+
10635
+ var REMOVE_CHIP_TEMPLATE = '\
10636
+ <md-button ng-if="!$mdChipsCtrl.readonly" ng-click="$mdChipsCtrl.removeChip($index)">\
10637
+ <md-icon md-svg-icon="close"></md-icon>\
10638
+ <span class="visually-hidden">Remove</span>\
10639
+ </md-button>';
10640
+
10641
+ /**
10642
+ *
10643
+ * @param $compile
10644
+ * @param $timeout
10645
+ * @returns {{restrict: string, require: string[], link: Function, scope: boolean}}
10646
+ * @constructor
10647
+ */
10648
+ function MdChipRemove ($compile, $timeout) {
10649
+ return {
10650
+ restrict: 'E',
10651
+ template: REMOVE_CHIP_TEMPLATE,
10652
+ require: ['^mdChips'],
10653
+ scope: false
10654
+ };
10655
+ }
10656
+ MdChipRemove.$inject = ["$compile", "$timeout"];
10657
+ })();
10658
+
10659
+ /*!
10660
+ * Angular Material Design
10661
+ * https://github.com/angular/material
10662
+ * @license MIT
10663
+ * v0.8.3
10664
+ */
10665
+ (function () {
10666
+ 'use strict';
10667
+ angular
10668
+ .module('material.components.chips')
10669
+ .controller('MdChipsCtrl', MdChipsCtrl);
10670
+
10671
+
10672
+
10673
+ /**
10674
+ * Controller for the MdChips component. Responsible for adding to and
10675
+ * removing from the list of chips, marking chips as selected, and binding to
10676
+ * the models of various input components.
10677
+ *
10678
+ * @param $mdUtil
10679
+ * @param $mdConstant
10680
+ * @param $log
10681
+ * @ngInject
10682
+ * @constructor
10683
+ */
10684
+ function MdChipsCtrl ($mdUtil, $mdConstant, $log) {
10685
+ /** @type {Object} */
10686
+ this.$mdConstant = $mdConstant;
10687
+
10688
+ /** @type {$log} */
10689
+ this.$log = $log;
10690
+
10691
+ /** @type {angular.NgModelController} */
10692
+ this.ngModelCtrl = null;
10693
+
10694
+ /** @type {Object} */
10695
+ this.mdAutocompleteCtrl = null;
10696
+
10697
+ /** @type {Array.<Object>} */
10698
+ this.items = [];
10699
+
10700
+ /** @type {number} */
10701
+ this.selectedChip = -1;
10702
+
10703
+ /**
10704
+ * Model used by the input element.
10705
+ * @type {string}
10706
+ */
10707
+ this.chipBuffer = '';
10708
+
10709
+ /**
10710
+ * Whether to use the mdChipAppend expression to transform the chip buffer
10711
+ * before appending it to the list.
10712
+ * @type {boolean}
10713
+ */
10714
+ this.useMdChipAppend = false;
10715
+
10716
+ /**
10717
+ * Whether the Chip buffer is driven by an input element provided by the
10718
+ * caller.
10719
+ * @type {boolean}
10720
+ */
10721
+ this.hasInputElement = false;
10722
+ }
10723
+ MdChipsCtrl.$inject = ["$mdUtil", "$mdConstant", "$log"];
10724
+
10725
+
10726
+ /**
10727
+ * Handles the keydown event on the input element: <enter> appends the
10728
+ * buffer to the chip list, while backspace removes the last chip in the list
10729
+ * if the current buffer is empty.
10730
+ * @param event
10731
+ */
10732
+ MdChipsCtrl.prototype.defaultInputKeydown = function(event) {
10733
+ switch (event.keyCode) {
10734
+ case this.$mdConstant.KEY_CODE.ENTER:
10735
+ if ( this.chipBuffer ) {
10736
+ event.preventDefault();
10737
+ this.appendChipBuffer();
10738
+ }
10739
+ break;
10740
+ case this.$mdConstant.KEY_CODE.BACKSPACE: // backspace
10741
+ if (!this.chipBuffer) {
10742
+ event.preventDefault();
10743
+ // TODO(typotter): Probably want to open the previous one for edit instead.
10744
+ this.removeChip(this.items.length - 1);
10745
+ }
10746
+ break;
10747
+ default:
10748
+ }
10749
+ };
10750
+
10751
+
10752
+ /**
10753
+ * Sets the selected chip index to -1.
10754
+ */
10755
+ MdChipsCtrl.prototype.resetSelectedChip = function() {
10756
+ this.selectedChip = -1;
10757
+ };
10758
+
10759
+
10760
+ /**
10761
+ * Append the contents of the buffer to the chip list. This method will first
10762
+ * call out to the md-chip-append method, if provided
10763
+ */
10764
+ MdChipsCtrl.prototype.appendChipBuffer = function() {
10765
+ var newChip = this.getChipBuffer();
10766
+ if (this.useMdChipAppend && this.mdChipAppend) {
10767
+ newChip = this.mdChipAppend({'$chip': newChip});
10768
+ }
10769
+ this.items.push(newChip);
10770
+ this.resetChipBuffer();
10771
+ };
10772
+
10773
+
10774
+ /**
10775
+ * Sets whether to use the md-chip-append expression. This expression is
10776
+ * bound to scope and controller in {@code MdChipsDirective} as
10777
+ * {@code mdChipAppend}. Due to the nature of directive scope bindings, the
10778
+ * controller cannot know on its own/from the scope whether an expression was
10779
+ * actually provided.
10780
+ */
10781
+ MdChipsCtrl.prototype.useMdChipAppendExpression = function() {
10782
+ this.useMdChipAppend = true;
10783
+ };
10784
+
10785
+
10786
+ /**
10787
+ * Gets the input buffer. The input buffer can be the model bound to the
10788
+ * default input item {@code this.chipBuffer}, the {@code selectedItem}
10789
+ * model of an {@code md-autocomplete}, or, through some magic, the model
10790
+ * bound to any inpput or text area element found within a
10791
+ * {@code md-input-container} element.
10792
+ * @return {Object|string}
10793
+ */
10794
+ MdChipsCtrl.prototype.getChipBuffer = function() {
10795
+ if (this.mdAutocompleteCtrl) {
10796
+ this.$log.error('md-autocomplete not yet supported');
10797
+ } else if (this.hasInputElement) {
10798
+ this.$log.error('user-provided inputs not yet supported');
10799
+ } else {
10800
+ return this.chipBuffer;
10801
+ }
10802
+ };
10803
+
10804
+
10805
+ /**
10806
+ * Resets the input buffer.
10807
+ */
10808
+ MdChipsCtrl.prototype.resetChipBuffer = function() {
10809
+ if (this.mdAutocompleteCtrl) {
10810
+ this.$log.error('md-autocomplete not yet supported');
10811
+ } else {
10812
+ this.chipBuffer = '';
10813
+ }
10814
+ };
10815
+
10816
+
10817
+ /**
10818
+ * Removes the chip at the given index.
10819
+ * @param index
10820
+ */
10821
+ MdChipsCtrl.prototype.removeChip = function(index) {
10822
+ this.items.splice(index, 1);
10823
+ };
10824
+
10825
+
10826
+ /**
10827
+ * Marks the chip at the given index as selected.
10828
+ * @param index
10829
+ */
10830
+ MdChipsCtrl.prototype.selectChip = function(index) {
10831
+ if (index >= 0 && index <= this.items.length) {
10832
+ this.selectedChip = index;
10833
+ } else {
10834
+ this.$log.warn('Selected Chip index out of bounds; ignoring.');
10835
+ }
10836
+ };
10837
+
10838
+
10839
+ /**
10840
+ * Configures the required interactions with the ngModel Controller.
10841
+ * Specifically, set {@code this.items} to the {@code NgModelCtrl#$viewVale}.
10842
+ * @param ngModelCtrl
10843
+ */
10844
+ MdChipsCtrl.prototype.configureNgModel = function(ngModelCtrl) {
10845
+ this.ngModelCtrl = ngModelCtrl;
10846
+
10847
+ var self = this;
10848
+ ngModelCtrl.$render = function() {
10849
+ // model is updated. do something.
10850
+ self.items = self.ngModelCtrl.$viewValue;
10851
+ };
10852
+ };
10853
+
10854
+
10855
+ /**
10856
+ * Configure bindings with the MdAutocomplete control.
10857
+ * @param mdAutocompleteCtrl
10858
+ */
10859
+ MdChipsCtrl.prototype.configureMdAutocomplete = function(mdAutocompleteCtrl) {
10860
+ this.mdAutocompleteCtrl = mdAutocompleteCtrl;
10861
+ // TODO(typotter): create and register a selectedItem watcher with mdAutocompleteCtrl.
10862
+ };
10863
+ })();
10864
+
10865
+ /*!
10866
+ * Angular Material Design
10867
+ * https://github.com/angular/material
10868
+ * @license MIT
10869
+ * v0.8.3
10870
+ */
10871
+ (function () {
10872
+ 'use strict';
10873
+ angular
10874
+ .module('material.components.chips')
10875
+ .directive('mdChips', MdChips);
10876
+ /**
10877
+ * @ngdoc directive
10878
+ * @name mdChips
10879
+ * @module material.components.chips
10880
+ *
10881
+ * @description
10882
+ * `<md-chips>` is an input component for building lists of strings or objects. The list items are displayed as
10883
+ * 'chips'. This component can make use of an `<input>` element or an `<md-autocomplete>` element.
10884
+ *
10885
+ * <strong>Custom `<md-chip>` template</strong>
10886
+ * A custom template may be provided to render the content of each chip. This is achieved by specifying an `<md-chip>`
10887
+ * element as a child of `<md-chips>`. Note: Any attributes on the passed `<md-chip>` will be dropped as only the
10888
+ * innerHTML is used for the chip template. The variables `$chip` and `$index` are available in the scope of
10889
+ * `<md-chip>`, representing the chip object and its index int he list of chips, respectively.
10890
+ *
10891
+ * <h3> Pending Features </h3>
10892
+ * <ul style="padding-left:20px;">
10893
+ * <ul>Expand input controls: Support md-autocomplete
10894
+ * <li>plain `<input>` tag as child</li>
10895
+ * <li>textarea input</li>
10896
+ * <li>md-input?</li>
10897
+ * </ul>
10898
+ *
10899
+ * <ul>List Manipulation
10900
+ * <li>delete item via DEL or backspace keys when selected</li>
10901
+ * </ul>
10902
+ *
10903
+ * <ul>Validation
10904
+ * <li>de-dupe values (or support duplicates, but fix the ng-repeat duplicate key issue)</li>
10905
+ * <li>allow a validation callback</li>
10906
+ * <li>hilighting style for invalid chips</li>
10907
+ * </ul>
10908
+ *
10909
+ * <ul>Item mutation
10910
+ * <li>Support `
10911
+ * <md-chip-edit>` template, show/hide the edit element on tap/click? double tap/double click?
10912
+ * </li>
10913
+ * </ul>
10914
+ *
10915
+ * <ul>Truncation and Disambiguation (?)
10916
+ * <li>Truncate chip text where possible, but do not truncate entries such that two are indistinguishable.</li>
10917
+ * </ul>
10918
+ *
10919
+ * <ul>Drag and Drop
10920
+ * <li>Drag and drop chips between related `
10921
+ * <md-chips>` elements.
10922
+ * </li>
10923
+ * </ul>
10924
+ * </ul>
10925
+ *
10926
+ * <span style="font-size:.8em;text-align:center">
10927
+ * Warning: This component is a WORK IN PROGRESS. If you use it now,
10928
+ * it will probably break on you in the future.
10929
+ * </span>
10930
+ *
10931
+ *
10932
+ * @param {string=|object=} ng-model A model to bind the list of items to
10933
+ * @param {string=} placeholder Placeholder text that will be forwarded to the input.
10934
+ * @param {string=} secondary-placeholder Placeholder text that will be forwarded to the input, displayed when there
10935
+ * is at least on item in the list
10936
+ * @param {boolean=} readonly Disables list manipulation (deleting or adding list items), hiding the input and delete
10937
+ * buttons
10938
+ * @param {expression} md-chip-append An expression expected to convert the input string into an object when adding
10939
+ * a chip.
10940
+ *
10941
+ * @usage
10942
+ * <hljs lang="html">
10943
+ * <md-chips
10944
+ * ng-model="myItems"
10945
+ * placeholder="Add an item"
10946
+ * readonly="isReadOnly">
10947
+ * </md-chips>
10948
+ * </hljs>
10949
+ *
10950
+ */
10951
+
10952
+
10953
+ var MD_CHIPS_TEMPLATE = '\
10954
+ <md-chips-wrap ng-if="!$mdChipsCtrl.readonly || $mdChipsCtrl.items.length > 0" class="md-chips">\
10955
+ <div role="presentation">\
10956
+ <md-chip ng-repeat="$chip in $mdChipsCtrl.items"\
10957
+ ng-class="{selected: $mdChipsCtrl.selectedChip == $index}"\
10958
+ ng-click="!$mdChipsCtrl.readonly && $mdChipsCtrl.selectChip($index)"\
10959
+ class="md-chip">\
10960
+ </md-chip>\
10961
+ <div ng-if="!$mdChipsCtrl.readonly" class="md-chip-worker"></div>\
10962
+ </div>\
10963
+ </md-chips-wrap>';
10964
+
10965
+ var CHIP_INPUT_TEMPLATE = '\
10966
+ <input\
10967
+ placeholder="{{$mdChipsCtrl.items.length == 0 ? $mdChipsCtrl.placeholder : $mdChipsCtrl.secondaryPlaceholder}}"\
10968
+ class="md-chip-input"\
10969
+ ng-model="$mdChipsCtrl.chipBuffer"\
10970
+ ng-focus="$mdChipsCtrl.resetSelectedChip()"\
10971
+ ng-keydown="$mdChipsCtrl.defaultInputKeydown($event)">';
10972
+
10973
+ var CHIP_DEFAULT_TEMPLATE = '\
10974
+ <span>{{$chip}}</span>\
10975
+ <md-chip-remove ng-if="!$mdChipsCtrl.readonly"></md-chip-remove>';
10976
+
10977
+
10978
+
10979
+ /**
10980
+ * MDChips Directive Definition
10981
+ * @param $mdTheming
10982
+ * @param $log
10983
+ * @ngInject
10984
+ */
10985
+ function MdChips ($mdTheming, $log) {
10986
+ return {
10987
+ template: function(element, attrs) {
10988
+ // Clone the element into an attribute. By prepending the attribute
10989
+ // name with '$', Angular won't write it into the DOM. The cloned
10990
+ // element propagates to the link function via the attrs argument,
10991
+ // where various contained-elements can be consumed.
10992
+ attrs['$mdUserTemplate'] = element.clone();
10993
+ return MD_CHIPS_TEMPLATE;
10994
+ },
10995
+ require: ['ngModel', 'mdChips'],
10996
+ restrict: 'E',
10997
+ controller: 'MdChipsCtrl',
10998
+ controllerAs: '$mdChipsCtrl',
10999
+ bindToController: true,
11000
+ compile: compile,
11001
+ scope: {
11002
+ readonly: '=readonly',
11003
+ placeholder: '@',
11004
+ secondaryPlaceholder: '@',
11005
+ mdChipAppend: '&'
11006
+ }
11007
+ };
11008
+ function compile(element, attr) {
11009
+ var userTemplate = attr['$mdUserTemplate'];
11010
+ var chipEl = userTemplate.find('md-chip');
11011
+ var chipHtml;
11012
+ if (chipEl.length === 0) {
11013
+ chipHtml = CHIP_DEFAULT_TEMPLATE;
11014
+ } else {
11015
+ // Warn if no remove button is included in the template.
11016
+ if (chipEl.find('md-chip-remove').length == 0) {
11017
+ $log.warn('md-chip-remove attribute not found in md-chip template.');
11018
+ }
11019
+ // Take only the chip's inner HTML as the encasing repeater is an md-chip element.
11020
+ chipHtml = chipEl[0].innerHTML;
11021
+ }
11022
+ var listNode = angular.element(element[0].querySelector('.md-chip'));
11023
+ listNode.append(chipHtml);
11024
+
11025
+ // Input Element: Look for an autocomplete or an input.
11026
+ var inputEl = userTemplate.find('md-autocomplete');
11027
+ var hasAutocomplete = inputEl.length > 0;
11028
+
11029
+ if (!hasAutocomplete) {
11030
+ // TODO(typotter): Check for an input or a textarea
11031
+
11032
+ // Default element.
11033
+ inputEl = angular.element(CHIP_INPUT_TEMPLATE);
11034
+ var workerChip = angular.element(element[0].querySelector('.md-chip-worker'));
11035
+ workerChip.append(inputEl);
11036
+ }
11037
+
11038
+ return function postLink(scope, element, attrs, controllers) {
11039
+ $mdTheming(element);
11040
+ var ngModelCtrl = controllers[0];
11041
+ var mdChipsCtrl = controllers[1];
11042
+ mdChipsCtrl.configureNgModel(ngModelCtrl);
11043
+
11044
+ if (attrs.mdChipAppend) {
11045
+ mdChipsCtrl.useMdChipAppendExpression();
11046
+ }
11047
+
11048
+ if (hasAutocomplete) {
11049
+ // TODO(typotter): Tell the mdChipsCtrl about the mdAutocompleteCtrl and have it
11050
+ // watch the selectedItem model.
11051
+ $log.error('md-autocomplete not yet supported');
11052
+ }
11053
+ };
11054
+ }
11055
+ }
11056
+ MdChips.$inject = ["$mdTheming", "$log"];
11057
+ })();
11058
+
11059
+ /*!
11060
+ * Angular Material Design
11061
+ * https://github.com/angular/material
11062
+ * @license MIT
11063
+ * v0.8.3
11064
+ */
11065
+ (function () {
11066
+ 'use strict';
11067
+ angular
11068
+ .module('material.components.autocomplete')
11069
+ .controller('MdAutocompleteCtrl', MdAutocompleteCtrl);
11070
+
11071
+ function MdAutocompleteCtrl ($scope, $element, $mdUtil, $mdConstant, $timeout) {
11072
+
11073
+ //-- private variables
11074
+
11075
+ var self = this,
11076
+ itemParts = $scope.itemsExpr.split(/ in /i),
11077
+ itemExpr = itemParts[1],
11078
+ elements = null,
11079
+ promise = null,
11080
+ cache = {},
11081
+ noBlur = false,
11082
+ selectedItemWatchers = [];
11083
+
11084
+ //-- public variables
10389
11085
 
10390
- self.scope = $scope;
10391
- self.parent = $scope.$parent;
11086
+ self.scope = $scope;
11087
+ self.parent = $scope.$parent;
10392
11088
  self.itemName = itemParts[0];
10393
- self.matches = [];
10394
- self.loading = false;
10395
- self.hidden = true;
10396
- self.index = null;
11089
+ self.matches = [];
11090
+ self.loading = false;
11091
+ self.hidden = true;
11092
+ self.index = null;
10397
11093
  self.messages = [];
10398
- self.id = $mdUtil.nextUid();
11094
+ self.id = $mdUtil.nextUid();
10399
11095
 
10400
11096
  //-- public methods
10401
11097
 
10402
- self.keydown = keydown;
10403
- self.blur = blur;
10404
- self.clear = clearValue;
10405
- self.select = select;
10406
- self.getCurrentDisplayValue = getCurrentDisplayValue;
10407
- self.fetch = $mdUtil.debounce(fetchResults);
11098
+ self.keydown = keydown;
11099
+ self.blur = blur;
11100
+ self.focus = focus;
11101
+ self.clear = clearValue;
11102
+ self.select = select;
11103
+ self.fetch = $mdUtil.debounce(fetchResults);
11104
+ self.getCurrentDisplayValue = getCurrentDisplayValue;
11105
+ self.registerSelectedItemWatcher = registerSelectedItemWatcher;
11106
+ self.unregisterSelectedItemWatcher = unregisterSelectedItemWatcher;
11107
+
10408
11108
  self.listEnter = function () { noBlur = true; };
10409
11109
  self.listLeave = function () { noBlur = false; };
10410
11110
  self.mouseUp = function () { elements.input.focus(); };
@@ -10430,13 +11130,8 @@ angular.module('material.components.whiteframe', []);
10430
11130
  $scope.$watch('searchText', wait
10431
11131
  ? $mdUtil.debounce(handleSearchText, wait)
10432
11132
  : handleSearchText);
10433
- $scope.$watch('selectedItem', function (selectedItem, previousSelectedItem) {
10434
- if (selectedItem) {
10435
- $scope.searchText = getDisplayValue(selectedItem);
10436
- }
10437
- if ($scope.itemChange && selectedItem !== previousSelectedItem)
10438
- $scope.itemChange(getItemScope(selectedItem));
10439
- });
11133
+ registerSelectedItemWatcher(selectedItemChange);
11134
+ $scope.$watch('selectedItem', handleSelectedItemChange);
10440
11135
  }
10441
11136
 
10442
11137
  function gatherElements () {
@@ -10449,6 +11144,41 @@ angular.module('material.components.whiteframe', []);
10449
11144
 
10450
11145
  //-- event/change handlers
10451
11146
 
11147
+ function selectedItemChange (selectedItem, previousSelectedItem) {
11148
+ if (selectedItem) {
11149
+ $scope.searchText = getDisplayValue(selectedItem);
11150
+ }
11151
+ if ($scope.itemChange && selectedItem !== previousSelectedItem)
11152
+ $scope.itemChange(getItemScope(selectedItem));
11153
+ }
11154
+
11155
+ function handleSelectedItemChange(selectedItem, previousSelectedItem) {
11156
+ for (var i = 0; i < selectedItemWatchers.length; ++i) {
11157
+ selectedItemWatchers[i](selectedItem, previousSelectedItem);
11158
+ }
11159
+ }
11160
+
11161
+ /**
11162
+ * Register a function to be called when the selected item changes.
11163
+ * @param cb
11164
+ */
11165
+ function registerSelectedItemWatcher(cb) {
11166
+ if (selectedItemWatchers.indexOf(cb) == -1) {
11167
+ selectedItemWatchers.push(cb);
11168
+ }
11169
+ }
11170
+
11171
+ /**
11172
+ * Unregister a function previously registered for selected item changes.
11173
+ * @param cb
11174
+ */
11175
+ function unregisterSelectedItemWatcher(cb) {
11176
+ var i = selectedItemWatchers.indexOf(cb);
11177
+ if (i != -1) {
11178
+ selectedItemWatchers.splice(i, 1);
11179
+ }
11180
+ }
11181
+
10452
11182
  function handleSearchText (searchText, previousSearchText) {
10453
11183
  self.index = getDefaultIndex();
10454
11184
  //-- do nothing on init if there is no initial value
@@ -10456,36 +11186,31 @@ angular.module('material.components.whiteframe', []);
10456
11186
  //-- clear selected item if search text no longer matches it
10457
11187
  if (searchText !== getDisplayValue($scope.selectedItem)) $scope.selectedItem = null;
10458
11188
  else return;
11189
+ //-- trigger change event if available
11190
+ if ($scope.textChange && searchText !== previousSearchText)
11191
+ $scope.textChange(getItemScope($scope.selectedItem));
10459
11192
  //-- cancel results if search text is not long enough
10460
- if (!searchText || searchText.length < Math.max(parseInt($scope.minLength, 10), 1)) {
11193
+ if (!isMinLengthMet()) {
10461
11194
  self.loading = false;
10462
11195
  self.matches = [];
10463
11196
  self.hidden = shouldHide();
10464
11197
  updateMessages();
10465
- return;
10466
- }
10467
- var term = searchText.toLowerCase();
10468
- //-- cancel promise if a promise is in progress
10469
- if (promise && promise.cancel) {
10470
- promise.cancel();
10471
- promise = null;
10472
- }
10473
- //-- if results are cached, pull in cached results
10474
- if (!$scope.noCache && cache[term]) {
10475
- self.matches = cache[term];
10476
- updateMessages();
10477
11198
  } else {
10478
- fetchResults(searchText);
11199
+ handleQuery();
10479
11200
  }
10480
- self.hidden = shouldHide();
10481
- if ($scope.textChange && searchText !== previousSearchText)
10482
- $scope.textChange(getItemScope($scope.selectedItem));
10483
11201
  }
10484
11202
 
10485
11203
  function blur () {
10486
11204
  if (!noBlur) self.hidden = true;
10487
11205
  }
10488
11206
 
11207
+ function focus () {
11208
+ //-- if searchText is null, let's force it to be a string
11209
+ if (!angular.isString($scope.searchText)) return $scope.searchText = '';
11210
+ self.hidden = shouldHide();
11211
+ if (!self.hidden) handleQuery();
11212
+ }
11213
+
10489
11214
  function keydown (event) {
10490
11215
  switch (event.keyCode) {
10491
11216
  case $mdConstant.KEY_CODE.DOWN_ARROW:
@@ -10520,6 +11245,10 @@ angular.module('material.components.whiteframe', []);
10520
11245
 
10521
11246
  //-- getters
10522
11247
 
11248
+ function getMinLength () {
11249
+ return angular.isNumber($scope.minLength) ? $scope.minLength : 1;
11250
+ }
11251
+
10523
11252
  function getDisplayValue (item) {
10524
11253
  return (item && $scope.itemText) ? $scope.itemText(getItemScope(item)) : item;
10525
11254
  }
@@ -10536,6 +11265,7 @@ angular.module('material.components.whiteframe', []);
10536
11265
  }
10537
11266
 
10538
11267
  function shouldHide () {
11268
+ if (!isMinLengthMet()) return true;
10539
11269
  return self.matches.length === 1
10540
11270
  && $scope.searchText === getDisplayValue(self.matches[0])
10541
11271
  && $scope.selectedItem === self.matches[0];
@@ -10545,6 +11275,10 @@ angular.module('material.components.whiteframe', []);
10545
11275
  return getDisplayValue(self.matches[self.index]);
10546
11276
  }
10547
11277
 
11278
+ function isMinLengthMet () {
11279
+ return $scope.searchText.length >= getMinLength();
11280
+ }
11281
+
10548
11282
  //-- actions
10549
11283
 
10550
11284
  function select (index) {
@@ -10609,260 +11343,26 @@ angular.module('material.components.whiteframe', []);
10609
11343
  }
10610
11344
  }
10611
11345
 
10612
- }
10613
- MdAutocompleteCtrl.$inject = ["$scope", "$element", "$mdUtil", "$mdConstant", "$timeout"];
10614
- })();
10615
-
10616
- /*!
10617
- * Angular Material Design
10618
- * https://github.com/angular/material
10619
- * @license MIT
10620
- * v0.8.3
10621
- */
10622
- (function () {
10623
- 'use strict';
10624
- angular
10625
- .module('material.components.autocomplete')
10626
- .directive('mdAutocomplete', MdAutocomplete);
10627
-
10628
- /**
10629
- * @ngdoc directive
10630
- * @name mdAutocomplete
10631
- * @module material.components.autocomplete
10632
- *
10633
- * @description
10634
- * `<md-autocomplete>` is a special input component with a drop-down of all possible matches to a custom query.
10635
- * This component allows you to provide real-time suggestions as the user types in the input area.
10636
- *
10637
- * @param {string=} md-search-text A model to bind the search query text to
10638
- * @param {object=} md-selected-item A model to bind the selected item to
10639
- * @param {expression} md-items An expression in the format of `item in items` to iterate over matches for your search.
10640
- * @param {string=} md-item-text An expression that will convert your object to a single string.
10641
- * @param {string=} placeholder Placeholder text that will be forwarded to the input.
10642
- * @param {boolean=} md-no-cache Disables the internal caching that happens in autocomplete
10643
- * @param {expression} md-selected-item-change An expression to be run each time a new item is selected
10644
- * @param {expression} md-search-text-change An expression to be run each time the search text updates
10645
- * @param {boolean=} ng-disabled Determines whether or not to disable the input field
10646
- * @param {number=} md-min-length Specifies the minimum length of text before autocomplete will make suggestions
10647
- * @param {number=} md-delay Specifies the amount of time (in milliseconds) to wait before looking for results
10648
- * @param {boolean=} md-autofocus If true, will immediately focus the input element
10649
- * @param {boolean=} md-autoselect If true, the first item will be selected by default
10650
- *
10651
- * @usage
10652
- * <hljs lang="html">
10653
- * <md-autocomplete
10654
- * md-selected-item="selectedItem"
10655
- * md-search-text="searchText"
10656
- * md-items="item in getMatches(searchText)"
10657
- * md-item-text="item.display">
10658
- * <span md-highlight-text="searchText">{{item.display}}</span>
10659
- * </md-autocomplete>
10660
- * </hljs>
10661
- */
10662
-
10663
- function MdAutocomplete () {
10664
- return {
10665
- transclude: true,
10666
- controller: 'MdAutocompleteCtrl',
10667
- controllerAs: '$mdAutocompleteCtrl',
10668
- link: link,
10669
- scope: {
10670
- searchText: '=mdSearchText',
10671
- selectedItem: '=mdSelectedItem',
10672
- itemsExpr: '@mdItems',
10673
- itemText: '&mdItemText',
10674
- placeholder: '@placeholder',
10675
- noCache: '=?mdNoCache',
10676
- itemChange: '&mdSelectedItemChange',
10677
- textChange: '&mdSearchTextChange',
10678
- isDisabled: '=ngDisabled',
10679
- minLength: '=mdMinLength',
10680
- delay: '=mdDelay',
10681
- autofocus: '=?mdAutofocus',
10682
- floatingLabel: '@mdFloatingLabel',
10683
- autoselect: '=?mdAutoselect'
10684
- },
10685
- template: '\
10686
- <md-autocomplete-wrap role="listbox">\
10687
- <md-input-container ng-if="floatingLabel">\
10688
- <label>{{floatingLabel}}</label>\
10689
- <input type="text"\
10690
- id="fl-input-{{$mdAutocompleteCtrl.id}}"\
10691
- name="fl-input-{{$mdAutocompleteCtrl.id}}"\
10692
- autocomplete="off"\
10693
- ng-disabled="isDisabled"\
10694
- ng-model="$mdAutocompleteCtrl.scope.searchText"\
10695
- ng-keydown="$mdAutocompleteCtrl.keydown($event)"\
10696
- ng-blur="$mdAutocompleteCtrl.blur()"\
10697
- aria-owns="ul-{{$mdAutocompleteCtrl.id}}"\
10698
- aria-label="{{floatingLabel}}"\
10699
- aria-autocomplete="list"\
10700
- aria-haspopup="true"\
10701
- aria-activedescendant=""\
10702
- aria-expanded="{{!$mdAutocompleteCtrl.hidden}}"/>\
10703
- \
10704
- </md-input-container>\
10705
- <input type="text"\
10706
- id="input-{{$mdAutocompleteCtrl.id}}"\
10707
- name="input-{{$mdAutocompleteCtrl.id}}"\
10708
- ng-if="!floatingLabel"\
10709
- autocomplete="off"\
10710
- ng-disabled="isDisabled"\
10711
- ng-model="$mdAutocompleteCtrl.scope.searchText"\
10712
- ng-keydown="$mdAutocompleteCtrl.keydown($event)"\
10713
- ng-blur="$mdAutocompleteCtrl.blur()"\
10714
- placeholder="{{placeholder}}"\
10715
- aria-owns="ul-{{$mdAutocompleteCtrl.id}}"\
10716
- aria-label="{{placeholder}}"\
10717
- aria-autocomplete="list"\
10718
- aria-haspopup="true"\
10719
- aria-activedescendant=""\
10720
- aria-expanded="{{!$mdAutocompleteCtrl.hidden}}"/>\
10721
- <button\
10722
- type="button"\
10723
- ng-if="$mdAutocompleteCtrl.scope.searchText && !isDisabled"\
10724
- ng-click="$mdAutocompleteCtrl.clear()">\
10725
- <md-icon md-svg-icon="cancel"></md-icon>\
10726
- <span class="visually-hidden">Clear</span>\
10727
- </button>\
10728
- <md-progress-linear\
10729
- ng-if="$mdAutocompleteCtrl.loading"\
10730
- md-mode="indeterminate"></md-progress-linear>\
10731
- <ul role="presentation"\
10732
- id="ul-{{$mdAutocompleteCtrl.id}}"\
10733
- ng-mouseenter="$mdAutocompleteCtrl.listEnter()"\
10734
- ng-mouseleave="$mdAutocompleteCtrl.listLeave()"\
10735
- ng-mouseup="$mdAutocompleteCtrl.mouseUp()">\
10736
- <li ng-repeat="(index, item) in $mdAutocompleteCtrl.matches"\
10737
- ng-class="{ selected: index === $mdAutocompleteCtrl.index }"\
10738
- ng-show="$mdAutocompleteCtrl.scope.searchText && !$mdAutocompleteCtrl.hidden"\
10739
- ng-click="$mdAutocompleteCtrl.select(index)"\
10740
- ng-transclude\
10741
- md-autocomplete-list-item="$mdAutocompleteCtrl.itemName">\
10742
- </li>\
10743
- </ul>\
10744
- </md-autocomplete-wrap>\
10745
- <aria-status\
10746
- class="visually-hidden"\
10747
- role="status"\
10748
- aria-live="assertive">\
10749
- <p ng-repeat="message in $mdAutocompleteCtrl.messages">{{message.display}}</p>\
10750
- </aria-status>'
10751
- };
10752
-
10753
- function link (scope, element, attr) {
10754
- angular.forEach(scope.$$isolateBindings, function (binding, key) {
10755
- if (binding.optional && angular.isUndefined(scope[key])) {
10756
- scope[key] = attr.hasOwnProperty(attr.$normalize(binding.attrName));
10757
- }
10758
- });
10759
- }
10760
- }
10761
- })();
10762
-
10763
- /*!
10764
- * Angular Material Design
10765
- * https://github.com/angular/material
10766
- * @license MIT
10767
- * v0.8.3
10768
- */
10769
- (function () {
10770
- 'use strict';
10771
- angular
10772
- .module('material.components.autocomplete')
10773
- .controller('MdHighlightCtrl', MdHighlightCtrl);
10774
-
10775
- function MdHighlightCtrl ($scope, $element, $interpolate) {
10776
- var term = $element.attr('md-highlight-text'),
10777
- text = $interpolate($element.text())($scope),
10778
- watcher = $scope.$watch(term, function (term) {
10779
- var regex = new RegExp('^' + sanitize(term), 'i'),
10780
- html = text.replace(regex, '<span class="highlight">$&</span>');
10781
- $element.html(html);
10782
- });
10783
- $element.on('$destroy', function () { watcher(); });
10784
-
10785
- function sanitize (term) {
10786
- if (!term) return term;
10787
- return term.replace(/[\*\[\]\(\)\{\}\\\^\$]/g, '\\$&');
10788
- }
10789
- }
10790
- MdHighlightCtrl.$inject = ["$scope", "$element", "$interpolate"];
10791
-
10792
- })();
10793
-
10794
- /*!
10795
- * Angular Material Design
10796
- * https://github.com/angular/material
10797
- * @license MIT
10798
- * v0.8.3
10799
- */
10800
- (function () {
10801
- 'use strict';
10802
- angular
10803
- .module('material.components.autocomplete')
10804
- .directive('mdHighlightText', MdHighlight);
10805
-
10806
- /**
10807
- * @ngdoc directive
10808
- * @name mdHighlightText
10809
- * @module material.components.autocomplete
10810
- *
10811
- * @description
10812
- * The `md-highlight-text` directive allows you to specify text that should be highlighted within
10813
- * an element. Highlighted text will be wrapped in `<span class="highlight"></span>` which can
10814
- * be styled through CSS. Please note that child elements may not be used with this directive.
10815
- *
10816
- * @param {string=} md-highlight-text A model to be searched for
10817
- *
10818
- * @usage
10819
- * <hljs lang="html">
10820
- * <input placeholder="Enter a search term..." ng-model="searchTerm" type="text" />
10821
- * <ul>
10822
- * <li ng-repeat="result in results" md-highlight-text="searchTerm">
10823
- * {{result.text}}
10824
- * </li>
10825
- * </ul>
10826
- * </hljs>
10827
- */
10828
-
10829
- function MdHighlight () {
10830
- return {
10831
- terminal: true,
10832
- scope: false,
10833
- controller: 'MdHighlightCtrl'
10834
- };
10835
- }
10836
- })();
10837
-
10838
- /*!
10839
- * Angular Material Design
10840
- * https://github.com/angular/material
10841
- * @license MIT
10842
- * v0.8.3
10843
- */
10844
- (function () {
10845
- 'use strict';
10846
- angular
10847
- .module('material.components.autocomplete')
10848
- .directive('mdAutocompleteListItem', MdAutocompleteListItem);
10849
-
10850
- function MdAutocompleteListItem ($compile, $mdUtil) {
10851
- return {
10852
- require: '^?mdAutocomplete',
10853
- terminal: true,
10854
- link: link,
10855
- scope: false
10856
- };
10857
- function link (scope, element, attr, ctrl) {
10858
- var newScope = ctrl.parent.$new(false, ctrl.parent),
10859
- itemName = ctrl.scope.$eval(attr.mdAutocompleteListItem);
10860
- newScope[itemName] = scope.item;
10861
- $compile(element.contents())(newScope);
10862
- element.attr({ 'role': 'option', 'id': 'item_' + $mdUtil.nextUid() });
11346
+ function handleQuery () {
11347
+ var searchText = $scope.searchText,
11348
+ term = searchText.toLowerCase();
11349
+ //-- cancel promise if a promise is in progress
11350
+ if (promise && promise.cancel) {
11351
+ promise.cancel();
11352
+ promise = null;
11353
+ }
11354
+ //-- if results are cached, pull in cached results
11355
+ if (!$scope.noCache && cache[term]) {
11356
+ self.matches = cache[term];
11357
+ updateMessages();
11358
+ } else {
11359
+ fetchResults(searchText);
11360
+ }
11361
+ self.hidden = shouldHide();
10863
11362
  }
11363
+
10864
11364
  }
10865
- MdAutocompleteListItem.$inject = ["$compile", "$mdUtil"];
11365
+ MdAutocompleteCtrl.$inject = ["$scope", "$element", "$mdUtil", "$mdConstant", "$timeout"];
10866
11366
  })();
10867
11367
 
10868
11368
  /*!
@@ -10874,248 +11374,179 @@ angular.module('material.components.whiteframe', []);
10874
11374
  (function () {
10875
11375
  'use strict';
10876
11376
  angular
10877
- .module('material.components.chips')
10878
- .directive('mdChipRemove', MdChipRemove);
11377
+ .module('material.components.autocomplete')
11378
+ .directive('mdAutocomplete', MdAutocomplete);
10879
11379
 
10880
11380
  /**
10881
11381
  * @ngdoc directive
10882
- * @name mdChipRemove
10883
- * @module material.components.chips
11382
+ * @name mdAutocomplete
11383
+ * @module material.components.autocomplete
10884
11384
  *
10885
11385
  * @description
10886
- * `<element md-chip-remove>`
10887
- * Identifies an element within an <md-chip> as the delete button. This
10888
- * directive binds to that element's click event and removes the chip.
11386
+ * `<md-autocomplete>` is a special input component with a drop-down of all possible matches to a custom query.
11387
+ * This component allows you to provide real-time suggestions as the user types in the input area.
11388
+ *
11389
+ * @param {string=} md-search-text A model to bind the search query text to
11390
+ * @param {object=} md-selected-item A model to bind the selected item to
11391
+ * @param {expression} md-items An expression in the format of `item in items` to iterate over matches for your search.
11392
+ * @param {string=} md-item-text An expression that will convert your object to a single string.
11393
+ * @param {string=} placeholder Placeholder text that will be forwarded to the input.
11394
+ * @param {boolean=} md-no-cache Disables the internal caching that happens in autocomplete
11395
+ * @param {expression} md-selected-item-change An expression to be run each time a new item is selected
11396
+ * @param {expression} md-search-text-change An expression to be run each time the search text updates
11397
+ * @param {boolean=} ng-disabled Determines whether or not to disable the input field
11398
+ * @param {number=} md-min-length Specifies the minimum length of text before autocomplete will make suggestions
11399
+ * @param {number=} md-delay Specifies the amount of time (in milliseconds) to wait before looking for results
11400
+ * @param {boolean=} md-autofocus If true, will immediately focus the input element
11401
+ * @param {boolean=} md-autoselect If true, the first item will be selected by default
10889
11402
  *
10890
11403
  * @usage
10891
11404
  * <hljs lang="html">
10892
- * <md-chip>{{$chip}}<button md-chip-remove>x</button></md-chip>
11405
+ * <md-autocomplete
11406
+ * md-selected-item="selectedItem"
11407
+ * md-search-text="searchText"
11408
+ * md-items="item in getMatches(searchText)"
11409
+ * md-item-text="item.display">
11410
+ * <span md-highlight-text="searchText">{{item.display}}</span>
11411
+ * </md-autocomplete>
10893
11412
  * </hljs>
10894
11413
  */
10895
11414
 
10896
- function MdChipRemove () {
11415
+ function MdAutocomplete () {
10897
11416
  return {
10898
- restrict: 'A',
10899
- require: ['^mdChips'],
10900
- link: function postLink(scope, element, attrs, controllers) {
10901
- var mdChipsCtrl = controllers[0];
10902
- element.on('click', removeItemListener(mdChipsCtrl, scope));
11417
+ controller: 'MdAutocompleteCtrl',
11418
+ controllerAs: '$mdAutocompleteCtrl',
11419
+ link: link,
11420
+ scope: {
11421
+ name: '@',
11422
+ searchText: '=?mdSearchText',
11423
+ selectedItem: '=?mdSelectedItem',
11424
+ itemsExpr: '@mdItems',
11425
+ itemText: '&mdItemText',
11426
+ placeholder: '@placeholder',
11427
+ noCache: '=?mdNoCache',
11428
+ itemChange: '&?mdSelectedItemChange',
11429
+ textChange: '&?mdSearchTextChange',
11430
+ isDisabled: '=?ngDisabled',
11431
+ minLength: '=?mdMinLength',
11432
+ delay: '=?mdDelay',
11433
+ autofocus: '=?mdAutofocus',
11434
+ floatingLabel: '@?mdFloatingLabel',
11435
+ autoselect: '=?mdAutoselect'
10903
11436
  },
10904
- scope: false
11437
+ template: function (element, attr) {
11438
+ attr.$mdAutocompleteTemplate = element.html();
11439
+ return '\
11440
+ <md-autocomplete-wrap role="listbox">\
11441
+ <md-input-container ng-if="floatingLabel">\
11442
+ <label>{{floatingLabel}}</label>\
11443
+ <input type="text"\
11444
+ id="fl-input-{{$mdAutocompleteCtrl.id}}"\
11445
+ name="{{name}}"\
11446
+ autocomplete="off"\
11447
+ ng-disabled="isDisabled"\
11448
+ ng-model="$mdAutocompleteCtrl.scope.searchText"\
11449
+ ng-keydown="$mdAutocompleteCtrl.keydown($event)"\
11450
+ ng-blur="$mdAutocompleteCtrl.blur()"\
11451
+ ng-focus="$mdAutocompleteCtrl.focus()"\
11452
+ aria-owns="ul-{{$mdAutocompleteCtrl.id}}"\
11453
+ aria-label="{{floatingLabel}}"\
11454
+ aria-autocomplete="list"\
11455
+ aria-haspopup="true"\
11456
+ aria-activedescendant=""\
11457
+ aria-expanded="{{!$mdAutocompleteCtrl.hidden}}"/>\
11458
+ \
11459
+ </md-input-container>\
11460
+ <input type="text"\
11461
+ id="input-{{$mdAutocompleteCtrl.id}}"\
11462
+ name="{{name}}"\
11463
+ ng-if="!floatingLabel"\
11464
+ autocomplete="off"\
11465
+ ng-disabled="isDisabled"\
11466
+ ng-model="$mdAutocompleteCtrl.scope.searchText"\
11467
+ ng-keydown="$mdAutocompleteCtrl.keydown($event)"\
11468
+ ng-blur="$mdAutocompleteCtrl.blur()"\
11469
+ ng-focus="$mdAutocompleteCtrl.focus()"\
11470
+ placeholder="{{placeholder}}"\
11471
+ aria-owns="ul-{{$mdAutocompleteCtrl.id}}"\
11472
+ aria-label="{{placeholder}}"\
11473
+ aria-autocomplete="list"\
11474
+ aria-haspopup="true"\
11475
+ aria-activedescendant=""\
11476
+ aria-expanded="{{!$mdAutocompleteCtrl.hidden}}"/>\
11477
+ <button\
11478
+ type="button"\
11479
+ ng-if="$mdAutocompleteCtrl.scope.searchText && !isDisabled"\
11480
+ ng-click="$mdAutocompleteCtrl.clear()">\
11481
+ <md-icon md-svg-icon="cancel"></md-icon>\
11482
+ <span class="visually-hidden">Clear</span>\
11483
+ </button>\
11484
+ <md-progress-linear\
11485
+ ng-if="$mdAutocompleteCtrl.loading"\
11486
+ md-mode="indeterminate"></md-progress-linear>\
11487
+ <ul role="presentation"\
11488
+ id="ul-{{$mdAutocompleteCtrl.id}}"\
11489
+ ng-mouseenter="$mdAutocompleteCtrl.listEnter()"\
11490
+ ng-mouseleave="$mdAutocompleteCtrl.listLeave()"\
11491
+ ng-mouseup="$mdAutocompleteCtrl.mouseUp()">\
11492
+ <li ng-repeat="(index, item) in $mdAutocompleteCtrl.matches"\
11493
+ ng-class="{ selected: index === $mdAutocompleteCtrl.index }"\
11494
+ ng-hide="$mdAutocompleteCtrl.hidden"\
11495
+ ng-click="$mdAutocompleteCtrl.select(index)"\
11496
+ md-autocomplete-list-item-template="contents"\
11497
+ md-autocomplete-list-item="$mdAutocompleteCtrl.itemName">\
11498
+ </li>\
11499
+ </ul>\
11500
+ </md-autocomplete-wrap>\
11501
+ <aria-status\
11502
+ class="visually-hidden"\
11503
+ role="status"\
11504
+ aria-live="assertive">\
11505
+ <p ng-repeat="message in $mdAutocompleteCtrl.messages">{{message.display}}</p>\
11506
+ </aria-status>';
11507
+ }
10905
11508
  };
10906
11509
 
10907
- function removeItemListener(chipsCtrl, scope) {
10908
- return function() {
10909
- scope.$apply(function() {
10910
- chipsCtrl.removeChip(scope.$index);
10911
- });
10912
- };
11510
+ function link (scope, element, attr) {
11511
+ scope.contents = attr.$mdAutocompleteTemplate;
11512
+ angular.forEach(scope.$$isolateBindings, function (binding, key) {
11513
+ if (binding.optional && angular.isUndefined(scope[key])) {
11514
+ scope[key] = attr.hasOwnProperty(attr.$normalize(binding.attrName));
11515
+ }
11516
+ });
10913
11517
  }
10914
11518
  }
10915
11519
  })();
10916
11520
 
10917
- /*!
10918
- * Angular Material Design
10919
- * https://github.com/angular/material
10920
- * @license MIT
10921
- * v0.8.3
10922
- */
10923
- (function () {
10924
- 'use strict';
10925
- angular
10926
- .module('material.components.chips')
10927
- .controller('MdChipsCtrl', MdChipsCtrl);
10928
-
10929
-
10930
-
10931
- /**
10932
- * Controller for the MdChips component. Responsible for adding to and
10933
- * removing from the list of chips, marking chips as selected, and binding to
10934
- * the models of various input components.
10935
- *
10936
- * @param $mdUtil
10937
- * @param $mdConstant
10938
- * @param $log
10939
- * @ngInject
10940
- * @constructor
10941
- */
10942
- function MdChipsCtrl ($mdUtil, $mdConstant, $log) {
10943
- /** @type {Object} */
10944
- this.$mdConstant = $mdConstant;
10945
-
10946
- /** @type {$log} */
10947
- this.$log = $log;
10948
-
10949
- /** @type {angular.NgModelController} */
10950
- this.ngModelCtrl = null;
10951
-
10952
- /** @type {Object} */
10953
- this.mdAutocompleteCtrl = null;
10954
-
10955
- /** @type {Array.<Object>} */
10956
- this.items = [];
10957
-
10958
- /** @type {number} */
10959
- this.selectedChip = -1;
10960
-
10961
- /**
10962
- * Model used by the input element.
10963
- * @type {string}
10964
- */
10965
- this.chipBuffer = '';
10966
-
10967
- /**
10968
- * Whether to use the mdChipAppend expression to transform the chip buffer
10969
- * before appending it to the list.
10970
- * @type {boolean}
10971
- */
10972
- this.useMdChipAppend = false;
10973
-
10974
- /**
10975
- * Whether the Chip buffer is driven by an input element provided by the
10976
- * caller.
10977
- * @type {boolean}
10978
- */
10979
- this.hasInputElement = false;
10980
- }
10981
- MdChipsCtrl.$inject = ["$mdUtil", "$mdConstant", "$log"];
10982
-
10983
-
10984
- /**
10985
- * Handles the keydown event on the input element: <enter> appends the
10986
- * buffer to the chip list, while backspace removes the last chip in the list
10987
- * if the current buffer is empty.
10988
- * @param event
10989
- */
10990
- MdChipsCtrl.prototype.defaultInputKeydown = function(event) {
10991
- switch (event.keyCode) {
10992
- case this.$mdConstant.KEY_CODE.ENTER:
10993
- event.preventDefault();
10994
- this.appendChipBuffer();
10995
- break;
10996
- case this.$mdConstant.KEY_CODE.BACKSPACE: // backspace
10997
- if (!this.chipBuffer) {
10998
- event.preventDefault();
10999
- // TODO(typotter): Probably want to open the previous one for edit instead.
11000
- this.removeChip(this.items.length - 1);
11001
- }
11002
- break;
11003
- default:
11004
- }
11005
- };
11006
-
11007
-
11008
- /**
11009
- * Sets the selected chip index to -1.
11010
- */
11011
- MdChipsCtrl.prototype.resetSelectedChip = function() {
11012
- this.selectedChip = -1;
11013
- };
11014
-
11015
-
11016
- /**
11017
- * Append the contents of the buffer to the chip list. This method will first
11018
- * call out to the md-chip-append method, if provided
11019
- */
11020
- MdChipsCtrl.prototype.appendChipBuffer = function() {
11021
- var newChip = this.getChipBuffer();
11022
- if (this.useMdChipAppend && this.mdChipAppend) {
11023
- newChip = this.mdChipAppend({'$chip': newChip});
11024
- }
11025
- this.items.push(newChip);
11026
- this.resetChipBuffer();
11027
- };
11028
-
11029
-
11030
- /**
11031
- * Sets whether to use the md-chip-append expression. This expression is
11032
- * bound to scope and controller in {@code MdChipsDirective} as
11033
- * {@code mdChipAppend}. Due to the nature of directive scope bindings, the
11034
- * controller cannot know on its own/from the scope whether an expression was
11035
- * actually provided.
11036
- */
11037
- MdChipsCtrl.prototype.useMdChipAppendExpression = function() {
11038
- this.useMdChipAppend = true;
11039
- };
11040
-
11041
-
11042
- /**
11043
- * Gets the input buffer. The input buffer can be the model bound to the
11044
- * default input item {@code this.chipBuffer}, the {@code selectedItem}
11045
- * model of an {@code md-autocomplete}, or, through some magic, the model
11046
- * bound to any inpput or text area element found within a
11047
- * {@code md-input-container} element.
11048
- * @return {Object|string}
11049
- */
11050
- MdChipsCtrl.prototype.getChipBuffer = function() {
11051
- if (this.mdAutocompleteCtrl) {
11052
- this.$log.error('md-autocomplete not yet supported');
11053
- } else if (this.hasInputElement) {
11054
- this.$log.error('user-provided inputs not yet supported');
11055
- } else {
11056
- return this.chipBuffer;
11057
- }
11058
- };
11059
-
11060
-
11061
- /**
11062
- * Resets the input buffer.
11063
- */
11064
- MdChipsCtrl.prototype.resetChipBuffer = function() {
11065
- if (this.mdAutocompleteCtrl) {
11066
- this.$log.error('md-autocomplete not yet supported');
11067
- } else {
11068
- this.chipBuffer = '';
11069
- }
11070
- };
11071
-
11072
-
11073
- /**
11074
- * Removes the chip at the given index.
11075
- * @param index
11076
- */
11077
- MdChipsCtrl.prototype.removeChip = function(index) {
11078
- this.items.splice(index, 1);
11079
- };
11080
-
11081
-
11082
- /**
11083
- * Marks the chip at the given index as selected.
11084
- * @param index
11085
- */
11086
- MdChipsCtrl.prototype.selectChip = function(index) {
11087
- if (index >= 0 && index <= this.items.length) {
11088
- this.selectedChip = index;
11089
- } else {
11090
- this.$log.warn('Selected Chip index out of bounds; ignoring.');
11091
- }
11092
- };
11093
-
11094
-
11095
- /**
11096
- * Configures the required interactions with the ngModel Controller.
11097
- * Specifically, set {@code this.items} to the {@code NgModelCtrl#$viewVale}.
11098
- * @param ngModelCtrl
11099
- */
11100
- MdChipsCtrl.prototype.configureNgModel = function(ngModelCtrl) {
11101
- this.ngModelCtrl = ngModelCtrl;
11521
+ /*!
11522
+ * Angular Material Design
11523
+ * https://github.com/angular/material
11524
+ * @license MIT
11525
+ * v0.8.3
11526
+ */
11527
+ (function () {
11528
+ 'use strict';
11529
+ angular
11530
+ .module('material.components.autocomplete')
11531
+ .controller('MdHighlightCtrl', MdHighlightCtrl);
11102
11532
 
11103
- var self = this;
11104
- ngModelCtrl.$render = function() {
11105
- // model is updated. do something.
11106
- self.items = self.ngModelCtrl.$viewValue;
11107
- };
11108
- };
11533
+ function MdHighlightCtrl ($scope, $element, $interpolate) {
11534
+ var term = $element.attr('md-highlight-text'),
11535
+ text = $interpolate($element.text())($scope),
11536
+ watcher = $scope.$watch(term, function (term) {
11537
+ var regex = new RegExp('^' + sanitize(term), 'i'),
11538
+ html = text.replace(regex, '<span class="highlight">$&</span>');
11539
+ $element.html(html);
11540
+ });
11541
+ $element.on('$destroy', function () { watcher(); });
11109
11542
 
11543
+ function sanitize (term) {
11544
+ if (!term) return term;
11545
+ return term.replace(/[\*\[\]\(\)\{\}\\\^\$]/g, '\\$&');
11546
+ }
11547
+ }
11548
+ MdHighlightCtrl.$inject = ["$scope", "$element", "$interpolate"];
11110
11549
 
11111
- /**
11112
- * Configure bindings with the MdAutocomplete control.
11113
- * @param mdAutocompleteCtrl
11114
- */
11115
- MdChipsCtrl.prototype.configureMdAutocomplete = function(mdAutocompleteCtrl) {
11116
- this.mdAutocompleteCtrl = mdAutocompleteCtrl;
11117
- // TODO(typotter): create and register a selectedItem watcher with mdAutocompleteCtrl.
11118
- };
11119
11550
  })();
11120
11551
 
11121
11552
  /*!
@@ -11127,182 +11558,70 @@ angular.module('material.components.whiteframe', []);
11127
11558
  (function () {
11128
11559
  'use strict';
11129
11560
  angular
11130
- .module('material.components.chips')
11131
- .directive('mdChips', MdChips);
11561
+ .module('material.components.autocomplete')
11562
+ .directive('mdHighlightText', MdHighlight);
11563
+
11132
11564
  /**
11133
11565
  * @ngdoc directive
11134
- * @name mdChips
11135
- * @module material.components.chips
11566
+ * @name mdHighlightText
11567
+ * @module material.components.autocomplete
11136
11568
  *
11137
11569
  * @description
11138
- * `<md-chips>` is an input component for building lists of strings or objects. The list items are displayed as
11139
- * 'chips'. This component can make use of an `<input>` element or an `<md-autocomplete>` element.
11140
- *
11141
- * <h3> Pending Features </h3>
11142
- * <ul style="padding-left:20px;">
11143
- * <ul>Expand input controls: Support md-autocomplete
11144
- * <li>plain `<input>` tag as child</li>
11145
- * <li>textarea input</li>
11146
- * <li>md-input?</li>
11147
- * </ul>
11148
- *
11149
- * <ul>List Manipulation
11150
- * <li>delete item via DEL or backspace keys when selected</li>
11151
- * </ul>
11152
- *
11153
- * <ul>Validation
11154
- * <li>de-dupe values (or support duplicates, but fix the ng-repeat duplicate key issue)</li>
11155
- * <li>allow a validation callback</li>
11156
- * <li>hilighting style for invalid chips</li>
11157
- * </ul>
11158
- *
11159
- * <ul>Item mutation
11160
- * <li>Support `
11161
- * <md-chip-edit>` template, show/hide the edit element on tap/click? double tap/double click?
11162
- * </li>
11163
- * </ul>
11164
- *
11165
- * <ul>Truncation and Disambiguation (?)
11166
- * <li>Truncate chip text where possible, but do not truncate entries such that two are indistinguishable.</li>
11167
- * </ul>
11168
- *
11169
- * <ul>Drag and Drop
11170
- * <li>Drag and drop chips between related `
11171
- * <md-chips>` elements.
11172
- * </li>
11173
- * </ul>
11174
- * </ul>
11175
- *
11176
- * <span style="font-size:.8em;text-align:center">
11177
- * Warning: This component is a WORK IN PROGRESS. If you use it now,
11178
- * it will probably break on you in the future.
11179
- * </span>
11180
- *
11570
+ * The `md-highlight-text` directive allows you to specify text that should be highlighted within
11571
+ * an element. Highlighted text will be wrapped in `<span class="highlight"></span>` which can
11572
+ * be styled through CSS. Please note that child elements may not be used with this directive.
11181
11573
  *
11182
- * @param {string=|object=} ng-model A model to bind the list of items to
11183
- * @param {string=} placeholder Placeholder text that will be forwarded to the input.
11184
- * @param {string=} secondary-placeholder Placeholder text that will be forwarded to the input, displayed when there
11185
- * is at least on item in the list
11186
- * @param {boolean=} readonly Disables list manipulation (deleting or adding list items), hiding the input and delete
11187
- * buttons
11188
- * @param {expression} md-chip-append An expression expected to convert the input string into an object when adding
11189
- * a chip.
11574
+ * @param {string=} md-highlight-text A model to be searched for
11190
11575
  *
11191
11576
  * @usage
11192
11577
  * <hljs lang="html">
11193
- * <md-chips
11194
- * ng-model="myItems"
11195
- * placeholder="Add an item"
11196
- * readonly="isReadOnly">
11197
- * </md-chips>
11578
+ * <input placeholder="Enter a search term..." ng-model="searchTerm" type="text" />
11579
+ * <ul>
11580
+ * <li ng-repeat="result in results" md-highlight-text="searchTerm">
11581
+ * {{result.text}}
11582
+ * </li>
11583
+ * </ul>
11198
11584
  * </hljs>
11199
- *
11200
11585
  */
11201
11586
 
11202
-
11203
- var MD_CHIPS_TEMPLATE = '\
11204
- <md-chips-wrap ng-class="{readonly : $mdChipsCtrl.readonly}" class="md-chips">\
11205
- <div role="presentation">\
11206
- <div ng-repeat="$chip in $mdChipsCtrl.items"\
11207
- ng-class="{selected: $mdChipsCtrl.selectedChip == $index}"\
11208
- ng-click="!$mdChipsCtrl.readonly && $mdChipsCtrl.selectChip($index)"\
11209
- class="md-chip">\
11210
- </div>\
11211
- <div ng-if="!$mdChipsCtrl.readonly" class="md-chip-worker"></div>\
11212
- </div>\
11213
- </md-chips-wrap>';
11214
-
11215
- var CHIP_INPUT_TEMPLATE = '\
11216
- <input\
11217
- placeholder="{{$mdChipsCtrl.items.length == 0 ? $mdChipsCtrl.placeholder : $mdChipsCtrl.secondaryPlaceholder}}"\
11218
- class="md-chip-input"\
11219
- ng-model="$mdChipsCtrl.chipBuffer"\
11220
- ng-focus="$mdChipsCtrl.resetSelectedChip()"\
11221
- ng-keydown="$mdChipsCtrl.defaultInputKeydown($event)">';
11222
-
11223
- var CHIP_DEFAULT_TEMPLATE = '\
11224
- <md-chip>\
11225
- <span>{{$chip}}</span>\
11226
- <md-button ng-if="!$mdChipsCtrl.readonly"\
11227
- md-chip-remove>x</md-button>\
11228
- </md-chip>';
11229
-
11230
-
11231
- /**
11232
- * MDChips Directive Definition
11233
- * @param $mdTheming
11234
- * @param $log
11235
- * @ngInject
11236
- */
11237
- function MdChips ($mdTheming, $log) {
11587
+ function MdHighlight () {
11238
11588
  return {
11239
- template: function(element, attrs) {
11240
- // Clone the element into an attribute. By prepending the attribute
11241
- // name with '$', Angular won't write it into the DOM. The cloned
11242
- // element propagates to the link function via the attrs argument,
11243
- // where various contained-elements can be consumed.
11244
- attrs['$mdUserTemplate'] = element.clone();
11245
- return MD_CHIPS_TEMPLATE;
11246
- },
11247
- require: ['ngModel', 'mdChips'],
11248
- restrict: 'E',
11249
- controller: 'MdChipsCtrl',
11250
- controllerAs: '$mdChipsCtrl',
11251
- bindToController: true,
11252
- compile: compile,
11253
- scope: {
11254
- readonly: '=readonly',
11255
- placeholder: '@',
11256
- secondaryPlaceholder: '@',
11257
- mdChipAppend: '&'
11258
- }
11589
+ terminal: true,
11590
+ scope: false,
11591
+ controller: 'MdHighlightCtrl'
11259
11592
  };
11260
- function compile(element, attr) {
11261
- var userTemplate = attr['$mdUserTemplate'];
11262
- var chipEl = userTemplate.find('md-chip');
11263
- if (chipEl.length === 0) {
11264
- chipEl = angular.element(CHIP_DEFAULT_TEMPLATE);
11265
- } else {
11266
- // Warn if no remove button is included in the template.
11267
- if (!chipEl[0].querySelector('[md-chip-remove]')) {
11268
- $log.warn('md-chip-remove attribute not found in md-chip template.');
11269
- }
11270
- }
11271
- var listNode = angular.element(element[0].querySelector('.md-chip'));
11272
- listNode.append(chipEl);
11273
-
11274
- // Input Element: Look for an autocomplete or an input.
11275
- var inputEl = userTemplate.find('md-autocomplete');
11276
- var hasAutocomplete = inputEl.length > 0;
11277
-
11278
- if (!hasAutocomplete) {
11279
- // TODO(typotter): Check for an input or a textarea
11280
-
11281
- // Default element.
11282
- inputEl = angular.element(CHIP_INPUT_TEMPLATE);
11283
- var workerChip = angular.element(element[0].querySelector('.md-chip-worker'));
11284
- workerChip.append(inputEl);
11285
- }
11286
-
11287
- return function postLink(scope, element, attrs, controllers) {
11288
- $mdTheming(element);
11289
- var ngModelCtrl = controllers[0];
11290
- var mdChipsCtrl = controllers[1];
11291
- mdChipsCtrl.configureNgModel(ngModelCtrl);
11593
+ }
11594
+ })();
11292
11595
 
11293
- if (attrs.mdChipAppend) {
11294
- mdChipsCtrl.useMdChipAppendExpression();
11295
- }
11596
+ /*!
11597
+ * Angular Material Design
11598
+ * https://github.com/angular/material
11599
+ * @license MIT
11600
+ * v0.8.3
11601
+ */
11602
+ (function () {
11603
+ 'use strict';
11604
+ angular
11605
+ .module('material.components.autocomplete')
11606
+ .directive('mdAutocompleteListItem', MdAutocompleteListItem);
11296
11607
 
11297
- if (hasAutocomplete) {
11298
- // TODO(typotter): Tell the mdChipsCtrl about the mdAutocompleteCtrl and have it
11299
- // watch the selectedItem model.
11300
- $log.error('md-autocomplete not yet supported');
11301
- }
11302
- };
11608
+ function MdAutocompleteListItem ($compile, $mdUtil) {
11609
+ return {
11610
+ require: '^?mdAutocomplete',
11611
+ terminal: true,
11612
+ link: link,
11613
+ scope: false
11614
+ };
11615
+ function link (scope, element, attr, ctrl) {
11616
+ var newScope = ctrl.parent.$new(false, ctrl.parent),
11617
+ itemName = ctrl.scope.$eval(attr.mdAutocompleteListItem);
11618
+ newScope[itemName] = scope.item;
11619
+ element.html(ctrl.scope.$eval(attr.mdAutocompleteListItemTemplate));
11620
+ $compile(element.contents())(newScope);
11621
+ element.attr({ 'role': 'option', 'id': 'item_' + $mdUtil.nextUid() });
11303
11622
  }
11304
11623
  }
11305
- MdChips.$inject = ["$mdTheming", "$log"];
11624
+ MdAutocompleteListItem.$inject = ["$compile", "$mdUtil"];
11306
11625
  })();
11307
11626
 
11308
11627
  /*!
@@ -11505,22 +11824,20 @@ angular.module('material.components.whiteframe', []);
11505
11824
  angular.module('material.components.tabs')
11506
11825
  .directive('mdTabScroll', MdTabScroll);
11507
11826
 
11508
- function MdTabScroll () {
11827
+ function MdTabScroll ($parse) {
11509
11828
  return {
11510
11829
  restrict: 'A',
11511
- link: function (scope, element, attr) {
11512
- element.on('mousewheel', function (event) {
11513
- var newScope = scope.$new();
11514
- newScope.$event = event;
11515
- newScope.$element = element;
11516
- newScope.$apply(function () {
11517
- newScope.$eval(attr.mdTabScroll);
11830
+ compile: function ($element, attr) {
11831
+ var fn = $parse(attr.mdTabScroll, null, true);
11832
+ return function ngEventHandler (scope, element) {
11833
+ element.on('mousewheel', function (event) {
11834
+ scope.$apply(function () { fn(scope, { $event: event }); });
11518
11835
  });
11519
- });
11836
+ };
11520
11837
  }
11521
-
11522
11838
  }
11523
11839
  }
11840
+ MdTabScroll.$inject = ["$parse"];
11524
11841
  })();
11525
11842
  /*!
11526
11843
  * Angular Material Design
@@ -11553,6 +11870,7 @@ angular.module('material.components.whiteframe', []);
11553
11870
  ctrl.attachRipple = attachRipple;
11554
11871
  ctrl.shouldStretchTabs = shouldStretchTabs;
11555
11872
  ctrl.shouldPaginate = shouldPaginate;
11873
+ ctrl.shouldCenterTabs = shouldCenterTabs;
11556
11874
  ctrl.insertTab = insertTab;
11557
11875
  ctrl.removeTab = removeTab;
11558
11876
  ctrl.select = select;
@@ -11574,15 +11892,24 @@ angular.module('material.components.whiteframe', []);
11574
11892
  $scope.$watch('$mdTabsCtrl.offsetLeft', handleOffsetChange);
11575
11893
  angular.element($window).on('resize', function () { $scope.$apply(handleWindowResize); });
11576
11894
  $timeout(updateInkBarStyles, 0, false);
11895
+ $timeout(updateHeightFromContent, 0, false);
11577
11896
  }
11578
11897
 
11579
11898
  function getElements () {
11580
- var elements = {};
11581
- elements.canvas = $element[0].getElementsByTagName('md-tabs-canvas')[0];
11582
- elements.wrapper = elements.canvas.getElementsByTagName('md-pagination-wrapper')[0];
11583
- elements.tabs = elements.wrapper.getElementsByTagName('md-tab-item');
11584
- elements.dummies = elements.canvas.getElementsByTagName('md-dummy-tab');
11585
- elements.inkBar = elements.wrapper.getElementsByTagName('md-ink-bar')[0];
11899
+ var elements = {};
11900
+
11901
+ //-- gather tab bar elements
11902
+ elements.wrapper = $element[0].getElementsByTagName('md-tabs-wrapper')[0];
11903
+ elements.canvas = elements.wrapper.getElementsByTagName('md-tabs-canvas')[0];
11904
+ elements.paging = elements.canvas.getElementsByTagName('md-pagination-wrapper')[0];
11905
+ elements.tabs = elements.paging.getElementsByTagName('md-tab-item');
11906
+ elements.dummies = elements.canvas.getElementsByTagName('md-dummy-tab');
11907
+ elements.inkBar = elements.paging.getElementsByTagName('md-ink-bar')[0];
11908
+
11909
+ //-- gather tab content elements
11910
+ elements.contentsWrapper = $element[0].getElementsByTagName('md-tabs-content-wrapper')[0];
11911
+ elements.contents = elements.contentsWrapper.getElementsByTagName('md-tab-content');
11912
+
11586
11913
  return elements;
11587
11914
  }
11588
11915
 
@@ -11618,7 +11945,8 @@ angular.module('material.components.whiteframe', []);
11618
11945
  }
11619
11946
 
11620
11947
  function handleOffsetChange (left) {
11621
- angular.element(elements.wrapper).css('left', '-' + left + 'px');
11948
+ var newValue = shouldCenterTabs() ? '' : '-' + left + 'px';
11949
+ angular.element(elements.paging).css('left', newValue);
11622
11950
  $scope.$broadcast('$mdTabsPaginationChanged');
11623
11951
  }
11624
11952
 
@@ -11634,6 +11962,7 @@ angular.module('material.components.whiteframe', []);
11634
11962
  }
11635
11963
 
11636
11964
  function adjustOffset () {
11965
+ if (shouldCenterTabs()) return;
11637
11966
  var tab = elements.tabs[ctrl.focusIndex],
11638
11967
  left = tab.offsetLeft,
11639
11968
  right = tab.offsetWidth + left;
@@ -11643,6 +11972,7 @@ angular.module('material.components.whiteframe', []);
11643
11972
 
11644
11973
  function handleWindowResize () {
11645
11974
  ctrl.lastSelectedIndex = $scope.selectedIndex;
11975
+ updateHeightFromContent();
11646
11976
  updateInkBarStyles();
11647
11977
  ctrl.offsetLeft = fixOffset(ctrl.offsetLeft);
11648
11978
  }
@@ -11657,7 +11987,7 @@ angular.module('material.components.whiteframe', []);
11657
11987
  id: $mdUtil.nextUid()
11658
11988
  },
11659
11989
  tab = angular.extend(proto, tabData);
11660
- if (!angular.isString(tabData.template)) {
11990
+ if (!tabData.template) {
11661
11991
  ctrl.hasContent = false;
11662
11992
  $element.addClass('md-no-tab-content');
11663
11993
  }
@@ -11688,6 +12018,7 @@ angular.module('material.components.whiteframe', []);
11688
12018
  $scope.selectedIndex = getNearestSafeIndex(newValue);
11689
12019
  ctrl.lastSelectedIndex = oldValue;
11690
12020
  updateInkBarStyles();
12021
+ updateHeightFromContent();
11691
12022
  $scope.$broadcast('$mdTabsChanged');
11692
12023
  }
11693
12024
 
@@ -11712,19 +12043,27 @@ angular.module('material.components.whiteframe', []);
11712
12043
  });
11713
12044
  }
11714
12045
 
12046
+ function updateHeightFromContent () {
12047
+ if (!$scope.dynamicHeight) return $element.css('height', '');
12048
+ var tabContent = elements.contents[$scope.selectedIndex],
12049
+ contentHeight = tabContent.offsetHeight,
12050
+ tabsHeight = elements.wrapper.offsetHeight,
12051
+ newHeight = contentHeight + tabsHeight;
12052
+ $element.css('height', newHeight + 'px');
12053
+ }
12054
+
11715
12055
  function updateInkBarStyles () {
11716
12056
  if (!ctrl.tabs.length) return;
11717
12057
  //-- if the element is not visible, we will not be able to calculate sizes until it is
11718
12058
  //-- we should treat that as a resize event rather than just updating the ink bar
11719
12059
  if (!$element.prop('offsetParent')) return handleResizeWhenVisible();
11720
12060
  var index = $scope.selectedIndex,
11721
- totalWidth = elements.wrapper.offsetWidth,
12061
+ totalWidth = elements.paging.offsetWidth,
11722
12062
  tab = elements.tabs[index],
11723
12063
  left = tab.offsetLeft,
11724
12064
  right = totalWidth - left - tab.offsetWidth;
11725
12065
  updateInkBarClassName();
11726
12066
  angular.element(elements.inkBar).css({ left: left + 'px', right: right + 'px' });
11727
-
11728
12067
  }
11729
12068
 
11730
12069
  function updateInkBarClassName () {
@@ -11760,7 +12099,12 @@ angular.module('material.components.whiteframe', []);
11760
12099
  }
11761
12100
  }
11762
12101
 
12102
+ function shouldCenterTabs () {
12103
+ return $scope.centerTabs && !shouldPaginate();
12104
+ }
12105
+
11763
12106
  function shouldPaginate () {
12107
+ if ($scope.noPagination) return false;
11764
12108
  var canvasWidth = $element.prop('clientWidth');
11765
12109
  angular.forEach(elements.tabs, function (tab) { canvasWidth -= tab.offsetWidth; });
11766
12110
  return canvasWidth < 0;
@@ -11885,6 +12229,9 @@ angular.module('material.components.whiteframe', []);
11885
12229
  * @param {boolean=} md-no-bar If present, disables the selection ink bar.
11886
12230
  * @param {string=} md-align-tabs Attribute to indicate position of tab buttons: `bottom` or `top`; default is `top`
11887
12231
  * @param {string=} md-stretch-tabs Attribute to indicate whether or not to stretch tabs: `auto`, `always`, or `never`; default is `auto`
12232
+ * @param {boolean=} md-dynamic-height When enabled, the tab wrapper will resize based on the contents of the selected tab
12233
+ * @param {boolean=} md-center-tabs When enabled, tabs will be centered provided there is no need for pagination
12234
+ * @param {boolean=} md-no-pagination When enabled, pagination will remain off
11888
12235
  *
11889
12236
  * @usage
11890
12237
  * <hljs lang="html">
@@ -11918,6 +12265,9 @@ angular.module('material.components.whiteframe', []);
11918
12265
  function MdTabs ($mdTheming) {
11919
12266
  return {
11920
12267
  scope: {
12268
+ noPagination: '=?mdNoPagination',
12269
+ dynamicHeight: '=?mdDynamicHeight',
12270
+ centerTabs: '=?mdCenterTabs',
11921
12271
  selectedIndex: '=?mdSelected',
11922
12272
  stretchTabs: '@?mdStretchTabs'
11923
12273
  },
@@ -11953,6 +12303,7 @@ angular.module('material.components.whiteframe', []);
11953
12303
  ng-keydown="$mdTabsCtrl.keydown($event)"\
11954
12304
  role="tablist">\
11955
12305
  <md-pagination-wrapper\
12306
+ ng-class="{ \'md-center-tabs\': $mdTabsCtrl.shouldCenterTabs() }"\
11956
12307
  md-tab-scroll="$mdTabsCtrl.scroll($event)">\
11957
12308
  <md-tab-item\
11958
12309
  tabindex="-1"\
@@ -11988,26 +12339,33 @@ angular.module('material.components.whiteframe', []);
11988
12339
  </div>\
11989
12340
  </md-tabs-canvas>\
11990
12341
  </md-tabs-wrapper>\
11991
- <md-tabs-content-wrapper ng-if="$mdTabsCtrl.hasContent">\
12342
+ <md-tabs-content-wrapper ng-show="$mdTabsCtrl.hasContent">\
11992
12343
  <md-tab-content\
11993
- ng-repeat="(index, tab) in $mdTabsCtrl.tabs" \
11994
- md-tab-data="tab"\
11995
12344
  id="tab-content-{{tab.id}}"\
11996
- aria-labelledby="tab-item-{{tab.id}}"\
11997
12345
  role="tabpanel"\
12346
+ aria-labelledby="tab-item-{{tab.id}}"\
12347
+ md-tab-data="tab"\
11998
12348
  md-swipe-left="$mdTabsCtrl.incrementSelectedIndex(1)"\
11999
12349
  md-swipe-right="$mdTabsCtrl.incrementSelectedIndex(-1)"\
12350
+ ng-if="$mdTabsCtrl.hasContent"\
12351
+ ng-repeat="(index, tab) in $mdTabsCtrl.tabs" \
12000
12352
  ng-class="{\
12001
12353
  \'md-no-transition\': $mdTabsCtrl.lastSelectedIndex == null,\
12002
12354
  \'md-active\': tab.isActive(),\
12003
12355
  \'md-left\': tab.isLeft(),\
12004
- \'md-right\': tab.isRight()\
12356
+ \'md-right\': tab.isRight(),\
12357
+ \'md-no-scroll\': dynamicHeight\
12005
12358
  }"></md-tab-content>\
12006
12359
  </md-tabs-content-wrapper>\
12007
12360
  ',
12008
12361
  controller: 'MdTabsController',
12009
12362
  controllerAs: '$mdTabsCtrl',
12010
12363
  link: function (scope, element, attr) {
12364
+ angular.forEach(scope.$$isolateBindings, function (binding, key) {
12365
+ if (binding.optional && angular.isUndefined(scope[key])) {
12366
+ scope[key] = attr.hasOwnProperty(attr.$normalize(binding.attrName));
12367
+ }
12368
+ });
12011
12369
  //-- watch attributes
12012
12370
  attr.$observe('mdNoBar', function (value) { scope.noInkBar = angular.isDefined(value); });
12013
12371
  //-- set default value for selectedIndex
@@ -12020,5 +12378,5 @@ angular.module('material.components.whiteframe', []);
12020
12378
  MdTabs.$inject = ["$mdTheming"];
12021
12379
  })();
12022
12380
  (function(){
12023
- angular.module("material.core").constant("$MD_THEME_CSS", "md-autocomplete { background: '{{background-50}}'; } md-autocomplete button md-icon path { fill: '{{background-600}}'; } md-autocomplete button:after { background: '{{background-600-0.3}}'; } md-autocomplete ul { background: '{{background-50}}'; } md-autocomplete ul li { border-top: 1px solid '{{background-400}}'; color: '{{background-900}}'; } md-autocomplete ul li .highlight { color: '{{background-600}}'; } md-autocomplete ul li:hover, md-autocomplete ul li.selected { background: '{{background-200}}'; }md-backdrop.md-opaque.md-THEME_NAME-theme { background-color: '{{foreground-4-0.5}}'; }md-bottom-sheet.md-THEME_NAME-theme { background-color: '{{background-50}}'; border-top-color: '{{background-300}}'; } md-bottom-sheet.md-THEME_NAME-theme.md-list md-item { color: '{{foreground-1}}'; } md-bottom-sheet.md-THEME_NAME-theme .md-subheader { background-color: '{{background-50}}'; } md-bottom-sheet.md-THEME_NAME-theme .md-subheader { color: '{{foreground-1}}'; }.md-button.md-THEME_NAME-theme { border-radius: 3px; } .md-button.md-THEME_NAME-theme:not([disabled]):focus { background-color: '{{background-500-0.2}}'; } .md-button.md-THEME_NAME-theme.md-fab { border-radius: 50%; background-color: '{{accent-color}}'; color: '{{accent-contrast}}'; } .md-button.md-THEME_NAME-theme.md-fab:not([disabled]):focus { background-color: '{{accent-A700}}'; } .md-button.md-THEME_NAME-theme.md-primary { color: '{{primary-color}}'; } .md-button.md-THEME_NAME-theme.md-primary.md-raised, .md-button.md-THEME_NAME-theme.md-primary.md-fab { color: '{{primary-contrast}}'; background-color: '{{primary-color}}'; } .md-button.md-THEME_NAME-theme.md-primary.md-raised:not([disabled]):focus, .md-button.md-THEME_NAME-theme.md-primary.md-fab:not([disabled]):focus { background-color: '{{primary-600}}'; } .md-button.md-THEME_NAME-theme.md-raised { color: '{{background-contrast}}'; background-color: '{{background-50}}'; } .md-button.md-THEME_NAME-theme.md-raised:not([disabled]):focus { background-color: '{{background-200}}'; } .md-button.md-THEME_NAME-theme.md-warn { color: '{{warn-color}}'; } .md-button.md-THEME_NAME-theme.md-warn.md-raised, .md-button.md-THEME_NAME-theme.md-warn.md-fab { color: '{{warn-contrast}}'; background-color: '{{warn-color}}'; } .md-button.md-THEME_NAME-theme.md-warn.md-raised:not([disabled]):focus, .md-button.md-THEME_NAME-theme.md-warn.md-fab:not([disabled]):focus { background-color: '{{warn-700}}'; } .md-button.md-THEME_NAME-theme.md-accent { color: '{{accent-color}}'; } .md-button.md-THEME_NAME-theme.md-accent.md-raised, .md-button.md-THEME_NAME-theme.md-accent.md-fab { color: '{{accent-contrast}}'; background-color: '{{accent-color}}'; } .md-button.md-THEME_NAME-theme.md-accent.md-raised:not([disabled]):focus, .md-button.md-THEME_NAME-theme.md-accent.md-fab:not([disabled]):focus { background-color: '{{accent-700}}'; } .md-button.md-THEME_NAME-theme[disabled], .md-button.md-THEME_NAME-theme.md-raised[disabled], .md-button.md-THEME_NAME-theme.md-fab[disabled] { color: '{{foreground-2}}'; cursor: not-allowed; } .md-button.md-THEME_NAME-theme.md-raised[disabled], .md-button.md-THEME_NAME-theme.md-fab[disabled] { background-color: '{{foreground-4}}'; } .md-button.md-THEME_NAME-theme[disabled] { background-color: 'transparent'; }md-card.md-THEME_NAME-theme { border-radius: 2px; } md-card.md-THEME_NAME-theme .md-card-image { border-radius: 2px 2px 0 0; }md-checkbox.md-THEME_NAME-theme .md-ripple { color: '{{accent-600}}'; }md-checkbox.md-THEME_NAME-theme.md-checked .md-ripple { color: '{{background-600}}'; }md-checkbox.md-THEME_NAME-theme .md-icon { border-color: '{{foreground-2}}'; }md-checkbox.md-THEME_NAME-theme.md-checked .md-icon { background-color: '{{accent-color-0.87}}'; }md-checkbox.md-THEME_NAME-theme.md-checked .md-icon:after { border-color: '{{background-200}}'; }md-checkbox.md-THEME_NAME-theme:not([disabled]).md-primary .md-ripple { color: '{{primary-600}}'; }md-checkbox.md-THEME_NAME-theme:not([disabled]).md-primary.md-checked .md-ripple { color: '{{background-600}}'; }md-checkbox.md-THEME_NAME-theme:not([disabled]).md-primary .md-icon { border-color: '{{foreground-2}}'; }md-checkbox.md-THEME_NAME-theme:not([disabled]).md-primary.md-checked .md-icon { background-color: '{{primary-color-0.87}}'; }md-checkbox.md-THEME_NAME-theme:not([disabled]).md-primary.md-checked .md-icon:after { border-color: '{{background-200}}'; }md-checkbox.md-THEME_NAME-theme:not([disabled]).md-warn .md-ripple { color: '{{warn-600}}'; }md-checkbox.md-THEME_NAME-theme:not([disabled]).md-warn .md-icon { border-color: '{{foreground-2}}'; }md-checkbox.md-THEME_NAME-theme:not([disabled]).md-warn.md-checked .md-icon { background-color: '{{warn-color-0.87}}'; }md-checkbox.md-THEME_NAME-theme:not([disabled]).md-warn.md-checked .md-icon:after { border-color: '{{background-200}}'; }md-checkbox.md-THEME_NAME-theme[disabled] .md-icon { border-color: '{{foreground-3}}'; }md-checkbox.md-THEME_NAME-theme[disabled].md-checked .md-icon { background-color: '{{foreground-3}}'; }md-chips.md-THEME_NAME-theme .md-chip { color: '{{background-contrast}}'; background-color: '{{background-100}}'; }md-content.md-THEME_NAME-theme { background-color: '{{background-hue-3}}'; }md-dialog.md-THEME_NAME-theme { border-radius: 4px; background-color: '{{background-hue-3}}'; } md-dialog.md-THEME_NAME-theme.md-content-overflow .md-actions { border-top-color: '{{foreground-4}}'; }md-divider.md-THEME_NAME-theme { border-top-color: '{{foreground-4}}'; }md-icon.md-THEME_NAME-theme.md-primary { color: '{{primary-color}}'; }md-icon.md-THEME_NAME-theme.md-accent { color: '{{accent-color}}'; }md-icon.md-THEME_NAME-theme.md-warn { color: '{{warn-color}}'; }md-icon.md-THEME_NAME-theme.md-danger { color: '{{danger-color}}'; }md-input-container.md-THEME_NAME-theme .md-input { color: '{{foreground-1}}'; border-color: '{{foreground-4}}'; text-shadow: '{{foreground-shadow}}'; } md-input-container.md-THEME_NAME-theme .md-input::-webkit-input-placeholder, md-input-container.md-THEME_NAME-theme .md-input::-moz-placeholder, md-input-container.md-THEME_NAME-theme .md-input:-moz-placeholder, md-input-container.md-THEME_NAME-theme .md-input:-ms-input-placeholder { color: '{{foreground-3}}'; }md-input-container.md-THEME_NAME-theme > md-icon { color: '{{foreground-1}}'; }md-input-container.md-THEME_NAME-theme label, md-input-container.md-THEME_NAME-theme .md-placeholder { text-shadow: '{{foreground-shadow}}'; color: '{{foreground-3}}'; }md-input-container.md-THEME_NAME-theme div[ng-messages] { color: '{{warn-500}}'; }md-input-container.md-THEME_NAME-theme:not(.md-input-invalid).md-input-has-value label { color: '{{foreground-2}}'; }md-input-container.md-THEME_NAME-theme:not(.md-input-invalid).md-input-focused .md-input { border-color: '{{primary-500}}'; }md-input-container.md-THEME_NAME-theme:not(.md-input-invalid).md-input-focused label { color: '{{primary-500}}'; }md-input-container.md-THEME_NAME-theme:not(.md-input-invalid).md-input-focused md-icon { color: '{{primary-500}}'; }md-input-container.md-THEME_NAME-theme:not(.md-input-invalid).md-input-focused.md-accent .md-input { border-color: '{{accent-500}}'; }md-input-container.md-THEME_NAME-theme:not(.md-input-invalid).md-input-focused.md-accent label { color: '{{accent-500}}'; }md-input-container.md-THEME_NAME-theme:not(.md-input-invalid).md-input-focused.md-warn .md-input { border-color: '{{warn-500}}'; }md-input-container.md-THEME_NAME-theme:not(.md-input-invalid).md-input-focused.md-warn label { color: '{{warn-500}}'; }md-input-container.md-THEME_NAME-theme.md-input-invalid .md-input { border-color: '{{warn-500}}'; }md-input-container.md-THEME_NAME-theme.md-input-invalid label { color: '{{warn-500}}'; }md-input-container.md-THEME_NAME-theme.md-input-invalid ng-message, md-input-container.md-THEME_NAME-theme.md-input-invalid data-ng-message, md-input-container.md-THEME_NAME-theme.md-input-invalid x-ng-message, md-input-container.md-THEME_NAME-theme.md-input-invalid [ng-message], md-input-container.md-THEME_NAME-theme.md-input-invalid [data-ng-message], md-input-container.md-THEME_NAME-theme.md-input-invalid [x-ng-message], md-input-container.md-THEME_NAME-theme.md-input-invalid .md-char-counter { color: '{{warn-500}}'; }md-input-container.md-THEME_NAME-theme .md-input[disabled], [disabled] md-input-container.md-THEME_NAME-theme .md-input { border-bottom-color: transparent; color: '{{foreground-3}}'; background-image: linear-gradient(to right, '{{foreground-4}}' 0%, '{{foreground-4}}' 33%, transparent 0%); background-image: -ms-linear-gradient(left, transparent 0%, '{{foreground-4}}' 100%); }md-progress-circular.md-THEME_NAME-theme { background-color: transparent; } md-progress-circular.md-THEME_NAME-theme .md-inner .md-gap { border-top-color: '{{primary-color}}'; border-bottom-color: '{{primary-color}}'; } md-progress-circular.md-THEME_NAME-theme .md-inner .md-left .md-half-circle, md-progress-circular.md-THEME_NAME-theme .md-inner .md-right .md-half-circle { border-top-color: '{{primary-color}}'; } md-progress-circular.md-THEME_NAME-theme .md-inner .md-right .md-half-circle { border-right-color: '{{primary-color}}'; } md-progress-circular.md-THEME_NAME-theme .md-inner .md-left .md-half-circle { border-left-color: '{{primary-color}}'; } md-progress-circular.md-THEME_NAME-theme.md-warn .md-inner .md-gap { border-top-color: '{{warn-color}}'; border-bottom-color: '{{warn-color}}'; } md-progress-circular.md-THEME_NAME-theme.md-warn .md-inner .md-left .md-half-circle, md-progress-circular.md-THEME_NAME-theme.md-warn .md-inner .md-right .md-half-circle { border-top-color: '{{warn-color}}'; } md-progress-circular.md-THEME_NAME-theme.md-warn .md-inner .md-right .md-half-circle { border-right-color: '{{warn-color}}'; } md-progress-circular.md-THEME_NAME-theme.md-warn .md-inner .md-left .md-half-circle { border-left-color: '{{warn-color}}'; } md-progress-circular.md-THEME_NAME-theme.md-accent .md-inner .md-gap { border-top-color: '{{accent-color}}'; border-bottom-color: '{{accent-color}}'; } md-progress-circular.md-THEME_NAME-theme.md-accent .md-inner .md-left .md-half-circle, md-progress-circular.md-THEME_NAME-theme.md-accent .md-inner .md-right .md-half-circle { border-top-color: '{{accent-color}}'; } md-progress-circular.md-THEME_NAME-theme.md-accent .md-inner .md-right .md-half-circle { border-right-color: '{{accent-color}}'; } md-progress-circular.md-THEME_NAME-theme.md-accent .md-inner .md-left .md-half-circle { border-left-color: '{{accent-color}}'; }md-progress-linear.md-THEME_NAME-theme .md-container { background-color: '{{primary-100}}'; }md-progress-linear.md-THEME_NAME-theme .md-bar { background-color: '{{primary-color}}'; }md-progress-linear.md-THEME_NAME-theme.md-warn .md-container { background-color: '{{warn-100}}'; }md-progress-linear.md-THEME_NAME-theme.md-warn .md-bar { background-color: '{{warn-color}}'; }md-progress-linear.md-THEME_NAME-theme.md-accent .md-container { background-color: '{{accent-100}}'; }md-progress-linear.md-THEME_NAME-theme.md-accent .md-bar { background-color: '{{accent-color}}'; }md-progress-linear.md-THEME_NAME-theme[md-mode=buffer].md-warn .md-bar1 { background-color: '{{warn-100}}'; }md-progress-linear.md-THEME_NAME-theme[md-mode=buffer].md-warn .md-dashed:before { background: radial-gradient('{{warn-100}}' 0%, '{{warn-100}}' 16%, transparent 42%); }md-progress-linear.md-THEME_NAME-theme[md-mode=buffer].md-accent .md-bar1 { background-color: '{{accent-100}}'; }md-progress-linear.md-THEME_NAME-theme[md-mode=buffer].md-accent .md-dashed:before { background: radial-gradient('{{accent-100}}' 0%, '{{accent-100}}' 16%, transparent 42%); }md-radio-button.md-THEME_NAME-theme .md-off { border-color: '{{foreground-2}}'; }md-radio-button.md-THEME_NAME-theme .md-on { background-color: '{{accent-color-0.87}}'; }md-radio-button.md-THEME_NAME-theme.md-checked .md-off { border-color: '{{accent-color-0.87}}'; }md-radio-button.md-THEME_NAME-theme.md-checked .md-ink-ripple { color: '{{accent-color-0.87}}'; }md-radio-button.md-THEME_NAME-theme .md-container .md-ripple { color: '{{accent-600}}'; }md-radio-button.md-THEME_NAME-theme:not([disabled]).md-primary .md-on { background-color: '{{primary-color-0.87}}'; }md-radio-button.md-THEME_NAME-theme:not([disabled]).md-primary.md-checked .md-off { border-color: '{{primary-color-0.87}}'; }md-radio-button.md-THEME_NAME-theme:not([disabled]).md-primary.md-checked .md-ink-ripple { color: '{{primary-color-0.87}}'; }md-radio-button.md-THEME_NAME-theme:not([disabled]).md-primary .md-container .md-ripple { color: '{{primary-600}}'; }md-radio-button.md-THEME_NAME-theme:not([disabled]).md-warn .md-on { background-color: '{{warn-color-0.87}}'; }md-radio-button.md-THEME_NAME-theme:not([disabled]).md-warn.md-checked .md-off { border-color: '{{warn-color-0.87}}'; }md-radio-button.md-THEME_NAME-theme:not([disabled]).md-warn.md-checked .md-ink-ripple { color: '{{warn-color-0.87}}'; }md-radio-button.md-THEME_NAME-theme:not([disabled]).md-warn .md-container .md-ripple { color: '{{warn-600}}'; }md-radio-button.md-THEME_NAME-theme[disabled] .md-container .md-off { border-color: '{{foreground-3}}'; }md-radio-button.md-THEME_NAME-theme[disabled] .md-container .md-on { border-color: '{{foreground-3}}'; }md-radio-group.md-THEME_NAME-theme:focus:not(:empty) { border-color: '{{foreground-1}}'; }md-select.md-THEME_NAME-theme.ng-invalid.ng-dirty .md-select-label { color: '{{warn-500}}' !important; border-bottom-color: '{{warn-500}}' !important; }md-select.md-THEME_NAME-theme:not([disabled]):focus .md-select-label { border-bottom-color: '{{primary-color}}'; color: '{{ foreground-1 }}'; } md-select.md-THEME_NAME-theme:not([disabled]):focus .md-select-label.md-placeholder { color: '{{ foreground-1 }}'; }md-select.md-THEME_NAME-theme:not([disabled]):focus.md-accent .md-select-label { border-bottom-color: '{{accent-color}}'; }md-select.md-THEME_NAME-theme:not([disabled]):focus.md-warn .md-select-label { border-bottom-color: '{{warn-color}}'; }md-select.md-THEME_NAME-theme[disabled] .md-select-label { color: '{{foreground-3}}'; } md-select.md-THEME_NAME-theme[disabled] .md-select-label.md-placeholder { color: '{{foreground-3}}'; }md-select.md-THEME_NAME-theme .md-select-label { border-bottom-color: '{{foreground-4}}'; } md-select.md-THEME_NAME-theme .md-select-label.md-placeholder { color: '{{foreground-2}}'; }md-select-menu.md-THEME_NAME-theme md-optgroup { color: '{{foreground-2}}'; } md-select-menu.md-THEME_NAME-theme md-optgroup md-option { color: '{{foreground-1}}'; }md-select-menu.md-THEME_NAME-theme md-option[selected] { background-color: '{{primary-50}}'; } md-select-menu.md-THEME_NAME-theme md-option[selected]:focus { background-color: '{{primary-100}}'; } md-select-menu.md-THEME_NAME-theme md-option[selected].md-accent { background-color: '{{accent-50}}'; } md-select-menu.md-THEME_NAME-theme md-option[selected].md-accent:focus { background-color: '{{accent-100}}'; }md-select-menu.md-THEME_NAME-theme md-option:focus:not([selected]) { background: '{{background-200}}'; }md-sidenav.md-THEME_NAME-theme { background-color: '{{background-hue-3}}'; }md-slider.md-THEME_NAME-theme .md-track { background-color: '{{foreground-3}}'; }md-slider.md-THEME_NAME-theme .md-track-ticks { background-color: '{{foreground-4}}'; }md-slider.md-THEME_NAME-theme .md-focus-thumb { background-color: '{{foreground-2}}'; }md-slider.md-THEME_NAME-theme .md-focus-ring { border-color: '{{foreground-4}}'; }md-slider.md-THEME_NAME-theme .md-disabled-thumb { border-color: '{{background-hue-3}}'; }md-slider.md-THEME_NAME-theme.md-min .md-thumb:after { background-color: '{{background-hue-3}}'; }md-slider.md-THEME_NAME-theme .md-track.md-track-fill { background-color: '{{accent-color}}'; }md-slider.md-THEME_NAME-theme .md-thumb:after { border-color: '{{accent-color}}'; background-color: '{{accent-color}}'; }md-slider.md-THEME_NAME-theme .md-sign { background-color: '{{accent-color}}'; } md-slider.md-THEME_NAME-theme .md-sign:after { border-top-color: '{{accent-color}}'; }md-slider.md-THEME_NAME-theme .md-thumb-text { color: '{{accent-contrast}}'; }md-slider.md-THEME_NAME-theme.md-warn .md-track.md-track-fill { background-color: '{{warn-color}}'; }md-slider.md-THEME_NAME-theme.md-warn .md-thumb:after { border-color: '{{warn-color}}'; background-color: '{{warn-color}}'; }md-slider.md-THEME_NAME-theme.md-warn .md-sign { background-color: '{{warn-color}}'; } md-slider.md-THEME_NAME-theme.md-warn .md-sign:after { border-top-color: '{{warn-color}}'; }md-slider.md-THEME_NAME-theme.md-warn .md-thumb-text { color: '{{warn-contrast}}'; }md-slider.md-THEME_NAME-theme.md-primary .md-track.md-track-fill { background-color: '{{primary-color}}'; }md-slider.md-THEME_NAME-theme.md-primary .md-thumb:after { border-color: '{{primary-color}}'; background-color: '{{primary-color}}'; }md-slider.md-THEME_NAME-theme.md-primary .md-sign { background-color: '{{primary-color}}'; } md-slider.md-THEME_NAME-theme.md-primary .md-sign:after { border-top-color: '{{primary-color}}'; }md-slider.md-THEME_NAME-theme.md-primary .md-thumb-text { color: '{{primary-contrast}}'; }md-slider.md-THEME_NAME-theme[disabled] .md-thumb:after { border-color: '{{foreground-3}}'; }md-slider.md-THEME_NAME-theme[disabled]:not(.md-min) .md-thumb:after { background-color: '{{foreground-3}}'; }.md-subheader.md-THEME_NAME-theme { color: '{{ foreground-2-0.23 }}'; background-color: '{{background-hue-3}}'; } .md-subheader.md-THEME_NAME-theme.md-primary { color: '{{primary-color}}'; } .md-subheader.md-THEME_NAME-theme.md-accent { color: '{{accent-color}}'; } .md-subheader.md-THEME_NAME-theme.md-warn { color: '{{warn-color}}'; }md-switch.md-THEME_NAME-theme .md-thumb { background-color: '{{background-50}}'; }md-switch.md-THEME_NAME-theme .md-bar { background-color: '{{background-500}}'; }md-switch.md-THEME_NAME-theme.md-checked .md-thumb { background-color: '{{accent-color}}'; }md-switch.md-THEME_NAME-theme.md-checked .md-bar { background-color: '{{accent-color-0.5}}'; }md-switch.md-THEME_NAME-theme.md-checked.md-primary .md-thumb { background-color: '{{primary-color}}'; }md-switch.md-THEME_NAME-theme.md-checked.md-primary .md-bar { background-color: '{{primary-color-0.5}}'; }md-switch.md-THEME_NAME-theme.md-checked.md-warn .md-thumb { background-color: '{{warn-color}}'; }md-switch.md-THEME_NAME-theme.md-checked.md-warn .md-bar { background-color: '{{warn-color-0.5}}'; }md-switch.md-THEME_NAME-theme[disabled] .md-thumb { background-color: '{{background-400}}'; }md-switch.md-THEME_NAME-theme[disabled] .md-bar { background-color: '{{foreground-4}}'; }md-switch.md-THEME_NAME-theme:focus .md-label:not(:empty) { border-color: '{{foreground-1}}'; border-style: dotted; }md-tabs.md-THEME_NAME-theme md-tabs-wrapper { background-color: transparent; border-color: '{{foreground-4}}'; }md-tabs.md-THEME_NAME-theme .md-paginator md-icon { color: '{{primary-color}}'; }md-tabs.md-THEME_NAME-theme md-ink-bar { color: '{{accent-color}}'; background: '{{accent-color}}'; }md-tabs.md-THEME_NAME-theme .md-tab { color: '{{foreground-2}}'; } md-tabs.md-THEME_NAME-theme .md-tab[disabled] { color: '{{foreground-3}}'; } md-tabs.md-THEME_NAME-theme .md-tab.md-active, md-tabs.md-THEME_NAME-theme .md-tab.md-focus { color: '{{primary-color}}'; } md-tabs.md-THEME_NAME-theme .md-tab.md-focus { background: '{{primary-color-0.1}}'; } md-tabs.md-THEME_NAME-theme .md-tab .md-ripple-container { color: '{{accent-100}}'; }md-tabs.md-THEME_NAME-theme.md-accent md-tabs-wrapper { background-color: '{{accent-color}}'; }md-tabs.md-THEME_NAME-theme.md-accent md-tab:not([disabled]) { color: '{{accent-100}}'; } md-tabs.md-THEME_NAME-theme.md-accent md-tab:not([disabled]).md-active, md-tabs.md-THEME_NAME-theme.md-accent md-tab:not([disabled]).md-focus { color: '{{accent-contrast}}'; } md-tabs.md-THEME_NAME-theme.md-accent md-tab:not([disabled]).md-focus { background: '{{accent-contrast-0.1}}'; }md-tabs.md-THEME_NAME-theme.md-accent md-ink-bar { color: '{{primary-600-1}}'; background: '{{primary-600-1}}'; }md-tabs.md-THEME_NAME-theme.md-primary md-tabs-wrapper { background-color: '{{primary-color}}'; }md-tabs.md-THEME_NAME-theme.md-primary md-tab:not([disabled]) { color: '{{primary-100}}'; } md-tabs.md-THEME_NAME-theme.md-primary md-tab:not([disabled]).md-active, md-tabs.md-THEME_NAME-theme.md-primary md-tab:not([disabled]).md-focus { color: '{{primary-contrast}}'; } md-tabs.md-THEME_NAME-theme.md-primary md-tab:not([disabled]).md-focus { background: '{{primary-contrast-0.1}}'; }md-tabs.md-THEME_NAME-theme.md-warn md-tabs-wrapper { background-color: '{{warn-color}}'; }md-tabs.md-THEME_NAME-theme.md-warn md-tab:not([disabled]) { color: '{{warn-100}}'; } md-tabs.md-THEME_NAME-theme.md-warn md-tab:not([disabled]).md-active, md-tabs.md-THEME_NAME-theme.md-warn md-tab:not([disabled]).md-focus { color: '{{warn-contrast}}'; } md-tabs.md-THEME_NAME-theme.md-warn md-tab:not([disabled]).md-focus { background: '{{warn-contrast-0.1}}'; }md-input-group.md-THEME_NAME-theme input, md-input-group.md-THEME_NAME-theme textarea { text-shadow: '{{foreground-shadow}}'; } md-input-group.md-THEME_NAME-theme input::-webkit-input-placeholder, md-input-group.md-THEME_NAME-theme input::-moz-placeholder, md-input-group.md-THEME_NAME-theme input:-moz-placeholder, md-input-group.md-THEME_NAME-theme input:-ms-input-placeholder, md-input-group.md-THEME_NAME-theme textarea::-webkit-input-placeholder, md-input-group.md-THEME_NAME-theme textarea::-moz-placeholder, md-input-group.md-THEME_NAME-theme textarea:-moz-placeholder, md-input-group.md-THEME_NAME-theme textarea:-ms-input-placeholder { color: '{{foreground-3}}'; }md-input-group.md-THEME_NAME-theme label { text-shadow: '{{foreground-shadow}}'; color: '{{foreground-3}}'; }md-input-group.md-THEME_NAME-theme input, md-input-group.md-THEME_NAME-theme textarea { color: '{{foreground-1}}'; border-color: '{{foreground-4}}'; }md-input-group.md-THEME_NAME-theme.md-input-focused input, md-input-group.md-THEME_NAME-theme.md-input-focused textarea { border-color: '{{primary-500}}'; }md-input-group.md-THEME_NAME-theme.md-input-focused label { color: '{{primary-500}}'; }md-input-group.md-THEME_NAME-theme.md-input-focused.md-accent input, md-input-group.md-THEME_NAME-theme.md-input-focused.md-accent textarea { border-color: '{{accent-500}}'; }md-input-group.md-THEME_NAME-theme.md-input-focused.md-accent label { color: '{{accent-500}}'; }md-input-group.md-THEME_NAME-theme.md-input-has-value:not(.md-input-focused) label { color: '{{foreground-2}}'; }md-input-group.md-THEME_NAME-theme .md-input[disabled] { border-bottom-color: '{{foreground-4}}'; color: '{{foreground-3}}'; }md-toast.md-THEME_NAME-theme { background-color: '{{foreground-1}}'; color: '{{background-50}}'; } md-toast.md-THEME_NAME-theme .md-button { color: '{{background-50}}'; } md-toast.md-THEME_NAME-theme .md-button.md-highlight { color: '{{primary-A200}}'; } md-toast.md-THEME_NAME-theme .md-button.md-highlight.md-accent { color: '{{accent-A200}}'; } md-toast.md-THEME_NAME-theme .md-button.md-highlight.md-warn { color: '{{warn-A200}}'; }md-toolbar.md-THEME_NAME-theme { background-color: '{{primary-color}}'; color: '{{primary-contrast}}'; } md-toolbar.md-THEME_NAME-theme .md-button { color: '{{primary-contrast}}'; } md-toolbar.md-THEME_NAME-theme.md-accent { background-color: '{{accent-color}}'; color: '{{accent-contrast}}'; } md-toolbar.md-THEME_NAME-theme.md-warn { background-color: '{{warn-color}}'; color: '{{warn-contrast}}'; }md-tooltip.md-THEME_NAME-theme { color: '{{background-A100}}'; } md-tooltip.md-THEME_NAME-theme .md-background { background-color: '{{foreground-2}}'; }");
12381
+ angular.module("material.core").constant("$MD_THEME_CSS", "md-autocomplete { background: '{{background-50}}'; } md-autocomplete button md-icon path { fill: '{{background-600}}'; } md-autocomplete button:after { background: '{{background-600-0.3}}'; } md-autocomplete ul { background: '{{background-50}}'; } md-autocomplete ul li { border-top: 1px solid '{{background-400}}'; color: '{{background-900}}'; } md-autocomplete ul li .highlight { color: '{{background-600}}'; } md-autocomplete ul li:hover, md-autocomplete ul li.selected { background: '{{background-200}}'; }md-backdrop.md-opaque.md-THEME_NAME-theme { background-color: '{{foreground-4-0.5}}'; }md-bottom-sheet.md-THEME_NAME-theme { background-color: '{{background-50}}'; border-top-color: '{{background-300}}'; } md-bottom-sheet.md-THEME_NAME-theme.md-list md-item { color: '{{foreground-1}}'; } md-bottom-sheet.md-THEME_NAME-theme .md-subheader { background-color: '{{background-50}}'; } md-bottom-sheet.md-THEME_NAME-theme .md-subheader { color: '{{foreground-1}}'; }.md-button.md-THEME_NAME-theme { border-radius: 3px; } .md-button.md-THEME_NAME-theme:not([disabled]):focus { background-color: '{{background-500-0.2}}'; } .md-button.md-THEME_NAME-theme.md-fab { border-radius: 50%; background-color: '{{accent-color}}'; color: '{{accent-contrast}}'; } .md-button.md-THEME_NAME-theme.md-fab:not([disabled]):focus { background-color: '{{accent-A700}}'; } .md-button.md-THEME_NAME-theme.md-primary { color: '{{primary-color}}'; } .md-button.md-THEME_NAME-theme.md-primary.md-raised, .md-button.md-THEME_NAME-theme.md-primary.md-fab { color: '{{primary-contrast}}'; background-color: '{{primary-color}}'; } .md-button.md-THEME_NAME-theme.md-primary.md-raised:not([disabled]):focus, .md-button.md-THEME_NAME-theme.md-primary.md-fab:not([disabled]):focus { background-color: '{{primary-600}}'; } .md-button.md-THEME_NAME-theme.md-raised { color: '{{background-contrast}}'; background-color: '{{background-50}}'; } .md-button.md-THEME_NAME-theme.md-raised:not([disabled]):focus { background-color: '{{background-200}}'; } .md-button.md-THEME_NAME-theme.md-warn { color: '{{warn-color}}'; } .md-button.md-THEME_NAME-theme.md-warn.md-raised, .md-button.md-THEME_NAME-theme.md-warn.md-fab { color: '{{warn-contrast}}'; background-color: '{{warn-color}}'; } .md-button.md-THEME_NAME-theme.md-warn.md-raised:not([disabled]):focus, .md-button.md-THEME_NAME-theme.md-warn.md-fab:not([disabled]):focus { background-color: '{{warn-700}}'; } .md-button.md-THEME_NAME-theme.md-accent { color: '{{accent-color}}'; } .md-button.md-THEME_NAME-theme.md-accent.md-raised, .md-button.md-THEME_NAME-theme.md-accent.md-fab { color: '{{accent-contrast}}'; background-color: '{{accent-color}}'; } .md-button.md-THEME_NAME-theme.md-accent.md-raised:not([disabled]):focus, .md-button.md-THEME_NAME-theme.md-accent.md-fab:not([disabled]):focus { background-color: '{{accent-700}}'; } .md-button.md-THEME_NAME-theme[disabled], .md-button.md-THEME_NAME-theme.md-raised[disabled], .md-button.md-THEME_NAME-theme.md-fab[disabled] { color: '{{foreground-2}}'; cursor: not-allowed; } .md-button.md-THEME_NAME-theme.md-raised[disabled], .md-button.md-THEME_NAME-theme.md-fab[disabled] { background-color: '{{foreground-4}}'; } .md-button.md-THEME_NAME-theme[disabled] { background-color: 'transparent'; }md-card.md-THEME_NAME-theme { background-color: '{{background-hue-3}}'; border-radius: 2px; } md-card.md-THEME_NAME-theme .md-card-image { border-radius: 2px 2px 0 0; }md-checkbox.md-THEME_NAME-theme .md-ripple { color: '{{accent-600}}'; }md-checkbox.md-THEME_NAME-theme.md-checked .md-ripple { color: '{{background-600}}'; }md-checkbox.md-THEME_NAME-theme .md-icon { border-color: '{{foreground-2}}'; }md-checkbox.md-THEME_NAME-theme.md-checked .md-icon { background-color: '{{accent-color-0.87}}'; }md-checkbox.md-THEME_NAME-theme.md-checked .md-icon:after { border-color: '{{background-200}}'; }md-checkbox.md-THEME_NAME-theme:not([disabled]).md-primary .md-ripple { color: '{{primary-600}}'; }md-checkbox.md-THEME_NAME-theme:not([disabled]).md-primary.md-checked .md-ripple { color: '{{background-600}}'; }md-checkbox.md-THEME_NAME-theme:not([disabled]).md-primary .md-icon { border-color: '{{foreground-2}}'; }md-checkbox.md-THEME_NAME-theme:not([disabled]).md-primary.md-checked .md-icon { background-color: '{{primary-color-0.87}}'; }md-checkbox.md-THEME_NAME-theme:not([disabled]).md-primary.md-checked .md-icon:after { border-color: '{{background-200}}'; }md-checkbox.md-THEME_NAME-theme:not([disabled]).md-warn .md-ripple { color: '{{warn-600}}'; }md-checkbox.md-THEME_NAME-theme:not([disabled]).md-warn .md-icon { border-color: '{{foreground-2}}'; }md-checkbox.md-THEME_NAME-theme:not([disabled]).md-warn.md-checked .md-icon { background-color: '{{warn-color-0.87}}'; }md-checkbox.md-THEME_NAME-theme:not([disabled]).md-warn.md-checked .md-icon:after { border-color: '{{background-200}}'; }md-checkbox.md-THEME_NAME-theme[disabled] .md-icon { border-color: '{{foreground-3}}'; }md-checkbox.md-THEME_NAME-theme[disabled].md-checked .md-icon { background-color: '{{foreground-3}}'; }md-chips.md-THEME_NAME-theme .md-chip { color: '{{background-contrast-0.6}}'; background-color: '{{background-100}}'; } md-chips.md-THEME_NAME-theme .md-chip .md-button { color: '{{background-contrast}}'; }md-content.md-THEME_NAME-theme { background-color: '{{background-hue-3}}'; }md-dialog.md-THEME_NAME-theme { border-radius: 4px; background-color: '{{background-hue-3}}'; } md-dialog.md-THEME_NAME-theme.md-content-overflow .md-actions { border-top-color: '{{foreground-4}}'; }md-divider.md-THEME_NAME-theme { border-top-color: '{{foreground-4}}'; }md-icon.md-THEME_NAME-theme { color: '{{foreground-2}}'; } md-icon.md-THEME_NAME-theme.md-primary { color: '{{primary-color}}'; } md-icon.md-THEME_NAME-theme.md-accent { color: '{{accent-color}}'; } md-icon.md-THEME_NAME-theme.md-warn { color: '{{warn-color}}'; } md-icon.md-THEME_NAME-theme.md-danger { color: '{{danger-color}}'; }md-input-container.md-THEME_NAME-theme .md-input { color: '{{foreground-1}}'; border-color: '{{foreground-4}}'; text-shadow: '{{foreground-shadow}}'; } md-input-container.md-THEME_NAME-theme .md-input::-webkit-input-placeholder, md-input-container.md-THEME_NAME-theme .md-input::-moz-placeholder, md-input-container.md-THEME_NAME-theme .md-input:-moz-placeholder, md-input-container.md-THEME_NAME-theme .md-input:-ms-input-placeholder { color: '{{foreground-3}}'; }md-input-container.md-THEME_NAME-theme > md-icon { color: '{{foreground-1}}'; }md-input-container.md-THEME_NAME-theme label, md-input-container.md-THEME_NAME-theme .md-placeholder { text-shadow: '{{foreground-shadow}}'; color: '{{foreground-3}}'; }md-input-container.md-THEME_NAME-theme div[ng-messages] { color: '{{warn-500}}'; }md-input-container.md-THEME_NAME-theme:not(.md-input-invalid).md-input-has-value label { color: '{{foreground-2}}'; }md-input-container.md-THEME_NAME-theme:not(.md-input-invalid).md-input-focused .md-input { border-color: '{{primary-500}}'; }md-input-container.md-THEME_NAME-theme:not(.md-input-invalid).md-input-focused label { color: '{{primary-500}}'; }md-input-container.md-THEME_NAME-theme:not(.md-input-invalid).md-input-focused md-icon { color: '{{primary-500}}'; }md-input-container.md-THEME_NAME-theme:not(.md-input-invalid).md-input-focused.md-accent .md-input { border-color: '{{accent-500}}'; }md-input-container.md-THEME_NAME-theme:not(.md-input-invalid).md-input-focused.md-accent label { color: '{{accent-500}}'; }md-input-container.md-THEME_NAME-theme:not(.md-input-invalid).md-input-focused.md-warn .md-input { border-color: '{{warn-500}}'; }md-input-container.md-THEME_NAME-theme:not(.md-input-invalid).md-input-focused.md-warn label { color: '{{warn-500}}'; }md-input-container.md-THEME_NAME-theme.md-input-invalid .md-input { border-color: '{{warn-500}}'; }md-input-container.md-THEME_NAME-theme.md-input-invalid label { color: '{{warn-500}}'; }md-input-container.md-THEME_NAME-theme.md-input-invalid ng-message, md-input-container.md-THEME_NAME-theme.md-input-invalid data-ng-message, md-input-container.md-THEME_NAME-theme.md-input-invalid x-ng-message, md-input-container.md-THEME_NAME-theme.md-input-invalid [ng-message], md-input-container.md-THEME_NAME-theme.md-input-invalid [data-ng-message], md-input-container.md-THEME_NAME-theme.md-input-invalid [x-ng-message], md-input-container.md-THEME_NAME-theme.md-input-invalid .md-char-counter { color: '{{warn-500}}'; }md-input-container.md-THEME_NAME-theme .md-input[disabled], [disabled] md-input-container.md-THEME_NAME-theme .md-input { border-bottom-color: transparent; color: '{{foreground-3}}'; background-image: linear-gradient(to right, '{{foreground-4}}' 0%, '{{foreground-4}}' 33%, transparent 0%); background-image: -ms-linear-gradient(left, transparent 0%, '{{foreground-4}}' 100%); }md-list.md-THEME_NAME-theme md-item.md-double-line .md-item-text h3, md-list.md-THEME_NAME-theme md-item.md-double-line .md-item-text h4, md-list.md-THEME_NAME-theme md-item.md-triple-line .md-item-text h3, md-list.md-THEME_NAME-theme md-item.md-triple-line .md-item-text h4 { color: '{{foreground-1}}'; }md-list.md-THEME_NAME-theme md-item.md-double-line .md-item-text p, md-list.md-THEME_NAME-theme md-item.md-triple-line .md-item-text p { color: '{{foreground-2}}'; }md-list.md-THEME_NAME-theme .md-proxy-focus.md-focused div.md-no-style, md-list.md-THEME_NAME-theme .md-secondary:focus, md-list.md-THEME_NAME-theme .md-no-style:focus { background-color: '{{background-100}}'; }md-list.md-THEME_NAME-theme md-item > md-icon { color: '{{foreground-2}}'; } md-list.md-THEME_NAME-theme md-item > md-icon.md-highlight { color: '{{primary-color}}'; } md-list.md-THEME_NAME-theme md-item > md-icon.md-highlight.md-accent { color: '{{accent-color}}'; }md-progress-circular.md-THEME_NAME-theme { background-color: transparent; } md-progress-circular.md-THEME_NAME-theme .md-inner .md-gap { border-top-color: '{{primary-color}}'; border-bottom-color: '{{primary-color}}'; } md-progress-circular.md-THEME_NAME-theme .md-inner .md-left .md-half-circle, md-progress-circular.md-THEME_NAME-theme .md-inner .md-right .md-half-circle { border-top-color: '{{primary-color}}'; } md-progress-circular.md-THEME_NAME-theme .md-inner .md-right .md-half-circle { border-right-color: '{{primary-color}}'; } md-progress-circular.md-THEME_NAME-theme .md-inner .md-left .md-half-circle { border-left-color: '{{primary-color}}'; } md-progress-circular.md-THEME_NAME-theme.md-warn .md-inner .md-gap { border-top-color: '{{warn-color}}'; border-bottom-color: '{{warn-color}}'; } md-progress-circular.md-THEME_NAME-theme.md-warn .md-inner .md-left .md-half-circle, md-progress-circular.md-THEME_NAME-theme.md-warn .md-inner .md-right .md-half-circle { border-top-color: '{{warn-color}}'; } md-progress-circular.md-THEME_NAME-theme.md-warn .md-inner .md-right .md-half-circle { border-right-color: '{{warn-color}}'; } md-progress-circular.md-THEME_NAME-theme.md-warn .md-inner .md-left .md-half-circle { border-left-color: '{{warn-color}}'; } md-progress-circular.md-THEME_NAME-theme.md-accent .md-inner .md-gap { border-top-color: '{{accent-color}}'; border-bottom-color: '{{accent-color}}'; } md-progress-circular.md-THEME_NAME-theme.md-accent .md-inner .md-left .md-half-circle, md-progress-circular.md-THEME_NAME-theme.md-accent .md-inner .md-right .md-half-circle { border-top-color: '{{accent-color}}'; } md-progress-circular.md-THEME_NAME-theme.md-accent .md-inner .md-right .md-half-circle { border-right-color: '{{accent-color}}'; } md-progress-circular.md-THEME_NAME-theme.md-accent .md-inner .md-left .md-half-circle { border-left-color: '{{accent-color}}'; }md-progress-linear.md-THEME_NAME-theme .md-container { background-color: '{{primary-100}}'; }md-progress-linear.md-THEME_NAME-theme .md-bar { background-color: '{{primary-color}}'; }md-progress-linear.md-THEME_NAME-theme.md-warn .md-container { background-color: '{{warn-100}}'; }md-progress-linear.md-THEME_NAME-theme.md-warn .md-bar { background-color: '{{warn-color}}'; }md-progress-linear.md-THEME_NAME-theme.md-accent .md-container { background-color: '{{accent-100}}'; }md-progress-linear.md-THEME_NAME-theme.md-accent .md-bar { background-color: '{{accent-color}}'; }md-progress-linear.md-THEME_NAME-theme[md-mode=buffer].md-warn .md-bar1 { background-color: '{{warn-100}}'; }md-progress-linear.md-THEME_NAME-theme[md-mode=buffer].md-warn .md-dashed:before { background: radial-gradient('{{warn-100}}' 0%, '{{warn-100}}' 16%, transparent 42%); }md-progress-linear.md-THEME_NAME-theme[md-mode=buffer].md-accent .md-bar1 { background-color: '{{accent-100}}'; }md-progress-linear.md-THEME_NAME-theme[md-mode=buffer].md-accent .md-dashed:before { background: radial-gradient('{{accent-100}}' 0%, '{{accent-100}}' 16%, transparent 42%); }md-radio-button.md-THEME_NAME-theme .md-off { border-color: '{{foreground-2}}'; }md-radio-button.md-THEME_NAME-theme .md-on { background-color: '{{accent-color-0.87}}'; }md-radio-button.md-THEME_NAME-theme.md-checked .md-off { border-color: '{{accent-color-0.87}}'; }md-radio-button.md-THEME_NAME-theme.md-checked .md-ink-ripple { color: '{{accent-color-0.87}}'; }md-radio-button.md-THEME_NAME-theme .md-container .md-ripple { color: '{{accent-600}}'; }md-radio-button.md-THEME_NAME-theme:not([disabled]).md-primary .md-on { background-color: '{{primary-color-0.87}}'; }md-radio-button.md-THEME_NAME-theme:not([disabled]).md-primary.md-checked .md-off { border-color: '{{primary-color-0.87}}'; }md-radio-button.md-THEME_NAME-theme:not([disabled]).md-primary.md-checked .md-ink-ripple { color: '{{primary-color-0.87}}'; }md-radio-button.md-THEME_NAME-theme:not([disabled]).md-primary .md-container .md-ripple { color: '{{primary-600}}'; }md-radio-button.md-THEME_NAME-theme:not([disabled]).md-warn .md-on { background-color: '{{warn-color-0.87}}'; }md-radio-button.md-THEME_NAME-theme:not([disabled]).md-warn.md-checked .md-off { border-color: '{{warn-color-0.87}}'; }md-radio-button.md-THEME_NAME-theme:not([disabled]).md-warn.md-checked .md-ink-ripple { color: '{{warn-color-0.87}}'; }md-radio-button.md-THEME_NAME-theme:not([disabled]).md-warn .md-container .md-ripple { color: '{{warn-600}}'; }md-radio-button.md-THEME_NAME-theme[disabled] .md-container .md-off { border-color: '{{foreground-3}}'; }md-radio-button.md-THEME_NAME-theme[disabled] .md-container .md-on { border-color: '{{foreground-3}}'; }md-radio-group.md-THEME_NAME-theme:focus:not(:empty) { border-color: '{{foreground-1}}'; }md-select.md-THEME_NAME-theme.ng-invalid.ng-dirty .md-select-label { color: '{{warn-500}}' !important; border-bottom-color: '{{warn-500}}' !important; }md-select.md-THEME_NAME-theme:not([disabled]):focus .md-select-label { border-bottom-color: '{{primary-color}}'; color: '{{ foreground-1 }}'; } md-select.md-THEME_NAME-theme:not([disabled]):focus .md-select-label.md-placeholder { color: '{{ foreground-1 }}'; }md-select.md-THEME_NAME-theme:not([disabled]):focus.md-accent .md-select-label { border-bottom-color: '{{accent-color}}'; }md-select.md-THEME_NAME-theme:not([disabled]):focus.md-warn .md-select-label { border-bottom-color: '{{warn-color}}'; }md-select.md-THEME_NAME-theme[disabled] .md-select-label { color: '{{foreground-3}}'; } md-select.md-THEME_NAME-theme[disabled] .md-select-label.md-placeholder { color: '{{foreground-3}}'; }md-select.md-THEME_NAME-theme .md-select-label { border-bottom-color: '{{foreground-4}}'; } md-select.md-THEME_NAME-theme .md-select-label.md-placeholder { color: '{{foreground-2}}'; }md-select-menu.md-THEME_NAME-theme md-optgroup { color: '{{foreground-2}}'; } md-select-menu.md-THEME_NAME-theme md-optgroup md-option { color: '{{foreground-1}}'; }md-select-menu.md-THEME_NAME-theme md-option[selected] { background-color: '{{primary-50}}'; } md-select-menu.md-THEME_NAME-theme md-option[selected]:focus { background-color: '{{primary-100}}'; } md-select-menu.md-THEME_NAME-theme md-option[selected].md-accent { background-color: '{{accent-50}}'; } md-select-menu.md-THEME_NAME-theme md-option[selected].md-accent:focus { background-color: '{{accent-100}}'; }md-select-menu.md-THEME_NAME-theme md-option:focus:not([selected]) { background: '{{background-200}}'; }md-sidenav.md-THEME_NAME-theme { background-color: '{{background-hue-3}}'; }md-slider.md-THEME_NAME-theme .md-track { background-color: '{{foreground-3}}'; }md-slider.md-THEME_NAME-theme .md-track-ticks { background-color: '{{foreground-4}}'; }md-slider.md-THEME_NAME-theme .md-focus-thumb { background-color: '{{foreground-2}}'; }md-slider.md-THEME_NAME-theme .md-focus-ring { border-color: '{{foreground-4}}'; }md-slider.md-THEME_NAME-theme .md-disabled-thumb { border-color: '{{background-hue-3}}'; }md-slider.md-THEME_NAME-theme.md-min .md-thumb:after { background-color: '{{background-hue-3}}'; }md-slider.md-THEME_NAME-theme .md-track.md-track-fill { background-color: '{{accent-color}}'; }md-slider.md-THEME_NAME-theme .md-thumb:after { border-color: '{{accent-color}}'; background-color: '{{accent-color}}'; }md-slider.md-THEME_NAME-theme .md-sign { background-color: '{{accent-color}}'; } md-slider.md-THEME_NAME-theme .md-sign:after { border-top-color: '{{accent-color}}'; }md-slider.md-THEME_NAME-theme .md-thumb-text { color: '{{accent-contrast}}'; }md-slider.md-THEME_NAME-theme.md-warn .md-track.md-track-fill { background-color: '{{warn-color}}'; }md-slider.md-THEME_NAME-theme.md-warn .md-thumb:after { border-color: '{{warn-color}}'; background-color: '{{warn-color}}'; }md-slider.md-THEME_NAME-theme.md-warn .md-sign { background-color: '{{warn-color}}'; } md-slider.md-THEME_NAME-theme.md-warn .md-sign:after { border-top-color: '{{warn-color}}'; }md-slider.md-THEME_NAME-theme.md-warn .md-thumb-text { color: '{{warn-contrast}}'; }md-slider.md-THEME_NAME-theme.md-primary .md-track.md-track-fill { background-color: '{{primary-color}}'; }md-slider.md-THEME_NAME-theme.md-primary .md-thumb:after { border-color: '{{primary-color}}'; background-color: '{{primary-color}}'; }md-slider.md-THEME_NAME-theme.md-primary .md-sign { background-color: '{{primary-color}}'; } md-slider.md-THEME_NAME-theme.md-primary .md-sign:after { border-top-color: '{{primary-color}}'; }md-slider.md-THEME_NAME-theme.md-primary .md-thumb-text { color: '{{primary-contrast}}'; }md-slider.md-THEME_NAME-theme[disabled] .md-thumb:after { border-color: '{{foreground-3}}'; }md-slider.md-THEME_NAME-theme[disabled]:not(.md-min) .md-thumb:after { background-color: '{{foreground-3}}'; }.md-subheader.md-THEME_NAME-theme { color: '{{ foreground-2-0.23 }}'; background-color: '{{background-hue-3}}'; } .md-subheader.md-THEME_NAME-theme.md-primary { color: '{{primary-color}}'; } .md-subheader.md-THEME_NAME-theme.md-accent { color: '{{accent-color}}'; } .md-subheader.md-THEME_NAME-theme.md-warn { color: '{{warn-color}}'; }md-switch.md-THEME_NAME-theme .md-thumb { background-color: '{{background-50}}'; }md-switch.md-THEME_NAME-theme .md-bar { background-color: '{{background-500}}'; }md-switch.md-THEME_NAME-theme.md-checked .md-thumb { background-color: '{{accent-color}}'; }md-switch.md-THEME_NAME-theme.md-checked .md-bar { background-color: '{{accent-color-0.5}}'; }md-switch.md-THEME_NAME-theme.md-checked.md-primary .md-thumb { background-color: '{{primary-color}}'; }md-switch.md-THEME_NAME-theme.md-checked.md-primary .md-bar { background-color: '{{primary-color-0.5}}'; }md-switch.md-THEME_NAME-theme.md-checked.md-warn .md-thumb { background-color: '{{warn-color}}'; }md-switch.md-THEME_NAME-theme.md-checked.md-warn .md-bar { background-color: '{{warn-color-0.5}}'; }md-switch.md-THEME_NAME-theme[disabled] .md-thumb { background-color: '{{background-400}}'; }md-switch.md-THEME_NAME-theme[disabled] .md-bar { background-color: '{{foreground-4}}'; }md-switch.md-THEME_NAME-theme:focus .md-label:not(:empty) { border-color: '{{foreground-1}}'; border-style: dotted; }md-tabs.md-THEME_NAME-theme md-tabs-wrapper { background-color: transparent; border-color: '{{foreground-4}}'; }md-tabs.md-THEME_NAME-theme .md-paginator md-icon { color: '{{primary-color}}'; }md-tabs.md-THEME_NAME-theme md-ink-bar { color: '{{accent-color}}'; background: '{{accent-color}}'; }md-tabs.md-THEME_NAME-theme .md-tab { color: '{{foreground-2}}'; } md-tabs.md-THEME_NAME-theme .md-tab[disabled] { color: '{{foreground-3}}'; } md-tabs.md-THEME_NAME-theme .md-tab.md-active, md-tabs.md-THEME_NAME-theme .md-tab.md-focus { color: '{{primary-color}}'; } md-tabs.md-THEME_NAME-theme .md-tab.md-focus { background: '{{primary-color-0.1}}'; } md-tabs.md-THEME_NAME-theme .md-tab .md-ripple-container { color: '{{accent-100}}'; }md-tabs.md-THEME_NAME-theme.md-accent md-tabs-wrapper { background-color: '{{accent-color}}'; }md-tabs.md-THEME_NAME-theme.md-accent md-tab-item:not([disabled]) { color: '{{accent-100}}'; } md-tabs.md-THEME_NAME-theme.md-accent md-tab-item:not([disabled]).md-active, md-tabs.md-THEME_NAME-theme.md-accent md-tab-item:not([disabled]).md-focus { color: '{{accent-contrast}}'; } md-tabs.md-THEME_NAME-theme.md-accent md-tab-item:not([disabled]).md-focus { background: '{{accent-contrast-0.1}}'; }md-tabs.md-THEME_NAME-theme.md-accent md-ink-bar { color: '{{primary-600-1}}'; background: '{{primary-600-1}}'; }md-tabs.md-THEME_NAME-theme.md-primary md-tabs-wrapper { background-color: '{{primary-color}}'; }md-tabs.md-THEME_NAME-theme.md-primary md-tab-item:not([disabled]) { color: '{{primary-100}}'; } md-tabs.md-THEME_NAME-theme.md-primary md-tab-item:not([disabled]).md-active, md-tabs.md-THEME_NAME-theme.md-primary md-tab-item:not([disabled]).md-focus { color: '{{primary-contrast}}'; } md-tabs.md-THEME_NAME-theme.md-primary md-tab-item:not([disabled]).md-focus { background: '{{primary-contrast-0.1}}'; }md-tabs.md-THEME_NAME-theme.md-warn md-tabs-wrapper { background-color: '{{warn-color}}'; }md-tabs.md-THEME_NAME-theme.md-warn md-tab-item:not([disabled]) { color: '{{warn-100}}'; } md-tabs.md-THEME_NAME-theme.md-warn md-tab-item:not([disabled]).md-active, md-tabs.md-THEME_NAME-theme.md-warn md-tab-item:not([disabled]).md-focus { color: '{{warn-contrast}}'; } md-tabs.md-THEME_NAME-theme.md-warn md-tab-item:not([disabled]).md-focus { background: '{{warn-contrast-0.1}}'; }md-toolbar > md-tabs.md-THEME_NAME-theme md-tabs-wrapper { background-color: '{{primary-color}}'; }md-toolbar > md-tabs.md-THEME_NAME-theme md-tab-item:not([disabled]) { color: '{{primary-100}}'; } md-toolbar > md-tabs.md-THEME_NAME-theme md-tab-item:not([disabled]).md-active, md-toolbar > md-tabs.md-THEME_NAME-theme md-tab-item:not([disabled]).md-focus { color: '{{primary-contrast}}'; } md-toolbar > md-tabs.md-THEME_NAME-theme md-tab-item:not([disabled]).md-focus { background: '{{primary-contrast-0.1}}'; }md-toolbar.md-accent > md-tabs.md-THEME_NAME-theme md-tabs-wrapper { background-color: '{{accent-color}}'; }md-toolbar.md-accent > md-tabs.md-THEME_NAME-theme md-tab-item:not([disabled]) { color: '{{accent-100}}'; } md-toolbar.md-accent > md-tabs.md-THEME_NAME-theme md-tab-item:not([disabled]).md-active, md-toolbar.md-accent > md-tabs.md-THEME_NAME-theme md-tab-item:not([disabled]).md-focus { color: '{{accent-contrast}}'; } md-toolbar.md-accent > md-tabs.md-THEME_NAME-theme md-tab-item:not([disabled]).md-focus { background: '{{accent-contrast-0.1}}'; }md-toolbar.md-accent > md-tabs.md-THEME_NAME-theme md-ink-bar { color: '{{primary-600-1}}'; background: '{{primary-600-1}}'; }md-toolbar.md-warn > md-tabs.md-THEME_NAME-theme md-tabs-wrapper { background-color: '{{warn-color}}'; }md-toolbar.md-warn > md-tabs.md-THEME_NAME-theme md-tab-item:not([disabled]) { color: '{{warn-100}}'; } md-toolbar.md-warn > md-tabs.md-THEME_NAME-theme md-tab-item:not([disabled]).md-active, md-toolbar.md-warn > md-tabs.md-THEME_NAME-theme md-tab-item:not([disabled]).md-focus { color: '{{warn-contrast}}'; } md-toolbar.md-warn > md-tabs.md-THEME_NAME-theme md-tab-item:not([disabled]).md-focus { background: '{{warn-contrast-0.1}}'; }md-input-group.md-THEME_NAME-theme input, md-input-group.md-THEME_NAME-theme textarea { text-shadow: '{{foreground-shadow}}'; } md-input-group.md-THEME_NAME-theme input::-webkit-input-placeholder, md-input-group.md-THEME_NAME-theme input::-moz-placeholder, md-input-group.md-THEME_NAME-theme input:-moz-placeholder, md-input-group.md-THEME_NAME-theme input:-ms-input-placeholder, md-input-group.md-THEME_NAME-theme textarea::-webkit-input-placeholder, md-input-group.md-THEME_NAME-theme textarea::-moz-placeholder, md-input-group.md-THEME_NAME-theme textarea:-moz-placeholder, md-input-group.md-THEME_NAME-theme textarea:-ms-input-placeholder { color: '{{foreground-3}}'; }md-input-group.md-THEME_NAME-theme label { text-shadow: '{{foreground-shadow}}'; color: '{{foreground-3}}'; }md-input-group.md-THEME_NAME-theme input, md-input-group.md-THEME_NAME-theme textarea { color: '{{foreground-1}}'; border-color: '{{foreground-4}}'; }md-input-group.md-THEME_NAME-theme.md-input-focused input, md-input-group.md-THEME_NAME-theme.md-input-focused textarea { border-color: '{{primary-500}}'; }md-input-group.md-THEME_NAME-theme.md-input-focused label { color: '{{primary-500}}'; }md-input-group.md-THEME_NAME-theme.md-input-focused.md-accent input, md-input-group.md-THEME_NAME-theme.md-input-focused.md-accent textarea { border-color: '{{accent-500}}'; }md-input-group.md-THEME_NAME-theme.md-input-focused.md-accent label { color: '{{accent-500}}'; }md-input-group.md-THEME_NAME-theme.md-input-has-value:not(.md-input-focused) label { color: '{{foreground-2}}'; }md-input-group.md-THEME_NAME-theme .md-input[disabled] { border-bottom-color: '{{foreground-4}}'; color: '{{foreground-3}}'; }md-toast.md-THEME_NAME-theme { background-color: #323232; color: '{{background-50}}'; } md-toast.md-THEME_NAME-theme .md-button { color: '{{background-50}}'; } md-toast.md-THEME_NAME-theme .md-button.md-highlight { color: '{{primary-A200}}'; } md-toast.md-THEME_NAME-theme .md-button.md-highlight.md-accent { color: '{{accent-A200}}'; } md-toast.md-THEME_NAME-theme .md-button.md-highlight.md-warn { color: '{{warn-A200}}'; }md-toolbar.md-THEME_NAME-theme { background-color: '{{primary-color}}'; color: '{{primary-contrast}}'; } md-toolbar.md-THEME_NAME-theme .md-button { color: '{{primary-contrast}}'; } md-toolbar.md-THEME_NAME-theme.md-accent { background-color: '{{accent-color}}'; color: '{{accent-contrast}}'; } md-toolbar.md-THEME_NAME-theme.md-warn { background-color: '{{warn-color}}'; color: '{{warn-contrast}}'; }md-tooltip.md-THEME_NAME-theme { color: '{{background-A100}}'; } md-tooltip.md-THEME_NAME-theme .md-background { background-color: '{{foreground-2}}'; }");
12024
12382
  })();