Commit a3efcb6f authored by alexpott's avatar alexpott

Issue #2389515 by nod_: Update ESLint rules

parent 1e08b50f
core/assets/vendor/**/*
core/modules/locale/tests/locale_test.js
core/modules/tour/js/jquery.joyride-2.0.3.js
core/vendor/**/*
sites/**/files/**/*
libraries/**/*
sites/**/libraries/**/*
profiles/**/libraries/**/*
......@@ -14,21 +14,40 @@
"CKEDITOR": true
},
"rules": {
// Errors.
"block-scoped-var": 2,
"brace-style": [2, "stroustrup", {"allowSingleLine": true}],
"comma-style": [2, "last"],
"eqeqeq": [2, "smart"],
"guard-for-in": 2,
"key-spacing": [2, {"beforeColon": false, "afterColon": true}],
"no-implied-eval": 2,
"no-mixed-spaces-and-tabs": 2,
"no-nested-ternary": 2,
"no-reserved-keys": 2,
"no-trailing-spaces": 2,
"no-undef": 2,
"no-undefined": 2,
"no-unused-vars": [2, {"vars": "local", "args": "none"}],
"semi": [2, "always"],
"space-after-keywords": [2, "always", {"checkFunctionKeyword": true}],
"space-before-blocks": [2, "always"],
"space-in-brackets": [2, "never"],
"space-in-parens": [2, "never"],
"spaced-line-comment": [2, "always"],
"strict": 2,
"new-cap": 0,
"quotes": 0,
// Warnings.
"max-nested-callbacks": [1, 3],
// Disabled.
"camelcase": 0,
"no-underscore-dangle": 0,
"no-new": 0,
"consistent-return": 0,
"dot-notation": 0,
"new-cap": 0,
"no-alert": 0,
"no-new": 0,
"no-shadow": 0,
"no-underscore-dangle": 0,
"no-use-before-define": 0,
"consistent-return": 0,
"no-constant-condition": 0
"quotes": 0
}
}
......@@ -44,7 +44,7 @@
$('.use-ajax').once('ajax', function () {
var element_settings = {};
// Clicked links look better with the throbber than the progress bar.
element_settings.progress = { 'type': 'throbber' };
element_settings.progress = {'type': 'throbber'};
// For anchor tags, these will go to the target of the anchor rather
// than the usual location.
......@@ -54,8 +54,8 @@
}
element_settings.accepts = $(this).data('accepts');
element_settings.dialog = $(this).data('dialog-options');
var base = $(this).attr('id');
Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings);
var baseUseAjax = $(this).attr('id');
Drupal.ajax[baseUseAjax] = new Drupal.ajax(baseUseAjax, this, element_settings);
});
// This class means to submit the form to the action using Ajax.
......@@ -71,10 +71,10 @@
// Form buttons use the 'click' event rather than mousedown.
element_settings.event = 'click';
// Clicked form buttons look better with the throbber than the progress bar.
element_settings.progress = { 'type': 'throbber' };
element_settings.progress = {'type': 'throbber'};
var base = $(this).attr('id');
Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings);
var baseUseAjaxSubmit = $(this).attr('id');
Drupal.ajax[baseUseAjaxSubmit] = new Drupal.ajax(baseUseAjaxSubmit, this, element_settings);
});
}
};
......@@ -106,7 +106,7 @@
// Again, we don't have a way to know for sure whether accessing
// xmlhttp.responseText is going to throw an exception. So we'll catch it.
try {
responseText = "\n" + Drupal.t("ResponseText: !responseText", {'!responseText': $.trim(xmlhttp.responseText) });
responseText = "\n" + Drupal.t("ResponseText: !responseText", {'!responseText': $.trim(xmlhttp.responseText)});
}
catch (e) {}
......@@ -721,7 +721,7 @@
/**
* Command to update a form's build ID.
*/
update_build_id: function(ajax, response, status) {
update_build_id: function (ajax, response, status) {
$('input[name="form_build_id"][value="' + response.old + '"]').val(response.new);
},
......
......@@ -71,7 +71,6 @@
* @param {Function} response
*/
function sourceData(request, response) {
/*jshint validthis:true */
var elementId = this.element.attr('id');
if (!(elementId in autocomplete.cache)) {
......@@ -115,8 +114,7 @@
showSuggestions(autocomplete.cache[elementId][term]);
}
else {
var options = $.extend({ success: sourceCallbackHandler, data: { q: term } }, autocomplete.ajax);
/*jshint validthis:true */
var options = $.extend({success: sourceCallbackHandler, data: {q: term}}, autocomplete.ajax);
$.ajax(this.element.attr('data-autocomplete-path'), options);
}
}
......
......@@ -15,7 +15,8 @@
var opts = this.options;
var primaryIndex;
var $buttons;
for (var index = 0, il = opts.buttons.length; index < il; index += 1) {
var index, il;
for (index = 0, il = opts.buttons.length; index < il; index += 1) {
if (opts.buttons[index].primary && opts.buttons[index].primary === true) {
primaryIndex = index;
delete opts.buttons[index].primary;
......
......@@ -3,7 +3,7 @@
"use strict";
// autoResize option will turn off resizable and draggable.
drupalSettings.dialog = $.extend({ autoResize: true, maxHeight: '95%' }, drupalSettings.dialog);
drupalSettings.dialog = $.extend({autoResize: true, maxHeight: '95%'}, drupalSettings.dialog);
/**
* Resets the current options for positioning.
......@@ -61,10 +61,10 @@
$(window).on({
'dialog:aftercreate': function (event, dialog, $element, settings) {
var autoResize = debounce(resetSize, 20);
var eventData = { settings: settings, $element: $element };
var eventData = {settings: settings, $element: $element};
if (settings.autoResize === true || settings.autoResize === 'true') {
$element
.dialog('option', { resizable: false, draggable: false })
.dialog('option', {resizable: false, draggable: false})
.dialog('widget').css('position', 'fixed');
$(window)
.on('resize.dialogResize scroll.dialogResize', eventData, autoResize)
......
......@@ -126,7 +126,7 @@
var displacement = 0;
var horizontal = (edge === 'left' || edge === 'right');
// Get the offset of the element itself.
var placement = $el.offset()[ horizontal ? 'left' : 'top'];
var placement = $el.offset()[horizontal ? 'left' : 'top'];
// Subtract scroll distance from placement to get the distance
// to the edge of the viewport.
placement -= window['scroll' + (horizontal ? 'X' : 'Y')] || document.documentElement['scroll' + (horizontal) ? 'Left' : 'Top'] || 0;
......
/**
* Base framework for Drupal-specific JavaScript, behaviors, and settings.
*/
window.Drupal = { behaviors: {}, locale: {} };
window.Drupal = {behaviors: {}, locale: {}};
// Class indicating that JS is enabled; used for styling purpose.
document.documentElement.className += ' js';
......@@ -90,7 +90,7 @@ if (window.jQuery) {
behaviors[i].attach(context, settings);
}
catch (e) {
errors.push({ behavior: i, error: e });
errors.push({behavior: i, error: e});
}
}
}
......@@ -156,7 +156,7 @@ if (window.jQuery) {
behaviors[i].detach(context, settings, trigger);
}
catch (e) {
errors.push({ behavior: i, error: e });
errors.push({behavior: i, error: e});
}
}
}
......
......@@ -128,6 +128,7 @@
var $context = $(context);
var contextIsForm = $context.is('form');
var $forms = (contextIsForm ? $context : $context.find('form')).once('form-updated');
var formFields;
if ($forms.length) {
// Initialize form behaviors, use $.makeArray to be able to use native
......@@ -135,7 +136,7 @@
$.makeArray($forms).forEach(function (form) {
var events = 'change.formUpdated keypress.formUpdated';
var eventHandler = debounce(function (event) { triggerFormUpdated(event.target); }, 300);
var formFields = fieldsList(form).join(',');
formFields = fieldsList(form).join(',');
form.setAttribute('data-drupal-form-fields', formFields);
$(form).on(events, eventHandler);
......@@ -143,7 +144,7 @@
}
// On ajax requests context is the form element.
if (contextIsForm) {
var formFields = fieldsList(context).join(',');
formFields = fieldsList(context).join(',');
// @todo replace with form.getAttribute() when #1979468 is in.
var currentFields = $(context).attr('data-drupal-form-fields');
// if there has been a change in the fields or their order, trigger
......
......@@ -55,7 +55,7 @@
* AND and OR clauses.
*/
states.Dependent = function (args) {
$.extend(this, { values: {}, oldValue: null }, args);
$.extend(this, {values: {}, oldValue: null}, args);
this.dependees = this.getDependees();
for (var selector in this.dependees) {
......@@ -124,7 +124,7 @@
$(selector).on('state:' + state, {selector: selector, state: state}, stateEventHandler);
// Make sure the event we just bound ourselves to is actually fired.
new states.Trigger({ selector: selector, state: state });
new states.Trigger({selector: selector, state: state});
}
}
},
......@@ -190,7 +190,7 @@
// By adding "trigger: true", we ensure that state changes don't go into
// infinite loops.
this.element.trigger({ type: 'state:' + this.state, value: value, trigger: true });
this.element.trigger({type: 'state:' + this.state, value: value, trigger: true});
}
},
......@@ -355,14 +355,14 @@
var value = valueFn.call(this.element, e);
// Only trigger the event if the value has actually changed.
if (oldValue !== value) {
this.element.trigger({ type: 'state:' + this.state, value: value, oldValue: oldValue });
this.element.trigger({type: 'state:' + this.state, value: value, oldValue: oldValue});
oldValue = value;
}
}, this));
states.postponed.push($.proxy(function () {
// Trigger the event once for initialization purposes.
this.element.trigger({ type: 'state:' + this.state, value: oldValue, oldValue: null });
this.element.trigger({type: 'state:' + this.state, value: oldValue, oldValue: null});
}, this));
}
};
......@@ -436,7 +436,8 @@
this.pristine = this.name = state;
// Normalize the state name.
while (true) {
var process = true;
do {
// Iteratively remove exclamation marks and invert the value.
while (this.name.charAt(0) === '!') {
this.name = this.name.substring(1);
......@@ -448,9 +449,9 @@
this.name = states.State.aliases[this.name];
}
else {
break;
process = false;
}
}
} while (process);
};
/**
......@@ -519,7 +520,7 @@
$(document).on('state:required', function (e) {
if (e.trigger) {
if (e.value) {
var $label = $(e.target).attr({ 'required': 'required', 'aria-required': 'aria-required' }).closest('.form-item, .form-wrapper').find('label');
var $label = $(e.target).attr({'required': 'required', 'aria-required': 'aria-required'}).closest('.form-item, .form-wrapper').find('label');
// Avoids duplicate required markers on initialization.
if (!$label.hasClass('form-required').length) {
$label.addClass('form-required');
......@@ -560,7 +561,15 @@
* Bitwise AND with a third undefined state.
*/
function ternary(a, b) {
return typeof a === 'undefined' ? b : (typeof b === 'undefined' ? a : a && b);
if (typeof a === 'undefined') {
return b;
}
else if (typeof b === 'undefined') {
return a;
}
else {
return a && b;
}
}
/**
......@@ -574,7 +583,12 @@
* Compares two values while ignoring undefined values.
*/
function compare(a, b) {
return (a === b) ? (typeof a === 'undefined' ? a : true) : (typeof a === 'undefined' || typeof b === 'undefined');
if (a === b) {
return typeof a === 'undefined' ? a : true;
}
else {
return typeof a === 'undefined' || typeof b === 'undefined';
}
}
})(jQuery);
......@@ -62,7 +62,7 @@
this.rtl = $(this.table).css('direction') === 'rtl' ? -1 : 1; // Direction of the table.
// Configure the scroll settings.
this.scrollSettings = { amount: 4, interval: 50, trigger: 70 };
this.scrollSettings = {amount: 4, interval: 50, trigger: 70};
this.scrollInterval = null;
this.scrollY = 0;
this.windowHeight = 0;
......@@ -309,7 +309,7 @@
Drupal.tableDrag.prototype.makeDraggable = function (item) {
var self = this;
var $item = $(item);
//Add a class to the title link
// Add a class to the title link
$item.find('td:first a').addClass('menu-item__link');
// Create the handle.
var handle = $('<a href="#" class="tabledrag-handle"><div class="handle">&nbsp;</div></a>').attr('title', Drupal.t('Drag to re-order'));
......@@ -639,7 +639,7 @@
*/
Drupal.tableDrag.prototype.pointerCoords = function (event) {
if (event.pageX || event.pageY) {
return { x: event.pageX, y: event.pageY };
return {x: event.pageX, y: event.pageY};
}
return {
x: event.clientX + document.body.scrollLeft - document.body.clientLeft,
......@@ -654,7 +654,7 @@
Drupal.tableDrag.prototype.getPointerOffset = function (target, event) {
var docPos = $(target).offset();
var pointerPos = this.pointerCoords(event);
return { x: pointerPos.x - docPos.left, y: pointerPos.y - docPos.top };
return {x: pointerPos.x - docPos.left, y: pointerPos.y - docPos.top};
};
/**
......@@ -890,7 +890,13 @@
var b = document.body;
var windowHeight = this.windowHeight = window.innerHeight || (de.clientHeight && de.clientWidth !== 0 ? de.clientHeight : b.offsetHeight);
var scrollY = this.scrollY = (document.all ? (!de.scrollTop ? b.scrollTop : de.scrollTop) : (window.pageYOffset ? window.pageYOffset : window.scrollY));
var scrollY;
if (document.all) {
scrollY = this.scrollY = !de.scrollTop ? b.scrollTop : de.scrollTop;
}
else {
scrollY = this.scrollY = window.pageYOffset ? window.pageYOffset : window.scrollY;
}
var trigger = this.scrollSettings.trigger;
var delta = 0;
......@@ -1120,7 +1126,7 @@
}
}
return { 'min': minIndent, 'max': maxIndent };
return {'min': minIndent, 'max': maxIndent};
};
/**
......
......@@ -18,7 +18,7 @@
// Keep track of the table, which checkbox is checked and alias the settings.
var table = this, checkboxes, lastChecked;
var $table = $(table);
var strings = { 'selectAll': Drupal.t('Select all rows in this table'), 'selectNone': Drupal.t('Deselect all rows in this table') };
var strings = {'selectAll': Drupal.t('Select all rows in this table'), 'selectNone': Drupal.t('Deselect all rows in this table')};
var updateSelectAll = function (state) {
// Update table's select-all checkbox (and sticky header's if available).
$table.prev('table.sticky-header').addBack().find('th.select-all input[type="checkbox"]').each(function () {
......
......@@ -53,7 +53,7 @@
$.ajax({
async: false,
url: Drupal.url(path),
data: { date: dateString },
data: {date: dateString},
dataType: 'json',
success: function (data) {
if (data) {
......
......@@ -37,13 +37,13 @@
// Transform each details into a tab.
$details.each(function () {
var $this = $(this);
var $that = $(this);
var vertical_tab = new Drupal.verticalTab({
title: $this.find('> summary').text(),
details: $this
title: $that.find('> summary').text(),
details: $that
});
tab_list.append(vertical_tab.item);
$this
$that
.removeClass('collapsed')
// prop() can't be used on browsers not supporting details element,
// the style won't apply to them if prop() is used.
......@@ -51,7 +51,7 @@
.addClass('vertical-tabs-pane')
.data('verticalTab', vertical_tab);
if (this.id === focusID) {
tab_focus = $this;
tab_focus = $that;
}
});
......
......@@ -11,14 +11,14 @@
attach: function (context) {
var $context = $(context);
$context.find('.block-content-form-revision-information').drupalSetSummary(function (context) {
var $context = $(context);
var revisionCheckbox = $context.find('.form-item-revision input');
var $revisionContext = $(context);
var revisionCheckbox = $revisionContext.find('.form-item-revision input');
// Return 'New revision' if the 'Create new revision' checkbox is checked,
// or if the checkbox doesn't exist, but the revision log does. For users
// without the "Administer content" permission the checkbox won't appear,
// but the revision log will if the content type is set to auto-revision.
if (revisionCheckbox.is(':checked') || (!revisionCheckbox.length && $context.find('.form-item-revision-log textarea').length)) {
if (revisionCheckbox.is(':checked') || (!revisionCheckbox.length && $revisionContext.find('.form-item-revision-log textarea').length)) {
return Drupal.t('New revision');
}
......@@ -26,15 +26,15 @@
});
$context.find('fieldset.block-content-translation-options').drupalSetSummary(function (context) {
var $context = $(context);
var $translationContext = $(context);
var translate;
var $checkbox = $context.find('.form-item-translation-translate input');
var $checkbox = $translationContext.find('.form-item-translation-translate input');
if ($checkbox.size()) {
translate = $checkbox.is(':checked') ? Drupal.t('Needs to be updated') : Drupal.t('Does not need to be updated');
}
else {
$checkbox = $context.find('.form-item-translation-retranslate input');
$checkbox = $translationContext.find('.form-item-translation-retranslate input');
translate = $checkbox.is(':checked') ? Drupal.t('Flag other translations as outdated') : Drupal.t('Do not flag other translations as outdated');
}
......
......@@ -94,7 +94,7 @@
* A callback to invoke after the button group naming modal dialog has been
* closed.
*/
registerButtonMove: function(view, $button, callback) {
registerButtonMove: function (view, $button, callback) {
var $group = $button.closest('.ckeditor-toolbar-group');
// If dropped in a placeholder button group, the user must name it.
......@@ -312,7 +312,7 @@
});
// Announce to the user that a modal dialog is open.
var text = Drupal.t('Editing the name of the new button group in a dialog.');
if ($group.attr('data-drupal-ckeditor-toolbar-group-name') !== undefined) {
if (typeof $group.attr('data-drupal-ckeditor-toolbar-group-name') !== 'undefined') {
text = Drupal.t('Editing the name of the "@groupName" button group in a dialog.', {
'@groupName': $group.attr('data-drupal-ckeditor-toolbar-group-name')
});
......
......@@ -23,7 +23,7 @@
}
var output = '';
output += Drupal.t('Uploads enabled, max size: @size @dimensions', { '@size': maxFileSize, '@dimensions': maxDimensions });
output += Drupal.t('Uploads enabled, max size: @size @dimensions', {'@size': maxFileSize, '@dimensions': maxDimensions});
if ($scheme.length) {
output += '<br />' + $scheme.attr('data-label');
}
......
......@@ -166,7 +166,7 @@
selector: '.ckeditor-dialog-loading-link',
url: url,
event: 'ckeditor-internal.ckeditor',
progress: { 'type': 'throbber' },
progress: {'type': 'throbber'},
submit: {
editor_object: existingValues
}
......@@ -177,7 +177,7 @@
// After a short delay, show "Loading…" message.
window.setTimeout(function () {
$content.find('span').animate({ top: '0px' });
$content.find('span').animate({top: '0px'});
}, 1000);
// Store the save callback to be executed when this dialog is closed.
......@@ -187,7 +187,7 @@
// Respond to new dialogs that are opened by CKEditor, closing the AJAX loader.
$(window).on('dialog:beforecreate', function (e, dialog, $element, settings) {
$('.ckeditor-dialog-loading').animate({ top: '-40px' }, function () {
$('.ckeditor-dialog-loading').animate({top: '-40px'}, function () {
$(this).remove();
});
});
......
......@@ -31,7 +31,7 @@
if (!_.isEqual(previousStylesSet, stylesSet)) {
previousStylesSet = stylesSet;
$ckeditorActiveToolbar.trigger('CKEditorPluginSettingsChanged', [
{ stylesSet: stylesSet }
{stylesSet: stylesSet}
]);
}
});
......@@ -81,7 +81,7 @@
// Build the data structure CKEditor's stylescombo plugin expects.
// @see http://docs.cksource.com/CKEditor_3.x/Developers_Guide/Styles
stylesSet.push({
attributes: { class: classes.join(' ') },
attributes: {'class': classes.join(' ')},
element: element,
name: label
});
......@@ -103,7 +103,7 @@
}
else {
var count = $.trim(styles).split("\n").length;
return Drupal.t('@count styles configured', { '@count': count});
return Drupal.t('@count styles configured', {'@count': count});
}
});
}
......
......@@ -180,7 +180,7 @@
editor.addCommand('editdrupalimage', {
allowedContent: 'img[alt,!src,width,height,!data-entity-type,!data-entity-uuid]',
requiredContent: 'img[alt,src,width,height,data-entity-type,data-entity-uuid]',
modes: { wysiwyg: 1 },
modes: {wysiwyg: 1},
canUndo: true,
exec: function (editor, data) {
var dialogSettings = {
......
......@@ -102,20 +102,21 @@
var attrs = element.attributes;
var retElement = element;
var caption;
// We won't need the attributes during editing: we'll use widget.data
// to store them (except the caption, which is stored in the DOM).
if (captionFilterEnabled) {
var caption = attrs['data-caption'];
caption = attrs['data-caption'];
delete attrs['data-caption'];
}
if (alignFilterEnabled) {
data.align = attrs['data-align'];
delete attrs['data-align'];
}
data['data-entity-type' ] = attrs['data-entity-type'];
data['data-entity-type'] = attrs['data-entity-type'];
delete attrs['data-entity-type'];
data['data-entity-uuid' ] = attrs['data-entity-uuid'];
data['data-entity-uuid'] = attrs['data-entity-uuid'];
delete attrs['data-entity-uuid'];
if (captionFilterEnabled) {
......
......@@ -13,7 +13,7 @@
editor.addCommand('drupallink', {
allowedContent: 'a[!href,target]',
requiredContent: 'a[href]',
modes: { wysiwyg: 1 },
modes: {wysiwyg: 1},
canUndo: true,
exec: function (editor) {
var linkElement = getSelectedLink(editor);
......@@ -26,8 +26,8 @@
// Populate an array with the link's current attributes.
var attribute = null, attributeName;
for (var key = 0; key < linkDOMElement.attributes.length; key++) {
attribute = linkDOMElement.attributes.item(key);
for (var attrIndex = 0; attrIndex < linkDOMElement.attributes.length; attrIndex++) {
attribute = linkDOMElement.attributes.item(attrIndex);
attributeName = attribute.nodeName.toLowerCase();
// Don't consider data-cke-saved- attributes; they're just there to
// work around browser quirks.
......@@ -64,7 +64,7 @@
}
// Create the new link by applying a style to the new text.
var style = new CKEDITOR.style({ element: 'a', attributes: returnValues.attributes });
var style = new CKEDITOR.style({element: 'a', attributes: returnValues.attributes});
style.type = CKEDITOR.STYLE_INLINE;
style.applyToRange(range);
range.select();
......@@ -74,17 +74,17 @@
}
// Update the link properties.
else if (linkElement) {
for (var key in returnValues.attributes) {
if (returnValues.attributes.hasOwnProperty(key)) {
for (var attrName in returnValues.attributes) {
if (returnValues.attributes.hasOwnProperty(attrName)) {
// Update the property if a value is specified.
if (returnValues.attributes[key].length > 0) {
var value = returnValues.attributes[key];
linkElement.data('cke-saved-' + key, value);
linkElement.setAttribute(key, value);
if (returnValues.attributes[attrName].length > 0) {
var value = returnValues.attributes[attrName];
linkElement.data('cke-saved-' + attrName, value);
linkElement.setAttribute(attrName, value);
}
// Delete the property if set to an empty string.
else {
linkElement.removeAttribute(key);
linkElement.removeAttribute(attrName);
}
}
}
......@@ -111,7 +111,7 @@
allowedContent: 'a[!href]',
requiredContent: 'a[href]',
exec: function (editor) {
var style = new CKEDITOR.style({ element: 'a', type: CKEDITOR.STYLE_INLINE, alwaysRemoveElement: 1 });
var style = new CKEDITOR.style({element: 'a', type: CKEDITOR.STYLE_INLINE, alwaysRemoveElement: 1});
editor.removeStyle(style);
},
refresh: function (editor, path) {
......@@ -125,7 +125,8 @@
}
});
editor.setKeystroke(CKEDITOR.CTRL + 75 /*K*/, 'drupallink');
// CTRL + K.
editor.setKeystroke(CKEDITOR.CTRL + 75, 'drupallink');
// Add buttons for link and unlink.
if (editor.ui.addButton) {
......@@ -184,7 +185,7 @@
var menu = {};
if (anchor.getAttribute('href') && anchor.getChildCount()) {
menu = { link: CKEDITOR.TRISTATE_OFF, unlink: CKEDITOR.TRISTATE_OFF };
menu = {link: CKEDITOR.TRISTATE_OFF, unlink: CKEDITOR.TRISTATE_OFF};
}
return menu;
});
......
......@@ -242,8 +242,8 @@
// Remove duplicate buttons.
existingButtons = _.unique(existingButtons);
// Prepare the active toolbar and available-button toolbars.
for (i = 0; i < existingButtons.length; i++) {
var button = existingButtons[i];
for (var n = 0; n < existingButtons.length; n++) {
var button = existingButtons[n];
var feature = this.getFeatureForButton(button);