I have a webpage with multiple images loaded using a JSON File with schema something like -
[
{ "item" : "Lotus",
"images" : [ "images/lotus1.jpg", "images/lotus2.jpg", "images/lotus3.jpg" ]
},
{ "item" : "Tulip",
"images" : [ "images/tulip1.jpg", "images/tulip2.jpg", "images/tulip3.jpg" ]
}
....
]
If I want to add a search functionality on the page and dynamically show only the relevant images.
for eg. If a user wants to search for a particular flower and enters search text as "Tu", images with name having the search text should be displayed.
What technique, libraries or procedure I can follow? Is it possible to handle this only through front end or Does this percolate till the back end?
Any pointers are really appreciated!
I recommend you to read this page http://api.jquery.com/find/ and try
One way would be to display all the images on one page and let the isotope plugin take care of the filtering.
Here is a link to the docs on filtering.
As a bonus it comes with fancy CSS effects, which make sorting a real pleasure ;)
You can find the code which addresses filtering by typing in a search field here.
It basically works by adding the names of your images as class names, showing only the ones that match your search while hiding the other classes.
However, if you have to deal with large amounts of images, this might not be an ideal solution, as all the images are loaded in advance to make this work. In this case, server side handling of the search would be the way to go.
Edit
Here is another example on how to filter with a search field and isotope.
I think the best way to do this is with the back end. You should have your server return a json file with only relevant images, then your client side doesn't have to process that, and it could even be cached.
Otherwise client side it would just be an issue of looping through all the image "items", and searching for the query with .indexOf in the name. However, this would put a lot more work on your client side and probably make your site slower.
If you'd like to keep it all in the front-end, you can use underscore.js. There are ways to filter through a array/object, see: http://underscorejs.org/#filter. You would query using regex to match against all the item names, example:
var images = [{ "item" : "Lotus", "images" : [ "images/lotus1.jpg", "images/lotus2.jpg", "images/lotus3.jpg" ]},{ "item" : "Tulip","images" : [ "images/tulip1.jpg","images/tulip2.jpg", "images/tulip3.jpg" ]}];
var searchResults = _.filter(images, function(obj){ return /lot/i.test(obj.item) });
This would return an object, with only the lotus, and all of the images needed. See fiddle: http://jsfiddle.net/cbM5W/1/
This does use the underscore library, but you could implement this with vanilla JS.
Related
For a dynamic system, which is a "bag" and some "parts" in it, I am trying to make an edit-page. It should be able to get the bag and the parts. Getting the data from the backend is no problem, but saving it is.
I tried to give each "part"-Input field names like name="parts[][partName], name="parts[][internalNumber] and so on, but the $_POST-Array has a strange structure of many arrays:
parts [
[partName = "Test1"],
[internalNumber = "111"],
[partName = "Test2"],
[internalNumber = "222"],
...
]
I think that relying on counting and dividing doesn't seem like a reliable method to me, especially because most of the inputs can be empty.
Working with fixed names, like "parts[0][...]", "parts[1][...]" would be kind of difficult because of the dynamic structure by adding, removing and editing the groups.
What would be the best way to get the data reliably?
Hopefully I explain this to where it makes sense, the most I could find by searching terms like I used in the title gave plenty of autocomplete examples, but nothing quite what I'm looking for. I have a list of buttons (they're coded as inputs right now) and I want to add a search field that will narrow down the buttons as the user types in a search field.
Say for example, I have 30 buttons with popular websites. If a person wanted to pull Google, they'd start typing it out which would start by including everything with the letter "G" in it, then "O", etc. Everything else would "disappear" from the page.
I can sort of think of a way to do this manually, but I think my code wouldn't be DRY. Possibly set an "on" and "off" ID, and use CSS to display:none or something to that effect.
I think the best way to do this would be via AJAX, but there may be some javascript voodoo more applicable.
To easy. At first, its unneccessary to filter the answers serverside, if all the data is already at the users. Also, you shouldnt write html and filter it with js, you should write it in js and generate an html output. Lets start with the structure:
var links=[
{
name:"google",
url:"http://google.com"
},
{nextone}
];
Now generate the links in html:
window.onload=function(){
var container=document.body;//change this to your needs
for(i=0;i<links.length;i++){
var link=links[i];
link.html=document.createElement("a");
link.html.innerHTML=link.name;
link.html.src=link.url;
container.appendChild(link.html);
}
};
If sth is inputed, hide the the unmatched ones:
function filter(string){
//loop trough links
for(i=0;i<links.length;i++){
var link=links[i];
//if string doesnt match name
if(!link.name.split(string)[1]){
link.html.style.display="none";
}else{
link.html.style.display="block";
}
}
}
Use like this:
filter("goo");
You could bind that to an input:
yourinput.addEventListener("onchange",function(){filter(this.value)},false);
I'm creating a front-end React application which has no back-end logic. In this application, users can enter data into multiple form fields. I'm wanting to allow users to link directly to the application with their fields filled in based on data stored in the URL. The problem is, I don't know if there's a way of generating a nice looking URL with JavaScript alone.
Ideally I'm wanting the end-result to look something like this:
http://example.com/#/.../sdf098sdfipodfi0sf3j
...when the user loads up that URL, it should decrypt the string and restore the saved data (how resources like Codepen and JSFiddle allow linking directly to results, but without a back-end or database).
Here's an example of the data I have:
{
"Episodes": [
{
"Id":"1",
"Age":"25",
"SEX":"1",
"Diagnosis":["1","2","3","4","5","6","7","8","9","10"],
"Procedure":["1","2","3","4","5","6","7","8","9","10"]
}
]
}
There problem I'm having is that there can be:
Up to 250 Episodes.
Up to 999 Diagnoses and Procedures within each.
The above requirements are absolute extremes and for the most part there will probably only ever be around 5 or 6 Episodes each with around 10 Diagnoses and 4 or 5 Procedures.
If I stringify and then encode the JSON object and stick that in the URL, I'll end up with an incredibly ugly output riddled with % symbols:
http://example.com/#/.../%7B%22Episodes%22:%5B%7B%22Id%22:%221%22,%22Age%22:%2225%22,%22SEX%22:%221%22,%22Diagnosis%22:%5B%221%22,%222%22,%223%22,%224%22,%225%22,%226%22,%227%22,%228%22,%229%22,%2210%22%5D,%22Procedure%22:%5B%221%22,%222%22,%223%22,%224%22,%225%22,%226%22,%227%22,%228%22,%229%22,%2210%22%5D%7D%5D%7D
If I go further and convert that into Base64 using btoa, I get something which looks more like a shortened URL, but bearing in mind this is with the demo data I've provided above, this becomes way too long:
http://example.com/#/.../JTdCJTIyRXBpc29kZXMlMjI6JTVCJTdCJTIySWQlMjI6JTIyMSUyMiwlMjJBZ2UlMjI6JTIyMjUlMjIsJTIyU0VYJTIyOiUyMjElMjIsJTIyRGlhZ25vc2lzJTIyOiU1QiUyMjElMjIsJTIyMiUyMiwlMjIzJTIyLCUyMjQlMjIsJTIyNSUyMiwlMjI2JTIyLCUyMjclMjIsJTIyOCUyMiwlMjI5JTIyLCUyMjEwJTIyJTVELCUyMlByb2NlZHVyZSUyMjolNUIlMjIxJTIyLCUyMjIlMjIsJTIyMyUyMiwlMjI0JTIyLCUyMjUlMjIsJTIyNiUyMiwlMjI3JTIyLCUyMjglMjIsJTIyOSUyMiwlMjIxMCUyMiU1RCU3RCU1RCU3RA==
Is there a nicer way I can condense a lot of information into a relatively small string which would fit nicely in a URL, without any back-end logic?
Ideally I'm wanting a native JavaScript solution, but I appreciate that may not be possible.
How uniform is the data structure?
I can see that with the example you've given above:
{
"Episodes": [
{
"Id":"1",
"Age":"25",
"SEX":"1",
"Diagnosis":["1","2","3","4","5","6","7","8","9","10"],
"Procedure":["1","2","3","4","5","6","7","8","9","10"]
}
]
}
You could reconstruct that with:
http://example.com/#/.../E1I1A25S1D10P10
But that's still a 15-character shortcode for 1 episode... so if there were 6 episodes, that would increase to around 90 characters.
I am surprised that no one on StackOverflow asked this question before.
Looking through the JSON object documentation and a quick google search did not yield satisfactory results.
What's the advantage of it? How does it work?
Edit: To make it clear, take a look at this flatten/un-flatten example.
Fastest way to flatten / un-flatten nested JSON objects
Thank you.
There are many situations where you get JSON text that was automatically built by some library. Throughout the programming languages, there are many libraries that build JSON text (one example is here).
Whenever libraries add some additional object or array wrappings, you might want to get rid of them maybe because you send the JSON to the server and your code there crashes because it expects a primitive value instead of an object (or an array). Or, if your JSON is a server response, you don't want the resulting Javascript code having to differ between object/array or not object/array. In all these cases, flattening is helpful as it will save you time. You will have to implement lesser if/elses, and you can reliably expect your data structure to be as flat as possible.
The other approach to improve code for the scenario mentioned is to write the code in a maximal robust way so there is no way for it to crash by superfluous wrappings ever. So always expect some wrappers and get it's contents. Then, flattening is not needed.
You see, it depends on what is building the JSON and what is parsing it. The building may be out of your scope.
This leads also to data model questions. I've worked with XML code that needed to be parsed quiet a different way if there where 0 entries of some XY, or if there were >0 entries of some XY. Having a wrapper that is allowed to have 0 or more entries of some XY will make live easier. These are data model desicions.
In all cases where the JSON represents an object structure that I've combined manually, I expect it not to change. So flattening something I've designed in detail would be disturbing. Standard operations as far I've seen them do not need flattening (e.g. JSON.stringify(), json_encode() etc.)
Here's a simple scenario: In a web app you have an HTTP POST that is updating a complex relational object.
POST
update=1
&user.id=12345
&user.email=testmail#domain.tld
&user.profile.name=Mr. Test
&user.profile.age=42
&user.profile.friend.0.email=tom#domain.tld
&user.profile.friend.1.email=sally#domain.tld
&user.profile.friend.2.email=bob#domain.tld
&user.profile.skill.0.id=100
&user.profile.skill.0.name=javascript
&user.profile.skill.1.id=200
&user.profile.skill.1.name=piano
Everything is already in a flat structure, so why not have a simple one-to-one binding? If you had a list of constraints or security requirements that you needed to enforce you could validate them by searching directly on the sorted key list.
Flat structures are easier for people to understand and work with there's even some cross-over with database de-normalisation. It also allows for context specific security and constraints to be implemented in a readable, but more verbose way.
When showing a user's view in full you may want to hide the display of the primary key ID for the user's list of skills.
"user.profile.skill.#.id": { hidden: true, readonly: true }
But when looking directly at a skill (to possibly edit it as an administrator) you may want to see the ID.
"skill.id": { readonly: true }
If you were writing a user-centric/self-service type CMS application you'd get more users on board and able to contribute using a straightforward flat model (flat abstraction of the underlying nested relational model) than you would with just the nested model.
TLDR: Flat is easier to read than nested. While programmers can handle nested schemas, recursive parsing and processing; end-users and admins usually prefer that part abstracted away.
I realize this is a 5 year old question at this point, but I figured, I'd add my thoughts to it, in case someone runs into a similar use case and finds this useful.
One of the use cases why you would want to flatten a JSON object, is for dynamic template binding via Regular Expression (RegEx) string interpolation. Well wasn't that a mouthful 👀😅? It simply translates to "template filling a string without hardcoding".
Ok Imagine a scenario, you have a template string like this for an email:
Hello {{firstName}},
It is amazing you chose to join our site. We are happy to have you on board.
To get started, we would really love it if you can confirm your email address
by clicking on the link: {{confirm_url}}.
Welcome aboard
The Team!
Given the following JSON object in memory:
{
"user" : {
"prefix" : "Dr.",
"firstName" : "Awah",
"lastName" : "Teh",
"email" : "awah#superduperubercoolsite.com",
"address" : {
"street": "100 Main St",
"city" : "PleasantVille",
"state" : "NY",
"phone" : "+1-212-555-1212"
}
},
"meta" : {
"confirm_url" : "http://superduperubercoolsite.com/confirm/ABC123"
}
}
it seems super simple to do a Regular Expression replace like so (assuming our email template string was stored in a variable named template and the json object was stored in a variable called templateData:
template = template.replace(new RegExp('{{firstName}}', 'g'), templateData.user.firstName);
template = template.replace(new RegExp('{{confirm_url}}', 'g'), templateData.meta.confirm_url);
Easy right? --> Actually yes! How about this email had 10 templated fields, or you wanted to decouple the template from the code, by storing it in a separate system like SendGrid, where your cool head of marketing can access the template and make changes to the copy-language, without having to call someone from engineering to make changes to the code, test the code and redeploy to production (what a hassle).
This is exactly where flattening of the JSON comes save the day!
Now there are many ways to flatten JSON, I have attached a link to a codepen I wrote that has logic to flatten JSON (actually, I demonstrate two similar but different approaches in the methods flattenJSONIntoKVP and flattenJSONIntoRAW check 'em out!).
That said, there are other implementations out there, and it is worth remembering that the focus on this post is to discuss the WHY JSON flattening could be useful, not the HOW.
Moving on! Assume you flattened the JSON from above (using my implementation that results in key value pairs) to something like this:
[
{ "key": "user.prefix", "value": "Dr."},
{ "key": "user.firstName", "value": "Awah"},
{ "key": "user.lastName", "value": "Teh"},
{ "key": "user.email", "value": "awah#superduperubercoolsite.com"},
{ "key": "user.address.street", "value": "100 Main St"},
{ "key": "user.address.city", "value": "{PleasantVille"},
{ "key": "user.address.state", "value": "NY"},
{ "key": "user.address.phone", "value": "+1-212-555-1212"},
{ "key": "meta.confirm_url", "value": "http://superduperubercoolsite.com/confirm/ABC123"},
]
Now, my friend, you are cooking with GAS!
Why, cause now you can dynamically interpolate the template string with values from the JSON object without giving too much worry to the structure of the JSON (if it changes due to the application evolving, you don't have to also remember to come down here and change this interpolation code -- you simply just have to update the email template itself, which mind you, is on SendGrid [per this example]).
So how to do it you say?: Simple, iteratively. Let's assume that flattened from above was stored in a variable called flatJSON:
///Notice how I use Javascripts native string interpolation to create my RegExp
///Also note that I am replacing the dot (.) in my flattened JSON variable names with a double underscore (__), I only do this because my intended target is SendGrid, and I don't believe it likes dots in its template placeholders.
flatJSON.forEach(kvp=>template = template.replace(new RegExp(`{{${kvp.key.replace(/\./g, '__'}}}`, 'g'), kvp.value));
That's it, one line of code to replace possibly 10 or even hundreds or even thousands (ok.. maybe not thousands, but you get the point).
Ohh! almost forgot, we need to update our template string.
Notice how now, in our new templated string we can use a somewhat FQDN style variable to map back to our original JSON (Ideally if SendGrid supported dots in their template placeholders, this would look super sweet but alas, can't always win everything!ðŸ˜.
Hello {{user__firstName}},
It is amazing you chose to join our site. We are happy to have you on board.
To get started, we would really love it if you can confirm your email address
by clicking on the link: {{meta__confirm_url}}.
Welcome aboard {{user__prefix}} {{user__lastName}}!
The Team!
Et Voila!
Just like that, we have accomplished some good here today; we have:
Answered the WHY of flattening JSON objects
We dibble-dabbled into the how, with the codepen example
And we even overviewed a use case where taking advantage of JSON flattening can help you write durable dynamic code, that evolves as your underlying object structures change -- and that doesn't require you to leverage the big bad ugly eval method (we can talk about big bad ugly eval on another post).
I have implemented jquery auto suggestions in my application which has a bunch of cities in it. The problem is it showing every strings which has the entered query. if i type how it shows all the strings which has 'how' in it in between..
The following is the list of results i get if i type how but i prefer to get it in a different order which i descrided and i don't want to show other results. I dont want to show other results.
Bhowra Bh
Chalk howa <--------------------------------This should come third
Chowka Ghat
Chowrigacha
Howbagh Jabalpur <--------------------------This should come first
Howrah <------------------------------------This should come second
Khowang
Ladhowal
Majhowalia
MHOW
Mhow
Mount Howrah <------------------------------This should come fourth
Pehowa Road
Pipalwali Chowki
Saheed Ishwar Chowdhary H
how do is make this work. here is the code i use.. or is there any other way to achieve this in javascript without jquery..?
$(".selector").autocomplete(/*parameters*/);
NOTE: I use an array to store the city names and use them as source for auto complete. And i don't use AJAX
You can use a callback to do the filtering and sorting yourself.
$(".selector").autocomplete(
source: function(request, response) {
// filter parameters based on request.term
response(/*params*/, request.term);
}
);
It's also possible to alter the search term at that point, but that wouldn't work in this case.