Arabic characters are garbled when exported and viewed in Excel - xpages

I am trying to export my xpages to excel. It involves exporting arabic text and number to excel.
The problem is when I view the export column in excel (client name in arabic). the result is garbage.
My lotus database is configure to support english and arabic, encoding is utf-8
Any help is very much welcome.
Here is the code I am using.
var exCon = facesContext.getExternalContext();
var writer = facesContext.getResponseWriter();
var response = exCon.getResponse();
docIDArray=sessionScope.selectedDocs;
//lets define domino classess
var myView:NotesView = database.getView(sessionScope.vname);
response.setContentType("application/vnd.ms-excel;charset=utf-8");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Content-disposition", "attachment; filename=CustomerCare.xls");
writer.write("<table>");
writer.write("<thead><tr>");
writer.write("<td><b>Created</b></td>");
writer.write("<td><b>Client Name</b></td>");
writer.write("<td><b>Daybreak ID</b></td>");
writer.write("<td><b>Request type</b></td>");
writer.write("<td><b>Status</b></td>");
writer.write("<td><b>Mobile #</b></td>");
writer.write("<td><b>Escalation</b></td>");
writer.write("<td><b>Request via</b></td>");
writer.write("<td><b>From</b></td>");
writer.write("<td><b>Updated by</b></td>");
writer.write("</tr></thead>");
/**
debuggin purpose only
print(sessionScope.vname+'-viewname');
print(sessionScope.selectedDocs+' -selectedDocs');
print(sessionScope.vfilter+'-vfilter' );
print(sessionScope.catFilter+'-catFilter');
**/
//determine if user wants to export all or the individual documents
//export all document in current display/view
if (docIDArray.length==0){
//since some view are special evaluate them here
switch(sessionScope.vname)
{
case "Status":
var dc:NotesDocumentCollection=myView.getAllDocumentsByKey(sessionScope.vfilter);
var doc:NotesDocument=dc.getFirstDocument();
while (doc!= null){
writer.write("<tr>");
writer.write("<td>" + doc.getItemValueDateTimeArray("dxdateFiled").elementAt(0)+ "</td>");
writer.write("<td>" + doc.getItemValueString("cxClientName")+ "</td>");
writer.write("<td>" + doc.getItemValueString("cxDBID") + "</td>");
writer.write("<td>" + #Implode(doc.getItemValueString("cxStatus_1"),",") + "</td>");
//writer.write("<td>" + doc.getItemValueString("cxStatus_1") + "</td>");
writer.write("<td>" + doc.getItemValueString("cxStatus1") + "</td>");
writer.write("<td>" + doc.getItemValueString("cxMobile") + "</td>");
if(doc.getItemValue("escalationlevel").toString()=='[3.0]'){
writer.write("<td>" + '3' + "</td>");
}else{
writer.write("<td>" + '-' + "</td>");
}
writer.write("<td>" + doc.getItemValueString("cxRecRequestvia") + "</td>");
writer.write("<td>" + doc.getItemValueString("From")+ "</td>");
writer.write("<td>" + doc.getItemValueString("Closedby") + "</td>");
writer.write("</tr>");
doc=dc.getNextDocument(doc);
}
break;
case "Categories":
case "callStatus":
var sString:String = sessionScope.catFilter;
var viewNav:NotesViewNavigator = myView.createViewNavFromCategory(sString);
var viewEnt:NotesViewEntry = viewNav.getFirst();
while (viewEnt!=null){
writer.write("<tr>");
writer.write("<td>" + viewEnt.getColumnValues()[2] + "</td>");
writer.write("<td>" + viewEnt.getColumnValues()[3] + "</td>");
writer.write("<td>" + viewEnt.getColumnValues()[5] + "</td>");
writer.write("<td>" + viewEnt.getColumnValues()[7].toString() + "</td>");
writer.write("<td>" + viewEnt.getColumnValues()[8] + "</td>");
writer.write("<td>" + viewEnt.getColumnValues()[9] + "</td>");
if( viewEnt.getColumnValues()[6].toString()=='3'){
writer.write("<td>" + '3' + "</td>");
}else{
writer.write("<td>" + '-' + "</td>");
}
writer.write("<td>" + viewEnt.getColumnValues()[10] + "</td>");
writer.write("<td>" + viewEnt.getColumnValues()[1] + "</td>");
writer.write("<td>" + viewEnt.getColumnValues()[11] + "</td>");
writer.write("</tr>");
viewEnt = viewNav.getNext(viewEnt);
}
break;
default:
var viewNav:NotesViewNavigator = myView.createViewNav();
var viewEnt:NotesViewEntry = viewNav.getFirst();
while (viewEnt!=null){
writer.write("<tr>");
writer.write("<td>" + viewEnt.getColumnValues()[2] + "</td>");
writer.write("<td>" + viewEnt.getColumnValues()[3] + "</td>");
writer.write("<td>" + viewEnt.getColumnValues()[5] + "</td>");
writer.write("<td>" + viewEnt.getColumnValues()[7].toString() + "</td>");
writer.write("<td>" + viewEnt.getColumnValues()[8] + "</td>");
writer.write("<td>" + viewEnt.getColumnValues()[9] + "</td>");
if( viewEnt.getColumnValues()[6].toString()=='3'){
writer.write("<td>" + '3' + "</td>");
}else{
writer.write("<td>" + '-' + "</td>");
}
writer.write("<td>" + viewEnt.getColumnValues()[10] + "</td>");
writer.write("<td>" + viewEnt.getColumnValues()[1] + "</td>");
writer.write("<td>" + viewEnt.getColumnValues()[11] + "</td>");
writer.write("</tr>");
viewEnt = viewNav.getNext(viewEnt);
}
}
}else{
var db:NotesDatabase = session.getCurrentDatabase();
switch(sessionScope.vname)
{
case "Status":
for(i=0;i < docIDArray.length;i++){
var docId=docIDArray[i];
var doc:NotesDocument=db.getDocumentByID(docId);
var output:string = "";
if(doc != null) {
writer.write("<tr>");
writer.write("<td>" + doc.getItemValueDateTimeArray("dxdateFiled").elementAt(0)+ "</td>");
writer.write("<td>" + doc.getItemValueString("cxClientName")+ "</td>");
writer.write("<td>" + doc.getItemValueString("cxDBID") + "</td>");
writer.write("<td>" + doc.getItemValueString("cxStatus_1") + "</td>");
writer.write("<td>" + doc.getItemValueString("cxStatus1") + "</td>");
writer.write("<td>" + doc.getItemValueString("cxMobile") + "</td>");
if(doc.getItemValue("escalationlevel").toString()=='[3.0]'){
writer.write("<td>" + '3' + "</td>");
}else{
writer.write("<td>" + '-' + "</td>");
}
writer.write("<td>" + doc.getItemValueString("cxRecRequestvia") + "</td>");
writer.write("<td>" + doc.getItemValueString("cxUsername") + "</td>");
writer.write("<td>" + doc.getItemValueString("Closedby") + "</td>");
writer.write("</tr>");
} // end if
}//end for
break;
default:
for(i=0;i < docIDArray.length;i++){
var docId=docIDArray[i];
var doc:NotesDocument=db.getDocumentByID(docId);
var output:string = "";
if(doc != null) {
writer.write("<tr>");
writer.write("<td>" + doc.getItemValueDateTimeArray("dxdateFiled").elementAt(0)+ "</td>");
writer.write("<td>" + doc.getItemValueString("cxClientName")+ "</td>");
writer.write("<td>" + doc.getItemValueString("cxDBID") + "</td>");
writer.write("<td>" + doc.getItemValueString("cxStatus_1") + "</td>");
writer.write("<td>" + doc.getItemValueString("cxStatus1") + "</td>");
writer.write("<td>" + doc.getItemValueString("cxMobile") + "</td>");
if(doc.getItemValue("escalationlevel").toString()=='[3.0]'){
writer.write("<td>" + '3' + "</td>");
}else{
writer.write("<td>" + '-' + "</td>");
}
writer.write("<td>" + doc.getItemValueString("cxRecRequestvia") + "</td>");
writer.write("<td>" + doc.getItemValueString("cxUsername") + "</td>");
writer.write("<td>" + doc.getItemValueString("Closedby") + "</td>");
writer.write("</tr>");
} // end if
}//end for
}
}
writer.write("</table>");
writer.endDocument();
facesContext.responseComplete();

I'd recommend looking at Apache POI. It's likely to have addressed the issue you're encountering and is also more widely used. The APIs for creating an Excel spreadsheet are pretty intuitive, especially if you've done similar things in LotusScript.
The approach you're using at the moment will throw security warnings to the user with more recent version of MS Office (it's generic to web development and MS Office, not specific to XPages). Apache POI will also mean you don't get those warnings.

