Backbone.js's Ajax call different behavior in Chrome and Firefox - javascript

I am facing a weird issue in Firefox. We are loading a page and while calling Routers.initializeRouters(); an ajax request is sent to fetch the data and loadFormSuccessHandler function populate response into the views.
In case of Chrome, Ajax request waits for views to be initialized then data get populated into the view with ajax response.
In case of Firefox, Ajax request fetch the data and start populating the view and it fails because some of the views still not initialized.
How can I notify ajax request to wait for views to be initialized before populating data.
Any pointers will be helpful.
Main.js
var Main = {
treeView : null,
formView : null,
mainTabBarView : null,
currentFieldView : null,
designModeViewPointer : null,
carousel : null,
advancedControlsView : null,
renderUI : function() {
Templates.loadTemplateList();
Utility.initializeFieldHandlerMap();
Views.showBody();
Routers.initializeRouters();
var form = new Models.Form();
this.formView = Views.showForm('formDetailsDiv', form);
this.treeView = new Views.TreeView({
el : $('#controlsTreeDiv'),
model : null
});
this.treeView.getTree().attachEvent("onDblClick",
ControlBizLogic.formTreeNodeClickHandler);
Main.mainTabBarView = new Views.TabBarView({
el : $('#csdOperationsContainer'),
model : null
});
Views.showControlTab('control');
this.carousel = $('#controlTypesSlider');
this.carousel.tinycarousel();
Main.advancedControlsView = new Views.AdvancedPropertiesTabView({
el : $('#advancedControlProperties'),
model : null
});
// init design mode
Main.designModeViewPointer = new Views.DesignMode({
el : $("#design")
});
Routers.designModeOnBeforeDragEvent();
Routers.designModeOnDragEvent();
}
}
Main.renderUI();
Method with ajax call response
loadForm : function(_id, edit) {
$("#formWaitingImage").show();
if (Main.formView == null) {
Main.formView = Views.showForm('formTab',
new Models.Form({
"id" : _id
}));
}
Main.formView.getFormModel().set({
id : _id
});
GlobalMemory.editForm = (edit == "true");
Main.formView.getFormModel().fetch({
url : 'csdApi/form/' + _id + "/" + edit,
success : this.loadFormSuccessHandler
});
// save as
},
loadFormSuccessHandler : function(model, response) {
var formId = model.get('id');
if (formId != undefined && formId != null) {
GlobalMemory.editForm = true;
}
Routers.formEventsRouterPointer.updateUI(model);
Routers.formEventsRouterPointer.loadFormulae(Main.formView
.getFormModel(), "", "");
AdvancedControlPropertiesBizLogic
.loadSkipRules(Main.formView.getFormModel());
Main.formView.getFormModel().set({
skipRules : model.get('skipRules'),
id : model.get('id')
});
Main.advancedControlsView.setTableCss('formulaTable');
// Main.mainTabBarView.loadFormSummary();
Main.mainTabBarView.getFormSummaryView().displayFormInfo(
model.getFormInformation());
$("#formWaitingImage").hide();
// save form
if (!GlobalMemory.editForm) {
$('#saveForm').prop("value", " Save As ")
}
},

This issue was related to specific firefox version and it was fixed in the next firefox release.

Related

How to make API request from HTML select tags?

