Implement ajax save in form - html

I'm implementing a virtual tour application, and want to add ajax functionality to the tour build process.
I have a number of mini-forms on the page, the number of which is determined by the count of images in a specified directory.
So the page currently looks like
---------------------------------------------------
| | Location
| | Latitude
| Thumb | Longitude --------
| | | Save |
|-------------- --------
|
---------------------------------------------------
---------------------------------------------------
| | Location
| | Latitude
| Thumb | Longitude --------
| | | Save |
|-------------- --------
|
---------------------------------------------------
---------------------------------------------------
| | Location
| | Latitude
| Thumb | Longitude --------
| | | Save |
|-------------- --------
|
---------------------------------------------------
and goes on for n number of images.
What I'd like to do is have the save button execute an ajax function to save the information
without refreshing the page. My issue has to do with the button IDs. As the form is rendered via PHP echo statements in a loop, I can add the loop number to the button ID, but how can I use said ID in a jquery function?
Specifically,
$("#save").click(function(){
//ajax POST code goes here
});
won't work when the #save has a number added to the end.
What other options do I have to implement ajax functionality to these forms?

I would add a class to each button then attach the click event to that class and then find the ID that way. Then you can run your AJAX.
Like this:
$('.buttonClass').click(function (){
var id = this.id;
var $thisButton = $('#' + id);
//Can do jQuery stuff with $thisButton now
//Run AJAX
});
Just make sure you add the class to every save button.

EDIT
I may have misunderstood your question --- I thought you were looking to upload images via these forms. The first part of my answer would apply, the second part is probably not relevant. You could still use the method, even with the form you've got (no file elements), but there are other methods that may be more "common" for your use case.
It looks like you're using jQuery, but I'll talk about vanilla methods for this before I get in to the "jQuery Way"
Your goal here is twofold: first, differentiate between forms so you can keep track of which for is doing what, and second, you want to submit your form via an IFRAME to simulate AJAX-like form submission.
The first part is easy: use some kind of unique identifier for the form element, the button, and the container itself:
<div class="oneFormContainer oneFormContainerGTRX2">
<form class="oneForm oneFormGTRX2" id="GTRX2">
<!-- form elements -->
<button class="oneFormButton onFormButtonGTRX2" rel="GTRX2">Submit</button>
</form>
</div>
In this example, the entire shebang has a unique identifier of "GTRX2" (a random string), so I put that on each element as a class. I prefer to deal with classes rather than ids, but you could do the same thing with ids for the most part. The bottom line here is that when the button is clicked, one can read the rel attribute and quickly locate the associated container (to show a loading message) and the associated form (to submit it).
The second part of the goal here, as I mentioned, is to submit the form to an IFRAME. This might be surprising, given that IFRAMEs have a bad rap, but in this case you're going to use a hidden one to simulate an AJAX request -- that is, you are going to use a normal form post, but it will happen asynchronously to the page load. This strategy is required because, using the standard XHR method for AJAX, one cannot submit a file.
In pseudo-javascript, then:
onPageLoad {
// add a 'click' event to all elements with the class "oneFormButton"
document.body.getElementsByClassName('oneFormButton').addEvent('click', handleFormUpload);
}
handleFormUpload {
var uid = clickedButton.get('rel');
var form = document.getElementByClassName('oneForm'+uid);
var container = document.getElementByClassName('oneFormContainer '+uid);
// make a hidden iframe element, add to body
var iframe = createElement('iframe');
iframe.id = 'ajFormSubmitFrame'+uid;
iframe.name = 'ajFormSubmitFrame'+uid;
iFrame.style.position = 'absolute';
iFrame.style.top= '-9000';
iFrame.style.left= '-9000';
iFrame.style.width= '10px';
iFrame.style.height= '10px';
document.body.appendChild(iFrame);
// tell the form to target the iframe
form.target = 'ajFormSubmitFrame'+uid;
// add an onload event to capture the return
iFrame.addEvent( 'load', uploadCallback );
// show some kind of loading message
showLoader(container);
// submit the form
form.submit();
}
uploadCallback {
// deal with the response
// and be sure to remove that iFrame, reset the target property of your form, and clean up the loading message
}
Whew! With all that understood, popular libraries usually encapsulate this into some kind of magic. You have these:
http://valums.com/ajax-upload/ - for jQuery
http://pixeline.be/experiments/jqUploader/ - for jQuery
http://www.fyneworks.com/jquery/multiple-file-upload/#tab-Examples - for jQuery
http://mootools.net/forge/p/form_upload - for mootools (Hurray!)
Don't get the idea you have to use a library for this -- using the pseudocode above as a basis, it would not be very difficult to roll your own that does exactly what you want and need without the clunky library overhead.
Also, you have the new FileReader API to consider (beyond the scope of this answer), see the docs for examples: https://developer.mozilla.org/en/DOM/FileReader