Related

accented strings not displayed correctly in csv file in Excel

I read data from mysql database and then save it to csv file. I checked on the server side, the file is correctly saved with utf8 format.
Then the user is prompted to download the file. When I download the file on my computer (MacOSX), the file is correct with utf8. (with file command in Termninal)
When I open the csv file in Excel, accented characters are wrong.
In Excel, I have AZERTY√©a instead of AZERTYéa if I open the file with a text editor.
Here is my piece of code:
// File creation
var reportFile = Date.now();
fs.closeSync(fs.openSync(__dirname + '/reports/' + reportFile + '.csv', 'w'));
var attributes = [];
var row = [];
fs.appendFileSync(__dirname + '/reports/' + reportFile + '.csv', "\ufeff");
for(var x = 0; x<fields.length; x++) attributes.push(fields[x].name);
fs.appendFile(__dirname + '/reports/' + reportFile + '.csv', attributes.join('|'), function (err) {
if(err) console.log('Error appending fields', err);
fs.appendFileSync(__dirname + '/reports/' + reportFile + '.csv', '\n');
for(var x = 0; x<results.length; x++) {
row = [];
for(var y = 0; y<attributes.length; y++){
row.push(results[x][attributes[y]]);
}
fs.appendFileSync(__dirname + '/reports/' + reportFile + '.csv', row.join('|'));
fs.appendFileSync(__dirname + '/reports/' + reportFile + '.csv', '\n');
}
// file download
req.reportFile = reportFile;
res.setHeader('Content-disposition', 'attachment; filename='+__dirname + '/reports/' + reportFile + '.csv');
res.set('Content-Type', 'text/csv; charset=utf-8');
fs.readFile(__dirname + '/reports/' + reportFile + '.csv', 'utf8', function (err,data) {
if (err) {
return console.log(err);
}
console.log(data);
res.header("Access-Control-Allow-Origin", "*");
res.status(200).send(data);
});
});
I finnaly found the solution. It was a BOM problem when sending the file. I tought that it was already set because I set it when writing the file....
I changed this line
res.status(200).send(data);
to
res.status(200).send('\ufeff'+data);

