I'm currently trying to dynamically add a new textAngular when clicking on the "Add" button.
As the first textAngular element is already present in the HTML page, the initialisation works fine using wysiwyg function and I'm able to use the toolbar and see the result in the corresponding textarea.
When I click on the "Add" button, I would like to have another textAngular editor along with its corresponding textarea, which I manage to have and to initialise but as soon as I do this the previous textAngular editor doesn't work and isn't linked to its textarea anymore. The toolbar is also unclickable.
I get the following result :
Here's the code of the index.html page :
<body>
<div id="mainContainer">
<div ng-app="textAngularTest" ng-controller="wysiwygeditor" class="container app">
<div name="cours" id="textbox1">
<h3>TextBOX 1</h3>
<div text-angular="text-angular" name="htmlcontent" ng-model="htmlcontent" ta-disabled="disabled"></div>
<h3>HTML BRUT 1</h3>
<textarea ng-model="htmlcontent" style="width: 100%"></textarea>
<br>
<button id="btn1" onclick="displayEditor()">Add</button>
</div>
</div>
</div>
<script src='https://ajax.googleapis.com/ajax/libs/angularjs/1.2.4/angular.min.js'></script>
<script src='https://ajax.googleapis.com/ajax/libs/angularjs/1.2.4/angular-sanitize.min.js'></script
<script src='https://cdnjs.cloudflare.com/ajax/libs/textAngular/1.1.2/textAngular.min.js'></script
</body>
<!-- partial -->
<script src="./textbox.js"></script>
The style.css:
.ta-editor {
min-height: 300px;
height: auto;
overflow: auto;
font-family: inherit;
font-size: 100%;
}
And here is the code of textbox.js :
angular.module("textAngularTest", ['textAngular']);
function wysiwygeditor($scope) {
console.log($scope);
$scope.orightml = 'Hello';
$scope.htmlcontent = $scope.orightml;
$scope.disabled = false;
};
function displayEditor() {
var number = Math.random();
document.getElementById("mainContainer").innerHTML += '<div ng-app="textAngularTest' + number + '" ng-controller="myController' + number + '" class="container app" id="mainContainer' + number + '"><h3>TextBox2</h3><div text-angular="text-angular" id="htmlcontent" name="htmlcontent" ng-model="htmlcontent" ta-disabled="disabled"></div><h3>HTML BRUT 2</h3><textarea ng-model="htmlcontent" style="width: 100%"></textarea>';
angular.module('textAngularTest' + number, ['textAngular'])
.controller('myController' + number, function ($scope) {
$scope.orightml = 'Hey';
$scope.htmlcontent = $scope.orightml;
});
angular.bootstrap(document.getElementById('mainContainer' + number), ['textAngularTest' + number]);
}
Explanation of the code : When I click on the "Add" button, I build the HTML of the new textAngular editor and its textarea giving them unique attributes so they are independant with the previous ones. When I add this new HTML content on the DOM, I initialise the new angular module with its own controller. But as soon as I do this and as I said it above, the previous textAngular editors don't work anymore.
Does anyone know how to reach that goal and initialise multiple textAngular editors without breaking the previous ones ?
Related
<div class="editable" contenteditable="true"></div>
<textarea name="markdown" class="markdown" /></textarea>//display none
new MediumEditor('.editable', {
extensions: {
markdown: new MeMarkdown(function (md) {
document.querySelector(".markdown").textContent = md;
}),
img: new imgButton()
}
$('.editable').append("<img src='abc' />");
I have a div use medium-editor & medium-editor markdown
when user type inside of .editable, textarea will sync.
I also have a button click, it will append an image into .editable
my problem is markdown only update when .editable keypress
so if I append text, textarea wont sync, unless I press any key inside of .editable again
anyone know how to tell markdown to update after append image
try this
function updateTextArea(index,editable){
var textarea = editable.parentNode.querySelector('textarea[medium-editor-textarea-id="' + editable.getAttribute('medium-editor-textarea-id') + '"]');
if (textarea) {
textarea.value = editable.innerHTML.trim();
}
}
$('.editable').append("<img src='abc' />");
$('.editable').each(updateTextArea);
The updateTextArea function will update a text area corresponds to editable area.
Here is the code I tried
var editor = new MediumEditor('.editable', {
buttonLabels: 'fontawesome'
});
function updateTextArea(index,editable){
var textarea = editable.parentNode.querySelector('textarea[medium-editor-textarea-id="' + editable.getAttribute('medium-editor-textarea-id') + '"]');
if (textarea) {
textarea.value = editable.innerHTML.trim();
}
}
$("#addImage").click(function(){
$('.editable').append("<img src='abc' />");
$('.editable').each(updateTextArea);
});
$('.editable').change(updateTextArea);
<link href="http://yabwe.github.io/medium-editor/bower_components/medium-editor/dist/css/themes/tim.min.css" rel="stylesheet"/>
<link href="http://netdna.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.css" rel="stylesheet"/>
<link href="http://yabwe.github.io/medium-editor/bower_components/medium-editor/dist/css/medium-editor.min.css" rel="stylesheet"/>
<script src="http://yabwe.github.io/medium-editor/bower_components/medium-editor/dist/js/medium-editor.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<h1>Medium Editor</h1>
<textarea class="editable medium-editor-textarea" name="markdown" id="markdown"><p>Textarea is now supported</p></textarea>
<input type="button" id="addImage" value="Add Image">
<input type="button" value="Alert textarea content" onclick="alert(document.getElementById('markdown').value)">
</div>
If you use the setContent() method of the editor (documentation here), this will allow you to add content and the editor will detect the change and fire all the proper events. This should include notifying the markdown extension that the content has changed and that should update the markdown.
So, instead of this:
$('.editable').append('<img src="abc" />');
Try this:
editor.setContent(editor.getContent() + '<img src="abc" />');
This also leverages the getContent() method (documentation here).
NOTE: These examples assume you're only using a single editor element for MediumEditor. If you are passing multiple elements into a single instance of MediumEditor, you may need to specify a value for the index parameter to both setContent() and getContent()
I am using a code snippet that I found to display a multipage form using visibility hidden.
There is a very good possibility that all of my problem stems from this method. That resource was from here:
http://www.devx.com/webdev/Article/10483/0/page/2
It is a fairly straightforward way to display multiple pages of a form...it probably was never intended to be able to allow printing.
<html>
<head>
<script type="text/javascript" src="jquery-1.10.2.min.js"></script>
<script language="JavaScript">
$.getScript("printThis.js", function(){
});
var currentLayer = 'page1';
function showLayer(lyr){
hideLayer(currentLayer);
document.getElementById(lyr).style.visibility = 'visible';
currentLayer = lyr;
}
function hideLayer(lyr){
document.getElementById(lyr).style.visibility = 'hidden';
}
function showValues(form){
var values = '';
var len = form.length - 1; //Leave off Submit Button
for(i=0; i<len; i++){
if(form[i].id.indexOf("C")!=-1||form[i].id.indexOf("B")!=-1)
continue;
values += form[i].id;
values += ': ';
values += form[i].value;
values += '\n';
}
alert(values);
}
</script>
<style>
body{
font: 10pt sans-serif;
}
.page{
position: absolute;
top: 10;
left: 100;
visibility: hidden;
}
</style>
</head>
<body>
<form id="multiForm" action="App1.php" method="POST" action="javascript:void(0)" onSubmit="showValues(this)" id="app">
<div id="page1" class="page" style="visibility:visible;">
Applicant Name: <input type="text" size="50" name="name1" >
</form>
<p><input type="button" id="C1" value="Continue" onClick="showLayer('page2')"></p>
</div>
<div id="page2" class="page">
This is Page 2
<br>
<input type="button" id="B1" value="Go Back" onClick="showLayer('page1')">
<input type="button" id="B2" value="Print App" onClick="$('#page1').printThis({})">
<br><br>
</div>
</form>
</body>
</html>
The "Print App" button is properly calling the printThis plugin. However, I get no content from the page1 DIV section. All that is printed is the normal header portion (Page 1 of 1) in the upper right and about:blank in lower left and date in lower right of pageā¦no content, which with my sample file should be Applicant Name input box.
I assume that this is because the DIV for page1 is set to "hidden" while the content of page2 is being displayed. If I substitute "page2" in the button call then I get the content from page2 as expected.
So...I guess what I am after is a way to temporarily change the DIV being referenced in the printThis button call to be visible just long enough to perform the page print.
Any ideas?
I'm the plugin author - you need to incorporate the print media query into your css.
This would also help users that select file > print or control + P, as it will show all form elements.
The print media query allows you to make styling changes specifically for the printed page.
Example:
#media print {
#page1, #page2 {
display: block;
visibility: visible;
position: relative;
}
}
You include this in your css.
Additionally, based on your above code - you have css and javascript inline in your page. You should consider moving both to an external files, for maintenance and improved code standards.
printThis won't work with your current setup, because the plugin looks for the container (selector) you have specified and any linked css in the head of the document.
So for the above, you can do the following:
<!-- move all of this to the bottom of the page for performance -->
<script type="text/javascript" src="jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="printThis.js"></script>
<script type="text/javascript" src="myJavascript.js"></script>
<!-- the above file is your javascript externalized, remove $.getScript, wrap in $(document).ready() -->
Then put this in your head:
<link type='text/css' rel='stylesheet' href='style.css'>
<!-- contains your css from the page, including the print media query -->
<body>
<div class="container">
Input
<form class="form-inline" role="form">
<div class="form-group">
<input type="text" class="form-control" id="getString" placeholder="Enter some string">
</div>
<button type="button" class="btn btn-primary" id="nowBtn">Now</button>
</form>
<br/>
<br/>
All Headings<textarea class="form-control" rows="6"></textarea>
</div>
</body>
I am using bootstrap and I will give some string in the form, when the Now button is pressed.
I should get the <h1> tag of that string in the textarea (i.e <h1>some string</h1> in the textarea with applied <h1> tag ).
Is it achievable? I want to use jQuery.
From your comments I've understood you'd like to set the font-size in the textarea to same size as h1 tag would have.
Since there's no h1 tag in your HTML, you need to create a one in the click event handler function of the #nowBtn:
var header = document.createElement('h1'),
size = window.getComputedStyle(header, null).fontSize; // Depending used browser and CSS, this returns for example 32px
Then you can set the font-size of textarea like this:
$('textarea').css('font-size', size);
A live demo at jsFiddle.
EDIT
As bfavaretto has mentioned, a cross-browser way would be to use jQuery to get the size of the h1:
size = $(header).css('font-size');
Have a look at this fiddle - it might be what you want.
http://jsfiddle.net/Nj7pj/
$(document).ready(function () {
$('.btn-primary').on('click', function () {
inputVal = $('#getString').val();
newTextAreaVal = "<h1>" + inputVal + "</h1>";
$('textarea').val(newTextAreaVal);
});
});
I think you can do
var h1 = $("h1.classYouWant");
$(".form-control").val( "<h1>" + h1.text() + "</h1>" );
if is dynamic the header (h1 or h2 or h3 )
you can do
var header = $(".classYouWant").get(0);
$(".form-control").val( header.outerHTML );
how to format the data caption
I am planning to display three different names for a single image
after i click the cube light box opens and the caption comes with div tag
but i wanted to display it one by one on the light box
its working fine without light box
$data = '';
$('[data-caption]').each(function(){
$data += '<div>' + $(this).data('caption') + '</div>';
});
$('body').append('<div id="more-info">' + $data + '</div>');
http://jsfiddle.net/ZrpLT/52/
<body>
<div class="row">
<div class="span10">
<div class="melonhtml5_gallery">
<div data-caption="<div>Paul Scholes</div> <div>Wayne Rooney</div> <div>Sir Alex Ferguson</div>" data-image="http://www.defie.co/designerImages/thumbnails/inventory.png"></div>
</div>
</div>
</body>
http://jsfiddle.net/ZrpLT/63/
This requires updating the Gallery class to use .html instead of .text when the caption is appended specifically in the onClick function on the line:
var m = $("<div>").addClass("caption").html(g ? g : ""),
As long as you are able to do that, you can get this to work for you.
I'd like to be able to convert specific textareas on a page to be ACE editors.
Does anyone have any pointers please?
EDIT:
I have the the editor.html file working with one textarea, but as soon as I add a second, the second isn't converted to an editor.
EDIT 2:
I decided to scrap the idea of having several, and instead open one up in a new window. My new predicament is that when I hide() and show() the textarea, the display goes awry. Any ideas?
As far as I understood the idea of Ace, you shouldn't make a textarea an Ace editor itself. You should create an additional div and update textarea using .getSession() function instead.
html
<textarea name="description"/>
<div id="description"/>
js
var editor = ace.edit("description");
var textarea = $('textarea[name="description"]').hide();
editor.getSession().setValue(textarea.val());
editor.getSession().on('change', function(){
textarea.val(editor.getSession().getValue());
});
or just call
textarea.val(editor.getSession().getValue());
only when you submit the form with the given textarea. I'm not sure whether this is the right way to use Ace, but it's the way it is used on GitHub.
Duncansmart has a pretty awesome solution on his github page, progressive-ace which demonstrates one simple way to hook up an ACE editor to your page.
Basically we get all <textarea> elements with the data-editor attribute and convert each to an ACE editor. The example also sets some properties which you should customize to your liking, and demonstrates how you can use data attributes to set properties per element like showing and hiding the gutter with data-gutter.
// Hook up ACE editor to all textareas with data-editor attribute
$(function() {
$('textarea[data-editor]').each(function() {
var textarea = $(this);
var mode = textarea.data('editor');
var editDiv = $('<div>', {
position: 'absolute',
width: textarea.width(),
height: textarea.height(),
'class': textarea.attr('class')
}).insertBefore(textarea);
textarea.css('display', 'none');
var editor = ace.edit(editDiv[0]);
editor.renderer.setShowGutter(textarea.data('gutter'));
editor.getSession().setValue(textarea.val());
editor.getSession().setMode("ace/mode/" + mode);
editor.setTheme("ace/theme/idle_fingers");
// copy back to textarea on form submit...
textarea.closest('form').submit(function() {
textarea.val(editor.getSession().getValue());
})
});
});
textarea {
width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.9/ace.js"></script>
<textarea name="my-xml-editor" data-editor="xml" data-gutter="1" rows="15"></textarea>
<br>
<textarea name="my-markdown-editor" data-editor="markdown" data-gutter="0" rows="15"></textarea>
You can have multiple Ace Editors. Just give each textarea an ID and create an Ace Editor for both IDS like so:
<style>
#editor, #editor2 {
position: absolute;
width: 600px;
height: 400px;
}
</style>
<div style="position:relative; height: 450px; " >
<div id="editor">some text</div>
</div>
<div style="position:relative; height: 450px; " >
<div id="editor2">some text</div>
</div>
<script src="ace.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-twilight.js" type="text/javascript" charset="utf-8"></script>
<script src="mode-xml.js" type="text/javascript" charset="utf-8"></script>
<script>
window.onload = function() {
var editor = ace.edit("editor");
editor.setTheme("ace/theme/twilight");
var XmlMode = require("ace/mode/xml").Mode;
editor.getSession().setMode(new XmlMode());
var editor2 = ace.edit("editor2");
editor2.setTheme("ace/theme/twilight");
editor2.getSession().setMode(new XmlMode());
};
</script>
To create an editor just do:
HTML:
<textarea id="code1"></textarea>
<textarea id="code2"></textarea>
JS:
var editor1 = ace.edit('code1');
var editor2 = ace.edit('code2');
editor1.getSession().setValue("this text will be in the first editor");
editor2.getSession().setValue("and this in the second");
CSS:
#code1, code2 {
position: absolute;
width: 400px;
height: 50px;
}
They must be explicitly positioned and sized. By show() and hide() I believe you are referring to the jQuery functions. I'm not sure exactly how they do it, but it cannot modify the space it takes up in the DOM. I hide and show using:
$('#code1').css('visibility', 'visible');
$('#code2').css('visibility', 'hidden');
If you use the css property 'display' it will not work.
Check out the wiki here for how to add themes, modes, etc... https://github.com/ajaxorg/ace/wiki/Embedding---API
Note: they do not have to be textareas, they can be whatever element you want.
For anyone that just wants a minimal, working example of using Ace from the CDN:
<!DOCTYPE html>
<html lang="en">
<body style="margin:0">
<div id="editor">function () {
console.log('this is a demo, try typing!')
}
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.01/ace.js" type="text/javascript" charset="utf-8"></script>
<script>
var editor = ace.edit("editor");
editor.setTheme("ace/theme/monokai");
editor.getSession().setMode("ace/mode/javascript");
document.getElementById("editor").style.height = "120px";
</script>
</body>
</html>