typed.js - Calling custom function before each new string using preStringTyped - callback

Trying to fire a custom function before each new string is typed. Would like the strings to loop, use smart backspace, and be SEO friendly. Is this possible?
jsfiddle: https://jsfiddle.net/bmess/qcpfs4n9/1/
HTML
<h1 id="typed-strings" class="page-title">
<span>Built to be Autonomous.</span>
<span>Built to be Reliable.</span>
<span>Built to be Portable.</span>
<span>Built to Last.</span>
</h1>
<h2 class="h1 page-title">
<span id="typed"></span>
</h2>
JS
var typed = new Typed("#typed", {
stringsElement: '#typed-strings',
typeSpeed: 50,
backSpeed: 10,
backDelay: 2000,
smartBackspace: true,
loop: true,
loopCount: false,
preStringTyped: function(index, self) {
alert(index);
// Fire custom function here
},
});
Code above should throw alert before the typing of every new string is started. It loops through with smart backspacing however it's not trowing an alert before each new string is typed out. Any ideas?

Related

Equivalent document.querySelector inside Mutation Observer dynamic elements

I'm using Mutation Observer to listen to the new added elements and it's working fine for all elements but for Switchery jQuery Plugin it doesn't because Switchery get element by [document.querySelector]
This is my code...
MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
var observerjQueryPlugins = function (repeaterWrapper) {
_.each(repeaterWrapper, function (repeaterItem, index) {
var jq_nodes = $(repeaterItem.addedNodes);
jq_nodes.each(function () {
// Color Picker (Working Good)
$(this).find('.element-wrapper.element-wpcolor .color-picker').wpColorPicker();
// Switchery using document.querySelector and i need to know the
// equivalent way to do it inside this loop .. like that
// Of course this code is WRONG
sw_current = $(this).find('.switchery-element');
var switchery = new Switchery( sw_current, {
disabled: false,
size: '',
color: '#8ce196',
secondaryColor: '#ddd',
jackColor: '#fff',
jackSecondaryColor: '#fff'
});
});
});
}
new MutationObserver(observerjQueryPlugins).observe(document.body, {
childList: true,
subtree: true,
attributes: false,
characterData: false
});
Thanks for your help.
It seems that Switchery is not a jQuery Plugin. That's why the sample code in GitHub uses document.querySelector to acquire element to apply it.
As you use jQuery to find elements, you need to use jQuery.each in order to process every DOM element for Switchery.
The following is an example to find element by jQuery and apply Switchery to each element. so, do the similar thing after sw_current = $(this).find('.switchery-element'); in your code.
$(function() {
sw_current = $(this).find('.switchery-element');
sw_current.each(function() {
var switchery = new Switchery(this);
})
});
#import url("http://abpetkov.github.io/switchery/dist/switchery.min.css");
<input type="checkbox" class="switchery-element" checked />Check 1
<p/>
<input type="checkbox" class="switchery-element" checked />Check 2
<p/>
<input type="checkbox" class="switchery-element" checked />Check 3
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://abpetkov.github.io/switchery/dist/switchery.min.js"></script>

AngularJs Directive: Using TemplateURL. Replace element. Add form input. Getting form.input.$error object

