I'm new to .net MVC and Razor engine but I have been using PHP for a long time. I'm trying to do this PHP code in Razor:
var data = [
<?php for ($i = 0; $i < 50; ++$i) {
echo '[' . $i . ',' . sin($i) . ']';
if ($i != 49)
echo ',';
?>
],
I managed to do it using this, but it looks bad and complex for something so simple
var data = [
#for(int i = 0; i < 50; ++i) {
<text>[</text>#i<text>,</text>#Math.Sin(i)<text>]</text>if (i != 49) {<text>,</text>}
}
];
The problem is that [, ] and , are confused with Razor syntax and gives syntax errors, so I had to wrap them on <text> tags.
Is there a simpler/nicer way to do this? Maybe something like the PHP echo.
Thanks.
A gerenal equivalent of echo in MVC cshtml might be:
#Html.Raw("SomeStringDirectlyInsideTheBrowserPageHTMLCode")
This renders the (dynamic) string at its position where '<' and '>' no need to be HTML-coded. For example #Html.Raw(String.Format("<div class=\"{0}\" style=\"{1}\">", myclass, mystyle)) works fine.
Note that the HTML tags rendered by #Html.Raw(MyString) cannot be checked by the compiler. I mean: #Html.Raw("<div ....>") cannot be closed by mere </div> because you will get an error (<div ....> is not detected by the compiler) so you must close the tag with #Html.Raw("</div>")
P.S.In some cases this doesn't work (for example it fails within DevExpress) - use ViewContext.Writer.Write() or ViewContext.Writer.WriteLine() instead.
Use this:
#String.Format("[{0},{1}]", i, Math.Sin(i))
And for comma you can use String.Join() if you create array (String.Join Method )
Old question I know, but an alternative is to use the plaintext syntax #:
var data = [
#for (int i = 0; i < 50; ++i)
{
#:[#i,#Math.Sin(i)]
#(i != 49 ? "," : "")
}
];
Constructing a JSON object using a view is not really the best way to go about it. You can use the native JSON support to do this directly from a controller, for example:
public JsonResult SinArray()
{
return new JsonResult() {
Data = Enumerable.Range(0, 50).Select(i => new[] { i, Math.Sin(i) }),
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
This returns
[[0,0],[1,0.8414709848078965],[2,0.90929742682568171],.....,[49,-0.95375265275947185]]
As a bonus you get the correct content-type.
Related
I spent so much time on a very simple thing and had to post here on StackOverflow
I want to get all inner text except the script/style tags
$doc = new DOMDocument;
$doc->preserveWhiteSpace = false;
$html = <<<EOD
<div>
<script>var main=0</script>
<div>
<p>my</p>
<script>var inner=0</script>
</div>
<p>text</p>
only
</div>
EOD;
$doc->loadHTML($html);
$xpath = new DOMXPath($doc);
echo $entries = $xpath->query('//*[not(self::script)]')->item(0)->nodeValue;
gives me
var main=0 my var inner=0 text only
and also tried
$entries = $xpath->query('//*[not(self::script)]');
foreach ($entries as $entry) {
if ($entry->tagName == 'style' || $entry->tagName == 'script') {
continue;
}
echo preg_replace('/\s\s+/', ' ', $entry->nodeValue);
}
gives me
var main=0 my var inner=0 text only var main=0 my var inner=0 text only var main=0 my var inner=0 text only my var inner=0mytext
I tried several xpaths but it doesn't work
my desired output is my text only
I am a Scrapy developer and I do that easily in Scrapy, but having a bad time with PHP today
Unfortunately, PHP doesn't support xpath 2.0 (and, IIRC, neither does Scrapy), so the name() method which would have made it easy, isn't available...
The closest thing I can think of is the following, which should get you close enough (note that, because there is no <style> tag in your $html, I only focused on <script>):
$entries = $xpath->query('//*[not(./text()/parent::script)]/text()');
foreach ($entries as $entry) {
echo trim($entry->textContent) . " ";
}
Output:
my text only
I am using katex to render math.
https://github.com/Khan/KaTeX
Generally, to get this to work I link to the files katex.min.js and katex.min.css from a cdn, which is one of the ways the directions suggest.
I wrap what needs to be rendered in tags and give all the same class. For example:
<span class='math'>\begin{bmatrix}a & b \\c & d\end{bmatrix}</span>
And inside a script tag I apply the following:
var math = document.getElementsByClassName('math');
for (var i = 0; i < math.length; i++) {
katex.render(math[i].innerHTML, math[i]);
}
So, my implementation works but there is a problem in what katex returns. The output of the above gives me:
This exact same question is asked here:
https://github.com/j13z/reveal.js-math-katex-plugin/issues/2
But I can't understand any of it.
The solution is to use element.textContent, not element.innerHTML.
If I use a form like what follows, the matrix will be rendered properly.
var math = document.getElementsByClassName('math');
for (var i = 0; i < math.length; i++) {
katex.render(math[i].textContent, math[i]); // <--element.textContent
}
A solution that works for me is the following (it is more of a hack rather than a fix):
<script type="text/javascript">
//first we define a function
function replaceAmp(str,replaceWhat,replaceTo){
replaceWhat = replaceWhat.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
var re = new RegExp(replaceWhat, 'g');
return str.replace(re,replaceTo);
}
//next we use this function to replace all occurences of 'amp;' with ""
var katexText = $(this).html();
var html = katex.renderToString(String.raw``+katexText+``, {
throwOnError: false
});
//hack to fix amp; error
var amp = '<span class="mord mathdefault">a</span><span class="mord mathdefault">m</span><span class="mord mathdefault">p</span><span class="mpunct">;</span>';
var html = replaceAmp(html, amp, "");
</script>
function convert(input) {
var input = input.replace(/amp;/g, '&'); //Find all 'amp;' and replace with '&'
input=input.replace(/&&/g, '&'); //Find all '&&' and replace with '&'. For leveling 10&x+ &3&y+&125&z = 34232
var html = katex.renderToString(input, {
throwOnError: false});
return html
}
Which version are you using?
Edit the src/utils.js and comment line number 51 to 55 after updated run in terminal npm run build command.
I've got some problems with my url on my website. I'm trying to get a link with the given GET parameters, but i'm getting my previous parameter aswell.
My url looks like this:
www.cdwinkel.dev/search-results?genre=Pop&medium=DVD&medium=Single .
It should be:
www.cdwinkel.dev/search-results?genre=Pop&medium=Single .
I'm running the following code:
$data['url'] = createurl();
function createurl(){
$i = 1;
$string = "?";
$keys = array_keys($_GET);
foreach($_GET as $get){
if($get != ""){
$string .= $keys[$i] . "=" . $get ."&";
$i++;
}
}
$string = rtrim($string, "&");
return $string;
}
$i = 1, because my first value in my array is empty.
And my button looks like this:
<a href='".$data['url'].'&medium='.$names[$i]."'>
I guess I should'nt set &medium=.$names[$i] in the href tag,
but I wont get the new $names[$i] in my function, so I won't get a new url if i wont add it in.
I'm looking forward to your responce.
Sincerely,
Kars Takens
At this point i've created an array with the right arraykeys and values.
$url = array_slice($_GET, 1);
This returns the following array:
array (size=2)
'genre' => string 'Pop' (length=3)
'medium' => string 'DVD' (length=3)
After this I decoded this into a new string:
genre=Pop&medium=DVD
I got 6 button which I created in a foreach loop, but i'm getting &medium='VALUE' Twice. This only happens after the first time. So the first time my button works well.
<?php
$names = array_keys($data['tellen']);
$i = 0;
foreach($data['tellen'] as $m){
echo "<li><a href='search-results?".$data['url'].'&medium='.$names[$i]."'>". $names[$i] ." <span class='product-amount'>(". $m[0]->count. ")</span></a></li>";
$i++;
}
Hopefully you can help me further with this information.
I solved my problem by adding this in my forloop:
foreach($data['tellen'] as $m){
if(isset($_GET['medium'])){
unset($_GET['medium']);
$url = array_slice($_GET, 1);
$data['url'] = urldecode(http_build_query($url));
}
echo "<li><a href='search-results?".$data['url'].'&medium='.$names[$i]."'>". $names[$i] ." <span class='product-amount'>(". $m[0]->count. ")</span></a></li>";
$i++;
}
In Asp.net MVC, Razor inserts extra space between text blocks. I want to render a list this way: "1, 2, 3" but get "1 , 2 , 3".
#for (int i = 1; i < 3; i++)
{
<text>#i</text>
if (i != 2)
{
<text>, </text>
}
}
Is there any ways to remove extra whitespace ?
I want to render a list this way: "1, 2, 3"
Quick and dirty:
#string.Join(", ", Enumerable.Range(1, 3))
Obviously a custom helper seems more appropriate to the job of formatting something in the view:
public static class HtmlExtensions
{
public static IHtmlString FormatList(this HtmlHelper html, IEnumerable<int> list)
{
return MvcHtmlString.Create(string.Join(", ", list));
}
}
and then simply:
#Html.FormatList(Model.MyList)
You are seeing the extra whitespace between the number and the comma because your razor template includes a line break (which displays as whitespace in the browser) between the number and the comma:
#for (int i = 1; i < 3; i++)
{
<text>#i</text> >LINE BREAK HERE<
if (i != 2)
{
<text>, </text>
}
}
I like Darin's answer, and I would suggest removing your loop and replacing it with a more declarative statement, but if you don't want to go that far, try at least removing the line break:
#for (int i = 1; i < 3; i++)
{
<text>#i</text>if (i != 2){<text>, </text>}
}
Instead of writing out bits of text in different places each time round the loop, you could accumulate all the text in a StringBuilder, then outside the loop do #stringBuilderObject.ToString().
The problem is with the source that is generated. When you look at the actual source you get:
1
,
2
,
3
As you can see there is a lot of white space in there which browsers collapse down to a single space (look at the definition for normal).
Using a StringBuilder or string.Join is the way to fix this if all you're doing is outputting these three numbers. But if you're trying to do something else and this is a simplified example then see this blog post for a way of doing it using ol/ul and lis.
I might assume that it is not issue of Razor, but rather element is rendered with some margings.
Open FireBug (or Chrome or whatever) and see that it is really markup issue.
In you css file try to add
text { margin: 0 }
Facebook has this unique and clever approach to localization of their site: translators (in their case users that help to translate the site voluntarily) can simply click on the not-yet-translated strings – which are marked with a green bottom border – in their natural context on the site. See http://www.facebook.com/translations/.
Now, if you ever had to deal with the translation of a website, you'll be well aware of how odd and funny some of these translations can be when using tools like poedit where the translator isn't fully aware of the spot the translated string will lated appear in on the website.
Example: Please translate "Home". In German, for instance, the start page of a website would be "Home" while the house you live in is "Heim". Now, you as the translator basically have to guess which context this term is likely to appear in on the website and translate accordingly. Chances are, you're new website on home furniture now translates as "Home-Einrichtung" which sounds ridiculous to any German.
So, my question boils down to:
Do you know any open source PHP projects that work on something like this? I'm basically looking for a framework that allows you to put your internationalized website in "translation mode" and make strings clickable and translatable e.g. through a Javascript modal.
I'm not so much looking for a full-fledged and ready-made solution, but would love to know about similar projects that I can contribute code to.
Thanks in advance!
If you want to roll your own with jquery & jquery browserLanguage, this might get you going.
Tag all translatable text's contain elements with class="i18n", and include jquery, jquery browserLanguage, and your i18n script.
1. the internationalization javascript
— this needs to accept translations via ajax from your server, like:
var i18n = {};
i18n.bank = new Array();
i18n.t = function ( text, tl=$.browserLanguage ) {
var r = false;
$.ajax({
url: "/i18n_t.php?type=request&from="+ escape(text) +"&tl="+ tl,
success: function(){ i18n.bank[text] = this; r = true; }
});
return r;
};
2. php i18n translation service
— now we need to serve up translations, and accept them
the database will look like a bunch of tables, one for each language.
// SCHEMA for each language:
CREATE TABLE `en`
(
`id` INT PRIMARY KEY AUTO INCREMENT NOT NULL,
`from` VARCHAR(500) NOT NULL,
`to` VARCHAR(500) NOT NULL
)
the php will need some connection and db manipulation.. for now this may do:
//Connect to the database
$connection = mysql_connect('host (usually localhost)', 'mysql_username' , 'mysql_password');
$selection = mysql_select_db('mysql_database', $connection);
function table_exists($tablename, $database = false) {
if(!$database) {
$res = mysql_query("SELECT DATABASE()");
$database = mysql_result($res, 0);
}
$res = mysql_query("SELECT COUNT(*) AS count FROM information_schema.tables WHERE table_schema = '$database' AND table_name = '$tablename'
");
return mysql_result($res, 0) == 1;
}
the code is simply:
<?php
// .. database stuff from above goes here ..
$type=$_GET["type"];
$from=$_GET["from"];
$to=$_GET["to"];
$tl=$_GET["tl"];
if (! table_exists($tl)) {
...
}
if ($type == "request") { // might want to set $tl="en" when ! table_exists($tl)
$find = mysql_query("SELECT to FROM `'$tl'` WHERE from='$from'");
$row = mysql_fetch_array($find);
echo $row['to'];
} elsif ($type == "suggest") {
$find = mysql_query("SELECT COUNT(*) AS count FROM `'$tl'` WHERE from='$from'");
if ( !(mysql_result($res, 0)) == 0 ) {
$ins = mysql_query("INSERT INTO `'$tl'` (from, to) VALUES ('$from','$to')");
}
}
?>
3. page translation mechanics
— finally we can tie them together in your webpages with some further jquery:
i18n.suggest = function (from) { // post user translation to our php
$.ajax({
url: "/i18n_t.php?type=suggest&from='+from+'&to="+ escape( $('#i18n_s').contents() ) +"&tl="+ $.browserLanguage,
success: function(){ $('#i18n_t_div').html('<em>Thanks!</em>').delay(334).fadeOut().remove(); }
});
};
$(document).ready(function() {
i18n.t("submit");
i18n.t("Thanks!");
$('.i18n').click( function(event) { //add an onClick event for all i18n spans
$('#i18n_t_div').remove;
$(this).parent().append(
'<div id="i18n_t_div"><form class="i18n_t_form">
<input type="text" id="i18n_s" name="suggestion" value="+$(this).contents()+" />
<input type="button" value="'+ i18n.bank[ "submit" ] +'" onclick="i18n.suggest( '+$(this).contents()+' )" />
</form></div>'
);
}).each(function(){
var c = $(this).contents(); //now load initial translations for browser language for all the internationalized content on the page
if ( i18n.t(c) ){
$(this).html(i18n.bank[c]);
}
});
});
Mind you I don't have a server to test this on... and I don't actually code php. :D It will take some debugging but the scaffolding should be correct.