JQuery Guillotine: Multiple Change Events Firing - javascript

Can somebody please give me some guidance with a problem I am having with the JQuery Guillotine? I have spent hours working on this and cannot identify the correct solution. The issue I am having is eventOnChange fires multiple times after I have changed the image. Each event is fired +1 for each successive image swap.
I have studied this link and am still unable to find a working solution: jQuery Guillotine - Swap Image
I've worked around this by killing the event and just capturing the relevant information I need when the form is posted, but it's really bothering me that I cannot find a solution that will allow me to take advantage of the event.
Here is a brief summary of what is going on:
page loads with default user avatar
user is able to manipulate avatar inside guillotine and one onchange event fires per manipulation (zoom in, zoom out, rotate, fit, etc.)
user opens file reader to select new avatar
new avatar is successfully loaded (correct scaling and dimensions)
user manipulates image but each manipulation event fires multiple times. For example, rotate right will rotate the image twice (180 degrees) after the user has selected a new avatar.
If the user opens the file reader again, the image will fire three times. And so one. 1 + x times the user selects a new avatar...
I have tried unbinding the event before reloading the image and initialing the plugin, but it has not solved the problem. Any help is greatly appreciated!
Relevant code is below.
JavaScript:
<script type="text/javascript" charset="UTF-8">
function showData (data) {
data.scale = parseFloat(data.scale.toFixed(4))
for(var k in data) { $('#'+k).html(data[k]) }
}
function loadInterface(picture) {
showData(picture.guillotine('getData'))
// Bind button actions
if(!picture.data('isBound')){
picture.data('isBound', true)
$('#rotate_left').click(function(){ picture.guillotine('rotateLeft') })
$('#rotate_right').click(function(){ picture.guillotine('rotateRight') })
$('#fit').click(function(){ picture.guillotine('fit') })
$('#zoom_in').click(function(){ picture.guillotine('zoomIn') });
$('#zoom_out').click(function(){ picture.guillotine('zoomOut') })
}
// Update data on change
picture.on('guillotinechange', function(e, data, action) {
console.log('guillotine onchange event called!')
showData(data);
console.log(action);
})
}
function loadGuillotine (picture, data) {
if(picture.guillotine('instance')){ picture.guillotine('remove') }
// Load plugin
picture.guillotine({
width: data['w'],
height: data['h'],
init: data,
eventOnChange: 'guillotinechange'
})
}
$(document).ready(function() {
var picture = $('#useravatar')
var data = { w: 250, h: 250, angle: 0, scale: 1 }
picture.on('load', function() {
// Load guillotine and controls
picture.guillotine('remove')
loadGuillotine(picture, data)
loadInterface(picture)
// Transform picture to fit, center
picture.guillotine('fit').guillotine('center')
})
})
function ReloadImage(){
var reader = new FileReader();
reader.readAsDataURL(document.getElementById("avatar_input").files[0]);
reader.onload = function (oFREvent){
document.getElementById("useravatar").src = oFREvent.target.result;
}
}
</script>
And inside Ruby Page:
<div id='content'>
<h1>Select Avatar</h1>
<%= form_for(#avatar, url: save_avatar_path, method: :patch) do |f| %>
<%= render 'shared/errors', object: #avatar %>
<div class='frame'>
<%= image_tag 'default-user-avatar.jpg', :id => :useravatar %>
</div>
<div id='controls'>
<button id='rotate_left' type='button' title='Rotate left'> < </button>
<button id='zoom_out' type='button' title='Zoom out'> - </button>
<button id='fit' type='button' title='Fit image'> [ ] </button>
<button id='zoom_in' type='button' title='Zoom in'> + </button>
<button id='rotate_right' type='button' title='Rotate right'> > </button>
</div>
<div id='controls'>
<%= f.hidden_field :image, value: #avatar.cached_image_data %>
<%= f.file_field :image, :class => :form_field, :id => :avatar_input, :onChange => "ReloadImage()" %>
</div>
<ul id='data'>
<div class='column'>
<li>x: <span id='x'></span></li>
<li>y: <span id='y'></span></li>
</div>
<div class='column'>
<li>width: <span id='w'></span></li>
<li>height: <span id='h'></span></li>
</div>
<div class='column'>
<li>scale: <span id='scale'></span></li>
<li>angle: <span id='angle'></span></li>
</div>
</ul>
<% end %>
</div>

I have not tested your code but believe/guess you have fallen into a trap that I once found myself in.
.click() applies your function event with every iteration of the loop hence why you get multiple change events fireing (thus if the loop calls three times then the event is added sequentially three times).
Try using .one() instead of .click()
Another potential solution is to use .off().click() but it creates overhead.

Related

Javascript doesn't run on back button or menu item click in my rails application

I have the following Javascript code contained in my profile.js file in Rails 7:
window.addEventListener('load', function () {
updateProfile();
})
window.onpageshow = function(event) {
if (event.persisted) {
window.location.reload();
}
};
window.addEventListener('popstate', function() {
updateProfile();
});
window.addEventListener( "pageshow", function ( event ) {
var historyTraversal = event.persisted ||
( typeof window.performance != "undefined" &&
window.performance.navigation.type === 2 );
if ( historyTraversal ) {
// Handle page restore.
window.location.reload();
}
});
function fileSelected() {
// Get the selected file
const file = document.querySelector('#fileInput').files[0];
if (file == null){
return
}
// Create a new FileReader object
const reader = new FileReader();
// Set the onload event handler for the FileReader object
reader.onload = function(event) {
// Update the src attribute of the profile image
document.querySelector('#profile-image').src = event.target.result;
};
// Read the selected file as a DataURL
reader.readAsDataURL(file);
}
function updateProfile(){
var toggle_switch = document.getElementById('toggle');
var save_button = document.getElementById('save-button');
let nameInput = document.getElementById('name');
nameInput.addEventListener('input', function(event) {
let error_element = document.getElementById('error-message-name');
let regex = /^.{3,}$/; // Regex that requires at least 3 characters
if (regex.test(value)) {
// Value is valid
error_element.classList.remove("visible-error")
error_element.classList.add("invisible-error")
} else {
// Value is invalid
error_element.classList.remove("invisible-error")
error_element.classList.add('visible-error');
}
});
toggle_switch.addEventListener('click', function() {
if (this.getAttribute('data-type') == "influencer"){
this.setAttribute('data-type', "vender");
document.getElementById('profile_type').value = "vender";
}else{
this.setAttribute('data-type', "influencer");
document.getElementById('profile_type').value = "influencer";
}
});
save_button.addEventListener('click', function() {
let new_name = document.getElementById('name').value;
let new_headline = document.getElementById('headline').value;
let new_country = document.getElementById('country').value;
let new_city = document.getElementById('city').value;
let new_about = document.getElementById("about").value;
let new_profile_type = document.getElementById('toggle').getAttribute('data-type');
let div = document.getElementById('user_id');
let user_id = div.getAttribute('data');
var fileInput = document.getElementById("fileInput");
var file = fileInput.files[0];
if (file == null) {
$.ajax({ //A new image was not uploaded for change
type: "PATCH",
url: encodeURI('/users/' + user_id),
beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))},
data: { user: { profile_type: new_profile_type, name: new_name, headline: new_headline, country: new_country, city: new_city, about: new_about} },
success: function(response) {
console.log("Update success.")
}
});
} else {
const formData = new FormData();
formData.append("avatar", file);
$.ajax({
url: encodeURI('/users/' + user_id),
type: "PUT",
beforeSend(xhr, options) {
xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'));
xhr.setRequestHeader('image-change', true);
options.data = formData;
},
success: function(response) {
console.log("Image Update success.")
},
error: () => {
alert("An issue occured. Please try again.");
}
});
}
});
}
This code should be run when a user navigates to my profile page with the following html.erb:
<head>
<%= stylesheet_link_tag 'linked_card', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= stylesheet_link_tag 'profile_card', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= stylesheet_link_tag 'alert', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag "profile", "data": { "turbolinks-track": "reload" } %>
</head>
<header>
<%= render partial: "layouts/header" %>
</header>
<body class = "profile_main_body">
<%= render partial: "layouts/profile_card", locals: { user: #user } %>
<br>
<br>
<div class="col-md-6 mx-auto text-center">
<h3 class="heading-black">Link Accounts</h3>
<p class="text-muted lead">Click the button below to link an account to your profile. You will be redirected to the chosen service.</p>
<i class="fa fa-link"></i> Link Account
</div>
<br>
<br>
<div class="container">
<div class="row">
<%= render partial: "layouts/linked_card" %>
<%= render partial: "layouts/linked_card" %>
</div>
</div>
<br>
</body>
<footer>
<%= render partial: "layouts/footer" %>
</footer>
I added the following line:
<%= javascript_include_tag "profile", "data": { "turbolinks-track": "reload" } %>
Because I was thinking this is a turbolinks issue. Nothing has changed though with the line above. Is there anyway I can re-run the my javascript when the user clicks a turbo link? The javascript runs fine on a full page reload. Any help would be great thanks!
Turbolinks is replaced by Turbo in Rails 7. However there is a lot of overlap in how you should think about JS.
Turbolinks/Turbo (or almost any SPA framework for that matter) creates a persistent browser session across pages. Thinking in terms of "when the page is loaded I want to attach an event handler to X that does Y" might have been OK in a basic JS tutorial ten years ago but is actually counter-productive:
It doesn't work when elements are inserted dynamically into the DOM. Like when Turbo Drive or Turbolinks replaces the page contents. Or whenever people try to insert content loaded with AJAX for the first time.
Adding event handlers directly to a bunch of elements adds a lot of overhead.
If you hook into an event like turbolinks:change you might be adding the event handler multiple times to the same element. Just switching out the load/ready event for the Turbo/Turbolinks equivilent won't necissarily fix stinky code and may just introduce new issues.
It's a broken mental model as you build your JS to just "frobnob X on page Y" instead of thinking in terms of reusable UI components or augmenting the behavior of elements in a reusable way.
So what then?
Stop assigning IDs and event handlers directly to everything. You're just going to end up with duplicate IDs and garbage JS.
Instead use delegation to catch the event as it bubbles to the top of the DOM:
// Do something awesome when the user clicks buttons with class="foo"
document.addEventHandler('click', function(event){
let el = event.target;
if (!el.matches('.foo')) return;
// ...
});
Use classes and attributes to target elements. Not ID's. Its not 2010 and querying the DOM is much faster.
Use DOM traversal and the form API to get elements relative to the element that was clicked/changed/etc. Remember that in JS functions can actually take arguments. Use data attributes if you need to pass additional information from the backend to your JS.
This is basically what Stimulus does:
<div data-controller="hello">
<input type="text">
<button>Greet</button>
</div>
// src/controllers/hello_controller.js
import { Controller } from "#hotwired/stimulus"
export default class extends Controller {
connect() {
console.log("Hello, Stimulus!", this.element)
}
}

Adding Checkbox Form Fields via Ajax response to Rails Form, Not showing in params on submit

First question asked here so hope I make the problem clear enough.
So I have this long rails form and am trying to cut down on load times and want to asynchronously add some checkboxes to my form from an AJAX response. I get the checkboxes to render appropriately but the values are not coming through to the controller on the form submit. I have tried several different options to no avail, so am looking for some guidance. Fairly new to Rails, so thats part of it.
Here is some code:
function fetchCodes(){
if (window.location.pathname.includes("/something")){
$.ajax({
url: '/codes',
success: function(response){
updateFields(response)
},
error: function (error) {
console.log(error);
throw new Error('ajax error: ' + $(JSON.stringify(error)));
},
});
}
}
function updateFields(response){
var select_option_core_business = $(".codes");
var selected_options = response.data.selected_options
console.log(selected_options)
$.each(response.data.options, function(key, value) {
select_option_core_business
.append($('<div class="col-lg-12"><input type="checkbox" name="registration_form[core_business][]" value=' + value + '><label for="registration_form_core_business">' + value + '</label></div>'));
}
So after some time, the checkboxes appear on the DOM just as if they were rendered using my initial method:
<% codes.each do |segment| %>
<div class="col-lg-12">
<%= check_box_tag(
'registration_form[core_business][]',
segment,
#registration_form.core_business.include?(segment),
class: 'form-check-label'
)%>
<small><%= f.label :core_business, segment, class: 'form-check-label' %></small>
</div>
<% end %>
But when I submit the form, core_business does not come through in the params. My thoughts are that the form doesn't recognize the newly added checkboxes since they were loaded asynchronously, but I can't be certain. Has anyone else tried to do this? I have tried appending in different ways with the same outcome, but only using jQuery methods.
Here is how it appears on the DOM:
<div class="col-lg-12">
<input type="checkbox" name="registration_form[core_business][]" value="Some Value" class="form-check-label" id="nil">
<small class="pl-1">
<label for="registration_form_core_business" class="form-check-
label">Some Value</label>
</small>
</div>
Which matches how rails form helper outputs the html
Hoping someone has run into this before. Thank you for your time!

Load Function not updating Global Variable

I'm creating a node application and having trouble updating a global variable.
Here is my code (ejs file):
<% include ../partials/header %>
<div class="page container">
<div id="campgroundsRow" class="row">
</div> <!-- row end -->
<button id="loadMore">Load More</button>
</div> <!-- Container End -->
<% include ../partials/footer %>
<script>
var numGroundsToLoad = 1;
var numGroundsLoaded = 0;
loadCampgrounds(numGroundsLoaded, numGroundsToLoad);
function loadCampgrounds(numGroundsLoaded, numGroundsToLoad) {
var grounds = <%-JSON.stringify(campgrounds) %>
for(var i=numGroundsLoaded + 1; i<numGroundsLoaded + numGroundsToLoad; i++) {
//code to add grounds[i] to campgroundsRow div
}
numGroundsLoaded += numGroundsToLoad;
}
$("#loadMore").on("click", function() {
loadCampgrounds(numGroundsLoaded, numGroundsToLoad);
});
</script>
The problem I'm having is the loadCampgrounds function is not actually updating numGroundsLoaded. So when I click the load more button (#loadMore), it thinks that I am adding ground[0].
What I want is that each time I click load more, the next ground is added. I.e, ground[0] gets added by default. Then on load more, ground[1]. Then on load more, ground[2] and so on (assume there are unlimited grounds for now).
As you can see, the problem is related to both scope and when stuff is being loaded.
Because you update the local variable. In this case, to update global variable you need to access it through window.numGroundsLoaded.

JQuery loading issue on submission

On my website. Im having trouble with JQuery. Im not an expert here so please understand.
Here it is the script that I'm using its working actually but, once you click the submit btn..even you have an incomplete info in the form the loader still show processing. Even the my board says: please complete your..., still the loading gif is running.
The Script:
<script src="//code.jquery.com/jquery-1.10.2.min.js"></script>
<script>
$(document).on( "click", ".show-page-loading-msg", function() {
var $this = $( this ),
theme = $this.jqmData( "theme" ) || $.mobile.loader.prototype.options.theme,
msgText = $this.jqmData( "msgtext" ) || $.mobile.loader.prototype.options.text,
textVisible = $this.jqmData( "textvisible" ) || $.mobile.loader.prototype.options.textVisible,
textonly = !!$this.jqmData( "textonly" );
html = $this.jqmData( "html" ) || "";
$.mobile.loading( 'show', {
text: msgText,
textVisible: textVisible,
theme: theme,
textonly: textonly,
html: html
});
})
.on( "click", ".hide-page-loading-msg", function() {
$.mobile.loading( "hide" );
});
</script>
My php code: (This is not complete i just want to share the end part)
<div class="form-group">
<div class="col-md-5 col-sm-8 col-xs-8">
<?if (Core::config('general.recaptcha_active')):?>
<?=Captcha::recaptcha_display()?>
<div id="recaptcha3"></div>
<?else:?>
<?= FORM::label('captcha', _e('Captcha'), array('for'=>'captcha'))?>
<span id="helpBlock" class="help-block"><?=captcha::image_tag('publish_new')?></span>
<?= FORM::input('captcha', "", array('class' => 'form-control', 'id' => 'captcha', 'required', 'data-error' => __('Captcha is not correct')))?>
<?endif?>
</div>
</div>
<?endif?>
<div class="control-group">
<div class="controls">
<?= FORM::button('submit', __('<i class="glyphicon glyphicon-send"></i> Publish New Ad'), array('type'=>'submit', 'data-corners'=>'false', 'class'=>'pub-new show-page-loading-msg', 'data-theme'=>'b', 'data-textonly'=>'false', 'data-msgtext'=>'Processing....', 'data-textvisible'=>'true', 'action'=>Route::url('post_new',array('controller'=>'new','action'=>'index'))))>
</div>
</div>
</fieldset>
<?= FORM::close()?>
To know more Please you can go here, but you need to use mobile to see : https://linkinads.com/publish-new.html or here in youtube for video : https://www.youtube.com/watch?v=dKzabE2eJN0
though I dont know the real issued here but after i move this, things are fixed
'data-ajax'=>'false'
solve my issue.
Your button is a submit button. These button fire an event to process the form natively in HTML.
In your Javascript, instead of binding your code to the click event for the class of the button, you should instead bind it to the submit event of the form (which is tied to the button and the form as a whole) and then block the default submit action. Something like the below.
$('#publish-new').submit(function(event) {
event.preventDefault(); //Prevents the default form event from firing
//Rest of your code can go here
});

How to post ASP.NET MVC Ajax form using JavaScript rather than submit button

I have a simple form created using Ajax.BeginForm:
<% using (Ajax.BeginForm("Update", "Description", new { id = Model.Id },
new AjaxOptions
{
UpdateTargetId = "DescriptionDiv",
HttpMethod = "post"
},new {id ='AjaxForm' })) {%>
Description:
<%= Html.TextBox("Description", Model.Description) %><br />
<input type="submit" value="save" />
<% }%>
The controller is wired up and returns a partial view that updates the DescriptionDiv. And it all works neatly.
Now I would like to be able to submit this form without having the submit button (via a clik on a link or on an image or whatever). Unfortunately this little jQuery snippet does not do the job:
$('form#AjaxForm').submit();
It does submit the form, but does (I suppose not surprisingly) a regular post-back and not an Ajax one.
For the sake of simplicity the above jQuery is wired up like this:
submit
The form's onsubmit is using the Sys.Mvc.AsyncForm.handleSubmit() but the jQuery submit seems to be bypassing this.
PS. I am looking for a solution in this particular approach. I know how to achieve the same using a normal form and posting it using AJAX+jQuery. I am interested in this particular solution though.
I'm going to assume that your lack of quotes around the selector is just a transcription error, but you should check it anyway. Also, I don't see where you are actually giving the form an id. Usually you do this with the htmlAttributes parameter. I don't see you using the signature that has it. Again, though, if the form is submitting at all, this could be a transcription error.
If the selector and the id aren't the problem I'm suspicious that it might be because the click handler is added via markup when you use the Ajax BeginForm extension. You might try using $('form').trigger('submit') or in the worst case, have the click handler on the anchor create a hidden submit button in the form and click it. Or even create your own ajax submission using pure jQuery (which is probably what I would do).
Lastly, you should realize that by replacing the submit button, you're going to totally break this for people who don't have javascript enabled. The way around this is to also have a button hidden using a noscript tag and handle both AJAX and non-AJAX posts on the server.
BTW, it's consider standard practice, Microsoft not withstanding, to add the handlers via javascript not via markup. This keeps your javascript organized in one place so you can more easily see what's going on on the form. Here's an example of how I would use the trigger mechanism.
$(function() {
$('form#ajaxForm').find('a.submit-link').click( function() {
$('form#ajaxForm').trigger('submit');
}).show();
}
<% using (Ajax.BeginForm("Update", "Description", new { id = Model.Id },
new AjaxOptions
{
UpdateTargetId = "DescriptionDiv",
HttpMethod = "post"
}, new { id = "ajaxForm" } )) {%>
Description:
<%= Html.TextBox("Description", Model.Description) %><br />
Save
<noscript>
<input type="submit" value="Save" />
</noscript>
<% } %>
A simple example, where a change on a dropdown list triggers an ajax form-submit to reload a datagrid:
<div id="pnlSearch">
<% using (Ajax.BeginForm("UserSearch", "Home", new AjaxOptions { UpdateTargetId = "pnlSearchResults" }, new { id="UserSearchForm" }))
{ %>
UserType: <%: Html.DropDownList("FilterUserType", Model.UserTypes, "--", new { onchange = "$('#UserSearchForm').trigger('submit');" })%>
<% } %>
</div>
The trigger('onsubmit') is the key thing: it calls the onsubmit function that MVC has grafted onto the form.
NB. The UserSearchResults controller returns a PartialView that renders a table using the supplied Model
<div id="pnlSearchResults">
<% Html.RenderPartial("UserSearchResults", Model); %>
</div>
Unfortunately triggering the onsubmit or submit events wont work in all browsers.
Works in IE and Chrome: #('form#ajaxForm')trigger('onsubmit');
Works in Firefox and Safari: #('form#ajaxForm')trigger('submit');
Also, if you trigger('submit') in Chrome or IE, it causes the entire page to be posted rather than doing an AJAX behavior.
What works for all browsers is removing the onsubmit event behavior and just calling submit() on the form itself.
<script type="text/javascript">
$(function() {
$('form#ajaxForm').submit(function(event) {
eval($(this).attr('onsubmit')); return false;
});
$('form#ajaxForm').find('a.submit-link').click( function() {
$'form#ajaxForm').submit();
});
}
</script>
<% using (Ajax.BeginForm("Update", "Description", new { id = Model.Id },
new AjaxOptions
{
UpdateTargetId = "DescriptionDiv",
HttpMethod = "post"
}, new { id = "ajaxForm" } )) {%>
Description:
<%= Html.TextBox("Description", Model.Description) %><br />
Save
<% } %>
Also, the link doesn't have to be contained within the form in order for this to work.
I've tried a few times to get the ajax form submit working nicely, but always met with either complete failure or too many compromises. Here's an example of page that uses the jQuery Form plug-in inside of a MVC page to update a list of projects (using a partially rendered control) as the user types in an input box:
<div class="searchBar">
<form action="<%= Url.Action ("SearchByName") %>" method="get" class="searchSubmitForm">
<label for="projectName">Search:</label>
<%= Html.TextBox ("projectName") %>
<input class="submit" type="submit" value="Search" />
</form>
</div>
<div id="projectList">
<% Html.RenderPartial ("ProjectList", Model); %>
</div>
<script type="text/javascript">
jQuery(document).ready(function() {
jQuery("#projectName").keyup(function() {
jQuery(".searchSubmitForm").submit();
});
jQuery(".searchSubmitForm").submit(function() {
var options = {
target : '#projectList'
}
jQuery(this).ajaxSubmit(options);
return false;
});
// We remove the submit button here - good Javascript depreciation technique
jQuery(".submit").remove();
});
</script>
And on the controller side:
public ActionResult SearchByName (string projectName)
{
var service = Factory.GetService<IProjectService> ();
var result = service.GetProjects (projectName);
if (Request.IsAjaxRequest ())
return PartialView ("ProjectList", result);
else
{
TempData["Result"] = result;
TempData["SearchCriteria"] = projectName;
return RedirectToAction ("Index");
}
}
public ActionResult Index ()
{
IQueryable<Project> projects;
if (TempData["Result"] != null)
projects = (IQueryable<Project>)TempData["Result"];
else
{
var service = Factory.GetService<IProjectService> ();
projects = service.GetProjects ();
}
ViewData["projectName"] = TempData["SearchCriteria"];
return View (projects);
}
Ajax.BeginForm looks to be a fail.
Using a regular Html.Begin for, this does the trick just nicely:
$('#detailsform').submit(function(e) {
e.preventDefault();
$.post($(this).attr("action"), $(this).serialize(), function(r) {
$("#edit").html(r);
});
});
Try the following way:
<input type="submit" value="Search" class="search-btn" />
Go
Rather than using JavaScript perhaps try something like
<a href="#">
<input type="submit" value="save" style="background: transparent none; border: 0px none; text-decoration: inherit; color: inherit; cursor: inherit" />
</a>
Simply place normal button indide Ajax.BeginForm and on click find parent form and normal submit. Ajax form in Razor:
#using (Ajax.BeginForm("AjaxPost", "Home", ajaxOptions))
{
<div class="form-group">
<div class="col-md-12">
<button class="btn btn-primary" role="button" type="button" onclick="submitParentForm($(this))">Submit parent from Jquery</button>
</div>
</div>
}
and Javascript:
function submitParentForm(sender) {
var $formToSubmit = $(sender).closest('form');
$formToSubmit.submit();
}

Categories