Not sure if this is possible but I'm trying, and keep coming up short.
http://plnkr.co/edit/Gcvm0X?p=info
I want a 'E' (element) directive that is replaced with a more complex nested HTML node using the 'templateUrl' feature of directives.
HTML defining the directive (form tag included for complete mental image):
<form id="frm" name="frm">
<ds-frm-input-container
class="col-md-1"
frm-Name="frm"
frm-obj="frm"
input-name="txtFName"
ds-model="user.firstName"></ds-frm-input-container>
</form>
TemplateUrl contents which 'replaces' the above directive 'ds-frm-input-container' HTML element:
<div>
<input
required
ng-minlength=0
ng-maxlength=50
class="form-control"
ng-model="dsModel"
placeholder="{{dsPlaceHolder}}" />
<span ng-if="showErrs" class="label label-danger">FFFFF: {{dsModel}}</span>
</div>
Controller and Directive:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = "Nacho";
$scope.user = {};
$scope.user.firstName = "";
})
.directive('dsFrmInputContainer', function(){
var ddo = {
priority: 0,
restrict: 'AE',
scope:
{
frmName: '#',
inputName: '#',
dsPlaceHolder: '#',
dsModel: '=',
frmObj: '='
},
templateUrl: 'template1.html',
replace: true,
controller: function($scope)
{
$scope.showErrs = true;
},
compile: function compile(ele, attr) {
return {
pre: function preLink(scope, ele, attr, controller)
{
},
post: function postLink(scope, ele, attr, controller)
{
var txt = ele.find('input');
txt.attr('id', scope.inputName);
txt.attr('name', scope.inputName);
//BLUR
txt.bind('blur', function () {
console.log("BLUR BLUR BLUR");
angular.forEach(scope.frmObj.$error, function(value, key){
var type = scope.frmObj.$error[key];
for(var x=0; x < type.length; x++){
console.log(type[x]);
}
});
event.stopPropagation();
event.preventDefault();
});
}
};
},
};
return ddo;
});
The directive replaces just fine and the input element is named just fine. The form object however doesn't include the input element name in the error information. This makes it impossible for me to single out the input element during a 'blur' event that is setup in the directive.
I am doing this trying to reduce the show/hide logic 'noise' in the html for error messages (spans) and it should be reusable.
UPDATE (2014.01.28):
2014.01.28:
Added promises. There is a service that allows validation on button clicks. NOT USING built in angular validation anymore found some compatibility issues with another library (or viceversa).
ORIGINAL:
Here is my form validation directive vision completed (plnkr link below). Completed in concert with the help of the stack overflow community. It may not be perfect but neither are butterfingers but they taste good.
http://plnkr.co/edit/bek8WR?p=info
So here is a link that has the name variables set as expected on the given input form error object. http://plnkr.co/edit/MruulPncY8Nja1BUfohp?p=preview
The only difference is that the inputName is read from the attrs object and is not part of the scope. This is then read before the link function is returned, in the compile phase, to set the template DOM correctly.
I have just spent quite a while trying to sort this problem out, and while this is not exactly what you were looking for, his is my attempt. It uses bootstrap for all the styling, and allows for required and blur validation, but its definitely not finished yet. Any thoughts or advice much appreciated.
https://github.com/mylescc/angular-super-input

IE does not pick up form processing data in inputs in a jQuery Dialog

I have an HTML5 page with several data inputs inside a jQuery Dialog box. I sweep this data into form processing with the input attribute form=dataInput. It works fine in Firefox and Chrome, but not in IE because IE does not support the input form attribute. Something about the Dialog widget makes input box elements 'invisible' to form processing. The form attribute fixes this for browsers that support HTML5, but no released IE has this support. I tried $('.ui-dialog').appendTo('form'); in the Dialog open: option, but it does not fix the problem. Is there a way to get IE to sweep input data out of a Dialog widget and into $_POST ?
Here is a sample of an input box inside the Dialog
<label><input type="radio" id="unitedStates" name="country" form="dataInput" value="US">United States</label>
I use the jQuery Form plug-in to perform the submit. It has some options, like beforeSubmit and beforeSerialize, but I don't understand the documentation or the submit process well enough to know if they can be used to solve this problem. Please be specific with code or tutorials. I'm new enough to this that I don't follow general instructions well. ;-) (BTW, IE has the other feature support I need, just not this one.)
Here's my code with Andrew Hagner's suggestion and my modification. Dialog works, but IE does not set a value for the country. What needs to change?
var countrySelected = $("input[type=radio][name=country]").val(); //set earlier by W3C geocoding
var countryChooser = $('#countryChoices').dialog( {
autoOpen: false,
bgiframe: true,
height: 300,
width: 850,
resizable: false,
draggable: true,
title: "Click to select another country",
open: function () {
$('#regions').tabs(
{
event: "mouseover",
})
},
buttons: {
'Close / continue location input': function ()
{
countrySelected = $('input[name=country]:checked').val();
$(this).dialog('close');
}
}
});
//then later on
getCityFromGeonames3Step(countrySelected);
Updated:
// Before you enter dialog, assign the element you will
// be grabbing the info from to a variable.
var countrySelectionElement = $("input[type=radio][name=country]").val();
var countrySelected = "";
var countryChooser = $('#countryChoices').dialog( {
autoOpen: false,
bgiframe: true,
height: 300,
width: 850,
resizable: false,
draggable: true,
title: "Click to select another country",
open: function () {
$('#regions').tabs(
{
event: "mouseover",
})
},
buttons: {
'Close / continue location input': function ()
{
// Since jQuery won't work in here, use the variable
// we assigned above to access value.
countrySelected = countrySelectionElement.val();
$(this).dialog('close');
}
}
});
//then later on
getCityFromGeonames3Step(countrySelected);
Original:
Before you open the dialog assign the input to a variable:
function OpenDialog()
{
var input = $("yourinput");
// Open dialog, use input to work with that element.
// If you want you can then place the entered data in a hidden field
// using jQuery, in the same way we are using input here. Then you will
// be able to post that data back however you like.
}
I had this problem the other day, I found this solution on jQuery's Dialog site.
http://jqueryui.com/demos/dialog/#modal-form

How to highlight friends name in Facebook status update box (textarea)?

