I have an image that i am binding the source to pull in dynamic data:
<img :src="'/public/images/' + media.client.name + '_' + media.client.id + '/' + media.type + '/' + media.fileName + '.' + media.ext " alt >
The media.client.name returns a string that has %20 instead of spaces.
I have created a filter:
removeSpecial(value) {
return value.replace("%20", " ");
}
How can I use this filter in the data binding of source please?
I have tried:
<img :src="'/public/images/' + media.client.name | removeSpecial + '_' + media.client.id + '/' + media.type + '/' + media.fileName + '.' + media.ext " alt >
and
<img :src="'/public/images/' + {{ media.client.name | removeSpecial }} + '_' + media.client.id + '/' + media.type + '/' + media.fileName + '.' + media.ext " alt >
Neither seem to work unfortunately.
You can make method which will return prepared url computed method like this:
imageUrl(media){
return '/public/images/' + media.client.name.replace("%20", " ") + '_' + media.client.id + '/' + media.type + '/' + media.fileName + '.' + media.ext;
}
Or if media is assigned in data you can use computed method which will return you same url
computed: {
imageUrl(){
return '/public/images/' + this.media.client.name.replace("%20", " ") + '_' + this.media.client.id + '/' + this.media.type + '/' + this.media.fileName + '.' + media.ext;
}
}
That would depend on how you want to decode the URI component. If this media data is populated dynamically (I suppose so), you could make a method for parsing and decoding it (see example below). If you need this decoder as a filter, however, here's an excerpt from the docs:
Filters should be appended to the end of the JavaScript expression, denoted by the "pipe" symbol.
So your best bet is probably to use a computed property so you can "pipe" it. And yes, you could utilize the native method decodeURIComponent() for this exact purpose.
Approach #1: Method only
new Vue({
el: '#app',
data() {
return {
rootPath: '/public/images/',
media: {
client: {
name: 'Music%20file%20with%20spaces',
id: 123
},
type: 'music-file',
fileName: 'some_music',
ext: 'mp3'
}
}
},
methods: {
getImgSource(media) {
// Destructures the properties for improved readability.
const { client, type, fileName, ext } = media;
const { name, id } = client;
// Uses template literals. Particularly useful for this situation
// where you have several, unique delimiters.
// Helps you see clearer how each of these URI components is combined.
return `${this.rootPath}${decodeURIComponent(name)}_${id}/${type}/${fileName}.${ext}`;
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<!-- Commented out for demo purposes, because I don't have the file.
<img :src="getImgSource(media)" :alt="media.fileName" /> -->
<!-- Let's assume this is an image element -->
<div v-text="getImgSource(media)"></div>
</div>
Approach #2: Computed property + filter
new Vue({
el: '#app',
data() {
return {
rootPath: '/public/images/',
media: {
client: {
name: 'Music%20file%20with%20spaces',
id: 123
},
type: 'music-file',
fileName: 'some_music',
ext: 'mp3'
}
}
},
computed: {
mediaFile() {
const { client, type, fileName, ext } = this.media;
const { name, id } = client;
return `${this.rootPath}${name}_${id}/${type}/${fileName}.${ext}`;
}
},
filters: {
decodeName: window.decodeURIComponent
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<!-- Let's assume this is an image element -->
<div>{{ mediaFile | decodeName }}</div>
</div>
Hope that helps.
Related
I am using markdown-pdf via gulp to convert .md files to .pdf. I want to get the sha of the latest git commit and add it to the footer. I can get the hash like so in my gulpfile.js (found the answer):
revision = require('child_process')
.execSync('git rev-parse HEAD')
.toString().trim();
But how can I get that into my footer?
Below is my code for markdown-pdf that I am using in my gulpfile.js:
function docsToPdf() {
return src(["Views/Documentation/Files/*.md", "!Views/Documentation/Files/_README.md"])
.pipe(markdownPdf({
preProcessMd: preProcessMd,
remarkable: {
html: true
},
paperBorder: "1cm",
runningsPath: "Content/Pdf/assets/js/runnings.js",
cssPath: "Content/Pdf/assets/css/pdf.min.css"
}))
.pipe(dest("Content/Pdf"))
}
And my runnings.js file:
module.exports = {
header: {
height: '2cm',
contents: function (pageNum) {
if (pageNum == 1) {
return '<header class="pdf-header" style="padding-bottom: 20px;"><h2 style="text-align:center;margin:0;">Documentation</h2></header>'
}
return ''
}
},
footer: {
height: '1.5cm',
contents: function (pageNum, numPages) {
return '<footer class="pdf-footer" style="padding-top:20px;"><p style="float:left;width:33.33%;margin:0;font-size:10px;">' + new Date().toDateString() + '</p><p style="float:left;width:33.33%;margin:0;font-size:10px;text-align:center;">© 2020</p><p style="float:right;width:33.33%;margin:0;font-size:10px;text-align:right;">Page ' + pageNum + ' of ' + numPages + '</p></footer>'
}
}
}
And my preProccessMd:
function preProcessMd() {
var splitter = split()
var docsUrl = "https://example.org/docs/";
var urlOne = /\[\[((?:(?!\[\[).)*?)\|(.*?)]]/g;
var urlImg = /(\()(images)/g;
var replacer = through(function (data, path) {
this.queue(
data
.replace(urlOne, (_, x, y) => `[${x}](${docsUrl}${y.replace(/(?!^)[A-Z]/g, '-$&').toLowerCase()})`)
.replace(urlImg, "$1$2".replace("$2", "content/images/docs"))
+ "\n"
)
})
splitter.pipe(replacer)
return duplexer(splitter, replacer)
}
The best way to do this would be to use the preProcessMd method to inject the SHA into the footer. You do seem to have the preprocessor defined in preProcessMd: preProcessMd,. Is that actually doing anything? If so, what is the definition?
EDIT, after update from OP: Quick and dirty solution would be to use an empty span where you want the SHA to go. Then look for that span and replace with the SHA in your preProcessMd. For e.g., <span class="git-hash"></span>. Then replace <span class="git-hash"> with <span>YOUR-SHA.
You might need to update your gulp task like so:
function docsToPdf() {
revision = require('child_process')
.execSync('git rev-parse HEAD')
.toString().trim();
return src(["Views/Documentation/Files/*.md", "!Views/Documentation/Files/_README.md"])
.pipe(markdownPdf({
preProcessMd: preProcessMd.bind(this, revision),
remarkable: {
html: true
},
paperBorder: "1cm",
runningsPath: "Content/Pdf/assets/js/runnings.js",
cssPath: "Content/Pdf/assets/css/pdf.min.css"
}))
.pipe(dest("Content/Pdf"))
}
And your function preProcessMd() { to function preProcessMd(revision) {
NOTE: I'm unsure if the preProcessMd.bind(this, ... is going to be problematic or not.
Hello I think it's easier to show partial lines of my code.
What I'm trying to do is when I input a zipcode, the right icon will show.
I'm using https://erikflowers.github.io/weather-icons/ this git.
for example: if NY weather condition says clear
weather condition in weather.pug should be like i.wi.wi-night-sleet
is it possible to add class name in icon tag from topic.js? or
can I use equal statement in pug flie like - if text=='clear' i.wi.wi-night-sleet
topic.js
router.post('/weather', function(req,res){
let url = `http://api.openweathermap.org/data/2.5/weather?zip=${req.body.zipcode}&units=imperial&appid=${apiKey}`
request(url, function (err, response, body) {
if(err){
res.status(500).send('Internal Server Error');
console.log('error: ' ,err);
} else {
if(req.body.zipcode.length != 5) {
res.render('topic/weather', {text: "Zipcode does not exist"})
} else {
let weather = JSON.parse(body)
let temp = weather.main.temp
let location = weather.name;
let day_weather = weather.weather[0].main;
let message = `It's ${weather.main.temp} degrees in ${weather.name}!`;
//below this I want to call icon tag that has a class name
res.render('topic/weather', {text: location + " : " + day_weather, weatherCondition: `i.wi.wi-night-sleet`});
}
}
});
})
weather.pug
extends ./homepage
block navigate
div.container-fluid
div.row.row-centered
p= text
//- space 넣을떄
= " "
if text
= date
div.col-lg-6.col-centered
form.form-group(action='/weather', method='post')
p
input(type='text', class="form-control", id="zipcode",name='zipcode', placeholder='zipcode')
p
button(type='submit', class="btn btn-primary btn-lg" style='margin-right: 10px;') Login
In your route just pass the identifying part of the icon you need:
res.render('topic/weather', {text: location + " : " + day_weather, weatherCondition: "night-sleet"});
Then here's what your pug template needs to look like:
i.wi(class= 'wi-' + weatherCondition)
or
i(class= 'wi wi-' + weatherCondition)
Either of those lines of pug will produce the same html:
<i class="wi wi-night-sleet"></i>
I have implemented bootstrap-typeahead and when doing a search of, for example, the word "vision" (without accent), I want typeahead to find the coincidences that there is both "visión" (with accent) and "vision".
I have seen several examples to do this, like: accent insensitive regex but I do not understand the form to implement it in typeahaead. And I saw this too: Typeahead insensitive accent and I have created a new file bootstrap3-typeahead-ci.min.js as in this answer is shown, but this not working. Some help? Thanks.
EDITED
To complement the question
this is my typeahead.js (reduced)
$(document).ready(function(){
function buscar(texto){
$('#texto').val(texto);
$('#buscar').submit();
}
if ($('.typetitulo').length) {
var lang = $("#lang_js").data('value');
var json_location = 'storage/json/';
var noticia_location = 'actualidad/';
var noticias = new Bloodhound({
prefetch: {
url: json_location + lang + '/' + 'noticia.json',
cache: false
},
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('title', 'lead'),
queryTokenizer: Bloodhound.tokenizers.whitespace
});
var documentos = new Bloodhound({
prefetch: {
url: json_location + '/' + 'documento.json',
cache: false
},
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name', 'description'),
queryTokenizer: Bloodhound.tokenizers.whitespace
});
$('.typetitulo').typeahead(
{
name: 'noticias',
display: 'title',
source: noticias,
templates: {
header: "<h3>"+ tit_actualidad +"</h3>",
suggestion: function (item) {
var enlace = noticia_location + item.id + '/' + item.slug;
return "<div><a href='"+enlace+"'>" + item.title + "</a></div>";
}
}
},
{
name: 'documentos',
display: 'name',
source: documentos,
templates: {
header: "<h3>"+ tit_documentos +"</h3>",
suggestion: function (item) {
var enlace = item.path;
return "<div><a href='"+enlace+"'>" + item.name + "</a></div>";
}
}
}).on('typeahead:selected', function(e){
e.target.form.submit();
});
}
});
In the view:
{!! Form::open([
'route' => 'buscar',
'id' => 'buscar',
'name' => 'buscar',
'class' => 'buscador col-xs-12',
'method' => 'POST',
'accept-charset' => 'utf-8'
]) !!}
<input name="texto" class="input_buscador typetitulo" autocomplete="off" type="text"/>
<input name="lang" type="hidden" value="{{$lang}}"/>
{!! HTML::image('images/web/icons/lupa.svg', '', array('height' => '30', 'class' => 'boton_buscador', 'onclick' => 'document.buscar.submit()') ) !!}
{!! Form::close() !!}
// .... //
#if(isset($data['noticias']) && $data['noticias']->count() !== 0)
<div class="col-xs-12 pad_inf_2">
<h3>#lang('header.actualidad')</h3>
#foreach($data['noticias'] as $value)
<span class="item">
{{$value['title']}}
</span>
#endforeach
</div>
#endif
#if(isset($data['docs']) && $data['docs']->count() !== 0)
<div class="col-xs-12 pad_inf_2">
<h3>#lang('header.biblioteca')</h3>
#foreach($data['docs'] as $value)
<span class="item">
{{$value['name']}}
</span>
#endforeach
</div>
#endif
This is the typeahead-insensitive.js as in this answer is shown: Typeahead insensitive accent
// function for making a string accent insensitive
$.fn.typeahead.Constructor.prototype.normalize = function (str) {
// escape chars
var normalized = str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
// map equivalent chars
normalized = normalized.replace(/[aãáàâ]/gi, '[aãáàâ]');
normalized = normalized.replace(/[eẽéèê]/gi, '[eẽéèê]');
normalized = normalized.replace(/[iĩíìî]/gi, '[iĩíìî]');
normalized = normalized.replace(/[oõóòô]/gi, '[oõóòô]');
normalized = normalized.replace(/[uũúùû]/gi, '[uũúùû]');
normalized = normalized.replace(/[cç]/gi, '[cç]');
// convert string to a regular expression
// with case insensitive mode
normalized = new RegExp(normalized, 'gi');
// return regular expresion
return normalized;
}
// change 'matcher' method so it became accent insensitive
$.fn.typeahead.Constructor.prototype.matcher = function (item) {
// get item to be evaluated
var source = this.displayText(item);
// make search value case insensitive
var normalized = this.normalize(this.query);
// search for normalized value
return source.match(normalized);
}
// change 'highlighter' method so it became accent insensitive
$.fn.typeahead.Constructor.prototype.highlighter = function (item) {
// get html output
var source = this.displayText(item);
// make search value case insensitive
var normalized = this.normalize(this.query);
// highlight normalized value in bold
return source.replace(normalized, '<strong>$&</strong>');
}
And in the layout I added:
{{-- Typeahead --}}
{!! HTML::script('https://cdnjs.cloudflare.com/ajax/libs/typeahead.js/0.11.1/typeahead.bundle.min.js') !!}
{!! HTML::script('js/web/typeahead-insensitive.js') !!}
{!! HTML::script('js/web/typeahead.js') !!}
I'm using phantomjs to render pdf with header and footer. Adding header and footer is implemented in all pages. Is there any way to remove header/footer from 1st page alone?
header: {
height: "1cm",
contents: phantom.callback(function(pageNum, numPages) {
return "<h1>Header <span style='float:right'>" + pageNum + " / " + numPages + "</span></h1>";
})}, footer: {
height: "1cm",
contents: phantom.callback(function(pageNum, numPages) {
return "<h1>Footer <span style='float:right'>" + pageNum + " / " + numPages + "</span></h1>";
})}
While not perfect, I return and empty string instead of actual html content when pageNum is equal to 1 (or to numPages in my case). The height is still occupied but at least its empty.
How can I add fields dynamically in Jtable. I want to have multiple values for Cities
Please Refer the image attached
Thanks
Yes this is not built-in with jQuery jTable. To deal with this I've created a script for the same purpose. This handles (a) adding more controls OR group of controls and (b) remove control(s).
Here is the script:
//add '.add_more' class to
$(".add_more").on('click', function () {
// creates unique id for each element
var _uniqueid_ = +Math.floor(Math.random() * 1000000);
var new_ele_id = $(this).attr("data-clone-target") + _uniqueid_;
var cloneObj = $("#" + $(this).attr("data-clone-target"))
.clone()
.val('')
.attr("id", new_ele_id);
// if the control is grouped control
if ($(this).hasClass('group_control') == true) {
$($(cloneObj).children()).each(function () {
$(this).attr("id", $(this).attr("id") + _uniqueid_).val("");
});
}
$(cloneObj).insertBefore($(this));
//creates a 'remove' link for each created element or grouped element
$("<a href='javascript:void(0);' class='remove_this' data-target-id='" + new_ele_id + "'></a>")
.on('click', function () {
if ($(this).is(":visible") == true) {
if (confirm("Are you sure?")) {
$("#" + $(this).attr("data-target-id")).remove();
$(this).remove();
}
}
else {
$("#" + $(this).attr("data-target-id")).remove();
$(this).remove();
}
}).insertBefore($(this));
$("#" + new_ele_id).focus();
});
//remove element script
$(".remove_this").on('click', function () {
if ($(this).is(":visible") == true) {
if (confirm("Are you sure?")) {
$("#" + $(this).attr("data-target-id")).remove();
$(this).remove();
}
}
else {
$("#" + $(this).attr("data-target-id")).remove();
$(this).remove();
}
});
Usage: Single Element http://jsfiddle.net/vkscorpion1986/ktbn4qLg/2/
<input class="" id="<ELEMENT-ID>" type="text" name="input1">
Add More
Usage: Grouped Elements http://jsfiddle.net/vkscorpion1986/ktbn4qLg/4/
<div id="<ELEMENT-ID>">
<input class="" id="input1" type="text" name="input1">
<input class="" id="input2" type="text" name="input2">
</div>
Add More
attributes
href = javascript:void(0); // just to disable the anchor tag default behaviour
data-clone-target = id of the target element
css classes
.add_more = to implement the add more/remove controls functionality
.group_control = for indicating that this is group of elements which have to be repeted
Hope this works for you.
No, it's not made with jTable. You can use input option (http://jtable.org/ApiReference#fopt-input) and this: http://jqueryui.com/autocomplete/#multiple Or you can create your own dialog.