malsup jquery form submit on select change - html

I'm using Malsup's excellent Form plugin to dynamically load search results onto the same page.
It works great with a standard form submit, however I have 2 select elements in my form and would love for the results to update as the select is changed.
My code at the moment is thus:
$(document).ready(function() {
var options = {
target: '#bands-results',
beforeSubmit: showRequest
};
$('#bandsearch').ajaxForm(options);
});
// Show loading message and submit form
function showRequest(formData, jqForm, options) {
$('#bands-results').prepend('<span>Searching</span>');
return true;
}
I haven't seen other examples that do the same.
Help appreciated.

Got it licked with this
$(document).ready(function() {
$("#genre-filter").change(function() {
$("#band_search").submit();
});
// bind to the form's submit event
$('#band_search').ajaxForm({
beforeSubmit: showRequest,
target: '#band_list',
success: function() {
$('#premlim').hide();
}
});
})
function showRequest(formData, jqForm, options) {
return true;
}

Related

Selected item should not shown in auto complete list

I am using auto-complete web service sing JSON, If i am selecting a list item that must not be appear again in auto-complete list;
JSON AJAX code:
select: function (event, ui) {
var terms = split(this.value);
if (terms.length <= 10) {
// remove the current input
terms.pop();
// add the selected item
terms.push(ui.item.value);
// add placeholder to get the comma-and-space at the end
terms.push("");
this.value = terms.join(", ");
return false;
}
else {
var last = terms.pop();
$(this).val(this.value.substr(0, this.value.length - last.length - 0)); // removes text from input
$(this).effect("highlight", {}, 1000);
$(this).addClass("red");
$("#warnings").html("<span style='color:red;'>Max skill reached</span>");
return false;
}
}
I am attaching screenshot also, please see here :
Like #Bindred mentioned in the comments to your question, an easier solution would be to use the Select2 jQuery library. It is not exactly what you are looking for, but as far as UX goes I think it would achieve a similar goal, and it is a breeze to get working.
I have added an example for you to use: https://jsfiddle.net/9cqc5876/9/
HTML
<select id="txtExpertise" multiple="multiple"></select>
JavaSript
$(document).ready(function() {
$("#txtExpertise").prop("disabled", "disabled");
// do your ajax request for data
//$.getJSON("../WebServices/WebServiceSkills.asmx/GetAutoCompleteData", function(data) {
// fake json data
var data = {"languages": ["Java", "C", "C++", "PHP", "Visual Basic",
"Python", "C#", "JavaScript", "Perl", "Ruby"]};
// populate the select
$.each(data.languages, function(key, val) {
$('#txtExpertise')
.append($("<option></option>")
.attr("value", key)
.text(val));
});
// activate the select2
$("#txtExpertise").select2();
$("#txtExpertise").prop("disabled", false);
//});
});

TinyMCE and AngularJS - not loading after NgSwitch

