problem appending getJSON at the end of my webpage - javascript

I've been stuck for days with an issue that I think is really easy for anyone.
I'm currently working on building my own "fake" professional webpage using glitch. I managed to put everything I wanted on it using HTML and I stylized it using CSS. So far so good, it looks like a real webpage.
At the end of this web page I want to put a "contact us" section and that's where it get tricky. What I want to do is use Javascript and RANDOM USER GENERATOR to replicate professionals that viewers can contact.
Each professional (10 in total) has a picture and by putting their mouse on each profile, viewers can see the first name and name (maybe I'll add phone number and email address later) of the professional.
I pretty much got that part covered, here is my code,
professional.js :
$.getJSON( "https://randomuser.me/api/?results=10", function( json ) {
console.log( json ); // print data in the console
var users = json.results; // results is an array of users
// store the "body" of our document inside a jQuery object
var body = $( "body" );
// loop through each user in our "users" array
for( var i = 0; i< users.length; i = i + 1 ) {
// store the current user in a variable
var user = users[ i ];
// we create a container for the user image and its data
var imgContainer = $( "<div class='img-container'></div>" );
// we create a jQuery object with an "img" element
var img = $( "<img>" );
// set its "src" attribute with a jquery method
img.attr( "src", user.picture.large );
// and append this element to our container
imgContainer.append( img );
// we create a jQuery object with a new paragraph
var userData = $( "<p class='user-data'></p>" );
// set its inner HTML with jQuery
userData.html( user.name.first + "<br>" + user.name.last );
// and append this to our container
imgContainer.append( userData );
// finally we append the container to the "body" of our document
body.append( imgContainer );
}
} );
Here is the style used with CSS :
* {
margin: 0;
padding: 0;
}
body {
background: black;
text-align: center;
line-height: 0;
}
.img-container {
display: inline-block;
position: relative;
overflow: hidden;
cursor: pointer;
}
.user-data {
position: absolute;
bottom: 0;
left: -120%;
width: 100%;
height: 50px;
background: rgba( 0, 0, 0, 0.3 );
padding-left: 10px;
text-align: left;
color: white;
font-family: sans-serif;
font-size: 20px;
line-height: 24px;
transition: left 0.3s ease-in;
}
.img-container:hover .user-data {
left: 0;
}
The problem is that when I try to "import" my java to my document it "erase" my webpage. It's like it comes above it and hide all the content. I think that the problem comes from the fact that my .js file append the content in the "body" of my web page (body.append( imgContainer );).
So my question is, how can I append my .js project using getJSON into my webpage without erasing everything. I wish to append it at the very bottom of my webpage. It seems silly but I've been searching four hours and couldn't find any answer.
Many thanks in advance.

Related

Why does the animated text 'stutter' occasionally as it transitions across the screen?

I've been trying to make a simple marquee using velocity.js that will scroll multiple messages across the screen one after the other.
I've put together a working example but I'm experiencing issues with the text sporadically 'stuttering' as it moves.
Using the developer tools in Chrome I can see that I get a drop in framerate when this occurs but I can't figure out why:
There doesn't seem to be anything unusual such as high memory usage and the computer is doing little else.
The issue also occurs in both Internet Explorer and Mozilla Firefox so it's not a browser issue.
How can I diagnose/resolve the issue with stuttering animations, or is this situation to be expected?
The sample below should recreate the issue although as the stuttering is random you'd need to watch it carefully to see what I mean.
$(document).ready(function() {
// WINDOW WIDTH
var width = $(window).width();
// MESSAGE QUEUE
var messages = [
"This is the first message",
"This is the second message",
"This is the last message"
];
// APPEND EACH MESSAGE TO CONTAINER AND HIDE OFF RIGHT OF SCREEN
$.each(messages, function(index, value) {
$("#container").append( "<div id=\"message" + index + "\" class=\"message\">" + value + "</div>" );
$("#message" + index).css({left: width});
});
// START ANIMATION WITH FIRST MESSAGE
AnimateNext(0, messages.length - 1);
});
function AnimateNext(current) {
// GET THE CURRENT MESSAGE
var message = $("#message" + current);
// MOVE MESSAGE TO THE RIGHT OFF SCREEN POSITION
message.css({left: $(window).width()});
// MOVE MESSAGE TO THE LEFT AND OFF SCREEN
message.velocity({left: -message.width()}, 10000, "linear", function() {
// INCREASE CURRENT INDEX
current >= 2 ? current = 0 : current = current + 1;
// ANIMATE NEXT ITEM
AnimateNext(current);
});
};
html, body {
font-family: Helvetica, Arial, "Times New Roman";
height: 100%;
width: 100%;
padding: 0;
margin: 0;
background-color: black;
overflow: hidden;
}
#container {
height: 200px;
width: 100%;
background-color: darkred;
}
.message {
position: absolute;
color: white;
font-size: 100px;
white-space: nowrap;
}
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.5.0/velocity.min.js"></script>
<div id="container">
</div>
JSFiddle in case anyone wants to fork it