Node.JS call function can't with dictionary

I am new Node.JS developer.
I have a question, when I call function the parameter with Dictionary format. Then function that had been called can't be executed, why?
function testFunction(allObjects, test, response) {
console.log("go in testFunction");
var dic = {a: "aaa", b:"bbb"};
testFunctionTo(dic, response);
}
function testFunctionTo(dic, response) {
console.log("go in testFunctionTo");
response.send("success");
}
result:
go in testFunction;
the original code like below:
//generate and mapping all master data from this import
function prepareMasterRequireData(allObjects, response) {
var singleCustomer = {}; //id: ParseObjectId
var singleCustomerData = {}; //id: syncLog
var singleMaterial = {}; //id: ParseObjectId
var singleMaterialData = {}; // id: syncLog
var singleUom = {}; //id: ParseObjectId
var singleUomData = {}; // id: syncLog
var singleOrderHeader = {}; //id: ParseObjectId
var singleOrderHeaderData = {}; //id: syncLog
//prepare single data
for (var i=allObjects.length-1; i>=0; i--) {
var syncLog = allObjects[i];
if (syncLog.get("TypeFlag") == "A") {
//prepare for customer
var customerId = syncLog.get("Customer_SN");
if (singleCustomer[customerId] == null) {
singleCustomer[customerId] = "";
singleCustomerData[customerId] = syncLog;
}
//prepare for material
var materialId = syncLog.get("Product_SN");
if (singleMaterial[materialId] == null) {
singleMaterial[materialId] = "";
singleMaterialData[materialId] = syncLog;
}
//prepare for uom
var UomId = syncLog.get("Product_Unit");
if (singleUom[UomId] == null) {
singleUom[UomId] = "";
singleUomData[UomId] = syncLog;
}
//prepare for Orderheader
var orderId = syncLog.get("Order_SN_Master");
if (singleOrderHeader[orderId] = null) {
singleOrderHeader[orderId] = "";
singleOrderHeaderData[orderId] = syncLog;
}
} else {
delete allObjects[i];
}
}
var customerCount = Object.keys(singleCustomer).length;
var materialCount = Object.keys(singleMaterial).length;
var UomCount = Object.keys(singleUom).length;
var currentCustomerCount = 0;
var currentMaterialCount = 0;
var currentUomCount = 0;
for (key in singleCustomer) {
getCustomerID(key, singleCustomerData[key], {
success: function(key, objectId) {
singleCustomer[key] = objectId;
currentCustomerCount ++;
var stringValue = customerCount + " " + materialCount + " " + UomCount + " " +currentCustomerCount + " " +currentMaterialCount + " " + currentUomCount;
console.log("customer succ " + stringValue);
if ((currentCustomerCount == customerCount) &&
(currentMaterialCount == materialCount) &&
(currentUomCount == UomCount)) {
console.log("go customer succ");
updateImportMasterData(allObjects, singelCustomer, singleMaterial, singleUom, singleOrderHeader, response);
}
},
error: function(key, error) {
currentCustomerCount ++;
var stringValue = customerCount + " " + materialCount + " " + UomCount + " " +currentCustomerCount + " " +currentMaterialCount + " " + currentUomCount;
console.log("customer fail " + stringValue);
if ((currentCustomerCount == customerCount) &&
(currentMaterialCount == materialCount) &&
(currentUomCount == UomCount)) {
console.log("go customer fail");
updateImportMasterData(allObjects, singelCustomer, singleMaterial, singleUom, singleOrderHeader, response);
}
}
});
}
for (key in singleMaterial) {
getMaterialId(key, singleMaterialData[key], {
success: function(key, objectId) {
singleMaterial[key] = objectId;
currentMaterialCount ++;
var stringValue = customerCount + " " + materialCount + " " + UomCount + " " +currentCustomerCount + " " +currentMaterialCount + " " + currentUomCount;
console.log("material succ " + stringValue);
if ((currentCustomerCount == customerCount) &&
(currentMaterialCount == materialCount) &&
(currentUomCount == UomCount)) {
console.log("go material succ");
updateImportMasterData(allObjects, singelCustomer, singleMaterial, singleUom, singleOrderHeader, response);
}
},
error: function(key, error) {
currentMaterialCount ++;
var stringValue = customerCount + " " + materialCount + " " + UomCount + " " +currentCustomerCount + " " +currentMaterialCount + " " + currentUomCount;
console.log("material fail " + stringValue);
if ((currentCustomerCount == customerCount) &&
(currentMaterialCount == materialCount) &&
(currentUomCount == UomCount)) {
console.log("go material fail");
updateImportMasterData(allObjects, singelCustomer, singleMaterial, singleUom, singleOrderHeader, response);
}
}
});
}
for (key in singleUom) {
getUOMId(key, singleUomData[key], {
success: function(key, objectId) {
singleUom[key] = objectId;
currentUomCount ++;
var stringValue = customerCount + " " + materialCount + " " + UomCount + " " +currentCustomerCount + " " +currentMaterialCount + " " + currentUomCount;
console.log("uom succ " + stringValue);
if ((currentCustomerCount == customerCount) &&
(currentMaterialCount == materialCount) &&
(currentUomCount == UomCount)) {
//testFunctionTo(singelCustomer, response);
console.log("go uom succ");
updateImportMasterData(allObjects, singelCustomer, singleMaterial, singleUom, singleOrderHeader, response);
}
},
error: function(key, error) {
currentUomCount ++;
var stringValue = customerCount + " " + materialCount + " " + UomCount + " " +currentCustomerCount + " " +currentMaterialCount + " " + currentUomCount;
console.log("uom fail " + stringValue);
if ((currentCustomerCount == customerCount) &&
(currentMaterialCount == materialCount) &&
(currentUomCount == UomCount)) {
console.log("go uom fail");
updateImportMasterData(allObjects, singelCustomer, singleMaterial, singleUom, singleOrderHeader, response);
}
}
});
}
//response.send(resultString);
}
//update syncLog for this import
function updateImportMasterData(allObjects, singelCustomer, singleMaterial, singleUom, singleOrderHeader, response) {
console.log("yes in update");
......
}
result:
customer succ 1 1 1 1 0 0
material succ 1 1 1 1 1 0
uom succ 1 1 1 1 1 1
go uom succ
You call the function within the same block of "console.log("go material succ");" and that "go material succ" thing wasn't printed out, that means it didn't enter the if condition...
if ((currentCustomerCount == customerCount) &&
(currentMaterialCount == materialCount) &&
(currentUomCount == UomCount)) {
console.log("go material succ");
updateImportMasterData(allObjects, singelCustomer, singleMaterial, singleUom, singleOrderHeader, response);
}

