Character escaping in Polymer - polymer

I'm creating a component with Polymer which has a background image added with inline styles. The problem is that using double brackets inside parenthesis and quotes makes the {{imageurl}} act like a string. Any tips?
<div class="image-container" style="background-image: url( '{{imageurl}}' )">
Update: I've tried the method posted here with no luck.

What you will have to do is have a computed property that returns the style:
<div style$="{{divStyle}}">hi</div>
Note the use of $= here as were are data-binding to an attribute. See here for more info.
And your JavaScript:
Polymer({
is: "test-element",
properties: {
backgroundColor: {
type: String,
value: '#FF0000'
},
divStyle: {
computed: 'getDivStyle(backgroundColor)'
}
},
getDivStyle: function(backgroundColor) {
return 'background-color: ' + backgroundColor + ';';
}
});
See this plunker to see it in action.

String interpolation is not yet supported in Polymer 1.0. Use computed bindings instead.
<!-- Notice the `$` sign. Use attribute binding (`$=`) when binding native elements attribute -->
<div style$="{{_computeBackgroundImage(imageurl)}}"></div>
Polymer({
...
_computeBackgroundImage: function(url) {
return 'background-image: url('+url+');';
}
});

Related

How can I show a hidden link in a jQuery table [duplicate]

I am trying to change the CSS using jQuery:
$(init);
function init() {
$("h1").css("backgroundColor", "yellow");
$("#myParagraph").css({"backgroundColor":"black","color":"white");
$(".bordered").css("border", "1px solid black");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="bordered">
<h1>Header</h1>
<p id="myParagraph">This is some paragraph text</p>
</div>
What am I missing here?
Ignore the people that are suggesting that the property name is the issue. The jQuery API documentation explicitly states that either notation is acceptable: http://api.jquery.com/css/
The actual problem is that you are missing a closing curly brace on this line:
$("#myParagraph").css({"backgroundColor":"black","color":"white");
Change it to this:
$("#myParagraph").css({"backgroundColor": "black", "color": "white"});
Here's a working demo: http://jsfiddle.net/YPYz8/
$(init);
function init() {
$("h1").css("backgroundColor", "yellow");
$("#myParagraph").css({ "backgroundColor": "black", "color": "white" });
$(".bordered").css("border", "1px solid black");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="bordered">
<h1>Header</h1>
<p id="myParagraph">This is some paragraph text</p>
</div>
You can do either:
$("h1").css("background-color", "yellow");
Or:
$("h1").css({backgroundColor: "yellow"});
To clear things up a little, since some of the answers are providing incorrect information:
The jQuery .css() method allows the use of either DOM or CSS notation in many cases. So, both backgroundColor and background-color will get the job done.
Additionally, when you call .css() with arguments you have two choices as to what the arguments can be. They can either be 2 comma separated strings representing a css property and its value, or it can be a Javascript object containing one or more key value pairs of CSS properties and values.
In conclusion the only thing wrong with your code is a missing }. The line should read:
$("#myParagraph").css({"backgroundColor":"black","color":"white"});
You cannot leave the curly brackets out, but you may leave the quotes out from around backgroundColor and color. If you use background-color you must put quotes around it because of the hyphen.
In general, it's a good habit to quote your Javascript objects, since problems can arise if you do not quote an existing keyword.
A final note is that about the jQuery .ready() method
$(handler);
is synonymous with:
$(document).ready(handler);
as well as with a third not recommended form.
This means that $(init) is completely correct, since init is the handler in that instance. So, init will be fired when the DOM is constructed.
The .css() method makes it super simple to find and set CSS properties and combined with other methods like .animate(), you can make some cool effects on your site.
In its simplest form, the .css() method can set a single CSS property for a particular set of matched elements. You just pass the property and value as strings and the element’s CSS properties are changed.
$('.example').css('background-color', 'red');
This would set the ‘background-color’ property to ‘red’ for any element that had the class of ‘example’.
But you aren’t limited to just changing one property at a time. Sure, you could add a bunch of identical jQuery objects, each changing just one property at a time, but this is making several, unnecessary calls to the DOM and is a lot of repeated code.
Instead, you can pass the .css() method a Javascript object that contains the properties and values as key/value pairs. This way, each property will then be set on the jQuery object all at once.
$('.example').css({
'background-color': 'red',
'border' : '1px solid red',
'color' : 'white',
'font-size': '32px',
'text-align' : 'center',
'display' : 'inline-block'
});
This will change all of these CSS properties on the ‘.example’ elements.
When you are using Multiple css property with jQuery then you must use the curly Brace in starting and in the end. You are missing the ending curly brace.
function init() {
$("h1").css("backgroundColor", "yellow");
$("#myParagraph").css({"background-color":"black","color":"white"});
$(".bordered").css("border", "1px solid black");
}
You can have a look at this jQuery CSS Selector tutorial.
If you have one css:
$("p").css("background-color": "pink");
If you have more than one css:
$("p").css({"background-color": "pink", "font-size": "200%"});
Or you can use:
var style ="background-color:red;";
$("p").attr("style", style);
Just wanted to add that when using numbers for values with the css method you have to add them outside the apostrophe and then add the CSS unit in apostrophes.
$('.block').css('width',50 + '%');
or
var $block = $('.block')
$block.css({ 'width': 50 + '%', 'height': 4 + 'em', 'background': '#FFDAB9' });
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>
$( document ).ready(function() {
$('h1').css('color','#3498db');
});
</script>
<style>
.wrapper{
height:450px;
background:#ededed;
text-align:center
}
</style>
</head>
<body>
<div class="wrapper">
<h1>Title</h1>
</div>
</body>
</html>
$(".radioValue").css({"background-color":"-webkit-linear-gradient(#e9e9e9,rgba(255, 255, 255, 0.43137254901960786),#e9e9e9)","color":"#454545", "padding": "8px"});
$(function(){
$('.bordered').css({
"border":"1px solid #EFEFEF",
"margin":"0 auto",
"width":"80%"
});
$('h1').css({
"margin-left":"10px"
});
$('#myParagraph').css({
"margin-left":"10px",
"font-family":"sans-serif"
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="bordered">
<h1>Header</h1>
<p id="myParagraph">This is some paragraph text</p>
</div>
wrong code:$("#myParagraph").css({"backgroundColor":"black","color":"white");
its missing "}" after white"
change it to this
$("#myParagraph").css({"background-color":"black","color":"white"});

How to make links clickable in a chat

I have a chat on my website that reads from a JSON file and grabs each message and then displays it using Vue.js. However, my problem is that when a user posts a link, it is not contained in an anchor tag <a href=""/>. Therefore it is not clickable.
I saw this post, and I think something like this would work, however, I am not allowed to add any more dependencies to the site. Would there be a way for me to do something similar to this without adding more dependencies?
Code for displaying the message.
<p v-for="msg in messages">
<em class="plebe">
<b> [ {{msg.platform.toUpperCase()}} ]
<span style="color: red" v-if="msg.isadmin">{{msg.user.toUpperCase()}}</span>
<span style="color: #afd6f8" v-else="">{{msg.user.toUpperCase()}}</span>
</b>
</em>:
{{msg.message}}
</p>
In a situation like this, its preferred to write a custom functional component.
The reason for this is the fact that we are required to emit a complex html structure, but we have to make sure to properly protect against xss attacks (so v-html + http regex is out of the picture)
We are also going to use render functions, because render functions have the advantage to allow for javascript that generates the html, having more freedom.
<!-- chatLine.vue -->
<script>
export default {
functional: true,
render: function (createElement, context) {
// ...
},
props: {
line: {
type: String,
required: true,
},
},
};
</script>
<style>
</style>
We now need to think about how to parse the actual chat message, for this purpose, I'm going to use a regex that splits on any length of whitespace (requiring our chat urls to be surrounded with spaces, or that they are at the start or end of line).
I'm now going to make the code in the following way:
Make a list for child componenets
Use a regex to find url's inside the target string
For every url found, do:
If the match isn't at the start, place the text leading from the previous match/start inside the children
place the url inside the list of children as an <a> tag, with the proper href attribute
At the end, if we still have characters left, at them to the list of children too
return our list wrapped inside a P element
Vue.component('chat-line', {
functional: true,
// To compensate for the lack of an instance,
// we are now provided a 2nd context argument.
// https://vuejs.org/v2/guide/render-function.html#createElement-Arguments
render: function (createElement, context) {
const children = [];
let lastMatchEnd = 0;
// Todo, maybe use a better url regex, this one is made up from my head
const urlRegex = /https?:\/\/([a-zA-Z0-9.-]+(?:\/[a-zA-Z0-9.%:_()+=-]*)*(?:\?[a-zA-Z0-9.%:_+&/()=-]*)?(?:#[a-zA-Z0-9.%:()_+=-]*)?)/g;
const line = context.props.line;
let match;
while(match = urlRegex.exec(line)) {
if(match.index - lastMatchEnd > 0) {
children.push(line.substring(lastMatchEnd, match.index));
}
children.push(createElement('a', {
attrs:{
href: match[0],
}
}, match[1])); // Using capture group 1 instead of 0 to demonstrate that we can alter the text
lastMatchEnd = urlRegex.lastIndex;
}
if(lastMatchEnd < line.length) {
// line.length - lastMatchEnd
children.push(line.substring(lastMatchEnd, line.length));
}
return createElement('p', {class: 'chat-line'}, children)
},
// Props are optional
props: {
line: {
required: true,
type: String,
},
},
});
var app = new Vue({
el: '#app',
data: {
message: 'Hello <script>, visit me at http://stackoverflow.com! Also see http://example.com/?celebrate=true'
},
});
.chat-line {
/* Support enters in our demo, propably not needed in production */
white-space: pre;
}
<script src="https://unpkg.com/vue#2.0.1/dist/vue.js"></script>
<div id="app">
<p>Message:</p>
<textarea v-model="message" style="display: block; min-width: 100%;"></textarea>
<p>Output:</p>
<chat-line :line="message"></chat-line>
</div>
You can watch or write computed method for the variable having url and manupulate it to html content and then use v-html to show html content on the page
v-html

Can't get polymer databinding to custom html tag to work while it works on standard tags

I'm using polymer 1.3.1 but can't get the following to work inside a polymer-element named: poly-main. The text of the <div> should be in red but isn't.
<div testcolor="[[colorLocalRed]]">
-->ERROR This must be RED because testcolor="[[colorLocalRed]]"
(expected "myred" and styles.css translates this to color="red")
</div>
with the following at the start of the script tag:
Polymer({
is: 'poly-main',
properties: {
colorLocalRed: {
type: String,
value: "myred",
notify: true
},
And the following inside styles.css:'
[testcolor="myred"] {
color: red;
}
Note: the following works as it should:
<div testcolor="myred"> some red text </div>
Not using the custom tag testcolor but using directly style or color is not an option because this example is only to show the problem of databinding to a non-standard html-tag
I guess this is what you want:
<div testcolor$="[[colorLocalRed]]">
Adding $ to the attribute name binds to the attribute instead of the property which can't be addressed in CSS.
For more details see https://www.polymer-project.org/1.0/docs/devguide/data-binding.html#native-binding

Angular conditional container element

I have a large chunk of HTML in an ng-repeat that for certain elements has a container element and for others it does not. I'm currently achieving this with two ng-ifs:
<strike ng-if="elem.flag">
… <!-- several lines of directives handling other branching cases -->
</strike>
<div ng-if="!elem.flag">
… <!-- those same several lines copied-and-pasted -->
</div>
While this works, it means I have to remember copy-and-paste any edits, which is not only inelegant but also prone to bugs. Ideally, I could DRY this up with something like the following (inspired by ng-class syntax):
<ng-element="{'strike':flag, 'div':(!flag)}">
… <!-- lots of code just once! -->
</ng-element>
Is there any way to achieve a similarly non-repetitive solution for this case?
You can make such directive yourself.
You can use ng-include to include the same content into both elements.
Assuming the effect you desire is to have the text within your tag be striked through based on the condition of the elem.flag:
You could simply use the ng-class as follows
angular.module('ngClassExample', [])
.controller('elemController', Controller1);
function Controller1() {
vm = this;
vm.flag = true;
vm.clickItem = clickItem
function clickItem() {
// Toggle the flag
vm.flag = !vm.flag;
};
}
.strikethrough{
text-decoration: line-through
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='ngClassExample' ng-controller="elemController as elem">
<div ng-class="{strikethrough: elem.flag}" ng-click="elem.clickItem()">
element content should be sticked through: {{elem.flag}}
</div>
</div>
You can do it with a directive
module.directive('myFlag', function() {
var tmpl1 = '<strike>...</strike>';
var tmpl2 = '<div>...</div>';
return {
scope: {
myFlag: '='
},
link: function(scope, element) {
element.html(''); // empty element
if (scope.myFlag) {
element.append(tmpl1);
} else {
element.append(tmpl2);
}
}
};
});
And you just use it like:
<div ng-repeat="item in list" my-flag="item.flag"></div>
You could create a directive which will transclude the content based on condition. For tranclusion you could use ng-transclude drirective, in directive template. Also you need to set transclude: true.
HTML
<my-directive ng-attr-element="{{elem.flag ? 'strike': 'div'}}">
<div> Common content</div>
</my-directive>
Directive
app.directive('myDirective', function($parse, $interpolate) {
return {
transclude: true,
replace: false, //will replace the directive element with directive template
template: function(element, attrs) {
//this seems hacky statement
var result = $interpolate(attrs.element)(element.parent().scope);
var html = '<'+ result + ' ng-transclude></'+result+'>';
return html;
}
}
})
Demo Plunkr
You can also use ng-transclude :
Create your directive :
<container-directive strike="flag">
<!-- your html here-->
</container-directive>
Then in your directive do something like :
<strike ng-if="strike">
<ng-transclude></ng-transclude>
</strike>
<div ng-if="!strike">
<ng-transclude></ng-transclude>
</div>

How to set value for dir-Attribute via AngularJS

I want to set the direction of the body-element depending on some logic inside the controller.
So if a language file has a certain value, i want to change from "ltr" to "rtl".
I know there is a way of setting HTML attributes via ng-attr-, but it's not working for dir.
I made a JSFiddle to show my problem. The question is:
How can I set the dir-attribute via the controller?
<div ng-controller="MyCtrl">
<div ng-attr-dir="{{direct}}">
<p>Test</p>
</div>
</div>
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.direct = "rtl";
}
Just use dir, instead of ng-attr-dir.
<div dir="{{direct}}">
Fiddle
It can be accomplished with a trivial directive:
myApp.directive("myDir", function() {
return {
link: function(scope, elem, attrs) {
attrs.$observe("myDir", function(newval) {
if( newval ) {
elem.attr("dir", newval);
}
else {
elem.removeAttr("dir");
}
});
}
};
});
Use it as:
<div my-dir="{{direct}}">
A forked fiddle: http://jsfiddle.net/34ch4qef/1/
Use inline style="direction:{{direct}}" instead .
http://jsfiddle.net/HB7LU/7373/
You have to use an Angular version the actually supports ngAttr ;) 1.0 doesn't.