How to create buttons and text enters with javascript in scripts. (Tampermonkey)

Im creating scripts (Javascript) using tamper monkey. The most used scripts on this platform create buttons and boxes to enter text on the website they want the script to happen (for example creating an extra button on google.com and when clicked it does a function). I have a few examples like a you tube to mp4 converter thats directly on the youtube website itself. (If this helps) If this requires HTML or CSS In not really familiar with those languages.
How do I create buttons and text boxes like this script to put into my JavaScript code?
Script
This code will create a button (Add a JavaScript button using Greasemonkey or Tampermonkey?) :
// ==UserScript==
// #name _Adding a live button
// #description Adds live example button, with styling.
// #include https://stackoverflow.com/questions/*
// #grant GM_addStyle
// ==/UserScript==
/*--- Create a button in a container div. It will be styled and
positioned with CSS.
*/
var zNode = document.createElement ('div');
zNode.innerHTML = '<button id="myButton" type="button">'
+ 'For Pete\'s sake, don\'t click me!</button>'
;
zNode.setAttribute ('id', 'myContainer');
document.body.appendChild (zNode);
//--- Activate the newly added button.
document.getElementById ("myButton").addEventListener (
"click", ButtonClickAction, false
);
function ButtonClickAction (zEvent) {
/*--- For our dummy action, we'll just add a line of text to the top
of the screen.
*/
var zNode = document.createElement ('p');
zNode.innerHTML = 'The button was clicked.';
document.getElementById ("myContainer").appendChild (zNode);
}
//--- Style our newly added elements using CSS.
GM_addStyle ( multilineStr ( function () {/*!
#myContainer {
position: absolute;
top: 0;
left: 0;
font-size: 20px;
background: orange;
border: 3px outset black;
margin: 5px;
opacity: 0.9;
z-index: 222;
padding: 5px 20px;
}
#myButton {
cursor: pointer;
}
#myContainer p {
color: red;
background: white;
}
*/} ) );
function multilineStr (dummyFunc) {
var str = dummyFunc.toString ();
str = str.replace (/^[^\/]+\/\*!?/, '') // Strip function () { /*!
.replace (/\s*\*\/\s*\}\s*$/, '') // Strip */ }
.replace (/\/\/.+$/gm, '') // Double-slash comments wreck CSS. Strip them.
;
return str;
}

Calculating Paint Times of Elements In All Browsers

