I'm trying to incorporate this scanning software into an application.
The folder which contains all the necessary .js, .css and binary files is called Resources.
In my MVC app - I have placed the Resources file inside my Scripts folder.
In my .cshtml, I have the following:
#section scripts {
<script src="~/Scripts/Resources/dynamsoft.webtwain.config.js"></script>
<script src="~/Scripts/Resources/dynamsoft.webtwain.initiate.js"></script>
}
Which loads the scripts successfully.
The issue I'm facing is the scripts themselves reference relative paths within the Resources folder.
In dynamsoft.webtwain.config.js - you can set the path to the resources folder - I have mine set to the following:
Dynamsoft.WebTwainEnv.ResourcesPath = '~/Scripts/Resources';
However when the page loads - I'm receiving 404 errors for some of the files because it's trying to literally interpret the path:
I have also tried the following but with no luck:
Dynamsoft.WebTwainEnv.ResourcesPath = '#Url.Content("~/Scripts/Resources")';
As far as I know you can't use relative paths starting with tilde (~) in separate JS files because #Url.Content() helper and ASP.NET relative paths only work inside Razor view page, but you can pass the relative path by creating root path in JS global scope (i.e. Razor view page's <script> tag) like this:
<script>
var baseUrl = '#Url.Content("~")';
</script>
Then you can include the path inside JS files using that variable:
// custom JS file
if (typeof baseUrl !== 'undefined') {
Dynamsoft.WebTwainEnv.ResourcesPath = baseUrl + '/Scripts/Resources';
}
Or simply mentioning full path & pass it:
#* Razor page *#
<script>
var resourcesPath = '#Url.Content("~/Scripts/Resources")';
</script>
// custom JS file
if (typeof resourcesPath !== 'undefined') {
Dynamsoft.WebTwainEnv.ResourcesPath = resourcesPath;
}
Another alternative is using custom JS view engine together with file handler for JS scripts like example below:
// custom JS engine
public class CustomJSEngine : BuildManagerViewEngine
{
public CustomJSEngine()
{
ViewLocationFormats = new[]
{
"~/Scripts/{0}.js",
"~/Scripts/Resources/{0}.js"
};
FileExtensions = new[]
{
"js"
};
}
protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
{
var view = new RazorView(controllerContext, viewPath,
layoutPath: masterPath, runViewStartPages: true, viewStartFileExtensions: FileExtensions,
viewPageActivator: ViewPageActivator);
return view;
}
}
// put these lines below inside Application_Start()
RazorCodeLanguage.Languages.Add("js", new CSharpRazorCodeLanguage());
ViewEngines.Engines.Add(new CustomJSEngine());
// add this line if necessary
WebPageHttpHandler.RegisterExtension(".js");
References:
#Url.Content in separate javascript file using ASPNET MVC 3 and Razor
Returning razor-parsed Javascript as a ViewResult from a controller
Related
I would like to add some javascript libraries to my reactJS project.
I do this by adding script tags to the section of index.html
<script src="../src/components/reports/scripts/stimulsoft.reports.js"></script>
<script src="../src/components/reports/scripts/stimulsoft.viewer.js"></script>
and usage of library is like:
class Viewer extends React.Component {
render() {
return <div id="viewerContent"></div>;
}
componentWillMount() {
var report = Stimulsoft.Report.StiReport.createNewReport();
report.loadFile("reports/Report.mrt");
var options = new Stimulsoft.Viewer.StiViewerOptions();
this.viewer = new Stimulsoft.Viewer.StiViewer(options, "StiViewer", false);
this.viewer.report = report;
}
componentDidMount() {
this.viewer.renderHtml("viewerContent");
}
}
but I have this error:
these are original sample Stimulsoft Reports.JS and GitHub
Based on comments under the question, and the guides presented in index.html file of react project as follows:
//Notice the use of %PUBLIC_URL% in the tags above.
//It will be replaced with the URL of the `public` folder during the build.
//Only files inside the `public` folder can be referenced from the HTML.
I placed scripts folder into the public folder of react project and edit src attribute to new source address, and my problem was solved
and this code work for me:
<script src="%PUBLIC_URL%/StimulSoft/scripts/stimulsoft.reports.js"></script>
<script src="%PUBLIC_URL%/StimulSoft/scripts/stimulsoft.viewer.js"></script>
I have an AspNet app using typescript with onsen ui.
When i called component from onsen, i used these ref
// <reference path="TypeScriptHelper/Onsen/OnsPageController.ts"/>
But i want to use a javascript lib called devexpress that has no .d.ts defintion
How can i called these controls from my typescript file ?
The script are inserted in the index.html
But when i call them in my typescript file like this :
DevExpress.Dashboard.ResourceManager.embedBundledResources();
// Creates a new Web Dashboard control with the specified ID and settings:
var dashboardControl = new DevExpress.Dashboard.DashboardControl(document.getElementById("container"), {
// Configures an URL where the Web Dashboard's server-side is hosted:
endpoint: "https://demos.devexpress.com/services/dashboard/api",
workingMode: "Viewer",
extensions: {
"dashboard-panel": (control) => new DevExpress.Dashboard.DashboardPanelExtension(control)
}
});
They are not recognized
Any idea why and how to fixe it ?
Thx in advance,
I understand that Pug does not support dynamic includes or extends in templates. Ie
extend path/to/template
works but not
extend #{dynamic_path_to_template}
Is there a workaround (however convoluted) that will allow the same goal of modifying the template used by a view at runtime
Context: My use case is that I am developing an npm module and the template being used to extend other views is located inside the module. After the module is published and installed, the path will be defined (ie. node_modules/my_module/path/to/template) but during the development phase, I need to just be able to "npm link" to the module and have the templates work. I also would prefer not to hard code the links so I can publish the same code as tested.
I had this issue aswell and found this question while searching for a solution. My solution is similar to Nikolay Schambergs Answer, but i thought i should share it.
I've created a function that renders templates by giving it a path and passed it to the options object. Maybe it helps in your case aswell
const includeFunc = (pathToPug, options = {}) => {
return pug.renderFile(pathToPug, options); //render the pug file
}
const html = pug.renderFile('template.pug', {include: includeFunc});
and then use it as followed in your template:
body
h1 Hello World
|!{include(dynamicPugFilePathFromVariable)}
There is no way to do this for now, but you can work out your application architecture without dynamic extends.
Possible solution #1
Make a layout.jade that conditionally include multiple layouts:
layout.jade:
if conditionalVariable
include firstLayout.jade
else
include otherLayout
In your view, extend layout.jade, and define conditionalVariable in the controller (true/false):
view.jade:
extends layout
block content
p here goes my content!
Possible solution #2
Pass configurations to the layout
- var lang = req.getLocale();
doctype html
block modifyLayout
split the project into multiple entrances, each entrance extends the layout and passes its different configs, and includes different things in different blocks
extends ../layout
block modifyLayout
- var lang = "en" //force language to be en in this page.
block body
include my-page-body
Possible solution #3
use something like terraform which uses pug as its rendering engine, but it enables you to use dynamic partials like this
!= partial(dynamicFileFromVariable)
It works!
First, set res.locals middleware.
middlewares/setResLocals.js
const pug = require('pug')
const path = require('path')
module.exports = function(req, res, next) {
res.locals.include = (pathToPug, options = {}) => { // used for imitate includ pug function
return pug.renderFile(pathToPug, options); //render the pug file
}
res.locals.__PATH__ = path.join(__dirname, '../')
next()
}
server/index.js
app.use(require('../middlewares/setResLocals'))
file.pug
|!{include(`${__PATH__}/${something}`)}
In order to do dynamic include, you will have to use Unescaped String Interpolation, inserting pug contents that are pre-compiled before your main .pug file inside your route. In other words it works as follows:
1) Some .pug files are pre-compiled into HTML
2) The HTML gets fed into another .pug file compilation process
Here's an example how to do it
Inside your router file (routes.js or whatever)
var pug = require('pug')
var html = []
var files = ['file1','file2'] // file names in your views folders
let dir = path.resolve(path.dirname(require.main.filename) + `/app/server/views/`)
//dir is the folder with your templates
app.get('/some-route', (req,res) => {
for (let n = 0; n < files.length; n++) {
let file = path.resolve(dir + '/' + files[n] + `.pug`)
fs.access(file, fs.constants.F_OK, (err) => {
if (!err) {
html.push(pug.renderFile(file, data))
if (n === files.length - 1) {
res.render('dashboard', {html})
}
}
else {
res.status(500).json({code:500,status:"error", error:"system-error"})
}
})
}
})
Inside your desired .pug file:
for item in html
.
!{item}
The example above is specific to my own use case, but it should be easy enough to adapt it.
I know, this is a bit late for answering. But I found a possibility suitable for my purpose by this bit of information from the pug docs:
If the path is absolute (e.g., include /root.pug), it is resolved by
prepending options.basedir. Otherwise, paths are resolved relative to
the current file being compiled.
So, I provide most of my pug modules by relative paths and the stuff I want to exchange dynamically is organised in pug files of the same name but in different folders (think theme) and include them by absolute paths . Then I change the basedir option to dynamically choose a set of pug files (like choosing the theme).
May this help others, too.
I've got a problem, I am using Head.js plugin to import several js files in my template. Each file has a normal path e.g. assets/js/clock/date.js
The problem is that neither I can use the path directly in importing nor using the twig asset() function to get path to these files. As an example this is what I have in a separate js file
head.js("../assets/js/newsticker/jquery.newsTicker.js", function() { ... });
How can I get access to the files in folder assets inside a javascript file?
What you need is a global javascript defined variable in your twig which contains the path of whatever you want to load; for example
var generalPath = "{{ asset('path/to/your/asset') }}";
now you can call the function as header.js by concatenating with the defined global variable as
head.js(generalPath + 'jquery.cookie.js');
Recently I am building a project heavily relies on javascript/jquery. When some of the partial views are rendered, they need to apply some javascripts or CSS styles. Do you have any ideas on an efficient/effective way to manage those files?
I found a need to do this in my own project, because I wanted to be able to have a separate javascript\css file for each view.
What I ended up doing was creating a controller to aggregate the files on the server for me and then send only one css\js file to the browser. The answer is perhaps more intricate than you requested though, so I'll recommend the first part.
You can make an extension method that you can call at the top of each page to add a JS file to a list in the TempData dictionary for the request. You then call a separate method from the Layout that will render any additional links.
This works because the TempData is kept just for the request, and the layout's View is rendered last (after all the views and partials run).
I have a full example of a class here: http://pastebin.com/EUC2fAca but i'm also forming links to my aggregator, so you'll need to modify. The gist is as follows:
public static string JSKey = "pageJSList";
private static void AddToDictionary(HtmlHelper helper, string[] files, string key)
{
if (files == null || files.Length == 0)
return;
TempDataDictionary dict = helper.ViewContext.TempData;
if (!dict.ContainsKey(key))
dict.Add(key, new List<string>());
(dict[key] as List<string>).AddRange(files);
}
private static void InsertToDictionary(HtmlHelper helper, string[] files, string key)
{
if (files == null || files.Length == 0)
return;
TempDataDictionary dict = helper.ViewContext.TempData;
if (!dict.ContainsKey(key))
dict.Add(key, new List<string>());
(dict[key] as List<string>).InsertRange(0, files);
}
public static void AddJS(this HtmlHelper helper, params string[] files)
{
AddToDictionary(helper, files, JSKey);
}
public static void AddJSToTop(this HtmlHelper helper, params string[] files)
{
InsertToDictionary(helper, files, JSKey);
}
public static MvcHtmlString GetJsTagHtml(HtmlHelper helper)
{
var files = helper.ViewContext.TempData[JSKey] as List<string>;
StringBuilder tags = new StringBuilder();
string jsTemplate = "<script type=\"text/javascript\" src=\"/Scripts/{0}\"></script>";
foreach (string file in files)
{
tags.AppendLine(String.Format(jsTemplate, file));
}
return MvcHtmlString.Create(tags.ToString());
}
You'll want the Insert method to run it on the layout because, again, it runs last so you'll want to Insert jquery libraries or other dependencies that should be first on the list.
Your GetJS method should probably return an MvcHtmlString that contains all of the tags you need.
Hope that helps and wasn't too long winded =)
Management of CSS files and JavaScript files and almost any other file depends on your categorization favorites, or in other terms, your taxonomy. I think the better question is, what guidelines should I follow, to make my project become more successful. For example, however you manage and categorize your JavaScript files, try to not have many of'em in a page, as each of'em make a separate HTTP request to the server. Or, try to be as consistent in naming as possible, so that, in future you won't get puzzled by your code. For CSS and JavaScript, I suggest LDSW.
Use webpack to manage your files. A simple webpack setup could look like
# /webpack.config.js
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const postcssPresetEnv = require("postcss-preset-env");
module.exports = (env, argv) => {
const devMode = argv.mode !== "production";
return {
mode: argv.mode,
entry: {
// Main / Shared
'main': './Content/styles/main.scss',
'theme': './Content/styles/theme.scss',
// Pages
'page-home': './Content/styles/pages/home/home.scss',
'page-register': './Content/styles/pages/register/register.scss',
// If we import _register-forms.scss at the top of register.scss,
// there is no need to include it here. That has nothing to do with webpack.
// Components / Partials
'component-search': './Content/styles/components/search/search.scss',
// Javscripts
'client': './Content/client/client.js',
'home': './Content/client/pages/home/index.js',
'component-search': './Content/client/components/search/search.js',
// Got more partial files? Just import { Helper } from './_search-helpers.js' inside
// search.js, and the code will be included.
},
resolve: {
alias: {
// Setup optional aliases
pages: path.resolve(__dirname, 'Content/styles/pages'),
components: path.resolve(__dirname, 'Content/styles/components'),
}
},
output: {
path: path.resolve(__dirname, "Content/dist"),
publicPath: "/css",
filename: devMode ? "js/[name].js" : "js/[name].min.js"
},
... more webpack stuff here.
Then, you don't need to reference all of your scss files in webpack. For example, now you can just import smaller files with this:
# /Content/styles/pages/register/register.scss
#import './_register-form';
#import './_register-layout';
You don't have to include them in your webpack.config.js, because they are pulled into register.scss with the scss #import.
And likewise, in your javascript files you can just import what you need.
# /Content/client/components/search/search.js
import { SearchHelpers } from '_search-helpers';
search.js will now contain everything from _search-helpers.js.
To me, this seems like a logical structure for front-end code in an MVC project.