In Facebook status update box, when I type # and start typing and choose a name, say Steven Gerrard, from the friends list suggested by fb, my friend's name is highlighted in the textarea like this
I checked with Firebug and there's only
a div.highlighter which contains sort of formated text (Steven Gerrard is within b tags)
a textarea inside a div.uiTypeahead. Nothing interesting i could find
and a hidden input, that contains the actual text that will be posted: #[100001915747xxx:Steven Gerrard] is awesome
What is the secret trick behind this? Normal rich text editors like ckeditor usually have an iframe to display the text and an actual textarea to keep the original content. But in this case, I do not see anything. Someone please shed some lights?
I would like to make something like this but have no clue where to begin. Also, if I would like to display a small thumb next to my friend's name, is it possible at all?
Here is how it works:
You superpose the textarea (in front) and a div (behind) that will have the same size, and the same font size.
The textarea must have a transparent background, so we can see its text, but also see the div behind it.
The div behind it will have a white text and white background, so the text it contains will be transparent.
You set a hook on the textarea's keyup, and you process the text it contains as HTML: replace the line breaks by <br/>, replace the double spaces by , and also replace all the words that you want to highlight by a version surrounded by <span style="background-color: #D8DFEA;"></span>.
Since you can see the highlight div behind the textarea, and that the text the highlight div contains is perfectly aligned with the text in the textarea, and that the <span> is visible, you will have the illusion that the text in the textarea is highlighted.
I've written a quick example based on jquery so you can try it yourself, without too much code to analyze.
Here is a sample code you can just copy-paste-save and try:
This sample code will highlight a defined set of word, here: "hello" and "world".
I'll let you adapt it the way you want.
<html>
<head>
<title></title>
<!-- Load jQuery -->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<!-- The javascript xontaining the plugin and the code to init the plugin -->
<script type="text/javascript">
$(function() {
// let's init the plugin, that we called "highlight".
// We will highlight the words "hello" and "world",
// and set the input area to a widht and height of 500 and 250 respectively.
$("#container").highlight({
words: ["hello","world"],
width: 500,
height: 250
});
});
// the plugin that would do the trick
(function($){
$.fn.extend({
highlight: function() {
// the main class
var pluginClass = function() {};
// init the class
// Bootloader
pluginClass.prototype.__init = function (element) {
try {
this.element = element;
} catch (err) {
this.error(err);
}
};
// centralized error handler
pluginClass.prototype.error = function (e) {
// manage error and exceptions here
//console.info("error!",e);
};
// Centralized routing function
pluginClass.prototype.execute = function (fn, options) {
try {
options = $.extend({},options);
if (typeof(this[fn]) == "function") {
var output = this[fn].apply(this, [options]);
} else {
this.error("undefined_function");
}
} catch (err) {
this.error(err);
}
};
// **********************
// Plugin Class starts here
// **********************
// init the component
pluginClass.prototype.init = function (options) {
try {
// the element's reference ( $("#container") ) is stored into "this.element"
var scope = this;
this.options = options;
// just find the different elements we'll need
this.highlighterContainer = this.element.find('#highlighterContainer');
this.inputContainer = this.element.find('#inputContainer');
this.textarea = this.inputContainer.find('textarea');
this.highlighter = this.highlighterContainer.find('#highlighter');
// apply the css
this.element.css('position','relative');
// place both the highlight container and the textarea container
// on the same coordonate to superpose them.
this.highlighterContainer.css({
'position': 'absolute',
'left': '0',
'top': '0',
'border': '1px dashed #ff0000',
'width': this.options.width,
'height': this.options.height,
'cursor': 'text'
});
this.inputContainer.css({
'position': 'absolute',
'left': '0',
'top': '0',
'border': '1px solid #000000'
});
// now let's make sure the highlit div and the textarea will superpose,
// by applying the same font size and stuffs.
// the highlighter must have a white text so it will be invisible
this.highlighter.css({
'padding': '7px',
'color': '#eeeeee',
'background-color': '#ffffff',
'margin': '0px',
'font-size': '11px',
'font-family': '"lucida grande",tahoma,verdana,arial,sans-serif'
});
// the textarea must have a transparent background so we can see the highlight div behind it
this.textarea.css({
'background-color': 'transparent',
'padding': '5px',
'margin': '0px',
'font-size': '11px',
'width': this.options.width,
'height': this.options.height,
'font-family': '"lucida grande",tahoma,verdana,arial,sans-serif'
});
// apply the hooks
this.highlighterContainer.bind('click', function() {
scope.textarea.focus();
});
this.textarea.bind('keyup', function() {
// when we type in the textarea,
// we want the text to be processed and re-injected into the div behind it.
scope.applyText($(this).val());
});
} catch (err) {
this.error(err);
}
return true;
};
pluginClass.prototype.applyText = function (text) {
try {
var scope = this;
// parse the text:
// replace all the line braks by <br/>, and all the double spaces by the html version
text = this.replaceAll(text,'\n','<br/>');
text = this.replaceAll(text,' ',' ');
// replace the words by a highlighted version of the words
for (var i=0;i<this.options.words.length;i++) {
text = this.replaceAll(text,this.options.words[i],'<span style="background-color: #D8DFEA;">'+this.options.words[i]+'</span>');
}
// re-inject the processed text into the div
this.highlighter.html(text);
} catch (err) {
this.error(err);
}
return true;
};
// "replace all" function
pluginClass.prototype.replaceAll = function(txt, replace, with_this) {
return txt.replace(new RegExp(replace, 'g'),with_this);
}
// don't worry about this part, it's just the required code for the plugin to hadle the methods and stuffs. Not relevant here.
//**********************
// process
var fn;
var options;
if (arguments.length == 0) {
fn = "init";
options = {};
} else if (arguments.length == 1 && typeof(arguments[0]) == 'object') {
fn = "init";
options = $.extend({},arguments[0]);
} else {
fn = arguments[0];
options = $.extend({},arguments[1]);
}
$.each(this, function(idx, item) {
// if the component is not yet existing, create it.
if ($(item).data('highlightPlugin') == null) {
$(item).data('highlightPlugin', new pluginClass());
$(item).data('highlightPlugin').__init($(item));
}
$(item).data('highlightPlugin').execute(fn, options);
});
return this;
}
});
})(jQuery);
</script>
</head>
<body>
<div id="container">
<div id="highlighterContainer">
<div id="highlighter">
</div>
</div>
<div id="inputContainer">
<textarea cols="30" rows="10">
</textarea>
</div>
</div>
</body>
</html>
Let me know if you have any question or if you need help with this code.
After reviewing the way of Facebook do this, I see that the text shown on the screen is:
<span class="highlighterContent"><b>Ws Dev</b> is good</span>
That span is put in a table (with lots of div container), which is style accordingly.
So I think this is the process:
When you type in the box, Facebook does have a textarea that capture what you type, but use javascript to show the typed HTML content in a table.
When you submit, the formatted content in a hidden input (that you already spot in the question) get submitted. It's like "#[100001915747xxx:Steven Gerrard] is awesome".
When the formatted message submit, it is saved to the database. Everytime the page get loaded, from the saved message the HTML is composed and return.
To get the similar effect, you can use any jQuery autocomplete plugin.