I need help with this scenario, getting all data from multiple select tag
and use those data to send an API request.
I have these three select tags, and one button to send a request to a news API.
The user needs to select a value from those select tags to set data like "source" and "category".
Example: "https://xxxxxxxxxxxx.org/v2/top-headlines?source='+ source +' + '&category='+ cat +'&apiKey=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Not sure if this the efficient way.
Below is my js code.
//global variables
var apiUrl = 'https://xxxxxxxxxxxxxxxxxx',
apiKey = 'xxxxxxxxxxxxxxxxxxxxxxxx',
displayRequest = document.querySelector('.displayRequestData'),
requestBtn = document.querySelector('#runApi'), //Btn to display data
newsOpt = document.querySelector('#news-selection'), //news select tag
catOpt = document.querySelector('#news-category'); //category select tag
requestBtn.addEventListener('click', newsRequest); //onclick
function sourceSelected() { //news option
var source = newsOpt !== null ? newsOpt.options[newsOpt.selectedIndex].value : 'the-next-web';
var cat = catOpt !== null ? catOpt.options[catOpt.selectedIndex].value : 'general';
return newsRequest(source, cat);
}
function newsRequest(source, cat) {
axios.get(apiUrl + 'top-headlines?sources=' + source + '&language=' + cat + '&apiKey=' + apiKey)
.then(function (response) {
var reStringify = JSON.stringify(response);
var rejson = JSON.parse(reStringify);
if (rejson.data.status == 'ok'){
console.log(rejson.data.articles[1].source.name);
//console.log(requestBtn);
}
})
.catch(function (error) {
console.log(error);
});
}
By the way, i got this error
VM7472:1 GET https://xxxxxxxxxxxxxxxxxxxxxxxx/v2/top-headlines?sources=[object%20MouseEvent]&language=undefined&apiKey=xxxxxxxxxxxxxxxxxxxxxxxxxxxx 400 (Bad Request)
When you add the event listener to call newsRequest via onClick, the first and only parameter that will be sent to that function is the event object. Therefore, the parameters of source and cat are not passed to newsRequest when they click on the button. (This is why your resulting URL has the [object MouseEvent] in it)
Instead, you might want to call your sourceSelected function in the onClick event which is fetching the current field values and then calling the newsRequest function.
I play around with my code, it's working now.
Note: The news API I'm using not allowing me to mix some data like country, source and langauge. So I try things that only allowed for free account and it works.
requestBtn.addEventListener('click', sourceSelected); //onchange
function sourceSelected() { //news option
var source = newsOpt !== null ? newsOpt.options[newsOpt.selectedIndex].value : 'en';
var cat = catOpt !== null ? catOpt.options[catOpt.selectedIndex].value : 'general';
return newsRequest(source, cat);
} //end of sourceSelected
function newsRequest(source, cat) {
axios.get(apiUrl + 'top-headlines?country=' + source + '&category=' + cat + '&apiKey=' + apiKey)
.then(function (response) {
var reStringify = JSON.stringify(response);
var rejson = JSON.parse(reStringify);
if (rejson.data.status == 'ok') {
console.log(rejson.data.articles[1].source.name);
//console.log(requestBtn);
}
})
.catch(function (error) {
console.log(error);
});
}//newsRequest

Using Django and Jquery

