Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * @fileoverview User pod row implementation. | 6 * @fileoverview User pod row implementation. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 cr.define('login', function() { | 9 cr.define('login', function() { |
| 10 /** | 10 /** |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 52 var DESKTOP_POD_WIDTH = 180; | 52 var DESKTOP_POD_WIDTH = 180; |
| 53 var MD_DESKTOP_POD_WIDTH = 160; | 53 var MD_DESKTOP_POD_WIDTH = 160; |
| 54 var PUBLIC_EXPANDED_BASIC_WIDTH = 500; | 54 var PUBLIC_EXPANDED_BASIC_WIDTH = 500; |
| 55 var PUBLIC_EXPANDED_ADVANCED_WIDTH = 610; | 55 var PUBLIC_EXPANDED_ADVANCED_WIDTH = 610; |
| 56 var CROS_POD_HEIGHT = 213; | 56 var CROS_POD_HEIGHT = 213; |
| 57 var DESKTOP_POD_HEIGHT = 226; | 57 var DESKTOP_POD_HEIGHT = 226; |
| 58 var MD_DESKTOP_POD_HEIGHT = 200; | 58 var MD_DESKTOP_POD_HEIGHT = 200; |
| 59 var POD_ROW_PADDING = 10; | 59 var POD_ROW_PADDING = 10; |
| 60 var DESKTOP_ROW_PADDING = 32; | 60 var DESKTOP_ROW_PADDING = 32; |
| 61 var CUSTOM_ICON_CONTAINER_SIZE = 40; | 61 var CUSTOM_ICON_CONTAINER_SIZE = 40; |
| 62 var CROS_PIN_POD_WIDTH = 270; | |
| 63 var CROS_PIN_POD_HEIGHT = 594; | |
| 64 var PIN_EXTRA_WIDTH = 90; | |
| 62 | 65 |
| 63 /** | 66 /** |
| 64 * Minimal padding between user pod and virtual keyboard. | 67 * Minimal padding between user pod and virtual keyboard. |
| 65 * @type {number} | 68 * @type {number} |
| 66 * @const | 69 * @const |
| 67 */ | 70 */ |
| 68 var USER_POD_KEYBOARD_MIN_PADDING = 20; | 71 var USER_POD_KEYBOARD_MIN_PADDING = 20; |
| 69 | 72 |
| 70 /** | 73 /** |
| 71 * Maximum time for which the pod row remains hidden until all user images | 74 * Maximum time for which the pod row remains hidden until all user images |
| (...skipping 741 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 813 }, | 816 }, |
| 814 | 817 |
| 815 /** | 818 /** |
| 816 * Height number of pixels. | 819 * Height number of pixels. |
| 817 */ | 820 */ |
| 818 get height() { | 821 get height() { |
| 819 return this.offsetHeight; | 822 return this.offsetHeight; |
| 820 }, | 823 }, |
| 821 | 824 |
| 822 /** | 825 /** |
| 823 * Gets the authorization element of the pod. | |
| 824 * @type {!HTMLDivElement} | |
| 825 */ | |
| 826 get authElement() { | |
| 827 return this.querySelector('.auth-container'); | |
| 828 }, | |
| 829 | |
| 830 /** | |
| 831 * Gets image pane element. | |
| 832 * @type {!HTMLDivElement} | |
| 833 */ | |
| 834 get imagePaneElement() { | |
| 835 return this.querySelector('.user-image-pane'); | |
| 836 }, | |
| 837 | |
| 838 /** | |
| 839 * Gets image element. | 826 * Gets image element. |
| 840 * @type {!HTMLImageElement} | 827 * @type {!HTMLImageElement} |
| 841 */ | 828 */ |
| 842 get imageElement() { | 829 get imageElement() { |
| 843 return this.querySelector('.user-image'); | 830 return this.querySelector('.user-image'); |
| 844 }, | 831 }, |
| 845 | 832 |
| 846 /** | 833 /** |
| 847 * Gets name element. | 834 * Gets name element. |
| 848 * @type {!HTMLDivElement} | 835 * @type {!HTMLDivElement} |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 878 /** | 865 /** |
| 879 * Gets the password label, which is used to show a message where the | 866 * Gets the password label, which is used to show a message where the |
| 880 * password field is normally. | 867 * password field is normally. |
| 881 * @type {!HTMLInputElement} | 868 * @type {!HTMLInputElement} |
| 882 */ | 869 */ |
| 883 get passwordLabelElement() { | 870 get passwordLabelElement() { |
| 884 return this.querySelector('.password-label'); | 871 return this.querySelector('.password-label'); |
| 885 }, | 872 }, |
| 886 | 873 |
| 887 /** | 874 /** |
| 888 * Gets the pin-container of the pod. | |
| 889 * @type {!HTMLDivElement} | |
| 890 */ | |
| 891 get pinContainer() { | |
| 892 return this.querySelector('.pin-container'); | |
| 893 }, | |
| 894 | |
| 895 /** | |
| 896 * Gets the pin-keyboard of the pod. | 875 * Gets the pin-keyboard of the pod. |
| 897 * @type {!HTMLElement} | 876 * @type {!HTMLElement} |
| 898 */ | 877 */ |
| 899 get pinKeyboard() { | 878 get pinKeyboard() { |
| 900 return this.querySelector('pin-keyboard'); | 879 return this.querySelector('pin-keyboard'); |
| 901 }, | 880 }, |
| 902 | 881 |
| 903 /** | 882 /** |
| 904 * Gets user online sign in hint element. | 883 * Gets user online sign in hint element. |
| 905 * @type {!HTMLDivElement} | 884 * @type {!HTMLDivElement} |
| 906 */ | 885 */ |
| 907 get reauthWarningElement() { | 886 get reauthWarningElement() { |
| 908 return this.querySelector('.reauth-hint-container'); | 887 return this.querySelector('.reauth-hint-container'); |
| 909 }, | 888 }, |
| 910 | 889 |
| 911 /** | 890 /** |
| 912 * Gets the signed in indicator of the pod. | |
| 913 * @type {!HTMLDivElement} | |
| 914 */ | |
| 915 get signInElement() { | |
| 916 return this.querySelector('.signed-in-indicator'); | |
| 917 }, | |
| 918 | |
| 919 /** | |
| 920 * Gets the container holding the launch app button. | 891 * Gets the container holding the launch app button. |
| 921 * @type {!HTMLButtonElement} | 892 * @type {!HTMLButtonElement} |
| 922 */ | 893 */ |
| 923 get launchAppButtonContainerElement() { | 894 get launchAppButtonContainerElement() { |
| 924 return this.querySelector('.launch-app-button-container'); | 895 return this.querySelector('.launch-app-button-container'); |
| 925 }, | 896 }, |
| 926 | 897 |
| 927 /** | 898 /** |
| 928 * Gets launch app button. | 899 * Gets launch app button. |
| 929 * @type {!HTMLButtonElement} | 900 * @type {!HTMLButtonElement} |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1114 this.querySelector('.mp-policy-not-allowed-msg').hidden = false; | 1085 this.querySelector('.mp-policy-not-allowed-msg').hidden = false; |
| 1115 } else if (this.user_.isApp) { | 1086 } else if (this.user_.isApp) { |
| 1116 this.setUserPodIconType('app'); | 1087 this.setUserPodIconType('app'); |
| 1117 } | 1088 } |
| 1118 }, | 1089 }, |
| 1119 | 1090 |
| 1120 toggleTransitions: function(enable) { | 1091 toggleTransitions: function(enable) { |
| 1121 this.classList.toggle('flying-pin-pod', enable); | 1092 this.classList.toggle('flying-pin-pod', enable); |
| 1122 }, | 1093 }, |
| 1123 | 1094 |
| 1095 setPinClass_: function(element, enable) { | |
| 1096 element.classList.toggle('pin-enabled', enable); | |
| 1097 element.classList.toggle('pin-disabled', !enable); | |
| 1098 }, | |
| 1099 | |
| 1124 setPinVisibility: function(visible) { | 1100 setPinVisibility: function(visible) { |
| 1125 var elements = [this, this.authElement, this.imagePaneElement, | 1101 var elements = this.getElementsByClassName('pin-tag'); |
| 1126 this.imageElement, this.pinContainer]; | 1102 var elements_array = Array.prototype.slice.call(elements); |
| 1103 elements_array.push(this); | |
| 1127 | 1104 |
| 1128 for (var idx = 0; idx < elements.length; idx++) { | 1105 for (var idx = 0; idx < elements_array.length; idx++) { |
|
jdufault
2016/07/18 18:28:44
Iterate over elements directly and add an explicit
sammiequon
2016/07/18 22:34:21
Done.
| |
| 1129 var currentElement = elements[idx]; | 1106 var currentElement = elements_array[idx]; |
| 1130 currentElement.classList.toggle('pin-enabled', visible); | 1107 this.setPinClass_(currentElement, visible); |
| 1131 currentElement.classList.toggle('pin-disabled', !visible); | |
| 1132 } | 1108 } |
| 1133 | 1109 |
| 1134 // Set the focus to the input element after showing/hiding pin keyboard. | 1110 // Set the focus to the input element after showing/hiding pin keyboard. |
| 1135 if (visible) | 1111 if (visible) |
| 1136 this.pinKeyboard.focus(); | 1112 this.pinKeyboard.focus(); |
| 1137 else | 1113 else |
| 1138 this.mainInput.focus(); | 1114 this.mainInput.focus(); |
| 1139 }, | 1115 }, |
| 1140 | 1116 |
| 1117 isPinShown: function() { | |
| 1118 return this.classList.contains('pin-enabled'); | |
| 1119 }, | |
| 1120 | |
| 1141 setUserPodIconType: function(userTypeClass) { | 1121 setUserPodIconType: function(userTypeClass) { |
| 1142 this.userTypeIconAreaElement.classList.add(userTypeClass); | 1122 this.userTypeIconAreaElement.classList.add(userTypeClass); |
| 1143 this.userTypeIconAreaElement.hidden = false; | 1123 this.userTypeIconAreaElement.hidden = false; |
| 1144 }, | 1124 }, |
| 1145 | 1125 |
| 1146 /** | 1126 /** |
| 1147 * The user that this pod represents. | 1127 * The user that this pod represents. |
| 1148 * @type {!Object} | 1128 * @type {!Object} |
| 1149 */ | 1129 */ |
| 1150 user_: undefined, | 1130 user_: undefined, |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 1166 (Oobe.getInstance().displayType == DISPLAY_TYPE.USER_ADDING); | 1146 (Oobe.getInstance().displayType == DISPLAY_TYPE.USER_ADDING); |
| 1167 return isMultiProfilesUI && !this.user_.isMultiProfilesAllowed; | 1147 return isMultiProfilesUI && !this.user_.isMultiProfilesAllowed; |
| 1168 }, | 1148 }, |
| 1169 | 1149 |
| 1170 /** | 1150 /** |
| 1171 * Gets main input element. | 1151 * Gets main input element. |
| 1172 * @type {(HTMLButtonElement|HTMLInputElement)} | 1152 * @type {(HTMLButtonElement|HTMLInputElement)} |
| 1173 */ | 1153 */ |
| 1174 get mainInput() { | 1154 get mainInput() { |
| 1175 if (this.isAuthTypePassword) { | 1155 if (this.isAuthTypePassword) { |
| 1176 if (this.pinContainer.classList.contains('pin-enabled')) | 1156 if (this.isPinShown() && this.pinKeyboard.inputElement) |
| 1177 return this.pinKeyboard.inputElement; | 1157 return this.pinKeyboard.inputElement; |
| 1178 return this.passwordElement; | 1158 return this.passwordElement; |
| 1179 } else if (this.isAuthTypeOnlineSignIn) { | 1159 } else if (this.isAuthTypeOnlineSignIn) { |
| 1180 return this; | 1160 return this; |
| 1181 } else if (this.isAuthTypeUserClick) { | 1161 } else if (this.isAuthTypeUserClick) { |
| 1182 return this.passwordLabelElement; | 1162 return this.passwordLabelElement; |
| 1183 } | 1163 } |
| 1184 }, | 1164 }, |
| 1185 | 1165 |
| 1186 /** | 1166 /** |
| (...skipping 1808 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2995 var layout = this.calculateLayout_(); | 2975 var layout = this.calculateLayout_(); |
| 2996 var columns = this.columns = layout.columns; | 2976 var columns = this.columns = layout.columns; |
| 2997 var rows = this.rows = layout.rows; | 2977 var rows = this.rows = layout.rows; |
| 2998 var maxPodsNumber = columns * rows; | 2978 var maxPodsNumber = columns * rows; |
| 2999 var margin = isDesktopUserManager ? DESKTOP_MARGIN_BY_COLUMNS[columns] : | 2979 var margin = isDesktopUserManager ? DESKTOP_MARGIN_BY_COLUMNS[columns] : |
| 3000 MARGIN_BY_COLUMNS[columns]; | 2980 MARGIN_BY_COLUMNS[columns]; |
| 3001 this.parentNode.setPreferredSize( | 2981 this.parentNode.setPreferredSize( |
| 3002 this.columnsToWidth_(columns), this.rowsToHeight_(rows)); | 2982 this.columnsToWidth_(columns), this.rowsToHeight_(rows)); |
| 3003 var height = this.userPodHeight_; | 2983 var height = this.userPodHeight_; |
| 3004 var width = this.userPodWidth_; | 2984 var width = this.userPodWidth_; |
| 2985 | |
| 2986 var pinShownRow = maxPodsNumber + 1; | |
| 2987 var pinShownColumn = maxPodsNumber + 1; | |
| 2988 var podWithPin = this.focusedPod_; | |
|
jdufault
2016/07/18 18:28:44
What about extracting this logic into a helper fun
sammiequon
2016/07/18 22:34:21
Done.
| |
| 2989 | |
| 2990 if (podWithPin && podWithPin.isPinShown()) { | |
| 2991 this.pods.forEach(function(pod, index) { | |
| 2992 var column = index % columns; | |
| 2993 var row = Math.floor(index / columns); | |
| 2994 if (pod == podWithPin) { | |
| 2995 pinShownRow = row; | |
| 2996 pinShownColumn = column; | |
| 2997 } else if (pod.isPinShown()) { | |
| 2998 // Only the focused pod should ever show the PIN keyboard. | |
| 2999 console.error('Pod that is not the focused pod is showing its' + | |
|
jdufault
2016/07/18 18:28:44
nit: add space after its
Or what about:
consol
sammiequon
2016/07/18 22:34:21
Done.
| |
| 3000 'PIN keyboard.'); | |
| 3001 } | |
| 3002 }); | |
| 3003 } | |
| 3004 | |
| 3005 this.pods.forEach(function(pod, index) { | 3005 this.pods.forEach(function(pod, index) { |
| 3006 if (index >= maxPodsNumber) { | 3006 if (index >= maxPodsNumber) { |
| 3007 pod.hidden = true; | 3007 pod.hidden = true; |
| 3008 return; | 3008 return; |
| 3009 } | 3009 } |
| 3010 pod.hidden = false; | 3010 pod.hidden = false; |
| 3011 if (pod.offsetHeight != height) { | 3011 if (pod.offsetHeight != height && |
| 3012 pod.offsetHeight != CROS_PIN_POD_HEIGHT) { | |
| 3012 console.error('Pod offsetHeight (' + pod.offsetHeight + | 3013 console.error('Pod offsetHeight (' + pod.offsetHeight + |
| 3013 ') and POD_HEIGHT (' + height + ') are not equal.'); | 3014 ') and POD_HEIGHT (' + height + ') are not equal.'); |
| 3014 } | 3015 } |
| 3015 if (pod.offsetWidth != width) { | 3016 if (pod.offsetWidth != width && |
| 3017 pod.offsetWidth != CROS_PIN_POD_WIDTH) { | |
| 3016 console.error('Pod offsetWidth (' + pod.offsetWidth + | 3018 console.error('Pod offsetWidth (' + pod.offsetWidth + |
| 3017 ') and POD_WIDTH (' + width + ') are not equal.'); | 3019 ') and POD_WIDTH (' + width + ') are not equal.'); |
| 3018 } | 3020 } |
| 3019 var column = index % columns; | 3021 var column = index % columns; |
| 3020 var row = Math.floor(index / columns); | 3022 var row = Math.floor(index / columns); |
| 3023 var offsetFromPin = 0; | |
| 3024 if (row == pinShownRow) { | |
| 3025 offsetFromPin = PIN_EXTRA_WIDTH / 2; | |
| 3026 if (column <= pinShownColumn) | |
| 3027 offsetFromPin *= -1; | |
| 3028 } | |
| 3029 | |
| 3021 var rowPadding = isDesktopUserManager ? DESKTOP_ROW_PADDING : | 3030 var rowPadding = isDesktopUserManager ? DESKTOP_ROW_PADDING : |
| 3022 POD_ROW_PADDING; | 3031 POD_ROW_PADDING; |
| 3023 pod.left = rowPadding + column * (width + margin); | 3032 pod.left = rowPadding + column * (width + margin) + offsetFromPin; |
| 3024 | 3033 |
| 3025 // On desktop, we want the rows to always be equally spaced. | 3034 // On desktop, we want the rows to always be equally spaced. |
| 3026 pod.top = isDesktopUserManager ? row * (height + rowPadding) : | 3035 pod.top = isDesktopUserManager ? row * (height + rowPadding) : |
| 3027 row * height + rowPadding; | 3036 row * height + rowPadding; |
| 3028 }); | 3037 }); |
| 3029 Oobe.getInstance().updateScreenSize(this.parentNode); | 3038 Oobe.getInstance().updateScreenSize(this.parentNode); |
| 3030 }, | 3039 }, |
| 3031 | 3040 |
| 3032 /** | 3041 /** |
| 3033 * Number of columns. | 3042 * Number of columns. |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3084 } | 3093 } |
| 3085 this.insideFocusPod_ = true; | 3094 this.insideFocusPod_ = true; |
| 3086 | 3095 |
| 3087 for (var i = 0, pod; pod = this.pods[i]; ++i) { | 3096 for (var i = 0, pod; pod = this.pods[i]; ++i) { |
| 3088 if (!this.alwaysFocusSinglePod) { | 3097 if (!this.alwaysFocusSinglePod) { |
| 3089 pod.isActionBoxMenuActive = false; | 3098 pod.isActionBoxMenuActive = false; |
| 3090 } | 3099 } |
| 3091 if (pod != podToFocus) { | 3100 if (pod != podToFocus) { |
| 3092 pod.isActionBoxMenuHovered = false; | 3101 pod.isActionBoxMenuHovered = false; |
| 3093 pod.classList.remove('focused'); | 3102 pod.classList.remove('focused'); |
| 3103 pod.setPinVisibility(false); | |
| 3094 // On Desktop, the faded style is not set correctly, so we should | 3104 // On Desktop, the faded style is not set correctly, so we should |
| 3095 // manually fade out non-focused pods if there is a focused pod. | 3105 // manually fade out non-focused pods if there is a focused pod. |
| 3096 if (pod.user.isDesktopUser && podToFocus) | 3106 if (pod.user.isDesktopUser && podToFocus) |
| 3097 pod.classList.add('faded'); | 3107 pod.classList.add('faded'); |
| 3098 else | 3108 else |
| 3099 pod.classList.remove('faded'); | 3109 pod.classList.remove('faded'); |
| 3100 pod.reset(false); | 3110 pod.reset(false); |
| 3101 } | 3111 } |
| 3102 } | 3112 } |
| 3103 | 3113 |
| 3104 // Clear any error messages for previous pod. | 3114 // Clear any error messages for previous pod. |
| 3105 if (!this.isFocused(podToFocus)) | 3115 if (!this.isFocused(podToFocus)) |
| 3106 Oobe.clearErrors(); | 3116 Oobe.clearErrors(); |
| 3107 | 3117 |
| 3108 var hadFocus = !!this.focusedPod_; | 3118 var hadFocus = !!this.focusedPod_; |
| 3109 this.focusedPod_ = podToFocus; | 3119 this.focusedPod_ = podToFocus; |
| 3110 if (podToFocus) { | 3120 if (podToFocus) { |
| 3121 this.setFocusedPodPinVisibility(true); | |
| 3111 podToFocus.classList.remove('faded'); | 3122 podToFocus.classList.remove('faded'); |
| 3112 podToFocus.classList.add('focused'); | 3123 podToFocus.classList.add('focused'); |
| 3113 if (!podToFocus.multiProfilesPolicyApplied) { | 3124 if (!podToFocus.multiProfilesPolicyApplied) { |
| 3114 podToFocus.classList.toggle('signing-in', false); | 3125 podToFocus.classList.toggle('signing-in', false); |
| 3115 if (!opt_skipInputFocus) | 3126 if (!opt_skipInputFocus) |
| 3116 podToFocus.focusInput(); | 3127 podToFocus.focusInput(); |
| 3117 } else { | 3128 } else { |
| 3118 podToFocus.userTypeBubbleElement.classList.add('bubble-shown'); | 3129 podToFocus.userTypeBubbleElement.classList.add('bubble-shown'); |
| 3119 // Note it is not necessary to skip this focus request when | 3130 // Note it is not necessary to skip this focus request when |
| 3120 // |opt_skipInputFocus| is true. When |multiProfilesPolicyApplied| | 3131 // |opt_skipInputFocus| is true. When |multiProfilesPolicyApplied| |
| 3121 // is false, it doesn't focus on the password input box by default. | 3132 // is false, it doesn't focus on the password input box by default. |
| 3122 podToFocus.focus(); | 3133 podToFocus.focus(); |
| 3123 } | 3134 } |
| 3124 | 3135 |
| 3125 // focusPod() automatically loads wallpaper | 3136 // focusPod() automatically loads wallpaper |
| 3126 if (!podToFocus.user.isApp) | 3137 if (!podToFocus.user.isApp) |
| 3127 chrome.send('focusPod', [podToFocus.user.username]); | 3138 chrome.send('focusPod', [podToFocus.user.username]); |
| 3128 this.firstShown_ = false; | 3139 this.firstShown_ = false; |
| 3129 this.lastFocusedPod_ = podToFocus; | 3140 this.lastFocusedPod_ = podToFocus; |
| 3130 this.scrollFocusedPodIntoView(); | 3141 this.scrollFocusedPodIntoView(); |
| 3131 } | 3142 } |
| 3132 this.insideFocusPod_ = false; | 3143 this.insideFocusPod_ = false; |
| 3144 this.placePods_(); | |
| 3133 }, | 3145 }, |
| 3134 | 3146 |
| 3135 /** | 3147 /** |
| 3136 * Resets wallpaper to the last active user's wallpaper, if any. | 3148 * Resets wallpaper to the last active user's wallpaper, if any. |
| 3137 */ | 3149 */ |
| 3138 loadLastWallpaper: function() { | 3150 loadLastWallpaper: function() { |
| 3139 if (this.lastFocusedPod_ && !this.lastFocusedPod_.user.isApp) | 3151 if (this.lastFocusedPod_ && !this.lastFocusedPod_.user.isApp) |
| 3140 chrome.send('loadWallpaper', [this.lastFocusedPod_.user.username]); | 3152 chrome.send('loadWallpaper', [this.lastFocusedPod_.user.username]); |
| 3141 }, | 3153 }, |
| 3142 | 3154 |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3505 if (pod && pod.multiProfilesPolicyApplied) { | 3517 if (pod && pod.multiProfilesPolicyApplied) { |
| 3506 pod.userTypeBubbleElement.classList.remove('bubble-shown'); | 3518 pod.userTypeBubbleElement.classList.remove('bubble-shown'); |
| 3507 } | 3519 } |
| 3508 } | 3520 } |
| 3509 }; | 3521 }; |
| 3510 | 3522 |
| 3511 return { | 3523 return { |
| 3512 PodRow: PodRow | 3524 PodRow: PodRow |
| 3513 }; | 3525 }; |
| 3514 }); | 3526 }); |
| OLD | NEW |