I am trying to calculate the elapsed time an element is painted onto the DOM from the start time of the script or if the specific element was even painted at all. I am inserting a background gradient to the HTML, and then using javascript to create random (clouds, which are just large periods with a text shadow) in multiple places across the screen (some negative, some positive, some within scope, some outside of scope).
Currently my code looks like this:
<html>
<head>
<style>
.container {
border: 1px solid #3b599e;
overflow: hidden;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#315d8c', endColorstr='#84aace'); /* for IE */
background: -webkit-gradient(linear, left top, left bottom, from(#315d8c), to(#84aace)); /* for webkit browsers */
background: -moz-linear-gradient(top, #315d8c, #84aace); /* for firefox 3.6+ */
}
.cloud {
color: #fff;
position: relative;
font: 100% "Times New Roman", Times, serif;
text-shadow: 0px 0px 10px #fff;
line-height: 0;
}
</style>
<script type="text/javascript">
function cloud(){
var b1 = "<div class=\"cloud\" style=\"font-size: ";
var b2 = "px; position: absolute; top: ";
document.write(b1+"300px; width: 300px; height: 300"+b2+"34px; left: 28px;\">.<\/div>");
document.write(b1+"300px; width: 300px; height: 300"+b2+"46px; left: 10px;\">.<\/div>");
document.write(b1+"300px; width: 300px; height: 300"+b2+"46px; left: 50px;\">.<\/div>");
document.write(b1+"400px; width: 400px; height: 400"+b2+"24px; left: 20px;\">.<\/div>");
}
function clouds(){
var top = ['-80','80','240','400'];
var left = -10;
var a1 = "<div style=\"position: relative; top: ";
var a2 = "px; left: ";
var a3 = "px;\"><script type=\"text/javascript\">cloud();<\/script><\/div>";
for(i=0; i<8; i++)
{
document.write(a1+top[0]+a2+left+a3);
document.write(a1+top[1]+a2+left+a3);
document.write(a1+top[2]+a2+left+a3);
document.write(a1+top[3]+a2+left+a3);
if(i==4)
{
left = -90;
top = ['0','160','320','480'];
}
else
left += 160;
}
}
</script>
</head>
<body style="margin:0;padding:0;">
<div class="container" style="width: 728px; height: 90px;">
<script>clouds();</script>
</div>
</body>
</html>
I then run this inside of an iframe, trying to detect if the visible elements are being painted first, or if they are being painted in display order (pretty much, is the ad currently being viewed, or is it out of view).
I have not found a solid technique yet that works crossbrowser to detect this. In chrome, I was able to see it work when pasting images, as the visible images got an onload event fired first (even though they were at the end of the DOM), but this wasn't the case for firefox or IE.
I'm really not sure what you're after here. You said: "(pretty much, is the ad currently being viewed, or is it out of view)." But that is a bit cryptic.. What "ad" are you talking about?
In trying to figure out what you were trying to accomplish I pretty much rewrote your script to do exactly the same as before and it does an alert of the elapsed time as well as logs the time for each cloud in the console. It's not a good way to calculate execution time (which is what it seemed to me like you were after..).
NOTE: The only reason I rewrote everything was so I myself could make better sense of it in preparation for a response from you. Once I know exactly what you want I will edit my answer.
<style>
.container {
width: 728px;
height: 90px;
border: 1px solid #3b599e;
overflow: hidden;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#315d8c', endColorstr='#84aace'); /* for IE */
background: -webkit-gradient(linear, left top, left bottom, from(#315d8c), to(#84aace)); /* for webkit browsers */
background: -moz-linear-gradient(top, #315d8c, #84aace); /* for firefox 3.6+ */
}
.cloud {
color: #fff;
position: absolute;
font: 100% "Times New Roman", Times, serif;
text-shadow: 0px 0px 10px #fff;
line-height: 0;
}
.cloud-container {
position: relative;
}
</style>
<div class="container"></div>
<script type="text/javascript">
// for IE
if (!window.console) window.console = {};
if (!window.console.log) window.console.log = function () { };
var pxTop = ['34px', '46px', '46px', '24px'],
pxLeft = ['28px', '10px', '50px', '20px'],
size = ['300px', '300px', '300px', '400px'];
function cloud(callback) {
var df = document.createDocumentFragment(),
node;
for (var i = 0; i < 4; i++) {
node = document.createElement('div');
node.className = 'cloud';
node.style.fontSize = size[i];
node.style.width = size[i];
node.style.height = size[i];
node.style.top = pxTop[i];
node.style.left = pxLeft[i];
node.innerHTML = '.';
df.appendChild(node);
}
callback && callback();
return df;
}
function clouds(containerId, callback) {
var top = ['-80','80','240','400'],
left = -10,
container = document.querySelector(containerId);
container.appendChild(document.createTextNode("\n"));
for (i = 0; i < 8; i++) {
var div = document.createElement('div');
div.className = 'cloud-container';
div.style.top = top[0] + 'px';
div.style.left = left + 'px';
console.log('About to start making a cloud', new Date().getMilliseconds());
div.appendChild(cloud(function() {
console.log('Finished making cloud', new Date().getMilliseconds());
}));
container.appendChild(div);
container.appendChild(document.createTextNode("\n")); // newline for view source
if (i == 4) {
left = -90;
top = ['0','160','320','480'];
} else {
left += 160;
}
}
callback && callback();
}
var start = new Date().getMilliseconds();
clouds('.container', (function() {
var end = new Date().getMilliseconds(),
time = end - this;
alert('Execution time: ' + time);
}).bind(start));
</script>
You should use console API for measuring timings more accurately (and avoid DIY spaghetti):
console.time("Doing stuff");
/*le code*/
console.timeEnd("Doing stuff");
This functionality is available natively in Chrome and Firefox; it can also be polyfilled on other browsers like IE but will not be as precise.
Note that using Date is not appropriate/intended for benchmarking:
Depending on the browser and OS, Date's resolution can be as low as 15 milliseconds.
Date based on system time, isn't ideal. Most systems run a daemon which regularly synchronizes the time... tweaked a few milliseconds every 15-20 minutes. At that rate about 1% of 10 second intervals measured would be inaccurate.
Update:
Hold on, are you trying to measure browser paints' timing and order? These can't be monitored through js (ok, it's possible to have a js API, but ultimately it has to be benchmarked in the browser engine, so no js polyfills).
Rule of thumb is elements will be painted in parse order, with re-paints/re-flows triggered by content styling - like backgrounds being loaded, additional css rules becoming available or content of different size being added into a table column.
Html5rocks on profiling long paint times might get you started in the right direction.

Adding Event Listeners in JavaScript

I have a JavaScript and divs defined using CSS3 classes. I need to add event listener to specific class div but it is not getting bound to it.
e.g.:
this._incrementEnabled = document.createElement('div');
this._incrementEnabled.className = this._incrementButtonProperties.enabledClass;
this.divElt.appendChild(this._incrementEnabled);
if (this.properties.incrementButtonConfig.enabled == null) {
this.properties.incrementButtonConfig.enabled = false;
}
this.setIncrementEnabled(this.properties.incrementButtonConfig.enabled);
this._incrementEnabled.addEventListener('click', this._incrementButtonProperties.incrementSelectCallback, false);
and the CSS:
.SchedMainCtrlIncrementBtn_En {
position: absolute;
top: 3px;
left: 240px;
display: inline-block;
font-size: 28px;
vertical-align: middle;
width: 35px;
height: 65px;
height: 35px;
background: url("../../../images/icons/IcnListAddRecipient_En.png") no-repeat center;
}
something like this:
var divs = document.querySelectorAll( 'div.yourclass' );
for( var i=0; i < divs.length; i++ ){
divs[ i ].addEventListener( 'eventname', callback, false );
}
EDIT:
From reading your code with this very long variable names I conclude that you want to do something like this:
this.element = document.createElement( 'div' );
this.element.className = 'someName';
this.parentElement.appendChild( this.element );
this.element.addEventListener( 'click', callback, false );
So if this.parentElement is not defined, or if callback is not defined it wont work. I do not know how you coded the class, but all used functions (document.createElement, appendChild, addEventListener) are native functions, so they work.
If possible try to use Jquery it will be simpler you can this $('.class').click(function(){})

Twitter-style autocomplete in textarea

I am looking for a Javascript autocomplete implementation which includes the following:
Can be used in a HTML textarea
Allows for typing regular text without invoking autocomplete
Detects the # character and starts autocomplete when it is typed
Loads list of options through AJAX
I believe that this is similar to what Twitter is doing when tagging in a tweet, but I can't find a nice, reusable implementation.
A solution with jQuery would be perfect.
Thanks.
Another great library which solves this problem At.js (deprecated)
Source
Demo
They are now suggesting the Tribute library
https://github.com/zurb/tribute
Example
I'm sure your problem is long since solved, but jquery-textcomplete looks like it would do the job.
Have you tried this
GITHUB: https://github.com/podio/jquery-mentions-input
DEMO/CONFIG: http://podio.github.io/jquery-mentions-input/
It is pretty simple to implement.
I've created a Meteor package for this purpose. Meteor's data model allows for fast multi-rule searching with custom rendered lists. If you're not using Meteor for your web app, (I believe) you unfortunately won't find anything this awesome for autocompletion.
Autocompleting users with #, where online users are shown in green:
In the same line, autocompleting something else with metadata and bootstrap icons:
Fork, pull, and improve:
https://github.com/mizzao/meteor-autocomplete
Try this:
(function($){
$.widget("ui.tagging", {
// default options
options: {
source: [],
maxItemDisplay: 3,
autosize: true,
animateResize: false,
animateDuration: 50
},
_create: function() {
var self = this;
this.activeSearch = false;
this.searchTerm = "";
this.beginFrom = 0;
this.wrapper = $("<div>")
.addClass("ui-tagging-wrap");
this.highlight = $("<div></div>");
this.highlightWrapper = $("<span></span>")
.addClass("ui-corner-all");
this.highlightContainer = $("<div>")
.addClass("ui-tagging-highlight")
.append(this.highlight);
this.meta = $("<input>")
.attr("type", "hidden")
.addClass("ui-tagging-meta");
this.container = $("<div></div>")
.width(this.element.width())
.insertBefore(this.element)
.addClass("ui-tagging")
.append(
this.highlightContainer,
this.element.wrap(this.wrapper).parent(),
this.meta
);
var initialHeight = this.element.height();
this.element.height(this.element.css('lineHeight'));
this.element.keypress(function(e) {
// activate on #
if (e.which == 64 && !self.activeSearch) {
self.activeSearch = true;
self.beginFrom = e.target.selectionStart + 1;
}
// deactivate on space
if (e.which == 32 && self.activeSearch) {
self.activeSearch = false;
}
}).bind("expand keyup keydown change", function(e) {
var cur = self.highlight.find("span"),
val = self.element.val(),
prevHeight = self.element.height(),
rowHeight = self.element.css('lineHeight'),
newHeight = 0;
cur.each(function(i) {
var s = $(this);
val = val.replace(s.text(), $("<div>").append(s).html());
});
self.highlight.html(val);
newHeight = self.element.height(rowHeight)[0].scrollHeight;
self.element.height(prevHeight);
if (newHeight < initialHeight) {
newHeight = initialHeight;
}
if (!$.browser.mozilla) {
if (self.element.css('paddingBottom') || self.element.css('paddingTop')) {
var padInt =
parseInt(self.element.css('paddingBottom').replace('px', '')) +
parseInt(self.element.css('paddingTop').replace('px', ''));
newHeight -= padInt;
}
}
self.options.animateResize ?
self.element.stop(true, true).animate({
height: newHeight
}, self.options.animateDuration) :
self.element.height(newHeight);
var widget = self.element.autocomplete("widget");
widget.position({
my: "left top",
at: "left bottom",
of: self.container
}).width(self.container.width()-4);
}).autocomplete({
minLength: 0,
delay: 0,
maxDisplay: this.options.maxItemDisplay,
open: function(event, ui) {
var widget = $(this).autocomplete("widget");
widget.position({
my: "left top",
at: "left bottom",
of: self.container
}).width(self.container.width()-4);
},
source: function(request, response) {
if (self.activeSearch) {
self.searchTerm = request.term.substring(self.beginFrom);
if (request.term.substring(self.beginFrom - 1, self.beginFrom) != "#") {
self.activeSearch = false;
self.beginFrom = 0;
self.searchTerm = "";
}
if (self.searchTerm != "") {
if ($.type(self.options.source) == "function") {
self.options.source(request, response);
} else {
var re = new RegExp("^" + escape(self.searchTerm) + ".+", "i");
var matches = [];
$.each(self.options.source, function() {
if (this.label.match(re)) {
matches.push(this);
}
});
response(matches);
}
}
}
},
focus: function() {
// prevent value inserted on focus
return false;
},
select: function(event, ui) {
self.activeSearch = false;
//console.log("#"+searchTerm, ui.item.label);
this.value = this.value.replace("#" + self.searchTerm, ui.item.label) + ' ';
self.highlight.html(
self.highlight.html()
.replace("#" + self.searchTerm,
$("<div>").append(
self.highlightWrapper
.text(ui.item.label)
.clone()
).html()+' ')
);
self.meta.val((self.meta.val() + " #[" + ui.item.value + ":]").trim());
return false;
}
});
}
});
body, html {
font-family: "lucida grande",tahoma,verdana,arial,sans-serif;
}
.ui-tagging {
position: relative;
border: 1px solid #B4BBCD;
height: auto;
}
.ui-tagging .ui-tagging-highlight {
position: absolute;
padding: 5px;
overflow: hidden;
}
.ui-tagging .ui-tagging-highlight div {
color: transparent;
font-size: 13px;
line-height: 18px;
white-space: pre-wrap;
}
.ui-tagging .ui-tagging-wrap {
position: relative;
padding: 5px;
overflow: hidden;
zoom: 1;
border: 0;
}
.ui-tagging div > span {
background-color: #D8DFEA;
font-weight: normal !important;
}
.ui-tagging textarea {
display: block;
font-family: "lucida grande",tahoma,verdana,arial,sans-serif;
background: transparent;
border-width: 0;
font-size: 13px;
height: 18px;
outline: none;
resize: none;
vertical-align: top;
width: 100%;
line-height: 18px;
overflow: hidden;
}
.ui-autocomplete {
font-size: 13px;
background-color: white;
border: 1px solid black;
margin-bottom: -5px;
width: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea></textarea>
http://jsfiddle.net/mekwall/mcWnL/52/
This link will help you
I could not find any solution that matched my requirements perfectly, so I ended up with the following:
I use the jQuery keypress() event to check for the user pressing the # character.
If this is the case, a modal dialog is shown using jQuery UI. This dialog contains an autocomplete text field (many options can be used here, but I recommmend jQuery Tokeninput)
When the user selects an option in the dialog, a tag is added to the text field and the dialog is closed.
This is not the most elegant solution, but it works and it does not require extra keypresses compared to my original design.
Edit
So basically, we have our large text box where the user can enter text. He should be able to "tag" a user (this just means inserting #<userid> in the text). I attach to the jQuery keyup event and detect the # character using (e.which == 64) to show a modal with a text field for selecting the users to tag.
The meat of the solution is simply this modal dialog with a jQuery Tokeninput text box. As the user types here, the list of users is loaded through AJAX. See the examples on the website for how to use it properly. When the user closes the dialog, I insert the selected IDs into the large text box.
Recently i had to face this problem and this is how i nailed down...
Get the string index at the cursor position in the textarea by using selectionStart
slice the string from index 0 to the cursor position
Insert it into a span (since span has multiple border boxes)
Get the dimensions of the border box using element.getClientRects() relative to the view port. (here is the MDN Reference)
Calculate the top and left and feed it to the dropdown
This works in all latest browsers. haven't tested at old ones
Here is Working bin
Another plugin which provides similar functionality:
AutoSuggest
You can use it with custom triggers or you can use it without any triggers. Works with input fields, textareas and contenteditables. And jQuery is not a dependency.
I would recommend the textcomplete plugin. No jQuery dependency. You may need bootstrap.css to refer, but I recommend to write your own CSS, lighter and simple.
Follow the below steps to give it a try
npm install #textcomplete/core #textcomplete/textarea
Bind it to your input element
const editor = new TextareaEditor(inputEl);
const textcomplete = new Textcomplete(editor, strategy, options);
Set strategy(how to fetch suggestion list) and options(settings to configure the suggestions) according to your need.
JS version
Angular Version
This small extension seems to be the closest at least in presentation to what was asked. Since it's small, it can be easily understood and modified. http://lookapanda.github.io/jquery-hashtags/
THIS should work. With regards to the # kicking off the search, just add (dynamically or not) the symbol to the beginning of each possible search term.

Categories

Resources