This is the js function:
var onContentChange = function () {
var content =
$("#blogpost-content").data("kendoEditor").value($("#value").val());
console.log(content);
$http.post("/Map/SaveBlogPostContent?destinationId=" +
$("#currentDestinationId").val() +
"&blogPostId=" + $("#currentBlogPost").val() + "&content=" + content)
.then(onSaveBlogPostContent, onError);
}
This method is triggered on change of a textarea.
When it hits the console.log it writes out the correct text that is currently in the textarea but when it posts the data to my controller method it only receives a bit of the content.
Why is this?
It's quite possible you have 'illegal characters' in your textarea, try to escape the content variable, change it like so:
var onContentChange = function () {
var content = $("#blogpost-content").data("kendoEditor").value($("#value").val());
console.log(content);
$http.post("/Map/SaveBlogPostContent?destinationId=" + encodeURIComponent($("#currentDestinationId").val()) + "&blogPostId=" + encodeURIComponent($("#currentBlogPost").val()) + "&content=" + encodeURIComponent(content))
.then(onSaveBlogPostContent, onError);
}
The encodeURIComponent() is the important part there.
Since this is a get and not a post, there are limits to the length of data you can send in the get request, it will depend by browser. you also want to make sure you dont have any characters that need to be escaped. eg. charters used in the url such as ? or & or /. you can escape these by using.
var contentToPass = encodeURIComponent(content);
see here encodeURIComponent
Try this:
var onContentChange = function () {
var content =
$("#blogpost-content").data("kendoEditor").value($("#value").val());
console.log(content);
$http.post("/Map/SaveBlogPostContent", {
destinationId: $("#currentDestinationId").val(),
blogPostId: $("#currentBlogPost").val(),
content: content
}).then(onSaveBlogPostContent, onError);
}
Related
I have an external list in SharePoint that includes a URL column. The URL column is a calculated field in SQL server, so the entire URL is already there. I need this field to hyperlink and I have been trying to use JSLink to do so. What would the JavaScript for that look like?
For example, if my fields were...
First Name | Last Name | Profile URL
How would I get the URL in the Profile URL field to hyperlink?
I have been looking for solutions all morning without any luck. I am not familiar with JavaScript, so the code I am using is pieced together from posts I have been reading. I have made sure the my JSLink address is correct.
~site/SiteAssets/myCode.js
I have tried different variations of code. My latest is this:
(function () {
var profUrlField = {};
profUrlField.Templates = {};
profUrlField.Templates.Fields = {
"Profile_X0020_URL": {
"View": function (ctx) {
var urlField = ctx.CurrentItem[ctx.CurrentFieldSchema["Profile_X0020_URL"]];
return "<a href='" + urlField + "'>" + urlField + "</a>";
}
}
};
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(profileUrlField);
})();
After applying my JSLink to my web part I reload the page and nothing happens. No errors but no links.
I'm also not sure how to reference the column. In SQL Server it is PROFILE_URL, but in the SharePoint list header it is Profile URL.
Modify the code as below to check if it works.
(function () {
var profUrlField = {};
profUrlField.Templates = {};
profUrlField.Templates.Fields = {
"PROFILE_URL": {
"View": function (ctx) {
var urlField = ctx.CurrentItem[ctx.CurrentFieldSchema.Name];
return "<a href='" + urlField + "'>" + urlField + "</a>";
}
}
};
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(profileUrlField);
})();
I want to call a controller action whenever a value is updated from a textbox.
Note that this script sits inside the same view which will be returned from the Dispatch/Index controller action
I tried doing it like this:
<script>
$('#deliveryDate').change(function () {
var date = $('#deliveryDate').val();
var sDate = date.split('/');
location.href = 'dispatch/' + sDate[0] + sDate[1] + sDate[2];
});
</script>
And it works perfectly the first time the value changes (ie, the page redirects to /dispatch/12122016).
However, when I change the value again, it redirects to /dispatch/dispatch/13122016, so the value just keeps concatanating and this of course produces an error.
I tried chaging the redirect line to location.href = '#Url.Action("Index", "Dispatch")/' + sDate[0] + sDate[1] + sDate[2];, but now it just concatenates the new date on to the url instead of redirecting how I need it to... (ie, it navigates to /dispatch/12122016/13122016)
Is there ANY way of doing this without including the literal url path??
How can "clear" the current url before redirecting the action I need (which should just be dispatch/12122016 ?
Simply prepend a forward slash in the URL, this should always dictate that the url change is always bound to be absolute.
As a bonus: I also changed your date concatenation after /dispatch into a join.
$('#deliveryDate').change(function () {
var date = $('#deliveryDate').val();
location.href = '/dispatch/' + date.split('/').join('');
});
Try this by appending the forward slash. Because your concatenating the dispatch string on every redirect
<script>
$('#deliveryDate').change(function () {
var date = $('#deliveryDate').val();
var sDate = date.split('/');
Var URL = '/dispatch/' + sDate[0] + sDate[1] + sDate[2];
Window.location.href = URL
});
</script>
Is there a way to save the current webpage by using casperjs or phantomjs?
I tried to get the html and save it into a file. But the resulting file was a lot different from the screenshot of that time (with casper.capture). Is there a way to save the current webpage?
Andrey Borisko suggested to use the disk cache to retrieve the resources. My solution is not that efficient, but you don't need to decompress text files.
I use XMLHttpRequest to retrieve all resources after I registered them with the resource.received event handler. I then filter the resources into images, css and fonts. The current limitation is that remote resource paths that contain something like ../ or ./ are not handled correctly.
I retrieve the current page content with getHTML and iterate over all captured resources to replace the path used in the markup, that is identified by a portion of the complete resource URL, with a randomly generated file name. The file extension is created from the content type of the resource. It is converted using mimeType from this gist.
Since CSS files may contain background images or fonts, they have to be processed before saving to disk. The provided loadResource function loads the resource, but does not save it.
Since XMLHttpRequest to download the resources the script has to be invoked with the --web-security=false flag:
casperjs script.js --web-security=false
script.js
var casper = require("casper").create();
var utils = require('utils');
var fs = require('fs');
var mimetype = require('./mimetype'); // URL provided below
var cssResources = [];
var imgResources = [];
var fontResources = [];
var resourceDirectory = "resources";
var debug = false;
fs.removeTree(resourceDirectory);
casper.on("remote.message", function(msg){
this.echo("remote.msg: " + msg);
});
casper.on("resource.error", function(resourceError){
this.echo("res.err: " + JSON.stringify(resourceError));
});
casper.on("page.error", function(pageError){
this.echo("page.err: " + JSON.stringify(pageError));
});
casper.on("downloaded.file", function(targetPath){
if (debug) this.echo("dl.file: " + targetPath);
});
casper.on("resource.received", function(resource){
// don't try to download data:* URI and only use stage == "end"
if (resource.url.indexOf("data:") != 0 && resource.stage == "end") {
if (resource.contentType == "text/css") {
cssResources.push({obj: resource, file: false});
}
if (resource.contentType.indexOf("image/") == 0) {
imgResources.push({obj: resource, file: false});
}
if (resource.contentType.indexOf("application/x-font-") == 0) {
fontResources.push({obj: resource, file: false});
}
}
});
// based on http://docs.casperjs.org/en/latest/modules/casper.html#download
casper.loadResource = function loadResource(url, method, data) {
"use strict";
this.checkStarted();
var cu = require('clientutils').create(utils.mergeObjects({}, this.options));
return cu.decode(this.base64encode(url, method, data));
};
function escapeRegExp(string) {
// from https://stackoverflow.com/a/1144788/1816580
return string.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
}
function replaceAll(find, replace, str) {
// from https://stackoverflow.com/a/1144788/1816580
return str.replace(find, replace);
}
var wrapFunctions = [
function wrapQuot1(s){
return '"' + s + '"';
},
function wrapQuot2(s){
return "'" + s + "'";
},
function csswrap(s){
return '(' + s + ')';
}
];
function findAndReplace(doc, resources, resourcesReplacer) {
// change page on the fly
resources.forEach(function(resource){
var url = resource.obj.url;
// don't download again
if (!resource.file) {
// set random filename and download it **or** call further processing which in turn will load ans write to disk
resource.file = resourceDirectory+"/"+Math.random().toString(36).slice(2)+"."+mimetype.ext[resource.obj.contentType];
if (typeof resourcesReplacer != "function") {
if (debug) casper.echo("download resource (" + resource.obj.contentType + "): " + url + " to " + resource.file);
casper.download(url, resource.file, "GET");
} else {
resourcesReplacer(resource);
}
}
wrapFunctions.forEach(function(wrap){
// test the resource url (growing from the back) with a string in the document
var lastURL;
var lastRegExp;
var subURL;
// min length is 4 characters
for(var i = 0; i < url.length-5; i++) {
subURL = url.substring(i);
lastRegExp = new RegExp(escapeRegExp(wrap(subURL)), "g");
if (doc.match(lastRegExp)) {
lastURL = subURL;
break;
}
}
if (lastURL) {
if (debug) casper.echo("replace " + lastURL + " with " + resource.file);
doc = replaceAll(lastRegExp, wrap(resource.file), doc);
}
});
});
return doc;
}
function capturePage(){
// remove all <script> and <base> tags
this.evaluate(function(){
Array.prototype.forEach.call(document.querySelectorAll("script"), function(scr){
scr.parentNode.removeChild(scr);
});
Array.prototype.forEach.call(document.querySelectorAll("base"), function(scr){
scr.parentNode.removeChild(scr);
});
});
// TODO: remove all event handlers in html
var page = this.getHTML();
page = findAndReplace(page, imgResources);
page = findAndReplace(page, cssResources, function(cssResource){
var css = casper.loadResource(cssResource.obj.url, "GET");
css = findAndReplace(css, imgResources);
css = findAndReplace(css, fontResources);
fs.write(cssResource.file, css, "wb");
});
fs.write("page.html", page, "wb");
}
casper.start("http://www.themarysue.com/").wait(3000).then(capturePage).run(function(){
this.echo("DONE");
this.exit();
});
The magic happens in findAndReplace. capturePage is completely synchronous so it can be dropped anywhere without much head ache.
URL for mimetype.js
No, I don't think there is an easy way to do this as phantomjs doesn't support rendering pages in mht format (Render as a .mht file #10117). I believe that's what you wanted.
So, it needs some work to accomplish this. I did something similar, but i was doing it the other way around I had a rendered html code that I was rendering into image/pdf through phantomjs. I had to clean the file first and it worked fine for me.
So, what I think you need to do is:
strip all js calls, like script tags or onload attributes, etc..
if you have access from local to the resources like css, images and so on (and you don't need authentication to that domain where you grab the page) than you need to change relative paths of src attributes to absolute to load images/etc.
if you don't have access to the resources when you open the page then I think you need to implement similar script to download those resources at the time phantomjs loads the page and then redirect src attributes to that folder or maybe use data uri.
You might need to change links in css files as well.
This will bring up the images\fonts and styling you are missing currently.
I'm sure there are more points. I'll update the answer if you need more info, once I see my code.
I have a MVC3 action method with 3 parameters like this:
var url = "/Question/Insert?" + "_strTitle='" + title + "'&_strContent='" + content + "'&_listTags='" + listTags.toString() + "'";
and I want to call this by normal javascript function not AJAX (because it's not necessary to use AJAX function)
I tried to use this function but it didn't work:
window.location.assign(url);
It didn't jump to Insert action of QuestionController.
Is there someone would like to help me? Thanks a lot
This is more detail
I want to insert new Question to database, but I must get data from CKeditor, so I have to use this function below to get and validate data
// insert new question
$("#btnDangCauHoi").click(function () {
//validate input data
//chủ đề câu hỏi
var title = $("#txtTitle").val();
if (title == "") {
alert("bạn chưa nhập chủ đề câu hỏi");
return;
}
//nội dung câu hỏi
var content = GetContents();
content = "xyz";
if (content == "") {
alert("bạn chưa nhập nội dung câu hỏi");
return;
}
//danh sách Tag
var listTags = new Array();
var Tags = $("#list_tag").children();
if (Tags.length == 0) {
alert("bạn chưa chọn tag cho câu hỏi");
return;
}
for (var i = 0; i < Tags.length; i++) {
var id = Tags[i].id;
listTags[i] = id;
//var e = listTags[i];
}
var data = {
"_strTitle": title,
"_strContent": content,
"_listTags": listTags.toString()
};
// $.post(url, data, function (result) {
// alert(result);
// });
var url = "/Question/Insert?" + "_strTitle='" + title + "'&_strContent='" + content + "'&_listTags='" + listTags.toString() + "'";
window.location.assign(url); // I try to use this, and window.location also but they're not working
});
This URL call MVC action "Insert" below by POST method
[HttpPost]
[ValidateInput(false)]
public ActionResult Insert(string _strTitle, string _strContent, string _listTags)
{
try
{
//some code here
}
catch(Exception ex)
{
//if some error come up
ViewBag.Message = ex.Message;
return View("Error");
}
// if insert new question success
return RedirectToAction("Index","Question");
}
If insert action success, it will redirect to index page where listing all question include new question is already inserted. If not, it will show error page. So, that's reason I don't use AJAX
Is there some one help me? Thanks :)
Try:
window.location = yourUrl;
Also, try and use Fiddler or some other similar tool to see whether the redirection takes place.
EDIT:
You action is expecting an HTTP POST method, but using window.location will cause GET method. That is the reason why your action is never called.
[HttpPost]
[ValidateInput(false)]
public ActionResult Insert(string _strTitle, string _strContent, string _listTags)
{
// Your code
}
Either change to HttpGet (which you should not) or use jQuery or other library that support Ajax in order to perform POST. You should not use GET method to update data. It will cause so many security problems for your that you would not know where to start with when tackling the problem.
Considering that you are already using jQuery, you might as well go all the way and use Ajax. Use $.post() method to perform HTTP POST operation.
Inside a callback function of the $.post() you can return false at the end in order to prevent redirection to Error or Index views.
$.post("your_url", function() {
// Do something
return false; // prevents redirection
});
That's about it.
You could try changing
var url = "/Question/Insert?" + "_strTitle='" + title + "'&_strContent='" + content + "'&_listTags='" + listTags.toString() + "'";
to
var url = "/Question/Insert?_strTitle=" + title + "&_strContent=" + content + "&_listTags=" + listTags.toString();
I've removed the single quotes as they're not required.
Without seeing your php code though it's not easy to work out where the problem is.
When you say "It didn't jump to Insert action of QuestionController." do you mean that the browser didn't load that page or that when the url was loaded it didn't route to the expected controller/action?
You could use an iframe if you want to avoid using AJAX, but I would recommend using AJAX
<iframe src="" id="loader"></iframe>
<script>
document.getElementById("loader").src = url;
</script>
Basically, I want to have an interactive button on my website, that, when clicked, sends some data to the server in order to be checked and display the response (without form sending / page reload).
I thought it would be something like:
function checkData()
{
var req = new XMLHttpRequest();
var conf = document.getElementById('my_text_area').value;
req.open("GET", 'check_data', true);
req.onreadystatechange = function ()
{
var pre = document.getElementById('check_data_out');
pre.innerHTML = req.responseText;
}
req.send(conf);
return false;
}
And on the server side:
#get('/check_data')
def check_data():
# Process the content and answer something...
content = str(request.is_ajax) + ' - ' + str(request.GET) + ' - ' + str(request.POST)
return content
But this obviously doesn't work. Either it is not the right way to send data via javascript or not the right way to access it in bottle.py.
Showing me how it works is highly appreciated.
You can use dojo for client side logic.
var button = dojo.byId('button_id'); // button_id refers to the id of the button you want to click
dojo.connect(button,'onclick',dojo.xhrGet({
url: '/check_data',
handleAs : 'text',
load : function(response){
dojo.byId('button_id').innerHTML = response;
}
}));