Many JS improvements, moved a few things in view.js to stream.js, moved the clearForm plugin from view.js to rails.js (where we actually use it), refactored view.js and wrote specs
This commit is contained in:
parent
c5f2e8bb2d
commit
ba23bd7a0a
5 changed files with 450 additions and 115 deletions
|
|
@ -1,3 +1,23 @@
|
|||
/* Clear form plugin - called using $("elem").clearForm(); */
|
||||
$.fn.clearForm = function() {
|
||||
return this.each(function() {
|
||||
var type = this.type, tag = this.tagName.toLowerCase();
|
||||
if (tag == 'form')
|
||||
return $(':input',this).clearForm();
|
||||
if (type == 'text' || type == 'password' || tag == 'textarea')
|
||||
this.value = '';
|
||||
else if (type == 'checkbox' || type == 'radio')
|
||||
this.checked = false;
|
||||
else if (tag == 'select')
|
||||
this.selectedIndex = -1;
|
||||
else if (this.name == 'photos[]')
|
||||
this.value = '';
|
||||
$(this).blur();
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
jQuery(function ($) {
|
||||
var csrf_token = $('meta[name=csrf-token]').attr('content'),
|
||||
csrf_param = $('meta[name=csrf-param]').attr('content');
|
||||
|
|
|
|||
|
|
@ -15,6 +15,12 @@ var Stream = {
|
|||
$(this).closest("form").children(".comment_box").attr("rows", 1);
|
||||
});
|
||||
|
||||
$stream.delegate("textarea.comment_box", "keydown", function(e){
|
||||
if (e.keyCode === 13) {
|
||||
$(this).closest("form").submit();
|
||||
}
|
||||
});
|
||||
|
||||
$stream.delegate("textarea.comment_box", "focus", function(evt) {
|
||||
var commentBox = $(this);
|
||||
commentBox.attr("rows", 2)
|
||||
|
|
|
|||
|
|
@ -2,127 +2,198 @@
|
|||
* licensed under the Affero General Public License version 3 or later. See
|
||||
* the COPYRIGHT file.
|
||||
*/
|
||||
var View = {
|
||||
initialize: function() {
|
||||
/* Buttons */
|
||||
$("input[type='submit']").addClass("button");
|
||||
|
||||
$(document).ready(function(){
|
||||
$('#debug_info').click(function() {
|
||||
$('#debug_more').toggle('fast');
|
||||
});
|
||||
/* Tooltips */
|
||||
this.tooltips.bindAll();
|
||||
|
||||
/* Animate flashes */
|
||||
this.flashes.animate();
|
||||
|
||||
/* In field labels */
|
||||
$("label").inFieldLabels();
|
||||
|
||||
$('#flash_notice, #flash_error, #flash_alert').animate({
|
||||
/* Focus aspect name on fancybox */
|
||||
$(this.addAspectButton.selector)
|
||||
.click(this.addAspectButton.click);
|
||||
|
||||
/* Showing debug messages */
|
||||
$(this.debug.selector)
|
||||
.click(this.debug.click);
|
||||
|
||||
/* "Toggling" the search input */
|
||||
$(this.search.selector)
|
||||
.blur(this.search.blur)
|
||||
.focus(this.search.focus);
|
||||
|
||||
/* Getting started animation */
|
||||
$(this.gettingStarted.selector)
|
||||
.live("click", this.gettingStarted.click);
|
||||
|
||||
/* Submitting the status message form when the user hits enter */
|
||||
$(this.publisher.selector)
|
||||
.keyup(this.publisher.keyup);
|
||||
|
||||
/* User menu */
|
||||
$(this.userMenu.selector)
|
||||
.click(this.userMenu.click);
|
||||
|
||||
/* Sending a request message */
|
||||
$(this.newRequest.selector)
|
||||
.live("submit", this.newRequest.submit);
|
||||
|
||||
/* Button fancyboxes */
|
||||
$(this.fancyBoxButtons.selectors.join(", "))
|
||||
.fancybox({
|
||||
'titleShow': false,
|
||||
'hideOnOverlayClick' : false
|
||||
});
|
||||
|
||||
/* Webfinger form ajaxy loading */
|
||||
$(this.webFingerForm.selector)
|
||||
.submit(this.webFingerForm.submit);
|
||||
|
||||
$(document.body)
|
||||
.click(this.userMenu.removeFocus);
|
||||
},
|
||||
|
||||
addAspectButton: {
|
||||
click: function() {
|
||||
$("#aspect_name").focus();
|
||||
},
|
||||
selector: ".add_aspect_button"
|
||||
},
|
||||
|
||||
fancyBoxButtons: {
|
||||
selectors: [
|
||||
".add_aspect_button",
|
||||
".manage_aspect_contacts_button",
|
||||
".invite_user_button",
|
||||
".add_photo_button",
|
||||
".remove_person_button",
|
||||
".question_mark"
|
||||
]
|
||||
},
|
||||
|
||||
debug: {
|
||||
click: function() {
|
||||
$("#debug_more").toggle("fast");
|
||||
},
|
||||
selector: "#debug_info"
|
||||
},
|
||||
|
||||
flashes: {
|
||||
animate: function() {
|
||||
var $this = $(View.flashes.selector);
|
||||
$this.animate({
|
||||
top: 0
|
||||
}).delay(2000).animate({
|
||||
top: -100
|
||||
}, $(this).remove());
|
||||
}, $this.remove())
|
||||
},
|
||||
selector: "#flash_notice, #flash_error, #flash_alert"
|
||||
|
||||
//buttons//////
|
||||
$(".add_aspect_button," +
|
||||
".manage_aspect_contacts_button," +
|
||||
".add_photo_button," +
|
||||
".remove_person_button," +
|
||||
".question_mark").fancybox({ 'titleShow': false , 'hideOnOverlayClick' : false });
|
||||
},
|
||||
|
||||
$("input[type='submit']").addClass("button");
|
||||
|
||||
// focus aspect name on fancybox
|
||||
$(".add_aspect_button").click( function(){
|
||||
$("#aspect_name").focus();
|
||||
gettingStarted: {
|
||||
click: function() {
|
||||
var $this = $(this);
|
||||
$this.animate({
|
||||
left: parseInt($this.css("left"), 30) === 0 ? -$this.outerWidth() : 0
|
||||
}, function() {
|
||||
$this.css("left", "1000px");
|
||||
});
|
||||
},
|
||||
selector: ".getting_started_box"
|
||||
},
|
||||
|
||||
$("#q").focus(
|
||||
function() {
|
||||
$(this).addClass('active');
|
||||
}
|
||||
);
|
||||
newRequest: {
|
||||
submit: function() {
|
||||
$(this).hide().parent().find(".message").removeClass("hidden");
|
||||
},
|
||||
selector: ".new_request"
|
||||
},
|
||||
|
||||
$('.new_request').live("submit", function(){
|
||||
var foo = $(this).parent();
|
||||
$(this).hide();
|
||||
foo.find('.message').removeClass('hidden');
|
||||
});
|
||||
|
||||
|
||||
$("#q").blur(
|
||||
function() {
|
||||
$(this).removeClass('active');
|
||||
}
|
||||
);
|
||||
|
||||
$("#publisher").find("textarea").keydown( function(e) {
|
||||
publisher: {
|
||||
keyup: function(e) {
|
||||
if(e.keyCode === 13) {
|
||||
$(this).closest("form").submit();
|
||||
}
|
||||
});
|
||||
},
|
||||
selector: "#publisher textarea"
|
||||
},
|
||||
|
||||
$(".stream").delegate("textarea.comment_box", "keydown", function(e){
|
||||
if (e.keyCode === 13) {
|
||||
$(this).closest("form").submit();
|
||||
search: {
|
||||
blur: function() {
|
||||
$(this).removeClass("active");
|
||||
},
|
||||
focus: function() {
|
||||
$(this).addClass("active");
|
||||
},
|
||||
selector: "#q"
|
||||
},
|
||||
|
||||
tooltips: {
|
||||
addAspect: {
|
||||
bind: function() {
|
||||
$(".add_aspect_button", "#aspect_nav").tipsy({
|
||||
gravity:"w"
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
$("#user_menu").click( function(){
|
||||
avatars: {
|
||||
bind: function() {
|
||||
$("img.avatar").tipsy({
|
||||
live: true
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
whatIsThis: {
|
||||
bind: function() {
|
||||
$(".what_is_this").tipsy({
|
||||
live: true,
|
||||
delayIn: 400
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
bindAll: function() {
|
||||
for(var element in this) {
|
||||
if(element !== "bindAll") {
|
||||
this[element].bind();
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
userMenu: {
|
||||
click: function() {
|
||||
$(this).toggleClass("active");
|
||||
});
|
||||
},
|
||||
removeFocus: function(evt) {
|
||||
var $target = $(evt.target);
|
||||
if(!$target.closest("#user_menu").length) {
|
||||
$(View.userMenu.selector).removeClass("active");
|
||||
}
|
||||
},
|
||||
selector: "#user_menu"
|
||||
},
|
||||
|
||||
$('body').click( function(event){
|
||||
var target = $(event.target);
|
||||
if(!target.closest('#user_menu').length){
|
||||
$("#user_menu").removeClass("active");
|
||||
};
|
||||
if(!target.closest('.reshare_pane').length){
|
||||
$(".reshare_button").removeClass("active");
|
||||
$(".reshare_box").hide();
|
||||
};
|
||||
});
|
||||
|
||||
$("img", "#left_pane").tipsy({live:true});
|
||||
$(".add_aspect_button", "#aspect_nav").tipsy({gravity:'w'});
|
||||
$(".person img", ".dropzone").tipsy({live:true});
|
||||
$(".avatar", ".aspects").tipsy({live:true});
|
||||
$(".what_is_this").tipsy({live:true,delayIn:400});
|
||||
|
||||
$('.webfinger_form').submit(function(evt){
|
||||
form = $(evt.currentTarget);
|
||||
form.siblings('#loader').show();
|
||||
$('#request_result li:first').hide();
|
||||
});
|
||||
|
||||
// hotkeys
|
||||
$(window).bind('keyup', 'ctrl+f', function(){
|
||||
$("#q").focus();
|
||||
});
|
||||
|
||||
$(window).bind('keyup', 'ctrl+e', function(){
|
||||
EditPane.toggle();
|
||||
});
|
||||
|
||||
});//end document ready
|
||||
|
||||
|
||||
//Called with $(selector).clearForm()
|
||||
$.fn.clearForm = function() {
|
||||
return this.each(function() {
|
||||
var type = this.type, tag = this.tagName.toLowerCase();
|
||||
if (tag == 'form')
|
||||
return $(':input',this).clearForm();
|
||||
if (type == 'text' || type == 'password' || tag == 'textarea')
|
||||
this.value = '';
|
||||
else if (type == 'checkbox' || type == 'radio')
|
||||
this.checked = false;
|
||||
else if (tag == 'select')
|
||||
this.selectedIndex = -1;
|
||||
else if (this.name == 'photos[]')
|
||||
this.value = '';
|
||||
$(this).blur();
|
||||
});
|
||||
webFingerForm: {
|
||||
submit: function(evt) {
|
||||
$(evt.currentTarget).siblings("#loader").show();
|
||||
$("#request_result li:first").hide();
|
||||
},
|
||||
selector: ".webfinger_form"
|
||||
}
|
||||
};
|
||||
|
||||
$(".getting_started_box").live("click",function(evt){
|
||||
$(this).animate({
|
||||
left: parseInt($(this).css('left'),30) == 0 ?
|
||||
-$(this).outerWidth() :
|
||||
0
|
||||
},function(evt){ $(this).css('left', '1000px')});
|
||||
$(function() {
|
||||
/* Make sure this refers to View, not the document */
|
||||
View.initialize.apply(View);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -14,14 +14,16 @@ src_files:
|
|||
- public/javascripts/vendor/jquery144.js
|
||||
- public/javascripts/vendor/jquery-ui-1.8.6.custom.min.js
|
||||
- public/javascripts/vendor/jquery.tipsy.js
|
||||
- public/javascripts/validation.js
|
||||
- public/javascripts/vendor/jquery.infieldlabel.js
|
||||
- public/javascripts/vendor/fancybox/jquery.fancybox-1.3.1.pack.js
|
||||
- public/javascripts/diaspora.js
|
||||
- public/javascripts/mobile.js
|
||||
- public/javascripts/aspect-edit.js
|
||||
- public/javascripts/aspect-contacts.js
|
||||
- public/javascripts/web-socket-receiver.js
|
||||
- public/javascripts/view.js
|
||||
- public/javascripts/stream.js
|
||||
|
||||
- public/javascripts/validation.js
|
||||
# stylesheets
|
||||
#
|
||||
# Return an array of stylesheet filepaths relative to src_dir to include before jasmine specs.
|
||||
|
|
|
|||
236
spec/javascripts/view-spec.js
Normal file
236
spec/javascripts/view-spec.js
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
describe("View", function() {
|
||||
it("is the object that helps the UI", function() {
|
||||
expect(typeof View === "object").toBeTruthy();
|
||||
});
|
||||
|
||||
describe("initialize", function() {
|
||||
it("is called on DOM ready", function() {
|
||||
spyOn(View, "initialize");
|
||||
$(View.initialize);
|
||||
expect(View.initialize).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("fancyBoxButtons", function() {
|
||||
describe("selectors", function() {
|
||||
it("is an array of all the selectors that will have fancybox attached", function() {
|
||||
expect(typeof View.fancyBoxButtons.selectors === "object").toBeTruthy();
|
||||
expect($.isArray(View.fancyBoxButtons.selectors)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("debug", function() {
|
||||
describe("click", function() {
|
||||
beforeEach(function() {
|
||||
$("#jasmine_content").html(
|
||||
'<div id="debug_info">' +
|
||||
'<h5>DEBUG INFO</h5>' +
|
||||
'<div id="debug_more" style="display: none;">' +
|
||||
'DEBUG INFO' +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
);
|
||||
});
|
||||
|
||||
it("is called when the user clicks an element matching the selector", function() {
|
||||
spyOn(View.debug, "click");
|
||||
View.initialize();
|
||||
$(View.debug.selector).click();
|
||||
expect(View.debug.click).toHaveBeenCalled();
|
||||
setTimeout(function() {
|
||||
expect($(View.debug.selector).css("display")).toEqual("block");
|
||||
}, 500);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("flashes", function() {
|
||||
describe("animate", function() {
|
||||
beforeEach(function() {
|
||||
$("#jasmine_content").html(
|
||||
'<div id="flash_notice">' +
|
||||
'flash! flash! flash!' +
|
||||
'</div>'
|
||||
);
|
||||
});
|
||||
|
||||
it("is called when the DOM is ready", function() {
|
||||
spyOn(View.flashes, "animate").andCallThrough();
|
||||
View.initialize();
|
||||
expect(View.flashes.animate).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("newRequest", function() {
|
||||
beforeEach(function() {
|
||||
$("#jasmine_content").html(
|
||||
'<div id="user@joindiaspora.com">' +
|
||||
'<form accept-charset="UTF-8" action="/requests" class="new_request" data-remote="true" id="new_request" method="post">' +
|
||||
'<div style="margin:0;padding:0;display:inline">' +
|
||||
'<input id="request_to" name="request[to]" type="hidden" value="user@joindiaspora.com">' +
|
||||
'<input data-disable-with="Sending" id="request_submit" name="commit" type="submit" value="add contact" class="button">' +
|
||||
'</form>' +
|
||||
'<div class="message hidden">' +
|
||||
'<i>sent!</i>' +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
);
|
||||
});
|
||||
|
||||
describe("submit", function() {
|
||||
it("is called when the user submits the form", function() {
|
||||
spyOn(View.newRequest, "submit").andCallThrough();
|
||||
View.initialize();
|
||||
$(View.newRequest.selector).submit(function(evt) { evt.preventDefault(); });
|
||||
$(View.newRequest.selector).trigger("submit");
|
||||
expect(View.newRequest.submit).toHaveBeenCalled();
|
||||
expect($(View.newRequest.selector + " .message").css("display")).toEqual("block");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("publisher", function() {
|
||||
beforeEach(function() {
|
||||
$("#jasmine_content").html(
|
||||
'<div id="publisher">' +
|
||||
'<form action="/status_messages" class="new_status_message" id="new_status_message" method="post">' +
|
||||
'<textarea id="status_message_message" name="status_message[message]"></textarea>' +
|
||||
'</form>' +
|
||||
'</div>'
|
||||
);
|
||||
});
|
||||
|
||||
describe("keyup", function() {
|
||||
it("is called when the user types", function() {
|
||||
spyOn(View.publisher, "keyup");
|
||||
View.initialize();
|
||||
$(View.publisher.selector).trigger("keyup");
|
||||
expect(View.publisher.keyup).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("submits the form if the user hits enter while the textarea is focused", function() {
|
||||
spyOn($.fn, "submit");
|
||||
View.initialize();
|
||||
$(View.publisher.selector).focus();
|
||||
var event = $.Event("keyup");
|
||||
event.keyCode = 13;
|
||||
$(View.publisher.selector).trigger(event);
|
||||
expect($.fn.submit).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("search", function() {
|
||||
beforeEach(function() {
|
||||
$("#jasmine_content").html(
|
||||
'<input id="q" name="q" placeholder="Search" results="5" type="search" class="">'
|
||||
);
|
||||
});
|
||||
describe("focus", function() {
|
||||
it("adds the class 'active' when the user focuses the text field", function() {
|
||||
View.initialize();
|
||||
$(View.search.selector).focus();
|
||||
expect($(View.search.selector)).toHaveClass("active");
|
||||
});
|
||||
});
|
||||
describe("blur", function() {
|
||||
it("removes the class 'active' when the user blurs the text field", function() {
|
||||
View.initialize();
|
||||
$(View.search.selector).focus().blur();
|
||||
expect($(View.search.selector)).not.toHaveClass("active");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("tooltips", function() {
|
||||
describe("bindAll", function() {
|
||||
//Someone shorten this plz <3
|
||||
it("enumerates through the tooltips object, called the method 'bind' on any sibling that is not the bindAll method", function() {
|
||||
spyOn($, "noop");
|
||||
View.initialize();
|
||||
View.tooltips.myToolTip = { bind: $.noop };
|
||||
View.tooltips.bindAll();
|
||||
expect($.noop).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("userMenu", function() {
|
||||
beforeEach(function() {
|
||||
$("#jasmine_content").html(
|
||||
'<ul id="user_menu">' +
|
||||
'<div class="right">' +
|
||||
'.' +
|
||||
'</div>' +
|
||||
'<div class="avatar">' +
|
||||
'<img alt="Jasmine Specson" class="avatar" title="Jasmine Specson">' +
|
||||
'</div>' +
|
||||
'<a href="#">Jasmine Specson</a>' +
|
||||
'</ul>'
|
||||
);
|
||||
});
|
||||
describe("click", function() {
|
||||
it("adds the class 'active' when the user clicks the ul", function() {
|
||||
View.initialize();
|
||||
$(View.userMenu.selector).click();
|
||||
expect($(View.userMenu.selector)).toHaveClass("active");
|
||||
});
|
||||
});
|
||||
describe("removeFocus", function() {
|
||||
it("removes the class 'active' if the user clicks anywhere that isnt the userMenu", function() {
|
||||
View.initialize();
|
||||
$(View.userMenu.selector).click();
|
||||
expect($(View.userMenu.selector)).toHaveClass("active");
|
||||
var event = $.Event("click");
|
||||
event.target = document.body;
|
||||
$(document.body).trigger(event);
|
||||
expect($(View.userMenu.selector)).not.toHaveClass("active");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("webFingerForm", function() {
|
||||
beforeEach(function() {
|
||||
$("#jasmine_content").html(
|
||||
'<div class="span-7 last">' +
|
||||
'<h4>' +
|
||||
'Add a new contact' +
|
||||
'</h4>' +
|
||||
'<form accept-charset="UTF-8" action="/people/by_handle" class="webfinger_form" data-remote="true" method="post">' +
|
||||
'<input name="diaspora_handle" placeholder="diaspora@handle.org" results="5" type="search" value="">' +
|
||||
'<input name="commit" type="submit" value="Find by Diaspora handle" class="button">' +
|
||||
'</form>' +
|
||||
|
||||
'<div class="hidden" id="loader">' +
|
||||
'<img alt="Ajax-loader" src="/images/ajax-loader.gif?1290478032">' +
|
||||
'</div>' +
|
||||
'<ul id="request_result">' +
|
||||
'<li class="error hidden">' +
|
||||
'<div id="message">' +
|
||||
'<a href="/users/invitation/new">Know their email address? You should invite them</a>' +
|
||||
'</div>' +
|
||||
'</li>' +
|
||||
'</ul>' +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
// Prevent the form from being submitted
|
||||
$(View.webFingerForm.selector).submit(function(evt) { evt.preventDefault(); });
|
||||
});
|
||||
describe("submit", function() {
|
||||
it("shows the ajax loader after the user submits the form", function() {
|
||||
View.initialize();
|
||||
$(View.webFingerForm.selector).submit();
|
||||
expect($(View.webFingerForm.selector).siblings("#loader").css("display")).toEqual("block");
|
||||
});
|
||||
|
||||
it("hides the first list item in the result ul after the user submits the form", function() {
|
||||
View.initialize();
|
||||
$(View.webFingerForm.selector).submit();
|
||||
expect($("#request_result li:first").css("display")).toEqual("none");
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Reference in a new issue