I hope I am clear enough with this request for assistance, as it is hard to explain and I can't post all the code here. I have downloaded code to enable TinyMCE to be used in a NgRepeat with AngularJS:
angular.module('ui.tinymce', [])
.value('uiTinymceConfig', {})
.directive('uiTinymce', ['uiTinymceConfig', function (uiTinymceConfig) {
uiTinymceConfig = uiTinymceConfig || {};
var generatedIds = 0;
return {
require: 'ngModel',
link: function (scope, elm, attrs, ngModel) {
var expression, options, tinyInstance;
// generate an ID if not present
if (!attrs.id) {
attrs.$set('id', 'uiTinymce' + generatedIds++);
}
options = {
// Update model when calling setContent (such as from the source editor popup)
setup: function (ed) {
ed.on('init', function (args) {
ngModel.$render();
});
// Update model on button click
ed.on('ExecCommand', function (e) {
ed.save();
ngModel.$setViewValue(elm.val());
if (!scope.$$phase) {
scope.$apply();
}
});
// Update model on keypress
ed.on('KeyUp', function (e) {
ed.save();
ngModel.$setViewValue(elm.val());
if (!scope.$$phase) {
scope.$apply();
}
});
},
mode: 'exact',
elements: attrs.id
};
if (attrs.uiTinymce) {
expression = scope.$eval(attrs.uiTinymce);
} else {
expression = {};
}
angular.extend(options, uiTinymceConfig, expression);
setTimeout(function () {
tinymce.init(options);
});
ngModel.$render = function () {
if (!tinyInstance) {
tinyInstance = tinymce.get(attrs.id);
}
if (tinyInstance) {
tinyInstance.setContent(ngModel.$viewValue || '');
}
};
}
};
}]);
var gwApp = angular.module('gwApp', ['ui.tinymce']);
I don't really understand this code, but it works fine initially. My page starts with a list of Posts. I click on 'Show Reply' for the first post, and using NgSwitch the multiple replies become visible (nested NgRepeat). I submit a new reply message (the reply text is entered using tinymce) using a RESTful API service and a http call (too much code to post here). Then after clicking the submit button for the new reply message, the NgSwitch kicks in again unexpectedly to make the replies no longer visible. When I expand the replies again, the tinymce is just a regular textarea again, and the proper editor is gone.
I know this is not very clear, but I'm hoping someone can make sense of what I've written and can help me solve this problem..
I was having the same problem using ng-switch and ng-show so i added:
scope.$watch('onHidden()',function(){ tinymce.editors = [] });
after the setTimeout function.
Also replace the
ed.on('init',function(args){ ngModel.$render(); });
with
ed.on('init',function(args){ ed.setContent(ngModel.$viewValue); });
and remove the $render function.
This is the link to the working code in JsFiddle

JSON object does not update correctly

