Hello StackOverflow community,
I'm looking for some help to migrate from Datatables 1.9 to 1.10. The notation is not the same anymore, so in order to keep the "old" code working with the new Datatables version, I need to map them. I wrote a json object "mapping", like that (it's just an extract), based on this link https://datatables.net/upgrade/1.10-convert :
var mapping : {"oLanguage" : {"sEmptyTable" : "language.emptyTable"}};
Now, I would like to create a JSON object from "language.emptyTable" to :
{"language" : {"emptyTable"}}
I tried some different recursive functions but... call stack and so on.
I know it's not a very clean method to upgrade to new version but I have at least a hundred Datatables in my app and can't modify all this code in time, I will do it step by step and not in a hurry.
Thank you very much for your help.
I was working on it since yesterday and found the answer just after I posted this message... So, if someone is interested by the answer, here it is:
<script>
var txt = 'language.search';
var fn = function(str) {
var obj = {};
var pos = str.indexOf('.');
//console.log(pos);
if(pos != '-1') {
//console.log(str.substr(pos+1));
obj[str.substr(0,pos)] = fn(str.substr(pos+1));
}
else if (str.length) {
obj[str] = {};
//return obj;
}
return obj;
};
console.log(fn(txt));
There is no need to convert options, jQuery DataTables 1.10 has backward support of options used by jQuery Datatables 1.9.
See Converting parameter names for 1.10:
The change is fully backwards compatible and you can continue to use the old versions of the parameter names and API methods as you were before.
Related
I am working on an angularJS widget (my first) and I currently am looking for an angularJS solution to my problem.
Basically I have one array containing a list of string values.
var array1 = [
"Need to Know",
"Test Category 2",
"News"
];
and another array containing another list of string values
var array2 = [
"need to know",
"release notes",
"NEWS"
];
I need a true statement if any element from one array matches any element from the other array. The result also needs to be case insensitive.
Here is my current solution and works great.
angular.module("myWidget", function(...){
// angular code here
})
.service('arrayService', function() {
function arrayToLowerCase(array) {
return array.join("~!~").toLowerCase().split("~!~");
}
function arrayElementIsInArray(array1, array2) {
for (var i in array1) {
if (array2.indexOf(array1[i]) >= 0) {
return true;
}
}
return false;
}
function arrayCompare(array1, array2) {
return arrayElementIsInArray(arrayToLowerCase(array1), arrayToLowerCase(array2));
}
return {
arrayToLowerCase: arrayToLowerCase,
arrayElementIsInArray: arrayElementIsInArray,
arrayCompare: arrayCompare
};
})
the problem is my javascript coders (I primary work in c#) feel there is a more angularJS way to do this but they have brought nothing to the table as a definitive solution. It was suggested that the $filter module might be useful but I didn't see how it would exactly solve my problem.
If I already have the best solution, then awesome. If not please let me know what you think and lets go from there.
Thanks in advance.
EDIT: In response to some of the answers, I felt that I might have misinterpreted my request. What I am asking is there a built in function that angular provides that does this out of the box?
After researching this a bit more; the $filter Module will probably do it with a custom comparater implemented but that seems like way overkill for what I am looking for.
The current responses are all good stuff though. Thanks again!
Absolutely nothing to do with Angular. This is plain data structures and data manipulation. To say there should be a more AngularJS way of doing it would be like saying there should be a more MVC way to add two numbers.
Angular provides no basic data structures and utility set of functions beyond what is available in your browser's native list of array functions, which is different depending on which ECMAScript standard the browser supports.
You may want to look into a library like Lo-Dash for stuff like this (which you can use right along with Angular with no problems) as it's preferable to have proven code for these kind of data manipulations than to constantly have to debug your own.
With Lo-Dash, and remembering the requirement for case-insensitivity:
var array1Lowered = _.map(array1, function (value) { return value.toLowerCase(); });
var anyMatchesBool = _.any(array2, function (value) {
return _.contains(array1Lowered, value);
});
Note that I'm making the assumption that there will be no non-string items in either array.
Lo-Dash normalizes the API so you don't need to worry about what functions each browswer supports. If there's a native function, Lo-Dash will use it because it's faster. If not, Lo-Dash provides an all-JavaScript implementation.
Try this on for size. To me this really has nothing to do with Angular
(function(array1, array2) {
var tlc = function(a) { return a.toLowerCase(); };
array2 = array2.map(tlc);
array1 = array1.map(tlc);
return array1.filter(function(n) {
return array2.indexOf(n) != -1;
}).length > 0;
})(array1, array2);
Using native functions...
var intersection = array1.filter(function(n) {
return array2.indexOf(n) != -1
});
With help from Simplest code for array intersection in javascript
I am using bootstrap-typeahead in order to allow multiple selection.
Here is the demo.
The original code has been update by #Sherbrow Twitter bootstrap typeahead multiple values
My question is related to the following use case:
after inserting Alaska value, I would like to update the source not showing again Alaska value.
Any hints?
I had the same problem and this one will save you a lot of time. I've updated your old jsFiddle with my code example. The basic thing is that you need to do
var autocomplete = $('input').typeahead();
autocomplete.data('typeahead').source = newSource;
Where newSource is the new array. Now you just need a function that adds or removes an element, or whatever you need to do with it.
None of the given answers worked for me, I had to destroy the original typeahead instance and re initialize it.
$('input').typeahead('destroy').typeahead(options);
Based on the default updater method of typeahead :
updater: function (item) {
var pos = this.source.indexOf(item);
if(pos != -1) {
var newSource =
this.source.slice(0,pos)
.concat(this.source.slice(pos+1));
this.source = newSource;
}
return item
}
Demo with multiple values (jsfiddle)
Keep in mind that you can access this source from anywhere with $('sel').data('typeahead').source considering that the typeahead is initialized
I've been staring at this for hours and could really use some help. I'm working with some existing code for a movie theater website and the following should fill a select list with dates ranging from today to a max date from an xml file.
function populateSelect(xmlDoc, elSel) {
var dmindate = new Date();
var showings = xmlDoc.getElementsByTagName('Session');
fmaxdate = "";
for (var showing = 0; showing < showings.length; showing++) {
if (retText(showings[showing].getElementsByTagName('Date_time')[0]) > fmaxdate) {
fmaxdate=retText(showings[showing].getElementsByTagName('Date_time')[0]);//get the Max Date
}
}
var dmaxdate = new Date.parseString(fmaxdate, "yyyyMMddHHmmss");
while(dmindate <= dmaxdate){ //Fill in the Select List
var elOptNew = document.createElement('option');
elOptNew.text = dmindate.format("EE NNN d, yyyy");
elOptNew.value = dmindate.format("MM/dd/yyyy");
dmindate.setDate(dmindate.getDate()+1);
try {
elSel.add(elOptNew, null); // standards compliant doesn't work in IE
}
catch(ex) {
elSel.add(elOptNew); // IE only
}
}
}
This works perfectly fine in FF, Chrome and Safari but IE8 doesn't display the dropdown with dates and it showed the Invalid Argument as being the same line as the closing bracket for try.
Any help would be greatly appreciated!
I don't know where Date.prototype.parseString or format methods come from, presumably you are adding some date library. They aren't part of ECMAScript ed 3 or 5.
You can replace these lines:
> var elOptNew = document.createElement('option');
> elOptNew.text =dmindate.format("EE NNN d, yyyy");
> elOptNew.value = dmindate.format("MM/dd/yyyy");
with:
var elOptNew = new Option(dmindate.format("EE NNN d, yyyy"), // option text
dmindate.format("MM/dd/yyyy")); // option value
then add it to the select:
elSel.appendChild(elOptNew);
The above will work in all versions of IE and other browsers. See http://dev.w3.org/html5/spec/single-page.html#the-option-element for details of the Option constructor.
Edit
In the DOM 2 HTML specification for the add method it says:
This method is the equivalent of the appendChild method of the Node
interface if the before parameter is null.
That doesn't mean to pass the ECMAScript null object, it means "if there is no second parameter". The specification is language neutral, it isn't javascript specific. The HTML5 OptionsCollection add method is the same (i.e. "null" means no parameter, not the javascript null object).
From the documentation I could find, having a null parameter doesn't make any sense. However, it is clear that the JavaScript engines in the different browsers handle this method differently, and that IE doesn't like null as the second parameter.
So, as per the mantra, you should use jQuery. It is good and does all things. It does actually help protect you from differences between browser implementations of the DOM, because it has a fairly broad compatibility. It fixed this guy's issue anyway.
You will probably want to use append() instead of the add(). For example:
var elOptNew = $('<option></option>');
...
elSel.append(elOptNew);
There is also an alternative way to add new options in to a select, i.e
var opts = elSel.options;
opts[opts.length] = new Option(dmindate.format("EE NNN d, yyyy"), dmindate.format("MM/dd/yyyy"));
Example that works in all mejor browsers.
Try to use
elSel.options.add(elOptNew)
This must work in all browsers. See example.
I have single html file that contains 10000 list items that needs to be in single html file
order by categories for example ordered by the ABC not all of them needs to be shown.
each time only 500 ( so the other are hidden ) .
what way or method can efficiently rearrange me the list in this way ?
java script ? css?
its all in client side , no server side.
You can use this to alphabetize your list:
var list = document.getElementById("myList");
var listItems = [].map.call(list.getElementsByTagName("li"), function(item) {
return { text: text(item), element: item };
});
function sortList() {
var frag = document.createDocumentFragment();
listItems = listItems.sort(function(a, b) {
return a.text < b.text ? -1 : b.text < a.text ? 1 : 0;
});
listItems.forEach(function (item) {
frag.appendChild(item.element);
});
list.innerHTML = "";
list.appendChild(frag);
}
function text(el) {
var s = el.innerText;
if (!s && s != "") {
s = el.textContent || "";
}
return s.toLowerCase();
}
Working demo: http://jsfiddle.net/4bm57/6/
To filter the list:
function filterList() {
var frag = document.createDocumentFragment();
listItems.forEach(function (item) {
if ([filter criteria code here]) {
frag.appendChild(item.element);
}
});
list.innerHTML = "";
list.appendChild(frag);
}
This code uses Array methods not available in some older browsers. For this code to work in IE8 or earlier, see the compatibility sections for Array.map() and Array.forEach().
A Datatable with Pagination is way to go.
Below example is a JSF component but I think it is good enough to give you the idea.
Example: DataTable Handling Large Data
I would reccommend that you look at KnockoutJs. It has all the features you may want.
It is designed to work with significant amounts of data that is client side.
You can dynamically create grids of different completely formats easily by using differing templates to display you data. See http://www.knockmeout.net/2011/03/quick-tip-dynamically-changing.html.
You can implement live searching easily. See http://jsfiddle.net/rniemeyer/cCBqJ/ for example. Using this example, you can also implement custom filtering to only display the data of interest.
You can implement any sort of dynamic sorting you would like. See http://jsfiddle.net/rniemeyer/93Z8N/ for a simple example. You can also chain output of filter into sort routine.
You can implement pagination easily by chaining a paging filter after the sorting function.
So you can easily slice and dice and show the data anyway you would like.
Downside is that there are not current a single open source project to that support generalized grids with sorting, filtering and client side paging. There are various partial implementations. Best information is at http://www.knockmeout.net/ and https://groups.google.com/forum/#!forum/knockoutjs.
I'm currently using all of the above features in my current project. KnockoutJs does have a learning curve. But I found it the best way to do this type of data presentation.
I'm using Zepto.js, a lightweight jquery clone. But that framework doesn't use .data() in the same way as jquery. Now I need to use this code:
var position = new Array;
$('#ipadmenu > section').each(function() {
position.push($(this).data('order'));
});
But I have no idea how to make this work on my framework.
How would I convert this to pure javascript? I have never really worked with arrays so i'm quite lost... also, might I have skipped something in the zepto doc (https://github.com/madrobby/zepto) that could help me with this? .get() for example?
Here is the HTML code. Basically I want to add all sections (the amount can change) into the array:
<nav id="ipadmenu">
<section data-order="0">
<a><p>text</p></a>
</section>
<section data-order="1">
<a><p>text</p></a>
</section>
</nav>
thank you for your help!
Based on my 30 second review of the zepto docs, it would look like this.
var position = new Array;
$('#ipadmenu > section').each(function() {
position.push($(this).data('order'));
});
the zepto docs you linked to say it supports all of the jquery methods in your snippet.
What about the data doesn't it handle? If it really doesn't handle data the same it also supports attr so you could say:
var position = new Array;
$('#ipadmenu > section').each(function() {
position.push($(this).attr('data-order'));
});
Here an alternative "pure" javascript solution:
var position = [];
var aSections = document.getElementById('ipadmenu').childNodes;
for (iIndex in aSections) {
if (aSections[iIndex].nodeName == 'SECTION') {
position.push(aSections[iIndex].getAttribute('data-order'));
}
}
Also see my jsfiddle.
=== UPDATE ===
A little smaler solution:
var position = [];
var aSections = document.getElementById('ipadmenu').getElementsByTagName('SECTION');
for (i = 0; i < aSections.length; i++) {
position.push(aSections[i].getAttribute('data-order'));
}
Here the new jsfiddle.
If you are using the data-* attributes then you can access them through the new dataset object available in HTMLElement. dataset is a StringMap object so you access the values using camel cased attribute names as the keys. If dataset is not available (if browser isn't HTML5 compatible or dataset spec is not implemented in the browser) then you can access the attribute using the regular attribute retrieval method.
So, if you have:
<script type="text/javascript">
var dataSet = document.getElementById("input1").dataset;
for(var key in dataSet) {
console.log("attribute is: " + key);
console.log(dataSet[key]);
}
</script>
<input type="text" id="input1" data-custom-attribute="some value"/>
Zepto support $(elem).data("attr-name") method, when you use a Custom Build of Zepto with "data" module. So, you can use same code for jquery and Zepto