In addition to this post https://stackoverflow.com/a/17732956 I want to change the order of a list via drag'n'drop and save it afterwards in django backend.
For test purposes and comprehension I've used following fiddle:
http://jsfiddle.net/LvA2z/#&togetherjs=LvHpjIr7L0
and updated the action of the form with my own action. So, instead of script.php, I used action="{% url 'save_order' %}".
In views my function looks like:
def save_order(request):
if (request.method == 'POST'):
list = request.POST['listCSV']
print(list)
Basically I want to change the order of list elements and save it afterwards with the result that after refreshing the page the saved order is given. However I do not know, how pass vars from jquery to django site. When I change the order, I have the sorted list in 'listCSV'. How do I pass this result to django site to save it in db?
EDIT:
If //$("#listsaveform").submit(); is not commented out and I fire this function referenced with my save_order function, I got this error:
jquery-1.10.2.min.js:6 POST http://localhost:8000/overview/saveOrder/ 405 (Method Not Allowed)
EDIT:
Okay, thanks for the hint. I have never worked with ajax and therefore I'm stucking a bit.
I have my list construct:
{% if habits %}
<ul id="sortable">
{% for habit in habits|dictsort:"priority" %}
<li class="ui-state-default">{{habit.title}}</li>
{% endfor %}
</ul>
{% endif %}
and this list construct is sortable with this lines of code:
$(function() {
$( "#sortable" ).sortable();
});
How does look my form?
Here is my solution based on https://impythonist.wordpress.com/2015/06/16/django-with-ajax-a-modern-client-server-communication-practise/.
In JS
// Sort & save order of habits
$(function () {
$('.sort').sortable({
handle: 'button',
cancel: '',
update: function(event, ui) {
var result = $(this).sortable( "serialize", {key: event.target.id});
// alert(result);
var csrftoken = getCookie('csrftoken');
$.ajax({
url : "/overview/saveOrder/", // the endpoint,commonly same url
type : "POST", // http method
data : { csrfmiddlewaretoken : csrftoken,
result : result,
}, // data sent with the post request
// handle a successful response
success : function(json) {
console.log(json); // another sanity check
//On success show the data posted to server as a message
// alert('Your list '+json['result']);
},
// handle a non-successful response
error : function(xhr,errmsg,err) {
console.log("FAILURE");
console.log(xhr.status + ": " + xhr.responseText); // provide a bit more info about the error to the console
}
});
}
});
// var sorted = $( ".selector" ).sortable( "serialize", { key: "sort" } );
// console.log(sorted)
})
//For getting CSRF token
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
and on Django side
def save_habit(request):
print('save_habit')
if (request.method == 'POST'):
if request.is_ajax():
habits = Habit.objects.filter(created_by=request.user.userprofile, is_active=True)
habit_title = request.POST.get('habit_title')
habit_trigger = request.POST.get('habit_trigger')
habit_routine = request.POST.get('habit_routine')
habit_targetbehavior = request.POST.get('habit_targetbehavior')
habit_image = request.POST.get('habit_image')
print(habit_image)
image = habit_image.split('http://localhost:8000/media')
print(image[1])
# TODO: was, wenn routine noch gar nicht existiert? --> speichern
obj_routine = Existingroutine.objects.get(name=habit_routine)
obj_targetbehavior = Targetbehavior.objects.get(name=habit_targetbehavior)
for habit in habits:
habit.priority += 1;
# habit.save();
habit = Habit(created_by=request.user.userprofile, is_active=True,
title=habit_title, trigger=habit_trigger, existingroutine=obj_routine,
targetbehavior=obj_targetbehavior, image=image[1])
#habit.save()
data = {"habit_title":habit_title,
"habit_trigger":habit_trigger,
"habit_routine":habit_routine,
"habit_targetbehavior":habit_targetbehavior };
return JsonResponse(data)
return redirect('display_habits')

Ajax POST XMLHttpRequest to DataLayer via Google Tag Manager

Please help me because i'm stuck.
First of all i am a newbie in Ajax and javascript.
So what i have:
I have AJAX calculator form on my website.
I want to track input, dropdown and selection fields and its values in Google Analytics.
I've installed and implemented Google Tag Manager.
I've created custom html tag firing when DOM is ready to pushing output to dataLayer:
<script>
(function() {
var xhrOpen = window.XMLHttpRequest.prototype.open;
var xhrSend = window.XMLHttpRequest.prototype.send;
window.XMLHttpRequest.prototype.open = function() {
this.method = arguments[0];
this.url = arguments[1];
return xhrOpen.apply(this, [].slice.call(arguments));
};
window.XMLHttpRequest.prototype.send = function() {
var xhr = this;
var xhrData = arguments[0];
var intervalId = window.setInterval(function() {
if(xhr.readyState != 4) {
return;
}
dataLayer.push({
'event': 'ajaxSuccess',
'eventCategory': 'AJAX ' + xhr.method,
'eventAction': xhr.url + (xhr.method == 'POST' && xhrData ? ';' + xhrData : ''),
'eventLabel': xhr.responseText
});
clearInterval(intervalId);
}, 1);
return xhrSend.apply(this, [].slice.call(arguments));
};
})();
</script>
5.And I am very happy because I finally got the data in data.layer
{
event: 'ajaxSuccess',
eventCategory: 'AJAX POST',
eventAction:'http://mylocalhosting.local/calculator/ajax_statistic_track;property_value=20000&state=1&property_type=1&first_home_buyer=2&are_you_purchasing=2&url=http%3A%2F%2Fnew.sharewood.ru%2Fembed.html',
eventLabel:'property_value=20000&state=1&property_type=1&first_home_buyer=2&are_you_purchasing=2&url=http%3A%2F%2Fnew.sharewood.ru%2Fembed.html'
}
And finally the Question:
How can I split the data received in URL with strings? I understand that i should create new triggers in GTM and edit the code. But how? JSON.parse?JSON.stringify?:
What i want to have in output:
{
event: 'ajaxSuccess',
eventCategory: 'AJAX POST',
eventAction:'http://mylocalhosting.local/calculator/ajax_statistic_track;property_value=20000&state=1&property_type=1&first_home_buyer=2&are_you_purchasing=2&url=http%3A%2F%2Fnew.sharewood.ru%2Fembed.html',
eventLabel:'property_value=20000&state=1&property_type=1&first_home_buyer=2&are_you_purchasing=2&url=http%3A%2F%2Fnew.sharewood.ru%2Fembed.html'
propertyValue: '20000'
state: '1'
propertyType: '1'
firstHomeBuyer: '2'
}
Since you passed your data as a url you can let GTM handle the parsing. GTM has a "url" type of variable which can also return parts of a url, including a value identified by a query parameter. First you create a dataLayer variable that reads the eventAction (which is in url format). Then you create a new "URL" type variable, set "Component Type" to query key to extract a query variable, set the query parameter name and in "More settings" you select the dataLayer var with the eventAction as "source" parameter. This should look like this to return the value for "propertyValue" (repeat for the other query parameters in the url):