First of all, I'm not sure if my title describes the problem correctly... I did search but didn't find anything that helped me out...
The project I'm working on has an #orderList. All orders have a delete option. After an order gets deleted the list is updated.
Sounds simple... I ran into a problem though.
/**
* Data returned at the end of selecting some options
*/
$.post(myUrl, $('#myForm').serialize(), function(data) {
// I build the orderlist
// The data returned is a JSON object holding session data (including orders)
buildOrderList(data);
...
// Do some other work
});
/*
* function to build the html list
*/
function buildOrderList(data) {
// Empty list
$('#orderList').empty();
// The click handler for the delete button is in here because it needs the data object
$(document).on('click', '[id^=delete_]', function() {
// Get the orderId from the delete button
var orderId = $(this).attr('id').split('_');
orderId = orderId['1'];
// I call the delete function
deleteOrder(orderId, data);
});
var html = '';
// Loop the data object
$.each(data, function(key,val){
...
// Put html code needed in var html
...
});
$('#orderList').append(html);
}
/*
* function to delete an order
*/
function deleteOrder(orderId, data) {
// Because of it depends on other 'products' in the list if the user can
// simply delete it, I use a jQuery dialog to give him some options.
// These options I send to a php script so it knows what should be deleted.
// This fires when a user clicks on the 'delete' button from a dialog.
// The dialog uses data to show options but does not change the value of data.
switch(data.type) {
case 'A':
delMsg += '<p>Some message for case A</p>';
delMsg += '<select>with some options for case A</select>';
$('#wizard_dialog').append(delMsg);
$('#wizard_dialog').dialog('option', 'buttons', [
{ text: "Delete", click: function() {
$.post(myUrl, $('#myDeleteOptions').serialize(), function(newData) {
// Now the returned data is the updated session data
// So I build the orderList again...
buildOrderList(newData);
...
// Do some other work
});
$( this ).dialog( "close" );
$(this).html(''); }},
{ text: "Cancel", click: function() { $( this ).dialog("close"); $(this).html(''); }}
] );
break;
case 'B':
// Do the same thing but different text and <select> elements
break;
}
}
The orderList updates correctly, however if I try to delete another order, the jQuery dialog gives me the option for the current (correct product) AND the option for the product that previously owned the id of the current. (Hope I didn't loose anyone in my attempt to explain the problem)
The main question is how to 'refresh' the data send to buildOrderList.
Since I call the function in a new $.post with fresh data object returned it should work, shouldn't it?
/**
* Enable the JQuery dialog
* (#wizard_dialog)
* this is the init (note that I only open the dialog in deleteOrder() and set text and buttons according to the data send to deleteOrder() )
*/
$('#wizard_dialog').dialog({
autoOpen: false,
resizable: false,
modal: true,
dialogClass: "no-close",
open: function() {
$('.ui-dialog-buttonpane').find('button:contains("Annuleren")').addClass('cancelButtonClass');
$('.ui-dialog-buttonpane').find('button:contains("Verwijderen")').addClass('deleteButtonClass');
$('.ui-dialog :button').blur(); // Because it is dangerous to put focus on 'OK' button
$('.ui-widget-overlay').css('position', 'fixed'); // Fixing overlay (else in wrong position?)
if ($(document).height() > $(window).height()) {
var scrollTop = ($('html').scrollTop()) ? $('html').scrollTop() : $('body').scrollTop(); // Works for Chrome, Firefox, IE...
$('html').addClass('noscroll').css('top',-scrollTop); // Prevent scroll without hiding the bar (thus preventing page to shift)
}
},
close: function() {
$('.ui-widget-overlay').css('position', 'absolute'); // Brake overlay again
var scrollTop = parseInt($('html').css('top'));
$('html').removeClass('noscroll'); // Allow scrolling again
$('html,body').scrollTop(-scrollTop);
$('#wizard_dialog').html('');
}
});
EDIT:
Because the problem could be in the dialog I added some code.
In the first code block I changed deleteOrder();
ANSWER
The solution was rather simple. I forgot to turn the click handler off before I added the new one. This returned the previous event and the new event.
$(document).off('click', '[id^=delete_]').on('click', '[id^=delete_]', function() {
// Get the orderId from the delete button
var orderId = $(this).attr('id').split('_');
orderId = orderId['1'];
// I call the delete function
deleteOrder(orderId, data);
});

JavaScript can not call content script JS function

I am developing chrome extension. I loaded JavaScript file successfully but the problem is external JavaScript (which I have loaded) can not call the function of content script files my code is as follows.
$(document).ready(function() {
$('.main_list').click(function()
{
$('.sub_list') .hide();
$(this) .parent() .children('.sub_list') .slideToggle("normal");
});
$('#click') .click(function()
{
$('.sub_list') .hide();
$(this) .parent() .parent() .children('.sub_list').slideToggle("normal");
});
$('#btnnewtask').click(function()
{
showdialog('http://localhost:51967/task.aspx');
});
$('#linknewtask').click(function()
{
showdialog('http://localhost:51967/task.aspx');
});
$('#btnnewcall').click(function()
{
showdialog('http://localhost:51967/call.aspx');
});
$('#linknewcall').click(function()
{
showdialog("http://localhost:51967/call.aspx");
});
$('#btnnewmeeting').click(function()
{
showdialog("http://localhost:51967/meeting.aspx");
});
$('#linknewmeeting').click(function()
{
showdialog("http://localhost:51967/meeting.aspx");
});
});
Showdialog() is function in content script. It is as follow
function showdialog(url)
{
var xhr=new XMLHttpRequest();
xhr.onreadystatechange=function()
{
if (xhr.readyState==4 && xhr.status==200)
{
xmldoc=xhr.responseXML;
var js=getfile(getjavascript(xmldoc));
for(i=0;i<js.length;i++)
{
loadjscssfile(js[i],"js");
}
var css=getfile(getstylesheet(xmldoc))
for(i=0;i<css.length;i++)
{
loadjscssfile(css[i],"css");
}
document.file.push(
{"url":url,"css":css,"js":js});
document.getElementById("dialogcontainer3").
innerHTML=gethtmldocument(xmldoc);
document.getElementById("blacklayer").style.display="block";
document.getElementById("dialogcontainer3").style.display=
"inline-block";
document.getElementById("dialogcontainer2").style.display="block";
document.getElementById("dialogcontainer1").style.display="block";
}
}
xhr.open("GET",url,true);
xhr.send();
}
But it gives error
Uncaught ReferenceError: showdialog is not defined (program):1
(anonymous function) (program):1
b.event.dispatch (program):3
v.handle (program):3
Content scripts execute in a special environment called an isolated
world. They have access to the DOM of the page they are injected into,
but not to any JavaScript variables or functions created by the page.
It looks to each content script as if there is no other JavaScript
executing on the page it is running on. The same is true in reverse:
JavaScript running on the page cannot call any functions or access any
variables defined by content scripts.
See http://developer.chrome.com/extensions/content_scripts.html#execution-environment
I would suggest trying shared DOM to communicate between the content script and the page or Message Passing.
An example of code on the page would be:
function showDialog(url) {
window.postMessage({
type: "FROM_PAGE",
text: url
}, "*");
}
And in the contentscript:
// This function will NOT collide with showDialog of the page:
function showDialog(url) {
/* ... */
}
window.addEventListener("message", function (event) {
// We only accept messages from ourselves
if (event.source != window) { return; }
// Make sure we're looking at the correct event:
if (event.data.type && (event.data.type == "FROM_PAGE")) {
showDialog(event.data.text);
}
}, false);
I haven't tested the above, so please consider it to be pseudocode. A similar example is available here: http://developer.chrome.com/extensions/content_scripts.html#host-page-communication

Chrome Extension - Get entire text content of the current tab

I'm developing an extension where I need to get the entire text content on the current tab. Now I've a plugin which retrieves selected text from the current tab. So, in essence I'm looking for the ctrl-A version of it :). This is what I've done so far taking the hint from #Derek.
This is in my event handler(this is just one, there are other listeners too for onUpdated etc):
chrome.tabs.onSelectionChanged.addListener(function(tabId,changeInfo,tab) {
chrome.tabs.getSelected(null,function(tab) {
chrome.tabs.sendRequest(tab.id, {method: "getSelection"}, function (response) {
selectedtext = response.data;
});
chrome.tabs.sendRequest(tab.id, {method: "getText"}, function (response) {
alltext = response.data;
});
});
});
This is what I've written in the content script:
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if (request.method == "getSelection")
sendResponse({data: window.getSelection().toString()});
else if (request.method == "getText")
sendResponse({data: document.body.innerText});
else
sendResponse({});
});
However the document.body.innerText is returning undefined. I need the entire text of the current tab in alltext. Can someone help me out on this?
Thanks.
You can use document.body.innerText or document.all[0].innerText to do it in the content script.
It will get all the text content in the page, without any HTML code.
Or you can use document.all[0].outerHTML to get the HTML of the whole page.
Example
In the Content Script
function getText(){
return document.body.innerText
}
function getHTML(){
return document.body.outerHTML
}
console.log(getText()); //Gives you all the text on the page
console.log(getHTML()); //Gives you the whole HTML of the page
Added
So you want the content script to return the text to the popup. You can use:
chrome.tabs.getSelected to get the tab selected,
chrome.tabs.sendRequest to send request to the content script,
and chrome.extension.onRequest.addListener to listen to requests.
Popup page
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.sendRequest(tab.id, {method: "getText"}, function(response) {
if(response.method=="getText"){
alltext = response.data;
}
});
});
Content Script
chrome.extension.onRequest.addListener(
function(request, sender, sendResponse) {
if(request.method == "getText"){
sendResponse({data: document.all[0].innerText, method: "getText"}); //same as innerText
}
}
);
This should work.
Use executeScript: (requires permission activeTab)
chrome.tabs.executeScript(null, {
code: `document.all[0].innerText`,
allFrames: false, // this is the default
runAt: 'document_start', // default is document_idle. See https://stackoverflow.com/q/42509273 for more details.
}, function(results) {
// results.length must be 1
var result = results[0];
process_result(result);
});
In case the code is complex, it's possible to define a function in the content script and call that function in the code (or use file).