Dropdown dynamic in django ajax - django

I am using django for dynamic dropdown. There are two dropdown when the first dropdown was click and there is a subcategory for it, the second dropdown will show options. I want to disable the second dropdown if there is no subcategory for it. How can I do that?
$("#id_general-collision_type").change(function () {
const url = $("#form_incidentgeneral").attr("data-acc-url"); // get the url of the `load_cities` view
const collisionId = $(this).val(); // get the selected country ID from the HTML input
$.ajax({ // initialize an AJAX request
url: url, // set the url of the request (= /persons/ajax/load-cities/ )
data: {
'collision_type_id': collisionId // add the country id to the GET parameters
},
success: function (data) {
//console.log(data) // `data` is the return of the `load_cities` view function
$("#id_general-collision_subcategory").html(data); // replace the contents of the city input with the data that came from the server
let html_data = '<option value="">---------</option>';
data.forEach(function (collision_subcategory) {
html_data += `<option value="${collision_subcategory.id}">${collision_subcategory.sub_category}</option>`
});
console.log(html_data);
$("#id_general-collision_subcategory").html(html_data);
}
});
});

success: function (data) {
let select_element = $('select'); #Sub_category select
$(select_element).html(''); #Make Empty Select
for(let i=;i<data.length;i++){
let x = data[i];
let option_element = `<option value='${x['id']}'`>${x['sub_category']}</option>`;
$(select_element).append(option_element);
}
}

Related

Getting query length with Ajax / Django

According to the selection in the form, I want to get the number of records that match the id of the selected data as an integer.
Here is my view :
def loadRelationalForm(request):
main_task_id = request.GET.get('main_task_id')
relational_tasks = TaskTypeRelations.objects.filter(main_task_type_id = main_task_id)
data_len = len(relational_tasks)
return JsonResponse({'data': data_len})
Here is my ajax :
<script>
$("#id_user_task-0-task_types_id").change(function () {
const url = $("#usertask-form").attr("data-relationalform-url");
const mainTaskId = $(this).val();
$.ajax({
url: url,
data: {
'main_task_id': mainTaskId,
},
success: function (resp) {
console.log(resp.data);
}
});
});
I want to write the number of relational tasks associated with the main_task_id of the selected data in the form. But I couldn't do it. Thanks for your help. Kind regards
Make sure the data you're pulling is an integer.
This line :
main_task_id = request.GET.get('main_task_id')
Might be a string, and the resulting query would find no match.
Aside, if you want a number of related objects, you have more efficients way to do it :
def loadRelationalForm(request):
main_task_id = request.GET.get('main_task_id')
if main_task_id:
main_task_id = int(main_task_id)
main_task = TheMainTaskModel.objects.get(id=main_task_id)
related_task_count = main_task.tasktyperelations_set.count()
return JsonResponse({'data': related_task_count})
See doc about reverse relationship and .count()

Django2: Submit and store blobs as image files

I have made a few Django projects after having read the tutorial but I am by no means an expert in Django.
I am trying to take a screenshot of the current page and store it (if one does not exist).
To achieve this, we require a few things:
function to get screen shot of current page
function to async post this image to a view which should store it
view that stores the posted image
However, the screen shot function results in a Blob and I am having trouble getting a Django view to properly handle this.
A demo project is available here: https://gitlab.com/SumNeuron/so_save_blob
Function for screenshot
const screenshot = (function() {
function urlsToAbsolute(nodeList) {
if (!nodeList.length) {
return [];
}
var attrName = 'href';
if (nodeList[0].__proto__ === HTMLImageElement.prototype
|| nodeList[0].__proto__ === HTMLScriptElement.prototype) {
attrName = 'src';
}
nodeList = [].map.call(nodeList, function (el, i) {
var attr = el.getAttribute(attrName);
if (!attr) {
return;
}
var absURL = /^(https?|data):/i.test(attr);
if (absURL) {
return el;
} else {
return el;
}
});
return nodeList;
}
function addOnPageLoad_() {
window.addEventListener('DOMContentLoaded', function (e) {
var scrollX = document.documentElement.dataset.scrollX || 0;
var scrollY = document.documentElement.dataset.scrollY || 0;
window.scrollTo(scrollX, scrollY);
});
}
function capturePage(){
urlsToAbsolute(document.images);
urlsToAbsolute(document.querySelectorAll("link[rel='stylesheet']"));
var screenshot = document.documentElement.cloneNode(true);
var b = document.createElement('base');
b.href = document.location.protocol + '//' + location.host;
var head = screenshot.querySelector('head');
head.insertBefore(b, head.firstChild);
screenshot.style.pointerEvents = 'none';
screenshot.style.overflow = 'hidden';
screenshot.style.webkitUserSelect = 'none';
screenshot.style.mozUserSelect = 'none';
screenshot.style.msUserSelect = 'none';
screenshot.style.oUserSelect = 'none';
screenshot.style.userSelect = 'none';
screenshot.dataset.scrollX = window.scrollX;
screenshot.dataset.scrollY = window.scrollY;
var script = document.createElement('script');
script.textContent = '(' + addOnPageLoad_.toString() + ')();';
screenshot.querySelector('body').appendChild(script);
var blob = new Blob([screenshot.outerHTML], {
type: 'text/html'
});
return blob;
}
return capturePage
})()
Function to async post Blob
function setupAjaxWithCSRFToken() {
// using jQuery
var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
// set csrf header
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
}
function asyncSubmitBlob( url, blob ) {
var fd = new FormData();
fd.append('image', blob);
$.ajax({
url: url,
type: "POST",
data: fd,
contentType: false,
processData: false,
success: function(response){ console.log(response) },
error: function(data){ console.log(data) }
})
}
So to submit a screenshot of the current page:
setupAjaxWithCSRFToken()
const page = window.location.pathname;
const blob_url = "{% url 'my-app:post_blob' 'REPLACE' %}".replace(/REPLACE/,page == '/' ? '' : page)
asyncSubmitBlob( blob_url, screenshot() )
View to store the posted blob image
urls.py
...
from django.urls import include, path
...
app_name='my-app'
url_patterns=[
...
path('post_blob/', views.post_blob, {'page':'/'},name='post_blob'),
path('post_blob/<page>', views.post_blob,name='post_blob'),
...
]
views.py
from .models import PageBlob
...
def post_blob(request, page):
if request.FILES: # save screenshot of specified page
try:
pb = PageBlob.objects.all().filter(page=page))
if not pb.count():
pb = PageBlob()
pb.page = page
pb.blob = request.FILES['image']
pb.save()
return HttpResponse('Blob Submitted')
except:
return HttpResponse('[App::my-app]\tError when requesting page_image({page})'.format(page=page))
else: # return screenshot of requested page
try:
# get objects storing screenshot for requested page
pb = PageBlob.objects.all().filter(page=page)
# if one exists
if pb.count():
pb = pb[0]
## this just returns the string literal "blob"
return HttpResponse(str(pb.blob))
return HttpResponse('[App::my-app]\tNo blob for {page}'.format(page=page))
except:
return HttpResponse('[App::my-app]\tError when trying to retrieve blob for {page}'.format(page=page))
return HttpResponse('Another response')
models.py
class PageBlob(models.Model):
page = models.CharField(max_length=500)
blob = models.TextField(db_column='data', blank=True)
But I can not seem to faithfully capture and retrieve the blob.
Many S.O. questions of storing blobs use the model approach with import base64 to encode and decode the blob. One even recommends using the BinaryField. However, Django's documentation states firmly that BinaryField is not a replacement for the handling of static files.
So how could I achieve this?
S.O. posts I have found helpful to get this far
Upload an image blob from Ajax to Django
How to screenshot website in JavaScript client-side / how Google did it? (no need to access HDD)
How to download data in a blob field from database in django?
passing blob parameter to django
Returning binary data with django HttpResponse
https://djangosnippets.org/snippets/1597/
Django Binary or BLOB model field
Django CSRF check failing with an Ajax POST request
How can javascript upload a blob?

Sharepoint: How to show AppendOnlyHistory on a display template in a cross-publishing scenario

The overarching requirement I am trying to implement is to show comments (made on a list, item by item basis).
I added the feature on the authoring side by enabling versioning on the list and adding a text field with the option "Append Changes to Existing Text" set to true.
This indeed allows me to comment on items and displays them chronologically, but on the authoring side only.
The issue is that the UI part will be done on another site collection and I can't find a straightforward way to get all comments there.
So far, every resource I have found points to
<SharePoint:AppendOnlyHistory runat="server" FieldName="YourCommentsFieldName" ControlMode="Display"/>
The thing is, I can't (don't know how to) use this inside a display template.
So far, I am getting all my data using the REST API, via
var siteUrl=_spPageContextInfo.webAbsoluteUrl.replace("publishing","authoring");
$.ajax({
url: siteUrl + "/_api/web/lists/getbytitle('" + listname + "')/items(" + id + ")",
type: 'GET',
async:false,
headers: {"accept": "application/json;odata=verbose",},
dataType: 'JSON',
success: function(json) {
console.log(json);
//var obj = $.parseJSON(JSON.stringify(json.d.results));
//alert(obj);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("error :"+XMLHttpRequest.responseText);
}
});
What this gives me is the latest comment only. I need a simple way to get a hold of the entire thread.
I ended up using javascript object model to get them like so:
function GetComments(listname, itemId) {
var siteUrl = _spPageContextInfo.webAbsoluteUrl.replace("publishing", "authoring");
if ($(".comments-history").length) {
$().SPServices({
operation: "GetVersionCollection",
async: false,
webURL: siteUrl,
strlistID: listname,
strlistItemID: itemId,
strFieldName: "Comments",
completefunc: function (xData, Status) {
$(xData.responseText).find("Version").each(function (data, i) {
var xmlComment = $(this)[0].outerHTML;
var arr = xmlComment.split(/comments|modified|editor/g);
var comment = arr[1].trim().substring(2, arr[1].length-2);
var dateSt = Date.parse((arr[2].substring(1, arr[2].length)).replace('/"', ''));
var user = getUsername(arr[3]);
var st = "<div class='comment-item'><div class='comment-user'>" + user + "(" + FormatDate(dateSt) + ")</div>";
st += "<div class='comment-text'>" + comment + "</div></div>";
$(".comments-history").append(st);
});
}
});
}
}
the parsing could be better, but this is just an initial working idea

Facebook FQLproblem with javascript sdk

Hey everyone,
i do the following query to get a user statuses:
FB.api(
{
method: 'fql.query',
query: 'SELECT message FROM statuses WHERE uid = ' + userId
},
function(data) {
// do something with the response
}
);
It works great when the number of result are more than 0.
but when there are no results, the callback function is not called at all.
i need to know if there are 0 rows returning from this query, is there any way to do it?
Thanks :)
First of all, the statuses table does not exists. You should be using status table.
The callback is always called but you should properly check against empty objects. Just paste this on the Javascript Test Console:
<fb:login-button scope="read_stream">
Grant access to statuses
</fb:login-button>
<button onclick="getStatuses()">Get Statuses</button>
<script>
window.getStatuses = function() {
FB.api(
{
method: 'fql.query',
query: 'SELECT message FROM status WHERE uid = me() AND time < 315532800'
},
function(data) {
if(!isEmpty(data)) {
for(var key in data) {
var obj = data[key];
console.log(obj['message'])
}
} else {
console.log("data is empty")
}
});
};
function isEmpty(obj) {
for(var prop in obj) {
if(obj.hasOwnProperty(prop))
return false;
}
return true;
}
</script>
Here I am checking for statuses before 1/1/1980 to insure that an empty result is returned. In your console you should note the data is empty response.
When there are no results from a query, you should be getting an empty array.
Also, there isn't a FQL table named "statuses", it's "status".

Jquery Tool: Keep selected tab on refresh or save data

I am using jquery tool for tab Ui,
Now I want to keep tab selected on page reload. Is there any way to do that? below is my code
$(function() {
// setup ul.tabs to work as tabs for each div directly under div.panes
$("ul.tabs").tabs("div.panes > div");
});
Here is a simple implementation of storing the cookie and retrieving it:
function getCookie(c_name) {
var i, x, y, ARRcookies = document.cookie.split(";");
for (i = 0; i < ARRcookies.length; i++) {
x = ARRcookies[i].substr(0, ARRcookies[i].indexOf("="));
y = ARRcookies[i].substr(ARRcookies[i].indexOf("=") + 1);
x = x.replace(/^\s+|\s+$/g, "");
if (x == c_name) {
return unescape(y);
}
}
}
function setCookie(c_name, value, exdays) {
var exdate = new Date();
exdate.setDate(exdate.getDate() + exdays);
var c_value = escape(value) + ((exdays == null) ? "" : "; expires=" + exdate.toUTCString());
document.cookie = c_name + "=" + c_value;
}
Then, to save/retrieve cookie data with jQuery UI Tabs:
$(function() {
// retrieve cookie value on page load
var $tabs = $('ul.tabs').tabs();
$tabs.tabs('select', getCookie("selectedtab"));
// set cookie on tab select
$("ul.tabs").bind('tabsselect', function (event, ui) {
setCookie("selectedtab", ui.index + 1, 365);
});
});
Of course, you'll probably want to test if the cookie is set and return 0 or something so that getCookie doesn't return undefined.
On a side note, your selector of ul.tabs may be improved by specifying the tabs by id instead. If you truly have a collection of tabs on the page, you will need a better way of storing the cookie by name - something more specific for which tab collection has been selected/saved.
UPDATE
Ok, I fixed the ui.index usage, it now saves with a +1 increment to the tab index.
Here is a working example of this in action: http://jsbin.com/esukop/7/edit#preview
UPDATE for use with jQuery Tools
According the jQuery Tools API, it should work like this:
$(function() {
//instantiate tabs object
$("ul.tabs").tabs("div.panes > div");
// get handle to the api (must have been constructed before this call)
var api = $("ul.tabs").data("tabs");
// set cookie when tabs are clicked
api.onClick(function(e, index) {
setCookie("selectedtab", index + 1, 365);
});
// retrieve cookie value on page load
var selectedTab = getCookie("selectedtab");
if (selectedTab != "undefined") {
api.click( parseInt(selectedTab) ); // must parse string to int for api to work
}
});
function getCookie(c_name) {
var i, x, y, ARRcookies = document.cookie.split(";");
for (i = 0; i < ARRcookies.length; i++) {
x = ARRcookies[i].substr(0, ARRcookies[i].indexOf("="));
y = ARRcookies[i].substr(ARRcookies[i].indexOf("=") + 1);
x = x.replace(/^\s+|\s+$/g, "");
if (x == c_name) {
return unescape(y);
}
}
}
function setCookie(c_name, value, exdays) {
var exdate = new Date();
exdate.setDate(exdate.getDate() + exdays);
var c_value = escape(value) + ((exdays === null) ? "" : "; expires=" + exdate.toUTCString());
document.cookie = c_name + "=" + c_value;
}
Here is a working (unstyled) example: http://jsbin.com/ixamig/12/edit#preview
Here is what I see in Firefox when inspecting the cookie from the jsbin.com example:
This is what worked for me... at least I haven't run into any issues yet:
$('#tabs').tabs({
select: function (event, ui)
{
$.cookie('active_tab', ui.index, { path: '/' });
}
});
$('#tabs').tabs("option", "active", $.cookie('active_tab'));
I'm using: jQuery 1.8.2, jQuery UI 1.9.1, jQuery Cookie Plugin.
I set the "path" because in C# I set this value in a mvc controller which defaults to "/". If the path doesn't match, it wont overwrite the existing cookie. Here is my C# code to set the value of the same cookie used above:
Response.Cookies["active_tab"].Value = "myTabIndex";
Edit:
As of jQuery UI 1.10.2 (I just tried this version, not sure if it's broken in previous versions), my method doesnt work. This new code will set the cookie using jQuery UI 1.10.2
$('#tabs').tabs({
activate: function (event, ui) {
$.cookie('active_tab', ui.newTab.index(), { path: '/' });
}
});
The easiest way to survive between page refresh is to store the selected tab id in session or through any server-side script.
Only methods to store data on client side are: Cookies or localStorage.
Refer to thread: Store Javascript variable client side