FancyTree activate function for a node on initiating

i need some help. I am trying to build a fancytree with url as source
var currentTree = $('#files_tree');
var urlBase = currentTree.attr("data-url");
currentTree.fancytree({
extensions: ["glyph", "dnd"],
glyph: {map: glyphIconClasses()},
// selectMode: 1,
source: {url: urlBase ,
data: {mode: "all"},
cache: false
},
activate: function (event, data) {
//data.node.render();
//show_edit_node_fnc(data.node.key);
//currentNodeToEdit = data.node;
id = data.node.data.id;
filesof = data.node.data.filesof;
list_files( filesof , id ) ; // Call to another JS function
},
and i make the content using php array, and send the request as json response
$arrFileTree['title'] = $project->name;
$arrFileTree['folder'] = true;
$arrFileTree['expanded'] = true;
$arrFileTree['activated'] = true;
$arrFileTree['data'] = array("filesof" => "project" , "id" => $project->id);
$arrSource = $project->sources ;
if($arrSource){
$arrChildren = array();
foreach($arrSource as $source){
$arNode['key'] = $source->id;
$arNode['title'] = $source->title;
$arNode['folder'] = true;
$arNode['data'] = array("filesof" => "source", "id" => $source->id);
$arrChildren[] = $arNode;
}
$arrFileTree['children'] = $arrChildren;
}
return array($arrFileTree);
what I need is, when i load the page for the first time, that an element be activated and the default "activate" function to be called on some value i assigned in php like ($arrFileTree['activated'] = true;)
So when i page loaded the "activate" function for a node will be called, and it will call my second function "list_files"
could anyone help me with this ?
Thanks
Wael
You could define the active state in the source data
...
$arrFileTree['active'] = true;
and trigger the activate event when the data was loaded:
$("#tree").fancytree({
source: {
...
},
init: function(event, data) {
data.tree.reactivate();
},

Print content of popup dialong by javascript in backbone project

I have a button in and it is used for calling a dialog. Dialog's content is a pdf got from jasper report.
Here is the backbone view of dialog :
var framSrc = getRSUR; //getting pdf from jasper reporting server
var ReportView = Backbone.View.extend({
tagName : "div",
id : "report",
initialize: function() {
},
events : {
'click #print' : 'printDialog'
},
'printDialog' : function(){
printReport();
},
render: function(){
this.$el.html('<div><a id="print"><img src="printer.png" width="30px"><span style="position:relative;bottom:10px; left:10px;">Print Report</span></a></div><iframe id="agingFrame" src="'+framSrc+'"></iframe>');
return this;
}
});
printReport() :
function printReport(){
try{
var oIframe = document.getElementById('agingFrame');
var oContent = document.getElementById('agingFrame').innerHTML;
var oDoc = (oIframe.contentWindow || oIframe.contentDocument);
if (oDoc.document) oDoc = oDoc.document;
oDoc.write("<html><head><title>title</title>");
oDoc.write("</head><body onload='this.focus(); this.print();'>");
oDoc.write(oContent + "</body></html>");
oDoc.close();
}
catch(e){
self.print();
}
}
But what I've got from printing is the full page of the web page, not the pdf content in iframe.

Categories

Resources