Node js + Multiple query transaction + Affiliate API data insert into postgresql database

Now i am working with Flipkart affiliate API and get the categories and products insert into my database.
I am using nodejs backend and postgresql database.
I used 4 async loop. But I done something but don't know the correct approach. Here I want to execute the loops in asynchronous and once all the process(loops) end means need to send response. How to I determine the all loops executed successfully. Please anyone suggest the correct approach.
var request = require('request');
var dateFormat = require('date-format');
var async = require('async');
router.get('/getproducts', function(req, res) {
var affiliateIdFrom = 1;
var affiliateUrl = "https://affiliate-api.flipkart.net/affiliate/api/<your affiliate_tracking_id>.json";
request(affiliateUrl, function(error, response, html) {
var resData = JSON.parse(html);
var dataObj = resData.apiGroups.affiliate.apiListings;
async.each(Object.keys(dataObj), function(item, done) {
var objData = dataObj[item].availableVariants['v0.1.0'];
var cname = objData.resourceName;
var curl = objData.get;
client.query('INSERT into product_category (affiliate_from, name, url,created_on) values (' + "'" + affiliateIdFrom + "'" + ',' + "'" + cname + "'" + ',' + "'" + curl + "'" + ',' + "'" + today + "'" + ')', function(err, result) {
if (err) {
console.log(err);
res.send({
data : "Soemthing went wrong",
});
}
done(err, result);
});
}, function(err) {
product.getProductDetails(affiliateIdFrom);
});
});
});
var product = {
getProductDetails : function(aId) {
var today = dateFormat(new Date());
client.query("select * from product_category where affiliate_from = " + aId + " limit 1", function(err, result) {
if (err) {
console.log(err);
}
var categoryList = result.rows;
async.each(categoryList, function(value, done) {
request.get({
headers : {
'Fk-Affiliate-Id' : 'XXXXX',
'Fk-Affiliate-Token' : 'XXXXXXXXXXXXXXXXXXXXXXX'
},
url : value.url
}, function(error, response, body) {
var data = JSON.parse(body);
var dataLength = data.productInfoList.length;
var dataObj = data.productInfoList;
if (dataLength > 0) {
async.each(dataObj, function(value1, done1) {
var productBasicInfo = value1.productBaseInfo.productIdentifier;
var productId = productBasicInfo.productId;
var productDetails = value1.productBaseInfo.productAttributes;
var pTitle = productDetails.title;
var thumbnailUrl = JSON.stringify(productDetails.imageUrls);
var category = productBasicInfo.categoryPaths.categoryPath[0][0].title;
var mrp = productDetails.maximumRetailPrice.amount;
var price = productDetails.sellingPrice.amount;
var prodcutUrl = productDetails.productUrl;
var productDescription = productDetails.productDescription;
if (productDescription != null) {
productDescription = productDescription.replace(/'/g, "\''");
}
var inStock = productDetails.inStock;
var information = JSON.stringify(value1);
var q = 'insert into product(affiliate_from, title, image_url, category_paths, mrp, price, url, description, in_stock, information, created_on) values (' + "'" + aId + "'" + ', ' + "'" + pTitle + "'" + ', ' + "'" + thumbnailUrl + "'" + ', ' + "'" + category + "'" + ', ' + "'" + mrp + "'" + ', ' + "'" + price + "'" + ', ' + "'" + prodcutUrl + "'" + ', ' + "'" + productDescription + "'" + ', ' + "'" + inStock + "'" + ', ' + "'" + information + "'" + ', ' + "'" + today + "'" + ' )';
console.log(q);
client.query(q, function(err, result) {
if (err) {
console.log(err);
} else {
console.log('inserted successfully');
}
});
done1("err", "result");
}, function(err) {
console.log('dddddddddd');
});
}
//console.log(data.productInfoList);
console.log(data.productInfoList.length);
done(err, "result");
});
}, function(err) {
console.log('doneeeeee');
});
});
}
};
The correct approach is to place each of your asynchronous requests inside a transaction, which when finished, will give you the indication of whether the whole set of queries was successful or not.
For example, using pg-promise syntax, your transaction would like this:
db.tx(function () {
return promise.all([
this.query("insert 1 ..."),
this.query("insert 2 ..."),
this.query("insert 3 ...")
]);
})
.then(function (data) {
// success;
}, function (reason) {
// error
});

How to implement a text editor in a browser [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
This is purely an exercise in self improvement and education.I am trying to implement an extension for a vi-like text editor within a browser. Has anyone got any idea how I would go about doin this?
I created a VERY basic editor a couple weeks ago for a project. It could get you started :) Toss this code into a JS file, add a reference to it on your webpage
Add this to your
$("#msgBody").SiteRtfEditor();
Add this to your body html:
<textarea id="msgBody"></textarea>
JS Code:
(function ($) {
$.fn.SiteRtfEditor = function (options) {
var defaults = {
iFrameUrl: "",
width: "100%",
height: "100%",
showModes: true
};
var opts = $.extend(defaults, options);
return this.each(function () {
var thisControlID = this.id.toString();
var rtfEditorID = "SiteRtfEditor_" + thisControlID.toString();
var swatchCommand = "forecolor";
$("<style type='text/css'>." + rtfEditorID + "_Swatch{display:block;width:13px;height:13px;margin:0;padding:0px;border:1px solid #d3d3d3;border-spacing:0px;border-collapse:collapse;}</style>").appendTo("head");
//Build HTML
var htmlOutput = "<div id='rtfEditorControls' style='padding:0px;margin:3px;text-align:left;line-height:21px;vertical-align:middle;white-space:nowrap;'>";
htmlOutput += "<select id='" + rtfEditorID + "_FontFamily'>";
htmlOutput += "<option value='Arial'>Arial</option>";
htmlOutput += "<option value='Comic Sans MS'>Comic Sans MS</option>";
htmlOutput += "<option value='Courier New'>Courier New</option>";
htmlOutput += "<option value='Monotype Corsiva'>Monotype</option>";
htmlOutput += "<option value='Tahoma'>Tahoma</option>";
htmlOutput += "<option value='Times'>Times</option>";
htmlOutput += "</select> <select id='" + rtfEditorID + "_FontSize'>";
htmlOutput += "<option value='8'>8pt</option><option value='10'>10pt</option><option value='12'>12pt</option><option value='14'>14pt</option>";
htmlOutput += "<option value='16'>16pt</option><option value='18'>18pt</option><option value='20'>20pt</option><option value='22'>22pt</option>";
htmlOutput += "<option value='24'>24pt</option><option value='28'>28pt</option><option value='32'>32pt</option><option value='36'>36pt</option>";
htmlOutput += "</select><br />";
htmlOutput += "<input type='button' id='" + rtfEditorID + "_Bold' style='height:21px;width:21px;font-weight:bold;margin:2px;padding:0px;border:1px solid #000000;' value='B' />";
htmlOutput += "<input type='button' id='" + rtfEditorID + "_Italic' style='height:21px;width:21px;font-style:italic;margin:2px;padding:0px;border:1px solid #000000;' value='I' />";
htmlOutput += "<input type='button' id='" + rtfEditorID + "_Underline' style='height:21px;width:21px;text-decoration:underline;margin:2px;padding:0px;border:1px solid #000000;' value='U' />";
htmlOutput += "<input type='button' id='" + rtfEditorID + "_BackColor' style='border:0px;height:16px;width:16px;margin:2px 6px 2px 6px;padding:0px;background:#ffffff url(/Images/BackColor.gif) no-repeat;' />";
htmlOutput += "<input type='button' id='" + rtfEditorID + "_ForeColor' style='border:0px;height:16px;width:16px;margin:2px 6px 2px 6px;padding:0px;background:#ffffff url(/Images/ForeColor.gif) no-repeat;' />";
htmlOutput += "<div id='" + rtfEditorID + "_ColorPalette' style='position:absolute;z-index:202;display:none;margin:0px;background-color:#ffffff;border:1px solid #a7abb0;'></div>";
htmlOutput += "</div>";
htmlOutput += "<div style='position:relative;z-index:200;width:100%;height:100%;margin:0px;padding:0px;'><iframe id='" + rtfEditorID + "_Frame' frameborder='0' marginheight='0' marginwidth='0' scrolling='auto' windowless='true' style='width:99%;height:100%;border-spacing:0px;border-collapse:collapse;border:1px solid #d3d3d3;background-color:#ffffff;padding:0px;margin-left:auto;margin-right:auto;position:relative;z-index:201;'></iframe></div>";
if (opts.showModes) {
htmlOutput += "<div style='width:100%;text-align:left;'><input type='button' id='" + rtfEditorID + "_DesignerMode' style='border:0;background:transparent;font-weight:bold;' value='Design' /> <input type='button' id='" + rtfEditorID + "_SourceMode' style='border:0;background:transparent;' value='Source' /></div>";
}
$("#" + thisControlID).before("<div id='" + rtfEditorID + "' style='position:relative;padding:0px;margin:0px;border:1px solid #d3d3d3;background-color:#f1f1f1;width:" + opts.Width + ";height:" + opts.Height + ";text-align:center;'>");
$("#" + thisControlID).css("width", "98%").css("height", "100%").css("margin", "auto");
$("#" + thisControlID).hide();
$("#" + rtfEditorID).html(htmlOutput);
$("#" + rtfEditorID + "_Frame").after($("#" + thisControlID));
BuildColorPalette(rtfEditorID + "_ColorPalette");
function BuildColorPalette(paletteID) {
var paletteHtml = "";
var firstRowList = ["ffffff", "000000", "eeece1", "1f497d", "4f81bd", "c0504d", "9bbb59", "8064a2", "4bacc6", "f79646"];
var colorcol1 = ["f2f2f2", "d8d8d8", "bfbfbf", "a5a5a5", "7f7f7f"];
var colorcol2 = ["7f7f7f", "595959", "3f3f3f", "262626", "0c0c0c"];
var colorcol3 = ["ddd9c3", "c4bd97", "938953", "494429", "1d1b10"];
var colorcol4 = ["c6d9f0", "8db3e2", "548dd4", "17365d", "0f243e"];
var colorcol5 = ["dbe5f1", "b8cce4", "95b3d7", "366092", "244061"];
var colorcol6 = ["f2dcdb", "e5b9b7", "d99694", "953734", "632423"];
var colorcol7 = ["ebf1dd", "d7e3bc", "c3d69b", "76923c", "4f6128"];
var colorcol8 = ["e5e0ec", "ccc1d9", "b2a2c7", "5f497a", "3f3151"];
var colorcol9 = ["dbeef3", "b7dde8", "92cddc", "31859b", "205867"];
var colorcol10 = ["fdeada", "fbd5b5", "fac08f", "e36c09", "974806"];
var lastRowList = ["c00000", "ff0000", "ffc000", "ffff00", "92d050", "00b050", "00b0f0", "0070c0", "002060", "7030a0"];
//First first
paletteHtml = "<table style='margin:3px;'><tr><td colspan='10'>Theme Colors</td></tr><tr>";
for (i = 0; i < firstRowList.length; i++) {
paletteHtml += "<td><input type='button' class='" + rtfEditorID + "_Swatch' title='#" + firstRowList[i] + "' style='background-color:#" + firstRowList[i] + ";' /></td>";
};
paletteHtml += "</tr><tr><td colspan='10' style='height:5px;'></td></tr><tr>";
//Middle shades
paletteHtml += "<td>" + BuildShadeColumn(colorcol1) + "</td>";
paletteHtml += "<td>" + BuildShadeColumn(colorcol2) + "</td>";
paletteHtml += "<td>" + BuildShadeColumn(colorcol3) + "</td>";
paletteHtml += "<td>" + BuildShadeColumn(colorcol4) + "</td>";
paletteHtml += "<td>" + BuildShadeColumn(colorcol5) + "</td>";
paletteHtml += "<td>" + BuildShadeColumn(colorcol6) + "</td>";
paletteHtml += "<td>" + BuildShadeColumn(colorcol7) + "</td>";
paletteHtml += "<td>" + BuildShadeColumn(colorcol8) + "</td>";
paletteHtml += "<td>" + BuildShadeColumn(colorcol9) + "</td>";
paletteHtml += "<td>" + BuildShadeColumn(colorcol10) + "</td>";
//Last row
paletteHtml += "</tr><tr><td colspan='10'>Standard Colors</td></tr><tr>";
for (i = 0; i < lastRowList.length; i++) {
paletteHtml += "<td><input type='button' class='" + rtfEditorID + "_Swatch' title='#" + lastRowList[i] + "' style='background-color:#" + lastRowList[i] + ";' /></td>";
};
paletteHtml += "</tr></table>";
$("#" + paletteID).html(paletteHtml);
}; //BuildColorPalette
function BuildShadeColumn(colorList) {
var tempHtml = "<table style='margin:0px;padding:0px;width:13px;'><tr><td>";
for (i = 0; i < colorList.length; i++) {
tempHtml += "<input type='button' class='" + rtfEditorID + "_Swatch' title='#" + colorList[i] + "' style='background-color:#" + colorList[i] + ";' />";
}
tempHtml += "</td></tr></table>";
return tempHtml;
}; //BuildShadeColumn
$(function () {
if (opts.iFrameUrl.length != 0) { $("#" + rtfEditorID + "_Frame").attr("src", opts.iFrameUrl.toString()); };
document.getElementById(rtfEditorID + "_Frame").contentWindow.document.designMode = "on";
document.getElementById(rtfEditorID + "_Frame").contentWindow.document.close();
$("#" + rtfEditorID + "_DesignerMode").click(function() {
$("#" + rtfEditorID + "_SourceMode").css("font-weight", "normal");
$("#" + rtfEditorID + "_DesignerMode").css("font-weight", "bold");
$("#" + thisControlID).hide();
$("#" + rtfEditorID + "_Frame").show();
});
$("#" + rtfEditorID + "_SourceMode").click(function() {
$("#" + rtfEditorID + "_SourceMode").css("font-weight", "bold");
$("#" + rtfEditorID + "_DesignerMode").css("font-weight", "normal");
$("#" + thisControlID).show();
$("#" + rtfEditorID + "_Frame").hide();
});
$("#" + rtfEditorID + "_BackColor").click(function () {
swatchCommand = "backcolor";
$("#" + rtfEditorID + "_ColorPalette").toggle();
});
$("#" + rtfEditorID + "_ForeColor").click(function () {
swatchCommand = "forecolor";
$("#" + rtfEditorID + "_ColorPalette").toggle();
});
//http://msdn.microsoft.com/en-us/library/ms533049(VS.85).aspx for execCommand options
$("." + rtfEditorID + "_Swatch").click(function () {
var edit = document.getElementById(rtfEditorID + "_Frame").contentWindow;
edit.focus();
edit.document.execCommand(swatchCommand, false, $(this).attr("title").toString());
edit.focus();
$("#" + rtfEditorID + "_ColorPalette").toggle();
});
$("#" + rtfEditorID + "_Bold").click(function () {
var edit = document.getElementById(rtfEditorID + "_Frame").contentWindow;
edit.focus();
edit.document.execCommand("bold", false, "");
edit.focus();
});
$("#" + rtfEditorID + "_Italic").click(function () {
var edit = document.getElementById(rtfEditorID + "_Frame").contentWindow;
edit.focus();
edit.document.execCommand("italic", false, "");
edit.focus();
});
$("#" + rtfEditorID + "_Underline").click(function () {
var edit = document.getElementById(rtfEditorID + "_Frame").contentWindow;
edit.focus();
edit.document.execCommand("underline", false, "");
edit.focus();
});
$("#" + rtfEditorID + "_FontFamily").change(function () {
var edit = document.getElementById(rtfEditorID + "_Frame").contentWindow;
edit.focus();
edit.document.execCommand("fontname", false, $("#" + rtfEditorID + "_FontFamily").val());
edit.focus();
});
$("#" + rtfEditorID + "_FontSize").change(function () {
var edit = document.getElementById(rtfEditorID + "_Frame").contentWindow;
edit.focus();
edit.document.execCommand("fontsize", false, $("#" + rtfEditorID + "_FontSize").val());
edit.focus();
});
$("#" + rtfEditorID + "_Frame").blur(function () {
$("#" + thisControlID).val(frames[rtfEditorID + "_Frame"].document.body.innerHTML.toString());
}); //update textbox control when editor loses focus
//Give iFrame default content
var newIFrame = frames[rtfEditorID + "_Frame"].document;
newIFrame.open();
newIFrame.close();
});
$.fn.SiteRtfEditorVal = function (htmlValue) {
if (htmlValue == null | htmlValue == "undefined") {
//Get
try {
return frames[rtfEditorID + "_Frame"].document.body.innerHTML.toString();
} catch (err) {
return "";
}
} else {
//Set
$("#" + rtfEditorID + "_Frame").load(function () {
$("#" + thisControlID).val(htmlValue);
frames[rtfEditorID + "_Frame"].document.body.innerHTML = htmlValue;
});
//If already loaded, it seems to skip the callback function, so we 'try' to set it one more time.
try {
$("#" + thisControlID).val(htmlValue);
frames[rtfEditorID + "_Frame"].document.body.innerHTML = htmlValue;
} catch(err) {
}
}
} //rtfEditorHtml
}); //return this.each
} //$.fn.SiteRtfEditor
})(jQuery);

node.js / Youtube API / Upload

Using the following code I'm tring to upload a video youtube via direct upload. I already have the access token (auth_key). I'm pretty sure I'm sending the post data incorrectly...
function upload(auth_key, devKey, callback){
fs.readFile('test.mp4', function(err, movie){
var boundary = randomString();
var xml =
'<?xml version="1.0"?>' +
'<entry xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007">' +
'<media:group>' +
'<media:title type="plain">Bad Wedding Toast</media:title>' +
'<media:description type="plain">I gave a bad toast at my friends wedding.</media:description>' +
'<media:category scheme="http://gdata.youtube.com/schemas/2007/categories.cat">People</media:category>' +
'<media:keywords>toast, wedding</media:keywords>' +
'</media:group>' +
'</entry>'
;
var post_data =
'--' + boundary + '\n' +
'Content-Type: application/atom+xml; charset=UTF-8' + '\n' +
xml + '\n' +
'--' + boundary + '\n' +
'Content-Type: video/mp4' + '\n' +
'Content-Transfer-Encoding: binary' + '\n' +
movie + '\n' +
'--' + boundary + '--' + '\n'
;
var options = {
host: 'uploads.gdata.youtube.com',
port: 443,
path: '/feeds/api/users/default/uploads',
method: 'POST',
headers: {
'Authorization:': 'GoogleLogin auth=' + auth_key,
'GData-Version': '2',
'X-GData-Key': 'key=' + devKey,
'Slug': 'test.mp4',
'Content-Type': 'multipart/related; boundary="' + boundary + '"',
'Content-Length': post_data.length,
'Connection': 'close'
}
}
var req = https.request(options, function(res) {
var response = '';
res.on('data', function(chunk) {
response += chunk;
});
res.on('end', function(){
callback(response);
});
});
if(post_data){
req.write(post_data);
}
req.end();
req.on('error', function(e) {
console.error(e);
});
});
}
Is failing with "Invalid Request"?
You have some errors in your code, the syntax of the html request is missing "\r\n". You should also use the http library and port 80. Your Authorization header is invalid, it should not contain an ":" at the end. And I think the way your are adding the data and calculating the content length also messes things up.
I've successfully uploaded videos to youtube with the following code:
var file_reader = fs.createReadStream(file_path, {encoding: 'binary'});
var file_contents = '';
file_reader.on('data', function(data)
{
file_contents += data;
});
file_reader.on('end', function()
{
var xml =
'<?xml version="1.0"?>' +
'<entry xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007">' +
' <media:group>' +
' <media:title type="plain">' + title + '</media:title>' +
' <media:description type="plain">' + description + '</media:description>' +
' <media:category scheme="http://gdata.youtube.com/schemas/2007/categories.cat">' + category + '</media:category>' +
' <media:keywords>' + keywords + '</media:keywords>' +
' </media:group>' +
'</entry>';
var boundary = Math.random();
var post_data = [];
var part = '';
part = "--" + boundary + "\r\nContent-Type: application/atom+xml; charset=UTF-8\r\n\r\n" + xml + "\r\n";
post_data.push(new Buffer(part, "utf8"));
part = "--" + boundary + "\r\nContent-Type: video/mp4\r\nContent-Transfer-Encoding: binary\r\n\r\n";
post_data.push(new Buffer(part, 'ascii'));
post_data.push(new Buffer(file_contents, 'binary'));
post_data.push(new Buffer("\r\n--" + boundary + "--"), 'ascii');
var post_length = 0;
for(var i = 0; i < post_data.length; i++)
{
post_length += post_data[i].length;
}
var options = {
host: 'uploads.gdata.youtube.com',
port: 80,
path: '/feeds/api/users/default/uploads?alt=json',
method: 'POST',
headers: {
'Authorization': 'GoogleLogin auth=' + auth_key,
'GData-Version': '2',
'X-GData-Key': 'key=' + exports.developer_key,
'Slug': 'video.mp4',
'Content-Type': 'multipart/related; boundary="' + boundary + '"',
'Content-Length': post_length,
'Connection': 'close'
}
}
var req = http.request(options, function(res)
{
res.setEncoding('utf8');
var response = '';
res.on('data', function(chunk)
{
response += chunk;
});
res.on('end', function()
{
console.log(response);
response = JSON.parse(response);
callback(response);
});
});
for (var i = 0; i < post_data.length; i++)
{
req.write(post_data[i]);
}
req.on('error', function(e) {
console.error(e);
});
req.end();
});

Resources