I've written a web application that is a replica of the iPhone's notes app. It turned out quite well, you can do everything you can on the iPhone's app except for sharing and sending it via texts etc. I've been sitting here trying to figure out a way to DRY this up, so far I think I've done a pretty good job in doing so.
However, there is one thing that annoys me a bit and I haven't been able to come up with a better solution then what I have now. It's these parts:
ctrl.functions.hideBtn('#done-btn');
ctrl.functions.hideBtn('#all-notes');
ctrl.functions.hideBtn('#edit');
ctrl.functions.showBtn('#add-note');
I repeat myself a lot by doing these things.. And I do them like 4-5 times throughout the code whenever the view needs to change. What I tried to do in the showBtn
and hideBtn
is sending in an array containing all the buttons
that needed to be manipulated and then using a loop in the respective functions to loop over that array and hide/show them. This, however, didn't work for some reason and after thinking about it it didn't really feel like a better solution, it just got more messy.
How can I remove this repetitiveness?
Also, feel free to leave feedback on anything else that can be improved. I'll leave the full code down below as well as two pictures of what it looks like for those who are interested.
$(document).ready(function() {
var model = {
ajaxURLs: {
addNote: '../includes/notepages/addnote.php',
editNote: '../includes/notepages/editnote.php',
deleteNote: '../includes/notepages/deletenote.php',
allNotes: '../includes/notepages/allnotes.php',
},
wrappers: {
topBar: $('#top-bar'),
content: $('#content-wrapper'),
timestamp: undefined
}
}
var ctrl = {
bindElements: (function() {
model.wrappers.topBar.on('click', '#add-note', function() {
var promise = ctrl.functions.restCall(model.ajaxURLs.addNote);
promise.done(function(data) {
$('#add-note').hide();
ctrl.functions.showBtn('#all-notes');
ctrl.functions.showBtn('#done-btn');
ctrl.functions.appendData(data);
});
});
model.wrappers.topBar.on('click', '#all-notes', function() {
var allNotesPromise = ctrl.functions.restCall(model.ajaxURLs.allNotes);
allNotesPromise.done(function(data) {
ctrl.functions.hideBtn('#done-btn');
ctrl.functions.hideBtn('#all-notes');
ctrl.functions.hideBtn('#edit');
ctrl.functions.showBtn('#add-note');
ctrl.functions.appendData(data);
});
});
model.wrappers.topBar.on('click', '#done-btn', function() {
var textarea = $('#notes-area');
if (textarea.val().length === 0) {
return false;
}
var allNotesPromise = ctrl.functions.restCall(model.ajaxURLs.allNotes);
allNotesPromise.done(function(data) {
ctrl.functions.hideBtn('#done-btn');
ctrl.functions.hideBtn('#all-notes');
ctrl.functions.showBtn('#add-note');
ctrl.functions.appendData(data);
});
});
model.wrappers.topBar.on('click', '#edit', function() {
$('#notes-area').attr('disabled', false);
ctrl.functions.hideBtn('#edit');
ctrl.functions.showBtn('#done-btn');
});
model.wrappers.content.on('click', '#notes-list li', function() {
model.timestamp = $(this).children('.timestamp').html();
var editPromise = ctrl.functions.restCall(model.ajaxURLs.editNote, 'timestamp', model.timestamp);
editPromise.done(function(data) {
ctrl.functions.appendData(data);
$('#timestamp-input').attr('value', model.timestamp);
});
ctrl.functions.hideBtn('#add-note');
ctrl.functions.showBtn('#all-notes');
ctrl.functions.showBtn('#edit');
});
model.wrappers.content.on('click', '#trashcan', function() {
var deletePromise = ctrl.functions.restCall(model.ajaxURLs.deleteNote, 'timestamp', model.timestamp);
deletePromise.done(function(data) {
var allNotesPromise = ctrl.functions.restCall(model.ajaxURLs.allNotes);
allNotesPromise.done(function(data) {
ctrl.functions.appendData(data);
});
ctrl.functions.hideBtn('#edit');
ctrl.functions.showBtn('#add-note');
});
});
}()),
functions: {
init: function() {
var promise = ctrl.functions.restCall('../includes/notepages/allnotes.php');
promise.done(function(data) {
ctrl.functions.appendData(data);
});
},
showBtn: function(id) {
$(id).show();
},
hideBtn: function(id) {
$(id).hide();
},
restCall: function(url, dataVar, data) {
return $.ajax({
url: url,
method: 'post',
data: '' + dataVar + '=' + data
});
},
appendData: function(data) {
model.wrappers.content.children().remove();
model.wrappers.content.append(data).hide().fadeIn();
}
}
}
window.onload = ctrl.functions.init;
});
This is the static HTML of the page, containing all the buttons (which is the main focus of this question):
<main class="full-height">
<div id="top-bar">
<button id="all-notes" class="btn brown-btn hide">Alla anteckningar</button>
<button id="add-note" class="btn brown-btn">Ny</button>
<input type="submit" form="note-text" value="Klar" id="done-btn" class="btn brown-btn hide">
<button id="edit" class="btn brown-btn hide">Ändra</button>
</div>
<div id="content-wrapper" class="full-height"></div>
</main>
This is a template file that holds the markup for the "note block" look and also a text area where you write the note:
<div class="vertical-stripes"></div>
<div class="vertical-stripes"></div>
<ul id="note-block" class="reset">
<li>
<span>Idag</span>
<span class="date"><?php include('datetime.php'); ?></span>
<span><?php echo date('H:i'); ?></span>
</li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<form id="note-text" method="post" action="../includes/notepages/savenote.php">
<textarea name="textarea" id="notes-area"></textarea>
</form>
When writing a note or editing it:
A list of all the notes currently added: