AngularJs: How to create a directive to replace innerText - php

I am working in a project(online exam, a single page application) using PHP+MySQL+AngularJs which has one very important section i.e. "Add Question". Let us take as a example:
$simple_question = "A train running at the speed of 60 km/hr crosses a pole in 9 seconds. What is the length of the train?";
$programmimg_question = "[code]#include int main(int argc, char **argv) { printf("%c\n", **++argv); return 0; }[/code]";
So you can see that, I am adding [code]....[/code] whenever programming language question is getting inserted so that I can prettify the code while showing the question. I am using twitter bootstrap which has <code> tag to show code between them. So I want to create a directive which will replace the [code] to <code> and render as a HTML in the view.
here is my code in HTML
<div class="question-container">
<code-highlighter> {{questionData.question}} </code-highlighter>
</div>
directive code(which is not working):
app.directive('codeHighlighter', function ($compile) {
return {
restrict: 'E',
scope: {
questions: "="
},
link: function (scope, element, attrs) {
var html = element[0].outerHTML;
var hasCodeElement = false;
if(html.indexOf('[code]')!=-1) hasCodeElement = true;
if(hasCodeElement) html = '<code>'+html+'</code>';
var e = $compile(html)(scope);
element.replaceWith(e);
}
};
})
I am pretty new for creating a directive in angularjs, please give me some resource or link to achieve the above problem, Please help me to out of it.
Thanks, In advance.

You don't need to $compile anything. Just set the elements HTML based on the assigned question-text, optionally replacing [code]...[/code] with <code>...</code>.
You can do it like this:
app.directive('question', function () {
return {
restrict: 'E',
scope: {
text: '='
},
link: function questionPostLink(scope, elem, attrs) {
var html = scope.text.replace(
/\[code\](.*?)\[\/code\]/g,
'<code>$1</code>');
elem.html(html);
}
};
});
Then you can use it like this:
$scope.questions = [
'This is a simple questions (without any [code]).',
'[code]var str = \'This is a programming question.\';[/code]'
];
<question text="txt" ng-repeat="txt in questions"></question>
See, also, this short demo.
UPDATE:
In order to be able to render HTML elements inside [code]...[/code] as is, use the following linking function:
link: function questionPostLink(scope, elem, attrs) {
// Here, I assume that programming questions
// always begin with [code] and end with [/code]
var isProgramming = progRE.test(scope.text);
if (!isProgramming) {
var html = scope.text;
elem.html(html);
} else {
var text = scope.text.replace(progRE, '$1');
elem.html('<code></code>');
elem.children().text(text);
}
}
See, also, this updated demo.

Related

Bold particular text in string on runtime jQuery

