Element not found - javascript

I'm having a problem with an element not being found. I have this Ui-State from ui-router called AuthDesc, And for the templateURL I have this:
<head>
<link rel="stylesheet" type="text/css" href="stylesheets/normalize.css" media="screen">
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'>
</head>
<body>
<textarea id="SimpleMDE">
# This one autosaves!
By default, it saves every 10 seconds, but this can be changed. When this textarea is included
in a form, it will automatically forget the saved value when the form is submitted.
</textarea>
</body>
And for the Controller I have this:
(function(angular) {
var app = angular.module('ForumApp');
app.controller('authDescCtrl', ["$scope", "$mdDialog", "$state", "$firebaseObject","refService","currentAuth",authDescCtrl])
function authDescCtrl($scope, $mdDialog, $state, $firebaseObject,refService,currentAuth){
$scope.topic = $firebaseObject(refService.ref().child("Topics"))
$scope.goToPerson = function(person, event) {
$mdDialog.show(
$mdDialog.alert()
.title('Navigating')
.textContent('Inspect ' + person)
.ariaLabel('Person inspect demo')
.ok('Neat!')
.targetEvent(event)
);
};
$scope.goToTopic = function(avatar, date, email, title, uid, username, value) {
$state.go("authHome.topic", {
"AVATAR": avatar,
"DATE": date,
"EMAIL": email,
"TITLE": title,
"UID": uid,
"USERNAME": username,
"VALUE": value
})
}
}
new SimpleMDE({
element: document.getElementById("SimpleMDE"),
spellChecker: true,
autosave: {
enabled: true,
unique_id: "SimpleMDE",
},
});
})(angular);
You can see in the last couple lines of controller that there is a new MDE Generator, however the console states that the element cannot be found:
SimpleMDE: Error. No element was found.
I am confused. There is a textarea named SimpleMDE, but I do not know how is it not finding it. Here is a link to the code in the wild: https://ide.c9.io/amanuel2/fourm2
I am afraid that the Javascript loads before the HTML, so it doesn't recognize the texarea with ID SimpleMDE.

Wrap your widget initialization in window.onload event handler
For angular controller use:
angular.element(document).ready(function () {
new SimpleMDE({
element: document.getElementById("SimpleMDE"),
spellChecker: true,
autosave: {
enabled: true,
unique_id: "SimpleMDE",
},
});
});

you can do it also with this code :
$timeout(function() {
new SimpleMDE({
element: document.querySelector("#SimpleMDE"),
spellChecker: true,
autosave: {
enabled: true,
unique_id: "SimpleMDE",
}
});
});

Related

Can I use a JavaScript inline edit library in my Angular 2 project?

