I'm using backbone to manage my routing. I need to implement multi-language on my website as following :
in french : www.example.com
in english : www.example.com/en
Moreover I have an additional root on my url on production, so it gives www.example.com/dev or www.example.com/dev/en
The root is provided through my web server (node). It's retrieved through the <%- prefix %> variable in the example below.
It works well on localhost, but as soon as I pass on my server with a url with the additional root, the pages are not found. I'm looking for a generic solution to manage both situations (with or without root).
<!DOCTYPE html>
<html>
<head>
...
</head>
<body>
<script type="text/javascript">
window.onload = function()
{
let prefix = '<%- prefix %>'.substr(1);
var BaseRouter = Backbone.Router.extend({
routes: {
[prefix + 'imgfocus/:imgid'] : 'imgfocus',
[prefix + 'skymap/:obsids'] : 'skymap',
// ...
},
imgfocus : function(imgid)
{
navservice.loadScreen({page : 'imgfocus', imgid : imgid});
},
skymap : function(obsids, stateid, tourid)
{
navservice.loadScreen({page : 'skymap', obsids : parseInt(obsids) === 0 ? undefined : obsids, stateid : stateid, tourid : tourid});
},
/// ...
});
let br = new BaseRouter();
for (let i = 0; i < navservice.languages.length; i++)
{
if (navservice.languages[i] !== '')
{
for (let key in br.routes)
{
br.routes[navservice.formatUrl(key, navservice.languages[i]).substr(1)] = br.routes[key];
}
}
}
// language retrieval
var language = navservice.getUserLanguage();
Backbone.history.start({pushState : true, root: '/' + (language ? language : '')});
}
$(document).on("click", "a:not([data-bypass])", function (evt) {
var href = { prop: $(this).prop("href"), attr: $(this).attr("href") };
var root = location.protocol + "//" + location.host + Backbone.history.options.root;
if (href.prop && href.prop.slice(0, root.length) === root) {
evt.preventDefault();
var route = href.attr;
// language retrieval
var lang = navservice.getUserLanguage(route);
if(lang && route.slice(0,lang.length+1) === "/" + lang) {
route = route.slice(lang.length+1);
}
Backbone.history.navigate(route, {trigger : true});
}
});
}
</script>
Create differents templates, then use history root option:
Backbone.history.start({pushState: true, root: "/en/"})
More info backbone history start.
Actually I managed to fix it by adding log inside backbone.js and checking what was going on.
The real issue was in the usage of 'prefix' variable in the routes definition. I removed it and most of the fix was done.
Related
I have a file called index.html that is supposedly display a map by executing this line : Controller.startup(notauth);. I have made sure that the logic comes to this line.
Somehow the map wont appear and i find out in the Chrome debugger that there are some calls to a wrong JS scripts path.
Here I include some lines from my index.html :
<script type="text/javascript">
var dojoConfig = {
async: true,
packages: [{
name: 'viewer',
location: location.pathname.replace(/[^\/]+$/, '') + 'js/viewer'
},{
name: 'config',
location: location.pathname.replace(/[^\/]+$/, '') + 'js/config'
},{
name: 'gis',
location: location.pathname.replace(/[^\/]+$/, '') + 'js/gis'
}]
};
</script>
<script type="text/javascript" src="http://10.255.1.77/sonar/arcgis_js_api/library/3.15/3.15/init.js"></script>
<script type="text/javascript">
//Get app ID from url
var file = 'config/viewer', s = window.location.search, q = s.match(/config=([^&]*)/i);
//alert ('var file ORI (config/viewer) : ' + file);
//alert ('nilainya Q : ' + q);
if (q && q.length > 0) {
file = q[1];
//alert ('Q1 : ' + file);
//alert ('S : ' + s);
if(file.indexOf('/') < 0) {
configfile = 'config/' + file;
}
//alert ('CONFIG-FILE : ' + configfile);
}
if (configfile == 'config/all')
{
//alert ('config == ALL');
//alert ('configfile is ' + configfile + ' -- strpathfile : ' + strpathfile);
if (ImgStatus && checkfileimg_js(strpathfile)) {
require(['viewer/Controller', configfile + '_imagery'], function(Controller, config){
Controller.startup(config);
});
}
else
{
alert ('controller.startup(notauth) Hellow NOAUTH ');
require(['viewer/Controller', 'config/all'], function(Controller, notauth)
{
Controller.startup(notauth);
});
}
}
else //IF configfile <> ALL (env,pims,clear dll)
{
Controller.startup(auth);
}
When i debug it in Chrome, I have the following results :
- result 1 : https://snag.gy/g37joA.jpg
- result 1 : https://snag.gy/aBMren.jpg
The correct path should be "http://10.255.1.77/sonar/arcgis_js_api/library/3.15/3.15/dijit/TitlePane.js"
NOT http://10.255.1.77/sonar/arcgis_js_api/library/3.15/dijit/TitlePane.js
Where are those JS coming from ? I cant find them being called in my index.html. Where and how can i find lines that calls these JS scripts ?
Please help
You can find this information in Chrome DevTools, tab Network, column Initiator:
You have to configure correctly the HOSTNAME_AND_PATH_TO_JSAPI in your init.js and dojo.js (inside esri js api),
should look like in both init.js and :
http://10.255.1.77/sonar/arcgis_js_api/library/3.15/3.15/
Where are those JS coming from ?
The scripts are laoded asynchronously ( see Modern dojo AMD )
require(['viewer/Controller'], function(controller)) ...
this will search for viewer (depends on config dojo created on top)your_app_url/js/viewer/Controller.js and load it in script and register it ,
also every require inside your controller will load scripts asynchronously , this modern AMD will prevent import unused modules (modular loading) .
I have a website with a language selector. It works great, except that whenever I do change language, it always redirects back to the root page as opposed to staying on whichever current page the user is on.
How can I go about fixing this?
Here is my code:
function checkLanguage() {
let lang = localStorage.getItem('lang');
let urlLang = window.location.pathname.split('/')[1];
if(isNullOrWhitespace(urlLang)) {
if (!lang) {
lang = navigator.language.toLocaleLowerCase();
}
if (lang) {
let userLang = languageDictionary[lang];
changeLanguage(userLang);
}
}
else {
localStorage.setItem('lang', urlLang);
}
var windowWidth = $(window).width();
if (windowWidth < 500 && lang === 'th-th') {
$('.integrations-container').css('display', 'none');
};
};
function isNullOrWhitespace( input ) {
return !input || !input.trim();
}
checkLanguage();
// Changing language
function changeLanguage(lang) {
if (languageOptions.indexOf(lang) === -1) {
return;
}
localStorage.setItem('lang', lang);
window.location.href = '/' + lang;
}
languageOptions = ['en', 'zh-cn', 'zh-hk', 'jp-jp', 'ko-kr', 'th-th'];
languageDictionary = {
'en': 'en',
'en-gb': 'en',
'en-us': 'en',
'zh-cn': 'zh-cn',
'zh-hk': 'zh-ch',
'ko-kr': 'ko-kr',
'th-th': 'th-th',
'jp-jp': 'jp-jp',
}
Thank you kindle in advance! Also I am very new, so laymens terms is always appreciated :)
window.location.href = '/' + lang;
I think this line is always redirecting back to top page when language is changed.
It would be helpful if you can provide the example url of the page.
Try change it to below to redirect to current page when language is changed. I think it should work in top page too.
// Changing language
function changeLanguage(lang) {
if (languageOptions.indexOf(lang) === -1) {
return;
}
localStorage.setItem('lang', lang);
var urlData = window.location.pathname.split('/'); // /en/detail/test.html -> ["", "en", "detail", "test.html"]
urlData.splice(0, 2).join('/'); //cut out ["", "en"]
var newPath = urlData.join('/'); // detail/test.html
window.location.href = '/' + lang + '/'+ newPath; // /jp-jp/detail/test.html
}
On my razor view, I am wanting to put all of my jQuery into a separate JS file and then reference that file on the view with #Scripts.Render.
On my view, I have a section jQuery that looks like this:
var settings = {};
settings.baseUri = '#Request.ApplicationPath';
var submissionUrl = "";
if (settings.baseUri === "/ProjectNameOnServer") {
submissionUrl = settings.baseUri + "/api/apiControllerName/apiControllerMethodName/";
} else {
submissionUrl = settings.baseUri + "api/apiControllerName/apiControllerMethodName/";
}
This section of code allows me to test submitting forms with api on both my localhost and live on the server without me having to change the url.
If I am testing on my localhost, then #Request.ApplicationPath == /, but if I test on my server then #Request.ApplicationPath == /ProjectNameOnServer.
I was wondering how I could achieve getting these same values but without the use of Razor, and instead only with jQuery.
I have tried:
var settings = {};
settings.baseUri = window.location.protocol + "//" + window.location.host;
but then settings.baseUri == http://localhost:xxxxx. I just need exactly what #Request.ApplicationPath is giving me.
Use location.host to conditionally create relative path
settings.baseUri = location.host.includes('localhost') ? '/' : '/ProjectNameOnServer';
I need to fire piece of jQuery code only if it is home page.
URL probability are
http://www.example.com
http://www.example.com/
http://www.example.com/default.aspx
How can i run code if it is any of the above url i can use
var currenturl = window.location
but then i have to change this every time i move my code to server as on local host my url is like
http://localhost:90/virtualDir/default.aspx
in asp.net we can get the it using various
HttpContext.Current.Request.Url.AbsolutePath
or
HttpContext.Current.Request.ApplicationPath
I am not sure what are the equivalent in jQuery
reference of asp.net example
UPDATE:
I have taken a simple approach as i could not find other easy way of doing it
var _href = $(location).attr('href').toLowerCase()
var _option1 = 'http://localhost:51407/virtualDir/Default.aspx';
var _option2 = 'http://www.example.com/Default.aspx';
var _option3 = 'http://www.example.com/';
if (_href == _option1.toLowerCase() || _href == _option2.toLowerCase() || _href == _option3.toLowerCase()) {
$(".bar-height").css("min-height", "689px");
// alert('aa');
}
else
{ //alert('bb'); }
Could you only include the script on the page where it's needed? i.e. only use <script type="text/javascript" src="homepage.js"></script> from default.aspx ?
If not, then, as dfsq said - use window.location.pathname .
var page = window.location.pathname;
if(page == '/' || page == '/default.aspx'){
// -- do stuff
}
You could just get the part after the last slash, to account for folder differences...
var page = window.location.toString();
page = page.substring(page.lastIndexOf('/'));
... but this would be true for both example.com/default.aspx and example.com/folder1/default.aspx.
Remember, this Javascript is client-side, so there's no equivalent to the C# example you linked.
You could use my approch to know exactly the page (also with urlrouting) to use it in javascript:
I use the body id to identify the page.
javascript code:
$(document).ready(function () {
if (document.body.id.indexOf('defaultPage') == 0) {
/*do something*/
}
});
Asp.net code:
in masterpage or page (aspx):
...
<body id="<%=BodyId %>">
...
code behind:
private string _bodyId;
public string BodyId
{
get
{
if (string.IsNullOrWhiteSpace(_bodyId))
{
var path = GetRealPagePath().TrimStart('/','~');
int index = path.LastIndexOf('.');
if (index > -1)
{
path = path.Substring(0, index);
}
_bodyId = path.Replace("/", "_").ToLower();
}
return string.Concat(_bodyId,"Page");
}
}
public string GetRealPagePath()
{
string rtn = Request.Path;
if (Page.RouteData != null && Page.RouteData.RouteHandler!= null)
{
try
{
if (Page.RouteData.RouteHandler.GetType() == typeof(PageRouteHandler))
{
rtn=((PageRouteHandler)Page.RouteData.RouteHandler).VirtualPath;
}
else
{
rtn = Page.Request.AppRelativeCurrentExecutionFilePath;
}
}
catch (Exception ex)
{
Logger.Error(string.Format("GetRealPagePath() Request.Path:{0} Page.Request.AppRelativeCurrentExecutionFilePath:{1}", Request.Path, rtn), ex);
}
}
return rtn;
}
I am using that code :
$.get(
'filename.html',
function(content)
{
$('#container').empty().append(content);
}
);
to load some external files and place the content into the current working page. The external files that I load are in plain HTML and I like to ask, if there is any good way to internationalize that loaded pages.
In my current page I have the opportunity to create a javascript object with all translation keys like:
var i18n = {
'doc1' : {
'title' : 'This is a title'
}
};
In example the external files looks like that
<h3>This is a title</h3>
.....
Is there a way to change that to something similar to
<h3>{doc1.title}</h3>
.....
and then after the load to replace the doc1.title;
May be like this:
var i18n = {
'doc1' : {
'title' : 'This is a title'
}
};
$.get(
'filename.html',
function(content)
{
for (var doc in i18n) {
for (var key in i18n[doc]) {
var val = i18n[doc][key];
content = content.replace( '{' + doc + '.' + key + '}', val );
}
}
$('#container').empty().append(content);
}
);
fiddle: http://jsfiddle.net/Kirrr/eW7Nn/
May be something like this you're looking for:
1. Updated
JavaScript:
var i18n = { doc1: { title: 'Title', ... }, ... };
var doc_name = 'doc1';
$.get(doc_name + '.html', function(data) {
for (var word in i18n[doc_name]) {
data = data.replace(new RegExp('/' + word + '/', 'g'), i18n[doc_name][word]);
}
$('#container').html(data);
});
HTML:
<h3>{title}</h3>
2.
JavaScript:
var doc1 = { title: 'Title', ... };
$.get("doc1.php", doc1, function(data) {
$('#container').html(data);
});
PHP:
<h3><?= $_GET['title'] ?></h3>
If your retrieved document contains
<h3 id="localTitle"></h3>
You could do
$.get(
'filename.html',
function(content)
{
$('#container').empty().append(content);
$('#container #localTitle').html('This is a title');
}
);