Html.ActionLink with id value from a dropdownlist

I've got a dropdownlist:
<%= Html.DropDownList("ddlNames", new SelectList(Model.NameList, "ID", "Name"))%>
I've got an ActionLink:
<%: Html.ActionLink("edit", "Edit", "Members", new { area = "MembersArea", id = XXX }, null)%>
I want the value of the dropdownlist in the XXX.
So I want to use values from controls on a view in the ActionLink.
Is that possible in a simple manner?
thanks,
Filip
You can't do this because the html helpers execute at the server side while the dropdown value can change at the client side. The only way to achieve it is to use javascript. You could register for the onchange event of the dropdown and modify the value of the href of the anchor:
$(function() {
$('#ddlNames').change(function() {
var value = this.value; // get the selected value
// TODO: modify the value of the anchor
});
});
This is probably not the best solution because the routes are configured on the server side and in order to modify the value of the link you need to do some string manipulation on the client side.
As an alternative you could use a form and a submit button instead of an anchor. This way the selected value of the dropdown will be automatically sent to the server and you don't need any javascript:
<% using (Html.BeginForm("Edit", "Members", new { area = "MembersArea" })) { %>
<%= Html.DropDownListFor(x => x.SelectedName,
new SelectList(Model.NameList, "ID", "Name"))%>
<input type="submit" value="Edit" />
<% } %>
Instead of modifying the value of the anchor every time a relevant dropdown is changed, just modify it once, on click.
Example using Razor:
#Html.DropDownList("DropDownFirstNames", new SelectList(Model.FirstNames, "ID", "Name"))
#Html.DropDownList("DropDownLastNames", new SelectList(Model.LastNames, "ID", "Name"))
#Html.ActionLink("Submit name", "ActionName", "ControllerName", null, new { #id = "SubmitName" })
<script type="text/javascript">
$('#SubmitName').click(function () {
var first = $('#DropDownFirstNames').val();
var last = $('#DropDownLastNames').val();
var path = '#Url.Content("~/ControllerName/ActionName")' + "?firstId=" + first + "+&lastId=" + last
$(this).attr("href", path);
});
</script>