Identify elements by class rather than ID: Zendesk will replace IDs. ()

https://github.com/zendesk/demo_apps/blob/master/Bestpractices.md
This commit is contained in:
bfcamara 2014-10-07 11:09:39 +01:00
Родитель fa3f22f082
Коммит 282938bb3e
7 изменённых файлов: 87 добавлений и 87 удалений

28
app.css
Просмотреть файл

@ -47,15 +47,15 @@ hr.split {
margin-bottom: 10px;
}
#linkModal .inputVsoProject {
.linkModal .inputVsoProject {
width: 330px;
}
#linkModal .results {
.linkModal .results {
margin-top: 15px;
}
#linkModal #inputVsoWorkItemId {
.linkModal .inputVsoWorkItemId {
width: calc(100% - 174px);
box-sizing: border-box;
height: 30px;
@ -63,31 +63,31 @@ hr.split {
margin-left: 10px;
}
#newWorkItemModal {
.newWorkItemModal {
width: 750px;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
margin: 0;
}
#newWorkItemModal .modal-body {
.newWorkItemModal .modal-body {
max-height: 550px;
}
#newWorkItemModal #description {
.newWorkItemModal .description {
height: 100px;
}
#newWorkItemModal #summary {
.newWorkItemModal .summary {
width: 530px;
}
#newWorkItemModal .attachments ul {
.newWorkItemModal .attachments ul {
margin: 0px;
}
#newWorkItemModal .copyDescription {
.newWorkItemModal .copyDescription {
display: block;
}
@ -199,18 +199,18 @@ hr.split {
padding-bottom: 10px;
}
#notifyModal textarea {
.notifyModal textarea {
width: 100%;
box-sizing: border-box;
height: 100px;
}
#notifyModal .copyLastComment {
.notifyModal .copyLastComment {
display: block;
margin-bottom: 20px;
}
#notifyModal label {
.notifyModal label {
margin-bottom: 0.5em;
}
@ -222,10 +222,10 @@ hr.split {
width: 30px;
}
#settings {
.settings {
table-layout: fixed;
}
#settings tbody tr td:first-of-type {
.settings tbody tr td:first-of-type {
word-wrap: break-word;
}

108
app.js
Просмотреть файл

@ -55,10 +55,10 @@
//New workitem dialog
'click .newWorkItem': 'onNewWorkItemClick',
'change #newWorkItemModal .inputVsoProject': 'onNewVsoProjectChange',
'change #newWorkItemModal #type': 'onNewVsoWorkItemTypeChange',
'click #newWorkItemModal .copyDescription': 'onNewCopyDescriptionClick',
'click #newWorkItemModal .accept': 'onNewWorkItemAcceptClick',
'change .newWorkItemModal .inputVsoProject': 'onNewVsoProjectChange',
'change .newWorkItemModal .type': 'onNewVsoWorkItemTypeChange',
'click .newWorkItemModal .copyDescription': 'onNewCopyDescriptionClick',
'click .newWorkItemModal .accept': 'onNewWorkItemAcceptClick',
//Admin side pane
'click .cog': 'onCogClick',
@ -70,23 +70,23 @@
//Link work item dialog
'click .link': 'onLinkClick',
'change #linkModal #project': 'onLinkVsoProjectChange',
'click #linkModal button.query': 'onLinkQueryButtonClick',
'click #linkModal button.accept': 'onLinkAcceptClick',
'click #linkModal button.search': 'onLinkSearchClick',
'click #linkModal a.workItemResult': 'onLinkResultClick',
'change .linkModal .project': 'onLinkVsoProjectChange',
'click .linkModal button.queryBtn': 'onLinkQueryButtonClick',
'click .linkModal button.accept': 'onLinkAcceptClick',
'click .linkModal button.search': 'onLinkSearchClick',
'click .linkModal a.workItemResult': 'onLinkResultClick',
//Unlink click
'click .unlink': 'onUnlinkClick',
'click #unlinkModal .accept': 'onUnlinkAcceptClick',
'click .unlinkModal .accept': 'onUnlinkAcceptClick',
//Notify dialog
'click .notify': 'onNotifyClick',
'click #notifyModal .accept': 'onNotifyAcceptClick',
'click #notifyModal .copyLastComment': 'onCopyLastCommentClick',
'click .notifyModal .accept': 'onNotifyAcceptClick',
'click .notifyModal .copyLastComment': 'onCopyLastCommentClick',
//Refresh work items
'click #refreshWorkItemsLink': 'onRefreshWorkItemClick',
'click .refreshWorkItemsLink': 'onRefreshWorkItemClick',
//Login
'click .user,.user-link': 'onUserIconClick',
@ -307,16 +307,16 @@
// UI
onNewWorkItemClick: function () {
var $modal = this.$('#newWorkItemModal').modal();
var $modal = this.$('.newWorkItemModal').modal();
$modal.find('.modal-body').html(this.renderTemplate('loading'));
this.ajax('getComments').done(function (data) {
var attachments = _.flatten(_.map(data.comments, function (comment) {
return comment.attachments || [];
}), true);
$modal.find('.modal-body').html(this.renderTemplate('new', { attachments: attachments }));
$modal.find('#summary').val(this.ticket().subject());
$modal.find('.summary').val(this.ticket().subject());
var projectCombo = $modal.find('#project');
var projectCombo = $modal.find('.project');
this.fillComboWithProjects(projectCombo);
projectCombo.change();
@ -324,15 +324,15 @@
},
onNewVsoProjectChange: function () {
var $modal = this.$('#newWorkItemModal');
var projId = $modal.find('#project').val();
var $modal = this.$('.newWorkItemModal');
var projId = $modal.find('.project').val();
this.showSpinnerInModal($modal);
this.loadProjectWorkItemTypes(projId)
.done(function () {
this.drawTypesList($modal.find('#type'), projId);
$modal.find('#type').change();
this.drawTypesList($modal.find('.type'), projId);
$modal.find('.type').change();
this.hideSpinnerInModal($modal);
}.bind(this))
.fail(function (jqXHR) {
@ -341,9 +341,9 @@
},
onNewVsoWorkItemTypeChange: function () {
var $modal = this.$('#newWorkItemModal');
var project = this.getProjectById($modal.find('#project').val());
var workItemType = this.getWorkItemTypeByName(project, $modal.find('#type').val());
var $modal = this.$('.newWorkItemModal');
var project = this.getProjectById($modal.find('.project').val());
var workItemType = this.getWorkItemTypeByName(project, $modal.find('.type').val());
//Check if we have severity
if (this.hasFieldDefined(workItemType, "Microsoft.VSTS.Common.Severity")) {
@ -355,25 +355,25 @@
onNewCopyDescriptionClick: function (event) {
event.preventDefault();
this.$('#newWorkItemModal #description').val(this.ticket().description());
this.$('.newWorkItemModal .description').val(this.ticket().description());
},
onNewWorkItemAcceptClick: function () {
var $modal = this.$('#newWorkItemModal').modal();
var $modal = this.$('.newWorkItemModal').modal();
//check project
var proj = this.getProjectById($modal.find('#project').val());
var proj = this.getProjectById($modal.find('.project').val());
if (!proj) { return this.showErrorInModal($modal, this.I18n.t("modals.new.errProjRequired")); }
//check work item type
var workItemType = this.getWorkItemTypeByName(proj, $modal.find('#type').val());
var workItemType = this.getWorkItemTypeByName(proj, $modal.find('.type').val());
if (!workItemType) { return this.showErrorInModal($modal, this.I18n.t("modals.new.errWorkItemTypeRequired")); }
//check summary
var summary = $modal.find("#summary").val();
var summary = $modal.find(".summary").val();
if (!summary) { return this.showErrorInModal($modal, this.I18n.t("modals.new.errSummaryRequired")); }
var description = $modal.find("#description").val();
var description = $modal.find(".description").val();
var attachments = [];
$modal.find('.attachments input').each(function () { if (this.checked) { attachments.push(this.value); } });
@ -382,8 +382,8 @@
this.buildPatchToAddWorkItemField("System.Title", summary),
this.buildPatchToAddWorkItemField("System.Description", description));
if (this.hasFieldDefined(workItemType, "Microsoft.VSTS.Common.Severity") && $modal.find('#severity').val()) {
operations.push(this.buildPatchToAddWorkItemField("Microsoft.VSTS.Common.Severity", $modal.find('#severity').val()));
if (this.hasFieldDefined(workItemType, "Microsoft.VSTS.Common.Severity") && $modal.find('.severity').val()) {
operations.push(this.buildPatchToAddWorkItemField("Microsoft.VSTS.Common.Severity", $modal.find('.severity').val()));
}
if (this.hasFieldDefined(workItemType, "Microsoft.VSTS.TCM.ReproSteps")) {
@ -452,7 +452,7 @@
},
onShowDetailsClick: function (event) {
var $modal = this.$('#detailsModal').modal();
var $modal = this.$('.detailsModal').modal();
$modal.find('.modal-header h3').html(this.I18n.t('modals.details.loading'));
$modal.find('.modal-body').html(this.renderTemplate('loading'));
var id = this.$(event.target).closest('.workItem').attr('data-id');
@ -463,38 +463,38 @@
},
onLinkClick: function () {
var $modal = this.$('#linkModal').modal();
var $modal = this.$('.linkModal').modal();
$modal.find('.modal-footer button').removeAttr('disabled');
$modal.find('.modal-body').html(this.renderTemplate('link'));
$modal.find("button.search").show();
var projectCombo = $modal.find('#project');
var projectCombo = $modal.find('.project');
this.fillComboWithProjects(projectCombo);
projectCombo.change();
},
onLinkSearchClick: function () {
var $modal = this.$('#linkModal');
var $modal = this.$('.linkModal');
$modal.find(".search-section").show();
},
onLinkResultClick: function (event) {
event.preventDefault();
var $modal = this.$('#linkModal');
var $modal = this.$('.linkModal');
var id = this.$(event.target).closest('.workItemResult').attr('data-id');
$modal.find('#inputVsoWorkItemId').val(id);
$modal.find('.inputVsoWorkItemId').val(id);
$modal.find('.search-section').hide();
},
onLinkVsoProjectChange: function () {
var $modal = this.$('#linkModal');
var projId = $modal.find('#project').val();
var $modal = this.$('.linkModal');
var projId = $modal.find('.project').val();
this.showSpinnerInModal($modal);
this.loadProjectWorkItemQueries(projId)
.done(function () {
this.drawQueriesList($modal.find('#query'), projId);
this.drawQueriesList($modal.find('.query'), projId);
this.hideSpinnerInModal($modal);
}.bind(this))
.fail(function (jqXHR) {
@ -503,9 +503,9 @@
},
onLinkQueryButtonClick: function () {
var $modal = this.$('#linkModal');
var projId = $modal.find('#project').val();
var queryId = $modal.find('#query').val();
var $modal = this.$('.linkModal');
var projId = $modal.find('.project').val();
var queryId = $modal.find('.query').val();
var _drawQueryResults = function (results, countQueryItemsResult) {
var workItems = _.map(results, function (workItem) {
@ -543,8 +543,8 @@
},
onLinkAcceptClick: function (event) {
var $modal = this.$('#linkModal');
var workItemId = $modal.find('#inputVsoWorkItemId').val();
var $modal = this.$('.linkModal');
var workItemId = $modal.find('.inputVsoWorkItemId').val();
if (!/^([0-9]+)$/.test(workItemId)) {
return this.showErrorInModal($modal, this.I18n.t('modals.link.errWorkItemIdNaN'));
@ -601,7 +601,7 @@
onUnlinkClick: function (event) {
var id = this.$(event.target).closest('.workItem').attr('data-id');
var workItem = this.getWorkItemById(id);
var $modal = this.$('#unlinkModal').modal();
var $modal = this.$('.unlinkModal').modal();
$modal.find('.modal-body').html(this.renderTemplate('unlink'));
$modal.find('.modal-footer button').removeAttr('disabled');
$modal.find('.modal-body .confirm').html(this.I18n.t('modals.unlink.text', { name: workItem.title }));
@ -610,7 +610,7 @@
onUnlinkAcceptClick: function (event) {
event.preventDefault();
var $modal = this.$(event.target).closest('#unlinkModal');
var $modal = this.$(event.target).closest('.unlinkModal');
this.showSpinnerInModal($modal);
var workItemId = $modal.attr('data-id');
@ -656,7 +656,7 @@
},
onNotifyClick: function () {
var $modal = this.$('#notifyModal');
var $modal = this.$('.notifyModal');
$modal.find('.modal-body').html(this.renderTemplate('loading'));
$modal.modal();
@ -671,7 +671,7 @@
},
onNotifyAcceptClick: function () {
var $modal = this.$('#notifyModal');
var $modal = this.$('.notifyModal');
var text = $modal.find('textarea').val();
if (!text) { return this.showErrorInModal($modal, this.I18n.t("modals.notify.errCommentRequired")); }
@ -707,20 +707,20 @@
onCopyLastCommentClick: function (event) {
event.preventDefault();
this.$('#notifyModal').find('textarea').val(this.lastComment);
this.$('.notifyModal').find('textarea').val(this.lastComment);
},
onRefreshWorkItemClick: function (event) {
event.preventDefault();
this.$('workItemsError').hide();
this.$('.workItemsError').hide();
this.switchTo('loading');
this.getLinkedVsoWorkItems();
},
onLoginClick: function (event) {
event.preventDefault();
var vso_username = this.$('#vso_username').val();
var vso_password = this.$('#vso_password').val();
var vso_username = this.$('.vso_username').val();
var vso_password = this.$('.vso_password').val();
if (!vso_username || !vso_password) {
this.$(".login-form").find('.errors').text(this.I18n.t("login.errRequiredFields")).show();
@ -757,7 +757,7 @@
if (!err) {
this.drawWorkItems();
} else {
this.$('#workItemsError').show();
this.$('.workItemsError').show();
}
} else {
this.$('.cog').toggle(false);

Просмотреть файл

@ -4,7 +4,7 @@
<div class="control-group">
<label class="control-label" for="inputVsoWorkItemId">Work item</label>
<div class="controls">
<input type="text" class='input-mini' id="inputVsoWorkItemId" required="" pattern='[0-9]*'>
<input type="text" class='inputVsoWorkItemId input-mini' required="" pattern='[0-9]*'>
<button type='button' class='btn btn-primary btn-small accept' style='display:inline;'>{{t "modals.link.accept"}}</button>
<button type='button' class='btn btn-mini search' style='display:inline;'>{{t "modals.link.search"}}</button>
<span class="help-block">{{t "modals.link.help"}}</span>
@ -19,12 +19,12 @@
<fieldset>
<legend>{{t "modals.link.searchLegend"}}</legend>
<label>{{t "modals.link.projectLabel"}}</label>
<select id='project' class='input-medium'>
<select class='project input-medium'>
</select>
<label>{{t "modals.link.queryLabel"}}</label>
<select id='query' class='input-medium'>
<select class='query input-medium'>
</select>
<button type="button" class="btn query">{{t "modals.link.query"}}</button>
<button type="button" class="btn queryBtn">{{t "modals.link.query"}}</button>
</fieldset>
<div class='results'>
</div>

Просмотреть файл

@ -15,13 +15,13 @@
<div class="control-group">
<label class="control-label" for="vso_username">{{t "login.username"}}</label>
<div class="controls">
<input type="text" id="vso_username" class="input">
<input type="text" id="vso_username" class="vso_username input">
</div>
</div>
<div class="control-group">
<label class="control-label" for="vso_password">{{t "login.password"}}</label>
<div class="controls">
<input type="password" id="vso_password" class="input">
<input type="password" id="vso_password" class="vso_password input">
</div>
</div>
<div class="control-group">

Просмотреть файл

@ -14,16 +14,16 @@
<div class='workItems'>
<div id='workItemsError' class="alert alert-error" style="display:none">
<div class="workItemsError alert alert-error" style="display:none">
<strong>{{t "errorOoops"}}</strong> {{t "errorLoadingWorkItems"}}
<a href="#" id="refreshWorkItemsLink" title="Refresh">
<a href="#" class="refreshWorkItemsLink" title="Refresh">
<i class="icon-refresh"></i>
</a>
</div>
</div>
<div id="detailsModal" class='modal hide fade' tabindex='-1' role='dialog'>
<div class='detailsModal modal hide fade' tabindex='-1' role='dialog'>
<div class='modal-header'>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h3>{{t "modals.details.loading"}}</h3>
@ -35,7 +35,7 @@
</div>
</div>
<div id="unlinkModal" class='modal hide fade' tabindex='-1' role='dialog'>
<div class='unlinkModal modal hide fade' tabindex='-1' role='dialog'>
<div class='modal-header'>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h3>{{t "modals.unlink.title"}}</h3>
@ -48,7 +48,7 @@
</div>
</div>
<div id="linkModal" class='modal hide fade' tabindex='-1' role='dialog'>
<div class='linkModal modal hide fade' tabindex='-1' role='dialog'>
<div class='modal-header'>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h3>{{t "modals.link.title"}}</h3>
@ -62,7 +62,7 @@
</div>
</div>
<div id="newWorkItemModal" class='modal hide fade' tabindex='-1' role='dialog'>
<div class='newWorkItemModal modal hide fade' tabindex='-1' role='dialog'>
<div class='modal-header'>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h3>{{t "modals.new.title"}}</h3>
@ -75,7 +75,7 @@
</div>
</div>
<div id="notifyModal" class='modal hide fade' tabindex='-1' role='dialog'>
<div class='notifyModal modal hide fade' tabindex='-1' role='dialog'>
<div class='modal-header'>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h3>{{t "modals.notify.title"}}</h3>

Просмотреть файл

@ -9,7 +9,7 @@
<div class='control-group'>
<label class='control-label' for='project'>{{t "modals.new.fields.project"}}:</label>
<div class='controls'>
<select id='project' class='input-xlarge inputVsoProject'>
<select id='project' class='project input-xlarge inputVsoProject'>
</select>
</div>
</div>
@ -17,11 +17,11 @@
<div class='control-group'>
<label class='control-label' for='type'>{{t "modals.new.fields.type"}}</label>
<div class='controls'>
<select id='type' class='input-xlarge'></select>
<select id='type' class='type input-xlarge'></select>
</div>
</div>
<div class='control-group severityInput'>
<label class='control-label' for='type'>{{t "modals.new.fields.severity"}}</label>
<label class='control-label' for='severity'>{{t "modals.new.fields.severity"}}</label>
<div class='controls'>
<select id='severity' class='input-xlarge'>
<option value='1 - Critical'>1 - Critical</option>
@ -35,14 +35,14 @@
<div class='control-group'>
<label class='control-label' for='summary'>{{t "modals.new.fields.summary"}}</label>
<div class='controls'>
<input type='text' id='summary' class='input-xxlarge'>
<input type='text' id='summary' class='summary input-xxlarge'>
</div>
</div>
<div class='control-group'>
<label class='control-label' for='description'>{{t "modals.new.fields.description"}}</label>
<div class='controls'>
<textarea id='description' class='input-xxlarge'></textarea>
<textarea id='description' class='description input-xxlarge'></textarea>
<a href="#" class="copyDescription">{{t "modals.new.copyDescription"}}</a>
</div>
</div>

Просмотреть файл

@ -1,4 +1,4 @@
<table id="settings" class='table'>
<table class='settings table'>
<thead>
<tr>
<th></th>