My requirement is : Thers's an input field. When user is going to filled it,
on runtime i searched for #tag and make text bold. And wants to separate both groups of #tags
For Example: "I am more #FromSide #FromSide and would like to speak with someone more #ToSide"
Group1: #FromSide #FromSide
Group2: #ToSide
Here's my code:
`$('#custm-field').keyup(function(){`
`let str = $(this).val();`
`let arr = str.split(" ");`
`$(arr).each((i,e)=>{`
`if(e=="#")`
`{ // $(e).css('font-weight','bold');`
`arr[i].replace(e,"<strong>"+e+"</strong>");}
`let newStr = arr.join(" ");`
`$('#custm-field').val(newStr)`
`});`
This can be achieved using RegEx:
$('#custm-field').keyup(function(){
let str = $(this).val();
str = str.replace(/#(.+?)\s/, '<strong>$1</strong>');
$('#custm-field').val(str);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="custm-field"></input>
However, the bold effect won't be displayed in input fields, you need a contenteditable element for this.
I've constructed a solution for you,
First of all, you can't add HTML tags inside the value of an input tag. So you have to make use of contenteditable HTML attribute, by setting it to true contenteditable="true" on any element you can start to edit the content of it (write inside it).
NOTE: I added a background-color to make it visible when its empty
<div contentEditable="true" id="text" style="background-color: #eee;"></div>
Your JavaScript (JQuery) would look like this:
Note that your code had many errors I had to fix.
$('#text').keyup(function(){
// get the div element
let e = document.querySelector('#text');
// get only the text inside the element (without the HTML tags)
let str = e.innerText;
e.innerHTML = '';
// create a new element to contain our text because you cant add HTML text inside a DOM element directly
let tag = document.createElement('div');
let arr = str.split(" ");
// this string will contain our HTML and text
let newStr = ``;
$(arr).each((i,e)=>{
if(e[0]=="#")
{
newStr += `<strong>${e}</strong>`;
}
else{
newStr += `${e}`
}
newStr += ` `;
})
// add the string to the inner HTML of the element we created
tag.innerHTML = newStr;
// append the newly created element inside the div
e.append(tag);
// based on Vito Gentile answer
// this is to move the cursor to the end of the text we added, other wise the cursor would be at start of the text
cursorManager.setEndOfContenteditable(e);
});
I made use of the code of this answer, this is where this line cursorManager.setEndOfContenteditable(e); came from. Here is their code for convenience.
(function( cursorManager ) {
//From: http://www.w3.org/TR/html-markup/syntax.html#syntax-elements
var voidNodeTags = ['AREA', 'BASE', 'BR', 'COL', 'EMBED', 'HR', 'IMG', 'INPUT', 'KEYGEN', 'LINK', 'MENUITEM', 'META', 'PARAM', 'SOURCE', 'TRACK', 'WBR', 'BASEFONT', 'BGSOUND', 'FRAME', 'ISINDEX'];
//From: https://stackoverflow.com/questions/237104/array-containsobj-in-javascript
Array.prototype.contains = function(obj) {
var i = this.length;
while (i--) {
if (this[i] === obj) {
return true;
}
}
return false;
}
//Basic idea from: https://stackoverflow.com/questions/19790442/test-if-an-element-can-contain-text
function canContainText(node) {
if(node.nodeType == 1) { //is an element node
return !voidNodeTags.contains(node.nodeName);
} else { //is not an element node
return false;
}
};
function getLastChildElement(el){
var lc = el.lastChild;
while(lc && lc.nodeType != 1) {
if(lc.previousSibling)
lc = lc.previousSibling;
else
break;
}
return lc;
}
//Based on Nico Burns's answer
cursorManager.setEndOfContenteditable = function(contentEditableElement)
{
while(getLastChildElement(contentEditableElement) &&
canContainText(getLastChildElement(contentEditableElement))) {
contentEditableElement = getLastChildElement(contentEditableElement);
}
var range,selection;
if(document.createRange)//Firefox, Chrome, Opera, Safari, IE 9+
{
range = document.createRange();//Create a range (a range is a like the selection but invisible)
range.selectNodeContents(contentEditableElement);//Select the entire contents of the element with the range
range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start
selection = window.getSelection();//get the selection object (allows you to change selection)
selection.removeAllRanges();//remove any selections already made
selection.addRange(range);//make the range you have just created the visible selection
}
else if(document.selection)//IE 8 and lower
{
range = document.body.createTextRange();//Create a range (a range is a like the selection but invisible)
range.moveToElementText(contentEditableElement);//Select the entire contents of the element with the range
range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start
range.select();//Select the range (make it the visible selection
}
}
}( window.cursorManager = window.cursorManager || {}));
Hopefully this works like what you want.

Removing html tags that are not closed - while pasting content to div with contenteditable

I am struggling here to find a solution to using
div using contenteditable
PHP
<div class="panel-body">
<div contenteditable="true" style="text-align: justify" id="text_data_1">
<?php echo(html_entity_decode($text_data_from_backend))?>
</div>
</div>
jQuery
var postFormData = {
'agent_id' : $("#text_data_1").val(),
'actionmode' : id
};
var link = 'myfile.php';
$.fn.getajaxresponse(link, postFormData, $.fn.this_callback);
Data is pasted or typed into the div which is contenteditable. The whole html layout fails when end users paste content from websites with tags that are not closed properly.
I am using div contenteditable so that new lines and basic html tags are preserved and can be transacted back and forth to database.
Is there a way to remove html tags that are not closed properly and I believe this is the show stopper in getting this methodology in place. Please note I use jQuery, PHP and MySQL
Thank you for your responses.
It was a bit tricky one and on searching I found a library where jQuery cleaned up without using regex
I attached an editor called Trumbowyg to the div - http://alex-d.github.io/Trumbowyg/
It was quite easy and cool. This one is lightweight and and requires to add the js file to the required page.
On saving via ajax, called a function where JClean [https://code.google.com/archive/p/jquery-clean/] library is used to clean the unclosed tags. Add the Jclean js file to the required page
This is how I did it eventually.
Attaching editor
$.fn.attach_event_div_contenteditable = function(){
var tb_buttons = [
['viewHTML'],
['formatting'],
'btnGrp-semantic',
['superscript', 'subscript'],
['link'],
'btnGrp-justify',
'btnGrp-lists',
['horizontalRule'],
['removeformat'],
['fullscreen']
];
$('#text_data_1').trumbowyg({
removeformatPasted: true,
btns: tb_buttons,
height:"100%",
});
$('#text_data_2').trumbowyg({
removeformatPasted: true,
btns: tb_buttons,
});
$('#text_data_3').trumbowyg({
removeformatPasted: true,
btns: tb_buttons,
});
$('#text_data_4').trumbowyg({
removeformatPasted: true,
btns: tb_buttons,
});
}
Cleaning elements
$.fn.get_latest_value = function(elem){
var tagname = elem.prop("tagName");
var returnvalue = "";
switch(tagname.toUpperCase()){
case "TEXTAREA":
returnvalue = elem.val();break;
case "INPUT":
returnvalue = elem.val(); break;
default:
returnvalue = elem.html();break;
}
returnvalue = returnvalue.replace(/\"/g,'"');
returnvalue = returnvalue.replace(/\'/g,'&apos;');
var temp = $("<input value='"+returnvalue+"'/>");
returnvalue = $.htmlClean(temp.val(), { format: true });
return returnvalue;
}
Ajax call
var postFormData = {
'agent_id' : $.fn.get_latest_value($("#text_data_1")),
'actionmode' : id
};
var link = 'myfile.php';
$.fn.getajaxresponse(link, postFormData, $.fn.this_callback);
This is the best I could find as an answer and went ahead. Hope this helps to anyone who wondered how I fixed it.

Get the result from data.php then convert it to javascript string

I don't really know what to call this. Here is my files
data.php => calculate some random numbers
jscript.js => this echos the result from data.php to a div id
but what i wanted to do on some part is get the value from data.php and then place it to
the style of the div.
$.get('jQuery/data.php?Con&userHP&perc' , { userID: xUserID } ,
function(output) {
$('#userHP').html(output).show();
var o = document.getElementById("userHealthbar");
o.style.width= result_here ;
}
);
instead of placing the result inside the div /div i want it to the style portion of the div.
P.S: i want the result from data.php to be a variable in javascript.
but i can't seem to make it work.
i hope my explanation is clear.
You should use jQuery selectors instead of document.getelementById.
Common way:
jQuery('#userHealthbar').attr('style', whateverYouGotFromPHP);
Better in this case:
jQuery('#userHealthbar').width(whateverYouGotFromPHP);
D.
If you want to return multiple things from php to javascript, you should use json.
So if you have 2 values you want to return in php, you can do:
$html = "your html string";
$value = 4; // the value you want to return
$array_to_return = array("html" => $html, "value" => $value);
echo json_encode($array_to_return); // the only thing you echo out in your php!
Then, in javascript, you can use $.getJSON instead of $.get:
$.getJSON('jQuery/data.php?Con&userHP&perc' , { userID: xUserID } ,
function(output) {
$('#userHP').html(output.html).show();
var o = document.getElementById("userHealthbar");
o.style.width= output.value ;
}
);

Using hash plus querystring as an anchor for jquery fueled webpage?

Here is my situation. I have a webpage (not quite finished):
http://grapplingbasics.com/beta.php
I have the page slide to a specific div which puts a a url with a hash in the URL bar. If the user refers to this URL they can hit that specific part of the page.
However, I would like to allow them to hit that part of the page AND load a specific video with one address.
It doesn't seem that you can put a query string and hash dealy together like so: www.blah.com/index.php#BLAH?neat=one
originally i tried turning the hash into part of the querystring, and then using split in jquery to assign it into a hash on the fly. However, the problem with this, is that if I return false to the nav, it wont show the querystring on the URL bar, and if i don't return false, then it wants to navigate to something that isnt there!
What's a possible solution here?
I created a little example for you which should explain how you can get this fixed.
<script type="text/javascript">
function getParameterByName(name) {
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regexS = "[\\?&]" + name + "=([^&#]*)";
var regex = new RegExp(regexS);
var results = regex.exec(window.location.href);
if (results == null)
return "";
else
return decodeURIComponent(results[1].replace(/\+/g, " "));
}
$(function () {
$('a').click(function (event) {
var thisHash = document.location.hash;
$('body').animate({ scrollTop: $(thisHash).offset().top }, function () {
if (getParameterByName('neat') != null) {
alert('I will play video ' + getParameterByName('neat'));
}
});
});
});
</script>
Html:
<a href='?neat=one#end'>Go</a>
<p id='end'>Imagine this is a panel you are going to in your example.</p>
The code above firstly has a getParameterByName function which looks into your URL to find your query string value pairs. and if its not null it returns its value.
in the section below that ...imagine that the anchor tag is your navigation and I clicked on it, then the page animates to the correct hash section. Once the animation is completed in the callback section is asks for the query string value. if it you have set a value for "neat" then your code for playing the video should sit where the alert is now.
You can put the querystring before the hash:
www.blah.com/index.php?neat=one#BLAH
Or for a more complex solution, look into the querying aspect of ben alman's jquery bbq plugin:
http://benalman.com/projects/jquery-bbq-plugin/

translate rss-feed that was grabbed by cURL

my most trusted programmers and thank for all the help!
I grab rss-feed by jquery-ajax using php curl. It's loading very nicely directly on the page. However, I would like to translate the text, that is now html, title within h2 and text within p, wrapped by a div-container.
Google's api-script for translation doesn't seem to run after the content was put into the div. Really nothing happens. I tried both putting the script in the ajax-url-file and the file that the content is displayed on.
I used .live(), but no result.
Any idea?
Thanks!
--
In one of the methods I create a table i mysql and put in title, link and text. After that I echo the table.
$query3 = mysql_query("SELECT * FROM temp_rss_$id") or die("$error_msg");
while ($row3 = mysql_fetch_array($query3)) {
$title = htmlentities($row3['title']);
$text = htmlentities($row3['text']);
$link = $row3['link'];
echo "
$titel
$text
";
}
The title is within in a h2 and an anchor, and the text is within a p.
Using simple jquery, this method without ajax, to grab this:
$('a.rss-links').live('click', function() {
$('#media').load(php_file);
});
Works like a charm. Then there's the google-api-script:
function initialize() {
var text = document.getElementById('media').innerHTML;
google.language.detect(text, function(result) {
if (!result.error && result.language) {
google.language.translate(text, result.language, "en", function(result) {
var translated = document.getElementById("media");
if (result.translation) {
translated.innerHTML = result.translation;
}
});
}
});
}
google.setOnLoadCallback(initialize);
It doesn't load the google-script. What can be done? Of course it does work if I put the text directly on the page, without loading another file. Using ajax and append(result) instead of .load doesn't make a difference. Any idea?
Thanks!
You can call that function after the .load() runs, as it's callback, like this:
$('a.rss-links').live('click', function() {
$('#media').load(php_file, initialize);
});
This will call the initialize function once the .load() has completed and the new content in the #media element is there and ready to translate.

Categories