I have written this factory which will be called in case of any errors
app.factory('customTranslationHandler', function ($translate) {
return function (caption, uses) {
if(uses=='en') {
var i = 0, strLength = caption.length;
for(i; i < strLength; i++) {
caption = caption.replace("_", " ");
}
var defaultText = caption.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
} else {
//var defaultText = $translate(caption).use('en');
//var defaultText = $translate.instant(caption).use('en');
}
return defaultText;
};});
If it is en, I format the caption and return it.
In case of any other language, I want to call translate for that caption using en as language. I get my translations from json files.
All I had to do was set fallBackLanguage:
$translateProvider.fallbackLanguage('en');
Related
I'm trying to insert url for menu through mustache template. But just the first value is being returned for the array.
Or is this the return method wrong
var main_menu_link = ["main_dashboard.html", "#", "online_dashboard.html","index.html","#","#","#"];
var url = "";
var i;
var url_link="";
for(i = 0; i < main_menu_link.length; i++) {
url += main_menu_link[i];
return '' + text + '';
}
CodePen working here
The return statement has to be after the loop:
var main_menu_link = ["main_dashboard.html", "#", "online_dashboard.html","index.html","#","#","#"];
var url = "";
var i;
var url_link="";
for(i = 0; i < main_menu_link.length; i++) {
url += '' + text + '';
}
return url;
Correct template as below in-case it can be of use to someone else
var link_details = { "link_details" :[
{ main_menu: "Dashboard", main_menu_link: "dashboard.html" },
{ main_menu: "Analytics", main_menu_link: "#" },
{ main_menu: "System", main_menu_link: "system.html" }
]};
var template = "<ul>{{#link_details}}<li>{{main_menu}}</li>{{/link_details}}</ul>";
var html = Mustache.to_html(template, link_details);
document.write(html)
I am trying to get innerHTML of a contenteditable div via function defined in controller of angularjs but it returns undefined every time.. what are the alternatives or how can I handle this issue?
$scope.genrate_HTML=function()
{
var read_string=document.getElementsByClassName("MainPage");
//console.log(read_string);
var p_tag= '\n<p id="test"> \n'+read_string.innerHTML+'\n </p>';
//document.getElementById("createdHTML").value = p_tag ;
//$compile( document.getElementById('createdHTML') )($scope);
}
the contenteditble div's classs name is "MainPage"
VisualEditor.controller("GenrateHTML",function($scope){
$scope.savefile=function()
{
$scope.genratedHTML_text=document.getElementById("createdHTML").value;
var text_file_blob= new Blob([$scope.genratedHTML_text],{type:'text/html'});
$scope.file_name_to_save=document.getElementById("file_name").value ;
var downloadLink=document.createElement("a");
downloadLink.download=$scope.file_name_to_save;
downloadLink.innerHTML="Download File";
if(window.URL!=null)
{
downloadLink.href=window.URL.createObjectURL(text_file_blob);
}
else
{
downloadLink.href = window.URL.createObjectURL(text_file_blob);
downloadLink.onclick = destroyClickedElement;
downloadLink.style.display = "none";
document.body.appendChild(downloadLink);
}
downloadLink.click();
}
function destroyClickedElement(event)
{
document.body.removeChild(event.target);
}
$scope.toggleModal = function(){
$scope.showModal = !$scope.showModal;
};
///add details
$scope.details=[];
$scope.addDetails=function(){
$scope.details.push({
Title:$scope.Details_Title,
meta_chars:$scope.Details_metaChars,
version:$scope.Details_version,
Auth_name:$scope.Details_AuthName,
copyRights:$scope.Details_copyRights
});
document.getElementById("createdHTML").innerHTML = $scope.details;
};
$scope.$watch('details', function (value) {
console.log(value);
}, true);
/////////////////////
$scope.genrate_HTML=function()
{
var read_string=document.getElementsByClassName("MainPage");
//console.log(read_string);
var p_tag = '';
for (var i = 0; i < read_string.length; i++) {
p_tag += '\n<p id="test_"' + i + '> \n' + read_string[i].innerHTML + '\n </p>';
document.getElementById("createdHTML").value = p_tag;
}
//$compile( document.getElementById('createdHTML') )($scope);
}
});
getElementsByClassName returns an Array, so, your read_string variable is an Array type. you should iterate through the elements of read_string with for loop.
NOTE: Please check the p element's id here aswell. Because id must be unique!
$scope.genrate_HTML = function() {
var read_string = document.getElementsByClassName("MainPage");
var p_tag = '';
for (var i = 0; i < read_string.length; i++) {
p_tag += '\n<p id="test_"'+i+'> \n'+read_string[i].innerHTML+'\n </p>';
}
/* Other code here... */
}
UPDATE: Don't use the code below! If read_string returns with no elements than your code will crash!
But if it's a 1 element Array then you can take the value like:
$scope.genrate_HTML = function() {
var read_string = document.getElementsByClassName("MainPage");
var p_tag= '\n<p id="test"> \n'+read_string[0].innerHTML+'\n </p>';
/* Other code here... */
}
I hope that helps. If it doesn't then paste the full code of the Controller.
Im in the process of converting a knockout app to angular, I currently get an array of objects from the server but I would like to extend each object by adding some extra properties.
In knockout I would do the following:
var mappedResults = ko.utils.arrayMap(results, function(item) {
item.selected = ko.observable(true);
item.viewPreview = ko.observable(false);
return new reed.search.Candidate(item, self.viewModel.fileDownloadFailCookieName);
});
and the Candidate viewmodel:
reed.search.Candidate = function(data, fileDownloadFailCookieName) {
debugger
if (data == null) {
throw 'Error: cannot initiate candidate';
}
this.fileDownloadFailCookieName = fileDownloadFailCookieName;
this.candidateId = data.CandidateId;
this.name = data.Name;
this.surname = data.Surname;
this.forename = data.Forename;
this.displayLocation = data.DisplayLocation;
this.lastJobDetails = data.LastJobDetails;
this.displayPayRate = data.DisplayPayRate;
this.lastSignIn = data.LastSignIn;
this.downloadCVUrl = data.DownloadCVUrl;
this.additionalInfo = data.AdditionalInfo;
this.isAvailable = (data.IsAvailable) ? "Availability confirmed" : "";
this.availableMornings = data.AvailableMornings;
this.availableAfternoons = data.AvailableAfternoons;
this.availableEvenings = data.AvailableEvenings;
this.availableWeekends = data.AvailableWeekends;
this.availableShiftWork = data.AvailableShiftWork;
this.availableNights = data.AvailableNights;
this.availabilityUpdatedOn = data.AvailabilityUpdatedOn;
this.availabilityUpdatedOnDate = "| <strong>Availability updated</strong> " + data.AvailabilityUpdatedOn;
this.isAvailableForSomething =
this.availableMornings
|| this.availableAfternoons
|| this.availableEvenings
|| this.availableWeekends
|| this.availableShiftWork
|| this.availableNights;
this.viewPreview = ko.observable(false);
this.selected = ko.observable(false);
this.hasBeenNotified = ko.observable(false);
this.select = function() {
this.selected(true);
};
this.deSelect = function() {
this.selected(false);
};
this.HasFlagSet = function(availability) {
return availability ? "availabilitySelected" : "availabilityNotSelected";
};
this.ajaxCvDownload = function() {
var path = window.location.href,
iframeError,
cookieName = this.fileDownloadFailCookieName;
// download path
path = path.match(/(.+\/)/ig)[0];
if (path.match(/home/ig)) {
path = path.replace('home', this.downloadCVUrl);
} else {
path = this.downloadCVUrl;
};
$('<iframe />').attr('src', path)
.hide()
.appendTo('body').load(function() {
var message = decodeURIComponent(reed.shared.utils.getCookie(cookieName));
message = message.replace(/\+/g, " ");
if (message.length > 0 && message != "null") {
reed.shared.utils.showMessage(message, "Download Failed");
}
});
}
}
how can I achieve the same functionality in angular?
You don't need angular for this array itself contains a map function and all modern browsers support it.
var mappedResults = results.map(function(item) {
item.selected = true;
item.viewPreview = false;
return new reed.search.Candidate(item,
self.viewModel.fileDownloadFailCookieName);
});
Some other things you can improve. Firstly if you are using webapi to return data, use a formatter that fixes casing.Check this blog http://blogs.msmvps.com/theproblemsolver/2014/03/26/webapi-pascalcase-and-camelcase/
Once you have the formatter lines such as these are not required
this.surname = data.Surname;
You can then use angular.extend to copy properties into your class.
I'm trying to construct a translated message by looping over an array of objects and then adding a new "message" property to that object containing the translated string. I see the correct message output while inside $translate.then(); but when I assign the message to the object it is undefined. What is the correct way to resolve the promise returned from $translate.then() and assign it to the "message" property?
//items.controller.js
function getItems() {
return itemsFactory.getItems()
.then(function (response) {
vm.items = initItemsList(response.activities);
});
}
function initItemsList(itemsList) {
for (var i = 0; i < itemsList.length; i++){
var activityType = itemsList[i].activityType;
switch (activityType){
case "HISTORY": {
var itemName = itemsList[i].item.itemName;
var itemVersion = itemsList[i].item.itemVersion;
$translate('activity.'+activityType, { itemname: itemName, itemversion: itemVersion }).then(function(content){
vm.itemContent = content;
console.log(vm.itemContent); // correct message displayed.
});
break;
}
default: {
break;
}
}
itemsList[i].message = vm.itemContent; // undefined
}
return itemsList;
}
// translation.json
"activity : {
"HISTORY" : "History for {{ itemname }} {{ itemversion }}."
}
Promises are always resolved asynchronously. So the statement
itemsList[i].message = vm.itemContent;
, which is executed right after the switch, is executed before the callback passed to the $translate promise. Just move the statement to the callback:
$translate('activity.'+activityType, { itemname: itemName, itemversion: itemVersion }).then(function(content){
vm.itemContent = content;
console.log(vm.itemContent);
itemsList[i].message = vm.itemContent;
});
As #Vegar correctly states, the code inside then is executed after the assignment so moving the assignment inside then function will take care of the problem. However, your itemsList will be returned from the function before all the translations are done so you will need to return a promise that resolves when all translations are done:
function initItemsList(itemsList) {
var allTranslations = [];
for (var i = 0; i < itemsList.length; i++){
var activityType = itemsList[i].activityType;
switch (activityType){
case "HISTORY": {
var itemName = itemsList[i].item.itemName;
var itemVersion = itemsList[i].item.itemVersion;
allTranslations.push($translate('activity.'+activityType, { itemname: itemName, itemversion: itemVersion }).then(function(content){
vm.itemContent = content;
itemsList[i].message = vm.itemContent;
}));
break;
}
default: {
break;
}
}
}
return $q.all(allTranslations);
}
The caller of your function will have to do like:
initItemList(itemList).then(function(translatedList){
//Do stuff with translated list
});
Below is code that populates a menu. Everything seems to work great, with no errors thrown, except for one crucial part. My megaPages array has the values ["HOME","BABIES","BRIDALS","MISC","WEDDINGS","ABOUT"], but the actual text that displays on screen (which is produced by megaPages) is like this:
As you can see, some of the text is arbitrarily being truncated. I've traced the text strings as they get passed through the various functions at various stages of the menu-build, and they are always right, but somehow when each DisplayObject make it on screen, letters get ommitted (notice though that 'HOME' abd 'ABOUT' are fine). I don't even know where to start with this problem.
function buildMenu() {
var itemMCs = new Array();
for (var i = 0; i < megaPages.length; i++) {
megaPages[i] = megaPages[i].toUpperCase();
trace(megaPages[i]); // at each iteration, traces as follows "HOME","BABIES","BRIDALS","MISC","WEDDINGS","ABOUT"
var textMC = createText(megaPages[i]);
var itemMC = new MovieClip();
if (i!=0) {
var newLink = new PlateLink();
newLink.y = 0;
itemMC.addChild(newLink);
}
var newPlate = new Plate();
if (i==0) {
newPlate.y = 0;
} else {
newPlate.y = newLink.height - 2;
}
newPlate.x = 0;
newPlate.width = textMC.width + (plateMargin*2);
itemMC.addChild(newPlate);
if (i!=0) {
newLink.x = (newPlate.width/2) - (newLink.width/2);
}
textMC.x = plateMargin;
textMC.y = newPlate.y + .5;
itemMC.addChild(textMC);
itemMCs.push(itemMC);
itemMC.x = (homeplateref.x + (homeplateref.width/2)) - (itemMC.width/2);
if (i==0) {
itemMC.y = homeplateref.y;
} else {
itemMC.y = itemMCs[i-1].y + (itemMCs[i-1].height - 6);
}
menuRef.addChild(itemMC);
}
}
function createText(menuTitle) {
trace(menuTitle);
var textContainer : MovieClip = new MovieClip();
var myFont = new Font1();
var backText = instantText(menuTitle, 0x000000);
backText.x = 1;
backText.y = 1;
var frontText = instantText(menuTitle, 0xFFFFFF);
frontText.x = 0;
frontText.y = 0;
textContainer.addChild(backText);
textContainer.addChild(frontText);
return textContainer;
}
function instantText(textContent, color) {
trace(textContent); // again, traces the right text each time it is fired
var myFont = new Font1();
var myFormat:TextFormat = new TextFormat();
myFormat.size = 18;
myFormat.align = TextFormatAlign.CENTER;
myFormat.font = myFont.fontName;
var myText:TextField = new TextField();
myText.defaultTextFormat = myFormat;
myText.embedFonts = true;
myText.antiAliasType = AntiAliasType.ADVANCED;
myText.text = textContent;
myText.textColor = color;
myText.autoSize = TextFieldAutoSize.LEFT;
trace(myText.text);
return myText;
}
You need to embed all the necessary characters for the font you're using.
For textfields created in Flash:
Select the TextField, and hit the 'Embed' button in the properties panel.
For dynamically created textfields:
When you set the font to export (Font1 in your case) make sure to include all the characters you need.
You can choose to embed all uppercase characters, or just type in the ones you need for those specific menu items.