| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 cr.define('options', function() { | 5 cr.define('options', function() { |
| 6 /** @const */ var ArrayDataModel = cr.ui.ArrayDataModel; | 6 /** @const */ var ArrayDataModel = cr.ui.ArrayDataModel; |
| 7 /** @const */ var DeletableItem = options.DeletableItem; | 7 /** @const */ var DeletableItem = options.DeletableItem; |
| 8 /** @const */ var DeletableItemList = options.DeletableItemList; | 8 /** @const */ var DeletableItemList = options.DeletableItemList; |
| 9 /** @const */ var List = cr.ui.List; | 9 /** @const */ var List = cr.ui.List; |
| 10 /** @const */ var ListItem = cr.ui.ListItem; | 10 /** @const */ var ListItem = cr.ui.ListItem; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 69 if (!this.languageCodeToLanguageInfo_) { | 69 if (!this.languageCodeToLanguageInfo_) { |
| 70 this.languageCodeToLanguageInfo_ = {}; | 70 this.languageCodeToLanguageInfo_ = {}; |
| 71 var languageList = loadTimeData.getValue('languageList'); | 71 var languageList = loadTimeData.getValue('languageList'); |
| 72 for (var i = 0; i < languageList.length; i++) { | 72 for (var i = 0; i < languageList.length; i++) { |
| 73 var languageInfo = languageList[i]; | 73 var languageInfo = languageList[i]; |
| 74 this.languageCodeToLanguageInfo_[languageInfo.code] = languageInfo; | 74 this.languageCodeToLanguageInfo_[languageInfo.code] = languageInfo; |
| 75 } | 75 } |
| 76 } | 76 } |
| 77 | 77 |
| 78 return this.languageCodeToLanguageInfo_[languageCode]; | 78 return this.languageCodeToLanguageInfo_[languageCode]; |
| 79 } | 79 }; |
| 80 | 80 |
| 81 /** | 81 /** |
| 82 * Returns true if the given language code is valid. | 82 * Returns true if the given language code is valid. |
| 83 * @param {string} languageCode Language code (ex. "fr"). | 83 * @param {string} languageCode Language code (ex. "fr"). |
| 84 */ | 84 */ |
| 85 LanguageList.isValidLanguageCode = function(languageCode) { | 85 LanguageList.isValidLanguageCode = function(languageCode) { |
| 86 // Having the display name for the language code means that the | 86 // Having the display name for the language code means that the |
| 87 // language code is valid. | 87 // language code is valid. |
| 88 if (LanguageList.getLanguageInfoFromLanguageCode(languageCode)) { | 88 if (LanguageList.getLanguageInfoFromLanguageCode(languageCode)) { |
| 89 return true; | 89 return true; |
| 90 } | 90 } |
| 91 return false; | 91 return false; |
| 92 } | 92 }; |
| 93 | 93 |
| 94 LanguageList.prototype = { | 94 LanguageList.prototype = { |
| 95 __proto__: DeletableItemList.prototype, | 95 __proto__: DeletableItemList.prototype, |
| 96 | 96 |
| 97 // The list item being dragged. | 97 // The list item being dragged. |
| 98 draggedItem: null, | 98 draggedItem: null, |
| 99 // The drop position information: "below" or "above". | 99 // The drop position information: "below" or "above". |
| 100 dropPos: null, | 100 dropPos: null, |
| 101 // The preference is a CSV string that describes preferred languages | 101 // The preference is a CSV string that describes preferred languages |
| 102 // in Chrome OS. The language list is used for showing the language | 102 // in Chrome OS. The language list is used for showing the language |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 updateDeletable: function() { | 143 updateDeletable: function() { |
| 144 var items = this.items; | 144 var items = this.items; |
| 145 for (var i = 0; i < items.length; ++i) { | 145 for (var i = 0; i < items.length; ++i) { |
| 146 var item = items[i]; | 146 var item = items[i]; |
| 147 var languageCode = item.languageCode; | 147 var languageCode = item.languageCode; |
| 148 var languageOptions = options.LanguageOptions.getInstance(); | 148 var languageOptions = options.LanguageOptions.getInstance(); |
| 149 item.deletable = languageOptions.languageIsDeletable(languageCode); | 149 item.deletable = languageOptions.languageIsDeletable(languageCode); |
| 150 } | 150 } |
| 151 }, | 151 }, |
| 152 | 152 |
| 153 /* | 153 /** |
| 154 * Adds a language to the language list. | 154 * Adds a language to the language list. |
| 155 * @param {string} languageCode language code (ex. "fr"). | 155 * @param {string} languageCode language code (ex. "fr"). |
| 156 */ | 156 */ |
| 157 addLanguage: function(languageCode) { | 157 addLanguage: function(languageCode) { |
| 158 // It shouldn't happen but ignore the language code if it's | 158 // It shouldn't happen but ignore the language code if it's |
| 159 // null/undefined, or already present. | 159 // null/undefined, or already present. |
| 160 if (!languageCode || this.dataModel.indexOf(languageCode) >= 0) { | 160 if (!languageCode || this.dataModel.indexOf(languageCode) >= 0) { |
| 161 return; | 161 return; |
| 162 } | 162 } |
| 163 this.dataModel.push(languageCode); | 163 this.dataModel.push(languageCode); |
| 164 // Select the last item, which is the language added. | 164 // Select the last item, which is the language added. |
| 165 this.selectionModel.selectedIndex = this.dataModel.length - 1; | 165 this.selectionModel.selectedIndex = this.dataModel.length - 1; |
| 166 | 166 |
| 167 this.savePreference_(); | 167 this.savePreference_(); |
| 168 }, | 168 }, |
| 169 | 169 |
| 170 /* | 170 /** |
| 171 * Gets the language codes of the currently listed languages. | 171 * Gets the language codes of the currently listed languages. |
| 172 */ | 172 */ |
| 173 getLanguageCodes: function() { | 173 getLanguageCodes: function() { |
| 174 return this.dataModel.slice(); | 174 return this.dataModel.slice(); |
| 175 }, | 175 }, |
| 176 | 176 |
| 177 /* | 177 /** |
| 178 * Clears the selection | 178 * Clears the selection |
| 179 */ | 179 */ |
| 180 clearSelection: function() { | 180 clearSelection: function() { |
| 181 this.selectionModel.unselectAll(); | 181 this.selectionModel.unselectAll(); |
| 182 }, | 182 }, |
| 183 | 183 |
| 184 /* | 184 /** |
| 185 * Gets the language code of the selected language. | 185 * Gets the language code of the selected language. |
| 186 */ | 186 */ |
| 187 getSelectedLanguageCode: function() { | 187 getSelectedLanguageCode: function() { |
| 188 return this.selectedItem; | 188 return this.selectedItem; |
| 189 }, | 189 }, |
| 190 | 190 |
| 191 /* | 191 /** |
| 192 * Selects the language by the given language code. | 192 * Selects the language by the given language code. |
| 193 * @returns {boolean} True if the operation is successful. | 193 * @return {boolean} True if the operation is successful. |
| 194 */ | 194 */ |
| 195 selectLanguageByCode: function(languageCode) { | 195 selectLanguageByCode: function(languageCode) { |
| 196 var index = this.dataModel.indexOf(languageCode); | 196 var index = this.dataModel.indexOf(languageCode); |
| 197 if (index >= 0) { | 197 if (index >= 0) { |
| 198 this.selectionModel.selectedIndex = index; | 198 this.selectionModel.selectedIndex = index; |
| 199 return true; | 199 return true; |
| 200 } | 200 } |
| 201 return false; | 201 return false; |
| 202 }, | 202 }, |
| 203 | 203 |
| 204 /** @override */ | 204 /** @override */ |
| 205 deleteItemAtIndex: function(index) { | 205 deleteItemAtIndex: function(index) { |
| 206 if (index >= 0) { | 206 if (index >= 0) { |
| 207 this.dataModel.splice(index, 1); | 207 this.dataModel.splice(index, 1); |
| 208 // Once the selected item is removed, there will be no selected item. | 208 // Once the selected item is removed, there will be no selected item. |
| 209 // Select the item pointed by the lead index. | 209 // Select the item pointed by the lead index. |
| 210 index = this.selectionModel.leadIndex; | 210 index = this.selectionModel.leadIndex; |
| 211 this.savePreference_(); | 211 this.savePreference_(); |
| 212 } | 212 } |
| 213 return index; | 213 return index; |
| 214 }, | 214 }, |
| 215 | 215 |
| 216 /* | 216 /** |
| 217 * Computes the target item of drop event. | 217 * Computes the target item of drop event. |
| 218 * @param {Event} e The drop or dragover event. | 218 * @param {Event} e The drop or dragover event. |
| 219 * @private | 219 * @private |
| 220 */ | 220 */ |
| 221 getTargetFromDropEvent_: function(e) { | 221 getTargetFromDropEvent_: function(e) { |
| 222 var target = e.target; | 222 var target = e.target; |
| 223 // e.target may be an inner element of the list item | 223 // e.target may be an inner element of the list item |
| 224 while (target != null && !(target instanceof ListItem)) { | 224 while (target != null && !(target instanceof ListItem)) { |
| 225 target = target.parentNode; | 225 target = target.parentNode; |
| 226 } | 226 } |
| 227 return target; | 227 return target; |
| 228 }, | 228 }, |
| 229 | 229 |
| 230 /* | 230 /** |
| 231 * Handles the dragstart event. | 231 * Handles the dragstart event. |
| 232 * @param {Event} e The dragstart event. | 232 * @param {Event} e The dragstart event. |
| 233 * @private | 233 * @private |
| 234 */ | 234 */ |
| 235 handleDragStart_: function(e) { | 235 handleDragStart_: function(e) { |
| 236 var target = e.target; | 236 var target = e.target; |
| 237 // ListItem should be the only draggable element type in the page, | 237 // ListItem should be the only draggable element type in the page, |
| 238 // but just in case. | 238 // but just in case. |
| 239 if (target instanceof ListItem) { | 239 if (target instanceof ListItem) { |
| 240 this.draggedItem = target; | 240 this.draggedItem = target; |
| 241 e.dataTransfer.effectAllowed = 'move'; | 241 e.dataTransfer.effectAllowed = 'move'; |
| 242 // We need to put some kind of data in the drag or it will be | 242 // We need to put some kind of data in the drag or it will be |
| 243 // ignored. Use the display name in case the user drags to a text | 243 // ignored. Use the display name in case the user drags to a text |
| 244 // field or the desktop. | 244 // field or the desktop. |
| 245 e.dataTransfer.setData('text/plain', target.title); | 245 e.dataTransfer.setData('text/plain', target.title); |
| 246 } | 246 } |
| 247 }, | 247 }, |
| 248 | 248 |
| 249 /* | 249 /** |
| 250 * Handles the dragenter event. | 250 * Handles the dragenter event. |
| 251 * @param {Event} e The dragenter event. | 251 * @param {Event} e The dragenter event. |
| 252 * @private | 252 * @private |
| 253 */ | 253 */ |
| 254 handleDragEnter_: function(e) { | 254 handleDragEnter_: function(e) { |
| 255 e.preventDefault(); | 255 e.preventDefault(); |
| 256 }, | 256 }, |
| 257 | 257 |
| 258 /* | 258 /** |
| 259 * Handles the dragover event. | 259 * Handles the dragover event. |
| 260 * @param {Event} e The dragover event. | 260 * @param {Event} e The dragover event. |
| 261 * @private | 261 * @private |
| 262 */ | 262 */ |
| 263 handleDragOver_: function(e) { | 263 handleDragOver_: function(e) { |
| 264 var dropTarget = this.getTargetFromDropEvent_(e); | 264 var dropTarget = this.getTargetFromDropEvent_(e); |
| 265 // Determines whether the drop target is to accept the drop. | 265 // Determines whether the drop target is to accept the drop. |
| 266 // The drop is only successful on another ListItem. | 266 // The drop is only successful on another ListItem. |
| 267 if (!(dropTarget instanceof ListItem) || | 267 if (!(dropTarget instanceof ListItem) || |
| 268 dropTarget == this.draggedItem) { | 268 dropTarget == this.draggedItem) { |
| 269 this.hideDropMarker_(); | 269 this.hideDropMarker_(); |
| 270 return; | 270 return; |
| 271 } | 271 } |
| 272 // Compute the drop postion. Should we move the dragged item to | 272 // Compute the drop postion. Should we move the dragged item to |
| 273 // below or above the drop target? | 273 // below or above the drop target? |
| 274 var rect = dropTarget.getBoundingClientRect(); | 274 var rect = dropTarget.getBoundingClientRect(); |
| 275 var dy = e.clientY - rect.top; | 275 var dy = e.clientY - rect.top; |
| 276 var yRatio = dy / rect.height; | 276 var yRatio = dy / rect.height; |
| 277 var dropPos = yRatio <= .5 ? 'above' : 'below'; | 277 var dropPos = yRatio <= .5 ? 'above' : 'below'; |
| 278 this.dropPos = dropPos; | 278 this.dropPos = dropPos; |
| 279 this.showDropMarker_(dropTarget, dropPos); | 279 this.showDropMarker_(dropTarget, dropPos); |
| 280 e.preventDefault(); | 280 e.preventDefault(); |
| 281 }, | 281 }, |
| 282 | 282 |
| 283 /* | 283 /** |
| 284 * Handles the drop event. | 284 * Handles the drop event. |
| 285 * @param {Event} e The drop event. | 285 * @param {Event} e The drop event. |
| 286 * @private | 286 * @private |
| 287 */ | 287 */ |
| 288 handleDrop_: function(e) { | 288 handleDrop_: function(e) { |
| 289 var dropTarget = this.getTargetFromDropEvent_(e); | 289 var dropTarget = this.getTargetFromDropEvent_(e); |
| 290 this.hideDropMarker_(); | 290 this.hideDropMarker_(); |
| 291 | 291 |
| 292 // Delete the language from the original position. | 292 // Delete the language from the original position. |
| 293 var languageCode = this.draggedItem.languageCode; | 293 var languageCode = this.draggedItem.languageCode; |
| 294 var originalIndex = this.dataModel.indexOf(languageCode); | 294 var originalIndex = this.dataModel.indexOf(languageCode); |
| 295 this.dataModel.splice(originalIndex, 1); | 295 this.dataModel.splice(originalIndex, 1); |
| 296 // Insert the language to the new position. | 296 // Insert the language to the new position. |
| 297 var newIndex = this.dataModel.indexOf(dropTarget.languageCode); | 297 var newIndex = this.dataModel.indexOf(dropTarget.languageCode); |
| 298 if (this.dropPos == 'below') | 298 if (this.dropPos == 'below') |
| 299 newIndex += 1; | 299 newIndex += 1; |
| 300 this.dataModel.splice(newIndex, 0, languageCode); | 300 this.dataModel.splice(newIndex, 0, languageCode); |
| 301 // The cursor should move to the moved item. | 301 // The cursor should move to the moved item. |
| 302 this.selectionModel.selectedIndex = newIndex; | 302 this.selectionModel.selectedIndex = newIndex; |
| 303 // Save the preference. | 303 // Save the preference. |
| 304 this.savePreference_(); | 304 this.savePreference_(); |
| 305 }, | 305 }, |
| 306 | 306 |
| 307 /* | 307 /** |
| 308 * Handles the dragleave event. | 308 * Handles the dragleave event. |
| 309 * @param {Event} e The dragleave event | 309 * @param {Event} e The dragleave event |
| 310 * @private | 310 * @private |
| 311 */ | 311 */ |
| 312 handleDragLeave_: function(e) { | 312 handleDragLeave_: function(e) { |
| 313 this.hideDropMarker_(); | 313 this.hideDropMarker_(); |
| 314 }, | 314 }, |
| 315 | 315 |
| 316 /* | 316 /** |
| 317 * Shows and positions the marker to indicate the drop target. | 317 * Shows and positions the marker to indicate the drop target. |
| 318 * @param {HTMLElement} target The current target list item of drop | 318 * @param {HTMLElement} target The current target list item of drop |
| 319 * @param {string} pos 'below' or 'above' | 319 * @param {string} pos 'below' or 'above' |
| 320 * @private | 320 * @private |
| 321 */ | 321 */ |
| 322 showDropMarker_: function(target, pos) { | 322 showDropMarker_: function(target, pos) { |
| 323 window.clearTimeout(this.hideDropMarkerTimer_); | 323 window.clearTimeout(this.hideDropMarkerTimer_); |
| 324 var marker = $('language-options-list-dropmarker'); | 324 var marker = $('language-options-list-dropmarker'); |
| 325 var rect = target.getBoundingClientRect(); | 325 var rect = target.getBoundingClientRect(); |
| 326 var markerHeight = 8; | 326 var markerHeight = 8; |
| 327 if (pos == 'above') { | 327 if (pos == 'above') { |
| 328 marker.style.top = (rect.top - markerHeight / 2) + 'px'; | 328 marker.style.top = (rect.top - markerHeight / 2) + 'px'; |
| 329 } else { | 329 } else { |
| 330 marker.style.top = (rect.bottom - markerHeight / 2) + 'px'; | 330 marker.style.top = (rect.bottom - markerHeight / 2) + 'px'; |
| 331 } | 331 } |
| 332 marker.style.width = rect.width + 'px'; | 332 marker.style.width = rect.width + 'px'; |
| 333 marker.style.left = rect.left + 'px'; | 333 marker.style.left = rect.left + 'px'; |
| 334 marker.style.display = 'block'; | 334 marker.style.display = 'block'; |
| 335 }, | 335 }, |
| 336 | 336 |
| 337 /* | 337 /** |
| 338 * Hides the drop marker. | 338 * Hides the drop marker. |
| 339 * @private | 339 * @private |
| 340 */ | 340 */ |
| 341 hideDropMarker_: function() { | 341 hideDropMarker_: function() { |
| 342 // Hide the marker in a timeout to reduce flickering as we move between | 342 // Hide the marker in a timeout to reduce flickering as we move between |
| 343 // valid drop targets. | 343 // valid drop targets. |
| 344 window.clearTimeout(this.hideDropMarkerTimer_); | 344 window.clearTimeout(this.hideDropMarkerTimer_); |
| 345 this.hideDropMarkerTimer_ = window.setTimeout(function() { | 345 this.hideDropMarkerTimer_ = window.setTimeout(function() { |
| 346 $('language-options-list-dropmarker').style.display = ''; | 346 $('language-options-list-dropmarker').style.display = ''; |
| 347 }, 100); | 347 }, 100); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 } | 431 } |
| 432 return filteredLanguageCodes; | 432 return filteredLanguageCodes; |
| 433 }, | 433 }, |
| 434 }; | 434 }; |
| 435 | 435 |
| 436 return { | 436 return { |
| 437 LanguageList: LanguageList, | 437 LanguageList: LanguageList, |
| 438 LanguageListItem: LanguageListItem | 438 LanguageListItem: LanguageListItem |
| 439 }; | 439 }; |
| 440 }); | 440 }); |
| OLD | NEW |