I use jquery autocomplete and it look like my code, to call the plugin, not good. is there any more simple way to call jquery autocomplete
js
$(document).ready(function(){
$("#m_occupation").autocomplete("search/moccupation.php", {
selectFirst: true
});
$("#foccupation").autocomplete("search/f_occupation.php", {
selectFirst: true
});
$("#g_address").autocomplete("search/g_address.php", {
selectFirst: true
});
$("#relationship").autocomplete("search/relationship.php", {
selectFirst: true
});
});
What you've got isn't really terrible. If you're only ever initializing these autocompletes one time, then it's pretty readable overall, although you do have some repetition.
Cache your jQuery objects for future use. In your snippet above, you only reference each jQuery object (e.g., $("#m_occupation") ) once, but in a real webapp, there's a pretty good chance you'll use it more. Caching helps reduce the number of jQuery finding operations, and is a good practice to adopt even though it's not likely to increase performance for a user noticeably.
Cache your options objects. You're repeating your option declaration multiple times; just declare a single autocompleteOptions object and be done with it.
Refactor initialization into a function. If you're really feeling like the autocomplete initialization is ugly, or complex, or subject to frequent edits, make it a single function. Future global edits to initialization can be made one time rather than multiple times.
A redo of your code taking those into account would look like:
var initAutocomplete = function($el, dataUrl) {
var autocompleteOptions = { selectFirst: true };
$el.autocomplete(dataUrl, autocompleteOptions);
};
$(document).ready(function(){
var $m_occupation, $foccupation, $g_address, $relationship;
$m_occupation = $('#m_occupation');
initAutocomplete($m_occupation, "search/moccupation.php");
$foccupation = $('#foccupation');
initAutocomplete($foccupation, "search/f_occupation.php");
$g_address = $('#g_address');
initAutocomplete($g_address, "search/g_address.php");
$relationship = $('#relationship');
initAutocomplete($relationship, "search/relationship.php");
});
You could technically optimize further by using a single string to represent the DOM ID and URL from which you gather the data, but in my experience, that breaks down in maintenance. So I wouldn't couple those too tightly.
Related
I have below code
$.fn.dataTableExt.aoFeatures.push({
"fnInit": function (oSettings) {
oSettings.oScroll.sY = 5;
return { "oSettings": oSettings } ;
},
"cFeature": "T"
});
$.extend($.fn.dataTable.defaults, {
//"scrollY": 5,
"dom":"T"
});
I can see scrollY changed in function but no effect in datatable, How can overwrite the default setting using this function, since i have to put condition ono tableid,
otherwise I could have done below way which is working
$.extend($.fn.dataTable.defaults, {
"scrollY": 5,
});
I believe I am missing something on return statement which will override the things
fiddle reference
You code is not working for a few reasons. First, you are using an outdated API. $.fn.dataTableExt.aoFeatures.push is the old API used with $(...).dataTable(). By using $(...).DataTable() (note the capital "D") as you did in your fiddle, you are choosing to use the new API. (Read about converting code using the old API to use the new API here.) Using the current API is a great choice, but you then need to use $.fn.dataTable.ext.feature.push to set up your feature.
This works:
$.fn.dataTable.ext.feature.push({
"fnInit": function (settings) {
settings.oScroll.sY = 25;
},
"cFeature": "T"
});
However, the dom feature is intended to indicate the order of elements in the table. Using it to set style like scrollY is OK, but not exactly what they had in mind. The point being that if you are going to specify dom at all, you have to specify all the elements you want. In particular, you have to specify t for table or else the DataTable will not attach itself to the table at all. So you need to set up your table with something like this to trigger your scrollY "feature":
$(document).ready(function() {
var table = $('#example').DataTable({
"dom":"Tlftip"
});
Note that the order matters. The "T" has to come before the other elements that are affected by the changes made in the feature. "dom":"lftipT" will not have the desired effect.
Goal: a dynamically generated list from external source.
I've set up a simple angular app that gets a list of events from an external JSON source. I want the list to update when events are added from the external source. It's currently working, but I have one problem and three questions:
1) I'm currently rewriting the list every 15 seconds. How do I just add to the end of the list without rewriting the list? (problem and question)
2) Is there another, better way to keep up to date with the external list? I'm trying to follow "RESTful" techniques, does that mean I should rely on the client side code to poll every so many seconds the way I'm doing? (best practice question)
3) Is setting the timeout in the controller best practice? Because it's controlling the action on the page?(best practice/comprehension question)
var eventModule = angular.module('eventModule', []);
eventModule.controller('eventControlller',
function($scope, $timeout, eventList) {
$scope.events = eventList.getAllEvents().success(
function(events) {$scope.events = events});
var poll = function() {
$timeout(function() {
$scope.events = eventList.getAllEvents().success(
function(events) {$scope.events = events});
poll();
}, 15000);
};
poll();
});
eventModule.factory('eventList', function($http) {
var url = "http://localhost/d8/events/request";
return {
getAllEvents: function() {
return $http.get(url);
}
};
});
If the list is an array, and you want to add new members to it, there are a few different ways. One way is to use the prototype.concat() function, like so:
function(events) {
$scope.events = $scope.events.concat(events)
});
If you cannot use that then you can go for loops solution:
function concatenateEvents(events) {
events.forEach(function(element) {
events.push(element);
}
}
Regarding the best ways to update the list, it depends on your requirements. If 15 seconds is not too long for you, then you can keep this logic, but if you need to speed up the response time, or even make it real time, then you need to emulate server-push architecture, which is different than the default web architecture, which is request-response architecture. Basically you may want to explore web sockets, and/or long polling, or reverse ajax, or comet... has many names. Web sockets is the recommended solution, others are only in case you have to use some non-compatible browsers.
Regarding the third question, I honestly don't know. Truly it doesn't feel good to control the UI from within your controller, but as I don't really know what your app is supposed to be doing, I don't know whether this is actually a bad way to do it.
Hope this helps!
EDIT - forgot to add another important point: You don't need to assign the eventList.getAllEvents() to $scope.events, as you are doing that in the callback handler function.
Perhaps you can modify your controller to something like this:
eventModule.controller('eventControlller', function($scope, $timeout, eventList) {
eventList.getAllEvents().success(
function(events) {
$scope.events = events
});
var poll = function() {
$timeout(function() {
eventList.getAllEvents().success(
function(events) {$scope.events = events});
poll();
}, 15000);
};
poll();
});
I have a not too big grid (30x20) with numbers in cells. I have to display all, calculate them in different ways (by columns, rows, some cells, etc.) and write values to some cells. This data is also written and read from db table fields. Everything is working, excluding simple (theoretically) mask tools.
In time of e.g. writing data to the field in the table I try to start mask and close it on finish. I used such a “masks” very often but only in this situation I have a problem and can’t solve it.
I prepare this mask the following way:
msk = new Ext.LoadMask(Ext.getBody(), { msg: "data loading ..." });
msk.show();
[writing data loops]
msk.hide();
msk.destroy();
I also tried to use grid obiect in place of Ext.getBody(), but without result.
I found also that the program behaves in a special way – loops which I use to write data to the table field are "omitted" by this mask, and it looks like loops are working in the background (asynchronously).
Would you be so kind as to suggest something?
No, no, no, sorry guys but my description isn’t very precise. It isn’t problem of loading or writing data to the database. Let’s say stores are in the memory but my problem is to calculate something and write into the grid. Just to see this values on the screen. Let me use my example once again:
msk = new Ext.LoadMask(Ext.getBody(), { msg: "data loading ..." });
msk.show();
Ext.each(dataX.getRange(), function (X) {
Ext.each(dataY.getRange(), function (Y) {
…
X.set('aaa', 10);
…
}
msk.hide();
msk.destroy();
And in such a situation this mask isn’t visible or is too fast to see it.
In the mean time I find (I think) a good description of my problem but still can’t find a solution for me. When I use e.g. alert() function I see this mask, when I use delay anyway, mask is too fast. Explanation is the following:
The reason for that is quite simple - JS is single threaded. If you modify DOM (for example by turning mask on) the actual change is made immediately after current execution path is finished. Because you turn mask on in beginning of some time-consuming task, browser waits with DOM changes until it finishes. Because you turn mask off at the end of method, it might not show at all. Solution is simple - invoke store rebuild after some delay.*
I have no idea how is your code looks in general but this is some tip that you could actually use.
First of all loading operations are asynchronously so you need to make that mask show and then somehow destroy when data are loaded.
First of all check if in your store configuration you have autoLoad: false
If yes then we can make next step:
Since Extjs is strongly about MVC design pattern you should have your controller somewhere in your project.
I suppose you are loading your data on afterrender or on button click event so we can make this:
In function for example loadImportantData
loadImportantData: function(){
var controller = this;
var store = controller.getStore('YourStore'); //or Ext.getStore('YourStore'); depends on your configuration in controller
var myMask = new Ext.LoadMask(Ext.getBody(), {msg:"Please wait..."});
myMask.show();
store.load({
callback: function (records, operation, success) {
//this callback is fired when your store load all data.
//then hide mask.
myMask.hide();
}
});
}
When data is loaded your mask will disappear.
If you have a reference to the grid, you can simply call grid.setLoading(true) to display a loading mask over the grid at any time.
Using Meteor, I'd like to understand the most efficient way to use JQuery UI's Autocomplete with large volumes of server-side data.
I have two working proposals and would like to hear opinions on the differences and if there are any better ways to do the same thing.
Using pub/sub:
// Server
Meteor.publish("autocompleteData", function (theSearchTerm) {
var query = {
name: { $regex: theSearchTerm, $options: 'i'}
};
return MyData.find(query, options);
});
// Client
Template.myTemplate.rendered = function() {
initAutocomplete($(this.find('.my.autocomplete')));
};
var initAutocomplete = function(element){
element.customAutocomplete({
source: function(request, callback){
var sub = Meteor.subscribe('autocompleteData', request.term, function(){
var results = MyData.find({}, {limit: 50}).fetch();
sub.stop();
callback(results);
});
},
select: function(event, ui){
// Do stuff with selected value
}
});
};
Using remote functions (Meteor.Methods):
// Server
Meteor.methods({
getData: function(theSearchTerm) {
var query = {
name: { $regex: theSearchTerm, $options: 'i'}
};
return MyData.find(query, {limit: 50}).fetch();
});
});
// Client
Template.myTemplate.rendered = function() {
initAutocomplete($(this.find('.my.autocomplete')));
};
var initAutocomplete = function(element){
element.customAutocomplete({
source: function(request, callback){
Meteor.call('getData', request.term, function(err, results){
callback(results);
});
},
select: function(event, ui){
// Do stuff with selected value
}
});
};
Which, if either, is the the most efficient way to setup a server-side autocomplete using Meteor with a large dataset?
For what it's worth, I'll offer a few of my thoughts on the subject. As a disclaimer, I'm just a Meteor enthusiast and not an expert, so please correct me if I've said something faulty.
To me, it seems like a potential advantage of pub/sub in cases like these is that data is cached. So when subscribing to the same record set, lookup will be near instantaneous since the client can search the local cache instead of asking the server for data again (publication is smart enough not to push repeated data to the client).
However, the advantage is lost here since you're stopping the subscription, so every time the user types the same search term, data is again pushed to the client (at least, the cursor's added event fires again for every document). In this case I would expect the pub/sub to be on nearly equal footing with Meteor.call.
If you want to cache the data of pub/sub, one way is to take out the sub.stop(). But unless your users have the tendency to search similar terms, caching the data is actually worse since with every letter the user types more data will be stored on the client, perhaps never to be seen again (unless searching is such a prominent feature in your app that the user would benefit from this?).
Overall, I see no compelling advantage with using pub/sub over Meteor methods, though I'm not versed in Meteor well enough to offer more specific advantages/disadvantages between the two. I personally think Meteor methods looks cleaner though.
If you're trying to implement a search feature though, I personally like the easy-search package, which supports this type of server-side search with autocomplete. In any case, I hope you get your question resolved! I'm curious to know the answer too.
I do front-end dev only like 10% of the time and am curious which is the better way to handle making ajax calls. These calls are just posting data to a web app that specifies an action name and an id.
<a href='javascript:addToList({'action':'set-default-time-zone','id':23})'>set default timezone</a>
<div class='add-to-list action-set-default-time-zone id-23'>set default timezone</div>
I have used both over the years but am not sure which one is preferred. It seems like they get to the same point in the end. Would you consider these to be the two best alternatives and is one better than the other?
I've implemented the div method as follows:
$(document).ready(function(){
$('.add-to-list').click(function(){
var id=getId($(this).attr("class"));
var action=getAction($(this).attr("class"));
$.post('/api/' + action,function(data){
...
},'json')
});
});
function getAction(str){
var parts=str.split(' ');
var phrase='action-';
for(i=0; i<parts.length; i++){
var val=parts[i].match(phrase);
if(val!=null){
var action=parts[i].split('action-');
return action[1];
}
}
}
function getId(piece){
var parts=piece.split('id-');
var frag_id=parts[parts.length-1];
var part_id=frag_id.split('-');
var id=part_id[part_id.length-1];
return id;
}
The link method would seem straightforward.
thx
Well the second approach is what you would call Unobtrusive JavaScript. It is believed to be a more robust approach (I'll avoid the term better here.)
However, your implementation is a bit over-complicated. It could be tuned down to:
HTML:
<div class="add-to-list" data-action="set-default-time-zone" data-id="23">
set default timezone
</div>
JavaScript:
$(document).ready(function () {
$('.add-to-list').click(function () {
var id = $(this).attr("data-id");
var action = $(this).attr("data-action");
$.post('/api/' + action, function(data) {
// ...
}, 'json')
});
});
The HTML5 specification allows for attributes starting with data- to be carrying user-defined data. And it's also backward compatible (will work with older browsers.)
Method 1:
<a href='javascript:addToList({'action':'set-default-time-zone','id':23})'>set default timezone</a>
Method 2:
<div class='add-to-list action-set-default-time-zone id-23'>set default timezone</div>
Method 2 is preferred because you would be practicing unobtrusive style of coding with a much clearer separation of your markup and your scripting code. It is alot easier to read and debug, and there for more maintainable. Also, i would propose instead of using CSS classes to pass data, to use the jQuery.data() method to store data on elements.