I want to create a Google Chrome extension that, among other things, will modify the chat text based on what is inputed. I will add a button next to the video, call, and add people buttons below the name, and when clicked will activate the modifications. I don't want to have to put any more scripts on the page than I have to, so I would like to be able to send the messages the way Gmail would be pressing "return" in the chat box. Also I want to to be able to show that both of the people chatting are using my extension by displaying text in the chat box just like the "This chat is off the record" text is, and possibly if both are using it add extra stuff to the chat. What I tried to do was make an imitation textarea and when the user 'sends' it, grab it and modify it, then insert it into the real one and send the new text. I can change the text but can't seem to send it...
Heres what I have so far, I enclosed everything in a setInterval to check if chat box exists and add appropriate stuff to it:
var chatBtnClone = setInterval(function() {
if ($("body").find(".nH .NG").length > 0) { //if chat is active
var clone = $("body").find(".nH .NG .NJ").first();
if (clone.children()[0].className.indexOf("chat") < 0) { //if already added my class
var clonned = clone.clone();
var clonnedChd = clonned.children().first();
clonnedChd.attr("title", "Start encrypted chat");
clonnedChd.on('click', function() {
console.log("clicked chatBtn!"); //make sure it works
var self = $(this);
if (self[0].className.indexOf("chatEncX") >= 0) { //toggle button pic
self.removeClass('chatEncX').addClass('chatEnc');
self.attr("title", "Stop encrypted chat");
} else {
self.removeClass('chatEnc').addClass('chatEncX');
self.attr("title", "Start encrypted chat");
}
});
clone.parent().prepend(clonned);
clonned.find('.NK').removeClass("NK-Y8").addClass("chatEncX");
}
var chatBoxs = $('body').find(".nn .AD");
var chatArea = chatBoxs.first().find(".nH textarea"); //get chat textareas
if (chatArea.length === 1) {
var clonChatArea = chatArea.first().clone();
clonChatArea.removeAttr("id");
chatArea.first().parent().append(clonChatArea);
// chatArea.first().hide();
var chatTextDiv = chatBoxs.first().find(".jp .nH .nH").first();
clonChatArea.focusin(function() {
chatTextDiv.removeClass("gv").addClass("f7");
});
clonChatArea.focusout(function() {
chatTextDiv.removeClass("f7").addClass("gv");
});
clonChatArea.on('keyup', function(event) {
var self = this;
//console.log(this.style.height); //make sure height it working
if (self.scrollHeight === 38) {
self.style.overflowY = "hidden";
self.style.height = "36px";
} else if (self.scrollHeight === 47) {
self.style.height = "54px";
} else if (self.scrollHeight === 62) {
self.style.height = "72px";
} else if (self.scrollHeight >= 77) {
self.style.height = "80px";
self.style.overflowY = "scroll";
}
if( event.keyCode === 13 && event.shiftKey ){
//regular, just insert a newline
} else if (event.keyCode === 13) {
//grab text and modify then reinsert into real textarea
var chatTxt = $(this).val();
var chatHidden = chatBoxs.first().find(".nH textarea").first();
var chatEncTxt = Crypto.AES.encrypt(chatTxt, "pass"); //modify text
//console.log(chatEncTxt);
chatHidden.val(chatEncTxt);
chatHidden.focus();
chatHidden.trigger({ type : 'keypress', which : 13 }); //try to imitate the return key and send (NOT WORKING!!!)
// $(this).focus();
}
});
}
}
},150);
This might be a bit late, but if anyone else is interested then I managed this by doing the following:
var e = new Event("keypress");
e.keyCode = e.which = 13;
// :mc is an example textarea id, but the OP has the code for finding that already
document.getElementById(':mc').dispatchEvent(e);
Related
Is there a recommended way to unittest javascript in Laravel 5? I'm using the jQuery framework to do the search autocomplete task (code below). There's a lot of if blocks that I want to test but I'm not sure how to best test everything in Laravel 5. Any help is appreciated.
<script type="text/javascript">
(function($) {
var autocomplete_timer;
var ajax_request;
var autocomplete_delay = 50;
var search_keyword = "";
var max_result_count = 5;
var autocomplete_results = $('#autocomplete-results');
var autocomplete_results_list;
var default_report_url = '{{ route('report_summary_date_range_filter') }}';
var selected_autocomplete_item_index = 0;
var active_li = false;
var autocomplete_error = $('#autocomplete-error');
var redirect_state = false; //
$(document).ready(function () {
autocomplete_results_list = autocomplete_results.children('ul');
// Search Autocomplete
$("#search").keyup(function (e) {
search_keyword = $(this).val();
// If there is an existing XHR, abort it.
if (ajax_request) {
ajax_request.abort()
}
// Enable list iteration via keyboard
if (e.keyCode == 40 || e.keyCode == 38) {
ajax_request.abort();
var results_count = autocomplete_results_list.children('li').length;
if (e.keyCode == 40 && selected_autocomplete_item_index < results_count && active_li != false) {
selected_autocomplete_item_index++;
} else if (e.keyCode == 38 && selected_autocomplete_item_index > 0 && active_li != false) {
selected_autocomplete_item_index--;
}
active_li = autocomplete_results_list.children('li:eq(' + selected_autocomplete_item_index + ')');
if (active_li.length > 0) {
active_li.addClass('active');
autocomplete_results_list.children('li').not(active_li).removeClass('active');
$('#search').val(active_li.children('.autocomplete-ticker').text());
}
e.preventDefault();
return false;
}
// Clear the timer so we don't end up with dupes.
clearTimeout(autocomplete_timer);
// don't trigger ajax if user pressed enter/return key
// while a redirect is triggered
if (e.keyCode == 13 && redirect_state == true) {
return false;
}
if (search_keyword != '') {
// reset the index
selected_autocomplete_item_index = 0;
active_li = false;
// assign timer a new timeout
autocomplete_timer = setTimeout(function() {
ajax_request = $.ajax({
type: 'POST',
url: '/ajax/company/search/' + search_keyword,
data: {'_token': '{{ csrf_token() }}'},
success: function(response) {
if (response.count != 0) {
autocomplete_results.show();
autocomplete_results_list.empty();
autocomplete_error.hide();
var current_results = ((response.count > max_result_count) ? max_result_count : response.count);
for (var index = 0; index < current_results; index++) {
autocomplete_results_list.append(
'<li>' +
'<span class="autocomplete-ticker">' + response.results[index].ticker + '</span>' +
'<span class="autocomplete-company">' + response.results[index].name + '</span>' +
'</li>'
);
}
} else {
autocomplete_results_list.empty();
autocomplete_results.show();
autocomplete_error.show();
}
}
});
}, autocomplete_delay);
} else {
autocomplete_results.hide();
autocomplete_results_list.empty();
}
}).keydown(function (e) {
// prevent moving cursor to start of input field
// if the user presses the up arrow key
if (e.keyCode == 38) {
e.preventDefault();
}
});
// handle user clicking of an autocomplete item
autocomplete_results_list.on('click', 'li', function () {
var ticker = $(this).children('.autocomplete-ticker').text();
$('#search').val(ticker);
default_report_url = default_report_url.replace('%7Bticker%7D', ticker);
// redirect
$(location).attr('href', default_report_url);
redirect_state = true;
});
// if the user presses the return key while an autocomplete list
// is present, select the first item on the list and trigger a redirect
$('#searchbar form').submit(function (e) {
if ($('#search').val() != '') {
if (autocomplete_results_list.has('li').length > 0) {
autocomplete_results_list.children('li').first().addClass('active');
var ticker = autocomplete_results_list.children('li').first()
.children('.autocomplete-ticker').text().toUpperCase();
if (ticker != '') {
default_report_url = default_report_url.replace('%7Bticker%7D', ticker);
// redirect
$(location).attr('href', default_report_url);
redirect_state = true;
}
}
}
e.preventDefault();
});
});
$(document).click(function (e) {
// Hide autocomplete results if user clicked outside the search input field
// or the autocomplete listing
var container = $('#searchbar');
if (!container.is(e.target) // if the target of the click isn't the container...
&& container.has(e.target).length === 0) // ... nor a descendant of the container
{
$('#autocomplete-results').hide();
$('#autocomplete-results ul').empty();
}
});
})(jQuery);
</script>
The choice of Laravel (or any other back-end framework/language/platform) is entirely irrelevant. This is purely front-end code. As such, you need to be using front-end testing tools for it.
However, even before you start thinking about unit testing this code, you need to do some re-coding so that it is actually testable in units. As things stand, you have a large monolithic blob of code there which cannot really be unit tested at all. You need to extract the functionality into discrete functions; the shorter the better.
Once you've done that, I'd suggest that the best starting point for your testing would be QUnit. This is a unit test framework developed by the jQuery foundation, and used for testing jQuery itself. Since your code has jQuery as a dependency, I'd suggest that this would probably be the best place to start. However there are numerous other testing frameworks for JavaScript, and you may want to investigate some of those as well.
Bear in mind that UI code (which most front-end JavaScript is) is notoriously difficult to write good quality unit tests for. You may find that functional testing -- ie automated end-user testing via a browser -- will serve you better. (indeed, you should be considering doing this kind of testing, even if you do also write unit tests for the JS code). For this, you will need an automation tool for the browser. The most well known one is Selenium, but you may also want to look into Sahi and also PhantomJS.
firstly English isn't my native language, sorry if I have any mistakes.
There is message sending problem in the function, I've played with Jquery codes but I couldn't fix it.
When I press the Enter, message reach to receiver, that's good.
But when I press the Shift with Enter, message reach to receiver again,
I want to create new line when press the both keys.
Jquery codes:
$(document).ready(function() {
$('input#chat').bind('keydown', function(e) {
if(e.keyCode==13) {
// Store the message into var
var message = $('input#chat').val();
var id = $('#chat').attr('class');
if(message) {
// Remove chat errors if any
$('.chat-error').remove();
// Show the progress animation
$('.message-loader').show();
// Reset the chat input area
document.getElementById("chat").style.height = "25px";
$('input#chat').val('');
Did you try it ?
if(e.shiftKey && e.keyCode==13){
// Don't fill
} else if(e.keyCode==13){
e.preventDefault();
// Store the message into var
var message = $('input#chat').val();
var id = $('#chat').attr('class');
if(message) {
........................
}
In this, while the shift key is pressed a boolean prevents the code from being run.
var ShiftDown = false; //Is false when not being pressed, true when being pressed
$(document).ready(function() {
$('input#chat').keydown(function(e) {
if(e.which === 16) {
//Shift key is pressed
ShiftDown = true;
}else if(e.which === 13){
//Code will only run if Shift key is not pressed
if(ShiftDown === false){
// Store the message into var
var message = $('input#chat').val();
var id = $('#chat').attr('class');
if(message) {
// Remove chat errors if any
$('.chat-error').remove();
// Show the progress animation
$('.message-loader').show();
// Reset the chat input area
document.getElementById("chat").style.height = "25px";
$('input#chat').val('');
}
}
}
})
$('input#chat').keyup(function(e) {
if(e.which === 16){
//Shift key is no longer pressed
ShiftDown = false;
}
});
}
I've just changed
$('input#chat').bind('keydown',function(e){})
to
$('input#chat').keydown(function(e){})
Move across each word in a sentences.
I have created shortcut key for enter in my application as, it will move towards and focus each input control in my page.
I need to set keyboard shortcuts for tab as, it has to select each string of a sentences which are in some textbox. For example txtAddress contain value like "Hi i am new user", if I press tab key it has to select a string "hi" then "i" then "am" then "new" then "user" after that it has to focus a next input control.
I have tried with following JS to focus next input control but don't know how to select each word in textbox.
$(document).unbind('keydown');
$(document).bind('keydown', 'tab', function assets() {
try {
var inputs = $(":input:not(input[type='hidden'])");
var CurInput = inputs.get(inputs.index(document.activeElement));
var nextInput = inputs.get(inputs.index(document.activeElement) + 1);
if (CurInput && nextInput.type == "text" && CurInput.style.display != "none") {
var strval = CurInput.value;
if (!strval) {
if (nextInput && nextInput.type != "hidden" && nextInput.style.display != "none") {
nextInput.focus();
}
}
}
else if (nextInput && nextInput.type != "hidden" && nextInput.style.display != "none") {
nextInput.focus();
}
return false;
}
catch (e) {
}
});
http://jsbin.com/cihahigevo/1/edit?html,js,output
var textarea = $('textarea')[0],
index = 0;
$(document).on('keydown.tab', function(e){
if( e.keyCode == 9 ){
textarea.focus();
textarea.value = textarea.value.trim() + ' ';
index = textarea.value.indexOf(' ', index) + 1;
textarea.setSelectionRange(0, index);
}
return false;
});
It's never a good idea to override a users keyboard, especially the tab button.
The tab button is used by people who (for whatever reason) don't use a mouse to navigate sites by 'tabbing' between buttons, form fields, etc.
If you remove this functionality by overriding the tab key, you've suddenly made your site unaccessible to these users.
You may also run afoul of you countries laws on website accessibility (the Disability & Discrimation act in the UK).
I've written some code using jQuery to do an ajax call and display a message on the page when the user moves focus away from a field. My field is called txtLogin and the user types in some text and clicks a button to create a new user account in a database using the given txtLogin value.
The issue is that a valid value must contain four letters, a dash, and then four more letters. My client insists that the form should have two fields, one for the first four letters, and another for the second four letters.
Suppose that these two fields are called txtLogin0 and txtLogin1. I still want to do an ajax call when the user moves focus away from the field, but the ajax call should not be invoked when the user moves from one of the two fields to the other!
My current code looks like this.
$('#txtLogin').blur(function() {
var login = $(this).val();
var isValid = testLogin(login);
if (!isValid) alert('Login is invalid');
});
I imagine my new code looking like this:
$('#txtLogin0').add('#txtLogin1').blur(function() {
var focusId = The Id of the newly focused element
if (focusId==='txtLogin0' || focusId==='txtLogin1) return
var login = $(#txtLogin0').val() + '-' + $('#txtLogin1').val();
var isValid = testLogin(login);
if (!isValid) alert('Login is invalid');
});
How can I get the id of the element that the focus moves to in the jQuery.blur event?
A simple hack is to create two var to store the current and previous element in onfocus and onblur and call the validate method inside a timer which will be triggered in 0 milli seconds.. Try below code and I think it is close to what you want.
DEMO
var prevEl, curEl;
$(document).ready(function() {
$('#txtLogin0, #txtLogin1').blur(function() {
prevEl = this.id;
setTimeout(validateLogin, 0);
}).focus(function() {
curEl = this.id;
});
});
function validateLogin() {
if ((prevEl === 'txtLogin0' && curEl === 'txtLogin1') || (curEl === 'txtLogin0' && prevEl === 'txtLogin1')) {
return;
}
prevEl = ''; curEl = '';
var login = $('#txtLogin0').val() + '-' + $('#txtLogin1').val();
var isValid = testLogin(login);
if (!isValid) alert('Login is invalid');
}
function testLogin(txt) {
return false;
}
var focusId = $(this).attr('id');
I have a drop down select box inside a div. When the user clicks on change, a dropdown box appears next to the change/submit button and the user makes a selection which then updates the database and the selection appears instead of the dropdown. All works fine in IE8 and Firefox but in IE7 it allows one selection (there are several identical dropdowns) but the second time a selection is made it hangs on "please wait". This is the relevant code:
<td width=200>
<input type="button" onclick="startChanging(this)" value="Change" /></td>
<script type="text/javascript">
var selectBox, isEditing = false;
var recordvalue;
if( window.XMLHttpRequest ) {
recordvalue = new XMLHttpRequest();
} else if( window.ActiveXObject ) {
try {
recordvalue = new ActiveXObject('Microsoft.XMLHTTP');
} catch(e) {}
}
window.onload = function () {
selectBox = document.getElementById('changer');
selectBox.id = '';
selectBox.parentNode.removeChild(selectBox);
};
function startChanging(whatButton) {
if( isEditing && isEditing != whatButton ) { return; } //no editing of other entries
if( isEditing == whatButton ) { changeSelect(whatButton); return; } //this time, act as "submit"
isEditing = whatButton;
whatButton.value = 'Submit';
var theRow = whatButton.parentNode.parentNode;
var stateCell = theRow.cells[3]; //the cell that says "present"
stateCell.className = 'editing'; //so you can use CSS to remove the background colour
stateCell.replaceChild(selectBox,stateCell.firstChild); //PRESENT is replaced with the select input
selectBox.selectedIndex = 0;
}
function changeSelect(whatButton) {
isEditing = true; //don't allow it to be clicked until submission is complete
whatButton.value = 'Change';
var stateCell = selectBox.parentNode;
var theRow = stateCell.parentNode;
var editid = theRow.cells[0].firstChild.firstChild.nodeValue; //text inside the first cell
var value = selectBox.firstChild.options[selectBox.firstChild.selectedIndex].value; //the option they chose
selectBox.parentNode.replaceChild(document.createTextNode('Please wait...'),selectBox);
if( !recordvalue ) {
//allow fallback to basic HTTP
location.href = 'getupdate.php?id='+editid+'&newvalue='+value;
} else {
recordvalue.onreadystatechange = function () {
if( recordvalue.readyState != 4 ) { return; }
if( recordvalue.status >= 300 ) { alert('An error occurred when trying to update'); }
isEditing = false;
newState = recordvalue.responseText.split("|");
stateCell.className = newState[0];
stateCell.firstChild.nodeValue = newState[1] || 'Server response was not correct';
};
recordvalue.open('GET', "getupdate.php?id="+editid+"&newvalue="+value, true);
recordvalue.send(null);
}
}
</script>
If anyone has any idea why this is happening I'd be very grateful
ok managed to solve it. I moved the recordvalue.open line near the bottom inside te last else loop and it works perfectly in all browsers just don't ask me why