Related

How to include a template variable in a MediaWiki extension tag?

I would like to invoke this tag from within a template:
<splist
parent={{{1}}}
showparent=no
showpath=no
kidsonly=yes
liststyle=bar
debug=1
/>
As you can see a template variable needs to be filled in here. But unfortunately MW does not do that.
My question: How to accomplish this? How do I need to call the extension in order to get the variable data filled into parameter parent?
Use {{#tag:}} parser function:
{{#tag:splist
| parent={{{1}}}
| showparent=no
| showpath=no
| kidsonly=yes
| liststyle=bar
| debug=1
}}
See https://www.mediawiki.org/wiki/Help:Magic_words#Miscellaneous.

Angular 5 - add tooltip to string, possibly with Angular Material 2 mat-tooltip

I would like to dynamically add tooltips to some text. Ideally I would like to do so with the built-in tooltips shipped with Angular Material 2, but also a custom solution will do.
As an example, in the sentence the dog is barking, I would like to add to the word dog a tooltip displaying german shepherd.
The text is currently shown like this: <p>{{ stringFromSecureServer }}</p>.
So far I've tried with a custom pipe (addTooltip) with which I find and replace text:
transform(value: string): any {
value = value.replace('dog', '<span matTooltip="german shepherd">dog</span>');
value = this.sanitizer.bypassSecurityTrustScript(result);
return value;
}
If then I inject in the page the text with <p [innerHTML]="stringFromSecureServer | addTooltip"></p>, the text is actually modified, but matTooltip (Angular Material 2 component) is converted to mattooltip and it won't work.
Assuming that the problem was somehow linket to AM2, I've tried with a custom Directive, based on the excellent guide by Netanel Basal.
While the custom [tooltip] Directive is working with statically typed DOM elements (e.g. <span tooltip="test">test</span>), this still does not work when I find and replace the text as shown above.
Is there a way to achieve what I'm trying to do?
PS
As far as I can tell, I should not have XSS issues because all the strings that I need to work on are NOT user generated. All strings are served by the server through an https connection (Let's Encrypt auto renewed cert)

Prevent search engines from scanning preview of other pages

I've got a website. After every article there is a big (7 sentences) preview for another article.
The problem is that google index this preview, and it makes my content duplicate.
How can I tell google not to read those previews?
One effective though less-than-ideal solution could be to load the random article preview with Javascript. It's similar to how some blogs have a "click to load comments" button - they don't want their blog being associated in Google searches with everything their commenters say.
Since you're keeping the primary content of each page the same, I don't think this would be a cloaking issue, but no guarantees.
You can do this by putting the preview section in a different span that would be hidden by Css properties and displayed using javascript at the time of page loading.Since the section is initially not displayed thus it would not be read by the search engine.
Dummy Html code
<span class="pgPreview">The preview for the next pages goes here </span>
Css code to hide it
.pgPreview {
display:none;
}
Javascript code to show it.
<script type="text/javascript">
$(document).ready(function()
{
$(".pgPreview").show();
}
</script>
Assuming that you have the jquery library included.
Reference
I know there used to be a system of labels such as:
<!-- googleon/googleoff: <index|anchor|link|all> -->
...but I do not know if that still works on these days...
also, I think it was only valid if you were using google custom search.
(do not really know for sure)
In any case, I can think in two ways to do what you need:
A) Hide content in iframes
B) Generate a text-image with that preview text
lolum dolimus
situs amen amdu etr --> normal content
nulusan ar sindh ew
_____________________
| lolum dolimus |
| situs amen amdu etr | --> iframe blocked with
| nulusan ar sindh ew | robots.txt file
---------------------
_____________________
| lolum dolimus | image with text
| situs amen amdu etr | --> unreadable to
| nulusan ar sindh ew | search engines
---------------------
Of course, both options are not completely infallible and depends solely on whether the search engine follow the directives in standardization and/or the ability to have OCR recognition.

Named anchor in a Single Page Application (SPA)

In a SPA, using a navigation framework such as Sammy.js, how could I use in page named anchors for in-page navigation?
e.g. Say I have a route like localhost/myapp/#/somerecord/1 where the application loads somerecord with id = 1.
However somerecord is really complicated and long. I want to be able to jump to a certain section using a named anchor.
Say an article element is defined like <article id=section-d> ... </article> and I just link to like <a href=#section-d>Section D</a> it technically works, but the URL reads like localhost/myapp/#section-d, this breaks the navigation stack. Hitting the Back button takes me back to localhost/myapp/#/somerecord/1 and without jumping back to the top.
The preferred action would be to either jump back to the top or to the previous page. Any ideas on how to accomplish this?
Effectively, you have to define your URL as a regular expression, and allow an optional bookmark hash at the end of it; something like:
get(/#\/somerecord\/(\d+)(#.+)?/, function() {
var args = this.params['splat'];
var recordId = args[0];
var articleId = args[1];
});
This should match any of the following routes:
#/somerecord/1
#/somerecord/1# (treated as if there is no article id)
#/somerecord/1#section-d (articleId = '#section-d')
You should then be able to use the articleId to find the matching element and manually scroll. e.g. in the last route above, using jQuery you could do something like:
var $article = $(articleId);
$(document.body).animate({ scrollTop: $article.offset().top });
});
I've just written up a more comprehensive article about this (using Durandal), if you're interested: http://quickduck.com/blog/2013/04/23/anchor-navigation-durandal/
Edit
Link is dead. The article available here http://decompile.it/blog/2013/04/23/anchor-navigation-durandal/
I've had the same problem using durandal with sammy.js. Basically, you have to create a (invisible) route for each anchor you want on your page. See a post from me about the solution I found: http://papamufflon.blogspot.de/2013/04/durandal-scrollspy.html