This is the library:
http://www.jqueryscript.net/demo/jQuery-jQuery-UI-Based-Content-editable-Widget-contenteditable-js/
This is used for inline editing on html pages. My code on HTML page is shown below -
<script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"></script>
<script src="http://sco7.com/del/jquery-contenteditable.js"></script>
<script>
$("#basic").editable();
$("#paragraph").editable({
multiline: true,
autoselect: true
});
$("#alert").editable({
multiline: true,
saveDelay: 800,
save: function(e, ui) {
alert("Saving actual content: " + ui.content);
}
});
$("#scalable").editable({
multiline: true
});
$("#nonempty").editable({
multiline: true,
saveDelay: 600,
autoselect: true,
save: function(e, ui) {
alert("Saving actual content: " + ui.content);
},
validate: function(e, ui) {
return ui.content !== "";
}
});
$("#complex").editable({
content: "a", //only link <a> is editable
autoselect: true,
save: function(e, ui) {
alert("New link: " + ui.content);
},
validate: function(e, ui) {
return ui.content !== ""
}
});
</script>
<p id="alert">
This sample fires alert each time changed content is supposed to be saved (e.g. sent to server).
It is currently set up to fire after 800ms delay of not typing anything.
</p>
I want to use this in my Angular project. Can I use this as it is? Like the <p id="alert">, do I need to do this in a similar way?
You can use contenteditable attribute or set designmode on html elements to make it editable. For more information you can refer Mozilla Developer Network
$(document).ready(function(){
$("#alert").keyup(function(){
console.info($(this).html()); // prints edited text
console.info("Inner Html---->"+$("#container").html()); // prints html of edited text
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<p id="alert" contenteditable="true">
EDIT ME
</p>
</div>
Example Code
<div #container>
<p #alert contenteditable="true">EDIT ME</p>
</div>
Script File
import {ElementRef,Renderer2} from '#angular/core';
#ViewChild('container') el:ElementRef;
constructor(private rd: Renderer2) {}
ngAfterViewInit() {
this.el.nativeElement.innerHtml;
}
Option 1: Add scripts directly
You can add that scrips directly in your page using $("selector")
index.html
<h2 id="basic">
Basic examples. Click on me to edit. Press 'ESC' or 'Tab' or click anywhere else to finish editing.
</h2>
<!--do not forget add scripts-->
<!--basic scripts-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.js"></script>
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"></script>
<script src="http://www.jqueryscript.net/demo/jQuery-jQuery-UI-Based-Content-editable-Widget-contenteditable-js/src/jquery-contenteditable.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.3/angular.js"></script>
<!--your scripts-->
<script src="app.js"></script>
<script src="your-editable.js"></script>
app.js
var app = angular.module("app", []);
your-editable.js
$("#basic").editable();
Options 2: convert to directive
There you can convert the editable to directive to have more access on elements
index.html
<!--options: basic, paragraph, alert, scalable, nonempty, complex-->
<h2 content="basic">
Basic examples. Click on me to edit. Press 'ESC' or 'Tab' or click anywhere else to finish editing.
</h2>
<!--do not forget add scripts-->
<!--basic scripts-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.js"></script>
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"></script>
<script src="http://www.jqueryscript.net/demo/jQuery-jQuery-UI-Based-Content-editable-Widget-contenteditable-js/src/jquery-contenteditable.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.3/angular.js"></script>
<!--your scripts-->
<script src="app.js"></script>
<script src="directive.js"></script>
app.js
var app = angular.module("app", []);
directive.js
Also you can improve this directive to get more options from developers
app.directive("content", function () {
return {
restrict: "A",
scope: {
content: "#"
},
link: function ($scope, $element) {
switch ($scope.content) {
case "basic":
$element.editable();
break;
case "paragraph":
$element.editable({
multiline: true,
autoselect: true
});
break;
case "alert":
$element.editable({
multiline: true,
saveDelay: 800,
save: function (content) {
alert("Saving actual content: " + content);
}
});
break;
case "scalable":
$element.editable({
multiline: true
});
break;
case "nonempty":
$element.editable({
multiline: true,
saveDelay: 600,
autoselect: true,
save: function (content) {
alert("Saving actual content: " + content);
},
validate: function (content) {
return content !== "";
}});
break;
case "complex":
$element.editable({
content: "a",
autoselect: true,
save: function (content) {
alert("New link: " + content);
},
validate: function (content) {
return content !== "";
}});
break;
default:
$element.editable();
}}}});

handle JavaScript plugin through angular js

I am new to AngularJS. I am developing a music app through AngularJS.
For HTML5 player I am using this: https://github.com/DIYgod/APlayer.
How to wrap aplyer inside angular so i only call directive to initialise player.
ex- INIT PLAYER
<div id="player1" class="aplayer"></div>
JS
var ap = new APlayer({
element: document.getElementById('player1'), // Optional, player element
narrow: false, // Optional, narrow style
autoplay: true, // Optional, autoplay song(s), not supported by mobile browsers
showlrc: 0, // Optional, show lrc, can be 0, 1, 2, see: ###With lrc
mutex: true, // Optional, pause other players when this player playing
theme: '#e6d0b2', // Optional, theme color, default: #b7daff
mode: 'random', // Optional, play mode, can be `random` `single` `circulation`(loop) `order`(no loop), default: `circulation`
preload: 'metadata', // Optional, the way to load music, can be 'none' 'metadata' 'auto', default: 'auto'
listmaxheight: '513px', // Optional, max height of play list
music: { // Required, music info, see: ###With playlist
title: 'Preparation', // Required, music title
author: 'Hans Zimmer/Richard Harvey', // Required, music author
url: 'http://7xifn9.com1.z0.glb.clouddn.com/Preparation.mp3', // Required, music url
pic: 'http://7xifn9.com1.z0.glb.clouddn.com/Preparation.jpg', // Optional, music picture
lrc: '[00:00.00]lrc here\n[00:01.00]aplayer' // Optional, lrc, see: ###With lrc
}
});
I am trying to use it by directive and pass template as
<div id="player1" class="aplayer"></div>
but I don't know how to add Aplayer JS to Angular.
You can initialize APlayer in a directive this way.
Use either <div class="aplayer"></div> or <div aplayer></div>
Attributes are declared using kebab-case in html code but you have to use camelCase to access them in directive code.
Note: data prefix is not required here. It's only used to prevent native html attribute collision.
(function() {
'use strict';
angular.module('app', []);
angular
.module('app')
.directive('aplayer', aplayer);
function aplayer() {
return {
restrict: 'AC',
link: function(scope, element, attrs) {
// `element` is the angular element the directive is attached to
// APlayer need the native one
var nativeElement = element[0];
var ap1 = new APlayer({
element: nativeElement,
narrow: false,
autoplay: true,
showlrc: false,
mutex: true,
theme: '#e6d0b2',
preload: 'metadata',
mode: 'circulation',
music: {
title: attrs["playerTitle"],
author: attrs["playerAuthor"],
url: attrs["playerUrl"],
pic: attrs["playerPic"]
}
});
ap1.on('play', function() {
console.log('play');
});
ap1.on('play', function() {
console.log('play play');
});
ap1.on('pause', function() {
console.log('pause');
});
ap1.on('canplay', function() {
console.log('canplay');
});
ap1.on('playing', function() {
console.log('playing');
});
ap1.on('ended', function() {
console.log('ended');
});
ap1.on('error', function() {
console.log('error');
});
}
};
}
})();
<!doctype html>
<html lang="en" ng-app="app">
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.4/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/aplayer/1.6.0/APlayer.min.js"></script>
<script src="script.js"></script>
</head>
<body>
<div class="aplayer"
data-player-title="Preparation"
data-player-author="Hans Zimmer/Richard Harvey"
data-player-url="http://devtest.qiniudn.com/Preparation.mp3"
data-player-pic="http://devtest.qiniudn.com/Preparation.jpg"></div>
</body>
</html>

Change style programmatically ionic toast

I have the following ionicToast into my popup:
onTap: function(e) {
var nombre = scope.data.nombre;
var telefono = scope.data.telefono;
if (nombre.length > 0 && telefono.toString().length > 0) {
scope.data.nombre = nombre;
scope.data.telefono = telefono;
return scope.data;
} else {
ionicToast.show('Debe completar todos los campos.', 'bottom', true, 2500);
e.preventDefault();
}
}
The toast works perfect. But I wanna differentiate when the toast is an error or a success message.
The question is: ¿How can I change the style of the toast programmatically?
Because Sometimes I need the background red (for error message) and sometimes i need it green (for success message).
Also I don't have this toast in my .HTML file, so I can't set a specific style
This is my style that I defined:
.toast-container-error{
background-color: red;
}
.toast-container-success{
background-color: green;
}
Thanks for helping me!
//EDIT//
Using toastr for my custom toast, it not showing on Android devices
index.html
<link href="bower_components/toastr/toastr.css" rel="stylesheet">
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js" ></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/js/toastr.min.js"></script>
<link href="//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/css/toastr.min.css" rel="stylesheet" />
Agenda.service (where I wanna use it)
agendaService.$inject = ['remoteDataService','$q', '$ionicPopup', '$rootScope', 'ionicDatePicker'];
/* #ngInject */
function agendaService(remoteDataService,$q, $ionicPopup, $rootScope, ionicDatePicker){
var agendaComplejo = [];
var service = {
obtenerAgenda: obtenerAgenda,
cargarNuevoTurno: cargarNuevoTurno,
abrirAgenda: abrirAgenda
};
toastr.options = {
"closeButton": true,
"debug": true,
"newestOnTop": false,
"progressBar": false,
"positionClass": "toast-bottom-full-width",
"preventDuplicates": false,
"onclick": null,
"showDuration": "300",
"hideDuration": "1000",
"timeOut": "5000",
"extendedTimeOut": "1000",
"showEasing": "swing",
"hideEasing": "linear",
"showMethod": "fadeIn",
"hideMethod": "fadeOut"
}
return service;
function cargarNuevoTurnoPopup() {
var scope = $rootScope.$new();
scope.data = {
nombre: '',
telefono: ''
};
return {
templateUrl: 'scripts/complejo/agenda/nuevo-turno.html',
title: "Nuevo Turno",
scope: scope,
buttons: [{
text: 'Cancelar',
onTap: function(e) {
scope.data.canceled = true;
return scope.data;
}
}, {
text: '<b>Guardar</b>',
type: 'button-positive',
onTap: function(e) {
var nombre = scope.data.nombre;
var telefono = scope.data.telefono;
if (nombre.length > 0 && telefono.toString().length > 0) {
scope.data.nombre = nombre;
scope.data.telefono = telefono;
return scope.data;
} else {
toastr["error"]("Debe completar todos los campos.")
e.preventDefault();
}
}
}]
};
}
Also, I generate the apk with the following command:
ionic build android --debug
It is possible but you have to overide the native style of the component to do this. In our project we use Toastr that give you standard method to display an error or an info and that can be overide more easily.
To include it in your project only include the js and the css
<script src="toastr.js"></script>
<link href="toastr.css" rel="stylesheet"/>
Then the api allow you to raise an info or an error
toastr.info('yourmessage')
toastr.error('your message')
toastr.success('your message')
You can found a demo here:
http://codeseven.github.io/toastr/demo.html

MathJax not Rendering With Angular

The issue I have is this:
On my website, I pull my blog content from an external source which, the first time it's called upon to display, has to use a HTTP request to get. Also, the blog posts are written in Markdown, and I have to parse this to HTML.
I have this controller that goes out and gets the posts from github, decodes them, and parses them into HTML:
app.controller('content', function ($scope, github, html) {
github.getAllContent().then(function (res) {
var files = [];
res.data.forEach(function (obj) {
github.getFile(obj.path).then(function (res) {
res.data.content = marked(window.atob(res.data.content));
res.data.name = res.data.name.slice(0, res.data.name.indexOf('.'));
files.push(res.data);
})
});
$scope.files = files;
});
$scope.renderHtml = html.renderHtml;
});
html is this service
app.service('html', function ($sce) {
this.renderHtml = function (string) {
return $sce.trustAsHtml(string);
}
});
that allows me to insert the HTML into each HTML element like this: <elem>ng-bind-html="renderHtml(info) </elem>".
Whenever I do this, however, LaTeX content isn't rendered. I have configured MathJax to recognize $ ... $ as delimiters, but no matter what happens, I can't seem to get anything to render. I have even called the MathJax.Hub.Typeset() function or set the typeset callback in the MathJax.Hub.Queue function and it doesn't work. Is this because of the markdown parser I use or how the data is encoded? Or is it just a matter of typesetting the MathJax at the right time?
In this project, I use Angular ui-router, if that has anything to do with it.
I have used this (mathjaxBind.directive.js) directive in my project for MathJax and its working for me:
Plunker
mathjaxBind.directive.js
'use strict';
MathJax.HTML.Cookie.Set("menu", {});
MathJax.Hub.Config({
skipStartupTypeset: true,
messageStyle: "none",
extensions: ["tex2jax.js", "mml2jax.js", "MathML/content-mathml.js", "MathML/mml3.js"],
jax: ["input/MathML", "input/TeX", "output/SVG", "output/HTML-CSS", "output/NativeMML", "output/CommonHTML"],
"HTML-CSS": {
availableFonts: [],
styles: {".MathJax_Preview": {visibility: "hidden"}},
showMathMenu: false
},
"SVG": {
availableFonts: [],
styles: {".MathJax_Preview": {visibility: "hidden"}},
showMathMenu: false
},
"NativeMML": {
availableFonts: [],
styles: {".MathJax_Preview": {visibility: "hidden"}},
showMathMenu: false
},
"CommonHTML": {
availableFonts: [],
styles: {".MathJax_Preview": {visibility: "hidden"}},
showMathMenu: false
}
});
MathJax.Hub.Register.StartupHook("HTML-CSS Jax Ready", function () {
var FONT = MathJax.OutputJax["HTML-CSS"].Font;
FONT.loadError = function (font) {
MathJax.Message.Set("Can't load web font TeX/" + font.directory, null, 2000);
document.getElementById("noWebFont").style.display = "";
};
FONT.firefoxFontError = function (font) {
MathJax.Message.Set("Firefox can't load web fonts from a remote host", null, 3000);
document.getElementById("ffWebFont").style.display = "";
};
});
(function (HUB) {
var MINVERSION = {
Firefox: 3.0,
Opera: 9.52,
MSIE: 6.0,
Chrome: 0.3,
Safari: 2.0,
Konqueror: 4.0,
Unknown: 10000.0 // always disable unknown browsers
};
if (!HUB.Browser.versionAtLeast(MINVERSION[HUB.Browser] || 0.0)) {
HUB.Config({
jax: [], // don't load any Jax
extensions: [], // don't load any extensions
"v1.0-compatible": false // skip warning message due to no jax
});
setTimeout('document.getElementById("badBrowser").style.display = ""', 0);
}
})(MathJax.Hub);
MathJax.Hub.Register.StartupHook("End", function () {
var HTMLCSS = MathJax.OutputJax["HTML-CSS"];
if (HTMLCSS && HTMLCSS.imgFonts) {
document.getElementById("imageFonts").style.display = ""
}
});
angular.module('fsaApp')
.directive('mathjaxBind', function () {
return {
restrict: "A",
controller: ["$scope", "$element", "$attrs", function ($scope, $element, $attrs) {
$scope.$watch($attrs.mathjaxBind, function (value) {
//$($element).parent().find('math').wrap("<script type='math/mml'></script>");
$element.html(value);
MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
});
}]
};
});
Controller:
app.controller('MainCtrl', function($scope) {
$scope.info='<script type=\"math/mml\"><math>\n<mstyle displaystyle=\"true\">\n<mtext> N </mtext>\n<msub>\n<mrow>\n<mtext> O </mtext>\n</mrow>\n<mrow>\n<mn> 2 </mn>\n</mrow>\n</msub>\n</mstyle>\n</math></script>';
$scope.info2='<script type=\"math/mml\"><math>\n<mstyle displaystyle=\"true\">\n<mtext> C </mtext>\n<msub>\n<mrow>\n<mtext> H </mtext>\n</mrow>\n<mrow>\n<mn> 4 </mn>\n</mrow>\n</msub>\n</mstyle>\n</math></script>';
});
Library:
<script type="text/javascript" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
in HTML:
<div mathjax-bind="info"></div>
<div mathjax-bind="info2"></div>

Javascript Variable Scope with KendoUI Components

I am trying to capture the text from a Kendo AutoComplete component and save it to a variable to later use in other components. The code is below and I have a link to the code at jsbin.com. Note: the code jsbin.com does not work for me in IE9, Firefox and Chrome work fine.
I attach my onSelect function fires when a selecton is made in the autoComplete control. I then assign the dataItem to my variable "selectedGeoname". I successfully write the object's text property to an element on screen and I use an alert to confirm that selectedGeoname is populated by the object.
However, when I later try to use the variable to pass the value to another component, the variable is null. I instantiate both components and declare the variable inside $(document)ready. I would have to believe that this is all ablout scope so perhaps one of you javascript wizards can help poor old .Net guy to fix this code.
Thanks,
Greg
HTML as follows:
<!DOCTYPE html>
<html>
<head>
<link href="http://cdn.kendostatic.com/2012.2.710/styles/kendo.common.min.css"
rel="stylesheet" type="text/css" />
<link href="http://cdn.kendostatic.com/2012.2.710/styles/kendo.default.min.css"
rel="stylesheet" type="text/css" />
<link href="http://cdn.kendostatic.com/2012.2.710/styles/kendo.dataviz.min.css"
rel="stylesheet" type="text/css" />
<link href="http://cdn.kendostatic.com/2012.2.710/styles/kendo.mobile.all.min.css"
rel="stylesheet" type="text/css" />
<script src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
<script src="http://cdn.kendostatic.com/2012.2.710/js/kendo.all.min.js"></script>
<title></title>
</head>
<body>
<p>
<label for="customer">Choose a customer:</label>
<input id="customer" />
<div id="result"></div>
</p>
<p>
<label for="stores">Choose a store:</label>
<input id="stores" />
</p>
<script type="text/javascript">
$(document).ready(function () {
$("#customer").kendoAutoComplete({
dataTextField: "name",
dataSource: {
serverFiltering: true,
transport: {
read: {
url: "http://ws.geonames.org/searchJSON",
dataType: "json",
data: {
featureClass: "P",
style: "full",
maxRows: 12,
name_startsWith: function () {
return $("#customer").val();
}
}
}
},
schema: {
data: "geonames"
}
},
filter: "startswith",
placeholder: "Select Customer...",
height: 500,
suggest: true,
select: onSelect
});
var selectedGeoname;
function onSelect(e) {
var dataItem = this.dataItem(e.item.index());
selectedGeoname = dataItem;
//output
$("#result").html(selectedGeoname.name);
alert(selectedGeoname);
}
$("#stores").kendoDropDownList({
autoBind: false,
enable: true,
dataTextField: "StoreName",
dataValueField: "StoreId",
dataSource: {
serverFiltering: true,
transport: {
read: {
url: '#Url.Action("JsonGetStores", "Home")',
data: {
customer: selectedGeoname
}
}
}
}
});
});
</script>
</body>
</html>
You can use this code as your onSelect to achieve this:
function onSelect(e) {
selectedGeoname = this.value();
//output
$("#result").html(selectedGeoname.name);
alert(selectedGeoname);
}
When called from the context of the AutoComplete object this.value() can be used to get the value of the AC input element.
If you need to access the current value of the variable outside of the scope you can use this method: $("#customer").data("kendoAutoComplete").value().
Hope this helps!

Categories