Getting inputs inside of a form tag

I have a form with id and multiple inputs with ids as well how i get a specific input inside a form tag.
<form action="#" method="post" id="frm-location">
<input type="text" name="txt-location" id="txt-location" />
</form>
what I want is to get the txt-location from the frm-location
You want a reference to the <input> element itself?
var form = document.getElementById('frm-location'),
input = form.getElementsByTagName('input');
// or, more specifically:
var form = document.getElementById('frm-location'),
input = form['txt-location'];
// if the name didn't have a dash in it, you could write this instead:
input = form.txtLocation;
// or, even better, since the input has an ID:
var input = document.getElementById('txt-location');
https://developer.mozilla.org/en/DOM/document.getElementByID
https://developer.mozilla.org/en/DOM/element.getElementsByTagName
https://developer.mozilla.org/en/HTML/element/form
https://developer.mozilla.org/en/DOM/element
You want the value of that element?
var input = /* whatever */,
inputValue = input.value;
https://developer.mozilla.org/en/DOM/HTMLInputElement
HTML is a static type markup language. As such, by itself there are not many options for accessing and processing data. There are a few general approaches for getting data from a web page. I'll keep the explainations generic, but they will translate to whatever platform/language you are using.
Access the data server side. This is accomplished by having the user submit the form. Once submitted, the values will be available via the query parameters. Various languages will have different methods to access the parameters.
Access the data client side. You can always use javascript to hook client side events like onblur, onchange, onfocus. Once your javascript fires, you can access various form elements with dom/js methods like getElementById/getElementByName -- Which would be able to reference your form elements but Id/Name respectively.
A Hybrid approach. AJAX is a mixture of the two approaches listed above. Client side code (javascript) makes async calls to the server. the server then processes the data in some manner and sends responses back to the client.
Hope this points you in the right direction. If you would like to clarify your question a bit, I can certainly try to cater the answer more to your specific case.